Javascript обратный вызов, когда IFRAME завершает загрузку? - PullRequest
142 голосов
/ 02 октября 2008

Мне нужно выполнить обратный вызов после завершения загрузки IFRAME. Я не могу контролировать содержимое в IFRAME, поэтому не могу запустить обратный вызов оттуда.

Это IFRAME создано программно, и мне нужно передать его данные в качестве переменной в обратном вызове, а также уничтожить iframe.

Есть идеи?

EDIT:

Вот что у меня сейчас:

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

Этот обратный вызов перед загрузкой iFrame, поэтому обратный вызов не возвращает данных.

Ответы [ 10 ]

49 голосов
/ 16 октября 2008

Прежде всего, перейдя к названию функции xssRequest , похоже, что вы пытаетесь выполнить межсайтовый запрос - что, если это правильно, вы не сможете прочитать содержимое iframe.

С другой стороны, если URL-адрес iframe находится на вашем домене, вы можете получить доступ к телу, но я обнаружил, что если я использую тайм-аут для удаления iframe, обратный вызов работает нормально:

// 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);
});
35 голосов
/ 03 мая 2013

Я использую jQuery, и, как ни странно, это загружается, так как я только что протестировал и загрузил тяжелую страницу, и я не получал предупреждение в течение нескольких секунд, пока не увидел загрузку iframe:

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

Так что, если вы не хотите использовать jQuery, взгляните на их исходный код и посмотрите, не работает ли эта функция по-разному с элементами iframe DOM, я сам посмотрю на нее позже, когда мне будет интересно, и опубликую здесь. Также я тестировал только на последнем хроме.

8 голосов
/ 12 февраля 2010

innerHTML вашего iframe пуст, потому что ваш тег iframe не окружает никакого содержимого в родительском документе. Чтобы получить содержимое со страницы, на которую ссылается атрибут src iframe, вам необходимо получить доступ к свойству contentDocument iframe. Исключение будет выдано, если src из другого домена. Это функция безопасности, которая предотвращает выполнение произвольного JavaScript на чужой странице, что может привести к уязвимости межсайтового скриптинга. Вот пример кода, иллюстрирующего то, о чем я говорю:

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

Чтобы продолжить пример, попробуйте использовать это как содержимое 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>
7 голосов
/ 05 декабря 2008

Мне приходилось делать это в тех случаях, когда такие документы, как word docs и pdfs, передавались в iframe и находили решение, которое работает довольно хорошо. Ключ обрабатывает событие onreadystatechanged в iframe.

Допустим, имя вашего фрейма "myIframe". Сначала где-нибудь в вашем коде запуска (я делаю это в любом месте после iframe) добавить что-то вроде этого, чтобы зарегистрировать обработчик событий:

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

Мне не удалось использовать атрибут onreadystatechage в iframe, я не могу вспомнить почему, но приложение должно было работать в IE 7 и Safari 3, так что это могло быть фактором.

Вот пример того, как получить полное состояние:

function MyIframeReadyStateChanged()
{
    if(document.getElementById('myIframe').readyState == 'complete')
    {
        // Do your complete stuff here.
    }
}
6 голосов
/ 10 декабря 2014

Я хотел спрятать div ожидающего счетчика, когда содержимое i-кадра полностью загружено в IE, я пробовал буквально все решения, упомянутые в Stackoverflow.Com, но ничего не получалось так, как я хотел.

Тогда у меня возникла мысль, что когда содержимое i-кадра полностью загружено, событие загрузки $ (Window) может быть запущено. И это именно то, что случилось. Итак, я написал этот небольшой сценарий и работал как по волшебству:

     $(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";
     }
 });

Надеюсь, это поможет.

2 голосов
/ 10 сентября 2011

У меня была такая же проблема, как и у вас. Что я сделал, так это то, что я использую что-то под названием jQuery. То, что вы затем делаете в коде JavaScript, это:

$(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();

    });

});

Кажется, что вы удаляете свой iFrame перед тем, как взять html из него. Теперь я вижу проблему с этим: p

Надеюсь, это поможет:).

2 голосов
/ 15 октября 2008

У меня есть похожий код в моих проектах, который отлично работает. Адаптируя мой код к вашей функции, решение может быть следующим:

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

Возможно, у вас есть пустой innerHTML, потому что (одна или обе причины): 1. вы должны использовать его против элемента тела 2. вы удалили iframe со своей страницы DOM

1 голос
/ 25 августа 2009

Я думаю, что событие загрузки правильно. Неправильно то, что вы используете для извлечения контента из контента iframe dom.

Вам нужен html страницы, загруженной в iframe, а не html объекта iframe.

Что вам нужно сделать, это получить доступ к документу содержимого с помощью iFrameObj.contentDocument. Это возвращает доменное имя страницы, загруженной в iframe, если она находится в том же домене текущей страницы.

Я получу содержимое перед удалением iframe.

Я тестировал в Firefox и Opera.

Тогда я думаю, что вы можете восстановить свои данные с помощью $(childDom).html() или $(childDom).find('some selector') ...

0 голосов
/ 26 марта 2018

Использование onload attrbute решит вашу проблему.

Вот пример.

function a() {
alert("Your iframe has been loaded");
}
<iframe src="https://stackoverflow.com" onload="a()"></iframe>

Это то, что вы хотите?

Нажмите здесь для получения дополнительной информации.

0 голосов
/ 02 октября 2008

В прошлом у меня была точно такая же проблема, и единственный способ найти ее - это добавить обратный вызов на страницу iframe. Конечно, это работает только тогда, когда у вас есть контроль над содержимым iframe.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...