// String Extensions ----------------------------------------------------------

String.prototype.startsWith = function(pattern)
{
	return this.indexOf(pattern) === 0;
}

String.prototype.endsWith = function(pattern)
{
	var d = this.length - pattern.length;
	return d >= 0 && this.lastIndexOf(pattern) === d;
}

// Cookies --------------------------------------------------------------------

function SetCookie(cookieName, cookieValue) 
{
	var today = new Date();
	var expire = new Date();
	expire.setTime(today.getTime() + 3600000*24*3000);
	document.cookie = cookieName+"="+escape(cookieValue) + ";expires="+expire.toGMTString();
}

function GetCookie(cookieName, defaultValue)
{
    var dc = document.cookie;
    var prefix = cookieName + "=";
    var begin = dc.indexOf("; " + prefix);
    if (begin == -1) {
        begin = dc.indexOf(prefix);
        if (begin != 0) return defaultValue;
    } else {
        begin += 2;
    }
    var end = document.cookie.indexOf(";", begin);
    if (end == -1) {
        end = dc.length;
    }
    return unescape(dc.substring(begin + prefix.length, end));
}

// http://www.quirksmode.org/viewport/elementdimensions.html
function WindowClientHeight()
{
    var clientHeight = 0;
    if (self.innerHeight) // all except Explorer
        clientHeight = self.innerHeight;
    else if (document.documentElement && document.documentElement.clientHeight) // Explorer 6 Strict Mode
	    clientHeight = document.documentElement.clientHeight;
    else if (document.body) // other Explorers
	     clientHeight = document.body.clientHeight;
    return clientHeight;	     
}

// http://www.quirksmode.org/js/findpos.html
function GetObjectX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function GetObjectY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

function HoverImage(imgId) 
{
	var e = document.getElementById(imgId);
	
    if(e.src.indexOf('Hover.') == -1)
    {
        var i = e.src.lastIndexOf('.');
        e.src = e.src.substr(0, i) + 'Hover' + e.src.substr(i, e.src.length - i);
    }
    else
    {
        e.src = e.src.replace('Hover.', '.');
    }
}

// http://www.robertnyman.com
function GetElementsByClassName(oElm, strTagName, strClassName)
{
    var arrElements = (strTagName == "*" && oElm.all) ? oElm.all : oElm.getElementsByTagName(strTagName);
    var arrReturnElements = new Array();
    strClassName = strClassName.replace(/\-/g, "\\-");
    var oRegExp = new RegExp("(^|\\s)" + strClassName + "(\\s|$)");
    var oElement;
    for(var i=0; i<arrElements.length; i++)
    {
        oElement = arrElements[i];      
        if(oRegExp.test(oElement.className))
        {
            arrReturnElements.push(oElement);
        }   
    }
    return (arrReturnElements)
}

// http://www.robertnyman.com
function GetElementsByAttribute(oElm, strTagName, strAttributeName, strAttributeValue)
{
    var arrElements = (strTagName == "*" && oElm.all) ? oElm.all : oElm.getElementsByTagName(strTagName);
    var arrReturnElements = new Array();
    var oAttributeValue = (typeof strAttributeValue != "undefined") ? new RegExp("(^|\\s)" + strAttributeValue + "(\\s|$)") : null;
    var oCurrent;
    var oAttribute;
    for(var i=0; i<arrElements.length; i++)
    {
        oCurrent = arrElements[i];
        oAttribute = oCurrent.getAttribute(strAttributeName);
        if(typeof oAttribute == "string" && oAttribute.length > 0)
        {
            if(typeof strAttributeValue == "undefined" || (oAttributeValue && oAttributeValue.test(oAttribute)))
            {
                arrReturnElements.push(oCurrent);
            }
        }
    }
    return arrReturnElements;
}

function Trace1(msg)
{
    // var traceTag = document.getElementById("trace");
    // traceTag.innerHTML = traceTag.innerHTML + "<p>" + strMessage + "</p>";
    if( typeof( jsTrace ) != 'undefined' )
        jsTrace.send( msg );
}

function CurrentTime()
{
    var d = new Date();
    return d.toLocaleDateString() + ": " + d.getMilliseconds();
}

