web-dev-qa-db-fra.com

comportement iframe de onload vs addEventListener ('load')

Je me suis amusé à ajouter des éléments iframe cachés à une page et je souhaite manipuler le DOM de ces éléments une fois chargé. J'ai remarqué que je ne pouvais pas commencer à manipuler le DOM immédiatement après l'ajout de l'iframe à une page, celle-ci n'ayant pas encore été chargée. Cela ne peut pas être fait avec l'événement DOMContentLoaded car celui-ci se déclenche sur le document qui n'existe pas dans l'iframe jusqu'à ce qu'il soit ajouté à la page. Nous devons donc utiliser l'événement load.

Voici un code de test:

var iframe = document.createElement('iframe');
iframe.onload = function() { console.log('loaded!'); };
document.getElementsByTagName('body')[0].appendChild(iframe);

Cela fonctionne comme prévu, mais lorsque je le change en addEventListener, il n'est même pas ajouté au DOM:

var iframe = document.createElement('iframe');
iframe.addEventListener('load', function() { console.log('loaded!'); });
document.getElementsByTagName('body')[0].appendChild(iframe);

Je n'ai pas testé attachEvent dans IE.

Quelqu'un a-t-il jeté la lumière là-dessus?

19
roryf

La fonction addEventListener() nécessite 3 arguments! Jetez un coup d’œil à https://developer.mozilla.org/en/DOM/element.addEventListener

Le 3ème argument est marqué comme optionnel, mais ensuite ils écrivent:

Notez que ce paramètre n'est pas facultatif dans toutes les versions du navigateur.

Je ne sais pas quand ni où cela est requis, mais mes tests sur FF4 ont généré une exception lors de l'appel de la variable addEventListener avec 2 arguments:

exception non interceptée: [Exception ... "Pas assez d'arguments" nsresult: "0x80570001 (NS_ERROR_XPC_NOT_ENOUGH_ARGS)" emplacement: "JS frame :: http: //localhost/index.php :: :: line 10" données: non]

Au fait, votre code fonctionne bien dans Chrome [la chaîne loaded! est enregistrée dans la console].

Comme FF, IE9 a besoin du 3ème argument en mode standard (avec <!DOCTYPE html>). IE9 est le premier IE prenant en charge le modèle d'événement du W3C. Donc, dans les versions précédentes, nous devons essayer attachEvent. Je n'ai pas d'IE antérieur, mais cela fonctionnait en mode Normes IE7/8 et même en mode Quirks dans IE9. Voici le code que j'ai utilisé:

<!DOCTYPE html>
<html>
<head><title></title></head>
<body>
<script>
    window.onload=function(){
        var iframe = document.createElement('iframe');
        var func = function() { console.log('loaded!');};
        if(iframe.addEventListener)
            iframe.addEventListener('load', func, true);
        else if(iframe.attachEvent)
            iframe.attachEvent('onload',func);
        document.body.appendChild(iframe);
    }
</script>
</body>
</html>
19

Cela fonctionne pour moi:

html:

iframe source code: <br />
<textarea id="output" rows="20" cols="60">loading ...</textarea>

javascript (sur documentReady):

var iframe = document.createElement('iframe');
iframe.id = iframe.name = "testframe";
iframe.src = "http://fiddle.jshell.net";
iframe.width = 400;
iframe.height = 100;
iframe.style.display = "none";

if (iframe.addEventListener)
    iframe.addEventListener("load", loaded, false);
else
    iframe.attachEvent("onload", loaded);

function loaded() {
    var html;
    if (iframe.contentDocument)
        html = iframe.contentDocument.getElementsByTagName("HTML")[0].innerHTML;
    else
        html = window.frames[iframe.name].document.getElementsByTagName("html")[0].innerHTML;

    document.getElementById("output").value = html;
}

document.getElementsByTagName("body")[0].appendChild(iframe);

Voir la démo à: http://jsfiddle.net/WcKEz/

Fonctionne avec addEventListener, mais inclut le repli sur attachEvent. L'accès au DOM de l'IFRAME bien sûr uniquement sur le même domaine.

1
roberkules

Le premier exemple fonctionne-t-il? Vous ne savez pas exactement ce que vous recherchez, mais cela devrait éclairer le moment où les événements fonctionnent: jQuery document.ready source

$ (document) .ready équivalent sans jQuery

addEventListener ne fonctionne pas dans IE, donc si c'est là que vous testez, le second échouera avant que l'iframe ne soit ajouté.

Vous pouvez également ajouter un rappel depuis la page elle-même, bien que (par exemple, en utilisant jQuery pour ne pas réinventer la roue), je soupçonne que $(iframe).ready() {..} vous donnerait un comportement cohérent.

0
Jamie Treworgy