/***************************************************************************
* Copyrighted (c) 2005 Compu-Creations (www.compu-creations.com)
* The software and related user documentation are protected under
* copyright laws and remain the sole property of Compu-Creations. Full license
* is available on the Compu-Creations website or in the original download.
**************************************************************************/

//******************************************************************************************************************
// Constants
//..................................................................................................................

// Keycodes for keyup, keydown, keypress events
var KEYCODE_ENTER = 13;

//******************************************************************************************************************
// DOM
//..................................................................................................................

/**
* Deletes all the child elements of a given element
*
* @param Element - e (The element)
* 
*/
function DeleteAllChildren(e)
{
	while (e2 = e.firstChild)
	{
		e.removeChild(e2);
	}
}

/**
* Sets a <select>'s current option by its value
*
* @param Element - e (The select element)
*
* @param ??? - val (The value)
* 
*/
function SetSelectByValue(e, val)
{
	for (i = 0; i < e.length; i++)
	{
		if (e[i].value == val)
		{
			e.selectedIndex = i;
			return;
		}
	}
}

/**
* Returns the text content of a node
*
* @param Element - e (The node)
*
* @return String - the text content
* 
*/
function GetNodeText(e)
{
	if (e)
	{
		if (e.firstChild)
		{
			return e.firstChild.nodeValue;
		}
	}
	return '';
}


/**
* Returns the X of an element in relation to the page top left
*
* @param Element - e (The elemente)
*
* @return String - the text content
* 
*/
function GetElementX(e)
{
	var x = e.offsetLeft;
	while ((e = e.offsetParent) != null)
	{
		x += e.offsetLeft;
	}
	return x;
}


/**
* Returns the Y of an element in relation to the page top left
*
* @param Element - e (The elemente)
*
* @return String - the text content
* 
*/
function GetElementY(e)
{
	var y = e.offsetTop;
	while ((e = e.offsetParent) != null)
	{
		y += e.offsetTop;
	}
	return y;
}


/**
* Returns the value of a radio button set
*
* @param String - name (The name shared by the set)
*
* @return String - the value checked
* 
*/
function GetRadioValue(name)
{
	radio_obj = document.getElementsByName(name);
	if (!radio_obj)
	{
		return "";
	}
	var radioLength = radio_obj.length;
	if (radioLength == undefined)
	{
		if(radio_obj.checked)
		{
			return radio_obj.value;
		}
		else
		{
			return "";
		}
	}
	
	for (var i = 0; i < radioLength; i++)
	{
		if (radio_obj[i].checked)
		{
			return radio_obj[i].value;
		}
	}
	return "";
}

/**
* Checks a radio in a set by value
*
* @param String - name (The name shared by the set)
*
* @param String - newValue (value to set the set to)
*
* @return String - the value checked
* 
*/
function SetRadioValue(name, newValue)
{
	radio_obj = document.getElementsByName(name);
	if (!radio_obj)
	{
		return;
	}
	var radioLength = radio_obj.length;
	if (radioLength == undefined)
	{
		radio_obj.checked = (radio_obj.value == newValue.toString());
		return;
	}
	for (var i = 0; i < radioLength; i++)
	{
		radio_obj[i].checked = false;
		if (radio_obj[i].value == newValue.toString())
		{
			radio_obj[i].checked = true;
		}
	}
}

/**
* Adds and removes CSS classes to a DHTML element
*
* @param Object - elem (The DHTML element)
*
* @param String - addClass (Name of class to add)
*
* @param String - remClass (Name of class to remove)
* 
*/
function ClassChange(elem, addClass, remClass)
{ 
	//Add + remove classnames function by www.hesido.com 
	if (!elem.className)
	{
		elem.className = '';
	}
	var clsnm = elem.className; 
	if (addClass && !clsnm.match(RegExp("\\b"+addClass+"\\b")))
	{
		clsnm = clsnm.replace(/(\S$)/, '$1 ')+addClass;
	}
	if (remClass)
	{
		clsnm = clsnm.replace(RegExp("(\\s*\\b"+remClass+"\\b(\\s*))*", "g"),'$2');
	}
	elem.className=clsnm;
}

//******************************************************************************************************************
// Animation
//..................................................................................................................


