function insertNodeAtSelection(win, insertNode)
{
	// get current selection
	var sel = win.getSelection();
	
	// get the first range of the selection
	// (there's almost always only one range)
	var range = sel.getRangeAt(0);
	
	// deselect everything
	sel.removeAllRanges();
	
	// remove content of current selection from document
	range.deleteContents();
	
	// get location of current selection
	var container = range.startContainer;
	var pos = range.startOffset;
	
	// make a new range for the new selection
	range = document.createRange();
	
	if (container.nodeType==3 && insertNode.nodeType==3) {
	
		// if we insert text in a textnode, do optimized insertion
		container.insertData(pos, insertNode.nodeValue);
	
		// put cursor after inserted text
		range.setEnd(container, pos+insertNode.length);
		range.setStart(container, pos+insertNode.length);
	
	} else {
	
	    var afterNode;
	    
	    if (container.nodeType==3) {
	
	      // when inserting into a textnode
	      // we create 2 new textnodes
	      // and put the insertNode in between
	
	      var textNode = container;
	      container = textNode.parentNode;
	      var text = textNode.nodeValue;
	
	      // text before the split
	      var textBefore = text.substr(0,pos);
	      // text after the split
	      var textAfter = text.substr(pos);
	
	      var beforeNode = document.createTextNode(textBefore);
	      var afterNode = document.createTextNode(textAfter);
	
	      // insert the 3 new nodes before the old one
	      container.insertBefore(afterNode, textNode);
	      container.insertBefore(insertNode, afterNode);
	      container.insertBefore(beforeNode, insertNode);
	
	      // remove the old node
	      container.removeChild(textNode);
	    } else {
	
	      // else simply insert the node
	      afterNode = container.childNodes[pos];
	      container.insertBefore(insertNode, afterNode);
	    }

		range.setEnd(afterNode, 0);
		range.setStart(afterNode, 0);
	}
	 
	sel.addRange(range);
}

function insertAtCursor(myValue,ctrl_id)
{
	var pln_txt = window.opener.document;
	var myField = pln_txt.getElementById(ctrl_id);

	//IE support
	if (pln_txt.selection) {
		myField.focus();
		sel = pln_txt.selection.createRange();
		sel.text = myValue;
	}
	//MOZILLA/NETSCAPE support
	else if (myField.selectionStart || myField.selectionStart == '0') {
		var startPos = myField.selectionStart;
		var endPos = myField.selectionEnd;
		myField.value = myField.value.substring(0, startPos)
			+ myValue
			+ myField.value.substring(endPos, myField.value.length);
	} else {
		myField.value += myValue;
	}
	
	window.close();
}

function getQueryVariable(variable) {
  var query = window.location.search.substring(1);
  var vars = query.split("&");
  for (var i=0;i < vars.length;i++) {
    var pair = vars[i].split("=");
    if (pair[0] == variable) {
      return pair[1];
    }
  } 
  return "";
}

function trim(inputString) {
   // Removes leading and trailing spaces from the passed string. Also removes
   // consecutive spaces and replaces it with one space. If something besides
   // a string is passed in (null, custom object, etc.) then return the input.
   if (typeof inputString != "string") return inputString;
   var retValue = inputString;
   var ch = retValue.substring(0, 1);
	
   while (ch == " ") { // Check for spaces at the beginning of the string
      retValue = retValue.substring(1, retValue.length);
      ch = retValue.substring(0, 1);
   }
   ch = retValue.substring(retValue.length-1, retValue.length);
	
   while (ch == " ") { // Check for spaces at the end of the string
      retValue = retValue.substring(0, retValue.length-1);
      ch = retValue.substring(retValue.length-1, retValue.length);
   }
	
	// Note that there are two spaces in the string - look for multiple spaces within the string
   while (retValue.indexOf("  ") != -1) {
		// Again, there are two spaces in each of the strings
      retValue = retValue.substring(0, retValue.indexOf("  ")) + retValue.substring(retValue.indexOf("  ")+1, retValue.length);
   }
   return retValue; // Return the trimmed string back to the user
}

function popup(page,popupname,width,height,scroll,resize) {
   var windowprops = 'width=' + width + ',height=' + height + 
   					 ',location=no,status=no,menubar=no,toolbar=no,scrollbars=' + scroll + 
   					 ',resizable=' + resize;
   newWindow = window.open(page,popupname,windowprops);
}

