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