Javascript – Width of an element accounting for quirks mode in javascript

csshtmljavascript

I've been scanning through all the popular js libraries, but I can't find one that has a width function for a DOM element that actually accounts for quirks mode in Internet Explorer. The issue is that padding and borders don't get counted in the the width when quirks mode is engaged. As far as I can tell this happens when the doctype is left out or the doctype is set to html 3.2.

Obviously I could just set the doctype to something standards compliant, but this script can be embedded anywhere so I don't have control over the doctype.

To break the problem down into smaller parts:

1) How do you detect quirks mode?
2) What's the best way to extract the border and padding from an element to compensate?

Example with prototype:

<html>
<head>
</head>
<body>

<div id="mydiv" style="width: 250px; pading-left: 1px; border: 2px black solid">hello</div>

<script>
  alert($('mydiv').getWidth())
</script>

</body>
</html>

result:

253 (ff)
250 (ie)

Thanks in advance!

Best Answer

@1

document.compatMode

"CSS1Compat" means "standards mode" and "BackCompat" means "quirks mode".

@2

offsetWidth property of a HTML elements gives its width on screen, in pixels.

<div id="mydiv" style="width: 250px; padding-left: 1px; border: 2px black solid">hello</div>

document.getElementById('mydiv').offsetWidth
//255 (standards) 250 (quirks)

A function that compensates the width for IE quirksmode has to check for the rendering mode then add borders and padding to the width;

function compensateWidth( el, targetWidth ){

    var removeUnit = function( str ){
        if( str.indexOf('px') ){
            return str.replace('px','') * 1;
        }
        else { //because won't work for other units... one may wish to implement 
            return 0;
        }
    }
    if(document.compatMode && document.compatMode=="BackCompat"){
        if(targetWidth && el.offsetWidth < targetWidth){
            el.style.width = targetWidth;
        }
        else if (el.currentStyle){
            var borders = removeUnit(el.currentStyle['borderLeftWidth']) + removeUnit(el.currentStyle['borderRightWidth']);
            var paddings = removeUnit(el.currentStyle['paddingLeft']) + removeUnit(el.currentStyle['paddingRight']);
            el.style.width = el.offsetWidth + borders + paddings +'px';
        }
    }

}

Now there are two ways to use it:

var div = document.getElementById('mydiv')
// will try to calculate target width, but won't be able to work with units other than px
compensateWidth( div );

//if you know what the width should be in standards mode
compensateWidth( div, 254 );