GWT inject script element into the html file - gwt

On my gwt project. i have a script that call the dictionary:
<script type="text/javascript" src=conf/iw_dictionary.js></script>
instead of writing this script element in the html file. i want to inject it into the html from the entry point, on the module load.
how can i do it?

Use com.google.gwt.core.client.ScriptInjector, since it was created specifically for stuff like this
ScriptInjector.fromUrl("conf/iw_dictionary.js").setCallback(
new Callback<Void, Exception>() {
public void onFailure(Exception reason) {
Window.alert("Script load failed.");
}
public void onSuccess(Void result) {
Window.alert("Script load success.");
}
}).inject();

Basically you inject the script element in your onModuleLoad():
Element head = Document.get().getElementsByTagName("head").getItem(0);
ScriptElement sce = Document.get().createScriptElement();
sce.setType("text/javascript");
sce.setSrc("conf/iw_dictionary.js");
head.appendChild(sce);
The browser will automatically load it as soon as it's injected.

You could simply add a <script> element in your *.gwt.xml file.
<script src='conf/iw_dictionary.js' />
onModuleLoad will only be called once the script is loaded (as if you had it in your html page).

The answers form jusio, Dom and Thomas Broyer are all valid here. In my particular case, I was looking to inject a series of polyfill scripts into GWT for some IE8 support we needed when running native JS code. The polyfill scripts needed to be available to the GWT iframe's window context - NOT the host page. To do that, using ScriptInjector was the correct approach as it attaches the script at that level. You can make ScriptInjector install the scripts to a host window by using setWindow(TOP_WINDOW). Adding scripts with the <script> tag in my *.gwt.xml file seemed to be attaching to the host window as did using #Dom's approach.

Related

how to call a GWT module entry point class?

