iFrame src改变事件检测?

时间:2010-03-11 22:07:46

标签: javascript jquery iframe onload

假设我无法控制iframe中的内容,是否有任何方法可以通过父页面检测到src更改?某种上载可能吗?

我的最后一招是,如果iframe src与以前相同,则进行1秒间隔测试,但是做这个hacky解决方案会很糟糕。

如果有帮助,我正在使用jQuery库。

7 个答案:

答案 0 :(得分:179)

您可能希望使用onLoad事件,如以下示例所示:

<iframe src="http://www.google.com/" onLoad="alert('Test');"></iframe>

只要iframe中的位置发生变化,系统就会弹出警报。它适用于所有现代浏览器,但可能无法在IE5和早期Opera等一些非常老的浏览器中使用。 (Source

如果iframe在父级的同一域中显示页面,您就可以使用contentWindow.location访问该位置,如下例所示:

<iframe src="/test.html" onLoad="alert(this.contentWindow.location);"></iframe>

答案 1 :(得分:54)

基于JQuery的答案&lt; 3

$('#iframeid').load(function(){
    alert('frame has (re)loaded');
});

如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

答案 2 :(得分:30)

如果您无法控制页面并希望观察某种变化,那么现代方法就是使用MutationObserver

使用示例,查看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>

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/ 

jsFiddle

Posted answer here as original question was closed as a duplicate of this one.

答案 3 :(得分:6)

iframe始终保留父页面,您应该使用它来检测您在iframe中的哪个页面:

Html代码:

<iframe id="iframe" frameborder="0" scrolling="no" onload="resizeIframe(this)" width="100%" src="www.google.com"></iframe>

JS:

    function resizeIframe(obj) {
        alert(obj.contentWindow.location.pathname);
    }

答案 4 :(得分:3)

其他答案提出了load事件,但在加载iframe中的新页面后,它会触发。您可能需要在网址更改后立即通知,而不是在加载新网页后通知。

这是一个简单的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>

这将成功跟踪src属性更改,以及iframe内部所做的任何网址更改。

在所有现代浏览器中测试过。

注意:以上代码段仅在iframe具有相同来源时才有效。

我也使用此代码制作了gist。您也可以查看我的其他answer。它深入探讨了它的工作原理。

答案 5 :(得分:2)

从Jquery 3.0版开始,您可能会收到错误

  

TypeError:url.indexOf不是函数

可以通过

轻松解决
{{1}}

答案 6 :(得分:1)

以下是Commerce SagePayCommerce Paypoint Drupal模块中使用的方法,它基本上将document.location.href与旧值进行比较,首先加载自己的iframe,然后加载外部iframe。

所以基本上我的想法是将空白页面加载为具有自己的JS代码和隐藏表单的占位符。然后,父JS代码将提交隐藏的表单,其#action指向外部iframe。一旦重定向/提交发生,仍然在该页面上运行的JS代码可以跟踪您的document.location.href值更改。

以下是iframe中使用的示例JS:

;(function($) {
  Drupal.behaviors.commercePayPointIFrame = {
    attach: function (context, settings) {
      if (top.location != location) {
        $('html').hide();
        top.location.href = document.location.href;
      }
    }
  }
})(jQuery);

这是在父页面中使用的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);

然后在临时空白登录页面中,您需要包含将重定向到外部页面的表单。