2008-10-02 11 views
135

Je dois exécuter un rappel lorsqu'un chargement IFRAME est terminé. Je n'ai aucun contrôle sur le contenu de l'IFRAME, donc je ne peux pas déclencher le rappel à partir de là.Rappel Javascript lorsque IFRAME a fini de charger?

Cet IFRAME est créé par programmation, et j'ai besoin de transmettre ses données comme une variable dans le rappel, ainsi que de détruire l'iframe.

Des idées?

EDIT:

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 callsback avant l'iFrame chargé, de sorte que le rappel n'a pas de données retournées.

+1

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

+1

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

+0

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

Répondre

0

J'ai eu exactement le même problème dans le passé et le seul moyen que j'ai trouvé pour le réparer était d'ajouter le rappel dans la page iframe. Bien sûr, cela ne fonctionne que lorsque vous avez le contrôle sur le contenu iframe.

+0

Je ne vois pas ce qui n'allait pas avec cette suggestion et pourquoi il était rejeté. Certaines personnes, eh .... – roryf

+18

Je ne vous ai pas voté, mais j'imagine que vous avez été rejeté parce que vous avez suggéré exactement ce qu'il a dit qu'il ne peut pas faire - il a dit spécifiquement, "Je n'ai aucun contrôle sur le contenu dans l'IFRAME, donc je ne peux pas déclencher le rappel à partir de là. " –

2

J'ai un code similaire dans mes projets qui fonctionne bien. Adapter mon code à votre fonction, une solution pourrait être la suivante:

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

    $(iFrameObj).load(function() 
    { 
     callback(window['myUniqueID'].document.body.innerHTML); 
     document.body.removeChild(iFrameObj); 
    }); 
} 

Peut-être que vous avez un innerHTML vide parce que (une ou deux causes confondues): 1. vous devez l'utiliser contre l'élément de corps 2. vous avez supprimé l'iframe de votre page DOM

47

D'abord, en passant par le nom de la fonction xssRequest il semble que vous essayez une demande inter-site - ce qui si c'est vrai, vous ne serez pas en mesure de lire le contenu de l'iframe.

D'autre part, si l'URL de iframe est sur votre domaine, vous pouvez accéder au corps, mais je l'ai trouvé que si j'utilise un délai d'attente pour supprimer le iframe le rappel fonctionne très 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

vous pouvez remplacer '$ ('body', this.contentWindow.document) .html()' par 'this.contentDocument.body.outerHTML' –

+10

Une idée de comment faire cela sans jQuery? – devios1

+6

+1 pour comprendre XSS, puis répondre à la question. – rook

6

J'ai dû le faire dans les cas où des documents tels que des documents Word et PDF ont été transmis à l'iframe et trouvé une solution qui fonctionne plutôt bien. La clé gère l'événement onreadystatechanged sur l'iframe.

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

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

je n'étais pas en mesure d'utiliser un attribut onreadystatechage sur le iframe, je peux » Je me souviens pourquoi, mais l'application a dû fonctionner dans IE 7 et Safari 3, ce qui peut ê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. 
    } 
} 
+0

voir aussi https://developer.mozilla.org/en-US/docs/Web/API/Document/readyState –

1

Je pense que l'événement de chargement est juste. Ce qui ne va pas, c'est la façon dont vous utilisez pour récupérer le contenu du contenu de l'iframe dom.

Ce dont vous avez besoin est le html de la page chargé dans l'iframe et non le html de l'objet iframe.

Ce que vous avez à faire est d'accéder au document de contenu avec iFrameObj.contentDocument. Renvoie la dom de la page chargée à l'intérieur de l'iframe, si elle se trouve sur le même domaine de la page en cours.

Je récupérerais le contenu avant de supprimer l'iframe.

J'ai testé dans Firefox et l'opéra.

Alors je pense que vous pouvez récupérer vos données avec $(childDom).html() ou $(childDom).find('some selector') ...

8

Le innerHTML de votre iframe est vide parce que votre balise iframe n'entoure aucun contenu dans le document parent. Pour obtenir le contenu de la page référencée par l'attribut src de l'iframe, vous devez accéder à la propriété contentDocument de l'iframe. Une exception sera levée si le src provient d'un domaine différent. Il s'agit d'une fonctionnalité de sécurité qui vous empêche d'exécuter du code JavaScript arbitraire sur la page de quelqu'un d'autre, ce qui créerait une vulnérabilité de script intersite. Voici quelques exemples de code l'illustre 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 d'autres l'exemple, essayez d'utiliser 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

La propriété contentDocument n'est pas supportée par IE 7 et peut-être plus d'IE aussi, la façon de gérer IE est la fenêtre [ 'iframeid']. document ou ce qui est exactement le même window.frames ['iframeid']. document preuve lien ici https://developer.mozilla.org/fr/Migrate_apps_from_Internet_Explorer_to_Mozilla#section_7 – Olga

1

J'ai eu un problème similaire que vous . Ce que j'ai fait, c'est que j'utilise quelque chose appelé jQuery. Ce que vous faites ensuite dans le code javascript est ceci:

$(function(){ //this is regular jQuery code. It waits for the dom to load fully the first time you open the page. 

    $("#myIframeId").load(function(){ 
     callback($("#myIframeId").html()); 
     $("#myIframeId").remove(); 

    }); 

}); 

Il semble que vous vous supprimez iFrame avant de saisir le code html de celui-ci. Maintenant, je vois un problème avec cela: p

Espérons que cela aide :).

+0

Pourquoi les downvotes? – Automatico

32

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

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

Alors Si vous ne voulez pas utiliser jQuery, jetez un coup d'oeil à leur code source et voyez si cette fonction se comporte différemment avec les éléments DOM iframe, je la regarderai plus tard comme je suis intéressé et je posterai ici. Aussi j'ai seulement testé dans le dernier chrome.

+0

J'ai remarqué que vous avez créé l'élément DOM avec javascript pur, puis transmis cette variable à jQuery en tant que sélecteur, peut-être que c'est la raison pour laquelle le code ne fonctionne pas? – Neo

+4

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

5

Je voulais cacher le div spinner en attente lorsque le contenu de la trame i est entièrement chargé sur IE, j'ai essayé littéralement toutes les solutions mentionnées dans Stackoverflow.Com, mais avec rien travaillé comme je le voulais. Puis j'ai eu une idée, que lorsque le contenu de la trame i est entièrement chargé, l'événement de chargement $ (Window) pourrait être déclenché. Et c'est exactement ce qui est arrivé. Donc, j'ai écrit ce petit script, et a travaillé comme par magie:

 $(window).load(function() { 
    //alert("Done window ready "); 
    var lblWait = document.getElementById("lblWait"); 
    if (lblWait != null) { 
     lblWait.style.visibility = "false"; 
     document.getElementById("divWait").style.display = "none"; 
    } 
}); 

Espérons que cela aide.

+0

c'est une solution simple et fonctionne très bien si vous voulez que votre javascript soit exécuté APRÈS que la page entière soit chargée. Cela signifie que d'abord vous voyez la page entièrement chargée, sans effet js, et après peut-être une seconde ou deux (en fonction de la charge) quels que soient les changements créés par le javascript se produira alors. J'ai personnellement essayé de redimensionner mon iframe, et cela fonctionne si vous ne faites pas attention à l'écran pendant les trois premières secondes après avoir cliqué sur une page, mais cela peut (comme dans mon cas) apparaître comme un patchwork au code. – ampersands

+0

merci pour votre commentaire, cette solution fonctionnait très bien dans mon cas, puisque je voulais que l'iframe soit chargé après le chargement de la page. –