﻿// ###########################################################
// Collection of Utility JavaScript functions compiled by ASI
// ###########################################################

//
// Adds event to window.onload without overwriting currently assigned onload functions.
//
function addLoadEvent(loadFunc)
{
    if (loadFunc)
    {
        var oldonload = window.onload;
        if (typeof window.onload != 'function')
        {
            window.onload = loadFunc;
        } 
        else
        {
            window.onload = function()
            {
                if (typeof oldonload == 'function') oldonload();
                loadFunc();
            }
        }
    }
}

// Add RadControl related load events
//
function addAjaxLoadEvent(loadFunc) 
{
    function f() { loadFunc(); Sys.Application.remove_load(f); }; 
    Sys.Application.add_load(f);
}

//
// Adds event to window.onresize without overwriting currently assigned onresize functions.
//
function addResizeEvent(resizeFunc, resizeControl)
{	
    if (resizeControl == null)
        resizeControl = window;
        
    $addHandler(resizeControl, 'resize', resizeFunc)
        
//	var oldonresize = resizeControl.onresize;
//	if (typeof resizeWin.onresize != 'function'){
    	//resizeControl.onresize = resizeFunc;
//	} else {
//		resizeControl.onresize = function(){
//		oldonresize();
//		resizeFunc();
//		}
//	}
}
var resizeFunctionNames = new Array();
//
// Adds a function name to a collection of function names that should be executed
// when the content is resized (window resize, or page content resized).
//
function addContentResizeEvent(resizeFunctionName)
{
    resizeFunctionNames.push(resizeFunctionName);
}
//
// Call this function after the main content area has been resized.
//
function contentResized(contentWidth, contentHeight)
{
    for (var i=0; i<resizeFunctionNames.length; i++)
    {
        var evalText = resizeFunctionNames[i] + '(' + contentWidth + ',' + contentHeight + ')';
        eval(evalText);
    }
}
//
// nextObject and previousObject perform exactly the same function as nextSibling and previousSibling, 
// but will only return the next/previous HTML element, ignoring text nodes altogether
//
function getNextObject(n) 
{ 
    do n = n.nextSibling; 
    while (n && n.nodeType != 1); 
    return n; 
} 
function getPreviousObject(p)
{ 
    do p = p.previousSibling; 
    while (p && p.nodeType != 1); 
    return p; 
} 

function cancelSubmit()
{
    return CancelEvent();
}
//
// Browser-independent way of cancelling the last event.
// Example:
//  <button onclick="if (!confirm('Do Something?')) return CancelEvent(); else doSomething();" />
//
function CancelEvent(e)
{
    if (!e)
    {
        e = window.event;
    }

    if (e != null)
        e.returnValue = false;
    return false;
}
// I can never remember the casing for this function, so this makes it not matter.
function cancelEvent()
{
    return CancelEvent();
}
//
// Browser-independent function for cancelling event
// propagation (event bubbling).
//
function CancelEventPropagation(e)
{
    if (!e)
    {
        e = window.event;
	}
	e.cancelBubble = true;
	
	if (e.stopPropagation) 
	    e.stopPropagation();
}
//
// Browser-independent method for getting the last event source object
//
function eventSource(e)
{
    if (window.event)
        return window.event.srcElement;
    
    return e.target;
}
//
// Get the last key entered by user
//
function KeyStroke(e)
{
    if (window.event)
    {
        return e.keyCode;
    }
    else
    {
        return e.which;
    }
}
//
// Convenience function for extracting a number from a given variable (presumably of
// some other type, like string)
//
function ExtractNumber(value)
{
    var n = parseInt(value);
    return n == null || isNaN(n) ? 0 : n;
}
//
// Convenience function for saving lots of typing, instead of typing 
// document.getElementById() all the time.
//
function $(id)
{
    return document.getElementById(id);
}
//
// Given any object within a form, this function will find the containing form and submit it
//
function submitForm(object)
{
	if (object && object != null)
		form = findAncestor(object, "FORM");
	else
		form = window.template;

	if (form != null)
		form.submit();
}
// Given an element, return its parent in a way that both IE6 and actual standards-compliant browsers both support.
function getParent(element)
{
    return element.parentNode || element.parentElement;
}
if (!window.Node) var Node =
    {
        ELEMENT_NODE: 1,
        ATTRIBUTE_NODE: 2,
        TEXT_NODE: 3,
        CDATA_SECTION_NODE: 4,
        ENTITY_REFERENCE_NODE: 5,
        ENTITY_NODE: 6,
        PROCESSING_INSTRUCTION_NODE: 7,
        COMMENT_NODE: 8,
        DOCUMENT_NODE: 9,
        DOCUMENT_TYPE_NODE: 10,
        DOCUMENT_FRAGMENT_NODE: 11,
        NOTATION_NODE: 12
    }
