I simply want to load a GWT(Google Web Toolkit) app by adding a script tag to the DOM, however because the GWT linker uses document.write()
I'm unable to find any good way of doing so. I've found some hacks for doing so on various blog posts but they all seem to fail with the latest version of GWT. Any reasonably non-invasive approach for doing this come to mind?
Clarification:
Normal way to start up a GWT app, in your host html page:
<script type="text/javascript" language="javascript" src="myapp.nocache.js"></script>
This, of course, starts up as soon as the page loads. I want to do it at a later time:
function startapp() {
var head = document.getElementsByTagName('head');
var s = document.createElement('script');
s.setAttribute('type', 'text/javascript');
s.setAttribute('src', 'myapp.nocache.js');
head[0].appendChild(s);
}
Here's what seems to work so far:
Add this to the top of your App.gwt.xml:
<!-- Cross site linker -->
<inherits name="com.google.gwt.core.Core" />
<add-linker name="xs" />
After compiling your app with the above setting, modify (or copy) the generated app.nocache.js as follows:
1) Comment the last $doc.write...
statement
2) Copy this portion from the $doc.write
statement you just commented out and eval it. Example:
eval('window.__gwtStatsEvent && window.__gwtStatsEvent({' + 'moduleName:"app", sessionId:window.__gwtStatsSessionId, subSystem:"startup",' + 'evtGroup: "loadExternalRefs", millis:(new Date()).getTime(),' + 'type: "end"});' + 'window.__gwtStatsEvent && window.__gwtStatsEvent({' + 'moduleName:"app", sessionId:window.__gwtStatsSessionId, subSystem:"startup",' + 'evtGroup: "moduleStartup", millis:(new Date()).getTime(),' + 'type: "moduleRequested"});');
3) Add this line right after.
document.body.appendChild(document.createElement('script')).src=base + strongName + ".cache.js";
So you're basically replacing the $doc.write
with those two lines.
Now, your bookmarklet will look something like:
<a href="javascript:(function(){document.body.appendChild(document.createElement('script')).src='http://abc.com/app.nocache.js';})();">My App</a>
I'm assuming you are already using the cross-domain linker and this does not resolve your problem with document.write. If not, it might be worth a look (sorry, not enough experience with it to say.)
One approach that I am fairly sure could be made to work is this:
Your bookmarklet adds a script tag to the page (as now)
This script is not GWT compiler output. It is a plain-old javascript that adds an IFrame to the page, and the src of that IFrame is pointed at an HTML page on your server that loads your GWT module.
Presumably the goal is for your GWT module to get things out of the page it was loaded into. Of course, it can't do this directly in this case because the IFrame comes from a different domain than the parent page.
In order to make this work you would have to use window.postMessage and window.addEventListener to communicate between your GWT module in the IFrame and your javascript stub in the parent (using JSNI on the GWT side.)
If you have to support older browsers, postMessage won't work - but you might be able to get away with hash manipulation - but this is probably where I'd draw a line on practicality.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With