2

In my site, I use an iframeA in an iframeB, and, when the iframeA changes it's content I have to set the src. I can set it only with the onload event, but this called when the site is loaded. I am looking for some event or trigger, that helps me detect the location/src change before it starts loading. I don't want to wait the whole page load, before the src set. I have no direct access to iframeA (just the script below)

Some code:

var myframe = document.getElementById('frameB').contentWindow.document.getElementById('frameA');
myframe.onload=function (funcname) {...};
Brian Tompsett - 汤莱恩
  • 5,195
  • 62
  • 50
  • 120
Pmillan
  • 523
  • 4
  • 9
  • 22

4 Answers4

4

Check this gist or my answer to this question. The code there does exactly that:

function iframeURLChange(iframe, callback) {
    var unloadHandler = function () {
        // Timeout needed because the URL changes immediately after
        // the `unload` event is dispatched.
        setTimeout(function () {
            callback(iframe.contentWindow.location.href);
        }, 0);
    };

    function attachUnload() {
        // Remove the unloadHandler in case it was already attached.
        // Otherwise, the change will be dispatched twice.
        iframe.contentWindow.removeEventListener("unload", unloadHandler);
        iframe.contentWindow.addEventListener("unload", unloadHandler);
    }

    iframe.addEventListener("load", attachUnload);
    attachUnload();
}

It utilizes the unload event. Whenever a page is unloaded, a new one is expected to start loading. If you listen for that event, though, you will get the current URL, not the new one. By adding a timeout with 0 milliseconds delay, and then checking the URL, you get the new iframe URL.

However, that unload listener is removed each time a new page is loaded, so it must be re-added again on each load.

The function takes care of all that, though. To use it, you only have to do:

iframeURLChange(document.getElementById("myframe"), function (url) {
    console.log("URL changed:", url);
});
dodov
  • 4,065
  • 3
  • 25
  • 44
1

You could also try taking the approach of detecting when your iframe is going to leave its current location. This may be useful in some situations. To do this, put the following code in you iFarme source.

$(window).on('beforeunload', function () {

alert('before load ...');

});

MarzSocks
  • 3,733
  • 2
  • 19
  • 32
  • True, but if run on the IFrame's window, that might run before unloading to the next page. Sometimes `document.activeElement.href` then has information on whatever element triggered it (usually a link). I haven't found a reliable way to catch between those two events. :( – Jasmine Hegman Apr 26 '16 at 20:33
  • That's before unload - true, but what happens immediately after an unload - a **load**. I utilized this event in my [answer](https://stackoverflow.com/a/47676171/3130281) and it works perfectly. – dodov Dec 06 '17 at 14:09
1

What will be changing the source of the iframe? If you have access to that code then you can do whatever is in your onload function then.

If a link has it's target attribute set to the iframe and that is how the source is changing then you can hi-jack the link clicks:

$('a[target="frameB"]').bind('click', function () {
    //run your onload code here, it will run as the iframe is downloading the new content
});

Also, just a side-note, you can bind an event handler for the load event in jQuery like this:

$('#frameB').bind('load', function () {
    //run onload code here
});

UPDATE

SITE -> frameB -> frameA

$("#frameB").contents().find("#frameA").bind('load', function () {
    //load code here
});

This selects the #frameB element (that is in the current top level DOM), gets it's contents, finds the #frameA element, and then binds an event handler for the load event.

Note that this code must be run after #frameB is loaded with the #frameA element already present in it's DOM. Something like this might be a good idea:

$('#frameB').bind('load', function () {
    $(this).contents().find('#frameA').bind('load', function () {
        //run load code here
    });
});

UPDATE

To hi-jack links in the #frameB element:

$('#frameB').contents().find('a[target="frameA"]').bind('click', function () {
    /*run your code here*/
});

This will find any link in the #frameB element that has its target attribute set to frameA and add a click event handler.

And again, this will only work if the #frameB iframe element has loaded (or atleast gotten to the document.ready event) so you can select it's elements.

Jasper
  • 74,169
  • 13
  • 144
  • 142
  • A javascript call will change the iframeA src (called from iframeA). I can only access to the top site's source code. SITE --> IFRAME_B --> IFRAME_A. The second snippet is only works if #frameB is a child of the top page isn't it? I can't hi.jack clicks, because the changing call come from a js. (ifamreA) – Pmillan Jan 18 '12 at 19:22
  • You can select elements in ` – Jasper Jan 18 '12 at 19:33
  • it's really nice, and thanks for your help, but load trigger is also called when iframe load is finished, and I need the moment before load. – Pmillan Jan 18 '12 at 20:01
  • How can I use the click hi-jack code deep? (S->A->B). Maybe I can use it with a couple of IFs. – Pmillan Jan 18 '12 at 20:07
  • 1
    If links within the first iframe are being clicked to change the source of the second (nested) iframe then you can hijack link clicks in the first iframe: `$('#frameB').contents().find('a[target="frameA"]').bind('click', function () {/*run your code here*/})` – Jasper Jan 18 '12 at 20:23
  • Thanks for your help really helpful :) – Pmillan Jan 18 '12 at 22:21
  • "Hijacking" anything at all is a pretty poor solution in my opinion. Using the iframe's `unload` event does the job. Whenever it's unloaded, wait a little bit and check the new URL that's about to be loaded. That's what my [answer](https://stackoverflow.com/a/47676171/3130281) does and it works flawlessly. – dodov Dec 06 '17 at 14:12
0

I think adding inline onload attribute with appropriate event handler to iframe tag will solve your problem.

function onIframeLoad(){
   //Write your code here
}

Markup change

<iframe src='..' onload='onIframeLoad()' />
ShankarSangoli
  • 67,648
  • 11
  • 84
  • 121
  • 2
    That will still fire once the content of the iframe has loaded, right? I think the question is to intercept the changing of the `src` attribute so something can be done without waiting for the content to download. – Jasper Jan 18 '12 at 19:06