/**
* box-sizing Polyfill
*
* A polyfill for box-sizing: border-box for IE6 & IE7.
*
* JScript
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* See <http://www.gnu.org/licenses/lgpl-3.0.txt>
*
* @category JScript
* @package box-sizing-polyfill
* @author Christian Schepp Schaefer <schaepp@gmx.de> <http://twitter.com/derSchepp>
* @copyright 2012 Christian Schepp Schaefer
* @license http://www.gnu.org/copyleft/lesser.html The GNU LESSER GENERAL PUBLIC LICENSE, Version 3.0
* @link http://github.com/Schepp/box-sizing-polyfill
*
* PREFACE:
*
* This box-sizing polyfill is based on previous work done by Erik Arvidsson,
* which he published in 2002 on http://webfx.eae.net/dhtml/boxsizing/boxsizing.html.
*
* USAGE:
*
* Add the behavior/HTC after every `box-sizing: border-box;` that you assign:
*
* box-sizing: border-box;
* *behavior: url(/scripts/boxsizing.htc);`
*
* Prefix the `behavior` property with a star, like seen above, so it will only be seen by
* IE6 & IE7, not by IE8+ who already implement box-sizing.
*
* The URL to the HTC file must be relative to your HTML(!) document, not relative to your CSS.
* That's why I'd advise you to use absolute paths like in the example.
*
*/
<component lightWeight="true">
<attach event="onpropertychange" onevent="checkPropertyChange()"/>
<attach event="ondetach" onevent="restore()"/>
<attach event="onresize" for="window" onevent="update()"/>
<script type="text/javascript">
//<![CDATA[

    var viewportwidth = (typeof window.innerWidth != 'undefined' ? window.innerWidth : element.document.documentElement.clientWidth);

// Shortcut for the document object
    var doc = element.document;

// Buffer for multiple resize events
    var resizetimeout = null;

// Don't apply box-sizing to certain elements
    var apply = false;
    switch (element.nodeName) {
    case '#comment':
    case 'HTML':
    case 'HEAD':
    case 'TITLE':
    case 'SCRIPT':
    case 'STYLE':
    case 'LINK':
    case 'META':
        break;

    default:
        apply = true;
        break;
    }

/*
* update gets called during resize events, then waits until there are no further resize events, and finally triggers a recalculation
*/
function update() {
    if (resizetimeout !== null) {
        window.clearTimeout(resizetimeout);
    }
    resizetimeout = window.setTimeout(function() {
        restore();
        init();
        resizetimeout = null;
    }, 100);
}

/*
* restore gets called when the behavior is being detached (see event binding at the top),
* resets everything like it was before applying the behavior
*/
function restore() {
    if (apply) {
        element.runtimeStyle.removeAttribute("width");
        element.runtimeStyle.removeAttribute("height");
    }
}

/*
* init gets called once at the start and then never again,
* triggers box-sizing calculations and updates width and height
*/
function init() {
    if (apply) {
        updateBorderBoxWidth();
        updateBorderBoxHeight();
    }
}

/*
* checkPropertyChange gets called as soon as an element property changes
* (see event binding at the top), it then checks if any property influencing its
* dimensions was changed and if yes recalculates width and height
*/
function checkPropertyChange() {
    if (apply) {
        var pn = event.propertyName;
        if (pn === "style.boxSizing" && element.style.boxSizing === "") {
            element.style.removeAttribute("boxSizing");
            element.runtimeStyle.removeAttribute("boxSizing");
            element.runtimeStyle.removeAttribute("width");
            element.runtimeStyle.removeAttribute("height");
        }
        switch (pn) {
        case "style.width":
        case "style.borderLeftWidth":
        case "style.borderLeftStyle":
        case "style.borderRightWidth":
        case "style.borderRightStyle":
        case "style.paddingLeft":
        case "style.paddingRight":
            updateBorderBoxWidth();
            break;

        case "style.height":
        case "style.borderTopWidth":
        case "style.borderTopStyle":
        case "style.borderBottomWidth":
        case "style.borderBottomStyle":
        case "style.paddingTop":
        case "style.paddingBottom":
            updateBorderBoxHeight();
            break;

        case "className":
        case "style.boxSizing":
            updateBorderBoxWidth();
            updateBorderBoxHeight();
            break;
        }
    }
}

/*
 * Helper function, taken from Dean Edward's IE7 framework,
 * added by Schepp on 12.06.2010.
 * http://code.google.com/p/ie7-js/
 *
 * Allows us to convert from relative to pixel-values.
 */
function getPixelValue(value) {
    var PIXEL = /^\d+(px)?$/i;
    if (PIXEL.test(value)) return parseInt(value);
    var style = element.style.left;
    var runtimeStyle = element.runtimeStyle.left;
    element.runtimeStyle.left = element.currentStyle.left;
    element.style.left = value || 0;
    value = parseInt(element.style.pixelLeft);
    element.style.left = style;
    element.runtimeStyle.left = runtimeStyle;

    return value;
}

function getPixelWidth(object, value) {
// For Pixel Values
    var PIXEL = /^\d+(px)?$/i;
    if (PIXEL.test(value)) return parseInt(value);

// For Percentage Values
    var PERCENT = /^[\d\.]+%$/i;
    if (PERCENT.test(value)) {
        try {
            parentWidth = getPixelWidth(object.parentElement, (object.parentElement.currentStyle.width != "auto" ? object.parentElement.currentStyle.width : "100%"));
            value = (parseFloat(value) / 100) * parentWidth;
        } catch (e) {
            value = (parseFloat(value) / 100) * element.document.documentElement.clientWidth;
        }
        return parseInt(value);
    }

// For EM Values
    var style = object.style.left;
    var runtimeStyle = object.runtimeStyle.left;
    object.runtimeStyle.left = object.currentStyle.left;
    object.style.left = value || 0;
    value = parseInt(object.style.pixelLeft);
    object.style.left = style;
    object.runtimeStyle.left = runtimeStyle;

    return value;
}

