Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iFrame postMessage Once Modal Loads

I've got a parent page that loads an iFrame within a modal. I want the iFrame and containing modal to resize dynamically based on the content height.

While I can send the height from the child page to the parent using postMessage when the parent page loads, the height is always wrong because the modal isn't visible yet.

How can I send the height once the modal has actually changed from display:none to display:block?

Here's what I'm doing now:

Parent Page

function receiveMessage(e) {
    // Check to make sure that this message came from the correct domain.
    if (e.origin !== "http://www.example.com")
        return;

    // Update the div element to display the message.
    alert("Message Received: " + e.data);
    var pixels = e.data;
    pixels +=32;
    console.log(pixels);
    $('#modal').css('height', pixels+'px');
    $('#iframe').css('height', pixels+'px');

}

Child Page

  function sendHeight () {
    var containerHeight = $('#main_container').height();
    alert("Height " + containerHeight);
    parent.postMessage(containerHeight, 'http://www.example.com');
  };
like image 266
Tim Avatar asked Mar 25 '26 05:03

Tim


2 Answers

EDIT 2:

This isn't meant to answer the issue of Chrome/Firefox/etc onload differences (chrome onload fires before images are loaded giving the smaller frame height) but if you were already getting around that with your own code you can do this to display the modal with the proper height.

JS

// edited old function
function receiveMessage(event) {
  if (event.origin !== "http://example.com") return;
  $('#modal').css('height', parseInt(event.data, 10) + 10 + 'px');
  $('#iframe').css('height', parseInt(event.data, 10) + 'px');
}
// new code
$('#show').click(function(e) {
  // use if CSS hides modal initially
  $('#modal').css('display', 'block');
  // use if hidden with inline style
  $('#modal').show();
  $('#iframe').attr('src', $('#iframe').data('src'));
});

HTML

<div id="modal" style="display: none;"><!-- for inline styling -->
  <iframe data-src="http://example.com" src="" id="iframe">
  </iframe>
</div>
<button id="show">Open the modal</button>  

GLHF

EDIT:

(I deleted the original part of the answer now that I know your requirements)
Still got the inspiration from here though.

Take #2:

I happen to run the same server under multiple domains and I finally have a use for it (yay).

So the parent page is on a different domain than the child page.

The parent page is only allowed this re-sizing madness if it's own origin matches what the child passes as an argument in postMessage(); - thus eliminating those darn leachers who want to re-size like us big kids.

The child page is only allowed to be re-sized if it comes from a hood near you (specified in receiveMessage() as a conditional) - also known as matching the origin

This is what you already knew but since I'm slow (and surely other Googlers in the future will be as well), I'm spelling it out here for us.

Here's my corrected code:

Parent:

var addEvent = function (element, myEvent, fnc) {
    return ((element.attachEvent) ? element.attachEvent('on' + myEvent, fnc) : element.addEventListener(myEvent, fnc, false));
};
addEvent(window, "message", receiveMessage);
function receiveMessage(event) {
  if (event.origin !== "http://www.myChildPageInsideMe.com") return;
  $('#iframe').css('height', parseInt(event.data, 10) + 10 + 'px');
}

Child / iFrizzame:

<body onload="parent.postMessage(document.body.scrollHeight, 'http://www.theOverBearingMotherPage.com');">

Feel free to use whatever event handling code you like. I like mine :)

And of course...

see it in action here (page on different domain than iFrame)


like image 76
Deryck Avatar answered Mar 26 '26 19:03

Deryck


You may use an interval function to check when the modal is actually visible and then apply all the changes:

var timer;
timer = setInterval( checkelemnt, 300 );
function checkelemnt(){

    //is the modal visible yet?

    if(! $("#modal':visible").length)
    {
        //wait
    }else{
        //resize the modal
        //and clear the interval

        clearInterval( timer );
    }

}

Another neat solution is using the easyXDM , especially if you are trying to make a Cross Domain call to the iframe

like image 32
vorillaz Avatar answered Mar 26 '26 19:03

vorillaz



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!