Подтвердить что ты не робот

Iframe поведение onload vs addEventListener ('load')

Я играл с добавлением скрытых элементов iframe на страницу, и я хочу манипулировать DOM этих загруженных. Я заметил, что я не могу начать манипулировать DOM сразу после добавления iframe на страницу, так как он еще не загружен. Это невозможно сделать с событием DOMContentLoaded, поскольку оно срабатывает против документа, который не существует в iframe, пока он не будет добавлен на страницу, поэтому мы должны использовать событие load.

Вот несколько тестовых кодов:

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

Это работает так, как ожидалось, однако, когда я меняю его на addEventListener, он даже не добавляется в DOM:

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

Я не тестировал attachEvent в IE.

Кто-нибудь проливает свет на это?

4b9b3361

Ответ 1

addEventListener() функция требует 3 аргумента! Взгляните на https://developer.mozilla.org/en/DOM/element.addEventListener

Третий аргумент помечен как необязательный, но затем они пишут:

Обратите внимание, что этот параметр не необязательно во всех версиях браузера.

Я не уверен, когда и где это необходимо, но мои тесты на FF4 вызывают исключение при вызове addEventListener с двумя аргументами:

исключение uncaught: [Exception... "Not достаточно аргументов" nsresult: "0x80570001 (NS_ERROR_XPC_NOT_ENOUGH_ARGS)" местоположение: "JS frame:: http://localhost/index.php::  :: строка 10 ": нет]

Кстати, ваш код хорошо работает в Chrome [строка loaded! зарегистрирована в консоли].

Подобно FF, IE9 нуждается в третьем аргументе в стандартном режиме (с <!DOCTYPE html>). IE9 - это первый IE, который поддерживает модель событий W3C. Поэтому в более ранних версиях нам нужно попробовать attachEvent. У меня нет более ранних IE, но он работал в стандартном режиме IE7/8 и даже в режиме Quirks в IE9. Вот код, который я использовал:

<!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>

Ответ 2

Это работает для меня:

HTML:

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

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

См. демонстрацию по адресу: http://jsfiddle.net/WcKEz/

Работает с addEventListener, но включает резервную копию attachEvent. Доступ к DOM IFRAME, конечно, только в том же домене.

Ответ 3

Работает ли первый пример? Не уверен, что именно вы ищете, но это должно освещаться при работе событий: источник jQuery document.ready

$(document).ready эквивалент без jQuery

addEventListener не работает в IE, поэтому, если вы тестируете, то второй будет терпеть неудачу до добавления iframe.

Вы также можете добавить обратный вызов из самой страницы (например, используя jQuery, чтобы вы не изобретали колесо). Я подозреваю, что $(iframe).ready() {..} даст вам последовательное поведение.