function getPixelHeight(object, value) {
// For Pixel Values
    var PIXEL = /^\d+(px)?$/i;
    if (PIXEL.test(value)) return parseInt(value);

// For Percentage Values
    var PERCENT = /^[\d\.]+%$/i;
    if (PERCENT.test(value)) {
        try {
            if (object.parentElement.currentStyle.height != "auto") {
                switch (object.parentElement.nodeName) {
                default:
                    parentHeight = getPixelHeight(object.parentElement, object.parentElement.currentStyle.height);
                    if (parentHeight !== "auto") {
                        value = (parseFloat(value) / 100) * parentHeight;
                    } else {
                        value = "auto";
                    }
                    break;

                case 'HTML':
                    parentHeight = element.document.documentElement.clientHeight;
                    if (parentHeight !== "auto") {
                        value = (parseFloat(value) / 100) * parentHeight;
                    } else {
                        value = "auto";
                    }
                    break;
                }
                if (value !== "auto") value = parseInt(value);
            } else {
                value = "auto";
            }
        } catch (e) {
            value = "auto";
        }
        return value;
    }

// For EM Values
    var style = object.style.left;
    var runtimeStyle = object.runtimeStyle.left;
    object.runtimeStyle.left = object.currentStyle.left;
    object.style.left = value || 0;
    value = parseInt(object.style.pixelLeft);
    object.style.left = style;
    object.runtimeStyle.left = runtimeStyle;

    return value;
}


/*
 * getBorderWidth & friends
 * Border width getters
 */
function getBorderWidth(sSide) {
    if (element.currentStyle["border" + sSide + "Style"] == "none") {
        return 0;
    }
    var n = getPixelValue(element.currentStyle["border" + sSide + "Width"]);
    return n || 0;
}

function getBorderLeftWidth() { return getBorderWidth("Left"); }

function getBorderRightWidth() { return getBorderWidth("Right"); }

function getBorderTopWidth() { return getBorderWidth("Top"); }

function getBorderBottomWidth() { return getBorderWidth("Bottom"); }


/*
 * getPadding & friends
 * Padding width getters
 */
function getPadding(sSide) {
    var n = getPixelValue(element.currentStyle["padding" + sSide]);
    return n || 0;
}

function getPaddingLeft() { return getPadding("Left"); }

function getPaddingRight() { return getPadding("Right"); }

function getPaddingTop() { return getPadding("Top"); }

function getPaddingBottom() { return getPadding("Bottom"); }


/*
 * getBoxSizing
 * Get the box-sizing value for the current element
 */
function getBoxSizing() {
    var s = element.style;
    var cs = element.currentStyle;
    if (typeof s.boxSizing != "undefined" && s.boxSizing != "") {
        return s.boxSizing;
    }
    if (typeof s["box-sizing"] != "undefined" && s["box-sizing"] != "") {
        return s["box-sizing"];
    }
    if (typeof cs.boxSizing != "undefined" && cs.boxSizing != "") {
        return cs.boxSizing;
    }
    if (typeof cs["box-sizing"] != "undefined" && cs["box-sizing"] != "") {
        return cs["box-sizing"];
    }
    return getDocumentBoxSizing();
}


/*
 * getDocumentBoxSizing
 * Get the default document box sizing (check for quirks mode)
 */
function getDocumentBoxSizing() {
    if (doc.compatMode === null || doc.compatMode === "BackCompat") {
        return "border-box";
    }
    return "content-box";
}


/*
 * setBorderBoxWidth & friends
 * Width and height setters
 */
function setBorderBoxWidth(n) {
    element.runtimeStyle.width = Math.max(0, n - getBorderLeftWidth() -
        getPaddingLeft() - getPaddingRight() - getBorderRightWidth()) + "px";
}

function setBorderBoxHeight(n) {
    element.runtimeStyle.height = Math.max(0, n - getBorderTopWidth() -
        getPaddingTop() - getPaddingBottom() - getBorderBottomWidth()) + "px";
}

function setContentBoxWidth(n) {
    element.runtimeStyle.width = Math.max(0, n + getBorderLeftWidth() +
        getPaddingLeft() + getPaddingRight() + getBorderRightWidth()) + "px";
}

function setContentBoxHeight(n) {
    element.runtimeStyle.height = Math.max(0, n + getBorderTopWidth() +
        getPaddingTop() + getPaddingBottom() + getBorderBottomWidth()) + "px";
}


/*
 * updateBorderBoxWidth & updateBorderBoxHeight
 *
 */
function updateBorderBoxWidth() {
    if (getDocumentBoxSizing() == getBoxSizing()) {
        return;
    }
    var csw = element.currentStyle.width;
    if (csw != "auto") {
        csw = getPixelWidth(element, csw);
        if (getBoxSizing() == "border-box") {
            setBorderBoxWidth(parseInt(csw));
        } else {
            setContentBoxWidth(parseInt(csw));
        }
    }
}

function updateBorderBoxHeight() {
    if (getDocumentBoxSizing() == getBoxSizing()) {
        return;
    }
    var csh = element.currentStyle.height;
    if (csh != "auto") {
        csh = getPixelHeight(element, csh);
        if (csh !== "auto") {
            if (getBoxSizing() == "border-box") {
                setBorderBoxHeight(parseInt(csh));
            } else {
                setContentBoxHeight(parseInt(csh));
            }
        }
    }
}


// Run the calculations
init();

//]]>
</script>
</component>