iFrame src Detekcja zdarzeń zmiany?

Zakładając, że nie mam kontroli nad treścią w ramce iframe, czy jest jakiś sposób, że mogę wykryć zmianę src w nim poprzez Stronę nadrzędną? Może jakiś ładunek?

Moją ostatnią deską ratunku jest wykonanie 1-sekundowego testu interwałowego, jeśli iframe src jest taki sam jak wcześniej, ale zrobienie tego hakerskiego rozwiązania byłoby do bani.

Używam biblioteki jQuery, jeśli to pomoże.

Author: Matrym, 2010-03-12

7 answers

Możesz użyć zdarzenia onLoad, jak w poniższym przykładzie:

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

Alert pojawi się po każdej zmianie lokalizacji w ramce iframe. Działa we wszystkich nowoczesnych przeglądarkach, ale może nie działać w niektórych bardzo starszych przeglądarkach, takich jak IE5 i wczesna Opera. (Source )

Jeśli ramka iframe wyświetla stronę w tej samej domenie rodzica , będzie można uzyskać dostęp do lokalizacji za pomocą contentWindow.location, jak w poniższym przykładzie:

<iframe src="/test.html" onLoad="alert(this.contentWindow.location);"></iframe>
 164
Author: Daniel Vassallo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-18 18:54:21

Odpowiedź na podstawie JQuery

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

Jak wspomniał subharb, od JQuery 3.0 należy to zmienić na:

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

Https://jquery.com/upgrade-guide/3.0/#breaking-change-load-unload-and-error-removed

 50
Author: Michiel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-21 09:55:25

Jeśli nie masz kontroli nad stroną i chcesz obserwować jakąś zmianę, to nowoczesną metodą jest użycie MutationObserver

Przykład jego użycia, obserwowanie atrybutu src do zmiany 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>

Wyjście po 3 sekundach

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.

 29
Author: Xotic750,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:39

Ramka iframe zawsze przechowuje Stronę nadrzędną, powinieneś użyć tego, aby wykryć, na której stronie jesteś w ramce iframe:

Kod 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
Author: Tarik FAMIL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-05 09:21:05

Oto metoda, która jest używana wCommerce SagePay i wCommerce Paypoint modułach Drupal, który zasadniczo porównuje document.location.href ze starą wartością, najpierw ładując własny iframe, a następnie zewnętrzny.

Więc zasadniczo chodzi o załadowanie pustej strony jako elementu zastępczego z własnym kodem JS i ukrytym formularzem. Następnie rodzic kod JS prześle Ukryty formularz, gdzie jego #action wskazuje na zewnętrzną ramkę iframe. Gdy nastąpi przekierowanie / submit, kod JS, który nadal działa na tej stronie można śledzić zmiany wartości document.location.href.

Oto przykład JS używany w iframe:

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

I tu jest js używany na stronie nadrzędnej:

;(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);

Następnie w tymczasowej pustej stronie docelowej musisz dołączyć formularz, który przekieruje na stronę zewnętrzną.

 1
Author: kenorb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-03-16 15:49:08

Inne odpowiedzi zaproponowały Zdarzenie load, ale wywołało ono Po załadowaniu nowej strony w ramce iframe. Może być konieczne powiadomienie natychmiast po zmianie adresu URL , a nie po załadowaniu nowej strony.

Oto proste rozwiązanie 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>

To z powodzeniem wyśledzi zmiany atrybutów src, jak również wszelkie zmiany adresów URL dokonane wewnątrz ramki iframe.

Testowane we wszystkich nowoczesnych przeglądarki.

Uwaga: powyższy fragment będzie działał tylko wtedy, gdy ramka iframe ma to samo pochodzenie.

Zrobiłem gist z tego kodu, jak również. Możesz też sprawdzić moją drugą odpowiedź . To idzie trochę dogłębnie do tego, jak to działa.

 1
Author: Hristiyan Dodov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-06 14:25:15

Od wersji 3.0 Jquery może pojawić się błąd

TypeError: url.indexOf nie jest funkcją

Które można łatwo naprawić wykonując

$('#iframe').on('load', function() {
    alert('frame has (re)loaded ');
});
 0
Author: subharb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-18 09:58:01