【问题标题】:JS Keep loading till img src changedJS 一直加载直到 img src 改变
【发布时间】:2014-08-05 05:06:11
【问题描述】:

我想监控我的 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 网站会在所有图像加载完成后立即停止加载,而不是在整个过程完成后停止加载。

【问题讨论】:

  • 在 iframe 中是 #uiView_TestPic 吗?
  • 如果 uiView_TestPic 与运行 JS 的 iframe 位于不同的 iframe 中,那么您必须从 iframe 获取文档并将 documentgetElementById() 一起使用。您当前的代码正在搜索您当前的文档,但图片在不同的文档中。
  • 如何让JS在iframe文档中看起来?
  • @user1685565 - 我添加了如何查看 iframe 文档的答案。

标签: javascript jquery image src


【解决方案1】:

首先,两个框架必须在同一个域上运行,因为如果它们是不同的域,浏览器会阻止一个框架中的代码访问另一个框架中的任何内容。如果这两个框架不在同一个域中,则 iframe 将必须监控自己并在使用完 window.postMessage() 之类的内容后通知另一个框架。

如果它们在同一个域中,这会稍微复杂一些。您必须获取 iframe 元素(在您的主文档中)。你必须等待它准备好(因为它必须加载它自己的内容)。然后,您必须在 iframe 中获取文档。然后您可以在 iframe 中找到所需的图像。然后你可以观察它的内容。当然,如果 iframe 与您的主页位于同一个域(由于安全限制),您只能执行上述任何操作。

首先,在 iframe 中添加一个 id:

<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 准备好的详细信息:How can I access the DOM elements within an iFrame


如果您控制 iframe 中的代码,那么实现这一点的更简洁的方法是在 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
        }
    });

【讨论】:

  • 好吧,他们没有相同的域。该网站正在运行我的树莓派(本地),另一个是我的路由器。这可能是您的代码对我不起作用的原因,我在 img src 更改后添加了一个简单的警报,但没有任何反应。也许还有另一种方法?甚至可能没有 iframe?这只是我能想到的第一个也是最简单的方法来调用一个网站并等待 img src 被更改
  • @user1685565 - 嗯,这是您的问题中没有的重要细节。如果浏览器在不同的域上运行,它们会阻止从一个框架到另一个框架的任何访问。正如我在回答末尾所说,如果您控制两个站点,那么当图像更改时,只需让 iframed 网站使用 window.postMessage() 到它的父窗口即可。 window.postMesssage() 允许在具有不同域的帧之间使用,但仅此而已。
  • @user1685565 - 我添加了一个使用window.postMessage() 用于跨源帧的示例。
  • 不幸的是它是路由器操作系统的一部分,我无法编辑它。那就是说没有办法让它发挥作用?
  • @user1685565 - 当 iframe 是不同的域时,无法从 iframe 外部访问 iframe DOM。我认为您无法从外部监控 GIF。
【解决方案2】:

您可以检查该元素是否在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") && 您会收到错误

【讨论】:

  • 嗯,现在我会立即收到完成警报,即使网站甚至没有完成加载。 (我赞成你的帖子让你回到 0 :P)
  • 因为#uiView_TestPic 不在同一个文档中,document.getElementById("uiView_TestPic") 将永远找不到它(它正在查找错误的文档)。必须等待 iframe 加载,然后从 iframe 中获取文档,然后从该文档中获取元素,然后查看它是否是正确的图像。
猜你喜欢
  • 1970-01-01
  • 2011-09-27
  • 2011-08-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多