Iframeのコンテンツを制御できないと仮定すると、親ページを介してsrcの変更を検出できる方法はありますか?多分何かのオンロード?
私の最後の手段は、iframe srcが以前と同じ場合に1秒の間隔テストを行うことですが、このハッキングの解決策を実行することはうまくいきません。
役立つ場合は、jQueryライブラリを使用しています。
次の例のように、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>
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
ページを制御できず、何らかの変更を監視したい場合、最新の方法は 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
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);
}
他の回答は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 も確認できます。これがどのように機能するかについて少し詳しく説明します。
Jqueryのバージョン3.0以降、エラーが発生する場合があります
TypeError:url.indexOfは関数ではありません
を行うことで簡単に修正できます
$('#iframe').on('load', function() {
alert('frame has (re)loaded ');
});
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);
次に、一時的な空白のランディングページに、外部ページにリダイレクトするフォームを含める必要があります。