//
// Given an object and a type of ancestor to find, locates the first ancestor of the given object that is of the specified type.
// If none is found, null is returned
//
function findAncestor(object, type)
{
	oParent = getParent(object);
	while (oParent != null)
	{
		if (oParent.tagName.toLowerCase() == type.toLowerCase())
			return oParent;
		oParent = getParent(oParent);
	}
	return null;
}
function trim(str, chars)
{
    return ltrim(rtrim(str, chars), chars);
}
function ltrim(str, chars)
{
    chars = chars || "\\s";
    return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
}
function rtrim(str, chars)
{
    chars = chars || "\\s";
    return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
} //
// Browser-independent function for returning the height of the current page.
//
function livePageHeight()
{
    if (window.innerHeight && window.scrollMaxY && BrowserDetect.version < 3) // Firefox 2
    {
        return window.innerHeight + window.scrollMaxY;

    }
    else // works in Explorer 6, 7 Strict, Mozilla, Safari and FireFox 3
    { 
        return document.body.offsetHeight + document.body.offsetTop; 
    }
    
    return null;
//	if (window.innerHeight != null)
//		return window.innerHeight;
//		
//	if (document.body.clientHeight != null)
//		return document.body.clientHeight;
//		
//	return null;
}
//
// Browser-independent function for returning the width of the current page.
//
function livePageWidth()
{
    if (window.innerHeight && window.scrollMaxY ) // Firefox 
    {
        return window.innerWidth + window.scrollMaxX;

    }
    else // works in Explorer 6 Strict, Mozilla (not FF) and Safari
    { 
        return document.body.offsetWidth + document.body.offsetLeft; 
    }
    
    return null;
    
//	if (window.innerWidth != null)
//		return window.innerWidth;
//		
//	if (document.body.clientWidth != null)
//		return document.body.clientWidth;
//		
//	return null;
}
//
// Given an object, finds its absolute and relative position on the page.
// Returns a "shape" which contains these attributes:
//  left, top, width, height, absoluteLeft, absoluteTop
//
function findAbsoluteCoords(obj)
{
    var shape = new Object();
    shape.left = obj.offsetLeft;
    shape.top = obj.offsetTop;
    shape.width = obj.clientWidth;
    shape.height = obj.clientHeight;
    shape.absoluteLeft = 0;
    shape.absoluteTop = 0;


    // figure out the absolute x,y coords by going up the ancestory
    var temp = obj;
    while (temp != null)
    {
        var tagName = temp.tagName.toUpperCase();
        if (tagName == 'BODY' || tagName == 'FORM' || tagName == 'HTML')
            break;

        shape.absoluteLeft = shape.absoluteLeft + temp.offsetLeft;
        shape.absoluteTop = shape.absoluteTop + temp.offsetTop;
        temp = temp.offsetParent;
        
        if (temp != null && (temp.style.position == 'absolute' || temp.style.position == 'relative'))
            break;
    }
    
    // if the width is 0 (i.e., unspecified) make it as wide as possible
    if (shape.width == 0)
        shape.width = livePageWidth() - shape.absoluteLeft;

    // if the height is 0 (i.e., unspecified) make it as tall as possible
    if (shape.height == 0)
        shape.height = livePageHeight() - shape.absoluteTop;

    return shape;
}
//
// Returns an array of the url parameters, with each element in the form of "param=value"
//
function GetURLParameters()
{
	var url = window.document.URL.toString();
	
	if (url.indexOf("?") > 0)
	{
		var parts = url.split("?");
		var paramsArray = parts[1].split("&");
		return paramsArray;
	}
	return null;
}
//
// Return the value in the URL parameter string for a given parameter name
//
function FindURLParameter(paramName)
{
	paramName = paramName.toUpperCase();
	var paramsArray = GetURLParameters();
	if (paramsArray != null)
		return FindParameterInArray(paramName,paramsArray);
	return null;
}
//
// Given an array of parm=value strings, splits the parm name from the value, looks for the paramName in the array of names
// and if found returns the param value
//
function FindParameterInArray(paramName, paramsArray)
{
	paramName = paramName.toUpperCase();
	for (i=0;i<paramsArray.length;i++)
	{
		var sParam =  paramsArray[i].split("=");
		if (sParam[0].toUpperCase() == paramName)
			return sParam[1];
	}	
	return null;
}
function findPos(obj) 
{
    var curleft = curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
    }
    return [curleft, curtop];
}