function isMSIE()
{
	var ua = navigator.userAgent.toLowerCase();
	
	var isMSIE = ((ua.indexOf("msie") != -1) && 
				  (ua.indexOf("opera") == -1) && 
				  (ua.indexOf("webtv") == -1));
	
	return isMSIE;
}

function URLEncode(str)
{
	// The Javascript escape and unescape functions do not correspond
	// with what browsers actually do...
	var SAFECHARS = "0123456789" +					// Numeric
					"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +	// Alphabetic
					"abcdefghijklmnopqrstuvwxyz" +
					"-_.!~*'()";					// RFC2396 Mark characters
	var HEX = "0123456789ABCDEF";

	var encoded = "";
	for (var i = 0; i < str.length; i++ ) {
		var ch = str.charAt(i);
	    if (ch == " ") {
		    encoded += "+";				// x-www-urlencoded, rather than %20
		} else if (SAFECHARS.indexOf(ch) != -1) {
		    encoded += ch;
		} else {
		    var charCode = ch.charCodeAt(0);
			if (charCode > 255) {
				return encoded;
			} else {
				encoded += "%";
				encoded += HEX.charAt((charCode >> 4) & 0xF);
				encoded += HEX.charAt(charCode & 0xF);
			}
		}
	} // for

	return encoded;
}

function URLDecode(str)
{
   // Replace + with ' '
   // Replace %xx with equivalent character
   // Put [ERROR] in output if %xx is invalid.
   var HEXCHARS = "0123456789ABCDEFabcdef"; 
   var encoded = str;
   var plaintext = "";
   var i = 0;
   while (i < encoded.length) {
       var ch = encoded.charAt(i);
	   if (ch == "+") {
	       plaintext += " ";
		   i++;
	   } else if (ch == "%") {
			if (i < (encoded.length-2) 
					&& HEXCHARS.indexOf(encoded.charAt(i+1)) != -1 
					&& HEXCHARS.indexOf(encoded.charAt(i+2)) != -1 ) {
				plaintext += unescape( encoded.substr(i,3) );
				i += 3;
			} else {
				i++;
			}
		} else {
		   plaintext += ch;
		   i++;
		}
	} // while
   
   return plaintext;
}

// Cookie functions
function setCookie(name, value, expires, path, domain, secure) {
  var curCookie = name + "=" + escape(value) +
      ((expires) ? "; expires=" + expires.toGMTString() : "") +
      ((path) ? "; path=" + path : "") +
      ((domain) ? "; domain=" + domain : "") +
      ((secure) ? "; secure" : "");
  document.cookie = curCookie;
}

function getCookie(name) {
  var dc = document.cookie;
  var prefix = name + "=";
  var begin = dc.indexOf("; " + prefix);
  if (begin == -1) {
    begin = dc.indexOf(prefix);
    if (begin != 0) return null;
  } else
    begin += 2;
  var end = document.cookie.indexOf(";", begin);
  if (end == -1)
    end = dc.length;
  return unescape(dc.substring(begin + prefix.length, end));
}

function deleteCookie(name, path, domain) {
  if (getCookie(name)) {
    document.cookie = name + "=" +
    ((path) ? "; path=" + path : "") +
    ((domain) ? "; domain=" + domain : "") +
    "; expires=Thu, 01-Jan-70 00:00:01 GMT";
  }
}

/**
 * Toggle checkbox object
 */
function toggleCheckBox()
{
	this.id_arr = [];
	
	this.addId = function (id) {
		this.id_arr[this.id_arr.length] = id;
	};
	
	this.toggleAll = function () { 
		this.processAll('t'); 
	};
	
	this.checkAll = function () { 
		this.processAll('c'); 
	};
	
	this.unCheckAll = function () { 
		this.processAll('u'); 
	};
	
	this.processAll = function (prcs_type) {
		for (var i = 0;i < this.id_arr.length;i++) {
			var chk_bx = document.getElementById(this.id_arr[i]);
			
			switch (prcs_type) {
				case 't':
				chk_bx.checked = !chk_bx.checked;
				break;
				
				case 'c':
				chk_bx.checked = true;
				break;
				
				case 'u':
				chk_bx.checked = false;
				break;
			}
		}
	}
}

