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

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

$('#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(){})

297483 次浏览

I'm not sure if you can detect whether it's loaded or not, but you can fire an event once it's done loading:

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

EDIT: As pointed out by Jesse Hallett, this will always fire when the iframe has loaded, even if it already has. So essentially, if the iframe has already loaded, the callback will execute immediately.

Try this.

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

kindly use:

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

Updated my answer as the standards changed.

When an iFrame loads, it initially contains the #document, so checking the load state might best work by checking what's there now..

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

Easiest option:

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


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

You can use the iframe's load event to respond when the iframe loads.

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

This won't tell you whether the correct content loaded: To check that, you can inspect the contentDocument.

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

Checking the contentDocument won't work if the iframe src points to a different domain from where your code is running.

I had the same issue and added to this, i needed to check if iframe is loaded irrespective of cross-domain policy. I was developing a chrome extension which injects certain script on a webpage and displays some content from the parent page in an iframe. I tried following approach and this worked perfect for me.
P.S.: In my case, i do have control over content in iframe but not on the parent site. (Iframe is hosted on my own server)

First:
Create an iframe with a data- attribute in it like (this part was in injected script in my case)
<iframe id="myiframe" src="http://anyurl.com" data-isloaded="0"></iframe>

Now in the iframe code, use :

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



Now back to the injected script as per my case:

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


and,

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



It may not exactly answer the question but it indeed is a possible case of this question which i solved by this method.

in my case it was a cross-origin frame and wasn't loading sometimes. the solution that worked for me is: if it's loaded successfully then if you try this code:

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

it won't allow you to access contentDocument and throw a cross-origin error however if frame is not loaded successfully then contentDocument will return a #document object

A really great method is use jQuery AJAX. The parent frame would look like this:

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

The iframe_load.php file would load the jQuery library and a JavaScript that attempts to load the destination URL in an AJAX GET:

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

IMPORTANT The destination must have contain the "Access-Control-Allow-Origin" header. Example in PHP:

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

If you need to know when the iframe is ready to manipulate, use an interval. In this case I "ping" the content every 250 ms and if there's any content inside target iframe, stop the "ping" and do something.

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

I got a trick working as follows: [have not tested cross-browser!]

Define iframe's onload event handler defined as

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


});

Disclaimer: It works only for SAME ORIGIN IFRAME documents.

If you're hosting the page and the iframe on the same domain you can listen for the iframe's Window.DOMContentLoaded event. You have to wait for the original page to fire DOMContentLoaded first, then attach a DOMContentLoaded event listener on the iframe's Window.

Given you have an iframe as follows,

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

the next snippet will allow you to hook into the iframe's DOMContentLoaded event:

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

This will work only if it's not a cross-origin iframe.

You can do it like this:

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


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