var g_InAutoPositionContentFooter = false;
var g_EnableAutoHeight = false;
var g_ForceAutoHeight = false;
var g_viewportWidth = 0;
var g_viewportHeight = 0;

function AutoPositionDisable()
{
    g_InAutoPositionContentFooter = true;
}

function AutoPositionAutoHeightEnable()
{
    // This can run real slow on IE when there are lot of controls...
    g_EnableAutoHeight = true;
}

function AutoPositionAutoHeightForce()
{
    // Skipping auto height calculations doesn't work for content that automatically adjusts its height
    g_ForceAutoHeight = true;
}

function AutoPositionResetData()
{
    // Trace1("Enter: AutoPositionResetData");
    
    g_InAutoPositionContentFooter = true;
    
    g_viewportWidth = g_viewportHeight = 0;
    
    var menuTag = document.getElementById("menu");
    if (menuTag)
		menuTag.style.height = "auto";

    var contentBodyTag = document.getElementById('contentBody');
    contentBodyTag.style.height = "auto";
    
    var autoHeightTags = null;
    if(g_EnableAutoHeight)
    {
        autoHeightTags = GetElementsByAttribute(contentBodyTag, "*", "AutoHeight", "True");
        for(var i = 0; i < autoHeightTags.length; i++)
            if(autoHeightTags[i].originalOffsetHeight)
                autoHeightTags[i].style.height = autoHeightTags[i].originalOffsetHeight + "px";
    }       
    
    g_InAutoPositionContentFooter = false;
    
    // Trace1("Exit: AutoPositionResetData");
}

function AutoPositionOnResize()
{
    g_InAutoPositionContentFooter = true;

    var viewportWidth  = YAHOO.util.Dom.getViewportWidth();
    var viewportHeight = YAHOO.util.Dom.getViewportHeight();
    if(g_viewportWidth != viewportWidth || g_viewportHeight != viewportHeight)
    {
        var menuTag = document.getElementById("menu");
        if (menuTag)
			menuTag.style.height = "auto";

        var contentBodyTag = document.getElementById('contentBody');
        contentBodyTag.style.height = "auto";
        
        var autoHeightTags = null;
        if(g_EnableAutoHeight)
        {
            autoHeightTags = GetElementsByAttribute(contentBodyTag, "*", "AutoHeight", "True");
            for(var i = 0; i < autoHeightTags.length; i++)
                if(autoHeightTags[i].originalOffsetHeight)
                    autoHeightTags[i].style.height = autoHeightTags[i].originalOffsetHeight + "px";
        }
    }
    
    g_InAutoPositionContentFooter = false;
    
    AutoPositionContentFooter();
}    

