//returns a reference to a document element
//params : elem_id - id of the desired element
//DEPRECATED - USE utilities.getElement instead
function get_elem(elem_id)
{
	if (document.getElementById){
		return document.getElementById(elem_id);
	}
	else if (document.all){
		return document.all(elem_id);
	}
	
	return false;
}

//tries to set a field to the given value
//at the moment only handles text inputs
function set_field(elem_id, value)
{
	value = value ? value : "";

	try{
		field = get_elem(elem_id);
		switch(field.type){
			case "text":
			case "textarea":
				field.value = value;
				break;
			
			case "checkbox":
				field.checked = value;
				break;
			
			case "select-one":
				field.value = value;
				break;
				
			default:
				alert("set_field does not support fields of type '" + field.type + "'");
		}
	}
	catch(e){
		alert("Could not set field\n" + e.description);
	}
}

//set up static class
function utilities(){}

//browser check
utilities.browserType = (document.all ? "IE" : "Moz");

//returns a reference to a document element from an id
utilities.getElement = function(elementId)
{
	if (document.getElementById)
		return document.getElementById(elementId);
	else if (document.all)
		return document.all(elementId);
	
	return false;
}

//add an event to the specified element, TESTED ON: IE 5.5+ & Moz
//very useful if event may already be assigned
utilities.addEvent = function(elem, evname, func) 
{
	if (utilities.browserType == "IE") 
	{
		elem.attachEvent("on" + evname, func);
	} else 
	{
		elem.addEventListener(evname, func, true);
	}
};

//add an event to the multiple elements
utilities.addEvents = function(elems, evname, func) 
{
	for (var i in elems)
	{
		utilities._addEvent(elems[i], evname, func);
	}
};

//remove an event from the specified element, TESTED ON: IE 5.5+ & Moz
utilities.removeEvent = function(elem, evname, func) 
{
	if (utilities.browserType == "IE") 
	{
		elem.detachEvent("on" + evname, func);
	} else 
	{
		elem.removeEventListener(evname, func, true);
	}
};

//remove an event from multiple elements, TESTED ON: IE 5.5+ & Moz
utilities.removeEvents = function(elems, evname, func) 
{
	for (var i in elems)
	{
		utilities._removeEvent(elems[i], evname, func);
	}
};

//convert decimal to hexidecimal
utilities.hexChars = "0123456789ABCDEF";
utilities.decToHex = function(dec_num){
	var hex_num;
	
	hex_num = utilities.hexChars.charAt(dec_num/16);
	hex_num += utilities.hexChars.charAt(dec_num%16);
	
	return hex_num;
}

//generate a password of specified size
utilities.passwordChars = new Array();
utilities.generate_password = function(size){
	var password = "";
	
	(! size) && (size = 8);	
	
	//we only have to generate passwordChars once, yay!!!
	if (utilities.passwordChars.length == 0)
	{
		for (i = 0; i <= 9; i++)
		{
			utilities.passwordChars.push( i );
		}
		for (i = 65; i <= 90; i++)
		{
			utilities.passwordChars.push( unescape("%"+ utilities.decToHex(i) ) );
		}
		for (i = 97; i <= 122; i++)
		{
			utilities.passwordChars.push( unescape("%"+ utilities.decToHex(i) ) );
		}
	}
	
	for(i = 0; i < size; i++)
	{
		password += utilities.passwordChars[Math.floor(Math.random() * utilities.passwordChars.length)];
	}

	return password;
}

//Appends query to end of url, adds necessary & or ?
utilities.appendURLQuery = function(url, query) {
	return url + (url.match("\\?") ? "&" : "?") + query;
};

//Toggle checked status on all the checkboxes in the given form
//default is the state of the checkboxes when first called, after that
//it switches between states
utilities.selected = {};
utilities.selectAll = function(formId, defaultState)
{
	try
	{
		form = get_elem(formId);
		
		if (! form || form.nodeName.toUpperCase() != "FORM")
		{
			throw("No form element given");
		}

		if (! utilities.selected[formId])
			utilities.selected[formId] = (defaultState != undefined ? defaultState : true);
		else
			utilities.selected[formId] = !utilities.selected[formId];

		for (var i = 0; i < form.elements.length; i++)
		{
			if (form.elements[i].type == "checkbox")
				form.elements[i].checked = utilities.selected[formId];
		}
	}
	catch(e){
		alert(e);
	}	
}