//
// Move an element directly on top of another element.  Optionally
// make it the same size or set an offset for X and Y coordinates.
//
//
// Move an element directly on top of another element.  Optionally
// make it the same size or set an offset for X and Y coordinates.
//
function Cover(bottomElement, topElement, ignoreSize, offsetX, offsetY) {
    var location = findPos(bottomElement);
    topElement.style.position = 'absolute';

    var positionY = location[1];
    if (offsetY != null && !isNaN(offsetY))
        positionY = positionY + offsetY;

    var positionX = location[0];
    if (offsetX != null && !isNaN(offsetX))
        positionX = positionX + offsetX;

    var bottomheight = 0;
    var bottomwidth = 0;

    // Use local vars for the Bottom control size - In this case we can compare those values to actual screen size and adjast them if size greater then Screen.
    bottomheight = bottomElement.offsetHeight;
    if (screen.height < bottomheight)
        bottomheight = screen.height;
    bottomwidth = bottomElement.offsetWidth;
    if (screen.width < bottomwidth)
        bottomwidth = screen.width;


    if (!ignoreSize) {
        topElement.style.height = bottomheight + 'px';
        topElement.style.width = bottomwidth + 'px';
    }

    // figure out the physical area of the page the browser is currently displaying, accounting for any scrolling
    var pageLeft = GetViewportScrollPos().x;
    var pageRight = pageLeft + document.body.offsetWidth - 1;
    var pageTop = GetViewportScrollPos().y;
    var pageBottom = pageTop + document.body.offsetHeight - 1;
    
    /*
    var pageHeight = livePageHeight() - 30;
    var pageWidth = livePageWidth() - 30;
    */

    // Check Right/Bottom screen boundaries
    var elementHeight = topElement.offsetHeight > 0 ? topElement.offsetHeight : bottomheight;
    var elementWidth = topElement.offsetWidth > 0 ? topElement.offsetWidth : bottomwidth;
    if ((positionY + elementHeight) > pageBottom)
        positionY = pageBottom - elementHeight;
    if ((positionX + elementWidth) > pageRight)
        positionX = pageRight - elementWidth;

    // Check Top/Left screen boundaries
    if (positionX < pageLeft)
        positionX = pageLeft;
    if (positionY < pageTop)
        positionY = pageTop;

    topElement.style.top = positionY + 'px';
    topElement.style.left = positionX + 'px';

    topElement.style.zIndex = 1001; // bottomElement.style.zIndex + 1;
}
//
// Create a cookie
//
function createCookie(name,value,days) {
	if (days) {
		var date = new Date();
		date.setTime(date.getTime()+(days*24*60*60*1000));
		var expires = "; expires="+date.toGMTString();
	}
	else var expires = "";
	document.cookie = name+"="+value+expires+"; path=/";
}
//
// Read a cookie
//
function readCookie(name) {
	var nameEQ = name + "=";
	var ca = document.cookie.split(';');
	for(var i=0;i < ca.length;i++) {
		var c = ca[i];
		while (c.charAt(0)==' ') c = c.substring(1,c.length);
		if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
	}
	return null;
}
//
// Delete a cookie
//
function eraseCookie(name) {
	createCookie(name,"",-1);
}

