views:

93

answers:

2

When you execute following example using Firefox 3:

<html>
 <head>
  <script language="javascript" type="text/javascript">
   <!--
   function openWindow(){
    var w = window.open('', 'otherWin', 'width=600,height=600');
    w.document.write(document.getElementsByTagName("html")[0].innerHTML);
    w.document.close();
    reportLinks(w.document.links);
   }

   function reportLinks(links){
    var report = 'links: '+links.length;
    for (var i=0;i<links.length;i++){
     report += '\n (link='+links[i].href+')';
    }
    alert(report);
   }
  //-->
  </script>
 </head>
 <body>
  <p><a href="javascript: openWindow()">Open Same Content and Show Links Report</a></p>
  <p><a href="javascript: reportLinks(document.links)">Show Links Report</a></p>
 </body>
</html>

You will see that both the number of links shown when clicking on 'Show Links Report' as when clicking on 'Open Same Content and Show Links Report' will be 2. However when having an external JavaScript file reference from this page the behavior seems different (just make an empty file some.js if you want). When clicking 'Open Same Content and Show Links Report' the number of links will be 0.

<html>
 <head>
  <script language="javascript" type="text/javascript" src="some.js"></script>
  <script language="javascript" type="text/javascript">
   <!--
   function openWindow(){
    var w = window.open('', 'otherWin', 'width=600,height=600');
    w.document.write(document.getElementsByTagName("html")[0].innerHTML);
    w.document.close();
    reportLinks(w.document.links);
   }

   function reportLinks(links){
    var report = 'links: '+links.length;
    for (var i=0;i<links.length;i++){
     report += '\n (link='+links[i].href+')';
    }
    alert(report);
   }
  //-->
  </script>
 </head>
 <body>
  <p><a href="javascript: openWindow()">Open Same Content and Show Links Report</a></p>
  <p><a href="javascript: reportLinks(document.links)">Show Links Report</a></p>
 </body>
</html>

It is probably a matter of loading the page and the moment that reportLinks executed exactly. I assume that the external some.js is added that the document is not completely build up. Is there a way that I can register this reportLinks call for onload event so that I can be sure that document.links is complete?

By the way the example works fine in both cases with Google Chrome.

(added after answer1)

As suggested by Marcel K. I rewrote the example, added also the code the way I really would like to have the thing going. And now testing it, and this simple example seems to work with Firefox and with Chrome.

<html>

 <head>

  <script type="text/javascript" src="some.js"></script>
  <script type="text/javascript">
   <!--
   function openWindow(){
    var w = window.open('', 'otherWin', 'width=600,height=600');
    w.document.write('<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;\n&lt;html&gt;\n'+
       document.getElementsByTagName("html")[0].innerHTML+'\n</html>');
w.onload=function(){
     reportLinks(w.document.links);
    };
    w.document.close();
   }

   function reportLinks(links){
    var report = 'links: '+links.length;
    for (var i=0;i<links.length;i++){
     report += '\n (link='+links[i].href+')';
    }
    alert(report);
   }
  //-->
  </script>
 </head>
 <body>
  <p><a href="javascript: openWindow()">Open Same Content and Show Links Report</a></p>
  <p><a href="javascript: reportLinks(document.links)">Show Links Report</a></p>
 </body>
</html>

I had hoped with this simple example to show a simple case of the actual code I am writing. A print preview screen of complicated html in which I want to disable all hrefs once opened. But in that one the onload handler is never called... How can I register an onload handler in this case in the most robust way?

Many thanks, Marcel

A: 

As I said in a comment, this is a very strange issue. But I think it happens because the inclusion of an external script causes a delay in page rendering (of the new page) and its DOM might not be ready to inspect.

My suspicion is supported by the fact that adding the (new) defer attribute seems to solve this issue:

This Boolean attribute is set to indicate to a browser that the script is meant to be executed after the document has been parsed.

The defer attribute can be set on the original page, as you want an exact copy of it. You can set it if it doesn't matter where a script is being included (e.g., when using document.write in your included file it does matter at which place you include it).

As defer is a Boolean attribute, it is activated when it is simply present (defer) or (when using XHTML) set to itself (defer="defer"). In your case, the script inclusion would read:

<script type="text/javascript" src="some.js" defer></script>

Update regarding your update: you should still insert a Doctype in the main page (consider using the HTML 5 one).

And I think the way you attached your onload event is the best you can do.

But considering the goal you want to achieve (a print preview without hyperlinks): you can also use the "print" media attribute and style hyperlinks like text; that's way more easy than the thing you are doing and it works when JavaScript is disabled.

Marcel Korpel
To start many thanks for the good advice! I have rewritten the example. See in further post. One question: how I understand defer='true': this will execute the script after the document is fully build up. But where do you set it then? It must be set inside the html of the popup (adding a script as string in the html you pass with write function)? Where this is very similar to putting the call to reportLinks inside a function registered as onload handler for the popup window. But how can onload listener be registered for popups (hopefully browser indep.) Thanks again!
Marcel
@Marcel: I updated my answer. Regarding the `onload` event of popups: as you're merely creating a new window, it has its own DOM and its own `onload` event. E.g., if it's defined in your some.js, the onload handler will be triggered on the main window, as well as on the newly created window.
Marcel Korpel
Thanks, now I see: defer for included script. Look at my extended question. There you can see what I mean with onload for the popup.
Marcel
A: 

The only way I could make the example above work portable over Firefox, Chrome and IE is by registering the onload listener through inlined JavaScript in the HTML loaded in the popup window. Following example code shows how.

<html>
 <head>
  <script type="text/javascript" src="script.js"></script>
 </head>
 <body>
  <p><a href="javascript: openWindow()">Open Same Content and Show Links Report</a></p>
  <p><a href="javascript: reportLinks(document.links)">Show Links Report</a></p>
 </body>
</html>

This page uses a script in script.js file. Following shows the content of that file.

function openWindow(){
  var w = window.open('', 'otherWin', 'width=600,height=600');
  w.document.write(
    '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" "http://www.w3.org/TR/html4/strict.dtd"&gt;\n&lt;html&gt;\n'+
    document.getElementsByTagName("html")[0].innerHTML+
    '\n <script type="text/javascript">\n'+
    '  function addOnloadListener(listener){\n'+
    '    if (window.addEventListener) {\n'+
    '      window.addEventListener("load", listener, false);\n'+
    '    } else {\n'+
    '      window.attachEvent("onload",listener);\n'+
    '    }\n'+
    '  }\n'+
    '  addOnloadListener(function(){reportLinks(document.links);});\n'+
    ' </script>\n'+
    '</html>');
  w.document.close();
}

function reportLinks(links){
  var report = 'links: '+links.length;
  for (var i=0;i<links.length;i++){
    report += '\n (link='+links[i].href+')';
  }
  alert(report);
}

When putting the function addOnloadListener directly in the JavaScript file (not inlined in the page) it doesn't work in IE6 because, I believe, it cannot handle the order of script entries correctly. When addOnloadListener was not inlined the inlined call to addOnloadListener didn't work, it simply couldn't find the function in the earlier:

<script type="text/javascript" src="script.js"></script>

The code is only a simple example that doesn't really do a lot. I used it for disabling all links in a print preview popup page.

A simpler way to register an onload listener for a popup window portable over browser is always welcome.

Thanks, Marcel

Marcel