/**
* JSUILoadingWidget is a full-screen veil for AJAX applications to disable user interaction while communication
* is in progress.
*
* var veil = new JSUILoadingWidget(); 		// create the object
* window.onload = veil.OnLoadInit;			// initialize it
* veil.Show("Loading, please wait...");	// display the veil, user can't interact with elements below it
* veil.Hide();										// remove the veil, user can now interact with the page again
*
*/

JSUILoadingWidget = function ()
{
	// Constructor for JSUILoadingWidget
	this.container = document.createElement('div');
	this.container.className = 'JSUILoadingWidget';
	this.container.style.width = "400px";
	this.container.style.height = "45px";
	this.container.style.left = (document.body.scrollWidth - 400) / 2;
	this.container.style.top = Math.max(50, (document.body.scrollHeight - 45) / 2 - 200);
	this.container.style.fontSize = "12px";
	this.container.style.border = "1px solid #0D71FD";
	this.container.style.padding = "5px";
	this.container.style.textAlign = "center";
	this.container.style.backgroundColor = "#ffffff";
	this.container.id = "JSUILibLoadingWidget";
	
	var img = document.createElement('img');
	img.src = 'img/JSUI/ajax-loader.gif';
	this.container.appendChild(img);
	
	var txt = document.createTextNode(' Loading, please wait...');
	this.container.appendChild(txt);
	
	this.veil = document.createElement('div');
	this.veil.className = 'JSUILoadingWidget_Veil';
	this.veil.innerHTML = '&nbsp;';
	
	document.body.appendChild(this.container);
	document.body.appendChild(this.veil);
	
	AddListener(window, 'resize', this.UpdateVeilWidth);
}


/**
* Does initialization that should be done after the page is fully loaded
*
* IE cannot add elements to <body> until after </body> is parsed so 
* this initialization has to be done after onload fires
*
* @access public
* 
*/
JSUILoadingWidget.prototype.OnLoadInit = function ()
{
	document.body.appendChild(this.container);
	document.body.appendChild(this.veil);
}

/**
* Displays the veil
*
* @param String - msg (A message to display on the veil)
*
* @access public
* 
*/
JSUILoadingWidget.prototype.Show = function(msg)
{
	DeleteAllChildren(this.container);
	
	var img = document.createElement('img');
	img.src = 'img/JSUI/ajax-loader.gif';
	this.container.appendChild(img);
	
	var txt = document.createTextNode(' ' + msg);
	this.container.appendChild(txt);
	
	var br = document.createElement('br');
	this.container.appendChild(br);
	
	var span = document.createElement('span');
	span.className = 'JSUILoadingWidget_RefreshText';
	var txt2 = document.createTextNode('If this message does not disappear in a few seconds click the refresh button of your browser!');
	span.appendChild(txt2);
	this.container.appendChild(span);
	
	this.container.style.display = "block";
	this.ShowVeil(true);
}

/**
* Hides the veil
*
* @access public
* 
*/
JSUILoadingWidget.prototype.Hide = function()
{
	this.container.style.display = "none";
	this.ShowVeil(false);
}

/**
* Internal function to show/hide the veil.
*
* DO NOT CALL DIRECTLY!
*
* @param bool - show (show or hide the veil?)
*
* @access public
* 
*/
JSUILoadingWidget.prototype.ShowVeil = function(show)
{
	if (show)
	{
		this.UpdateVeilWidth();
		this.veil.style.display = "block";
	}
	else
	{
		this.veil.style.display = "none";
	}
}

/**
* Updates the veil width
*
* Internally hooked to window.onresize
*
* @access public
* 
*/
JSUILoadingWidget.prototype.UpdateVeilWidth = function()
{
	this.veil.style.width = document.body.scrollWidth;
	this.veil.style.height = document.body.scrollHeight;
}

//******************************************************************************************************************
// Misc
//..................................................................................................................

/**
* Attaches an event listener to an object
*
* @param Object - obj (The object to attach to)
*
* @param String - event (The name of the event)
*
* @param Function - func (The function to execute)
*
*/
function AddListener(obj, event, func)
{
	if (obj.addEventListener)
	{
		obj.addEventListener(event, func, false);
	}
	else if (obj.attachEvent)
	{
		obj.attachEvent('on' + event, func);
	}
	else
	{
		return false;
	}
}


