Sunday, June 2, 2024
 Popular · Latest · Hot · Upcoming
146
rated 0 times [  149] [ 3]  / answers: 1 / hits: 89208  / 12 Years ago, tue, january 15, 2013, 12:00:00

I have an iframe as you can see on the following link;-



http://one2onecars.com



The iframe is the online booking in the centre of the screen. The problem I have is that although the height of the iframe is okay as the page loads, I need it to somehow auto adjust the height as the page content adjusts. For example, if I do a postcode search in the online booking it creates a dropdown menu and then makes the 'Next Step' button not viewable.



What I need to happen is that when the content of the online booking changes, the iframe auto adjusts to the new height of the iframe (dynamically) as it is not loading any other pages.



I have tried several different scripts using jquery to try resolving this issue, but they all only seem to auto adjust the height of the iframe when the page first loads and not as the contents of the iframe changes.



Is this even possible to do?



The code I have at the moment is with a set height at the moment:-



        <div id=main-online-booking>

<iframe id=main-online-frame class=booking-dimensions src=http://www.marandy.com/one2oneob/login-guest.php scrolling=no frameborder=0></iframe>

</div>

#main-online-booking {
height: 488px;
border-bottom: 6px #939393 solid;
border-left: 6px #939393 solid;
border-right: 6px #939393 solid;
z-index: 4;
background-color: #fff;
}


.booking-dimensions {
width: 620px;
height: 488px;
}


If anybody can help me with this I would be much appreciated!


More From » jquery

 Answers
118

Modern browsers have some new features that make this task easier than it use to be.


PostMessage


The postMessage API provides a simple method for comunicating between an iFrame and its parent.


To send a message to the parent page you call it as follows.


parent.postMessage('Hello parent','http://origin-domain.com');

In the other direction we can send the message to the iFrame with the following code.


var iframe = document.querySelector('iframe');
iframe.contentWindow.postMessage('Hello my child', 'http://remote-domain.com:8080');

To recevie a message create an event listerner for the message event.


function receiveMessage(event)
{
if (event.origin !== "http://remote-domain.com:8080")
return;

console.log(event.data);
}

if ('addEventListener' in window){
window.addEventListener('message', receiveMessage, false);
} else if ('attachEvent' in window){ //IE
window.attachEvent('onmessage', receiveMessage);

These examples uses the origin property to limit where the message is sent to and to check where it came from. It is possible to specify * to allow sending to any domain and you may in some cases you may want to accept messages from any domain. However, if you do this you need to consider the security implications and implement your own checks on the incoming message to ensure it contains what your expecting. In this case the iframe can post its height to '*', as we might have more than one parent domain. However, it's a good idea to check incoming messages are from the iFrame.


function isMessageFromIFrame(event,iframe){
var
origin = event.origin,
src = iframe.src;

if ((''+origin !== 'null') && (origin !== src.substr(0,origin.length))) {
throw new Error(
'Unexpect message received from: ' + origin +
' for ' + iframe.id + '. Message was: ' + event.data
);
}

return true;
}

MutationObserver


The other advance in more modern broswers is MutationObserver which allows you to watch for changes in the DOM; so it is now possible to detect changes that could affect the size of the iFrame without having to constantly poll with setInterval.


function createMutationObserver(){
var
target = document.querySelector('body'),

config = {
attributes : true,
attributeOldValue : false,
characterData : true,
characterDataOldValue : false,
childList : true,
subtree : true
},

observer = new MutationObserver(function(mutations) {
parent.postMessage('[iframeResize]'+document.body.offsetHeight,'*');
});

log('Setup MutationObserver');
observer.observe(target, config);
}

var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

if (MutationObserver){
createMutationObserver();
}

Working out an accurate height


Getting an accurate height for the iFrame is not as simple as it should be, as you have a choice of six different properties that you can check and none of them give a constantly right answer. The best solution I've come up with is this function that works so long as you don't use CSS to overflow the body tag.


function getIFrameHeight(){
function getComputedBodyStyle(prop) {
return parseInt(
document.defaultView.getComputedStyle(document.body, null),
10
);
}

return document.body.offsetHeight +
getComputedBodyStyle('marginTop') +
getComputedBodyStyle('marginBottom');
}

This is the IE9 version, for the much long IE8 version see this answer.


If you do overflow the body and you can't fix your code to stop this, then using either the offsetHeight or scrollHeight properties of document.documentElement are your best options. Both have pros and cons and it is best just to test both and see which works for you.


Other issues


Other things to consider include: having more than one iFrame on the page, CSS :Checkbox and :Hover events causing page resize, avoiding the use of height auto in the iFrames' body and html tags, and lastly the window being resized.


IFrame Resizer Library


I've wrapped all this up in a simple dependancy free library, that also provides some extra functions not discussed here.


https://github.com/davidjbradshaw/iframe-resizer


This works in all modern browsers.


[#80870] Monday, January 14, 2013, 12 Years  [reply] [flag answer]
Only authorized users can answer the question. Please sign in first, or register a free account.
billosvaldor

Total Points: 601
Total Questions: 113
Total Answers: 113

Location: Iceland
Member since Sat, Sep 17, 2022
2 Years ago
;