2

I have a cross-domain iframe inside one of my page, its content should use the window.parent.postMessage method to notify it is rendered to the containing page (so it can adjust iframe's height to its content). It works quite well, but only once, if I start clicking in the iframe and browsing different pages, the load event does not get triggered anymore even if all the pages in the iframe contains the same JavaScript code (see below).

here's the container's code let's say container.js:

function onMessage(jqEvent) {
    if (jqEvent.originalEvent.data.iframe) {
        var iframeContentHeight = jqEvent.originalEvent.data.iframe;
        $('iframe').height(iframeContentHeight + 300);
    }
}
$(window).on('message.socialPanel', onMessage);

and here is the code inside the iframe (it is in an external file, let's call it iframe.js):

$(window).on('load', function () {
   var height = $('html').height();
   window.parent.postMessage({'iframe': height}, '*');
});
Josh Crozier
  • 202,159
  • 50
  • 343
  • 273
n00dl3
  • 19,122
  • 6
  • 58
  • 74

3 Answers3

1

Ok, I finally found the solution (an explanation would be welcome though).

I had to put the iframe's javascript in an inline <script> tag and not in an external one.

So my previous code :

<script type="text/javascript" src="/assets/js/build.js" ></script>

has become:

<script type="text/javascript">
            window.onload = function () {
                var height = $('html').height();
                window.parent.postMessage({'iframe': height}, '*');
            }
</script>
n00dl3
  • 19,122
  • 6
  • 58
  • 74
  • Maybe use $(document).ready() instead? http://stackoverflow.com/questions/3698200/window-onload-vs-document-ready – webtrick101 Jan 16 '15 at 08:33
  • 1
    No, if I'm listening to load events it is because the page needs to be loaded... But thank you for taking time to answer... – n00dl3 Jan 16 '15 at 08:34
  • @n00dl3 I have an idea of what is going on. If the iframe finishes loading its `src` before the parent executes `/assets/js/build.js`, the handler won't be attached before the `load` event, and thus won't fire. Moving the script inline must have made it execute earlier. – Wisco crew Mar 02 '20 at 01:01
  • @Wiscocrew That would be relevant if the script was inside the parent window, but it was inside the iframe. – n00dl3 Mar 02 '20 at 09:40
1

another suggestion - onload is being triggered just once, yes, even when you change the src URL. But if you want it to be triggered again - just detach the iframe from DOM and attach it back again (when changing the URL). It did the trick for me.

Roman86
  • 1,601
  • 15
  • 18
1

I ran into exactly the same problem. @n00dl3's solution might not work in all situations - it didn't for me. It's due to a race condition - the load handler needs to be attached before the iframe loads its src. In some cases, moving the JS inline would move it early enough, in my case it didn't.

Here's how I solved it:

  1. Omit src and onload from the iframe tag:
<iframe id="foo"></iframe>
  1. Define (in the parent document) the function I want to run on load:
function resize() {
  // do the resizing here
}
  1. Again in the parent document, attach the load handler:
document.getElementById("foo").setAttribute("onload", "resize()");
  1. Still in the parent document, set the src:
document.getElementById("foo").setAttribute("src", "https://example.com/bar");

Boom, fires every time.

Wisco crew
  • 1,187
  • 1
  • 15
  • 23