Monday, May 19, 2008

Dynamically Resize an IFrame in Firefox AND IE

So this is a big mystery out there on the net. There are a ton of silly solutions that half work. This one works for me on IE 6 & 7 and Firefox 2.x. I haven't tried it on anything else. Firefox actually accomplishes all this easily; just set the height of the IFrame to 100%. IE, on the other hand, won't behave. The IFrame needs to be inside a table, and sized to 100% to fill the table. Then you have to alter the size of the table. This doesn't work in FireFox though.


/* Dynamic Resizer v1.1 by Peter Vieth
Resizes iframe(s) to be the same size as their content by attaching onload events for each browser
ATTACH THE FOLLOWING EVENT TO YOUR IFRAME (here called reportIFrame) */
if(window.addEventListener) // Mozilla, FF, NS
reportIFrame.addEventListener('load', resizeEvent, false) ;
else // IE
reportIFrame.attachEvent('onreadystatechange', resizeEvent );

/* Bug fix for IE (added v1.1): IFrames created by JavaScript don't actually have a "name" in IE's internals */
if(document.all) {
if(self.frames[reportIFrame.id].name!=reportIFrame.name)
self.frames[reportIFrame.id].name = reportIFrame.name;
}

/* HERE IS THE EVENT DEFINITION */

function resizeEvent(evt) {
var ieKey = "srcElement";
var mozKey = "currentTarget";
var IFrameObj;
evt[mozKey] ? IFrameObj = evt[mozKey] : IFrameObj = evt[ieKey];
fitIframe(IFrameObj);
}

/* THIS FUNCTION FITS THE IFRAME TO DOCUMENT SIZE */

function fitIframe(IFrameObj) {
var IFrameDoc;
if (IFrameObj.contentDocument) {
// For NS6
IFrameDoc = IFrameObj.contentDocument;
IFrameObj.style.height=(parseInt(IFrameDoc.height)+50)+"px";
//alert('detected NS6');
} else if (IFrameObj.contentWindow) {
// For IE5.5 and IE6
IFrameDoc = IFrameObj.contentWindow.document;
if(IFrameDoc.body!=null) { // the IE event fires too often, and fires before IFrame is loaded, in which case doc==null. It fires AGAIN once it loads fully, so ignore the first time
try {
var table = document.getElementById(IFrameObj.parentName);
} catch (e) { alert('IE5.5+: Unable to located IFrames parent table: '+IFrameObj.parentName ); }
try {
var height=parseInt(IFrameDoc.body.clientHeight)+20;
table.style.height=height;
} catch (e) { alert('IE5.5+: Unable to get size of IFrame: '+IFrameObj.name ); }
} // if IFrameDoc!=null

} else if (IFrameObj.document) {
// For IE5
IFrameDoc = IFrameObj.document;
try {
document.getElementById(IFrameObj.parentName).style.height=IFrameDoc.body.scrollHeight-IFrameDoc.body.offsetHeight;
} catch (e) { alert('IE 5.0: Unable to located IFrames parent table or get size of IFrame: '+IFrameObj.parentName ); }

} else {
alert('fitIframe was unable to detect the browser version');
return true;
}
}

11 comments:

Jason said...

Hey Everybody,

I couldnt get this to work when the iframe first loads but when your frame changes to a bigger/smaller page, it works great.

here is what i did to get it to work onload with firefox, and with ie6 ( don't know about 7 ) the onload event is enough ( after the call to launch(); )

here is the parent file with the iframe inside, and the iframe resizes when you navigate:

note will need to correct the html tags ;-)

{html}
{head}
{script}

function launch()
{
if(window.addEventListener)
{
document.getElementById('test').addEventListener('load', resizeEvent, false);
}
else
{
document.getElementById('test').attachEvent('onreadystatechange', resizeEvent );
}

//resizeEvent(this);

}

function resizeEvent(evt) {
var ieKey = "srcElement";
var mozKey = "currentTarget";
var IFrameObj = document.getElementById('test');
evt[mozKey] ? IFrameObj = evt[mozKey] : IFrameObj = evt[ieKey];
fitIframe(IFrameObj);
}

/* THIS FUNCTION FITS THE SIZE */

function fitIframe(IFrameObj) {
var IFrameDoc;
if (IFrameObj.contentDocument) {
// For NS6 - FF
IFrameDoc = IFrameObj.contentDocument;
IFrameObj.style.height=IFrameDoc.height + 25 +"px";

}
}

{/script}
{/head}
{body}
test{p}

{iframe name="test" id="test" frameborder="0" scroll="no" width="1024px"
src ="default.html"
onload="javascript:launch(); document.getElementById('test').style.height = test.document.body.scrollHeight + 10"}


{/iframe}

{/p}

{p}
Some older browsers don't support iframes. If they don't, the iframe will not be visible.
{/p}


{/body}
{/html}

Jason said...

oh, and many thanks Peter!

I was looking for a solution last night and today this is the first one I try! Saved me a headache and a half...

Jason said...

Retested with ie7 and firefox 2.x


Does anyone know how to remove the "active content" warning in IE 6 & 7 ?

Jason said...

Hmm... Actually now i have a bigger problem.

All this works fine if you are using an iframe to display other pages on the SAME host... but in my case, I am putting some of my pages on someone elses page.


With the example above, change the iframe src to http://google.ca -> The auto resizing no longer works. :-(

any help would be appreciated.

thanks,
Jason

Peter V said...

Hi Jason,

I know if you access another host you will have problems because manipulation of the other site's DOM could be a security issue, so it is not allowed by browsers.

Additionally I have since posting updated this code. It still doesn't work perfectly (some minor visual oddities between browsers), but it works better than anything else I found. I will update this post with any changes now...

Anonymous said...

Thanks for yet another solution that half works;-)

I'll just give up and resort to frameset/frame. It hurts, but that's life.

Peter V said...

I know "Anonymous" bashed the code, but so far I evaluated another 3 scripts I found and mine has worked the best among the browsers.

One addition that I will integrate (I'm still doing some other fixes) is that if the user clicks a link within the iframe, it does not resize. This is easily fixed by attaching an onload event to the dynamically created iframe.

Peter V said...

The active content warning is because the dynamically created IFrame is missing a src attribute. If you load a https page using this script, IE loads some internal blank page via http. The solution is to add a blank.html somewhere on your https site.

Ben is also improving this script with "loading" text. Stay tuned...

Anonymous said...

Hey mate, this all works fine in IE, but when the parent page first loads or is refreshed in FF the iframe renders at minimum height. Is that something to do with the way I've built my page or something other people are experiencing?

SG said...

Any update, Peter?

Mohammad said...

Thanx

Labels

Blog Archive

Contributors