Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Detect when an iframe is loaded

I'm using an <iframe> (I know, I know, ...) in my app (single-page application with ExtJS 4.2) to do file downloads because they contain lots of data and can take a while to generate the Excel file (we're talking anything from 20 seconds to 20 minutes depending on the parameters).

The current state of things is : when the user clicks the download button, he is "redirected" by Javascript (window.location.href = xxx) to the page doing the export, but since it's done in PHP, and no headers are sent, the browser continuously loads the page, until the file is downloaded. But it's not very user-friendly, because nothing shows him whether it's still loading, done (except the file download), or failed (which causes the page to actually redirect, potentially making him lose the work he was doing).

So I created a small non-modal window docked in the bottom right corner that contains the iframe as well as a small message to reassure the user. What I need is to be able to detect when it's loaded and be able to differenciate 2 cases :

  • No data : OK => Close window
  • Text data : Error message => Display message to user + Close window

But I tried all 4 events (W3Schools doc) and none is ever fired. I could at least understand that if it's not HTML data returned, it may not be able to fire the event, but even if I force an error to return text data, it's not fired.

If anyone know of a solution for this, or an alternative system that may fit here, I'm all ears ! Thanks !

EDIT : Added iframe code. The idea is to get a better way to close it than a setTimeout.

var url = 'http://mywebsite.com/my_export_route';

var ifr = $('<iframe class="dl-frame" src="'+url+'" width="0" height="0" frameborder="0"></iframe>');
ifr.appendTo($('body'));

setTimeout(function() {
    $('.dl-frame').remove();
}, 3000);
like image 681
3rgo Avatar asked May 20 '14 17:05

3rgo


People also ask

How do I check if an iframe is loaded?

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

How do I check if an iframe is empty?

If you want to check if no page loaded inside iframe, and the iframe is not cross-domain you could check for the existence of the body tag inside of the iframe. If it exists, then something loaded. If the iframe is cross-domain, you will be blocked by the same-origin policy.

What is iframe onload?

The onload event is used to run scripts and call JavaScript functions after the contents of a webpage have been loaded. It can be used to get the information about the user's browser so that the compatible version of the web page can be loaded.


2 Answers

I wonder if it would require some significant changes in both frontend and backend code, but have you considered using AJAX? The workflow would be something like this: user sends AJAX request to start file generating and frontend constantly polls it's status from the server, when it's done - show a download link to the user. I believe that workflow would be more straightforward.

Well, you could also try this trick. In parent window create a callback function for the iframe's complete loading myOnLoadCallback, then call it from the iframe with parent.myOnLoadCallback(). But you would still have to use setTimeout to handle server errors/connection timeouts.

And one last thing - how did you tried to catch iframe's events? Maybe it something browser-related. Have you tried setting event callbacks in HTML attributes directly? Like

<iframe onload="done()" onerror="fail()"></iframe>

That's a bad practice, I know, but sometimes job need to be done fast, eh?

UPDATE Well, I'm afraid you have to spend a long and painful day with a JS debugger. load event should work. I still have some suggestions, though:

1) Try to set event listener before setting element's src. Maybe onload event fires so fast that it slips between creating element and setting event's callback

2) At the same time try to check if your server code plays nicely with iframes. I have made a simple test which attempts to download a PDF from Dropbox, try to replace my URL with your backed route's.

<script src="https://code.jquery.com/jquery-1.11.1.min.js"></script>
<iframe id="book"></iframe>
<button id="go">Request downloads!</button>

<script>
    var bookUrl = 'https://www.dropbox.com/s/j4o7tw09lwncqa6/thinkpython.pdf';

    $('#book').on('load', function(){
        console.log('WOOT!', arguments);
    });

    $('#go').on('click', function(){
        $('#book').attr('src', bookUrl);
    });
</script>

UPDATE 2

3) Also, look at the Network tab of your browser's debugger, what happens when you set src to the iframe, it should show request and server's response with headers.

like image 94
Anton Melnikov Avatar answered Sep 21 '22 14:09

Anton Melnikov


I've tried with jQuery and it worked just fine as you can see in this post.

I made a working example here.

It's basically this:

<iframe src="http://www.example.com" id="myFrame"></iframe>

And the code:

function test() {
    alert('iframe loaded');
}

$('#myFrame').load(test);

Tested on IE11.

like image 32
Vitor Canova Avatar answered Sep 22 '22 14:09

Vitor Canova