/**
 *	Javascript utility functions
 * © Interactive Technology, Inc 2007
 */



var $;
if (!$ && document.getElementById) {
  $ = function() {
    var elements = new Array();
    for (var i = 0; i < arguments.length; i++) {
      var element = arguments[i];
      if (typeof element == 'string') {
        element = document.getElementById(element);
      }
      if (arguments.length == 1) {
        return element;
      }
      elements.push(element);
    }
    return elements;
  }
}
else if (!$ && document.all) {
  $ = function() {
    var elements = new Array();
    for (var i = 0; i < arguments.length; i++) {
      var element = arguments[i];
      if (typeof element == 'string') {
        element = document.all[element];
      }
      if (arguments.length == 1) {
        return element;
      }
      elements.push(element);
    }
    return elements;
  }
}


 /**
 * 
 */
function object(o)
{
	function F() {};
	F.prototype = o;
	return F;
}


  
 /**
  * Same as selectValue except if the value is "" returns " "
  */
 function selectNNValue( id ) {
 	if( $(id).selectedIndex < 0 )
 		return ' ';
  var v = $(id)[$(id).selectedIndex].value;
 	return v==""?" ":v;
 } 

 
 /**
  * Retrieve a value from a select list
  * @param String id of select element
  */
function selectValue( id ) 
{
	try
	{
 		if( $(id).selectedIndex < 0 )
 			return '';
 	}catch(ex) { alert(id+" does not exist"); }
	return $(id)[$(id).selectedIndex].value;
} 

 
 /**
  * Retrieve a CSV list of multiple values from a select list
  * @param String id of select element
  */
function selectMultipleValues( id, sep ) 
{
	var list = null;
	try {
		list = $(id);
 	}catch(ex) { alert(id+" does not exist"); return false; }
	
	var itms = "";
	if( $(id).selectedIndex < 0 )
		return itms;
 		
 	for( var i=0; i<list.length; i++ )
 	{
 		if(list[i].selected)
 			itms += list[i].value+sep;
 	}
 	if( itms.length>0 )
 		itms = itms.substring(0,itms.length-(sep.length));
 	return itms;
 } 

function swapSelectValue( list, values ) 
{
	vals = values.split(":");
	list = $(list);
	for( var i = 0; i < list.length; i++ )
	{
		if(list[i].value == vals[0])
		{
			list[i].value = vals[1];
			return true;
		}
	}
	return false;
 } 
  
 /**
  * Same as selectValue except if the value is "" returns " "
  */
 function selectNNValue( id ) {
  var v = $(id)[$(id).selectedIndex].value;
 	return v==""?" ":v;
 } 

 
 /**
  * Retrieve a label from a select list
  * @param String id of select element
  */
 function getSelectLabel( id ) {
 	return $(id)[$(id).selectedIndex].label;
 } 
  
 /**
  * Set a value in a select list
  * @param String id of select element, value
  */
 function setSelectValue( id, value ) 
 {
 	if( value == null )
 		return;
 	var e = $(id);
 	if( value == -1 )
 	{
 		e.selectedIndex = -1;
		return;
 	}
 	var options = e.length;
 	for( i = 0; i<options; i++ )
 	{
 		if(e[i].value == value)
 		{
 			e[i].selected = true;
 			break;
 		}
 	}
 } 
  
 /**
  * Set a value in a select list
  * @param String id of select element, value
  */
 function setInputValue( id, value ) 
 {
 	if( value == null )
 		$(id).value = "";
 	else
	 	$(id).value=value;
 } 




function tglSelects(list, state)
{
	for( var i = 0; i < list.length; i++ )
	{
		list[i].style.display = state;
	}
}

function tglSelect( id )
{
	$(id).selectedIndex = -1;
}

function selectPosFromValue(list,value)
{
	for( var i=0; i<list.length; i++ )
	{
		if(list[i].value == value)
			return i;
	}
	return -1;
}
function selectPosFromName(list,name)
{
	for( var i=0; i<list.length; i++ )
	{
		if(list[i].innerHTML == name)
			return i;
	}
	return -1;
}