/**
* Returns the current unix epoch
*
* @return int - the time since the unix epoch in ms
* 
*/
function GetCurrentMillisecond()
{
	d = new Date();
	return d.getTime();
}


/**
 * trim
 *
 * Strip whitespace from the beginning and end of a string
 *
 * object string
 * return string
 *
 * example:
 *   test = '\nsomestring\n\t\0'
 *   test.trim()  //returns 'somestring'
 */
String.prototype.trim = function()
{
  return this.replace(/^\s*([^ ]*)\s*$/, "$1");
}


/**
 * strPad
 *
 * Pad a string to a certain length with another string
 *
 * This functions returns the input string padded on the left, the right, or both sides
 * to the specified padding length. If the optional argument pad_string is not supplied,
 * the output is padded with spaces, otherwise it is padded with characters from pad_string
 * up to the limit.
 *
 * The optional argument pad_type can be STR_PAD_RIGHT, STR_PAD_LEFT, or STR_PAD_BOTH.
 * If pad_type is not specified it is assumed to be STR_PAD_RIGHT.
 *
 * If the value of pad_length is negative or less than the length of the input string,
 * no padding takes place.
 *
 * object string
 * return string
 *
 * examples:
 *   var input = 'foo';
 *   input.strPad(9);                      // returns "foo      "
 *   input.strPad(9, "*+", STR_PAD_LEFT);  // returns "*+*+*+foo"
 *   input.strPad(9, "*", STR_PAD_BOTH);   // returns "***foo***"
 *   input.strPad(9 , "*********");        // returns "foo******"
 */

var STR_PAD_LEFT  = 0;
var STR_PAD_RIGHT = 1;
var STR_PAD_BOTH  = 2;

String.prototype.strPad = function(pad_length, pad_string, pad_type)
{
	/* Helper variables */
	var num_pad_chars   = pad_length - this.length;/* Number of padding characters */
	var result          = '';                       /* Resulting string */
	var pad_str_val     = ' ';
	var pad_str_len     = 1;                        /* Length of the padding string */
	var pad_type_val    = STR_PAD_RIGHT;            /* The padding type value */
	var i               = 0;
	var left_pad        = 0;
	var right_pad       = 0;
	var error           = false;
	var error_msg       = '';
	var output           = this;

	if (arguments.length < 1 || arguments.length > 3)
	{
		error     = true;
		error_msg = "Wrong parameter count.";
	}


	else if(isNaN(arguments[0]) == true)
	{
		error     = true;
		error_msg = "Padding length must be an integer.";
	}

	/* Setup the padding string values if specified. */
	if (arguments.length > 1)
	{
		if (pad_string.length == 0)
		{
			error     = true;
			error_msg = "Padding string cannot be empty.";
		}
		pad_str_val = pad_string;
		pad_str_len = pad_string.length;

		if (arguments.length > 3)
		{
			pad_type_val = pad_type;
			if (pad_type_val < STR_PAD_LEFT || pad_type_val > STR_PAD_BOTH)
			{
				error     = true;
				error_msg = "Padding type has to be STR_PAD_LEFT, STR_PAD_RIGHT, or STR_PAD_BOTH."
			}
		}
	}

	if(error) throw error_msg;

	if(num_pad_chars > 0 && !error)
	{
		/* We need to figure out the left/right padding lengths. */
		switch (pad_type_val)
		{
			case STR_PAD_RIGHT:
				left_pad  = 0;
				right_pad = num_pad_chars;
				break;

			case STR_PAD_LEFT:
				left_pad  = num_pad_chars;
				right_pad = 0;
				break;

			case STR_PAD_BOTH:
				left_pad  = Math.floor(num_pad_chars / 2);
				right_pad = num_pad_chars - left_pad;
				break;
		}

		for(i = 0; i < left_pad; i++)
		{
			output = pad_str_val.substr(0, num_pad_chars) + output;
		}

		for(i = 0; i < right_pad; i++)
		{
			output += pad_str_val.substr(0, num_pad_chars);
		}
	}

	return output;
}


//******************************************************************************************************************
// GUI Elements
//..................................................................................................................