l split my GWT code in different different modules like
PrintPermit.gwt.xml
EmployeeResponse.gwt.xml
Rejected.gwt.xml
and every module has its own entry point class
in my HTML host page I am calling script like
ae.init.EmployeeResponse.nocache.js
I have a menu like
Print Application
Reject Application
New application
whenever user will click on new application default new application will open
as I declare EmployeeResponse.nocache.js statically in my HTML host page.
now I want to call other modules on click button print and reject button
how can i call nocache js for print and reject modules. is there any way to dynamic call.
please help me guys.
Here's how I've done it in the past:
First of all, in the module you want to export, you need to make sure that the code you're going to export doesn't end up obfuscated. This can be accomplished with the liberal use of #JsType; this is the new way of exporting JS, available in GWT 2.8 (as opposed to JSNI).
Your module's entry point onModuleLoad can be empty; it doesn't need to do anything.
Include your JS in the HTML you want to use (maybe the same page as your "main" module)
Check JSInterop documentation (perhaps the one available here) on how you can use native JS in your GWT app (because now, your GWT module became native JS). Import the classes via JSInterop from your library, and use them.
Please be aware of the async nature of the GWT JS loading; your library will be loading in an async manner, just like any JS application (and therefore, it won't be available immediately when your page loads). To overcome this, I've placed a call to a native JS function in my library's onModuleLoad function (i.e. to make sure you notify any potential listeners that the code has loaded; because when onModuleLoad runs, the code surely loaded).
There is a example of an InterAppEventBus:
https://github.com/sambathl/interapp-eventbus
which shows the communication between two GWT applications.
I have adopted it and replaced JSNI with Elemental2 and WebStorage:
https://github.com/FrankHossfeld/InterAppEventBus
Hope that helps.
You can achieve this through separate Html file for each module.
So first of all create separate html for each application e.g. PrintPermit.html and specify corresponding nocache.js in each html.
then on your buttons in menu, add click handlers and in each on click load a corresponding html through Window.open()
e.g. for PrintPermit,
printPermitButton.addClickHandler(new ClickHandler{
#Override
public void onClick(ClickEvent arg0) {
String s = GWT.getHostPageBaseURL() + "PrintPermit.html";
Window.open(s, "PrintPermit", "");
}
});
Please note the window.open will open in new tab in browser, you can also use gwt iframe to open html in same browser page.
Each module will have corresponding nocache.js and will be loaded through html using Window.open()

Calling functions from .js file from GWT

I have a page slider type widget from a third party that is pretty standard in that it runs some jquery code (inside an init function provided by the widget) on the HTML in your document looking for the classes of interest.
My issue is that I am using GWT so my HTML is being generated and then inserted in to the page by the GWT javascript file. The HTML being inserted has all the proper tags for the slider widget to work. So after it is added (to the DOM) I need to run the init js code so that the slider works as expected. I created a JSNI to make the call:
private native void initSlider() /*-{
Index.initLayerSlider();
}-*/;
I load Index in the head of the HTML file before the nocache.js GWT file, but I get the javascript console error when I load the site: Uncaught ReferenceError: Index is not defined so I tried
private native void initSlider() /*-{
jQuery(document).ready(function() {
Index.initLayerSlider();
});
}-*/;
and jQuery is also loaded in the head of my HTML file but I get the similar error: Uncaught ReferenceError: jQuery is not defined
How can I call this function from an external .js file from GWT? I guess I need to do something to make sure the browser has loaded and ran the .js file before GWT runs, or have GWT pause when it gets there until the .js file has been loaded. Or maybe I should approach this problem differently?
I would prefer to not have to make any modifications to the third party widget, but would be willing to make small ones if needed/possible. It has been obfuscated so it is very difficult to read.
call javascript from GWT need start with $wnd
see detail http://www.gwtproject.org/doc/latest/DevGuideCodingBasicsJSNI.html
private native void initSlider() /*-{
$wnd.Index.initLayerSlider();
}-*/;

GWT lifecycle - Deferred binding at runtime.What happens

Can someone explain what happens after the java code is converted to Javascript by the GWT compiler?
how will the compiled javascript reach the client browser and when does this happen.
Well from your server, you serve a html page which should contain a tag that points to your compiled javascript.
Example of what the script tag would look like
<script type="text/javascript" language="javascript" src="http://example.com/js/project/project.nocache.js"></script>
The GWT compiler generates output files as described here.
At a very high level. There is a very tiny loader file (the .nocache.) which you should include in a script tag in your page. This file's only job is to determine the correct compiled application code files to request from the server. This load happens asynchronously after the nocache script has loaded.

GWT: deferred loading of external JS resources

I have a widget depending on some external JS files, and I'd like to lazy load all these external resources. I've already used code splitting to lazy load the GWT code that concerns the widget, but the JS files defined in the gwt.xml, using the script tag, are loaded anyway, which is not desirable.
Is there a standard GWT way of loading these external resources on demand? I can do it myself using raw JS, but I'd rather not spend time on this too.
I think you'll want to take a look at the com.google.gwt.core.client.ScriptInjector class. From the javadocs:
Dynamically create a script tag and attach it to the DOM.
...
Usage with script loaded as URL:
ScriptInjector.fromUrl("http://example.com/foo.js").setCallback(
new Callback<Void, Exception>() {
public void onFailure(Exception reason) {
Window.alert("Script load failed.");
}
public void onSuccess(Void result) {
Window.alert("Script load success.");
}
}).inject();
This code can of course be invoked from within your split points, or indeed anywhere in your code.
ScriptInjector is quite portable. It doesn't have any external dependencies, so you should be able to backport it into your 2.3 application without much problem.

Problem with multiple entry Points in the same module

I have multiple entry points in the same module.
For example I have an Home entry point for the home page and an Admin
entry point for the admin page.
<entry-point class='com.company.project.client.HomeModule'/>
<entry-point class='com.company.project.client.AdminModule'/>
The way I am setup now - I need to check somt like this in my
OnModuleLoad:
if((RootPanel.get("someHomeWidget")!=null)&&
(RootPanel.get("someOtherHomeWidget")!=null))
{
// do the stuff
}
in order the the Admin Entrypoint not to be executed when the Home
page gets open and the other way around.
Not doing the check above also involves that if I have a div with the
same name in both the Home and Admin page whatever I am injecting in
it shows up twice on each of them.
This stinks 1000 miles away and is obviously wrong: what's the correct
way to do this in people experience?
Any help appreciated!
The correct way is to have a single entry point per module, that sticks the appropriate widgets in the appropriate divs:
RootPanel panel = RootPanel.get("someHomeWidget");
if (panel) panel.add(new HomeWidget());
panel = RootPanel.get("adminWidget");
if (panel) panel.add(new AdminWidget());
That way it just scans the page looking for any divs you have and inserts the appropriate widget. So your HTML page determines what widgets are displayed when and the GWT code is ready to handle any situation. There's nothing about the above that stinks, it's the way your entry point should be written.
The alternative is if your admin area and normally area are totally different (eg: you want to load them at separate times) then they should be separate modules, with separate entry points.
I also wanted to use multiple pages in a GWT toy app and I think I figured it out. It took some massaging of the deployment descriptor (myApp.gwt.xml), but here's what I did.
Made another class implementing EntryPoint and added some code that added to a div only in the new page.
Copied the original gwt.xml and changed two things:
The module-rename-to - I changed to "anothergwtapp"
The entry point specified the new class.
When I compile the project, there is another directory in the "war" folder called (wait for it...) "anothergwtapp". It contained the "anothergwtapp.nocache.js" that is the GWT magic.
Finally, I copied the orginal HTML page and replaced the "stockwatcher/stockwatcher.nocache.js" with "anothergwtapp/anothergwtapp.nocache.js" (yes, I'm very new - the tutorial is still on my machine)
I changed the new HTML to be a little different (new divs for the new entry point's onload to populate) and I added a simple href to the new page in the first page.
It worked. Just duplicate the gwt.xml and provide a new name for the module to go along with the new app page. I looked at some of the other links and I may have actually done what was described, but there were too many words and redirects and such (i.e. I didn't really read anything). I am using the latest GWT plugin for Galileo so maybe IJWs now.
Dont consider Admin and home page as different pages. Concept of pages is not applicable to GWT, as there is only one single page, ie single entrypoint.
If you want to give effect of different pages, then use URL rewriting features of GWT.
If you do want to use different Entrypoints, then as said in above comment, use different modules.
It's usually better to only have one EntryPoint. Multiple EntryPoints in one module all start at the same time and that can sometimes do things you did not expect.
You have plenty of options in how to handle it separately:
- Have 2 different compilations one for Admin and one for the Home application.
- Use the history tokens to indicate that you want Admin or Home
- Check a JS variable to show one or the other
- Check the presence of a specific DIV id to show Admin or Home (RootPanel.get(id))
- Use URL parameters to indicate the application.
- ... etc
There is a simple (tricky) way to achieve this:
Make a Main class Your entry point.
<module rename-to='gwt'>
<inherits name='com.google.gwt.user.User'/>
<entry-point class='com.example.client.Main'/>
<source path='client'/>
<source path='shared'/>
</module>;<br/>
Create this Main.java to work like a dispatcher:
package com.example.client;
import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.RootPanel;
public class Main implements EntryPoint {
public void onModuleLoad() {
String url = Window.Location.getHref();
if ( url.indexOf("?install")>-1 ) {
Install install = Install.getInstance();
RootPanel.get().add(install);
else if ( url.indexOf("?admin")>-1 ) {
Admin admin = Admin.getInstance();
RootPanel.get().add(admin);
} else {
Application app = Application.getInstance();
RootPanel.get().add(app);
}
}
}
Now the different classes Application, Admin and Install
work like seperate units.
Here is for example a simple Install:
package comexample.client;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.HTML;
public class Install extends FlowPanel {
/** Singleton stuff - to access Main from all subclasses! */
private static Install singelton;
public static Install getInstance() {
if (singelton == null) {singelton = new Install();}
return singelton;
}
/** Constructor - called by Main.onModuleLoad() */
private Install() {
this.add(new HTML("<h1>Do whatever You have to do!</h1>"));
}
}
You don't need the Singleton stuff (getInstance), but it is very handy in big applications.
Now in the /war-directory create directories named install and admin and in very of them create an HTML page like this:
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0; URL=/index.html?install">
</head>
<body></body>
</html>
So when the user directs his Brower to http://www.example.com/install he will be redirected to http://www.example.com/index?install and index.html is bound to Main.java which will dispatch the request and load Install.java