function rmvSelectOption(list, pos)
{
	var opt = list[pos];
	opt.parentNode.removeChild(opt);
}
function rmvSelectOptionByValue(list,value)
{
	rmvSelectOption( list, selectPosFromValue(list,value));
}

function clrSelectOptions(list)
{
	for(var i=list.length-1; i>-1; --i)
	{
		var opt = list[i];
		opt.parentNode.removeChild(opt);
	}
}

function selectAll(list)
{
	for( var i=0; i<list.length; i++ )
		list[i].selected = true;
}

/**
* Retrieve a value from an input HIDDEN | TEXT | TEXTAREA element
* An important note is that $(id).value only
* works some of the time in FF 1.5.01 and below.  It seems that if value
* is set in a hidden field when the page is loaded as with aTermType and cTermType
* it sometimes will not be found with the $(id).value method.
* On the otherhand if the value is set with js then no problem.
* Just a heads up
* @param String id of select element
*/
function getInputValue( id ) 
{
	try
	{
		return $(id).value.trim();
	}catch(ex) { alert(id+" does not exist"); }
}
 
 /**
  * Same as getValue except if the value is "" returns " "
  */
 function getNNValue( id ) {
 	return $(id).value.trim()==""?" ":$(id).value;
 }
 
 /**
  *
  */
 function getRadioValue( id ) {
 	var vals = document.getElementsByName(id);
 	for( var i=0; i<vals.length; i++ )
 	{
 		if( vals[i].checked )
 			return vals[i].value;
 	}
 	return null;
 }
 
 
 /**
  *	 Add trim() to strings
  */ 
String.prototype.trim = function() {
    return(this.replace(/^\s+/,'').replace(/\s+$/,''));
}
 
 
 /**
  *	 Extracts digits from a string
  */ 
String.prototype.digit = function() {
    return(this.replace(/\D+/gi,''));
}



function stout(msg)
{
	alert(msg);
}


function getChildNodesByName(node, name)
{
	name = name.toUpperCase();
	var nodeList = [];
	var nodes = node.childNodes;
	for(var i = 0; i < nodes.length; i++)
	{
		if(nodes[i].nodeName == name)
			nodeList.push(nodes[i]);
	}
	return nodeList;
}


function getCurrNodePos(nodeList, node)
{
	for( var i=0; i<nodeList.length; i++ )
	{
		if(nodeList[i] == node)
			return i;
	}
	return null;
}

/********** ROUNDTRIP FUNCTIONS **********/

	//Takes an object, creates a form and sends it off to the server
	function post(obj, controller, action, target) {
	 nuForm = document.createElement("FORM");
	 nuForm.style.display = "none";
	 nuForm.action = "/servlet/"+controller;
	 nuForm.method = "POST";
	 if ( target != null )
	   nuForm.target = target;
	 document.body.appendChild(nuForm);
	 var formInput = document.createElement('INPUT');
	 // Setup the controller action if any
	 if ( arguments[2] != null )
	 {
	   formInput = document.createElement('INPUT');
	   formInput.name = "action";
	   formInput.value = action;
	   nuForm.appendChild(formInput);
	 }
	 // Get properties, create inputs and values
	 for ( var x in obj )
	 {
	   formInput = document.createElement('INPUT');
	   formInput.name = x;
	   formInput.value = obj[x];
	   nuForm.appendChild(formInput);
	 }
	 nuForm.submit();
	 return true;
	}


/********** BROWSER STUFF **********/
	var isie = true;
	if ( navigator.appName.toLowerCase().indexOf("netscape") != -1 )
		isie = false;

function stopEvent(ev) {
	if (ev) {
		if (isie) {
			ev.cancelBubble = true;
			ev.returnValue = false;
		} else {
			ev.preventDefault();
			ev.stopPropagation();
		}
	}
	return false;
};




