如何检查 iframe 是不是已加载或是不是有内容?

Posted

技术标签:

【中文标题】如何检查 iframe 是不是已加载或是不是有内容?【英文标题】:How to check if iframe is loaded or it has a content?如何检查 iframe 是否已加载或是否有内容? 【发布时间】:2012-03-04 05:09:36 【问题描述】:

我有一个 id = "myIframe" 的 iframe,这里是我的代码来加载它的内容:

$('#myIframe').attr("src", "my_url");

问题是有时加载时间过长,有时加载速度很快。所以我必须使用“setTimeout”功能:

setTimeout(function()
   if (//something shows iframe is loaded or has content)
   
       //my code
   
   else
   
       $('#myIframe').attr("src",""); //stop loading content
   
,5000);

我只想知道如何确定 iFrame 是否已加载或是否有内容。使用iframe.contents().find() 将不起作用。我不能使用iframe.load(function())

【问题讨论】:

所以如果加载时间超过 5 秒,您不希望 iframe 加载任何内容? 感谢您的帮助 :) 。是的,如果加载时间超过 5 秒,我不想让 iframe 加载任何内容。如下所示,使用“.ready()”不起作用。 在这里查看我的答案***.com/questions/17158932/… 检查这个答案 - forums.tumult.com/t/detect-iframe-loaded/7588 【参考方案1】:

试试这个。

<script>
function checkIframeLoaded() 
    // Get a handle to the iframe element
    var iframe = document.getElementById('i_frame');
    var iframeDoc = iframe.contentDocument || iframe.contentWindow.document;

    // Check if loading is complete
    if (  iframeDoc.readyState  == 'complete' ) 
        //iframe.contentWindow.alert("Hello");
        iframe.contentWindow.onload = function()
            alert("I am loaded");
        ;
        // The loading is complete, call the function we want executed once the iframe is loaded
        afterLoading();
        return;
     

    // If we are here, it is not loaded. Set things up so we check   the status again in 100 milliseconds
    window.setTimeout(checkIframeLoaded, 100);


function afterLoading()
    alert("I am here");

</script>

<body onload="checkIframeLoaded();"> 

【讨论】:

将字符串传递给 setTimeout() 的缺点。传递函数引用更简洁:setTimeout(checkIframeLoaded, 100); 这会导致“不安全的 javascript 尝试从具有 url2 的框架访问具有 URL url1 的框架,域、协议和端口必须匹配。” 这是我想要完成的最佳解决方案。我在 iFrame 中使用 AngularJS,并使用 ng-include,这会延迟包含文件的加载。我试图在 onload 事件时打印 iframe 的内容,但它触发得太快了。检查readyState === "complete" 就行了,因为它在所有内容加载完毕之前都不会改变。 我不得不说这也是唯一对我有用的解决方案。你不能相信 iframe 上的 load 事件,因为它在大多数情况下会在 IE11、Chrome 和 Edge 上立即触发,iframe.contentDocument.location.href 显示为about:blank。即使在 html 中直接指定了 iframesrc,这似乎也是正确的。 如果 iframe 来自另一个域,这将不起作用:VM29320:1 Uncaught DOMException: Blocked a frame with origin "http://localhost:9002" from accessing a cross-origin frame.【参考方案2】:

请使用:

$('#myIframe').on('load', function()
    //your code (will be called once iframe is done loading)
);

随着标准的变化更新了我的答案。

【讨论】:

这种方法根本不起作用,因为事件会立即触发,因为iframes 通常以src="about:blank" 开头,即使src 直接在 HTML 中指定或在@987654325 之前指定@node 被添加到 DOM 中。我通过在 IE11、Chrome 和 Edge 上的紧密循环中轮询 iframecontentDocument.location.href 来测试这一点。如果被框起来的内容确实通过元标记或 javascript 重定向,它也不起作用。【参考方案3】:

我有同样的问题并添加到此,我需要检查 iframe 是否已加载,而与跨域策略无关。我正在开发一个 chrome 扩展,它在网页上注入某些脚本并在 iframe 中显示来自父页面的一些内容。我尝试了以下方法,这对我来说非常有效。P.S.:就我而言,我确实可以控制 iframe 中的内容,但不能控制父网站上的内容。 (iframe 托管在我自己的服务器上) 首先:创建一个带有 data- 属性的 iframe(在我的例子中,这部分是在注入脚本中) &lt;iframe id="myiframe" src="http://anyurl.com" data-isloaded="0"&gt;&lt;/iframe&gt; 现在在 iframe 代码中,使用:

