When you are using comet forever iframe techniques, you will see the browser throbber of doom keep spinning and showing progress indicator all the time while loading the iframe data. It is the same in IE, firefox, or webkit based browsers like chrome and safari. In order to overcome the problem, you have to handle differently for different browsers.

Firstly, let’s look at how comet was implemented usually.

Normally, in comet iframe, you will define some call back javascript functions in the parent windows, this are javascript functions that are going to be used to update the contents on the web pages when data are pushed from server. On the server side, the server will push html that contains javascript functions calls back to the client. E.g.

Client Side javascript:





In the comet.js:

var iframe = document.getElementById(this.iframe_id);
if(!iframe)
{
     iframe = document.createElement("iframe");
     iframe.name = iframe.id = "streaming_frame";
     document.body.appendChild(iframe);
}
iframe.style.display = "none";
iframe.src = "http://server/action=subscribe&channel=time"; 

Once the iframe src has been added, the server client communication has started.

On the server side, there are quite a number of open source package for you to choose.grizzly in glassfish, Jetty, Meteor, Node.JS, just to name a few. The example below assumes that you use glassfish as the server:

PrintWriter writer = response.getWriter();
writer.print("");
writer.flush();

Here we write the following line of javascript back to iframe before we push any other data.

function p(data, div_id){parent.p(data, div_id);}

The reason is that when later the data is pushed to the client, the content of the data can be written as

p("10:50pm", "time")

But actually, p is referring to the parent windows call back method p.

Alright, so this is how basically comet works. The following are hacks to different browsers to stop the browser from spinning.
1. Firefox
In firefox, before you trigger the call back method to update the content, you have to create a temp iframe and attach to the document body, then removes it. By keep doing this before you trigger the event, the browser throbber goes away. The modified p function looks like this:

p(data, div_id) {
  firefox_hack();
  document.getElementById(div_id).innerHTML = data;
}
function firefox_hack () {
    var state = pushPage.engine.state;
    if (/Firefox[\/\s](\d+\.\d+)/.test(navigator.userAgent)){
          var fake_iframe;
          if (fake_iframe == null){
              fake_iframe = document.createElement('iframe');
              fake_iframe.style.display = 'none';
          }
          document.body.appendChild(fake_iframe);
          document.body.removeChild(fake_iframe);
    }
}


2. Chrome/Safari
For chrome and safari if you just do like above, the forever iframe won’t work at all! There won’t be any data returned from server side. So how do you make comet iframe work in chrome and safari.The hacks lies on server side. There are two conditions that you must fullfill in order to make forever iframe happens in this webkit browsers.

Firstly, the server must push some junk data (around 2k) to the browser before you push the real data. So just write out some javascript comments to the browsers first.

for (int i = 0; i < 10; i++) {
   write.print("");
}

Well, I don’t know how big this is going to fill the browser, you may make the loop longer if you can’t make it work.
Secondly, you have to sent the response content type.

response.addHeader("Cache-Control", "private");
response.addHeader("Pragma", "no-cache");
response.setContentType("text/html;charset=ISO-8859-1");

However, my knowledge with chrome and safari is just able to make it work with forever iframe. However, the browser throbber of doom is still there.
3. IE
In IE, if you use above iframe method, it works. I have successfully done that. However in order to stop the browser throbber of doom, you have to make use of the special htmlfile object.
The following code snippet is taken from Alex in his article: What else is burried down in the depth’s of Google’s amazing JavaScript?

  // we were served from child.example.com but
  // have already set document.domain to example.com
  var currentDomain = "http://exmaple.com/";
  var dataStreamUrl = currentDomain+"path/to/server.cgi";
  var transferDoc = new ActiveXObject("htmlfile"); // !?!
  // make sure it's really scriptable
  transferDoc.open();
  transferDoc.write("");
  transferDoc.write("");
  transferDoc.write("");
  transferDoc.close();
  // set the iframe up to call the server for data
  var ifrDiv = transferDoc.createElement("div");
  transferDoc.appendChild(ifrDiv);
  // start communicating
  ifrDiv.innerHTML = "";

However, I haven’t really successfully implement this method in IE yet. The problem lies on the javascript call back. It always returns me null object error, when the server returns the following data:

