views:

90

answers:

3

I'm running into an issue that seems to only appear on Windows 7. It seemed to work fine in IE8 on a different version of Windows. Basically, I'm creating a new window with window.open(), then using document.write() to write the contents of that new window, which contains script includes. In IE, these scripts are not being executed properly. Most of the time they don't execute at all, but occasionally one of them will. This is only with a cleared cache - once the javascript files are in the cache, it works fine.

Boiled down test case:

test.html:

<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'&gt;
<html>
<head>
   <script type="text/javascript">
      var w = window.open();
      var windowHTML = "\
<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'&gt;\n\
<html>\n\
<head>\n\
   <script type='text/javascript' src='test.js'></scr"+"ipt>\n\
   <script type='text/javascript' src='test2.js'></scr"+"ipt>\n\
</head>\n\
<body>\n\
</body>\n\
</html>";
      w.document.write(windowHTML);
      w.document.close();
   </script>
</head>
<body>
</body>
</html>

test.js:

alert("test");

test2.js:

alert("test2");

When I go to test.html, I would expect to see a new window pop up with alerts for "test" then "test2". I do in most browsers, including IE6. However, when I try this in IE8 on Windows 7, it opens the blank page, but no alerts appear (or occasionally just one).

Is it some sort of timing issue? Has anyone else seen this? Is there some way I can get around it?


Edit: Here's the code I tried that Rob Cooney wanted to see. Again, it works in other browsers, but not in IE8 on Windows 7.

test.htm:

<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'&gt;
<html>
<head>
   <script type="text/javascript">
      var w = window.open();
      var windowHTML =
         "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'&gt;\n" +
         "<html>\n" +
         "<head>\n" +
         "   <script type='text/javascript' src='test.js'></scr"+"ipt>\n" +
         "   <script type='text/javascript' src='test2.js'></scr"+"ipt>\n" +
         "</head>\n" +
         "<body onload='test();test2()'>\n" +
         "</body>\n" +
         "</html>";
      w.document.write(windowHTML);
      setTimeout(function() {
         w.document.close();
      }, 10000);
   </script>
</head>
<body>
</body>
</html>

test.js:

function test() {
   alert("test");
}

test2.js:

function test2() {
   alert("test2");
}

Also, I've posted this as a question on the MSDN forums here.


Accepting no's workaround as the best answer. Here's my modified code:

<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'&gt;
<html>
<head>
   <script type="text/javascript">
      var w = window.open();
      var windowHTML =
         "<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'&gt;\n" +
         "<html>\n" +
         "<head></head>\n" +
         "<body></body>\n" +
         "</html>";
      w.document.write(windowHTML);
      w.document.close();

      var s = w.document.createElement("script");
      s.type = "text/javascript";
      s.src = "test.js";
      w.document.getElementsByTagName("HEAD")[0].appendChild(s);

      var s2 = w.document.createElement("script");
      s2.type = "text/javascript";
      s2.src = "test2.js";
      w.document.getElementsByTagName("HEAD")[0].appendChild(s2);
   </script>
</head>
<body>
</body>
</html>

Note: the thing to watch out for with this solution is that the javascript files are now loaded asynchronously, so if you have dependencies between the files, you can't be sure that they will load in the right order. I got around this with setTimeout and testing for the existence of variables in the first file before loading the second file.

A: 

You might want to consider wrapping your alert calls in function definitions in the imported js files, and then add an onLoad to the body tag of windowHTML that calls the function

EDIT:

<!DOCTYPE HTML PUBLIC '-//W3C//DTD HTML 4.01 Transitional//EN' 'http://www.w3.org/TR/html4/loose.dtd'&gt;
<html>
<head>
   <script type="text/javascript">
      var w = window.open();
      w.document.writeln("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 4.01 Transitional//EN\" \"http://www.w3.org/TR/html4/loose.dtd\"&gt;");
      w.document.writeln("<html>");
        w.document.writeln("<head>");
        w.document.writeln("<script type=\"text/javascript\" src=\"test.js\"></scr"+"ipt>");
        w.document.writeln("<script type=\"text/javascript\" src=\"test2.js\"></scr"+"ipt>");
        w.document.writeln("</head>");
        w.document.writeln("<body onload=\"test();test2()\">");
        w.document.writeln("</body>");
        w.document.writeln("</html>");
         w.document.close();
   </script>
</head>
<body>
</body>
</html>
Rob Cooney
I tried your suggestion to see if it works, but I get an error from IE saying "Object expected" when I call the functions in the onload. Again, if I try a second time (when the javascript files are in the cache already), it works fine. IE just isn't loading them properly the first time through.(My real code is using jquery's $(document).ready() in the included javascript files, not simple alerts. I just wanted to strip it down to the simplest test case that shows the behavior.)
Jennifer Grucza
If you remove w.document.close(); does it change the behaviour at all? I wonder if you are closing the window before the scripts have a chance to load and execute for the first time.
Rob Cooney
If I remove w.document.close(), the page never shows the alerts, even on later page loads. So then I tried putting the w.document.close() in a setTimeout, to give the scripts plenty of time to load, but that made no difference. So I don't think that's the problem.
Jennifer Grucza
sounds like a problem calling the function. can you post what the new code looks like?
Rob Cooney
Question edited with new code.
Jennifer Grucza
To be honest, I really can't see anything wrong with this. I've edited my answer with the only other thing I can think of trying - writing out each line separately and ensuring all the html tags have escaped double quotes. It's kind of a long shot though that this would make any difference.
Rob Cooney
Thanks for helping, Rob. Unfortunately, when I try your latest suggestion, IE just hangs. It hangs using IE6 on XP, too, using that code.
Jennifer Grucza
A: 

I'm not sure what is your purpose of calling a popup... if it is not essential to have a seperate window, you may try to have a overlaying layer on the existing page instead.. some people call it a lightbox.

window.open function on some browsers will initially prompt user to "accept pop-up" (which I do find annoying), if you don't need a popup and can implement everything on the same page, you can use the jQuery .load function instead to load the content into a container (without reloading the page).

http://api.jquery.com/load/

Brandon
Well, it's a very specific case. The new window contains two frames, one of which I load the current page into, the other of which has some controls that I use to interact with that page. It wouldn't really fit into a lightbox very well, since the purpose is not to be a dialog box. Thanks for the suggestion, though.
Jennifer Grucza
+2  A: 

Try something like this (untested):

var s=document.createElement('script');
s.type = "text/javascript";
s.src = "test.js";
document.body.appendChild(s);
no
I modified it a bit: var s = w.document.createElement("script"); s.type = "text/javascript"; s.src = "test.js"; w.document.getElementsByTagName("HEAD")[0].appendChild(s);And it does appear to work properly in IE8 on Windows 7 (as well as other browsers). I still think IE has a bug that my original code doesn't work, but this should work as a work-around.
Jennifer Grucza