//........... JSUI_THUMBNAIL_IMAGE ......................................................................
function JSUI_Thumbnail_Image_Highlight(id, on)
{
	e = findDOM(id + '_Thumb_Container');
	if (e)
	{
		if (on)
		{
			// MouseOver
			e_col = findDOM(id + '_Color_Over');
		}
		else
		{
			//MouseOut
			// Gotta see if this is selected or not
			e_val = findDOM(id);
			if (e_val)
			{
				if (e_val.value == '')
				{
					// Not selected
					e_col = findDOM(id + '_Color_Normal');
				}
				else
				{
					// Selected
					e_col = findDOM(id + '_Color_Selected');
				}
			}
		}
		
		if (e_col)
		{
			e.style.borderColor = e_col.value;
		}
	}
}


function JSUI_Thumbnail_Image_OnClick(id, sel_val)
{
	e = findDOM(id + '_Thumb_Container');
	e_val = findDOM(id);
	if (e && e_val)
	{
		if (e_val.value == '')
		{
			// Was not selected
			e_val.value = sel_val;
		}
		else
		{
			// Was selected, deselect it
			e_val.value = '';	
		}
	}
}


//........... ToggleButton ..............................................................................

/**
* Sets the state of a ToggleButton
*
* @param String - id (the id of the button)
*
* @param bool - state (the state to set the button to)
* 
*/
function JSUILib_ToggleButton_SetState(id, state)
{
	//alert(state);
	e = findDOM(id);
	if (state)
	{
		e.value = e.getAttribute("valueOn");
		findDOM(id + '_container').className = "JSUILib_ToggleButton_On"; 
	}
	else
	{
		e.value = e.getAttribute("valueOff");
		findDOM(id + '_container').className = "JSUILib_ToggleButton_Off";
	}
}


/**
* Changes the state of a ToggleButton
*
* @param String - id (the id of the button)
* 
*/
function JSUILib_ToggleButton_Toggle(id)
{
	e = findDOM(id);
	if (e)
	{
		//alert(e.value);
		if (e.value == e.getAttribute("valueOn"))
		{
			JSUILib_ToggleButton_SetState(id, false);
		}
		else
		{
			JSUILib_ToggleButton_SetState(id, true);
		}
	}
}

//........... RadioPushButtons .......................................................................

/**
* Sets the state of a RadioPushButtons set
*
* @param String - id (the id of the set)
*
* @param String - val (the value to set the set to)
* 
*/
function JSUILib_RadioPushButtons_SetState(id, val)
{
	e = findDOM(id);
	if (e)
	{
		e.value = val;
		i = 0;
		while (e = findDOM(id + "_Button_" + i))
		{
			if (val == e.getAttribute("PushValue"))
			{
				e.className = "JSUILib_ToggleButton_On";
			}
			else
			{
				e.className = "JSUILib_ToggleButton_Off";
			}
			
			i++;
		}
	}
}

//........... ColorSwatchSelector .......................................................................

/**
* Shows the selector window of a ColorSwatchSelector
*
* @param String - id (the id of the ColorSwatchSelector)
* 
*/
function JSUILib_ColorSwatchSelector_ShowSelector(id)
{
	var button = findDOM(id + '_Container');
	//var x = GetElementX(button) - 195;
	//var y = GetElementY(button) + 5;
	var x = -1;
	var y = 21;
	
	var selector = findDOM(id + '_SwatchContainer');
	if (selector)
	{
		selector.style.left = x + "px";
		selector.style.top = y + "px";
		//selector.style.zIndex = 21000;
		selector.style.display = 'block';
	}
	else
	{
		alert('Error creating color swatch selector');
	}
}

/**
* Hides the selector window of a ColorSwatchSelector
*
* @param String - id (the id of the ColorSwatchSelector)
*
* @param bool - force (true = try to close the selector again in 100ms)
* 
*/
function JSUI_ColorSwatchSelector_HideSelector(id, force)
{
	var selector = findDOM(id + '_SwatchContainer');
	if (selector)
	{
		selector.style.display = 'none';
	}
	else
	{
		alert('Error finding color swatch selector');
	}
	
	if (force)
	{
		setTimeout('JSUI_ColorSwatchSelector_HideSelector("' + id + '", false)', 100);
	}
}

