/**
 * File: DHTMLUtils.js
 *
 * DHTML Utils library  v0.1
 * Supported browsers:
 *          - as always work's only with DOM compiliant browsers.
 *              Old IE4 , Netscape 5 are not supported.
 *              Prefered are IE6, Mozilla, Firefox.
 *              It seem's to work with Opera >8 too.
 *
 * Development Started at: 10.10.2005
 *
 * <script SRC="DHTMLUtils.js"></script>
 *
 */

/**
 * Get the element's rectangualar area.
 *
 * @param element string    - Element for wich to work.
 *
 * @return object rect - {left: , top: , width: , height: , right: , bottom: }
 */
function GetElementRect(element)
{
    var offsetLeft = 0;
    var offsetTop = 0;
    var offsetTrail = null;

    element = GetElement(element);
    offsetTrail = element;

    var dx = 0;
    var dy = 0;

    while (offsetTrail) {
        offsetLeft += offsetTrail.offsetLeft + dx;
        offsetTop += offsetTrail.offsetTop + dy;
        offsetTrail = offsetTrail.offsetParent;
        if ( (offsetTrail)&&(!is_opera)  )
        {
            if ( offsetTrail.nodeName == "HTML" )
            {
                dx = 0;
                dy = 0;
            }
            else
            {
                dx = GetBorderWidths(offsetTrail).left;
                dy = GetBorderWidths(offsetTrail).top;
            }
        }
    }


    return { left   : offsetLeft,
             top    : offsetTop,
             width  : element.offsetWidth,
             height : element.offsetHeight,
             right  : offsetLeft + element.offsetWidth,
             bottom : offsetTop + element.offsetHeight };
}
/**
 * Get CSS style margins attributes for a element and returns them in one object
 *******************************************************************************
 * Note: It is assumed to use only one measurement units in the application, that's
 *           they are ignored and results are integers. It is also assumed to use pixels,
 *           because of the big defferences between all browsers. It seem's none of them
 *           for example, interpret's procents as you would expect. So my consideration is
 *           never to use anything but pixles for DHTML . Anoter consideration is that
 *           DOM get's margins dimensions always in pixels , but IE returns them as they are.
 *           You can convert them but if you use procents and ems things get rather complicated,
 *           and as awlays the presentation in variouse browsers differs.
 *           THE BROWSERS DON'T TELL US EXACTLY HOW WIDE IS SOMETHING .
 *******************************************************************************
 * @param reference|string      - reference or ID of the element
 *
 * @return object|boolean       - object {left: val, top: val, right: val, bottom: val}
 *                                                          values are integers . measurement units are ignored
 */
function GetMargins(element)
{
    var ret = {left: 0, top: 0, right: 0, bottom: 0};
    var styleVal;

    element = GetElement(element);

    ret.left = GetElementStyleAttr(element, "marginLeft", "margin-left");
    ret.top  = GetElementStyleAttr(element, "marginTop", "margin-top");
    ret.right = GetElementStyleAttr(element, "marginRight", "margin-right");
    ret.bottom = GetElementStyleAttr(element, "marginBottom", "margin-bottom");
    for ( var val in ret )
        if ( isNaN(parseInt(ret[val])) )
            ret[val] = 0;
        else
            ret[val] = parseInt(ret[val]);
    return ret;
}
/**
 * Get CSS style paddings attributes for a element and returns them in one object
 * @see function GetMargins
 *
 * @param reference|string      - reference or ID of the element
 * @return object
 *      - object {left: val, top: val, right: val, bottom: val}
 *        values are integers . measurement units are ignored
 */
function GetPaddings(element)
{
    var ret = {left: 0, top: 0, right: 0, bottom: 0};
    var styleVal;

    element = GetElement(element);

    ret.left = GetElementStyleAttr(element, "paddingLeft", "padding-left");
    ret.top  = GetElementStyleAttr(element, "paddingTop", "padding-top");
    ret.right = GetElementStyleAttr(element, "paddingRight", "padding-right");
    ret.bottom = GetElementStyleAttr(element, "paddingBottom", "padding-bottom");
    for ( var val in ret )
        if ( isNaN(parseInt(ret[val])) )
            ret[val] = 0;
        else
            ret[val] = parseInt(ret[val]);
    return ret;
}
/**
 * Get CSS style border-width attributes for element and returns them in one object
 * Works with borders specified by "thin", "medium", "thick" or in pixels.
 *
 * @param reference|string      - reference or ID of the element
 * @return object
 *      - object {left: val, top: val, right: val, bottom: val} <br/>
 *        values are integers . measurement units are ignored. <br/>
 *        Returns false on failure. <br/>
 */
