调用document.close后,Document.links为空

时间:2010-08-28 16:20:12

标签: javascript firefox window.open

使用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>

您将看到,点击“打开相同内容和显示链接报告”时单击“显示链接报告”时显示的链接数量将为2.但是,当从此页面获得外部JavaScript文件引用时行为似乎不同(如果你愿意,只需将一个空文件some.js)。单击“打开相同内容并显示链接报告”时,链接数将为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>

这可能是加载页面和reportLinks完全执行的时刻。我假设添加了外部some.js,文档没有完全构建。有没有办法可以注册这个reportLinks调用onload事件,以便我可以确定document.links是完整的?

顺便说一下,这个示例在谷歌浏览器的两种情况下都能正常工作。

(在回答1后添加)

正如Marcel K所建议的那样。我重写了这个例子,并且按照我真正希望的方式添加了代码。现在测试它,这个简单的例子似乎适用于Firefox和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">\n<html>\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>

我希望通过这个简单的例子来展示我正在编写的实际代码的简单案例。复杂html的打印预览屏幕,我想在打开后禁用所有href。但在那一个onload处理程序永远不会被调用...如何在这种情况下以最强大的方式注册一个onload处理程序?

非常感谢, 烫发

2 个答案:

答案 0 :(得分:0)

正如我在评论中所说,这是一个非常奇怪的问题。但我认为这是因为包含外部脚本会导致(新页面)页面呈现延迟,并且其DOM可能无法进行检查。

我怀疑添加(新)defer属性似乎解决了这个问题:

  

此布尔属性设置为向浏览器指示在解析文档后脚本将被执行

可以在原始页面上设置defer属性,因为您需要它的精确副本。您可以设置它,如果包含脚本的位置无关紧要(例如,当您在包含的文件中使用document.write时, 在您包含它的位置很重要。)

由于defer是一个布尔属性,it is activated只是存在(defer)或(当使用XHTML时)设置为自身(defer="defer")。在您的情况下,脚本包含将显示为:

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

关于您的更新的

更新:您仍应在主页中插入Doctype(请考虑使用HTML 5 one)。

我认为你附加onload事件的方式是你能做的最好的事情。

但考虑到你想要实现的目标(没有超链接的打印预览):你也可以使用“打印”media attribute和样式超链接,如文本;那个方式比你正在做的事情更容易,当JavaScript被禁用时它会起作用。

答案 1 :(得分:0)

我能使上述示例在Firefox,Chrome和IE上可移植的唯一方法是通过弹出窗口中加载的HTML中的内联JavaScript注册onload侦听器。以下示例代码显示了如何。

<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>

此页面使用script.js文件中的脚本。以下显示该文件的内容。

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">\n<html>\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);
}

将函数addOnloadListener直接放在JavaScript文件中(未在页面中内联)时,它在IE6中不起作用,因为我认为它无法正确处理脚本条目的顺序。当没有内联addOnloadListener时,对addOnloadListener的内联调用不起作用,它根本找不到前面的函数:

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

代码只是一个简单的例子,并没有真正做很多事情。我用它来禁用打印预览弹出页面中的所有链接。

通过浏览器可移植的弹出窗口注册onload侦听器的简单方法总是受欢迎的。

谢谢, 烫发