/********** INTERFACE UTILITIES **********/
//Utility to reset to defaultValues/Indexes INPUT and SELECT fields located within a Node (i.e. DIV)
function clearForm(node)
{
	//Firefox and Konqueror appear to have a problem with radio and checkboxes.  It seems when they
	//simply query the attribute "checked" they toggle the value.
	//chkradio is used hold the first occurrence of a true value of checked which should be when
	//it encounters the attribute checked and not whether it is true or false.  In otherwords
	//	<input name="somename" value="0" checked> when queried getAttribute("checked") will return "" 
	// and not undefined.
	var chkradio = { };
	
	var children = node.childNodes;
	for( var i = 0; i < children.length; i++ )
	{
		if( children[i].nodeName == "INPUT" && children[i].type == "submit" )
			continue;
			
		if( children[i].nodeName == "INPUT" &&
				(children[i].type == "radio" || children[i].type == "checkbox")  )
		{
			
			if( chkradio[children[i].name] != undefined )
				continue;
			if(children[i].getAttribute("checked")!=null)
			{
				chkradio[children[i].name];
				children[i].checked = true;
			}
			continue;
		}


		if( children[i].nodeName == "INPUT" || children[i].nodeName == "TEXTAREA" )
		{
			if( children[i].getAttribute("defaultValue") != null )
				children[i].value = children[i].getAttribute("defaultValue");
			else
				children[i].value = "";
		}
		else if( children[i].nodeName == "SELECT" )
		{
			if( children[i].getAttribute("defaultIndex") != null )
			{
				try{
				children[i].selectedIndex = children[i].getAttribute("defaultIndex");
				}catch(ex){alert(children[i].id+" cannot be set to defaultIndex");}
			}
			else if( children[i].getAttribute("defaultValue") != null )
			{
				try
				{
					var value = children[i].getAttribute("defaultValue");
					if( value == "clear" )
					{
						children[i].innerHTML = "";
						continue;
					}
					var options = children[i].options;
				 	for(var j = 0; j<options.length; j++ )
					{
						if(options[j].value == value)
						{
							options[j].selected = true;
							break;
						}
					}
				}catch(ex){alert(children[i].id+" cannot be set to defaultValue");}
			}
			else
				children[i].selectedIndex = -1;
		}
		else if( children[i].childNodes.length != 0 )
			clearForm(children[i]);
	}
}
function clearForms(forms /*a space delimited list of forms*/)
{
	var list = forms.split(" ");
	for( var i in list )
		clearForm($(list[i]));
}



//Utility to disable INPUT and SELECT fields located within a Node (i.e. DIV)
//@param node containing form elements
//@param true or false
function disableForm(node , state)
{
	var children = node.childNodes;
	for( var i = 0; i < children.length; i++ )
	{
		if( children[i].nodeName == "INPUT" ||
				children[i].nodeName == "SELECT" ||
				children[i].nodeName == "TEXTAREA"  )
		{
			children[i].disabled = state;
		}
		else if( children[i].childNodes.length != 0 )
			disableForm(children[i], state);
	}
}


function findFocus(id)
{
	$(id).focus();
}


function tglBlks( on, off )
{
	var ons = [];
	if( on != null )
		ons = on.trim().split(" ");
	var offs = [];
	if( off != null )
		offs = off.trim().split(" ");
	for( var i in offs )
	{
		try {
			$(offs[i]).style.display = "none";
		}catch(ex) { top.console.info("tglBlks.off "+offs[i]+" not found "); top.console.trace(); }
	}
	for( var i in ons )
	{
		try {
			$(ons[i]).style.display = "block";
		}catch(ex) { top.console.info("tglBlks.on "+ons[i]+" not found "); top.console.trace(); }
	}
}

function tglInlines( on, off )
{
	var ons = [];
	if( on != null )
		ons = on.trim().split(" ");
	var offs = [];
	if( off != null )
		offs = off.trim().split(" ");
	for( var i in offs )
		$(offs[i]).style.display = "none";
	for( var i in ons )
		$(ons[i]).style.display = "inline";
}

