IFrame src изменить событие обнаружения?

Предполагая, что я не контролирую содержимое в iframe, есть ли способ обнаружить изменение src в нем через родительскую страницу? Может быть, какая-то загрузка?

Мое последнее средство - выполнить 1-секундный интервал, если iframe src такой же, как и раньше, но выполнение этого хакерского решения сосало бы.

Я использую библиотеку jQuery, если это помогает.

Ответ 1

Возможно, вы захотите использовать событие 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>

Ответ 2

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

Ответ 3

Если у вас нет контроля над страницей и вы хотите наблюдать за каким-то изменением, то современный метод заключается в использовании 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>

Ответ 4

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

Ответ 5

Вот метод, который используется в Commerce SagePay и в Commerce Paypoint. Модули Drupal, которые в основном сравнивают document.location.href со старым значением, сначала загружая свой собственный iframe, затем внешний.

Итак, в основном идея состоит в том, чтобы загрузить пустую страницу в качестве заполнителя с собственным кодом JS и скрытой формой. Затем родительский JS-код отправит эту скрытую форму, где ее #action указывает на внешний iframe. После того, как произойдет перенаправление/отправка, код JS, который все еще работает на этой странице, может отслеживать ваше значение document.location.href.

Вот пример JS, используемый в iframe:

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

Затем на временной пустой целевой странице вам необходимо включить форму, которая будет перенаправляться на внешнюю страницу.

Ответ 6

Другие ответы предложили событие load, но он запускается после загрузки новой страницы в iframe. Возможно, вам потребуется уведомление сразу после изменения URL, а не после загрузки новой страницы.

Здесь простое решение для 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>