var sourceURL = document.referrer;
window.parent.postMessage('1',sourceURL);

现在根据我的情况回到注入的脚本:

setTimeout(function()
  var myIframe = document.getElementById('myiframe');
  var isLoaded = myIframe.prop('data-isloaded');
  if(isLoaded != '1')
  
    console.log('iframe failed to load');
   else 
    console.log('iframe loaded');
  
,3000);

并且,

window.addEventListener("message", receiveMessage, false);
function receiveMessage(event)

    if(event.origin !== 'https://someWebsite.com') //check origin of message for security reasons
    
        console.log('URL issues');
        return;
    
    else 
        var myMsg = event.data;
        if(myMsg == '1')
            //8-12-18 changed from 'data-isload' to 'data-isloaded
            $("#myiframe").prop('data-isloaded', '1');
        
               

它可能不能完全回答这个问题,但它确实是我通过这种方法解决的这个问题的一个可能案例。

【讨论】:

您的代码中有一些错误,例如 document.getElement->s @JohnK 感谢您指出这一点,我已经解决了。很高兴知道这对您有用。【参考方案4】:

最简单的选择:

<script type="text/javascript">
  function frameload()
   alert("iframe loaded")
  
</script>

<iframe onload="frameload()" src=...>

【讨论】:

不是一个可靠的解决方案,因为即使 URL 已损坏,它也会发出警报。【参考方案5】:

您可以使用 iframe 的 load 事件在 iframe 加载时做出响应。

document.querySelector('iframe').onload = function()
    console.log('iframe loaded');
;

这不会告诉您是否加载了正确的内容:要检查,您可以检查contentDocument

document.querySelector('iframe').onload = function()
    var iframeBody = this.contentDocument.body;
    console.log('iframe loaded, body is: ', body);
;

如果 iframe src 指向与您的代码运行所在不同的域,则检查 contentDocument 将不起作用。

【讨论】:

请考虑编辑您的帖子,以添加更多关于您的代码的作用以及它为何能解决问题的说明。一个大部分只包含代码的答案(即使它正在工作)通常不会帮助 OP 理解他们的问题。【参考方案6】:

在我的情况下,它是一个跨域框架,有时不会加载。 对我有用的解决方案是: 如果它已成功加载,那么如果您尝试此代码:

var iframe = document.getElementsByTagName('iframe')[0];
console.log(iframe.contentDocument);

它不允许您访问 contentDocument 并引发跨域错误 但是如果没有成功加载框架,那么contentDocument 将返回一个#document 对象

【讨论】:

【参考方案7】:

我不确定您是否可以检测到它是否已加载,但您可以在加载完成后触发事件:

$(function()
    $('#myIframe').ready(function()
        //your code (will be called once iframe is done loading)
    );
);

编辑:正如 Jesse Hallett 所指出的,当 iframe 加载时,它总是会触发,即使它已经加载了。所以本质上,如果iframe 已经加载,回调将立即执行。

【讨论】:

这个方法的好处是,即使在 iframe 完全加载后绑定它,jQuery 'ready' 事件也会触发。因此,这是检查 iframe 是否已有内容或在获得内容时通知您的好方法。 这似乎只为 iframe 触发一次。但是,如果您的 iframe 中包含可能导致重新加载 iframe 中的内容的链接,则此事件将不会再次触发。如果这是您的情况,请使用@pratikabu 的答案 - $('#myIframe').load(function() ) @skimberk1 嗨,根据这个answer,您的解决方案将不起作用,因为 jquery 拥有一个变量来记住 DOM 是否已加载,并且仅检查当前帧的当前 DOM 而不是当前帧的 DOM iframe。 是的,您可以在准备就绪后触发事件、显示视频、播放音乐,非常有用...... 根据这张票:dev.jquery.com/ticket/5511 在 iframe 上使用 ready 将始终立即执行该功能,因为它不支持其他文档,然后是运行 jQuery 的框架。【参考方案8】:

当 iFrame 加载时,它最初包含 #document,因此检查加载状态可能最好通过检查现在存在的内容来工作..

