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 във вградената рамка ли е?   -  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 - Добавих отговор как да гледам в 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 да бъде готов: Как мога да получа достъп до DOM елементите в iFrame


Ако контролирате кода във вградената рамка, тогава много по-чист начин за прилагане на това би бил да използвате window.postMessage() за публикуване на съобщение в родителския прозорец, когато кодът във вградената рамка приключи своята работа. След това родителският прозорец може просто да изслуша това едно съобщение и ще знае кога операцията е извършена.

Това може да изглежда нещо подобно. Поставете този код в 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 - Хм, това е важен детайл, който не беше във въпроса ти. Браузърите предотвратяват ВСЯКАКЪВ достъп от един кадър до друг, ако работят в отделни домейни. Както казах в края на отговора си, ако контролирате и двата сайта, тогава просто накарайте уебсайта с iframed да използва window.postMessage() към своя родителски прозорец, когато изображението се промени. window.postMesssage() е разрешено между рамки с различен домейн, но това е всичко, което е позволено. - person jfriend00; 05.08.2014
comment
@user1685565 - Добавих пример, използвайки window.postMessage() за рамки с кръстосано начало. - person jfriend00; 05.08.2014
comment
за съжаление това е част от операционната система на рутера, няма начин да го редактирам. Това означава, че няма начин да работи? - person user1685565; 05.08.2014
comment
@user1685565 - Няма начин да стигнете до iframe DOM извън 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
Хм, сега веднага получавам предупреждението Готово, дори когато сайтът дори не е завършил зареждането. (Гласувам за публикацията ви, за да ви върна на 0 :P) - person user1685565; 04.08.2014
comment
Тъй като #uiView_TestPic не е в същия документ, document.getElementById("uiView_TestPic") никога няма да го намери (търси в грешен документ). Човек трябва да изчака iframe да се зареди, след това да вземе документа от iframe, след това да вземе елемента от този документ и след това да види дали това е правилното изображение. - person jfriend00; 04.08.2014