admin管理员组

文章数量:1310074

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

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.")
        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.');
  };
Share Improve this question asked Jun 8, 2014 at 18:17 TimTim 3,05916 silver badges30 bronze badges 0
Add a ment  | 

4 Answers 4

Reset to default 6

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.") 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." 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 es 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.") return;
  $('#iframe').css('height', parseInt(event.data, 10) + 10 + 'px');
}

Child / iFrizzame:

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

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)


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

It sounds like you control the content in the parent and child frames. Excellent.

I would remend:

  1. using postMessage() to send a message from the child to the parent once the child is able to process messages
  2. then send a message from the parent to the child once the parent displays the child and the child is visible
  3. the child then sends the message to the parent regarding its content dimensions
  4. the parent then resizes the iframe and the modal per the desired dimensions

The downside is there's likely to be a little flickering. You might be able give the modal a large negative left CSS property or something similar to render out of the user's sight.

Security note: be sure to check the origin and/or source properties of the message event to make sure you have received a message from a trusted / expected source.

This is what I use in my program. Hope it helps you out

Parent Page

function dyniframesize(frameId) {
        var pTar = null;
        if (document.getElementById) {
            pTar = document.getElementById(frameId);
        } else {
            eval('pTar = ' + frameId + ';');
        }
        if (pTar && !window.opera) {
            // begin resizing iframe
            pTar.style.display = "block";
            pTar.height = "10px";   // 
            if (pTar.contentDocument && pTar.contentDocument.body.scrollHeight) {
                pTar.height = pTar.contentDocument.body.scrollHeight;
                pTar.width = pTar.contentDocument.body.scrollWidth;
            } else if (pTar.Document && pTar.Document.body.scrollHeight) {
                // ie5+
                pTar.height = pTar.Document.body.scrollHeight;
                pTar.width = pTar.Document.body.scrollWidth;
            }
        }
    }

<iframe id="frm" name="frm" marginheight="0" marginwidth="0" frameborder="0" scrolling="auto" onload="javascript:dyniframesize('frm');" width="100%" src=""></iframe>

本文标签: javascriptiFrame postMessage Once Modal LoadsStack Overflow