web-dev-qa-db-fra.com

Détection d'événement de changement d'iFrame src?

En supposant que je n'ai aucun contrôle sur le contenu de l'iframe, y a-t-il un moyen de détecter un changement de src via la page parent? Une sorte de surcharge peut-être?

Mon dernier recours est de faire un test d’intervalle d’une seconde si l’iframe src est identique à ce qu’il était auparavant, mais le fait de procéder de la sorte serait vraiment nul.

J'utilise la bibliothèque jQuery si cela peut aider.

161
Matrym

Vous souhaiterez peut-être utiliser l'événement onLoad, comme dans l'exemple suivant:

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

L'alerte apparaîtra à chaque changement d'emplacement dans l'iframe. Cela fonctionne dans tous les navigateurs modernes, mais peut ne pas fonctionner dans certains navigateurs très anciens comme IE5 et le début d'Opera. ( Source )

Si l'iframe affiche une page du même domaine que le parent , vous pourrez accéder à l'emplacement avec contentWindow.location, comme dans l'exemple suivant:

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

Réponse basée sur JQuery <3

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

Comme mentionné par subharb, à partir de JQuery 3.0, il faut modifier ceci:

$('#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

Si vous n’avez aucun contrôle sur la page et que vous souhaitez observer un changement, la méthode moderne consiste à utiliser MutationObserver

Un exemple de son utilisation, surveillant l'attribut src pour changer d'un 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>

Sortie après 3 secondes

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/ 

Sur jsFiddle

réponse publiée ici car la question initiale a été clôturée comme une copie de celle-ci.

33
Xotic750

L'iframe conserve toujours la page parent. Vous devriez l'utiliser pour déterminer dans quelle page vous vous trouvez dans l'iframe:

Code 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

D'autres réponses proposaient l'événement load, mais il se déclenche après la nouvelle page de l'iframe est chargée. Vous devrez peut-être être averti immédiatement après le changement d'URL , et non après le chargement de la nouvelle page.

Voici une solution JavaScript simple:

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>

Cela permettra de suivre avec succès les modifications d'attribut src, ainsi que toutes les modifications d'URL effectuées à partir de l'iframe lui-même.

Testé dans tous les navigateurs modernes.

Remarque: L'extrait de code ci-dessus ne fonctionnera que si l'iframe a la même origine.

J'ai fait un Gist avec ce code aussi. Vous pouvez vérifier mon autre réponse aussi. Cela va un peu en profondeur dans la façon dont cela fonctionne.

3
Hristiyan Dodov

Depuis la version 3.0 de Jquery, vous pourriez recevoir une erreur

TypeError: url.indexOf n'est pas une fonction

Ce qui peut être facilement résolu en faisant

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

Voici la méthode utilisée dans les modules Commerce SagePay et Commerce Paypoint Drupal qui compare fondamentalement document.location.href à l'ancienne valeur en premier chargement de son propre iframe, puis externe.

L’idée est donc de charger la page vierge en tant qu’espace réservé avec son propre code JS et sa forme masquée. Ensuite, le code JS parent soumettra ce formulaire caché où son #action pointe vers l'iframe externe. Une fois la redirection/soumission effectuée, le code JS qui est toujours actif sur cette page peut suivre vos changements de valeur document.location.href.

Voici un exemple de JS utilisé dans iframe:

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

Et voici JS utilisé dans la page parent:

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

Ensuite, dans la page de destination vierge temporaire, vous devez inclure le formulaire qui redirigera vers la page externe.

1
kenorb