I've googled a bit and there were a few leads, but I couldn't get any of those leads to work:
I have a page that has an iframe with the src pointing to an external page (cross domain). When the child/iframed page loads, it posts a message of its height. I put a console.log of the height in the javascript. If I open that page in a separate window (type the iframe's src URL in a separate tab, in other words), the console logs the expected height.
However, when I open the parent page with the iframe, the console logs either 0 or a very incorrect value of 150. I've looked through the css and html, and I don't have any specifications of 150.. Anyone have a clue what's going on here?
Abstracted code:
Parent HTML:
...
<iframe src="example.childpage.com" scrolling="no" frameBorder="0"></iframe>
...
Parent Javascript:
...
$(document).ready(function(){
window.addEventListener('message', function(m){
var messageData = m.data;
if(messageData.type=='document-loaded' &&
messageData.hasOwnProperty('height'){
resize_iframe(messageData.height); //function defined else where
//and works
};
});
...
IFrame Javascript:
...
$(document).ready(function(){
var body = document.body;
var html = document.documentElement;
var maxHeight = Math.max(body.scrollHeight, body.offsetHeight,
html.clientHeight, html.scrollHeight, html.offsetHeight);
//Logs height correctly when opened in a separate window but not when
//iframed
console.log("POSTING HEIGHT", maxHeight);
window.parent.postMessage({'type':'document-loaded', 'height': maxHeight},
PARENT_HOST_URL); //PARENT_HOST_URL defined elsewhere
});
...
I realize I have a mixture of jquery and vanilla javascript here; I've done both $(document).height() and the Math.max() shown above to get the height, but both ways still have the same issue.
Much thanks!
ok I finally found a good solution:
$('iframe').load(function() {
this.style.height =
this.contentWindow.document.body.offsetHeight + 'px';
});
Because some browsers (older Safari and Opera) report onload completed before CSS renders you need to set a micro Timeout and blank out and reassign the iframe's src.
$('iframe').load(function() {
setTimeout(iResize, 50);
// Safari and Opera need a kick-start.
var iSource = document.getElementById('your-iframe-id').src;
document.getElementById('your-iframe-id').src = '';
document.getElementById('your-iframe-id').src = iSource;
});
function iResize() {
document.getElementById('your-iframe-id').style.height =
document.getElementById('your-iframe-
id').contentWindow.document.body.offsetHeight + 'px';
}
I had a function that looped through not-yet-accessible elements and called $(element).hide() on them -- which sets the style display: none.
Turns out calculating the height of an element is respective of its visibility on the actual page, regardless of it being in an iframe. So the browser couldn't see it, so the height was being miscalculated (still weird it was returning a random 150px value). That explains why it was calculating correctly on a separate page.
Instead of doing hide(), I just set the visibility to hidden and that fixed my issue of getting the incorrect heights.
Related
I am using the follow script to set the height of the YouTube iframe so it keeps a nice 16:9 aspect ratio. The width is always 100% of the container.
The script should only set the height for YouTube videos. This works if the source of all the iframes on the page is the same. The Youtube embeds are correctly set, soundcloud embeds are ignored, however, once I use a Youtube and a Soundcloud source, it sets both. This makes sense as the iframe is not targeted to only set the height of those that include youtu in the source.
How do I make it set only the height of iframes where the source includes youtu ?
<script>
function iframeSizing() {
$('iframe[src*="youtu"]').each(function() {
var containerWidth = $('iframe').width();
iframeWidth = containerWidth;
iframeHeight = 0.5625 * iframeWidth;
$('iframe').css({
'height': iframeHeight + 'px'
});
});
};
$(window).resize(iframeSizing);
$(document).ready(iframeSizing);
</script>
thanks
Your issue is that you are using the $('iframe') selector over and over again, meanwhile your function doesn't actually know which iframe you are referring to.
Your selector inside the .each() function should be $(this) instead of $(iframe).
So, $(this).width() and $(this).css()
Basically, the way the .each() function works is it loops through all elements with $('iframe[src*="youtu"]') and then inside of that function, to refer to the current element that the loop is on you should use the selector $(this)
I have an iframe and I want to re-size the height according to the content which may resize if user makes certain actions.
I don't want a scroll bar so it appears as a normal page
Use a div instead of an iFrame. Try posting some sample code so we can help you more. Generally, you cannot resize an iframe based on its content.
scrollHeight is the major property to retrieve the height of the IFRAME's content like this:
contentWindow.document.body.scrollHeight
After the IFRAME is loaded, you can then change the height by doing the following:
<script type="text/javascript">
function resizeIframe() {
var iFrameID = document.getElementById('idIframe');
if(iFrameID) {
var cont = iFrameID.contentWindow.document.body || frame.contentDocument.body
// here you can make the height
iFrameID.height = cont.scrollHeight + "px";
}
}
</script>
On the IFRAME load event, you can call this function:
But sure..iframe should not be loaded from other website
I'm having a very strange occurrence when using an IFrame and jQuery.Contents.
We have a number of reports that are built in seperate pages, and a display page that uses jQuery Tabs to display a number of these pages at once.
These reports are of varying sizes based on the data and the inputs by the user, since they can vary we needed to dynamically set the height of the IFrame to be the height of the contents. To get the height of the contents I am using this following code :
var iframeHeight = $(this).contents().height();
iframeHeight += 50;
console.log(iframeHeight);
This code works fine on first load, but after the IFrame Postsback/Refreshes the iframeHeight that is logged is always 83px more than the previous height, regardless of the actual contents of the child page.
i.e. First report is 500px high,
Second report should be 300px high
but $(this).contents().height(); returns 583px.
Here is an example jsFiddle to demonstrate the problem. If you open the console and then click the JSFiddle Icon in the top left of the IFrame, you will notice that the logged height will be 83px more than the previous.
Is there anything that could explain this issue?
Am I miss-understanding how the jQuery.Contents function works?
If this will not work this way is there a better way to get the content height? (I've tried the height of the body + the height of the form object but this didn't work in IE).
Tested this in IE10 + Chrome Version 31.0.1650.57 m
Here is an implementation that seems to work (for expanding/shrinking contents..)
assuming that iframe's src is from the same domain and that there are not scripts that resize the iframe's contents once loaded
$(document).ready(function() {
$('#frameID').on('load', function () {
$('#ReportBuild').hide()
$(this).show();
var iframeHeight = $(this.contentDocument.documentElement).outerHeight(true);
$(this).css({ height: iframeHeight + 'px' });
this.contentWindow.onbeforeunload = function () {
$('.tabFrame').hide();
$('#ReportBuild').show();
}
});
});
Demo at http://jsfiddle.net/rq5S5/8/
With help I managed to finally find a solution, suggested examples worked on JSFiddle's but would not work when applied to my issue using ASP.NET controls generated on PostBack.
To handle this, on each of my Child pages I have wrapped the entire content inside a <div></div> and retrieved the height of this element.
Example :
<div id="ReportContent">
<!-- HTML Content -->
</div>
And the jQuery Code :
var iframeHeight = $(this).contents().find('#ReportContent').outerHeight(true);
This now works correctly for my problem in both IE10 and Google Chrome Version 31.0.1650.57 m
I'm having an issue resizing an iframe to fit the content located within the frame'd page. I used a suggestion I found here to resize the frame dynamically.
In my frame'd pages I have
<body onload='parent.resizeIframe(getDocHeight())'>
function getDocHeight() {
var D = document;
alert(D.URL);
return Math.max(
Math.max(D.body.scrollHeight, D.documentElement.scrollHeight),
Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
Math.max(D.body.clientHeight, D.documentElement.clientHeight)
);
}
And in the page containing the iframe I have this
function resizeIframe(newHeight) {
var showsFrame = document.getElementById('frm');
showsFrame.style.height = parseInt(newHeight) +'px';
}
The function is getting called correctly by each frame'd page, but for some reason the 'newHeight' parameter being passed is keeping the largest height value. For example if I have 2 frame'd pages one with a scroll height of 300px and the other with 500px. When I first click my link to load the 300px page it works fine, but if I click the link to the 500px page and then try and come back to the 300px page, the value of 'newHeight' remains at 500. Any ideas? TIA
I found the issue I was having for anyone else that is experiencing the same thing. Because my frame'd pages didn't have much content the scrollHeight was reporting the length of the entire document and not cutting where my content stopped. Instead of trying to calculate scrollHeight, I simply looked for the offsetHeight which was the correct height I was looking for. Firebug is a nice tool to inspect the DOM of each page and see the values of each attribute without having to write debugging messages. I put this line in every frame'd page
<body onload='parent.resizeIframe(getDocHeight())'>
and in a separate js file I have this code to calculate the height.
function getDocHeight() {
var D = document;
return Math.max(
Math.max(D.body.offsetHeight, D.documentElement.offsetHeight),
);
Try it with JQuery
function resizeIframe(newHeight) {
$('#iframeId').attr('height',newHeight);
or
$("#frameId").height(newHeight);
}
I would like to have an iframe take as much vertical space as it needs to display its content and not display a scrollbar. Is it at all possible ?
Are there any workarounds?
This should set the IFRAME height to its content's height:
<script type="text/javascript">
the_height = document.getElementById('the_iframe').contentWindow.document.body.scrollHeight;
document.getElementById('the_iframe').height = the_height;
</script>
You may want to add scrolling="no" to your IFRAME to turn off the scrollbars.
edit: Oops, forgot to declare the_height.
The workaround is not to use <iframe> and preprocess code on server-side.
Also check out this thread: How does the DiggBar dynamically resize its iframe's height based on content not on their domain?.
It addresses the same question.
This CSS snippet should remove the vertical scrollbar:
body {
overflow-x: hidden;
overflow-y: hidden;
}
I'm not sure yet about having it take up as much vertical space as it needs, but I'll see if I can't figure it out.
Adding a DOCTYPE declaration to the IFRAME source document will help to calculate the correct value from the line
document.getElementById('the_iframe').contentWindow.document.body.scrollHeight
see W3C DOCTYPE for examples
I was having problems with both IE and FF as it was rendering the iframe document in 'quirks' mode, until I added the DOCTYPE.
FF/IE/Chrome support: The .scrollHeight doesnt work with Chrome so I have come up with a javascript example using jQuery to set all IFRAME heights on a page based on the iframes content. NOTE: This is for reference pages within the your current domain.
<script type="text/javascript">
$(document).ready(function(){
$('iframe').each(function(){
var context = $(this);
context.load(function(event){ // attach the onload event to the iframe
var body = $(this.contentWindow.document).find('body');
if (body.length > 0 && $(body).find('*').length > 0) { // check if iframe has contents
context.height($(body.get(0)).height() + 20);
} else {
context.hide(); // hide iframes with no contents
}
});
});
});
</script>