iframe dynamic height resizing - javascript

Hi I currently have 2 pages (index.html and iframe_contents.html). Both are on the same domain.
I am currently trying to get the iframe to dynamically resize based on the contents size.
I was using this to assist me http://benalman.com/code/projects/jquery-resize/examples/resize/ and it works if the iframe_contents body tag gets larger or smaller on Firefox and IE 7/8/9 but for webkit it only can grow and can never shrink
I've narrowed it down to the body tag in iframe_contents.html not shrinking when content height changes but only in the iframe. When iframe_contents.html is not in a iframe if I shrink / enlarge elements the bodies overall height changes.
Is this a webkit specific issue?

After reading lots of answers here they all had the same issue with not resizing smaller when needed. I think most people are just doing a one-off resizing after the frame loads, so maybe don't care. I need to resize again anytime the window size changes. So for me, if they made the window narrow the iframe would get very tall, then when they make the window larger it should get shorter again. This wasn't happening on some browsers because the scrollHeight, clientHeight, jquery height() and any other height I could find with DOM inspectors (FireBug/Chrome Dev Tools) did not report the body or html height as being shorter after the iframe was made wider. Like the body had min-height 100% set or something.
For me the solution was to make the iframe 0 height, then check the scrollHeight, then set to that value. To avoid the scrollbar on my page jumping around, I set the height of the parent (that contains the iframe) to the iframe height to keep the total page size fixed while doing this.
I wish I had a cleaner sample, but here is the code I have:
$(element).parent().height($(element).height());
$(element).height(0);
$(element).height($(element).contents().height());
$(element).parent().height("");
element is my iframe.
The iframe has width: 100% style set and is inside a div with default styles (block).
Code is jquery, and sets the div height to the iframe height, then sets iframe to 0 height, then sets iframe to the contents height. If I remove the line that sets the iframe to 0 height, the iframe will get larger when needed, but never smaller.

This may not help you much but here is a function we have in what would be your iframe_contents.html page. It will attempt to resize the iframe in which it is loaded in a sort of self-resizing, cross-browserish, pure-JavaScript kind of way:
function makeMeFit() {
if (top.location == document.location) return; // if we're not in an iframe then don't do anything
if (!window.opera && !document.mimeType && document.all && document.getElementById) {
parent.document.getElementById('youriframeid').style.height = (this.document.body.offsetHeight + 30) + "px";
} else if (document.getElementById) {
parent.document.getElementById('youriframeid').style.height = (this.document.body.scrollHeight + 30) + "px"
}
}
You could put calls to it in a resize() event or following an event that changes the height of your page. The feature-testing in that method should separate out WebKit browsers and pick the correct height property.

Related

How can I trigger CSS layout recalculation after Javascript DOM updates?

I often find that if I create or reparent DOM nodes in javascript, the CSS engine doesn't recalculate the sizes of the parent containers. This happens in Firefox and Chrome.
For example, the body might stay the same size while new content overflows the bottom. If I resize the window the body grows, but it doesn't "lock in" to its correct size until the window is sized to be at least as big as the body should be.
Is there a way to trigger a full layout recomputation in Javascript?
I can able to trigger CSS Engine via:
document.body.style.zoom = 1.0000001;
setTimeout(function(){document.body.style.zoom = 1;},50); //allow some time to flush the css buffer.
For every time after resizing the window use the following:
$(window).resize(function() {
if(this.resizeTO) clearTimeout(this.resizeTO);
this.resizeTO = setTimeout(function() {
$(this).trigger('resizeEnd');
}, 500);
});
$(window).bind('resizeEnd', function() {
document.body.style.zoom = 1.0000001;
setTimeout(function(){document.body.style.zoom = 1;},50);
});
You can trigger a repaint from JavaScript by setting a CSS style to an innocuous value, e.g.
document.body.style.zIndex = 1;
Yes. I tend to put a random className on the <html> element, using:
document.documentElement.className = 'reflow_' + (new Date()).getTime();
which creates:
<html class="reflow_1483757400611">
Tried and tested on everything from Android Browser 4 to Smart TV's via camposat.tv
The browser does recompute the geometry of all elements after DOM manipulation. One likely reason you might see an element "stuck" at a certain height even after its content has changed is this CSS rule:
body { height: 100% };
It tells the browser, make the body element as large in height as the viewport regardless of its content.
Try changing it to:
body { min-height: 100% };
This will tell the browser to make body at least as large in height as the viewport or larger if there is more content.