utilities.confirmDelete = function(recType) {
	var msg = "Are you sure that you want to delete " + recType + "?";
	if (confirm(msg)) {
		return(true);
	} else {
		return(false);
	}
}

/**
* @return void
* @param HTMLSelectElement select
* @param HTMLOptionElement option
* @param integer insertAt
* @param boolean allowDuplicates
* @desc Inserts the option into the select element at the position specified by insertAt.
* If insertAt is -1, option is inserted after currently selected option.
* If insertAt is null, option is inserted at end of list.
* allowDuplicates specifies whether duplicate entres are allowed.
*/
utilities.insertOption = function(select, option, insertAt, allowDuplicates)
{
	/* default to false */
	(allowDuplicates == undefined) && (allowDuplicates = false);
	
	if (! allowDuplicates)
	{
		/* loop through each option and check if it has the same text/value pair */
		for (var i = 0; i < select.options.length; i++)
		{
			if (select.options[i].text == option.text
				&& select.options[i].value == option.value)
			{
				alert("Item '" + option.text + "' already in list");
				return;
			}
		}
	}
	
	/* if insertAt is not defined, insert after selected option */
	if (insertAt == -1)
		insertAt = select.options.selectedIndex + 1;
	
	/* if insertAt is still not valid, add to end of list */
	if (! insertAt || insertAt < 0)
		insertAt = select.options.length;

	/* move each option */
	for (var i = select.options.length; i > insertAt; i--)
		select.options[i] = new Option(select.options[i - 1].text, select.options[i - 1].value);
	
	/* insert new option */
	select.options[insertAt] = option;
}

/**
* @return void
* @param string sourceSelectId
* @param string seperator
* @desc Converts all entries in source select to a string seperated by seperator
*/
utilities.selectToString = function(sourceSelectId, seperator)
{
	(! seperator) && (seperator = ";");
	
	sourceSelect = document.getElementById(sourceSelectId);
	
	var data = "";
	for (var i = 0; i < sourceSelect.options.length; i++)
		data += (data ? seperator : "") + sourceSelect.options[i].value;
	
	return data;
}

/**
* @return void
* @param string sourceSelectId
* @param string data
* @param string seperator
* @desc Splits data by seperator and adds each section to target select
*/
utilities.populateSelect = function(targetSelectId, data, seperator)
{
	(! seperator) && (seperator = ";");
	
	targetSelect = utilities.getElement(targetSelectId);
	
	var items = data.split(seperator);
	
	if (items[0])
	{
		for(var i in items)
			targetSelect.options[targetSelect.options.length] = new Option(items[i], items[i]);
	}
}

/**
* @return void
* @param mixed element
* @desc Toggles the visibility state of the element given by element
* element can be either a reference to the element of the id of the element
*/
utilities.toggleVisibility = function(element)
{
	/* if we have element id, get the element */
	if (typeof(element) == "string")
		element = utilities.getElement(element);

	if (element.style.display == "block")
	{
		element.style.display = "none";
	}
	else
	{
		element.style.display = "block";
	}
}

/**
* @return window
* @param string url
* @param integer winWidth
* @param integer winHeight
* @param integer winLeft
* @param integer winTop
* @param string winTarget
* @param string extraAttributes
* @desc Opens a browser window and returns it's instance.
* @author Dayl & Flash
*/
utilities.openWindow = function(url, winWidth, winHeight, winTarget, extraAttributes)
{
	
	if (! extraAttributes) {extraAttributes = 'toolbar=1,location=0,resizable=1,scrollbars=1,menubar=1';}
	if (winWidth)  {extraAttributes += ',width='+ winWidth;}
	if (winHeight) {extraAttributes += ',height='+ winHeight;}
	if (! winTarget) {winTarget = 'flash';}

	newWindow = window.open(url, winTarget, extraAttributes);
	newWindow.focus();
	
	return newWindow;
}