function AutoPositionContentFooter()
{
    // Trace1("Enter: AutoPositionContentFooter");
    
    if(g_InAutoPositionContentFooter)
    {
        // Trace1("Skipping extra AutoPositionContentFooter call");
        return;
    }
    g_InAutoPositionContentFooter = true;
    
    var viewportWidth  = YAHOO.util.Dom.getViewportWidth();
    var viewportHeight = YAHOO.util.Dom.getViewportHeight();
    if(g_viewportWidth == viewportWidth && g_viewportHeight == viewportHeight)
    {
        // Trace1("Skipping AutoPositionContentFooter call for identical viewport size");
        g_InAutoPositionContentFooter = false;
        return;
    }
    g_viewportWidth  = viewportWidth;
    g_viewportHeight = viewportHeight;
    
    var menuTag = document.getElementById("menu");
    var headerTag = document.getElementById("header");
    var contentTag = document.getElementById('content');
    var contentHeaderTag = document.getElementById('contentHeader');
    var contentBodyTag = document.getElementById('contentBody');
    var contentFooterTag = document.getElementById('contentFooter');
    var footerTag = document.getElementById('footer');
    
    // Quick test
    if(!g_ForceAutoHeight && (headerTag.offsetHeight + contentHeaderTag.offsetHeight + contentBodyTag.offsetHeight + contentFooterTag.offsetHeight + footerTag.offsetHeight >= viewportHeight))
    {
        // Trace1("Skipping AutoPositionContentFooter call for large document");
        
        if (menuTag)
        {
		    var maxHeight = viewportHeight - headerTag.offsetHeight - footerTag.offsetHeight;
			maxHeight = Math.max(menuTag.offsetHeight, maxHeight);
    		menuTag.style.height = maxHeight + 'px';
			if(menuTag.offsetHeight > maxHeight)
				menuTag.style.height = (maxHeight - (menuTag.offsetHeight - maxHeight)) + px;
		}
        
        g_InAutoPositionContentFooter = false;
        return;
    }
    
    var autoHeightTags = null;
    if(g_EnableAutoHeight)
    {
        // If this is the first time through, record the original heights of elements that may be resized
        // Otherwise, reset everything back to its original size in preparation for the calculations below
        // Trace1("Searching for elements with AutoHeight attribute - " + CurrentTime());
        autoHeightTags = GetElementsByAttribute(contentBodyTag, "*", "AutoHeight", "True");
        // Trace1("Found " + autoHeightTags.length + " elements with AutoHeight attribute - " + CurrentTime());
        for(var i = 0; i < autoHeightTags.length; i++)
        {
            // // Trace1("autoHeightTags[" + i + "].originalOffsetHeight:" + autoHeightTags[i].originalOffsetHeight + " autoHeightTags[" + i + "].offsetHeight:" + autoHeightTags[i].offsetHeight);
            if(!autoHeightTags[i].originalOffsetHeight && autoHeightTags[i].offsetHeight)
                autoHeightTags[i].originalOffsetHeight = autoHeightTags[i].offsetHeight;
            else if(autoHeightTags[i].originalOffsetHeight)
                autoHeightTags[i].style.height = autoHeightTags[i].originalOffsetHeight + "px";
        }
        // Trace1("AutoHeight preparations are complete - " + CurrentTime());
    }       
    
    // Start with all available vertical window space
    var maxHeight = viewportHeight - headerTag.offsetHeight - footerTag.offsetHeight;
    // Choose the maximum of available vertical window space, content and menu height
    maxHeight = Math.max(contentTag.offsetHeight, maxHeight);
    if (menuTag)
		maxHeight = Math.max(menuTag.offsetHeight, maxHeight);
    
    // Trace1("WindowClientHeight:" + viewportHeight + " available height: " + (viewportHeight - headerTag.offsetHeight - footerTag.offsetHeight) + " menuTag.offsetHeight:" +  menuTag.offsetHeight + " contentTag.offsetHeight:" + contentTag.offsetHeight + " maxHeight:" + maxHeight);
    
    // There is no easy way to set the offsetHight of an element with margins, borders, padding, etc..
	// The idea below is based on http://www.paulbellows.com/getsmart/balance_columns/.
	// I'm not happy that elements might have to be resized twice (when offsetHeight != style.height in px)
	// but I spent some time on it and it seems to be the best way.
	if (menuTag)
	{
		menuTag.style.height = maxHeight + 'px';
		if(menuTag.offsetHeight > maxHeight)
			menuTag.style.height = (maxHeight - (menuTag.offsetHeight - maxHeight)) + px;
	}
	
    var newContentBodyHeight = (menuTag ? menuTag.offsetHeight : maxHeight) - contentHeaderTag.offsetHeight - contentFooterTag.offsetHeight;
    var extraHeight = Math.max(newContentBodyHeight - contentBodyTag.offsetHeight, 0);
    
    contentBodyTag.style.height = newContentBodyHeight + "px";
    if(contentBodyTag.offsetHeight > newContentBodyHeight)
        contentBodyTag.style.height = (newContentBodyHeight - (contentBodyTag.offsetHeight - newContentBodyHeight)) + "px";
        
    // Trace1("newContentBodyHeight: " + newContentBodyHeight + " extraHeight: " + extraHeight);
    
    for(var i = 0; autoHeightTags && i < autoHeightTags.length; i++)
    {
        // Trace1("autoHeightTags[" + i + "].originalOffsetHeight:" + autoHeightTags[i].originalOffsetHeight + " autoHeightTags[" + i + "].style.height:" + autoHeightTags[i].style.height);
        if(autoHeightTags[i].originalOffsetHeight)
            autoHeightTags[i].style.height =  autoHeightTags[i].originalOffsetHeight + extraHeight + 'px';
    }
    
    // Trace1("Exit: AutoPositionContentFooter");
    g_InAutoPositionContentFooter = false;
}
