/**
 * phplib.js
 *
 * The phplib javascript file.
 *
 * @author	Derek Parnell
 * @since	Apr 8, 2008 12:32:19 PM
 * @package	PHP_XHTML_Library
 */

	/**
	 * functions
	 */
	function addLoadEvent( func )
	{
		if( window_loaded === true )
			func();

		if( typeof(Prototype) != 'undefined' )
		{
			//alert( 'Prototype' );
			document.observe("dom:loaded", func);
			return;
		}
		var oldonload = document.onload;
		//console.log( document.onload );
		if( typeof document.onload != 'function' )
		{
			//console.log( "addLoadEvent: if( typeof document.onload != 'function' )" );
			document.onload = func;
		}
		else
		{
			//console.log( "addLoadEvent: else" );
			document.onload = function()
			{
				if( oldonload )
					oldonload();
				func();
			};
		}
	}

	var window_loaded = false;
	addLoadEvent( function() { window_loaded = true; } );

	function doPostBack( sPostbackTo, bCausesValidation )
	{
		//if( typeof(bCausesValidation) == "undefined" )
		//	bCausesValidation = false;

		//alert( sPostbackTo + ', ' + bCausesValidation );
		//	if( document.forms[0].action == sPostbackTo )
		//		sPostbackTo = '';
		//	document.getElementById('hdnTemplateName').value = sPostbackTo;
		document.forms[0].submit();
	}

	var arr_days_of_week = new Array( 'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday' );
	var arr_ordering = new Array('First', 'Second', 'Third', 'Fourth', 'Fifth');

	function BubbleMessage( dhtml, msg, cssClass )
	{
		_BubbleMessage_Setup();
		var bubble_message = document.getElementById('bubble_message');
		var container_bubble_message = document.getElementById('container_bubble_message');
		bubble_message.innerHTML = msg;
		if( typeof(cssClass) != 'string' )
			cssClass = 'bubble_message';
		var rect = Viewport.getElementBoundingRect( dhtml );
		container_bubble_message.style.top = rect.y + 'px';
		container_bubble_message.className = cssClass;
		container_bubble_message.style.left = (rect.x + rect.width) + 'px';
		container_bubble_message.style.visibility = 'visible';
		Fade( 'container_bubble_message' );
	}

	function _BubbleMessage_Setup()
	{
		var bubble_message = document.getElementById('bubble_message');
		if( bubble_message )
			return;

		var container_bubble_message = document.createElement( 'table' );
		container_bubble_message.id = 'container_bubble_message';

		var td_infos = [ [ { 'className':'topleft' }, { 'className':'topcenter', 'id':'bubble_message' }, { 'className':'topright' } ]
							, [ { 'className':'bottomleft' }, { 'className':'bottomright', 'colSpan':2 } ]
							];
		for( var r=0; r<td_infos.length; r++ )
		{
			var tr = container_bubble_message.insertRow(r);
			for( var c=0; c<td_infos[r].length; c++ )
			{
				var td = tr.insertCell(c);
				td.className = td_infos[r][c].className;
				if( td_infos[r][c]['id'] )
					td.id = td_infos[r][c]['id'];
				if( td_infos[r][c]['colSpan'] )
					td.colSpan = td_infos[r][c]['colSpan'];
				td.innerHTML = '&nbsp;';
			}
		}
		container_bubble_message.style.visibility = 'hidden';
		container_bubble_message.style.position = 'absolute';
		container_bubble_message.style.top = '0px';
		container_bubble_message.style.left = '0px';
		document.body.appendChild( container_bubble_message );
	}

	function popupNewWindow( url, features, recycle )
	{
		var window_name = '_blank';
		if( !features )
		{
			features = "height=400,width=600,location=0,menubar=1,resizable=1,scrollbars=1,status=0,titlebar=0,toolbar=0";
		}
		if( typeof(recycle) != 'boolean' || recycle == true )
		{
			window_name = 'recycle';
		}
		window.open( url, window_name, features );
	}
	function prettyAlert( url, message, features )
	{
		if( !features )
		{
			features = "height=400,width=600,location=0,menubar=0,resizable=0,scrollbars=0,status=0,titlebar=0,toolbar=0";
		}
		var w = window.open( url + "?msg=" + urlencode(message), "_blank", features );
	}

	var g_time_to_fade = 1000.0;
	function Fade( eid, out, delay )
	{
		var element = document.getElementById(eid);
		if(element == null)
			return;

		if( typeof(out) != 'boolean' )
			out = true;

		if( typeof(delay) != 'number' )
			delay = 2000;

		if( out )
			element.FadeState = 2;

		//if(element.FadeState == null)
		//{
		//	if(element.style.opacity == null
		//			|| element.style.opacity == ''
		//			|| element.style.opacity == '1')
		//	{
		//		element.FadeState = 2;
		//	}
		//	else
		//	{
		//		element.FadeState = -2;
		//	}
		//}

		//if(element.FadeState == 1 || element.FadeState == -1)
		//{
		//	element.FadeState = element.FadeState == 1 ? -1 : 1;
		//	element.FadeTimeLeft = g_time_to_fade - element.FadeTimeLeft;
		//}
		//else
		//{
			element.FadeState = element.FadeState == 2 ? -1 : 1;
			element.FadeTimeLeft = g_time_to_fade;
			setTimeout( "AnimateFade(" + (new Date().getTime()+delay) + ",'" + eid + "')", delay );
		//}
	}
	function AnimateFade(lastTick, eid)
	{
		var curTick = new Date().getTime();
		var elapsedTicks = curTick - lastTick;

		var element = document.getElementById(eid);

		if(element.FadeTimeLeft <= elapsedTicks)
		{
			element.style.opacity = element.FadeState == 1 ? '1' : '0';
			element.style.filter = 'alpha(opacity = '
					+ (element.FadeState == 1 ? '100' : '0') + ')';
			element.FadeState = element.FadeState == 1 ? 2 : -2;
			return;
		}

		element.FadeTimeLeft -= elapsedTicks;
		var newOpVal = element.FadeTimeLeft/g_time_to_fade;
		if(element.FadeState == 1)
			newOpVal = 1 - newOpVal;

		element.style.opacity = newOpVal;
		element.style.filter =
				'alpha(opacity = ' + (newOpVal*100) + ')';

		setTimeout("AnimateFade(" + curTick
				+ ",'" + eid + "')", 33);
	}

	function ApplyDefaultStyles( ctrl )
	{
		if( typeof(ctrl)=='string' )
			ctrl = document.getElementById(ctrl);

		if( ctrl.getAttribute('default_styles') != null )
		{
			var default_styles = ctrl.getAttribute( 'default_styles' );
			ApplyStyles( ctrl, default_styles );
		}
	}

	function ApplyStyles( ctrl, styles )
	{
		if( typeof(ctrl)=='string' )
			ctrl = document.getElementById(ctrl);
		if( typeof(styles)=='string' )
			styles = styles.split(';')

		for( var i=0; i<styles.length; i++ )
		{
			var style_pair = styles[i].trim();
			if( style_pair.length == 0 )
				continue;

			var pair = style_pair.split(':');
			if( pair.length > 2 )
			{
				//## Probably means that there is a url, for instance:
				//#- background: url(http://...), so we will just concat the rest of
				//#- items to the end of $pair[1]
				for( var j=2; j<pair.length; j++ )
				{
					pair[1] += ':' + pair[j];
				}
			}
			else if( pair.length < 2 )
			{
				continue;
			}

			TRACE( "applying " + ctrl.id + " --> " + pair[0].trim() + ": " + pair[1] );
			ctrl.style[ pair[0].trim() ] = pair[1];
		}
	}

	function Highlight( ctrl_id, start_hex, end_hex, time )
	{
		var ctrl = document.getElementById( ctrl_id );
		if( !ctrl )
		{
			TRACE( 'Highlight Failed: no control called ' + ctrl );
			return;
		}
		if( ctrl.getAttribute( 'highlight_timeout' ) )
			clearTimeout( ctrl.getAttribute( 'highlight_timeout' ) );

		if( !start_hex )
			start_hex = 'FFFD6C';
		if( !end_hex )
		{
			if( ctrl.currentStyle )
			{
				end_hex = ctrl.currentStyle['backgroundColor'].replace( /#/, '' );
				if( end_hex == 'transparent' )
					end_hex = '';
				if( end_hex.length == 3 )
				{
					var temp_end_hex = end_hex.split( '' );
					var end_hex = '';

					for( var i = 0; i < temp_end_hex.length; i++ )
					{
						end_hex += temp_end_hex[i] + temp_end_hex[i];
					}
				}
			}
			else if( window.getComputedStyle )
			{
				var style = document.defaultView.getComputedStyle( ctrl, null ).getPropertyValue( 'background-color' );
				if( style == 'transparent' )
					end_hex = '';
				else
				{
					var stripped_style = /(\d+),\s?(\d+),\s?(\d+)/.exec( style );

					end_hex = '';
					for( var i = 1; i <= 3; i++ )
					{
						var hex_snippet = parseInt( stripped_style[i] ).toString( 16 );
						end_hex += hex_snippet.length < 2 ? '0' + hex_snippet : hex_snippet;
					}
				}
			}

			if( !end_hex )
				end_hex = 'FFFFFF';
		}
		if( !time )
			time = 2.5;

		num_steps = Math.floor( time * 1000 / 50 );
		ctrl.setAttribute( 'arr_hex_codes', GetFadeColorArray( start_hex, end_hex.toUpperCase(), num_steps ) );
		HighlightElementBackground( ctrl, 0 );
		setTimeout( "ApplyDefaultStyles( '" + ctrl_id + "' );", i * 50 );

		//## IE selects don't continually update their background when they are open..
		//## so once they have focus we'll skip the animation
		if( ctrl.tagName.toLowerCase() == 'select' )
			ctrl.onfocus =
				function( event )
				{
					clearTimeout( this.getAttribute( 'highlight_timeout' ) );
					this.style.background = '#' + end_hex;
				}
	}

	function HighlightElementBackground( ctrl, index )
	{
		if( !ctrl ) // ctrl may have been removed
			return;
		var attr = ctrl.getAttribute( 'arr_hex_codes' );
		if( typeof( attr ) == 'string' )
			var arr_hex_codes = attr.split( ',' );
		else
			var arr_hex_codes = attr
		if( index >= arr_hex_codes.length )
			return;
		hex_code = arr_hex_codes[ index ];

		try
		{
			ctrl.style.background = '#' + hex_code;
		}
		catch( err )
		{
			; // text nodes..
		}

		var arr_tds = ctrl.getElementsByTagName( 'td' );
		for( var i = 0; i < arr_tds.length; i++ )
			arr_tds[i].style.background = '#' + hex_code;

		//## Curse you IE
		var arr_inputs = ctrl.getElementsByTagName( 'input' );
		for( var i = 0; i < arr_inputs.length; i++ )
		{
			if( arr_inputs[i].type == 'checkbox' || arr_inputs[i].type == 'radio' )
				arr_inputs[i].style.background = '#' + hex_code;
		}

		ctrl.setAttribute( 'highlight_timeout', setTimeout( "HighlightElementBackground( document.getElementById( '" + ctrl.id + "' ), '" + ( ( index * 1 ) + 1 ) + "' )", 50 ) );
	}

	function GetFadeColorArray( start_hex, end_hex, num_steps )
	{
		var arr_hex_colors = [];
		var he = "0123456789abcdef";
		var c = he.split( '' );
		var c1 = start_hex.toLowerCase().split( '' );
		var c2 = end_hex.toLowerCase().split( '' );

		arr_hex_colors[0] = start_hex;
		for (n=1; n<num_steps;n++)
		{
			var red = ((he.indexOf(c1[0])*16)+he.indexOf(c1[1]))+(n*(((he.indexOf(c2[0])*16)+he.indexOf(c2[1]))-((he.indexOf(c1[0])*16)+he.indexOf(c1[1])))/num_steps);
			var green = ((he.indexOf(c1[2])*16)+he.indexOf(c1[3]))+(n*(((he.indexOf(c2[2])*16)+he.indexOf(c2[3]))-((he.indexOf(c1[2])*16)+he.indexOf(c1[3])))/num_steps);
			var blue = ((he.indexOf(c1[4])*16)+he.indexOf(c1[5]))+(n*(((he.indexOf(c2[4])*16)+he.indexOf(c2[5]))-((he.indexOf(c1[4])*16)+he.indexOf(c1[5])))/num_steps);
			arr_hex_colors[n] = String(c[parseInt(red/16)]+c[parseInt(red-(parseInt(red/16)*16))]+c[parseInt(green/16)]+c[parseInt(green-(parseInt(green/16)*16))]+c[parseInt(blue/16)]+c[parseInt(blue-(parseInt(blue/16)*16))]).toUpperCase();
		}
		arr_hex_colors[arr_hex_colors.length] = end_hex;

		return arr_hex_colors;
	}

	function sleep( ms )
	{
		var startDate = new Date();
		var end_ms = startDate.valueOf() + ms;
		var curDate;
		while( true )
		{
			curDate = new Date();
			if( curDate.valueOf() >= end_ms )
				break;
		}
		alert( 'startDate was ' + startDate + ' and end date was ' + curDate );
	}

	function SelectAllNoneCheckboxes( cbx_id, b_selected )
	{
		var container = $( cbx_id );
		if( !container )
			return;

		var arr_cbx = container.getElementsByTagName( 'input' );
		for( var i = 0; i < arr_cbx.length; i++ )
		{
			if( arr_cbx[i].type == 'checkbox' )
				arr_cbx[i].checked = b_selected;
		}
	}

	_extrachars = new Array
		(
			'&', ' ', chr(161), chr(162), chr(163), chr(164), chr(165), chr(166)
			, chr(167), chr(168), chr(169), chr(170), chr(171), chr(172), chr(173), chr(174)
			, chr(175), chr(176), chr(177), chr(178), chr(179), chr(180), chr(181), chr(182)
			, chr(183), chr(184), chr(185), chr(186), chr(187), chr(188), chr(189)
			, chr(190), chr(191), chr(192), chr(193), chr(194), chr(195), chr(196)
			, chr(197), chr(198), chr(199), chr(200), chr(201), chr(202), chr(203)
			, chr(204), chr(205), chr(206), chr(207), chr(208), chr(209), chr(210)
			, chr(211), chr(212), chr(213), chr(214), chr(215), chr(216), chr(217)
			, chr(218), chr(219), chr(220), chr(221), chr(222), chr(223), chr(224)
			, chr(225), chr(226), chr(227), chr(228), chr(229), chr(230), chr(231)
			, chr(232), chr(233), chr(234), chr(235), chr(236), chr(237), chr(238)
			, chr(239), chr(240), chr(241), chr(242), chr(243), chr(244), chr(245)
			, chr(246), chr(247), chr(248), chr(249), chr(250), chr(251), chr(252)
			, chr(253), chr(254), chr(255), '"', '<', '>', "'"
		);

	_htmlentities = new Array
		( '&amp;', '&nbsp;', '&iexcl;', '&cent;', '&pound;', '&curren;', '&yen;', '&brvbar;'
			, '&sect;', '&uml;', '&copy;', '&ordf;', '&laquo;', '&not;', '&shy;', '&reg;'
			, '&macr;', '&deg;', '&plusmn;', '&sup2;', '&sup3;', '&acute;', '&micro;', '&para;'
			, '&middot;', '&cedil;', '&sup1;', '&ordm;', '&raquo;', '&frac14;', '&frac12;'
			, '&frac34;', '&iquest;', '&Agrave;', '&Aacute;', '&Acirc;', '&Atilde;', '&Auml;'
			, '&Aring;', '&AElig;', '&Ccedil;', '&Egrave;', '&Eacute;', '&Ecirc;', '&Euml;'
			, '&Igrave;', '&Iacute;', '&Icirc;', '&Iuml;', '&ETH;', '&Ntilde;', '&Ograve;'
			, '&Oacute;', '&Ocirc;', '&Otilde;', '&Ouml;', '&times;', '&Oslash;', '&Ugrave;'
			, '&Uacute;', '&Ucirc;', '&Uuml;', '&Yacute;', '&THORN;', '&szlig;', '&agrave;'
			, '&aacute;', '&acirc;', '&atilde;', '&auml;', '&aring;', '&aelig;', '&ccedil;'
			, '&egrave;', '&eacute;', '&ecirc;', '&euml;', '&igrave;', '&iacute;', '&icirc;'
			, '&iuml;', '&eth;', '&ntilde;', '&ograve;', '&oacute;', '&ocirc;', '&otilde;'
			, '&ouml;', '&divide;', '&oslash;', '&ugrave;', '&uacute;', '&ucirc;', '&uuml;'
			, '&yacute;', '&thorn;', '&yuml;', '&quot;', '&lt;', '&gt;', '&#39;'
		);
	/**
	 * Used for the html_entitiy_decode and htmlentities functions
	 * @global	HtmlTextBox	g_html_converter
	 * @author	Derek Parnell
	 * @since	Jun 5, 2008 8:00:57 AM
	 */
	var g_html_converter = null;
	/**
	 * Array function to decode html entities.
	 *
	 * @access	public
	 * @author	Derek Parnell
	 * @since	Jun 5, 2008 8:01:17 AM
	 * @return	string The decoded string.
	 * @param	string str The string to decode
	 */
	function html_entity_decode( str )
	{
		//console.log( "html_entity_decode: g_html_converter = " + g_html_converter );
		//if( !g_html_converter )
		//	g_html_converter = document.createElement('textarea');
		//console.log( "g_html_converter = " + g_html_converter );
		//console.log( "str = " + str );
		//console.log( "g_html_converter.value = " + g_html_converter.value );
		//g_html_converter.innerHTML = str;
		//console.log( "g_html_converter.innerHTML = " + g_html_converter.innerHTML );
		//return g_html_converter.value;
		for( var i=_extrachars.length-1; i>=0; i-- )
		{
			str = str.split( _htmlentities[i] ).join( _extrachars[i] );
		}
		return str;
	}

	/**
	 * Another version of htmlentities.  This time using the DOM.
	 *
	 * @access	public
	 * @author	Derek Parnell
	 * @since	Jun 5, 2008 8:07:24 AM
	 * @return	string The encoded string.
	 * @param	string str The string to be encoded.
	 */
	function htmlentities( str )
	{
		//console.log( htmlentities.caller );
		//console.log( "htmlentities: g_html_converter = " + g_html_converter );
		//if( !g_html_converter )
		//	g_html_converter = document.createElement('textarea');
		//g_html_converter.value = str;
		//return g_html_converter.innerHTML;
		return HtmlEntities( str, true )
	}

	function HtmlEntities( str, without_pre )
	{
		if( typeof(without_pre) == "undefined" )
			without_pre = false;
		str = str + '';
		for( var i=0; i<_extrachars.length; i++ )
		{
			str = str.split( _extrachars[i] ).join( _htmlentities[i] );
			//str = str.replace( _extrachars[i], _htmlentities[i] );
		}
		if( without_pre )
			return str;
		return "<pre>" + str + "</pre>";
	};
	function chr( code )
	{
		return String.fromCharCode(code);
	}

	function GETELEMENTS( theObj, include_funcs )
	{
		if( typeof(include_funcs) != 'boolean' && include_funcs != 'display' )	include_funcs = false;
		var a = new Array();
		for( prop in theObj )
		{
			if( (include_funcs===false) && (typeof( theObj[prop] ) == 'function') )
				continue;
			a.push( new String(prop) );
		}

		a = a.sort();
		var str = '';
		for( var i=0; i<a.length; i++ )
		{
			var cur = a[i] + " --> ";
			if( typeof( theObj[ a[i] ] ) == 'function' && include_funcs!='display')
				cur += 'function';
			else
				cur += theObj[ a[i] ];
			str += cur + "\n";
		}
		return str;
	}

	function SHOWELEMENTS( theObj, include_funcs )
	{
		TRACE( GETELEMENTS( theObj, include_funcs ), true );
	}
	function SHOWELEMENTSALERT( theObj, include_funcs )
	{
		alert(GETELEMENTS( theObj, include_funcs ));
	}

	function WARN( str, is_pre )
	{
		TRACE( str, is_pre, 'warn' );
	}
	function TRACE( str, is_pre, css_class )
	{
		var table_tbody = document.getElementById( 'id_tbl_Trace_Information_body' );
		if( !table_tbody )
			return;
		if( typeof(is_pre) != "boolean" )	is_pre = false;

		var num_rows = table_tbody.childNodes.length;
		if( typeof(css_class) == 'undefined' )
		{
			if( num_rows % 2 == 0 )
				var css_class = 'DebugTraceJS';
			else
				var css_class = 'DebugTraceAlternatingJS';
		}
		var tr = document.createElement( 'tr' );
		tr.className = css_class;
		table_tbody.appendChild( tr );

		var td = document.createElement( 'td' );
		td.className = 'DebugTrace';
		tr.appendChild( td );

		var span = document.createElement( 'div' );
		span.className = 'debugTimestamp';
		td.appendChild( span );

		var date_now = new Date();
		span.innerHTML = date_now.getFullYear() + '-' + ( date_now.getMonth() + 1 ) + '-' + date_now.getDate() + ' ' + date_now.getHours() + ':' + date_now.getMinutes() + ':' + date_now.getSeconds() + '.' + date_now.getMilliseconds();

		var txt_node = document.createElement( is_pre ? 'pre' : 'span' );
		txt_node.innerHTML = new String(htmlentities(str, true)).replace(/\n/g, "<br />\n");
		td.appendChild( txt_node );
	}
	if( typeof(console) == 'undefined' )
	{
		console = {'log': TRACE }
	};

	function DECHO( str, is_pre )
	{
		//## just to check for "debug" mode
		var table_tbody = document.getElementById( 'id_tbl_Trace_Information_body' );
		if( !table_tbody )
			return;

		decho_container = GetDechoContainer();

		var decho = document.createElement( 'div' );
		decho.className = "dechoDebug";
		decho.innerHTML = str;
		decho_container.appendChild( decho );
	}
	function AddInfoMessage( str, highlight )
	{
		decho_container = GetDechoContainer();

		var info = document.createElement( 'div' );
		info.className = "info";
		info.innerHTML = str;
		decho_container.appendChild( info );

		if( highlight )
		{
			info.id = highlight;
			Highlight( highlight );
		}
	}
	function GetDechoContainer()
	{
		var decho_container = document.getElementById('decho_container');
		if( !decho_container )
		{
			decho_container = document.createElement( 'div' );
			decho_container.id = 'decho_container';
			var CONTENT_ID = document.getElementById('CONTENT_ID');
			if( !CONTENT_ID )
			{
				alert( 'no CONTENT_ID. DECHO contents in TRACE' );
				TRACE( str );
				return;
			}
			CONTENT_ID.insertBefore( decho_container, CONTENT_ID.firstChild );
		}
		return decho_container;
	}
	function GET_STACK_TRACE(startingPoint)
	{
		var stackTraceMessage = "Stack trace: <br>\n";
		var nextCaller = startingPoint;
		while(nextCaller)
		{
			stackTraceMessage += getSignature(nextCaller) + "<br>\n";
			nextCaller = nextCaller.caller;
		}
		stackTraceMessage += "<br>\n\n";

		// display message
		TRACE( stackTraceMessage );
	}

	function getSignature(theFunction)
	{
		var signature = getFunctionName(theFunction);
		signature += "(";
		for(var x=0; x<theFunction.arguments.length; x++)
		{
			// trim long arguments
			var nextArgument = theFunction.arguments[x];
			if(nextArgument.length > 30)
				nextArgument = nextArgument.substring(0, 30) + "...";

			// apend the next argument to the signature
			signature += "'" + nextArgument + "'";

			// comma seperator
			if(x < theFunction.arguments.length - 1)
				signature += ", ";
		}
		signature += ")";
		return signature;
	}

	function getFunctionName(theFunction)
	{
		// mozilla makes it easy. I love mozilla.
		if(theFunction.name)
		{
			return theFunction.name;
		}

		// try to parse the function name from the defintion
		var definition = theFunction.toString();
		var name = definition.substring(definition.indexOf('function') + 8,definition.indexOf('('));
		if(name)
			return name;

		// sometimes there won't be a function name
		// like for dynamic functions
		return "anonymous";
	}

	function ShowHideSearchCriteria( oThis )
	{
		oThis.blur();
		var previously_visible = false;

		var filter_table = $( 'ldp_filter' );
		for( var i = 2; i < filter_table.tBodies[0].rows.length; i++ ) // 0 is header, 1 is page filter
		{
			var tr = filter_table.tBodies[0].rows[i];
			if( tr.style.display == 'none' )
				tr.style.display = '';
			else
			{
				previously_visible = true;
				tr.style.display = 'none';
			}
		}

		if( previously_visible )
			oThis.firstChild.src = oThis.firstChild.src.replace( /collapse/, 'expand' );
		else
			oThis.firstChild.src = oThis.firstChild.src.replace( /expand/, 'collapse' );

		cm = new Cookie_manager();
		cm.set_cookie( 'search_criteria', previously_visible ? 0 : 1, 60 );
	}

	function innerText( obj, val )
	{
		if( obj['innerText'] )
			obj.innerText( val );
		else
			obj.innerHTML = val;
	}

	//## No hasty hacks to see here.. Move along.
	function InsertTableRow( tr_html, anchor, insert_after_anchor, highlight )
	{
		if( typeof( anchor ) == 'string' )
			anchor = $( anchor );
		if( !anchor )
			return;

		if( insert_after_anchor !== false )
			insert_after_anchor = true;

		var div = document.createElement( 'DIV' );
		div.innerHTML = '<table>' + decodeURIComponent( tr_html ) + '</table>';
		var new_tr = anchor.parentNode.insertBefore( div.getElementsByTagName( 'TR' )[0], insert_after_anchor ? anchor.nextSibling : anchor );

		if( highlight === true && new_tr.id )
			Highlight( new_tr.id );
	}

	function IncludeJSScript( script_filename )
	{
		var html_doc = document.getElementsByTagName( 'head' ).item( 0 );
		var js = document.createElement('script' );
		js.setAttribute( 'language', 'javascript' );
		js.setAttribute( 'type', 'text/javascript' );
		js.setAttribute( 'src', script_filename );
		html_doc.appendChild( js );
	}
	/////////////////////////////////////////////
	//	Cookies

	// Ronald Weidner
	// quick and dirty cookie class

	// example:
	// var cm = new Cookie_manager();
	// cm.set_cookie("fred", "15");              // cookie fred = 15
	// c = cm.get_cookie("fred");                // c = 15
	// cm.append_cookie("fred", "16");       // cookie fred = 1516
	// cm.delete_cookie("fred");                 // cookie fred = expired and set to 0

	function _delete_cookie(name, path, domain, secure)
	{
		_set_cookie(name,"",-1, path, domain, secure);
	}
	function _append_cookie(name, value, expire)
	{
		var cur_val;
		var new_val;

		if (name)
		{
			cur_val = _get_cookie(name);
			new_val = cur_val + value;
			_set_cookie(name, new_val, expire);
		}
	}

	function _set_cookie(name, value, days, path, domain, secure)
	{
		if (days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			var expires = "; expires="+date.toGMTString();
		}
		else var expires = "";
		if( !path )
			path = '/';
		value = encodeURIComponent( value );
		document.cookie = name+"="+value+expires+"; path=" + path +
			( domain ? "; domain=" + domain : "" ) +
			( secure ? "; secure=" + secure : "" );
	}
	function _get_cookie(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 decodeURIComponent( c.substring(nameEQ.length,c.length) );
		}
		return null;
	}

	Cookie_manager.prototype.get_cookie = _get_cookie;
	Cookie_manager.prototype.set_cookie = _set_cookie;
	Cookie_manager.prototype.append_cookie = _append_cookie;
	Cookie_manager.prototype.delete_cookie = _delete_cookie;
	function Cookie_manager()
	{
	}
