web-dev-qa-db-ja.com

iFrame src変更イベントの検出?

Iframeのコンテンツを制御できないと仮定すると、親ページを介してsrcの変更を検出できる方法はありますか?多分何かのオンロード?

私の最後の手段は、iframe srcが以前と同じ場合に1秒の間隔テストを行うことですが、このハッキングの解決策を実行することはうまくいきません。

役立つ場合は、jQueryライブラリを使用しています。

159
Matrym

次の例のように、onLoadイベントを使用できます。

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

Iframe内の場所が変更されると、アラートがポップアップ表示されます。最新のすべてのブラウザで動作しますが、IE5や初期のOperaなどの非常に古いブラウザでは動作しない場合があります。 ( ソース

iframeが親の同じドメイン内のページを表示している場合、次の例のように、contentWindow.locationで場所にアクセスできます。

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

JQuery <3に基づく回答

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

サブハーバーで述べたように、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

54
Michiel

ページを制御できず、何らかの変更を監視したい場合、最新の方法は 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

元の質問がこの質問の複製として閉じられたため、ここに回答を投稿しました。

32
Xotic750

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);
    }
6
Tarik FAMIL

他の回答はloadイベントを提案しましたが、iframeの新しいページがロードされた後afterを起動します。新しいページが読み込まれた後ではなく、RLが変更された直後に通知する必要がある場合があります。

これがプレーン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自体から行われたURLの変更が正常に追跡されます。

最新のすべてのブラウザーでテスト済み。

注:上記のスニペットは、iframeが同じOriginである場合にのみ機能します。

このコードでも Gist を作成しました。他の answer も確認できます。これがどのように機能するかについて少し詳しく説明します。

3
Hristiyan Dodov

Jqueryのバージョン3.0以降、エラーが発生する場合があります

TypeError:url.indexOfは関数ではありません

を行うことで簡単に修正できます

$('#iframe').on('load', function() {
    alert('frame has (re)loaded ');
});
2
subharb

Commerce SagePay および Commerce Paypoint Drupalモジュールで使用されるメソッドは、基本的にdocument.location.hrefを最初に独自の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);

次に、一時的な空白のランディングページに、外部ページにリダイレクトするフォームを含める必要があります。

1
kenorb