function GetBorderWidths(element)
{

    function ConvertToPixels(borderWidth)
    {
        var ie_patch = ( is_ie ) ? 1 : 0;
        if (borderWidth === "thin")
            return 1 + ie_patch;
        else if (borderWidth === "medium") {
            return 3 + ie_patch;
        }
        else if (borderWidth === "thick") {
            return 5 + ie_patch;
        }
        else if (isNaN(parseInt(borderWidth)))
            return 0;
        else
            return parseInt(borderWidth);
    }

    var ret = {left: 0, top: 0, right: 0, bottom: 0};
    var borderStyle;

    element = GetElement(element);

    borderStyle = GetElementStyleAttr(element, "borderLeftStyle", "border-left-style");
    if ( borderStyle == "none" )
        ret.left = 0;
    else {
        ret.left = GetElementStyleAttr(element, "borderLeftWidth", "border-left-width");
        ret.left = ConvertToPixels(ret.left);
    }
    borderStyle = GetElementStyleAttr(element, "borderTopStyle", "border-top-style");
    if ( borderStyle == "none" )
        ret.top = 0;
    else {
        ret.top = GetElementStyleAttr(element, "borderTopWidth", "border-top-width");
        ret.top = ConvertToPixels(ret.top);
    }
    borderStyle = GetElementStyleAttr(element, "borderRightStyle", "border-right-style");
    if ( borderStyle == "none" )
        ret.right = 0;
    else {
        ret.right = GetElementStyleAttr(element, "borderRightWidth", "border-right-width");
        ret.right = ConvertToPixels(ret.right);
    }
    borderStyle = GetElementStyleAttr(element, "borderBottomStyle", "border-bottom-style");
    if ( borderStyle == "none" )
        ret.bottom = 0;
    else {
        ret.bottom = GetElementStyleAttr(element, "borderBottomWidth", "border-bottom-width");
        ret.bottom = ConvertToPixels(ret.bottom);
    }


    return ret;
}
/**
 * Get's client rect of the element , that is client width and height within borders and paddings
 *
 * @param element string|reference
 *      - reference of the element or its ID
 * @return object
 *      object {left: 0, top: 0, width: value, height: value} left and top are always zero.
 */
function GetElementClientRect(element)
{
    element = GetElement(element);

    var ret = { left: 0, top: 0 , width: 0 , height: 0 };
    rect = GetElementRect(element);
    var paddings = GetPaddings(element);
    //var margins = GetMargins(element);
    var borders = GetBorderWidths(element);

    ret.width = rect.width - paddings.left - paddings.right - borders.left - borders.right;
    ret.height = rect.height - paddings.top - paddings.bottom - borders.top - borders.bottom;
    return ret;
}
/**
 * Sets the dimensions of the element by given rectangular area .
 * ( you can use function GetElementRect to determine the rectangular area for a element )
 * Basically because width or height CSS style properties are the client width and height,
 * setting them directly, will not do the job . We must consider the borders and
 * paddings in order to set exact widths and heights. Also not to forget margins when setting
 * left and top coordinates.
 *
 * @param element reference|string      - reference or ID of the element
 * @param rect object
 *      - new dimensions of the element
 *        { left: val, top: val, width: val, height: val }
 * @return   undefined
 */
function SetElementRect(element, rect)
{
    element = GetElement(element);
    //if ( typeof element != "object" )
    //    return;
    //debug.Dump(element);
    var clientRect = GetElementClientRect(element);
    var oldRect = GetElementRect(element);
    var margins = GetMargins(element);

    element.style.left = rect.left - margins.left + "px";
    element.style.top = rect.top - margins.top + "px";
    if ( rect.width < oldRect.width - clientRect.width )
        element.style.width = "0px";
    else
        element.style.width = rect.width - ( oldRect.width - clientRect.width ) + "px";
    if ( rect.height < oldRect.height - clientRect.height )
        element.style.height = "0px";
    else
        element.style.height = rect.height - ( oldRect.height - clientRect.height ) + "px";
}

function GetWinSize()
{
    var width = 0, height = 0;
    if (typeof( window.innerWidth) == 'number')
    {
        width = window.innerWidth;
        height = window.innerHeight;
    }
    else if ( document.documentElement &&
              ( document.documentElement.clientWidth || document.documentElement.clientHeight ))
    {
        width = document.documentElement.clientWidth;
        height = document.documentElement.clientHeight;
    }
    else if ( document.body && (document.body.clientWidth || document.body.clientHeight))
    {
        width = document.body.clientWidth;
        height = document.body.clientHeight;
    }
    return { width: width, height : height };
}

/**
 * Gets scrolling position in the window
 *
 * @return object       - {scrollLeft : <left coord of the horz. scroll>, scrollTop : <top coord of the vert. scroll> }
 */
function GetScrollPos() {
    var scrollLeft = 0, scrollTop = 0;
    if( typeof( window.pageYOffset ) == 'number' )
    {
        //Netscape compliant
        scrollLeft = window.pageXOffset;
        scrOfY = window.pageYOffset;

    }
    else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) )
    {
        //DOM compliant
        scrollLeft = document.body.scrollLeft;
        scrollTop = document.body.scrollTop;
    }
    else if( document.documentElement &&
             ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) )
    {
        //IE6 standards compliant mode
        scrollLeft = document.documentElement.scrollLeft;
        scrollTop = document.documentElement.scrollTop;
    }
    return { scrollLeft: scrollLeft, scrollTop : scrollTop };
}
function GetPageSize()
{
    var width = 0, height = 0;
    var winSize = GetWinSize();
    /*if (window.innerHeight && window.scrollMaxY)
    {
		width = document.body.scrollWidth;
		height = window.innerHeight + window.scrollMaxY;
	}*/
	if (document.body.scrollHeight > document.body.offsetHeight)
	{ // all but Explorer Mac
		//width = document.body.scrollWidth;
		height = document.body.scrollHeight;
	}
	else
	{ // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		//width = document.body.offsetWidth;
		height = document.body.offsetHeight;
	}

	if (window.innerWidth && window.scrollMaxX)
	{
	    width = window.innerWidth + window.scrollMaxX;
	    /*debug.Dump(width);*/
	}
    else if (document.body.scrollWidth > document.body.offsetWidth)
	{
		width = document.body.scrollWidth;
	}
	else
	{
		width = document.body.offsetWidth;
	}
	if ( width < winSize.width)
	{
	    width = winSize.width;
	}
	if ( height < winSize.height)
	{
	    height = winSize.height;
	}
	return { width : width, height : height };
}