/**
 * A class that makes 1 SELECT control dependent on another
 */
function dependentSelect(f_ctrl_id,t_ctrl_id)
{
	this.t_optns_arr = [];
	
	this.f_ctrl = document.getElementById(f_ctrl_id);
	this.t_ctrl = document.getElementById(t_ctrl_id);
	
	this.addOption = function (f_val,t_val,t_txt) {
		if (arguments.length > 3) { 
			var is_sel = arguments[3];
		} else {
			var is_sel = false;
		}
		
		if (!this.t_optns_arr[f_val]) this.t_optns_arr[f_val] = [];
				
		this.t_optns_arr[f_val][this.t_optns_arr[f_val].length] = new Array(t_txt,t_val,is_sel);
	}
	
	this.addOptions = function (optns_arr) {
		this.t_optns_arr = optns_arr;
	}
	
	this.clearDependent = function () {
		this.t_ctrl.options.length = 0;
	}
	
	this.clone = function (new_f_ctrl_id,new_t_ctrl_id) {
		var dpdnt_sel = new dependentSelect(new_f_ctrl_id,new_t_ctrl_id);
		dpdnt_sel.addOptions(this.t_optns_arr);
		return dpdnt_sel;
	}
	
	this.change = function (indp_val) {
		this.clearDependent();
		
		if (this.t_optns_arr[indp_val]) {
			var options = this.t_ctrl.options
			
			for (var i = 0; i < this.t_optns_arr[indp_val].length; i++) {
				var tmp_arr = this.t_optns_arr[indp_val][i];
				if (!tmp_arr[0]) tmp_arr[0] = '';
				options[options.length] = new Option(tmp_arr[0],tmp_arr[1],false,tmp_arr[2]);
			}
		} else {
			/* Needs this for MSIE */
			if (isMSIE()) this.t_ctrl.options[0] = new Option('','',false);
		}
	}
	
	this.sync = function (dpd_val) {
		if (this.f_ctrl) this.change(this.f_ctrl.value);
		if (dpd_val) this.t_ctrl.value = dpd_val;
	}
	
	var dpd_sel = this;
	
	if (this.f_ctrl) this.f_ctrl.onchange = function () {
		dpd_sel.change(this.value);
	}
}

/**
 * Change the date on a date control
 */
function changeDateControl(ctrl_id,yr,mth,dy)
{
	var dt_ctrl = document.getElementById(ctrl_id);
	var tmp_node, node_type;
	
	for (var i = 0; i < dt_ctrl.childNodes.length; i++) {
		tmp_node = dt_ctrl.childNodes[i];
		
		if (tmp_node.nodeName.toUpperCase() == 'SELECT') {
			
			node_type = tmp_node.id.slice(ctrl_id.length);
			
			if (node_type == '_dy') {
				tmp_node.value = dy;
			} else if (node_type == '_mth') {
				tmp_node.value = mth;
			} else if (node_type == '_yr') {
				tmp_node.value = yr;
			}
		}
	}
	
	return false;
}

//***********************Begin Quirks Mode*************************
/** 
 * Find the rendered position of an element.
 */