/**
* @return window
* @param string url
* @desc Opens a browser window for help.
* @author GL
*/
utilities.openHelpWindow = function(url)
{

	newWindow = window.open(url, "", "toolbar=no,scrollbars=yes,location=no,resizable=yes,height=600,width=750");
	newWindow.focus();
	
	return newWindow;
}

/**
* @return string
* @param string elementId
* @param string text
* @desc Appends the text 'text' to the end of the element specified by elementId
* @author Osama! 
*/
utilities.appendToInnerHTML = function(elementId, text)
{
	myElement = utilities.getElement(elementId);
	myElement.innerHTML += text;
}

/**
* @return void
* @param string url
* @param integer target
* @desc Redirects the window specified by 'target' to the url specified by 'url'
* If target is not specified, will default to current window
* If url is not specified, will reload the desired window
* @author Flash
*/
utilities.redirectPage = function(url, target)
{
	/* default target to current window */
	if (! target)
		target = window;
	
	/* default location to target's own location (reload itself) */
	if (! url)
		url = target.location.href;
		
	target.location = url;
}
		
/**
* @return string
* @param mixed element
* @param string cssStyle
* @param string jsStyle
* @desc Gets the desired style of 'element', needed if you are wanting to get styles that aren't
* inline to the element (e.g. specified in <style> tags or set in external stylesheet)
* 'element' can be either a reference to the element of the id of the element
* 'cssStyle' is the original css style name of the desired style
* 'jsStyle' is the javascript style name of the desired style, if not set, it will try to guess from
* the cssStyle
* @author Flash
*/
utilities.getStyle = function(element, cssStyle, jsStyle)
{
	/* if we have element id, get the element */
	if (typeof(element) == "string")
		element = utilities.getElement(element);
		
	/* try to guess js style if not set */
	if (! jsStyle)
	{
		/* replace -x with X, with x being any character */
		jsStyle = cssStyle.replace(/-([a-zA-Z])/g, 
				function(fullMatch, subMatch1, position)
				{
					return subMatch1.toUpperCase()
				}
			);
	}
	
	/* mozilla way using cssStyle */
    if (window.getComputedStyle)
    {
        return window.getComputedStyle(element, "").getPropertyValue(cssStyle);
    }
    /* IE way using jsStyle */
    else if (element.currentStyle)
    {
        return element.currentStyle[jsStyle];
    }
}

/**
* @return void
* @param object selectBox1
* @param object selectBox2
* @param string selectBox1ArrayName
* @desc Checks the selected value in SelectBox1 and uses it to update the contents of SelectBox2
* You need to create a group of predefined arrays for the values and options to be loaded into SelectBox2
* for each value of SelectBox1.
* This group of arrays should be defined as follows:
* var 'selectBox1ArrayName'V'SelectBox1 Value1' = new Array('SelectBox2 value1', 'SelectBox2 value2', etc, 0);
* var 'selectBox1ArrayName'O'SelectBox1 Value1' = new Array('SelectBox2 option1', 'SelectBox2 option2', etc, 0);
* var 'selectBox1ArrayName'V'SelectBox1 Value2' = new Array('SelectBox2 value1', 'SelectBox2 value2', etc, 0);
* var 'selectBox1ArrayName'O'SelectBox1 Value2' = new Array('SelectBox2 option1', 'SelectBox2 option2', etc, 0);
* @author dgb
*/
utilities.updateSelectBox = function(selectBox1, selectBox2, selectBox1ArrayName, selectSearch )
{
	//var selectBox1Index = eval(selectBox1.selectedIndex);
	var initSelectBox2 = -1;
	var selectBox1Val = selectBox1.value;
	var selectBox2Val = selectBox2.value;
	selectBox2.length = 0;

	if (selectBox1Val != "-1" && selectBox1Val != "" && selectBox1Val != "0")
	{
		var selectBox1OptionArray = eval(selectBox1ArrayName + 'O' + selectBox1Val);
		var selectBox1ValArray = eval(selectBox1ArrayName + 'V' + selectBox1Val);
		selectBox2.length = 0;

		for (var i = 0; i < selectBox1ValArray.length-1; i++)
		{
			selectBox2.length += 1;
			selectBox2.options[selectBox2.length - 1] = new Option( selectBox1OptionArray[i] );
			selectBox2.options[selectBox2.length - 1].value = selectBox1ValArray[i];

			if ( selectBox2Val == selectBox1ValArray[i] )
			{
				initSelectBox2 = selectBox2.length - 1;
			}
		}
	}

	selectBox2.length += 1;
	if (selectSearch) 
	{
		selectBox2.options[selectBox2.length - 1] = new Option(" - Any - ");
		selectBox2.options[selectBox2.length - 1].value = "";
	}
	else
	{
		selectBox2.options[selectBox2.length - 1] = new Option(" - not selected - ");
		selectBox2.options[selectBox2.length - 1].value = "-1";
	}

	if (initSelectBox2 != -1){
		selectBox2.selectedIndex	= initSelectBox2;
	}
	else
	{
		selectBox2.selectedIndex	= selectBox2.options.length - 1;
	}

}	

