JS Продолжайте загрузку, пока img src не изменится

Я хочу отслеживать событие размонтирования на моем NAS. у него есть отдельная страница для размонтирования всех USB-накопителей. Я включил его через iframe и хочу, чтобы сайт загружался до тех пор, пока источник изображения не будет изменен на определенный источник (зеленая полоса, указывающая, что он выполнил размонтирование). Причина, по которой я хочу, чтобы он загружался, заключается в том, что я вызываю его через функцию jquery.get с другого сайта, и я хочу, чтобы он дождался завершения процесса размонтирования. Было бы здорово, если бы это было возможно только в простом javascript, но при необходимости я также могу включить jquery. Вот что я получил до сих пор:

<script type="text/javascript">
function check(){
if (!(document.getElementById("uiView_TestPic").src == "/css/default/images/finished_ok_green.gif")){
window.setTimeout(check(), 2000);
}else{
alert("Done!");
}}
window.onload(check());
</script></head>
<body>
<iframe seamless width="100%" frameborder="0" height="80%" src="http://fritz.box/usb/usb_diskcut.lua?usbdev=all"></iframe>

Я сразу получаю сообщение об ошибке, что элемент «uiView_TestPic» не существует, даже когда я добавляю тайм-аут перед запуском проверки.

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


person user1685565    schedule 04.08.2014    source источник
comment
#uiView_TestPic внутри iframe?   -  person haxxxton    schedule 04.08.2014
comment
Если uiView_TestPic находится в другом iframe, отличном от того, где работает JS, вам нужно получить документ из iframe и использовать этот document с getElementById(). Ваш текущий код ищет ваш текущий документ, но изображение находится в другом документе.   -  person jfriend00    schedule 04.08.2014
comment
как заставить JS выглядеть в документе iframe?   -  person user1685565    schedule 04.08.2014
comment
@user1685565 user1685565 - я добавил ответ о том, как искать в документе iframe.   -  person jfriend00    schedule 04.08.2014


Ответы (2)


Во-первых, оба фрейма должны работать в одном и том же домене, потому что браузеры предотвратят доступ кода в одном фрейме к чему-либо в другом фрейме, если они находятся в разных доменах. Если два фрейма не находятся в одном домене, то iframe должен будет контролировать себя и уведомлять другой фрейм, когда он закончит работу, используя что-то вроде window.postMessage().

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

Сначала добавьте идентификатор в iframe:

<iframe id="myFrame" seamless width="100%" frameborder="0" height="80%" src="http://fritz.box/usb/usb_diskcut.lua?usbdev=all"></iframe>

Затем вы можете использовать это:

    // put this code in your document AFTER the iFrame tag
    // or only run it after the DOM is loaded in your main document

    function checkImageSrc(obj) {
        if (obj.src.indexOf("/finished_ok_green.gif") !== -1) {
            // found the green gif
            // put whatever code you want here
        } else {
            // check repeatedly until we find the green image
            setTimeout(function() {
                checkImageSrc(obj);
            }, 2000);
        }
    }

    // get the iframe in my documnet
    var iframe = document.getElementById("myFrame");
    // get the window associated with that iframe
    var iWindow = iframe.contentWindow;

    // wait for the window to load before accessing the content
    iWindow.addEventListener("load", function() {
        // get the document from the window
        var doc = iframe.contentDocument || iframe.contentWindow.document;

        // find the target in the iframe content
        var target = doc.getElementById("uiView_TestPic");
        checkImageSrc(target);
    });

К вашему сведению, здесь более подробно описано ожидание готовности iframe: iframe/24603642#24603642">Как я могу получить доступ к элементам DOM в iFrame


Если вы управляете кодом в iframe, то более простым способом реализации этого будет использование window.postMessage() для отправки сообщения в родительское окно, когда код в iframe завершит свою работу. Затем родительское окно может просто прослушать это единственное сообщение и узнать, когда операция будет выполнена.

Это может выглядеть примерно так. Поместите этот код в iframe:

    // put this code in your document AFTER the relevant image tag
    // or only run it after the DOM is loaded in your iframe

    // if you can hook into the actual event that knows the unmount
    // is done, that would be even better than polling for the gif to change

    function checkImageSrc(obj) {
        if (obj.src.indexOf("/finished_ok_green.gif") !== -1) {
            // found the green gif
            // notify the parent
            window.parent.postMessage("unmount complete", "*");
        } else {
            // check repeatedly until we find the green image
            setTimeout(function() {
                checkImageSrc(obj);
            }, 2000);
        }
    }

    // find the target in the iframe content
    var target = document.getElementById("uiView_TestPic");
    checkImageSrc(target);

Затем в главном окне вы должны прослушать опубликованное сообщение следующим образом:

    window.addEventListener("message", function(e) {
        // make sure this is coming from where we expect (fill in the proper origin here)
        if (e.origin !== "http://example.org:8080") return;
        if (e.data === "unmount complete") {
            // unmount is complete - put your code here
        }
    });
person jfriend00    schedule 04.08.2014
comment
ну нет у них одного домена. на веб-сайте работает мой Raspberry Pi (локально), а другой — мой маршрутизатор. Это может быть причиной того, что ваш код у меня не работает, я добавил простое предупреждение после изменения img src, но ничего не происходит. может есть другой способ? может быть, даже без iframe? это был только первый и самый простой способ, который я могу придумать, чтобы вызвать веб-сайт и дождаться изменения img src - person user1685565; 04.08.2014
comment
@ user1685565 - Хм, это важная деталь, которой не было в вашем вопросе. Браузеры предотвращают ЛЮБОЙ доступ из одного фрейма в другой, если они работают на разных доменах. Как я сказал в конце своего ответа, если вы управляете обоими сайтами, тогда просто используйте iframe-сайт, используя window.postMessage() в своем родительском окне при изменении изображения. window.postMesssage() разрешено между кадрами с другим доменом, но это все, что разрешено. - person jfriend00; 05.08.2014
comment
@user1685565 user1685565 - я добавил пример использования window.postMessage() для кадров из разных источников. - person jfriend00; 05.08.2014
comment
к сожалению, это часть ОС маршрутизатора, я никак не мог ее отредактировать. Это значит, что нет никакого способа заставить его работать? - person user1685565; 05.08.2014
comment
@user1685565 user1685565 - Невозможно получить доступ к DOM iframe из-за пределов iframe, если это другой домен. Я не думаю, что вы можете контролировать GIF извне. - person jfriend00; 05.08.2014

Вы можете проверить, есть ли элемент в dom или нет, а затем проверить src. Что-то вроде этого должно работать:

function check(){
if (document.getElementById("uiView_TestPic") && !(document.getElementById("uiView_TestPic").src == "/css/default/images/finished_ok_green.gif")){
window.setTimeout(check(), 2000);
}else{
alert("Done!");
}}
window.onload(check());

В этом Fiddle вы увидите, что ошибка src null не возникает. Однако, если вы удалите document.getElementById("uiView_TestPic") &&, вы получите свою ошибку

person V31    schedule 04.08.2014
comment
Хм, теперь мне сразу приходит оповещение Done, даже когда сайт даже не догрузился. (Я голосую за ваш пост, чтобы вернуть вас к 0: P) - person user1685565; 04.08.2014
comment
Поскольку #uiView_TestPic находится не в том же документе, document.getElementById("uiView_TestPic") никогда его не найдет (он ищет не в том документе). Нужно дождаться загрузки iframe, затем получить документ из iframe, затем получить элемент из этого документа, а затем посмотреть, правильное ли это изображение. - person jfriend00; 04.08.2014