function findPosX(obj)
{
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

/**
 * Finds the viewport's rendered width and height
 */
function findWindowInnerDim()
{
	var x,y;
	if (self.innerHeight) {
		// all except Explorer
		x = self.innerWidth;
		y = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientHeight) {
		// Explorer 6 Strict Mode
		x = document.documentElement.clientWidth;
		y = document.documentElement.clientHeight;
	}
	else if (document.body) {
		// other Explorers
		x = document.body.clientWidth;
		y = document.body.clientHeight;
	}
	return {'x': x, 'y': y};
}

/**
 * Finds the viewport's scroll offset
 */
function findWindowScrollOffset()
{
	var x,y;
	if (self.pageYOffset) { 
		// all except Explorer
		x = self.pageXOffset;
		y = self.pageYOffset;
	}
	else if (document.documentElement && document.documentElement.scrollTop) {
		// Explorer 6 Strict
		x = document.documentElement.scrollLeft;
		y = document.documentElement.scrollTop;
	}
	else if (document.body) {
		// all other Explorers
		x = document.body.scrollLeft;
		y = document.body.scrollTop;
	}
	
	return {'x': x, 'y': y};
}
//***********************End Quirks Mode*************************

/**
 * Cross browser event attaching
 */
function addEvent(obj,evt,fnc,useCapture)
{
	if (!useCapture) useCapture=false;
	if (obj.addEventListener){
		obj.addEventListener(evt,fnc,useCapture);
		return true;
	} else if (obj.attachEvent) return obj.attachEvent("on"+evt,fnc);
}

/**
 * Use this alert message box to indicate
 * that an Ajax call is being conducted.
 */
function AlertMessage()
{
	var bdy;
	
	if (arguments.length > 0) {
		var elem = arguments[0];
		if (typeof elem == 'string') {
			bdy = document.getElementById(elem);
		} else {
			bdy = elem;
		}
	} else {
		bdy = document.getElementsByTagName('body')[0];
	}
	
	var msg_box = document.createElement('div');
	
	bdy.appendChild(msg_box);
	
	this.close = function () {
		setTimeout(function () { msg_box.style.display = 'none' },100); // Deal with IE weirdness
	}
	
	this.display = function (msg) {
		msg_box.innerHTML = msg;
		msg_box.style.display = 'block';
		this.position();
	}
	
	this.getAlertMessageObject = function () { 
		return msg_box; 
	}
	
	this.position = function () {
		msg_box.style.position = 'absolute';
		msg_box.style.top   = (findWindowScrollOffset().y + 10) + 'px';
		msg_box.style.right = '10px';
	}
	
	var this_obj = this;
	
	// Put the position() method in a function which allows over-riding
	addEvent(window,'resize',function () { this_obj.position() });
	addEvent(window,'scroll',function () { this_obj.position() });
	
	this.close();
}

/**
 * Creates an informational message box that uses 
 * yellow-fade-technique.
 */
function InfoMessage()
{
	var msg = new AlertMessage();
	
	this.tm = 300;
	
	// Over-riding position function 
	msg.position = function () {
		var msg_box = msg.getAlertMessageObject();
		
		var wd = msg_box.offsetWidth;
		var ht = msg_box.offsetHeight;
		
		msg_box.style.position = 'absolute';
		msg_box.style.top  = (Math.round((findWindowInnerDim().y - ht)/2) + findWindowScrollOffset().y) + 'px';
		msg_box.style.left = (Math.round((findWindowInnerDim().x - wd)/2) + findWindowScrollOffset().x) + 'px';
	}
	
	this.display = function (html) {
		msg.display(html);
		
		var obj = msg.getAlertMessageObject();
		
		var f_stp = new Array( 
			'ff','ee','dd','cc','bb','aa','99','88','77','66','55'
		);
		
		var stp_cnt = f_stp.length - 1;
		
		var tm = this.tm;
		
		var fade = function () {
			if (stp_cnt > -1) {
				obj.style.backgroundColor = '#ffff' + f_stp[stp_cnt];
				
				if (stp_cnt > 0) {
				    stp_cnt--;
					setTimeout(fade,tm);
				} else {
					obj.style.backgroundColor = 'transparent';
					msg.close();
				}
			}
		}
		
		fade();
	}
	
	this.setCSSClass = function (clss_nm) {
		msg.getAlertMessageObject().className = clss_nm;
	}
	
	this.setTiming = function (tm) {
		this.tm = tm;
	}
}

/**
 * Type determining functions from Crockford
 */
function isAlien(a) {
   return isObject(a) && typeof a.constructor != 'function';
}

function isArray(a) {
    return isObject(a) && a.constructor == Array;
}

function isBoolean(a) {
    return typeof a == 'boolean';
}

function isEmpty(o) {
    var i, v;
    if (isObject(o)) {
        for (i in o) {
            v = o[i];
            if (isUndefined(v) && isFunction(v)) {
                return false;
            }
        }
    }
    return true;
}

function isFunction(a) {
    return typeof a == 'function';
}

function isNull(a) {
    return typeof a == 'object' && !a;
}

function isNumber(a) {
    return typeof a == 'number' && isFinite(a);
}

function isObject(a) {
    return (a && typeof a == 'object') || isFunction(a);
}

function isString(a) {
    return typeof a == 'string';
}

function isUndefined(a) {
	return typeof a == 'undefined';
} 

function isDefined(variable)
{
	return (typeof(window[variable]) == "undefined") ? false : true;
}

/**
 * A singleton to hold all other singleton objects
 */
var SingletonStore = {
	obj_arr: [],
	
	hasSingleton: function (obj_nm) {
		return (typeof(this.obj_arr[obj_nm]) == 'undefined') ? false : true;
	},
	
	retrieve: function (obj_nm) {
		if (this.hasSingleton(obj_nm)) {
			return this.obj_arr[obj_nm];
		} else {
			return null;
		}
	},
	
	store: function (obj_nm,obj) {
		this.obj_arr[obj_nm] = obj;
	}
}

/**
 * 
 */
 
var HTTPRequest = Class.create();

HTTPRequest.prototype = {
	
	initialize: function (url,mthd,func) {
		this.url  = url;
		this.mthd = mthd;
		this.func = [];
		
		if (isFunction(func)) {
			this.func.onComplete = func;
		} else if (func.onLoading || func.onComplete) {
			this.func.onComplete = func.onComplete || false;
			this.func.onLoading  = func.onLoading || false;
		} else {
			this.func.onLoading  = false;
			this.func.onComplete = false;
		}
	},
	
	request: function () {
		
		var params = {};
		
		/*if (arguments.length == 0) {
			return;
		} else */
		if (arguments.length == 1 && isArray(arguments[0])) {
			params = arguments[0];
		} else {
			for (var i = 0; i < arguments.length; i++) {
				var key;
				if (i % 2 == 0) {
					key = arguments[i];
				} else {
					params[key] = arguments[i];
				}
			}
		}
		
		params['_AJAX_REQ_'] = '1';
		params = $H(params).toQueryString();
		
		var http_req = this;
		
		new Ajax.Request(this.url, {
			method: this.mthd.toLowerCase(),
			asynchronous: true,
			parameters: params,
			onLoading: function (request_obj) {
				if (http_req.func.onLoading) http_req.func.onLoading(request_obj);
			},
			onComplete: function (request_obj) {
				if (http_req.func.onComplete) http_req.func.onComplete(request_obj);
			}
		})
	}
}

function form_submit(event,func) 
{
	var element = Event.element(event);
	var params  = [];
	var butns   = [];
	var sbmt_butn = '';
	
	if (element.nodeName.toLowerCase() == 'form') {
		var form_to_query_string = function (object) {
			if (object.nodeType == '3' || !object.childNodes || object.childNodes.length == 0) return;
			
			for (var i = 0; i < object.childNodes.length; i++) {
				var child = object.childNodes[i];
				if (child.nodeName.toLowerCase() == 'input' || 
					child.nodeName.toLowerCase() == 'textarea' || 
					child.nodeName.toLowerCase() == 'select') {
					
					if (child.name != '_SBMT_BUTN_') {
						switch (child.type.toLowerCase()) {
							case 'submit':
								butns[butns.length] = child.name;
							case 'hidden':
							case 'password':
							case 'text':
							case 'textarea':
								params[child.name] = child.value;
								break;
							case 'checkbox':
							case 'radio':
								if (child.checked) params[child.name] = child.value;
								break;
							case 'select-one':
							case 'selectMany':
								var srlz_arr = Form.Element.Serializers.select(child);
								params[srlz_arr[0]] = srlz_arr[1];
								break;
						}
					} else {
						sbmt_butn = child.value;
					}
				} else {
					form_to_query_string(child);
				}
			}
			return;
		}
		
		// Presubmit function
		if (func && func.presubmit) {
			var ret_val = func.presubmit.bind(element)();
			if (ret_val == false && ret_val != null) return false;
		}
		
		if (func.onLoading || func.onComplete) {
			
			if (!func.__onLoading) func.__onLoading = func.onLoading || function () {};
			func.onLoading = func.__onLoading.bind(element);
			
			if (!func.__onComplete) func.__onComplete = func.onComplete || function () {};
			func.onComplete = func.__onComplete.bind(element);
		}
		
		form_to_query_string(element);
		
		// Remove buttons that are not pressed
		for (var i = 0; i < butns.length; i++) {
			if (sbmt_butn != butns[i]) delete params[butns[i]];
		}
		
		var http_req = new HTTPRequest(element.action,element.method,func);
		
		http_req.request(params);
	}
	
	return false;
}

function link_submit(event,mthd,func)
{
	var element = Event.element(event);
	
	// Make sure the clicked on element is a link.
	while (element.nodeName.toLowerCase() != 'a') element = element.parentNode;
	
	var params = [];
	
	// Presubmit function
	if (func && func.presubmit) {
		var ret_val = func.presubmit.bind(element)();
		if (ret_val == false && ret_val != null) return false;
	}
	
	if (func.onLoading || func.onComplete) {
		
		if (!func.__onLoading) func.__onLoading = func.onLoading || function () {};
		func.onLoading = func.__onLoading.bind(element);
		
		if (!func.__onComplete) func.__onComplete = func.onComplete || function () {};
		func.onComplete = func.__onComplete.bind(element);
	}
	
	var http_req = new HTTPRequest(element.href,mthd,func);
	
	if (element.attributes['param_name'])
		params[element.attributes['param_name'].value] = element.attributes['param_val'];
	
	http_req.request(params);
	
	return false;
}

function button_submit(event,mthd,href,func)
{
	var element = Event.element(event);
	var params  = [];
	
	// Presubmit function
	if (func && func.presubmit) {
		var ret_val = func.presubmit.bind(element)();
		if (ret_val == false && ret_val != null) return false;
	}
	
	if (func.onLoading || func.onComplete) {
		
		if (!func.__onLoading) func.__onLoading = func.onLoading || function () {};
		func.onLoading = func.__onLoading.bind(element);
		
		if (!func.__onComplete) func.__onComplete = func.onComplete || function () {};
		func.onComplete = func.__onComplete.bind(element);
	}
	
	var http_req = new HTTPRequest(href,mthd,func);
	
	if (element.attributes['param_name'])
		params[element.attributes['param_name'].value] = element.attributes['param_val'].value;
	
	http_req.request(params);
	
	return false;
}

function checkbox_submit(event,mthd,href,func) 
{
	var element = Event.element(event);
	var params  = [];
	
	// Presubmit function
	if (func && func.presubmit) {
		var ret_val = func.presubmit.bind(element)();
		if (ret_val == false && ret_val != null) return false;
	}
	
	if (func.onLoading || func.onComplete) {
		
		if (!func.__onLoading) func.__onLoading = func.onLoading || function () {};
		func.onLoading = func.__onLoading.bind(element);
		
		if (!func.__onComplete) func.__onComplete = func.onComplete || function () {};
		func.onComplete = func.__onComplete.bind(element);
	}
	
	var http_req = new HTTPRequest(href,mthd,func);
	
	if (element.attributes['param_name']) {
		params[element.attributes['param_name'].value] = element.value;
	} else if (element.attributes['value']) {
		params['value'] = element.value;
	} else if (element.name) {
		params[element.name] = element.value;
	}
	
	http_req.request(params);
	
	return true;
}

function select_submit(event,mthd,href,func)
{
	return checkbox_submit(event,mthd,href,func);
}

function getAlertBox ()
{
	var alrt_msg;
	
	if (!SingletonStore.hasSingleton('alrt_msg')) {
		alrt_msg = new AlertMessage();
		SingletonStore.store('alrt_msg',alrt_msg);
	} else {
		alrt_msg = SingletonStore.retrieve('alrt_msg');
	}
	
	if (arguments.length > 0) {
		alrt_msg.getAlertMessageObject().className = arguments[0];
	}
	
	return alrt_msg;
}

function getInfoBox ()
{
	var info_msg;
	
	if (!SingletonStore.hasSingleton('info_msg')) {
		info_msg = new InfoMessage();
		SingletonStore.store('info_msg',info_msg);
	} else {
		info_msg = SingletonStore.retrieve('info_msg');
	}
	
	if (arguments[0]) info_msg.setCSSClass(arguments[0]);
	
	info_msg.setTiming(arguments[1] || 300);
	
	return info_msg;
}

var FunctionRegistry = {
	
	func_arr: [],
	
	register: function (func_nm,func) {
		this.func_arr[func_nm] = func;
	},
	
	retrieve: function (func_nm) {
		return this.func_arr[func_nm];
	}
}

function yellow_fade (object,tm) 
{
	object = $(object);
	
	var curr_bg = object.style.backgroundColor;
	
	var f_stp = new Array( 
		'ff','ee','dd','cc','bb','aa','99','88','77','66','55'
	);
	
	var stp_cnt = f_stp.length - 1;
	
	var fade_step = function () {
		if (stp_cnt > -1) {
			object.style.backgroundColor = '#ffff' + f_stp[stp_cnt];
			
			if (stp_cnt > 0) {
			    stp_cnt--;
				setTimeout(fade_step,tm);
			} else {
				object.style.backgroundColor = curr_bg;
			}
		}
	}
	
	fade_step();
}

/**
 * Changing the Element.scrollTo in incorporate smooth scrolling.
 */
 Element.scrollTo = function (element, options) {
 	element = $(element);
    
    var coords = Position.cumulativeOffset(element);
    var x = coords[0];
    var y = coords[1];
    
    if (options) {
    	
    	var interval = options['interval'] || 20;
    	var movement = options['movement'] || 20;  
    	
    	Position.prepare();
    	var start_x = Position.deltaX;
    	var start_y = Position.deltaY;
    	var smoothScrollTo = function () {
    		if (start_x > x) {
    			start_x = start_x - movement;
    			if (start_x < x) start_x = x;
    		} else if (start_x < x) {
    			start_x = start_x + movement;
    			if (start_x > x) start_x = x;
    		}
    		
    		if (start_y > y) {
    			start_y = start_y - movement;
    			if (start_y < y) start_y = y;
    		} else if (start_y < y) {
    			start_y = start_y + movement;
    			if (start_y > y) start_y = y;
    		}
    		
    		if (start_x == x && start_y == y) return;
    		
    		window.scrollTo(start_x, start_y);
    		
    		setTimeout(smoothScrollTo,interval);
    	}
    	
    	smoothScrollTo();
    } else {
    	window.scrollTo(x, y);
    }
}

Element.tagName = function (element) {
	element = $(element);
	return element.tagName.toLowerCase();
}

Element.replace = function (element,new_element) {
	element = $(element);
	element.parentNode.replaceChild(new_element,element);
	return;
}

Element.replaceWithHTML = function (element,html) {
	element = $(element);
	var new_element = document.createElement('div');
	Element.update(new_element,html);
	var curr_child = new_element.firstChild;
	Element.replace(element,curr_child);
	for (var i = 1;i < new_element.childNodes.length;i++) {
		curr_child.insertAfter(new_element.childNodes[i],curr_child);
		curr_child = curr_child.nextSibling;
	}
	return;
}

Element.validate = function (element,func) {
	element = $(element);
	
	if (arguments.length <= 2) return true;
	
	var args = $A(arguments);
	var rule = args.pop();
	var val  = element.value;
	var rule_base, rule_modf, ndx, val_flg = true;
	
	if (isString(rule) && ((ndx = rule.indexOf(':')) > -1)) {
		rule_base = rule.slice(0,ndx); 
		rule_modf = rule.slice(ndx + 1).replace(/^\s*/,'').replace(/\s*$/,''); 
	} else {
		rule_base = rule;
	}
	
	switch (rule_base) {
		case 'is-numeric':
		val_flg = val.match(/[0-9]+(\.[0-9]+)?/);
		break;
		
		case 'not-blank':
		val_flg = val != '';
		break;
		
		case 'match-regexp':
		var regex = new RegExp(rule_modf);
		val_flg = regex.exec(val);
		break;
		
		case 'not-match-regexp':
		var regex = new RegExp(rule_modf);
		val_flg = !regex.exec(val);
		break;
		
		default:
		if (isFunction(rule_base)) val_flg = rule_base(val);
	}
	
	if (!val_flg) {
		if (func) return func(rule,element);
		return false;
	}
	
	return Element.validate.apply(this, args);
}

Element.findElement = function (element,tagName) {
	element = $(element);
	while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
}

function form_submit_button (event)
{
	var element = Event.element(event);
	var form = Event.findElement(event,'form');
 	
	if (form['_SBMT_BUTN_']) form['_SBMT_BUTN_'].value = element.name;
}

Position.viewportDimensions = function () {
	return {
		x: self.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
		y: self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
	};
}

Position.viewportScrollOffset = function () {
	return {
		x: self.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft,
		y: self.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
	};
}