/** Determines if the string is a url */
function IsUrl(s, optionalSchema) {
    var regexp = new RegExp('^(([a-z]+)://)' + (optionalSchema ? '?' : '') + '([a-z0-9\-]+|[a-z0-9][a-z0-9\-\.\_]*\.[a-z]+)(:[0-9]+)?(/.*)?$', 'i');
    return regexp.test(s);
}

// 
// Browser Detection
//
var BrowserDetect = {
	init: function () {
		this.browser = this.searchString(this.dataBrowser) || "An unknown browser";
		this.version = this.searchVersion(navigator.userAgent)
			|| this.searchVersion(navigator.appVersion)
			|| "an unknown version";
		this.OS = this.searchString(this.dataOS) || "an unknown OS";
	},
	searchString: function (data) {
		for (var i=0;i<data.length;i++)	{
			var dataString = data[i].string;
			var dataProp = data[i].prop;
			this.versionSearchString = data[i].versionSearch || data[i].identity;
			if (dataString) {
				if (dataString.indexOf(data[i].subString) != -1)
					return data[i].identity;
			}
			else if (dataProp)
				return data[i].identity;
		}
	},
	searchVersion: function (dataString) {
		var index = dataString.indexOf(this.versionSearchString);
		if (index == -1) return;
		return parseFloat(dataString.substring(index+this.versionSearchString.length+1));
	},
	dataBrowser: [
		{ 	string: navigator.userAgent,
			subString: "OmniWeb",
			versionSearch: "OmniWeb/",
			identity: "OmniWeb"
		},
		{
			string: navigator.vendor,
			subString: "Apple",
			identity: "Safari"
		},
		{
			prop: window.opera,
			identity: "Opera"
		},
		{
			string: navigator.vendor,
			subString: "iCab",
			identity: "iCab"
		},
		{
			string: navigator.vendor,
			subString: "KDE",
			identity: "Konqueror"
		},
		{
			string: navigator.userAgent,
			subString: "Firefox",
			identity: "Firefox"
		},
		{
			string: navigator.vendor,
			subString: "Camino",
			identity: "Camino"
		},
		{		// for newer Netscapes (6+)
			string: navigator.userAgent,
			subString: "Netscape",
			identity: "Netscape"
		},
		{
			string: navigator.userAgent,
			subString: "MSIE",
			identity: "Explorer",
			versionSearch: "MSIE"
		},
		{
			string: navigator.userAgent,
			subString: "Gecko",
			identity: "Mozilla",
			versionSearch: "rv"
		},
		{ 		// for older Netscapes (4-)
			string: navigator.userAgent,
			subString: "Mozilla",
			identity: "Netscape",
			versionSearch: "Mozilla"
		}
	],
	dataOS : [
		{
			string: navigator.platform,
			subString: "Win",
			identity: "Windows"
		},
		{
			string: navigator.platform,
			subString: "Mac",
			identity: "Mac"
		},
		{
			string: navigator.platform,
			subString: "Linux",
			identity: "Linux"
		}
	]

};


BrowserDetect.init();

/*
Returns the x/y coordinates of an element relative to the viewport.
If an element is at x=10,y=1000, but the browser window is scrolled down by 950px, the return coords will be x=10,y=50
*/
function GetElementViewportOffset(forElement) {

    var valueY = 0, valueX = 0, docBody = document.body;
    
    var element = forElement;
    do {
        valueY += element.offsetTop || 0;
        valueX += element.offsetLeft || 0;
        // Safari fix
        if (element.offsetParent == docBody && element.style.position && element.style.position == 'absolute') break;
    } while (element = element.offsetParent);

    element = forElement;
    do {
        // Opera < 9.5 sets scrollTop/Left on both HTML and BODY elements.
        // Other browsers set it only on the HTML element. The BODY element
        // can be skipped since its scrollTop/Left should always be 0.
        if (element != docBody) {
            valueY -= element.scrollTop || 0;
            valueX -= element.scrollLeft || 0;
        }
    } while (element = element.parentNode);
    
    var coords = new Object();
    coords.x = valueX;
    coords.y = valueY;

    return coords;
}