function tglVisibles( on, off )
{
	var ons = [];
	if( on != null )
		ons = on.trim().split(" ");
	var offs = [];
	if( off != null )
		offs = off.trim().split(" ");
	for( var i in offs )
		$(offs[i]).style.visibility = "hidden";
	for( var i in ons )
		$(ons[i]).style.visibility = "visible";
}

function tglBtn(btn, state)
{
	switch(state)
	{
			case("hidden"):$(btn).style.visibility = state;
														break;
			case("visible"):$(btn).style.visibility = state;
														break;
			case("block"):$(btn).style.display = state;
														break;
			case("none"):$(btn).style.display = state;
														break;
			case("inline"):$(btn).style.display = state;
														break;
			default:break;
	}	
}



// X-Browser position of an element in the window.
function elemPos(e)
{
	var pos = { };
	pos.x=0;
	pos.y=0;
	recurse(e, pos);
	function recurse( e, pos ) {
		pos.x += e.offsetTop;
		pos.y += e.offsetLeft;
		
		if( e.nodeName != "BODY" )
			recurse(e.offsetParent, pos)
	};
	pos.x += parseInt(document.body.scrollTop);
	return pos;
}



/**
 * Double click handler.
 * If you wanted to click and doubleClick on the same element
 * with different actions you would use it as so:
 * onclick = "clickHandler.register( functionToCallIfNotDblClicked )"
 * onDblClick = "clickHandler.unregister( functionToCallWhenDblClicked )"
 */
var clickHandler = {
	timeout:250,
	timeoutid:null,
	call:function() { },
	args:null,
	
	register:function( func, args ) 
		{
			clickHandler.args = args;
			clickHandler.call = func;
//			this.call = getOnce;
			timeoutid = setTimeout("clickHandler.finalize()", this.timeout);
		},
	
	unregister:function( func, args )
		{
			clickHandler.args = args;
			clickHandler.call = func;
//			this.call = getTwice;

			//Calling the function immediately instead of waiting for finalize
			clickHandler.call( args );
			
			//Calling "this" in Javascript has variable scope.  Normally you
			//would assume "this" references clickHandler but that is not always
			//the case.  If you alert(this) and call clickHandler from a 
			//<button onclick="clickHandler.unregister()"></button>
			//you will in fact find that this references clickHandler.
			// But if you assign clickHandler.unregister through
			//DOM or Javascript (i.e. btn.onclick = clickHandler.unregister ) "this" 
			//will reference the btn [HTMLButton].  I am not sure why scoping changes
			//this way but it is something to be aware of

			//this.call( args );

			//I set this.call back to null for Mozilla which does correctly set this.call
			//and so could potentially call this.call twice by calling it in finalize.
			clickHandler.call = null;
			clearTimeout(timeoutid);
		},
	
	finalize:function()
		{
			if( clickHandler.call != null )
				clickHandler.call( this.args );
		}
};

function getOnce() { alert("once"); }
function getTwice(s) { alert(s); }





/********** DATE UTILITIES **********/
var DateUtils = {
	getMMDDYY:function(longDate)
	{
		date = new Date(longDate);
		var m = date.getMonth()+1;
		var y = date.getFullYear();
		var d = date.getDate();
		return m+"/"+d+"/"+y;
	},
	getMMDD:function(longDate)
	{
		date = new Date(longDate);
		var m = date.getMonth()+1;
		var d = date.getDate();
		return m+"/"+d;
	},
	getDate:function(yr,mo,dy) // "yr mo dy"
	{
		var date = new Date(parseInt(yr),
												parseInt(mo),
												parseInt(dy)
											);
		return date;
	},
	getDateMillis:function(yr,mo,dy) // "yr mo dy"
	{
		return this.getDate(yr,mo,dy).getTime();
	}
}