Using Javascript to resize a div to screen height causes flickering when shrinking the browser window

The Background:
I tried to solve the StackOverflow question yet another HTML/CSS layout challenge - full height sidebar with sticky footer on my own using jQuery. Because the sidebar in my case may be longer than the main content it matches the case of comment 8128008. That makes it impossible to have a sidebar longer than the main content and having a sticky footer without getting problems when shrinking the browser window.
The status quo:
I have a html page with a div, which is automatically stretched to fill the screen. So if there is empty space below the element, I stretch it downwards:
But if the browser viewport is smaller than the div itself, no stretching is done but the scrollbar shows up:
I've attached jQuery to the window's resize event to resize the div, if the browser window is not to small and remove any resizing in the other case. This is done by checking if the viewport is higher or smaller than the document. If the viewport is smaller than the document, it seems like the content is larger than the browser window, why no resizing is done; in the other case we resize the div to fill the page.
if ($(document).height() > $(window).height()) {
// Scrolling needed, page content extends browser window
// --> No need to resize the div
// --> Custom height is removed
// [...]
} else {
// Window is larger than the page content
// --> Div is resized using jQuery:
$('#div').height($(window).height());
}
The Problem:
Up to now, everything runs well. But if I shrink the browser window, there are cases, where the div should be resized but the document is larger than the window's height, why my script assumes, that no resizing is needed and the div's resizing is removed.
The point is actually, that if I check the document's height using Firebug after the bug appeared, the height has just the value is was meant to have. So I thought, the document's height is set with a little delay. I tried to run the resize code delayed a bit but it did not help.
I have set up a demonstration on jsFiddle. Just shrink the browser window slowly and you'll see the div "flickering". Also you can watch the console.log() output and you will notice, that in the case of "flickering" the document's height and the window's height are different instead of being equal.
I've noticed this behavior in Firefox 7, IE 9, Chrome 10 and Safari 5.1. Can you confirm it?
Do you know if there is a fix? Or is the approach totally wrong? Please help me.
Ok -- wiping my old answer and replacing...
Here's your problem:
You are taking and comparing window and document height, without first taking into consideration the order of events here..
Window loads
Div grows to window height
Window shrinks
Document height remains at div height
Window height is less than div height
At this point, the previously set height of the div is keeping document height greater than the window height, and this logic is misinterpreted:
"Scrolling needed, no need to extend the sidebar" fires, erroneously
Hence the twitch.
To prevent it, just resize your div along with the window before making the comparison:
(function () {
var resizeContentWrapper = function () {
console.group('resizing');
var target = {
content: $('#resizeme')
};
//resize target content to window size, assuming that last time around it was set to document height, and might be pushing document height beyond window after resize
//TODO: for performance, insert flags to only do this if the window is shrinking, and the div has already been resized
target.content.css('height', $(window).height());
var height = {
document: $(document).height(),
window: $(window).height()
};
console.log('height: ', height);
if (height.document > height.window) {
// Scrolling needed, no need to externd the sidebar
target.content.css('height', '');
console.info('custom height removed');
} else {
// Set the new content height
height['content'] = height.window;
target.content.css('height', height['content']);
console.log('new height: ', height);
}
console.groupEnd();
}
resizeContentWrapper();
$(window).bind('resize orientationchange', resizeContentWrapper);
})(jQuery);
Per pmvdb's comment, i renamed your $$ to "target"
$(window).bind('resize',function(){
$("#resizeme").css("height","");
if($("#resizeme").outerHeight() < $(window).height()){
$("#resizeme").height($(window).height());
$("body").css("overflow-y","hidden");
}else{
$("body").css("overflow-y","scroll");
}
});
Maybe I am misunderstanding the problem, but why are you using Javascript? This seems like a layout (CSS) issue. My solution without JS: http://jsfiddle.net/2yKgQ/27/