/*
Returns the x/y scroll positions of viewport.
This refers to the browser or iFrame scrollbars, not the scrollbars of any sub elements on the page.
*/
function GetViewportScrollPos() {

    var scrollPos = new Object();
    scrollPos.x = scrollPos.y = 0;

    if (typeof window.pageYOffset != 'undefined') {
        scrollPos.y = window.pageYOffset;
        scrollPos.x = window.pageXOffset;
    }
    else
        if (document.documentElement) {
            scrollPos.y = document.documentElement.scrollTop;
            scrollPos.x = document.documentElement.scrollLeft;
    }
    else
        if (document.body && typeof document.body.scrollTop != 'undefined') {
            scrollPos.y = document.body.scrollTop;
            scrollPos.x = document.body.scrollLeft;
        }

    return scrollPos;

}

/*
Size an image to fit within specific width and height bounds.
If the image is larger than the bounds, it will be downsized maintaining its aspect ratio.
If the image is smaller than the bounds and allowUpsize=true, the image will be upsized maintaining its aspect ratio.

Params
    imageElement = (ref) reference to the image element to be sized
    maxWidth = (int) max allowed width in pixels or null
    maxHeight = (int) max allowed height in pixels or null
    allowUpsize = (bool) if the image is smaller than the bounds, then upscale it
    
maxWidth AND/OR maxHeight can be specified.
maxWidth
    The image width will be set to the specified maxWidth
    The height will be adjusted accordingly to maintain aspect ratio. There will be no upper bound for resulting height.
maxHeight
    The image height will be set to the specified maxHeight.
    The width will be adjusted accordingly to maintain aspect ratio. There will be no upper bound for resulting width.
maxWidth AND maxHeight
    Based on the images aspect ratio, the relevant maximum sizing parameter will be selected i.e. either width or height.
    The image will then be sized to its maximum based on that dimension i.e. either width to maxWidth or height to maxHeight.
    The other dimension will be adjusted accordingly to maintain aspect ratio. 
    The final result will be that both width and height fall within the bounds of maxWidth and maxHeight.
*/
function SizeImageWithinBounds(imageElement, maxWidth, maxHeight, allowUpsize) {

    // were we given some bounds
    maxWidth = parseInt(maxWidth);
    if (isNaN(maxWidth)) maxWidth = 0;
    maxHeight = parseInt(maxHeight);
    if (isNaN(maxHeight)) maxHeight = 0;
    if (maxWidth <= 0 && maxHeight <= 0) return;

    // do we have an image
    if (imageElement == null) return;
    if (!imageElement.tagName) return;
    if (imageElement.tagName.toUpperCase() != "IMG") return;
    var width = imageElement.width;
    var height = imageElement.height;
    if (width == 0 || height == 0) return;

    // determine current aspect ratio
    var aspectRatio = imageElement.width / imageElement.height;

    // figure out sizing mode
    var sizeMode = 0;       // 0(none), 1(by width), 2(by height)
    if (maxWidth > 0 && maxHeight > 0) {
        // width and height
        sizeMode = (Math.floor(maxWidth / aspectRatio) <= maxHeight) ? 1 : 2;
    }
    else {
        if (maxWidth > 0) {
            // width
            if (width > maxWidth || (width < maxWidth && allowUpsize)) sizeMode = 1;
        }
        else {
            // height
            if (height > maxHeight || (height < maxHeight && allowUpsize)) sizeMode = 2;
        }
    }
    if (sizeMode == 0) return;

    // size the image
    if (sizeMode == 1) {
        // by width
        width = maxWidth;
        height = Math.max(Math.floor(width / aspectRatio), 1);
    }
    else {
        // by height
        height = maxHeight;
        width = Math.max(Math.floor(height * aspectRatio), 1);
    }
    imageElement.width = width;
    imageElement.height = height;

}