if ($('iframe').contents().find('body').children().length > 0) 
    // is loaded
 else 
    // is not loaded

【讨论】:

如果它在不同的域上会失败 这是不正确的,因为 iframe 可能处于加载过程中(未完全加载)。【参考方案9】:

我有一个技巧如下: [尚未测试跨浏览器!]

定义 iframe 的 onload 事件处理程序定义为

$('#myIframe').on('load', function() 
    setTimeout(function() 
        try 
            console.log($('#myIframe')[0].contentWindow.document);
         catch (e) 
            console.log(e);
            if (e.message.indexOf('Blocked a frame with origin') > -1 || e.message.indexOf('from accessing a cross-origin frame.') > -1) 
                alert('Same origin Iframe error found!!!');
                //Do fallback handling if you want here
            
        
    , 1000);

);

免责声明:它仅适用于 SAME ORIGIN IFRAME 文档。

【讨论】:

【参考方案10】:

如果您需要知道 iframe 何时准备好操作,请使用间隔。在这种情况下,我每 250 毫秒“ping”一次内容,如果目标 iframe 中有 any 内容,请停止“ping”并做一些事情。

var checkIframeLoadedInterval = setInterval( checkIframeLoaded, 250 );

function checkIframeLoaded() 
    var iframe_content = $('iframe').contents();

    if (iframe_content.length > 0) 
        clearInterval(checkIframeLoadedInterval);

        //Apply styles to the button
        setTimeout(function () 
            //Do something inside the iframe 
            iframe_content.find("body .whatever").css("background-color", "red");
        , 100); //100 ms of grace time
    

【讨论】:

【参考方案11】:

一个非常棒的方法是使用 jQuery AJAX。父框架如下所示:

<iframe src="iframe_load.php" style="width: 100%; height: 100%;"></iframe>

iframe_load.php 文件将加载 jQuery 库和尝试在 AJAX GET 中加载目标 URL 的 JavaScript:

var the_url_to_load = "http://www.your-website.com" ;
$.ajax(
            type: "GET",
            url: the_url_to_load,
            data: "",
            success: function(data)
                // if can load inside iframe, load the URL
                location.href = the_url_to_load ;
            ,
            statusCode: 
                500: function() 
                    alert( 'site has errors' ) ;
                
            ,
            error:function (xhr, ajaxOptions, thrownError)
                // if x-frame-options, site is down or web server is down
                alert( 'URL did not load due to x-frame-options' ) ;
             );

重要提示 目的地必须包含“Access-Control-Allow-Origin”标头。 PHP 中的示例:

HEADER( "Access-Control-Allow-Origin: *" ) ;

【讨论】:

【参考方案12】:

如果您将页面和 iframe 托管在 同一域 上,则可以侦听 iframe 的 Window.DOMContentLoaded 事件。您必须先等待原始页面触发DOMContentLoaded,然后在iframe 的Window 上附加DOMContentLoaded 事件侦听器。

假设您有如下 iframe,

<iframe id="iframe-id" name="iframe-name" src="..."></iframe>

下一个 sn-p 将允许您挂钩 iframe 的 DOMContentLoaded 事件:

document.addEventListener('DOMContentLoaded', function () 
    var iframeWindow = frames['iframe-name'];
    // var iframeWindow = document.querySelector('#iframe-id').contentWindow
    // var iframeWindow = document.getElementById('iframe-id').contentWindow

    iframeWindow.addEventListener('DOMContentLoaded', function () 
        console.log('iframe DOM is loaded!');
    );
);

【讨论】:

【参考方案13】:

你可以这样做:

const $iframe = document.querySelector(`iframe`);

$iframe.addEventListener("load", function () 
    console.log("loaded");
);

【讨论】:

以上是关于如何检查 iframe 是不是已加载或是不是有内容?的主要内容,如果未能解决你的问题,请参考以下文章

检查 iframe 内容是不是已经加载

如何检查您的网站是不是已在 iframe 中加载并获取父 URL? [复制]

如何检测是不是加载了 iframe?

如何检查浏览器中的url是不是已被iframe更改

检查 iframe 内是不是加载了 Vimeo 视频 - jquery

如何使用 settimeout 函数检查谷歌地图 API 是不是已完全加载?