/**
* Similar to above, but provides for OPTGROUPS in the second select box.
**/
utilities.updateOptSelectBox = function(selectBox1, selectBox2, selectBox1ArrayName )
{
	//var selectBox1Index = eval(selectBox1.selectedIndex);
	var initSelectBox2 = -1;
	var selectBox1Val = selectBox1.value;
	var selectBox2Val = selectBox2.value;
	if(!selectBox2Val) selectBox2Val=selectBox2.getAttribute('selecteddefault');
	selectBox2.length = 0;

	if (selectBox1Val != "-1" && selectBox1Val != "" && selectBox1Val != "0")
	{
		var selectBox1OptionArray = eval(selectBox1ArrayName + 'O' + selectBox1Val);
		var selectBox1ValArray = eval(selectBox1ArrayName + 'V' + selectBox1Val);
		var selectBox1GroupArray = eval(selectBox1ArrayName + 'G' + selectBox1Val);
		while (selectBox2.hasChildNodes()) {
			selectBox2.removeChild(selectBox2.firstChild);
		}

		var group=selectBox1GroupArray[0];
		var optgroup=document.createElement('optgroup');
		var option;
		optgroup.label=group;
		for (var i = 0; i < selectBox1ValArray.length; i++)
		{
			if(group!=selectBox1GroupArray[i])
			{
				selectBox2.appendChild(optgroup);
				group=selectBox1GroupArray[i];
				optgroup=document.createElement('optgroup');
				optgroup.label=group;
			}
			option=new Option( selectBox1OptionArray[i] );
			option.value=selectBox1ValArray[i];
			option.innerHTML=selectBox1OptionArray[i];
			if(option.value==selectBox2Val) option.selected=true;
			optgroup.appendChild(option);
		}
	} else
	{
		while (selectBox2.hasChildNodes()) {
			selectBox2.removeChild(selectBox2.firstChild);
		}
	}
}	

utilities.GetElementLeft=function(eElement)
{
    var nLeftPos = eElement.offsetLeft;          // initialize var to store calculations
    var eParElement = eElement.offsetParent;     // identify first offset parent element  
    while (eParElement != null)
    {                                            // move up through element hierarchy
        nLeftPos += eParElement.offsetLeft;      // appending left offset of each parent
        eParElement = eParElement.offsetParent;  // until no more offset parents exist
    }
    return nLeftPos;                             // return the number calculated
}

utilities.GetElementTop=function(eElement)
{
    var nTopPos = eElement.offsetTop;            // initialize var to store calculations

    var eParElement = eElement.offsetParent;     // identify first offset parent element  
    while (eParElement != null)
    {                                            // move up through element hierarchy
        nTopPos += eParElement.offsetTop;        // appending top offset of each parent
        eParElement = eParElement.offsetParent;  // until no more offset parents exist
    }
    return nTopPos;                              // return the number calculated
}