/**
* Sets the value of a ColorSwatchSelector
*
* @param String - id (the id of the ColorSwatchSelector)
*
* @param String - col (the color to set it to)
* 
*/
function JSUILib_ColorSwatchSelector_SetValue(id, col)
{
	col = col.trim();
	
	var val_field = findDOM(id);
	val_field.value = col;
	
	if (col == '')
	{
		var img = findDOM(id + '_ValueImage');
		img.src = 'img/JSUI/transparent_color.gif';
	}
	else
	{
		var cell = findDOM(id + '_Container');
		cell.style.backgroundColor = col;
		
		var img = findDOM(id + '_ValueImage');
		img.src = 'img/JSUI/blank.gif';
	}
	
	JSUI_ColorSwatchSelector_HideSelector(id, true);
}

/**
* Event handler for when mouse moves over a color swatch
*
* @param String - id (the id of the ColorSwatchSelector)
*
* @param String - col (the color the mouse moved over)
* 
*/
function JSUILib_ColorSwatchSelector_OnMouseOverColor(id, col)
{
	JSUILib_ColorSwatchSelector_PreviewColor(id, col);
}

/**
* Event handler for when mouse clicks a color swatch
*
* @param String - id (the id of the ColorSwatchSelector)
*
* @param String - col (the color the mouse clicked)
* 
*/
function JSUILib_ColorSwatchSelector_OnClickColor(id, col)
{
	JSUILib_ColorSwatchSelector_SetValue(id, col);
}

/**
* Event handler for keypresses in the custom value box
*
* @param String - id (the id of the ColorSwatchSelector)
*
* @param Event - ev (the keyup event)
* 
*/
function JSUILib_ColorSwatchSelector_OnKeyUp(id, ev)
{
	var input = findDOM(id + '_Input');
	var col = input.value;
	if (col.length != 0)
	{
		col = col.strPad(7, '0');
	}
	
	if (window.event) //IE
	{
		keynum = ev.keyCode;
	}
	else	// Firefox/Netscape/opera
	{
		keynum = ev.which;
	}
	
	if (keynum == KEYCODE_ENTER)
	{
		JSUILib_ColorSwatchSelector_SetValue(id, col);
	}
	else
	{
		JSUILib_ColorSwatchSelector_PreviewColor(id, col);
	}
}


/**
* Previews a color in the ColorSwatchSelector
*
* @param String - id (the id of the ColorSwatchSelector)
*
* @param String - col (the color)
* 
*/
function JSUILib_ColorSwatchSelector_PreviewColor(id, col)
{
	//alert(col);
	var preview = findDOM(id + '_PreviewColor');
	var img = findDOM(id + '_PreviewImage');
	if (col == '')
	{
		img.src = 'img/JSUI/transparent_color.gif';
	}
	else
	{
		preview.style.backgroundColor = col;
		img.src = 'img/JSUI/blank.gif';
	}
	
	var input = findDOM(id + '_Input');
	input.value = col;
}



/**
* Erases the value of a DeletableDefault control
*
* @param String - id (the id of the DeletableDefault control)
* 
*/
function JSUILib_DeletableDefault_DeleteValue(id)
{
	display = findDOM(id + '_Display');
	button = findDOM(id + '_Img');
	e = findDOM(id);
	
	display.innerHTML = 'None';
	button.style.display = 'none';
	e.value = 'NULL';
}




//........... ImageStrip ................................................................................

var JSUI_ImageStrip_Scrollers = new Array();

/**
* Starts scrolling the ImageStrip
*
* @param String - id (the id of the ImageStrip)
* 
*/
function JSUI_ImageStrip_StartScroll(id, pace, delay, mode)
{
	JSUI_ImageStrip_Move(id, pace, delay, mode);
}

function JSUI_ImageStrip_StopScroll(id)
{
	try
	{
		clearTimeout(JSUI_ImageStrip_Scrollers[id]);
	}
	catch (e)
	{
	}
}


