156 votes

Callback Javascript lorsque le chargement de l'IFRAME est terminé ?

J'ai besoin d'exécuter un callback lorsqu'un IFRAME a fini de se charger. Je n'ai aucun contrôle sur le contenu de la IFRAME, je ne peux donc pas lancer la fonction de rappel à partir de là.

Cette IFRAME est créée de manière programmatique, et j'ai besoin de passer ses données comme une variable dans le callback, ainsi que de détruire l'iframe.

Des idées ?

EDITAR:

Voici ce que j'ai maintenant :

function xssRequest(url, callback)
{
    var iFrameObj = document.createElement('IFRAME');
    iFrameObj.src = url;            
    document.body.appendChild(iFrameObj);   

    $(iFrameObj).load(function() 
    {
        document.body.removeChild(iFrameObj);
        callback(iFrameObj.innerHTML);
    });
}

Ce rappel a lieu avant que l'iFrame ne soit chargée, de sorte que le rappel ne renvoie aucune donnée.

1 votes

Je pense que vous ne voulez pas attacher le gestionnaire d'événement sur l'iframe lui-même mais sur sa fenêtre de contenu.

1 votes

Le problème est la demande inter-domaine. Vous ne pouvez pas le faire si l'iframe provient d'un autre domaine.

0 votes

En fait, il y a un événement de chargement sur l'objet iframe qui se déclenche chaque fois que l'iframe termine le chargement d'un document, sinon, il faudrait se connecter à la fenêtre après chaque chargement.

49voto

Remy Sharp Points 2953

Tout d'abord, d'après le nom de la fonction xssRequest il semble que vous essayez de faire des requêtes intersites - ce qui, si c'est le cas, ne vous permettra pas de lire le contenu de l'iframe.

D'autre part, si l'URL de l'iframe se trouve sur votre domaine, vous pouvez accéder au corps, mais j'ai constaté que si j'utilise un délai d'attente pour supprimer l'iframe, le rappel fonctionne bien :

// possibly excessive use of jQuery - but I've got a live working example in production
$('#myUniqueID').load(function () {
  if (typeof callback == 'function') {
    callback($('body', this.contentWindow.document).html());
  }
  setTimeout(function () {$('#frameId').remove();}, 50);
});

4 votes

Vous pourriez remplacer $('body', this.contentWindow.document).html() con this.contentDocument.body.outerHTML

12 votes

Une idée de comment faire cela sans jQuery ?

7 votes

À partir de jQuery 3.0, load est parti. Veuillez utiliser .on('load', function() { ... }) à la place.

38voto

Neo Points 2870

J'utilise jQuery et, étonnamment, cela semble se charger. Je viens de tester et de charger une page lourde et je n'ai pas eu l'alerte pendant quelques secondes jusqu'à ce que je voie l'iframe se charger :

$('#the_iframe').load(function(){
    alert('loaded!');
});

Donc, si vous ne voulez pas utiliser jQuery, jetez un coup d'œil à leur code source et voyez si cette fonction se comporte différemment avec les éléments DOM des iframes, je regarderai moi-même plus tard car je suis intéressé et je posterai ici. Je n'ai testé qu'avec la dernière version de Chrome.

0 votes

J'ai remarqué que vous avez créé l'élément DOM avec du javascript pur et que vous avez ensuite passé cette variable à jQuery comme sélecteur, c'est peut-être la raison pour laquelle votre code ne fonctionne pas ?

16 votes

À partir de jQuery 3.0, load a disparu. Veuillez utiliser .on('load', function() { ... }) à la place.

8voto

allyourcode Points 5670

Le innerHTML de votre iframe est vide car votre balise iframe n'entoure aucun contenu dans le document parent. Pour obtenir le contenu de la page à laquelle fait référence l'attribut src de l'iframe, vous devez accéder à la propriété contentDocument de l'iframe. Une exception sera toutefois levée si le src provient d'un domaine différent. Il s'agit d'une fonction de sécurité qui vous empêche d'exécuter un JavaScript arbitraire sur la page de quelqu'un d'autre, ce qui créerait une vulnérabilité de scripting intersite. Voici quelques exemples de code qui illustrent ce dont je parle :

<script src="http://prototypejs.org/assets/2009/8/31/prototype.js" type="text/javascript"></script>

<h1>Parent</h1>

<script type="text/javascript">
function on_load(iframe) {
  try {
    // Displays the first 50 chars in the innerHTML of the
    // body of the page that the iframe is showing.
    // EDIT 2012-04-17: for wider support, fallback to contentWindow.document
    var doc = iframe.contentDocument || iframe.contentWindow.document;
    alert(doc.body.innerHTML.substring(0, 50));
  } catch (e) {
    // This can happen if the src of the iframe is
    // on another domain
    alert('exception: ' + e);
  }
}
</script>
<iframe id="child" src="iframe_content.html" onload="on_load(this)"></iframe>

Pour approfondir l'exemple, essayez d'utiliser ceci comme contenu de l'iframe :

<h1>Child</h1>

<a href="http://www.google.com/">Google</a>

<p>Use the preceeding link to change the src of the iframe
to see what happens when the src domain is different from
that of the parent page</p>

1 votes

La propriété contentDocument n'est pas supportée par IE 7 et peut-être d'autres IE aussi, la façon de traiter avec IE est window['iframeid'].document ou ce qui est exactement la même chose window.frames['iframeid'].document preuve lien ici developer.mozilla.org/fr/

8voto

Ryan Cook Points 5613

J'ai eu à le faire dans des cas où des documents tels que des documents Word et des PDF étaient transmis à l'iframe et j'ai trouvé une solution qui fonctionne assez bien. La clé est de gérer le onreadystatechanged sur l'iframe.

Disons que le nom de votre cadre est "myIframe". D'abord, quelque part dans votre code de démarrage (je le fais en ligne n'importe où après l'iframe), ajoutez quelque chose comme ceci pour enregistrer le gestionnaire d'événement :

document.getElementById('myIframe').onreadystatechange = MyIframeReadyStateChanged;

Je n'ai pas été en mesure d'utiliser un attribut onreadystatechage sur l'iframe, je ne me souviens plus pourquoi, mais l'application devait fonctionner dans IE 7 et Safari 3, donc cela a pu être un facteur.

Voici un exemple de la façon d'obtenir l'état complet :

function MyIframeReadyStateChanged()
{
    if(document.getElementById('myIframe').readyState == 'complete')
    {
        // Do your complete stuff here.
    }
}

6voto

Ed Graham Points 1281

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X