function p(data, div_id) { parent.p(data, div_id)}

I think the problem lies on the parent keyword. In htmlfile, probably you can’t refer to the parent frame just like that. I still need some time to figure out how to do that.

20 comments on “Stop the browser “throbber of doom” while loading comet forever iframe

  1. fritteritter on said:

    Faced these problems a few years ago while writing a Comet chat system though I used an XMLHttpRequest for Firefox and Opera. The best way I have found to allow the processing function to work in IE is by passing the function into the iframe rather than trying to access the parent, as follows:

    // after adding iframe, give it the p function
    transferDoc.getElementsByTagName(‘iframe’)[0].p = p;

    Also, IE has (or perhaps had) a strange limitation where it will not begin streaming unless the server returns at least 256 characters in the response. You may need to add additional whitespace to the server response.

  2. shanison on said:

    The thing is that the call back function would be used to modify the parent window DOM.(for example to modify some div content) If you put the definition of the call back method completely in the iframe, then how are you going to access the DOM of the parent window?

  3. fritteritter on said:

    If you set

    transferDoc.getElementsByTagName(‘iframe’)[0].p = p;

    you are giving the iframe a reference to the p function which is defined in the scope of the parent window. The function has access to the parent window DOM (I am not sure whether this works in Firefox since I did not use an iframe in Firefox). With this setup, your server response will look something like this, there is no definition of a local p function:

    [256 space characters]
    p({some: ‘data’}, ‘someDivID’);
    p({more: ‘data’}, ‘someDivID’);

    The function is called by the browser each time a new script tag is pushed. This works in IE 6-8.

  4. shanison on said:

    I tried that, but it seems that it gives me “null object” error, when ever then streaming push back p(…) javascript tag. I will check out with that. Anyway, thanks a lot for sharing.

  5. Laura Anderson on said:

    Great blog 9/10! Bookmarked :)

  6. Laurynas on said:

    var state = pushPage.engine.state;

    What is this? the variable is not used anywhere. Can it be the reason the firefox ‘hack’ does not work for me?

    thanks

    • shanison on said:

      This is the script that I used in my comet streaming that can control the state of streaming, whether it is initializing or running etc. You can ignore this.

  7. Tim Schmidt on said:

    So has anyone figured out a way to get Chrome to stop spinning when streaming to a hidden frame? I’ve been unsuccessful.

    • shanison on said:

      Well, so far i didn’t see anyone who has a solution for this as well. Even the lightstreamer also has this problem with chrome.http://www.lightstreamer.com

  8. Blaise Kal on said:

    It’s even easier in Firefox (4 beta, haven’t tested 3.6): load the iframe on window.onload. It also works in IE7, IE8 and IE9 beta. I’m not sure about IE6, don’t have it native.

  9. I found it I do the first poll with a setTimeout — chrome will stop spinning. Odd because I don’t call the first ‘poll’ until after I get the dom:loaded event — but it seemed to make the cursor go away

  10. One way to stop the browser spinning is to smash the monitor in with a hammer. Enjoy!

  11. Chad Pennington Jersey on said:

    I am an admirer of your website. Persist in up the good work.

  12. krishnamraju on said:

    i am facing the throbbing problem in chrome when i am reinitiating the forever iframe . any ideas?

  13. best css codes.

  14. So do you have found the solution how to stop the loading spinning indicator?

    • shanison on said:

      Unfortunately not for other browsers except firefox. I found that google finance is also using comet streaming, and it also has the spinning indicator. So i think that maybe it is really necessary to figure out a way to remove it as this gives the users an indication that the streaming is working. If this stopped, then there may be some problem.

  15. Javier on said:

    Hi. im working with “play framework”, and then using Comet Socket’s library.

    http://www.playframework.com/documentation/2.1.x/JavaComet

    How could i to do if i’d want stop the browser throbber like you do in your example, but in the way in that “play framework” works with comet socket.

    Basically in the example Comet Sockets in play is used just puting an Iframe in the web, and linking by and URL address to the Action that dispatch the socket.

    Regards and thanks

Leave a Reply

Your email address will not be published. Required fields are marked *

*

HTML tags are not allowed.