function JSUI_ImageStrip_Move(id, pace, delay, mode)
{
	//alert('x');
	ef = $(id + '_FlexLayer');
	ec = $(id + '_Container');
	if (ef && ec)
	{
		flex_w = ef.offsetWidth;
		flex_x = parseInt(ef.style.left);
		cont_w = ec.offsetWidth;
		
		ok = JSUI_ImageStrip_UpdateButtons(id, flex_w, flex_x, cont_w, pace, mode);
		//alert(ok);
		
		if (!ok)
		{
			return;
		}
		
		if (pace == 0)
		{
			return;
		}
		
		e = $(id + '_FlexLayer');
		if (e)
		{
			x = parseInt(e.style.left);
			//alert(x);
			x += pace;
			//alert(x);
			e.style.left = x + 'px';
		}
		else
		{
			//alert('No flex layer');
		}
		
		JSUI_ImageStrip_Scrollers[id] = setTimeout("JSUI_ImageStrip_Move('" + id + "', " + pace + ", " + delay + ", " + mode + ");", delay);
	}
	else
	{
		//alert(ef + '|' + ec);
	}
}

function JSUI_ImageStrip_ShowImage(id, linked_id, i)
{
	et = $(id + '_Img_' + i);
	ei = $(linked_id);
	if (et && ei)
	{
		ei.src = et.src;
	}
	else
	{
		//alert(er + '|' + ei);
	}
}

function JSUI_ImageStrip_UpdateButtons(id, flex_w, flex_x, cont_w, pace, mode)
{
	//window.defaultStatus = flex_w + ", " + flex_x + ", " + cont_w + ", " + pace;
	
	el = $(id + '_Left');
	er = $(id + '_Right');
	
	result = true;
	
	if (el)
	{
		if (flex_x >= 0)
		{
			if (el.style.opacity == 1.00 || el.style.opacity == '')
			{
				JSUI_ImageStrip_SetButtonState(el, false, mode);
			}
			
			if (pace > 0)
			{
				result = false;
			}
		}
		else
		{
			if (el.style.opacity == 0.40 || el.style.opacity == '')
			{
				JSUI_ImageStrip_SetButtonState(el, true, mode);
			}
		}
	}
	else
	{
		//alert("Missing EL");
	}
	
	if (er)
	{
		if (flex_x + flex_w <= cont_w)
		{
			if (er.style.opacity == 1.00 || er.style.opacity == '')
			{
				JSUI_ImageStrip_SetButtonState(er, false, mode);
			}
			
			if (pace < 0)
			{
				result = false;
			}
		}
		else
		{
			if (er.style.opacity == 0.40 || er.style.opacity == '')
			{
				JSUI_ImageStrip_SetButtonState(er, true, mode);
			}
		}
	}
	else
	{
		//alert("Missing ER");
	}
	
	return result;
}


function JSUI_ImageStrip_SetButtonState(e, state, mode)
{
	if (mode == 2) // Hide mode
	{
		if (state)
		{
			e.style.visibility = 'visible';
		}
		else
		{
			e.style.visibility = 'hidden';
		}
	}
	else if (mode == 1)
	{
		if (state)
		{
			e.style.opacity = 1.00;
    		e.style.MozOpacity = 1.00;
    		e.style.KhtmlOpacity = 1.00;
    		e.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=100)";
		}
		else
		{
			e.style.opacity = 0.40;
    		e.style.MozOpacity = 0.40;
    		e.style.KhtmlOpacity = 0.40;
    		e.style.filter = "progid:DXImageTransform.Microsoft.alpha(opacity=40)";
		}
	}
	else
	{
		alert('Unknown button mode');
	}
}



//******************************************************************************************************************
// AJAX
//..................................................................................................................


/**
* It creates a request object and it sends the request to the server, it also sets the function to handle the 
* returned data.
*
* @param String - url (is the url of the server site script that will return the data)
* @param String - action (GET, POST, HEADER (to get only the header info about the url))
* @param String - process_function (the javascript function that will handle the data returned from the server)
* 
* @return null
*/
// request object
var JSUI_req;

