检测使用 window.open 打开的窗口的 onload 事件

Posted

技术标签:

【中文标题】检测使用 window.open 打开的窗口的 onload 事件【英文标题】:Detecting the onload event of a window opened with window.open 【发布时间】:2011-03-03 03:09:49 【问题描述】:
 window.popup = window.open($(this).attr('href'), 'Ad', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0');
 $(window.popup).onload = function()
        
                alert("Popup has loaded a page");
        ;

这不适用于我尝试过的任何浏览器(IE、Firefox、Chrome)。如何检测页面何时加载到窗口中(如 iframe onload)?

【问题讨论】:

我猜你的 中已经有 onLoad 了? 假设我不控制弹出窗口中打开的页面 你想用$(...).onload 做什么? window.popup.onload 有什么问题? ^ 这实际上可能是它的问题.. 编辑:是的.. 修复了它,但不适用于跨域 【参考方案1】:

如Detecting the onload event of a window opened with window.open 所述,以下解决方案是理想的:

/* Internet Explorer will throw an error on one of the two statements, Firefox on the other one of the two. */
(function(ow) 
    ow.addEventListener("load", function()  alert("loaded"); , false);
    ow.attachEvent("onload", function()  alert("loaded"); , false);
)(window.open(prompt("Where are you going today?", location.href), "snapDown"));

其他 cmets 和答案犯了几个错误的误解,如下所述。

以下脚本演示了定义onload 的反复无常。将脚本应用于正在打开的窗口的“快速加载”位置,例如具有file: 方案的位置,并将其与“慢”位置进行比较以查看问题:可以看到onload 消息或根本没有(通过重新加载加载的页面可以看到所有 3 个变体)。还假设正在加载的页面本身没有定义onload 事件,这会使问题更加复杂。

onload 定义显然不是“内部弹出文档标记”:

var popup = window.open(location.href, "snapDown");
popup.onload = function()  alert("message one"); ;
alert("message 1 maybe too soon\n" + popup.onload);
popup.onload = function()  alert("message two"); ;
alert("message 2 maybe too late\n" + popup.onload);

你可以做什么:

打开一个带有“外来”URL 的窗口 在该窗口的地址栏上输入javascript: URI——代码将以与“外来”URL 域相同的权限运行 如果在地址栏中键入 javascript: URI 无效(可能是 2012 年左右发布的某些浏览器的情况),则可能需要将其添加书签

因此,几乎任何页面,无论来源如何,都可以修改为:

if(confirm("wipe out links & anchors?\n" + document.body.innerhtml))
    void(document.body.innerHTML=document.body.innerHTML.replace(/<a /g,"< a "))

嗯,差不多:

jar:file:///usr/lib/firefox/omni.ja!/chrome/toolkit/content/global/aboutSupport.xhtml,Mozilla Firefox 的疑难解答页面和其他 Jar 档案除外。

作为另一个示例,要定期禁用 Google 篡夺目标命中,请将其 rwt 函数更改为以下 URI:

javascript: void(rwt = function(unusurpURL)  return unusurpURL; )

(可选择将上述内容添加为书签,例如“Spay Google”(“neutralize Google”?)

然后在点击任何 Google 点击之前点击此书签,因此任何这些点击的书签都是干净的,而不是 Google 用它们制造的杂乱无章的变态异常。

使用Mozilla/5.0 (X11; Ubuntu; Linux i686; rv:11.0) Gecko/20100101 Firefox/11.0 UA 字符串完成的测试。

需要注意的是,Firefox 中的addEventListener 只有一个非标准的第四个布尔参数,如果true 允许为外部页面实例化不受信任的内容触发器。

参考:element.addEventListener | Document Object Model (DOM) | MDN:Interaction between privileged and non-privileged pages | Code snippets | MDN:

【讨论】:

这个答案中有很多句子说一件事,然后是另一个句子纠正前一个。这导致它难以遵循。这里有很好的信息,只是很难看到。说得更清楚,你会得到更多的支持。 另外,如果这个问题由另一个问题回答,也许值得将其标记为另一个问题的副本,并在评论中将提问者引导到另一个问题。 引用的答案是直接share 链接到这个问题的已发布答案 - 最好......完成! ... 支持本身不是问题 - 混淆?希望没有什么是直接矛盾的——“误解”是指以前的 cmets 和关于 x-site 脚本和创作政策的答案,希望不是这个答案! - 希望通过运行功能代码示例的经验证据更简洁准确地验证散文 - ow! (O pen W indow 或者应该是 function(ouch),双关语是指第一个示例中未处理的错误条件!)如果写作,散文非常尖锐读起来很痛……! 你的写作风格很难读。试图辨别这个答案的含义,我的大脑受伤了。简洁不是坏事。【参考方案2】:

首先,当您的第一个初始窗口被加载时,它被缓存。因此,当从第一个窗口创建new窗口时,新窗口的内容不是从服务器加载的,而是从缓存中加载的。因此,当您创建 new 窗口时,不会发生 onload 事件。

但是,在这种情况下,会发生 onpageshow 事件。它总是在onload 事件之后发生,即使页面是从缓存中加载。此外,现在所有主流浏览器都支持它。

 window.popup = window.open($(this).attr('href'), 'Ad', 'left=20,top=20,width=500,height=500,toolbar=1,resizable=0');
 $(window.popup).onpageshow = function() 
     alert("Popup has loaded a page");
 ;

w3school website 对此进行了详细说明:

onpageshow 事件类似于onload 事件,只是它在页面首次加载时发生在onload 事件之后。此外,每次加载页面时都会发生 onpageshow 事件,而从缓存加载页面时不会发生 onload 事件。

【讨论】:

【参考方案3】:

核心问题似乎是您正在打开一个窗口以显示其内容已缓存在浏览器中的页面。因此不会发生加载,因此不会发生加载事件。

一种可能性是改用“pageshow”事件,如下所述:

https://support.microsoft.com/en-us/help/3011939/onload-event-does-not-occur-when-clicking-the-back-button-to-a-previou

【讨论】:

【参考方案4】:

如果弹出窗口的文档来自不同的域,这是不可能的。

2015 年 4 月更新:我错了:如果您拥有这两个域,you can use window.postMessage and the message event 和 pretty much all browsers 与今天相关

如果没有,如果没有将文档加载到弹出窗口中的帮助,您仍然无法跨浏览器完成这项工作。您需要能够检测到弹出窗口加载后发生的变化,这可能是弹出页面中的 JavaScript 在处理自己的load 事件时设置的变量,或者如果您有一些控制它,您可以在开启程序中添加对函数的调用。

【讨论】:

一个简单的方法来检查它以在 setTimeout() 调用中监视另一个页面中 JS 函数的可用性。 根据这篇帖子***.com/questions/25098021/… 是可能的,但您必须同时拥有这两个域。【参考方案5】:

这对我有用;完整示例:

HTML:

<a href="/my-popup.php" class="import">Click for my popup on same domain</a>

Javascript:

(function()
    var doc = document;

    jQuery('.import').click(function(e)
        e.preventDefault();
        window.popup = window.open(jQuery(this).attr('href'), 'importwindow', 'width=500, height=200, top=100, left=200, toolbar=1');

        window.popup.onload = function() 
            window.popup.onbeforeunload = function()
                doc.location.reload(true); //will refresh page after popup close
            
        
    );
)();

【讨论】:

应该说只有两个域相同的情况下才有效【参考方案6】:
var myPopup = window.open(...);
myPopup.addEventListener('load', myFunction, false);

如果您关心 IE,请使用以下内容作为第二行:

myPopup[myPopup.addEventListener ? 'addEventListener' : 'attachEvent'](
  (myPopup.attachEvent ? 'on' : '') + 'load', myFunction, false
);

如您所见,支持 IE 相当繁琐,应该避免如果可能。我的意思是,如果您因为您的受众而需要支持 IE,请务必这样做。

【讨论】:

反正我可以跨域吗? 很遗憾没有。出于安全原因,浏览器禁用跨不同域的 JavaScript 对象交互。 然后只使用第三条件。我会添加它。 我花了几个小时寻找解决方案,这是唯一对我有用的解决方案。需要注意的一点是,Firefox 似乎在完全加载页面之前打开了打印对话框。这将导致打印空白页。我通过检测浏览器解决了这个问题,然后在需要时使用 onload 事件。这可能不是最好的方法,但它对我有用。这是我的代码: var w = window.open(targetUrl, "_blank"); w[w.addEventListener ? 'addEventListener' : 'attachEvent']( (w.attachEvent ? 'on' : '') + 'load', doPrint(w), false );【参考方案7】:

onload 事件处理程序必须在弹出窗口的 HTML &lt;body&gt; 标记内。

【讨论】:

这是我触发它的唯一方法,尝试了几乎所有其他可能的方法 - 谢谢。 $(popup).find('body').attr('onload', 'window.print();'); 终于成功了。

以上是关于检测使用 window.open 打开的窗口的 onload 事件的主要内容,如果未能解决你的问题,请参考以下文章

js打开新窗口并且不被拦截

window open怎样才能在原有窗口中打开新窗口

window.open打开网址被拦截

在浏览器窗口中打开新标签(使用 window.open 打开)

window.open(url)新窗口打开链接被浏览器拦截解决方案

window.open新打开窗口与新开标签页