Javascript iFrame src 更改事件检测?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2429045/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
iFrame src change event detection?
提问by Matrym
Assuming I have no control over the content in the iframe, is there any way that I can detect a src change in it via the parent page? Some sort of onload maybe?
假设我无法控制 iframe 中的内容,有什么方法可以通过父页面检测其中的 src 更改吗?也许是某种加载?
My last resort is to do a 1 second interval test if the iframe src is the same as it was before, but doing this hacky solution would suck.
如果 iframe src 与以前相同,我最后的手段是进行 1 秒的间隔测试,但是执行这个 hacky 解决方案会很糟糕。
I'm using the jQuery library if it helps.
如果有帮助,我正在使用 jQuery 库。
回答by Daniel Vassallo
You may want to use the onLoadevent, as in the following example:
您可能希望使用该onLoad事件,如下例所示:
<iframe src="http://www.google.com/" onLoad="alert('Test');"></iframe>
The alert will pop-up whenever the location within the iframe changes. It works in all modern browsers, but may not work in some very older browsers like IE5 and early Opera. (Source)
每当 iframe 中的位置发生变化时,就会弹出警报。它适用于所有现代浏览器,但可能不适用于一些非常旧的浏览器,如 IE5 和早期的 Opera。(来源)
If the iframe is showing a page within the same domain of the parent, you would be able to access the location with contentWindow.location, as in the following example:
如果 iframe 显示在 parent 的同一域中的页面,您将能够使用 访问该位置contentWindow.location,如下例所示:
<iframe src="/test.html" onLoad="alert(this.contentWindow.location);"></iframe>
回答by Michiel
Answer based on JQuery < 3
答案基于 JQuery < 3
$('#iframeid').load(function(){
alert('frame has (re)loaded');
});
As mentioned by subharb, as from JQuery 3.0 this needs to be changed to:
正如 subharb 所提到的,从 JQuery 3.0 开始,这需要更改为:
$('#iframe').on('load', function() {
alert('frame has (re)loaded ');
});
https://jquery.com/upgrade-guide/3.0/#breaking-change-load-unload-and-error-removed
https://jquery.com/upgrade-guide/3.0/#break-change-load-unload-and-error-removed
回答by Xotic750
If you have no control over the page and wish to watch for some kind of change then the modern method is to use MutationObserver
如果您无法控制页面并希望观察某种变化,那么现代方法是使用 MutationObserver
An example of its use, watching for the srcattribute to change of an iframe
它的使用示例,观察src属性的变化iframe
new MutationObserver(function(mutations) {
mutations.some(function(mutation) {
if (mutation.type === 'attributes' && mutation.attributeName === 'src') {
console.log(mutation);
console.log('Old src: ', mutation.oldValue);
console.log('New src: ', mutation.target.src);
return true;
}
return false;
});
}).observe(document.body, {
attributes: true,
attributeFilter: ['src'],
attributeOldValue: true,
characterData: false,
characterDataOldValue: false,
childList: false,
subtree: true
});
setTimeout(function() {
document.getElementsByTagName('iframe')[0].src = 'http://jsfiddle.net/';
}, 3000);
<iframe src="http://www.google.com"></iframe>
Output after 3 seconds
3秒后输出
MutationRecord {oldValue: "http://www.google.com", attributeNamespace: null, attributeName: "src", nextSibling: null, previousSibling: null…}
Old src: http://www.google.com
New src: http://jsfiddle.net/
On jsFiddle
Posted answer here as original question was closed as a duplicate of this one.
回答by dodov
Note:The snippet would only work if the iframe is with the same origin.
注意:该代码段仅在 iframe 具有相同来源时才有效。
Other answers proposed the loadevent, but it fires afterthe new page in the iframe is loaded. You might need to be notified immediately after the URL changes, not after the new page is loaded.
其他答案提出了该load事件,但它会在iframe 中的新页面加载后触发。您可能需要在 URL 更改后立即收到通知,而不是在加载新页面之后。
Here's a plain JavaScript solution:
这是一个简单的 JavaScript 解决方案:
function iframeURLChange(iframe, callback) {
var unloadHandler = function () {
// Timeout needed because the URL changes immediately after
// the `unload` event is dispatched.
setTimeout(function () {
callback(iframe.contentWindow.location.href);
}, 0);
};
function attachUnload() {
// Remove the unloadHandler in case it was already attached.
// Otherwise, the change will be dispatched twice.
iframe.contentWindow.removeEventListener("unload", unloadHandler);
iframe.contentWindow.addEventListener("unload", unloadHandler);
}
iframe.addEventListener("load", attachUnload);
attachUnload();
}
iframeURLChange(document.getElementById("mainframe"), function (newURL) {
console.log("URL changed:", newURL);
});
<iframe id="mainframe" src=""></iframe>
This will successfully track the srcattribute changes, as well as any URL changes made from within the iframe itself.
这将成功跟踪src属性更改,以及从 iframe 本身进行的任何 URL 更改。
Tested in all modern browsers.
在所有现代浏览器中测试。
I made a gistwith this code as well. You can check my other answertoo. It goes a bit in-depth into how this works.
回答by Tarik FAMIL
The iframe always keeps the parent page, you should use this to detect in which page you are in the iframe:
iframe 始终保留父页面,您应该使用它来检测您在 iframe 中的哪个页面:
Html code:
html代码:
<iframe id="iframe" frameborder="0" scrolling="no" onload="resizeIframe(this)" width="100%" src="www.google.com"></iframe>
Js:
JS:
function resizeIframe(obj) {
alert(obj.contentWindow.location.pathname);
}
回答by subharb
Since version 3.0 of Jquery you might get an error
从 Jquery 3.0 版开始,您可能会收到错误消息
TypeError: url.indexOf is not a function
类型错误:url.indexOf 不是函数
Which can be easily fix by doing
这可以通过执行轻松修复
$('#iframe').on('load', function() {
alert('frame has (re)loaded ');
});
回答by kenorb
Here is the method which is used in Commerce SagePayand in Commerce PaypointDrupal modules which basically compares document.location.hrefwith the old value by first loading its own iframe, then external one.
这是在Commerce SagePay和Commerce PaypointDrupal 模块中使用的方法,它基本上document.location.href通过首先加载自己的 iframe,然后加载外部 iframe 与旧值进行比较。
So basically the idea is to load the blank page as a placeholder with its own JS code and hidden form. Then parent JS code will submit that hidden form where its #actionpoints to the external iframe. Once the redirect/submit happens, the JS code which still running on that page can track your document.location.hrefvalue changes.
所以基本上的想法是将空白页面作为占位符加载,并带有自己的 JS 代码和隐藏表单。然后父 JS 代码将提交隐藏的表单,它#action指向外部 iframe。一旦重定向/提交发生,仍在该页面上运行的 JS 代码可以跟踪您的document.location.href值更改。
Here is example JS used in iframe:
以下是 iframe 中使用的示例 JS:
;(function($) {
Drupal.behaviors.commercePayPointIFrame = {
attach: function (context, settings) {
if (top.location != location) {
$('html').hide();
top.location.href = document.location.href;
? }
}
}
})(jQuery);
And here is JS used in parent page:
这是父页面中使用的JS:
;(function($) {
/**
* Automatically submit the hidden form that points to the iframe.
*/
Drupal.behaviors.commercePayPoint = {
attach: function (context, settings) {
$('div.payment-redirect-form form', context).submit();
$('div.payment-redirect-form #edit-submit', context).hide();
$('div.payment-redirect-form .checkout-help', context).hide();
}
}
})(jQuery);
Then in temporary blank landing page you need to include the form which will redirect to the external page.
然后在临时空白登录页面中,您需要包含将重定向到外部页面的表单。