How can I get the full height of a web page that uses a master page?

I'm writing a script that creates a popup that dims the screen behind the popup. I'm using JQuery's $("#dim").css("height", $(document).height()); to resize the div element in question, but it doesn't cover the master page area. Is there a way I can get the height of the WHOLE page and not just the child page?
EDIT: The problem may actually lie in the positioning, and not the size, of my div. I have it set to top:0, but maybe I need to move it using javascript?
Give this a shot:
var width = screen.availWidth;
var height = screen.availHeight;
Since .outerHeight() isn't supported for window or document, you'll have to add the padding to the height() yourself.
$("#dim").css( "height", $(document).height() + 2*parseInt($(document).css("padding"),10) );

How do I easily find the distance between a point on the page and the bottom of the browser window using JavaScript?

A view in my web app has a table which may be extremely long, so I wrapped it in a div with overflow: auto; max-height: 400px; so users can scroll through it while keeping the other controls on the page visible.
I want to use a bit of JavaScript to dynamically adjust the max-height CSS property so the div stretches to the bottom of the browser window. How can I determine this value? jQuery solutions are fine.
The table doesn't start at the top of the page, so I can't just set the height to 100%.
Something like this would work I think:
var topOfDiv = $('#divID').offset().top;
var bottomOfVisibleWindow = $(window).height();
$('#divID').css('max-height', bottomOfVisibleWindow - topOfDiv - 100);
I had a very similar problem, except in my case I had a dynamic pop-up element (a jQuery UI Multiselect widget), to which I wanted to apply a max-height so that it never went below the bottom of the page. Using offset().top on the target element wasn't enough, because that returns the x coordinate relative to the document, and not the vertical scroll-position of the page.
So if the user scrolls down the page, the offset().top won't provide an accurate description of where they are relative to the bottom of the window - you'll need to determine the scroll position of the page.
var scrollPosition = $('body').scrollTop();
var elementOffset = $('#element').offset().top;
var elementDistance = (elementOffset - scrollPosition);
var windowHeight = $(window).height();
$('#element').css({'max-height': windowHeight - elementDistance});
window.innerHeight gives you the visible height of the entire window. I did something almost identical recently so I'm pretty sure that's what you need. :) Let me know, though.
EDIT: You'll still need the Y-value of the overflowed div which you can get by document.getElementById("some_div_id").offsetHeight, seeing that .style.top won't give you a result unless it has been specifically set to a point via CSS. .offsetHeight should give you the correct 'top' value.
Then it's just a matter of setting the size of the table to the window height, minus the 'top' value of the div, minus whatever arbitrary wiggle room you want for other content.
something like max-height: 100%, but not to forget the html and body height 100%.

How can I reduce the size of an iframe without having the content cut?

I have a page that loads another page(url) onto it. The problem is that the iframe page does not fit well in the outer page. How can I reduce the size of the iframe page having the content of the iframe page intact? I do not wish to have scroll bars.
Unfortunately you can't really scale an iframe so that its contents change their size. To the browser, the iframe is a window onto another rendering context which has its own layout according to its own CSS. You are at the mercy of how the content inside the iframe is laid out.
If the iframe URL is from a different site and you can't modify it, then you can't really do anything.
If you can modify the page that's displayed within the iframe, well I'd assume you wouldn't be asking.
See the answer here ( How can I scale the content of an iframe? ). I'm using it and it works on FF, Chrome a little flakey.
You could try expanding the width/height of the iframe and checking the clientWidth vs iframe width. If they're equal, there's no scrollbar, otherwise there is.
Use a midpoint approach for efficiency. In sudo-code:
dx = iframe.width;
while (dx > 1) {
previous = iframe.width
if( iframe.width - iframe.clientWidth > 0 ) {
iframe.width += dx*2;
} else {
iframe.width -= dx/2;
}
dx = Math.abs(previous-iframe.width)
}

Categories