Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

GWT: Start running before page is ready (or body resources do not block running gwt)?

Tags:

javascript

gwt

In my html page there are external images and flashes, sometime they load slowly. My gwt app always starts running after they are loaded. I use xsiframe linker.

Is there any way to start running gwt before loading any images and resources which are inside body? Or make sure loading other things will not block starting gwt.

EDIT: I have created a minimal project that reproduces the problem:

entry point:

public class MyEntryPoint implements EntryPoint {
    public void onModuleLoad() {
        Window.confirm("onModuleLoad");
    }
}

html page:

<html><head>
    <script type="text/javascript"src="nocache.js"></script>
</head><body>
    <!-- http://stackoverflow.com/questions/100841/artificially-create-a-connection-timeout-error -->
    <img src="http://10.255.255.1/timeout.gif" alt="timeout image" />
</body></html>
like image 918
Ali Shakiba Avatar asked Oct 08 '22 20:10

Ali Shakiba


2 Answers

There are two possible solutions I can think of:

1. xs linker

You could use the old "xs" linker instead of "xsiframe". This is not so nice, especially because xs doesn't work in dev mode. But maybe you could use xsiframe during development, and then switch to xs for the real builds, tests and production.

2. the <noscript> tag trick

You can put the page contents, especially the slowly loading images, into a <noscript> tag, which is used, if the browser doesn't support JavaScript.

If however JavaScript is enabled, then the contents of that tag are ignored during loading. So what we will do in our GWT code (which can use the xsiframe linker again), is to copy the contents of the noscript tag back into the real page.

Here's some quick code:

<!doctype html>

<html>
  <head>
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">

    <script type="text/javascript" language="javascript"
            src="http://cdn.example.org/.../some.nocache.js"></script>
  </head>

  <body>

    <noscript>
      <p>A</p>
      <img src="http://10.255.255.1/timeout.gif" alt="timeout image" />
      <p>B</p>
    </noscript>

    <p>Test (should appear immediately if JavaScript is enabled)</p>
  </body>
</html>
@Override
public void onModuleLoad() {

  final NodeList<Element> noscriptElems = 
      RootPanel.get().getElement().getElementsByTagName("noscript");

  final Element noscriptElem = noscriptElems.getItem(0);

  RootPanel.get().add(new Label("Here is GWT"));

  RootPanel.get().add(new HTMLPanel(noscriptElem.getInnerText()));
      /* Be careful of course, not to have bad html in your noscript elem */

}
like image 125
Chris Lercher Avatar answered Oct 10 '22 10:10

Chris Lercher


First, sorry for "answering" when I don't know too much about GWT, and for presenting a pretty ugly hack.

Now then, two asynchronous loads with undefined outcome sounds like a race condition to me. So I'd say you need to "lock" your images/flash until the app loads and "unlocks" them.

One way to do this might be to give all the assets a dummy attribute instead of src, and then to have the app copy the dummy over to the real src. It would look something like this:

HTML example:

<img data-src="site.com/image.jpg" alt="loading..." />

Entry point:

public class MyEntryPoint implements EntryPoint {
    public void onModuleLoad() {
        var images = document.getElementsByTagName('img');
        for(var i=0; i<images.length; ++i){
            var dataSrc = images[i].getAttribute('data-src');
            if(dataSrc) images[i].src = dataSrc;
        }
        // ... rest of your entry point code
    }
}

Maybe you can adapt something like this to fit your needs.

like image 36
pieman72 Avatar answered Oct 10 '22 09:10

pieman72