views:

633

answers:

2

I have a strictly browser based javascript & xlst application. It's normally used on a local machine, but is sometimes accessed via Apache.

The main page is content.html which get's its content changed dynamically. In one case, an href in one page opens a new window and eventually the following code gets executed which sets up an onready function, with the intention of getting the content of the new window built.

This works in almost all cases. It works in all cases for Firefox. And it even works in all cases for IE when running locally (e.g. file:///C:/Program%20Files/Apache%20Software%20Foundation/Apache2.2/htdocs/hlic/index.html).

My problem is that when accessed via Apache in IE, I just get a blank window. It's acts like that the onready function is never fired. However, if I add an alert("fire"), the alert does get shown, after which, my window content does get displayed. So why does it only work with the alert? What else can I do to get the content to show up. Any help would be greatly appreciated.

Here's the code:

/*
 *  PresentStreamInNewBrowser
 *
 *      Creates a new browser window and fills with
 *      provided content stream. Also sizes the
 *      window to either default dimensions or to any       
 *      supplied dimensions.
 *
 *      A close and a print button are added to the bottom 
 *      of the content stream.
 *
 *      Inputs:
 *          pageStream - content stream to display
 *              in new window.
 *          height, width, top, left - dimensions
 *              for the newly opened window. (optional)
 * 
 */ 
function Presenter_PresentStreamInNewBrowser( pageStream, height, width, top, left )
{
    // set the features
    var features  = "height=" + height;
        features += ",width=" + width;
        features += ",top=" + top;
        features += ",left=" + left;
        features += ",scrollbars=yes";
        features += ",resizable=yes";

    // open the window
    var presenter = this;
    var newWindow = window.open(
        app.NormalizeURI("deview/frames/content.html"), '', features );

    // the rest of the code executes when the content window
    // calls its onready function, after it has loaded
    newWindow.onready = function() {



        var doc = newWindow.document;

        // create stylesheet links if applicable
        for(var i = 0; i < pageStream.stylesheet.length; i++) {
            var linkElement = doc.createElement("link");
            linkElement.rel = "stylesheet";
            linkElement.href = pageStream.stylesheet[i];
            doc.getElementsByTagName("head")[0].appendChild( linkElement );
        }

        // insert content
        doc.body.innerHTML = "";
        doc.body.appendChild( pageStream.content.importIntoDocument(doc) );
        doc.body.appendChild( doc.createElement("br") );

        // Handle generation of special pages.
        presenter.AddGeneratedContent( doc );

        // add a close button
        var selectionString =
        "displayStrings/promptStrings/promptString[@id='close_button_anchor']";
        var buttontext = app.displayStringsDOM.selectSingleNode(
        selectionString ).firstChild.nodeValue;
        var closeButtonElement = doc.createElement("button");
        closeButtonElement.id = "closebutton";
        closeButtonElement.className = "addonbutton";
        closeButtonElement.onclick = "javascript:window.close()";
        closeButtonElement.value = buttontext;
        doc.body.appendChild( closeButtonElement );

        // add a print button
        selectionString =
        "displayStrings/buttonLabelStrings/buttonLabelString[@id='print_button_anchor']";
        buttontext = app.displayStringsDOM.selectSingleNode(
        selectionString ).firstChild.nodeValue;
        var printButtonElement = doc.createElement("button");
        printButtonElement.id = "printbutton";
        printButtonElement.className = "addonbutton";
        printButtonElement.onclick = "javascript:window.print()";
        printButtonElement.value = buttontext;
        doc.body.appendChild( printButtonElement );

        // close up shop
        newWindow.document.body.appendChild(
        newWindow.document.createElement("br") );
        newWindow.document.title = '-';

        // add some language dependent text
        presenter.AddButtonLabel( doc );
        presenter.AddExamLabels( doc );

        //alert("fire");
  }        
}
+1  A: 

Best guess is that the ready event has already fired in the target window by the time your handler is assigned - in other words, you hit a race condition.

The solution I've used is to have something in content.html itself execute a callback to the parent window using window.opener either in inline Javascript or in a ready handler within content.html Is that feasible in your use case?

Dan
+1, great analysis
orip
Thanks for your reply. The problem does seem to be related to a race condition.
Brad Rhoads
+1  A: 

You could perhaps try checking the document readyState, something like

var newWindowReadyFired = false;

newWindow.onready = function() {
  if (newWindowReadyFired) return; //just in case race condition got us in here twice   
  newWindowReadyFired = true;

  //....the rest of your event handler
}

function chkFunc() {
  if (newWindowReadyFired) return; //magic already done

  if (newWindow.document && newWindow.document.readyState == 4) {
    newWindow.onready();
  } else {
    setTimeout(chkFunc,"100"); //wait and try again
  }
}
chkFunc();

Can't guarantee this will work, but perhaps worth a try?

Graza
This was extreamly helpful. Thank you!For my case, I can actually have multiple pop ups initiated from the same page, all using the same the code (content.html). So I just don't check for newWindowReadyFired in the onready function.
Brad Rhoads
Actually, it should still be safe for you to do that - "javascript closures" (scoping, allowing inner methods to access outer method's variables) *should* mean that there is a new instance of that variable created for each time you call your Presenter_PresentStreamInNewBrowser() method, and the correct instance would be referred to in the checks. I'm 90% sure of this (which also means 10% uncertain, so you'd still want to check this yourself somehow, perhaps by putting an alert() in to show the value of the var and checking it on your second window load)
Graza