PDA

View Full Version : Problem with resizing a div



BrettM
11-02-2006, 12:49 AM
I have a simple setup with two divs that are position:absolute. The first div is a header that I allow to expand to accomodate long topic titles or narrow browser windows that cause the text to wrap. The second div is the content, which scrolls beneath the header. When the header resizes, the content div must be repositioned so the top is below the header. In IE6 I also have to reset the height of the content div, or the vertical scroll bar extends below the bottom of the window. Here is my script as it currently stands:


<script type="text/javascript">
window.onload = adjustContent;
window.onresize = adjustContent;

var DHTML = (document.getElementById || document.all);

function adjustContent() {
if (!DHTML) return;

var oHeader = new getObj('FPheader');
var oContent = new getObj('FPcontent');

oContent.style.top = oHeader.obj.offsetHeight + "px";
oContent.style.height = document.body.offsetHeight - oHeader.obj.offsetHeight;
}

function getObj(name){
if (document.getElementById){
this.obj = document.getElementById(name);
this.style = document.getElementById(name).style;
}
else if (document.all){
this.obj = document.all[name];
this.style = document.all[name].style;
}
}
</script>

This script works perfectly in Netscape 7-8, Opera 8-9, Firefox 2, and IE6. Which is kind of amazing, because document.body.offsetHeight is 0 to all the browsers except IE6, so the script is attempting to set a negative style.height. Without the '+"px"' addition to the header height, the script will not work in Netscape7-8 or Firefox. Opera and IE6 don't care.

This morning I installed IE7, and things went bad fast. It doesn't like the "px", and it doesn't like the negative height. It's also showing a double vertical scroll bar, suggesting that it wants a width set, but the scroll bar is the right height, unlike IE6.

Is there any possible way I can fix this script so that it will work without browser sniffing? It seems so elegant the way it is, if I can just figure out what to use in place of the body's offsetHeight and what to do about the "px" problem. It is essential that it work in IE6-7, since it's a template for an HTML help project, but I would like it to be fully cross-browser compatible if possible so the project could be exported as a Web site.

Thanks in advance.

Brett

jscheuer1
11-03-2006, 09:49 AM
Instead of document.body.offsetHeight, try adding this function to your page:


function iecompattest(){
return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body;
}

So that it is available to all other functions. The same with this one:


function get_win_h(){
return window.innerHeight? window.innerheight : iecompatest().clientHeight? iecompatest().clientHeight : 0;
}

Now, wherever you use:


get_win_h()

It will return the window (inner) height dimension or 0 if it cannot determine it, ex:


oContent.style.height = get_win_h() - oHeader.obj.offsetHeight +'px';

I'm not entirely clear if this will help but, it certainly will if you are trying to reposition and/or resize on the basis of the window's height.

One thing to also be aware of, pixel units should always be used for style.height and style.top unless you want to use other units (like em's or pt's or %), in which case you should specify them. Except in NN4, which this script would never work in to begin with. You will also probably get more consistent results if you use a Strict or Transitional DOCTYPE.

BrettM
11-03-2006, 08:13 PM
Thanks, John. After much study of tutorials on heights and widths, plus much head banging, I finally came up with this script, which does the trick:


window.onload = adjustContent;
window.onresize = adjustContent;

// Be sure we're working under DOM.

var DHTML = (document.getElementById || document.all);

function adjustContent(){
if (!DHTML) return;

var oHeader = new getObj('FPheader');
var oContent = new getObj('FPcontent');

// Move the top of the content area for all browsers.

oContent.style.top = parseInt(oHeader.obj.offsetHeight,10) + 'px';

// For IE browsers (which don't recognize window.innerWidth/Height), we
// have to adjust the height of the content area or the scroll bar will
// extend below the window. We also need to adjust the width to keep
// the scroll bar in the right place.

if (!window.innerWidth){
var oWinSize = getWinSize();

oContent.style.overflow = 'auto';
oContent.style.height = oWinSize.height - parseInt(oHeader.obj.offsetHeight,10);

oContent.style.width = oWinSize.width; // Quirks mode

if (document.documentElement && document.documentElement.clientWidth){ // Standards mode
oContent.style.width = oWinSize.width - getExcessWidth(oContent);
}
}
}

// Create an object to reference a div element.

function getObj(name){
if (document.getElementById){
this.obj = document.getElementById(name);
this.style = document.getElementById(name).style;
}
else if (document.all){
this.obj = document.all[name];
this.style = document.all[name].style;
}
}

// Determine the height and width of the viewport.

function getWinSize(){
var iWidth = 0, iHeight = 0;

if (document.documentElement && document.documentElement.clientHeight){
iWidth = parseInt(document.documentElement.offsetWidth,10);
iHeight = parseInt(document.documentElement.offsetHeight,10);
}
else if (document.body){
iWidth = parseInt(document.body.offsetWidth,10);
iHeight = parseInt(document.body.offsetHeight,10);
}

return {width:iWidth, height:iHeight};
}

// Total up any border and padding applied to the right and left sides of the content division.
// These must be removed from the window offsetWidth to set the style.width for the content
// division in IE. Note that borders and padding *must* be specified in pixels for this to
// work properly.

function getExcessWidth(oContent){
var iExcess = 0;

if (window.getComputedStyle) {
iExcess = parseInt('0' + window.getComputedStyle(oContent.obj, null).getPropertyValue("padding-left"),10) +
parseInt('0' + window.getComputedStyle(oContent.obj, null).getPropertyValue("padding-right"),10) +
parseInt('0' + window.getComputedStyle(oContent.obj, null).getPropertyValue("border-left"),10) +
parseInt('0' + window.getComputedStyle(oContent.obj, null).getPropertyValue("border-right"),10);
}
else if (oContent.obj.currentStyle) {
iExcess = parseInt('0' + oContent.obj.currentStyle.paddingLeft,10) +
parseInt('0' + oContent.obj.currentStyle.paddingLeft,10) +
parseInt('0' + oContent.obj.currentStyle.borderLeft,10) +
parseInt('0' + oContent.obj.currentStyle.borderRight,10);
}

return (iExcess);
}

(Not quite as simple as the original, eh? But, things never are.)

I solved the 'px' problem by doing a parseInt on the header height before adding the 'px' back on. Now FF and IE7 are both happy.

The double-scrollbar problem in IE7 was handled by putting scroll="no" in the body tag to get rid of the main scrollbar, and then deducting any left/right border or padding from the offsetWidth. Unfortunately, that means I have to specify the padding in pixels instead of ems, since IE7 returns the original em units instead of converting them to pixels like the other browsers.

I also ended up needing another script from AListApart to detect font-size changes, so the content could resize properly in response to those as well as to window resizing.

But, it all works now, in all the browsers I've got. I sure have wasted a lot of time on what is really just a minor effect!

jsbeginner
11-15-2006, 02:30 AM
Hi BrettM,

I was just wondering how does the parseInt() help if the value is negative. I am a beginner JS programmer and having the same problem too(IE6 -> IE7) and I was considering something like

if (ht <0) {
ht = -ht;
}

Is there a more elegant solution ?

jscheuer1
11-15-2006, 04:37 AM
Math.abs(number)

will return the absolute value of the number.

amboy00
01-04-2007, 09:57 PM
I'm having a similar issue getting DIVs automatically adjust their size. Do you have an example page of the project you were working on?