function JSUI_request_data(url, action, process_function) 
{
	JSUI_req = null;
	// branch for native XMLHttpRequest object
	if(window.XMLHttpRequest) 
	{
		try 
		{
			JSUI_req = new XMLHttpRequest();
		} 
		catch(e) 
		{
			JSUI_req = false;
		}    
	} 
	// branch for IE/Windows ActiveX version
	else if(window.ActiveXObject) 
	{
		try 
		{
			JSUI_req = new ActiveXObject("Msxml2.XMLHTTP");
		} 
		catch(e) 
		{
			try 
			{
				JSUI_req = new ActiveXObject("Microsoft.XMLHTTP");
			} 
			catch(e) 
			{
				JSUI_req = false;
			}
		}
	}
	
	// if object created successfully then send the request
	if (JSUI_req) 
	{
		JSUI_req.onreadystatechange = eval(process_function);
		JSUI_req.open(action, url, true);
		JSUI_req.send("");
	}
} 


// AJAX
// http://www.bigbold.com/snippets/posts/show/2025
/*How to use:

ajax.x - The XMLHttpRequest object (or MS equivalent) used for communication

ajax.serialize(f)
f = the form element you wish to be serialized
This function serializes all the fields in a form so that they can be passed as a query string in the form "arg1=val1&arg2=val2".

ajax.get(url, func)
url = the url to query (can contain arguments after a '?')
func = the function to call once the response is returned
This function uses a GET request to query the specified url and return a response to the specified function.

ajax.gets(url)
url = the url to query (can contain arguments after a '?')
This function uses a GET request to query the specified url and return a response synchronously. Use this sparingly, as synchronous calls can lock up the browser.

ajax.post(url, func, args)
url = the url to query
func = the function to call once the response is returned
args = a string containing arguments to be passed to the url
This function uses a POST request to query the specified url and return a response to the specified function.

ajax.update(url, elm)
url = the url to query
elm = the (name of the) element to update
This function uses a GET request to query the specified url and insert the result into the specified element.

ajax.submit(url, elm, frm)
url = the url to query
elm = the (name of the) element to update
frm = the form element to submit
This function is typically used in the onsubmit handler of a function. The form is not submitted the usual way; the form is instead serialized using "ajax.serialize" and submitted using "ajax.post". The result is then inserted into the specified element.*/

function $(e){if(typeof e=='string')e=document.getElementById(e);return e};

function collect(a, f)
{
	var n = [];
	for (var i = 0; i < a.length; i++)
	{
		var v = f(a[i]);
		if (v != null)
			n.push(v);
	}
	return n;
};

ajax={};

ajax.x = function() 
{
	try
	{
		return new ActiveXObject('Msxml2.XMLHTTP');
	}
	catch (e)
	{
		try
		{
			return new ActiveXObject('Microsoft.XMLHTTP');
		}
		catch (e)
		{
			return new XMLHttpRequest()
		}
	}
};

ajax.serialize = function(f)
{
	var g = function(n)
				{
					return f.getElementsByTagName(n)
				};
	var nv = function(e)
				{
					if (e.name)
						return encodeURIComponent(e.name) + '=' + encodeURIComponent(e.value);
					else
						return '';
				};
	var i = collect(g('input'), 
						function(i)
						{
							if ((i.type != 'radio' && i.type != 'checkbox') || i.checked)
								return nv(i);
						}
			);
	var s = collect(g('select'), nv);
	var t = collect(g('textarea'), nv);
	
	return i.concat(s).concat(t).join('&');
};

ajax.send = function(u, f, m, a)
{
	var x = ajax.x();
	x.open(m, u, true);
	x.onreadystatechange = function()
	{
		if (x.readyState == 4)
		{
			f(x.responseText);
		}
	};
	if (m == 'POST' )
	{
		x.setRequestHeader('Content-type','application/x-www-form-urlencoded');
	}
	x.send(a);
};

ajax.get = function(url, func)
{
	ajax.send(url, func, 'GET');
};

ajax.gets=function(url){var x=ajax.x();x.open('GET',url,false);x.send(null);return x.responseText};
ajax.post=function(url,func,args){ajax.send(url,func,'POST',args)};

ajax.update = function(url, elm)
{
	var e = $(elm);
	var f = function(r)
	{
		e.innerHTML = r;
	};
	ajax.get(url, f);
};

ajax.submit=function(url, elm, frm)
{
	var e = $(elm);
	var f = function(r)
	{
		e.innerHTML = r;
	};
	ajax.post(url, f, ajax.serialize(frm))
};

ajax.doForm = function(url, func, frm)
{
	ajax.post(url, func, ajax.serialize($(frm)));
}
