/****************************************************************
Utilities
****************************************************************/

//Ah hah, to defined or not defined...That is the question!!!
function isUndef (o) { return typeof(o) == 'undefined' || o === '' || o == null }
function isDef(o){return!isUndef(o)};
function unDef(o) {return typeof(o)=='undefined';}
function elemRef(id) { return window.document.getElementById(id); }

function isTRUE(x) {return (x!=undefined && (x=="1" || x==1 || x=="true"));}
function isFALSE(x) {return !isTRUE(x);}

if(!String.prototype.trim) {
	String.prototype.trim = function() { return this.replace(/(^\s*)|(\s*$)/g, "");};
}


var Const = {
	SHOW:true,
	HIDE:false
}

if(!ASSERT) {
	var ASSERT=function(condition) {
		try {
			if(!condition)
				alert("Assertion failed:  in function " + ASSERT.caller);
		} catch(e) {
		}
	}
}

//DEPENDENCIES: none
ASSERT(true);

var Utils = {
	init: function() {
		if(this.m_userMessage) {//alert user if a message is defined.
			alert(this.m_userMessage);
		}
	}
	, elem: function(id) {//id->element
		return document.getElementById(id)
	}
	, show: function(id, vis) {//show/hide an element of given id. Return true if successful.
		var e=this.elem(id);
		try {
			e.style.display=vis? "":"none";	//NOTE: let the display style be empty to actually "show" the element. Don't use "block" as FireFox would choke when element is a table row!
		} catch(ex) {
			//D.warn(e.Message)
		}
		return e;	//return the element
	}
	, toggle: function(id) {//toggle visibility of an element by id
		var e=this.elem(id);
		var vis=(e.style.display=="none")? true:false;
		this.show(id, vis);
		return vis;	//return current visibility
	}
	, autoSubmit : function (e) { // on keypress of enter on a field, auto submit default form
		if (document.forms[0]) {
			var kcode;
			if (typeof(event)=="undefined") {
				// firefox
				kcode = e.keyCode;
			} else {
				// IE global event
				kcode = event.keyCode;
			}
			if (kcode==13) {
				document.forms[0].submit();
				// ignore the enter key as field value (don't BEEP in IE)
				return false;
			} else {
				// deal with the key
				return true;
			}
		}
	}
	, safeFocus : function (obj) { // given a reference to an object does a safe focus
		try {
			obj.focus();
			return true;
		} catch (e) {
			return false;
		}
	}
	, autoFocus : function (fname) { // automatically focus on the first visible field of the form
		if (document.forms[0]) {
			if (fname) {
				if (document.forms[0].elements[fname]) {
					if (!Utils.safeFocus(document.forms[0].elements[fname])) {
						return Utils.safeFocus(document.getElementById(fname));
					}
				}
			} else {
				for (var x=0; x< document.forms[0].elements.length; x++) {
					var field = document.forms[0].elements[x];
					if ((field.type != "hidden") &&
						(field.tyle != "image")) {
						if (Utils.safeFocus(field)) {
							return true;;
						}
					}
				}
				return false;
			}
		}
	}
	, popup : function (url, name, width, height) {
		var ret=window.open(url,name,"location=no,menubar=no,resizeable=no,status=no,toolbar=no,height="+height+",width="+width);
		if(ret) ret.focus();
		return ret;
	}
	/*Return child elements of given parent with given tag and attribute values
	If parent is nothing, the document is assumed.
	*/
	, getElementsByAttribute : function (tagname, aname, avalue, fromParent) {
		var doc=fromParent;
		if(!doc) doc=document;
		var candidates = doc.getElementsByTagName(tagname);
		var ret = new Array();
		for (var x=0; x<candidates.length; x++) {
			if (candidates[x].getAttribute(aname)!=null) {
				if ((avalue == undefined) ||
					(candidates[x].getAttribute(aname)==avalue)) {
					ret[ret.length]=candidates[x];
				}
			}
		}
		return ret;
	}

	//return true if the given value is an integer
	, isInteger : function(val) {
		var ret=false;
		try {	//it is an integer when it is parsable to integer
			ret= /^[0-9]+\d*$/.test(val);
		} catch(e) {
		}
		return ret;
	}

	, isEmpty : function(val) {
		return (val==null || val.trim().length==0)? true:false;
	}

	//return an array of checkbox value that are selected
	, getSelectedCheckboxValues : function(fromParent) {
		var ret= new Array();
		var arr=Utils.getElementsByAttribute("INPUT", "type", "checkbox", fromParent);
		for(var i=0, x=0; x<arr.length; ++x) {
			if(arr[x].checked) {
				ret[i++]=arr[x].value;
			}
		}
		return ret;
	}

	//return the value of the selected radio button
	, getSelectedRadioValue : function(fromParent) {
		//var ret= null;
		var arr=Utils.getElementsByAttribute("INPUT", "type", "radio", fromParent);
		for(var i=0, x=0; x<arr.length; ++x) {
			if(arr[x].checked) {
				return arr[x].value;
			}
		}
		return null;
	},

	/*This utiltiy creates and return a Yahoo dialog box which can be used
	to asynchronously submit a form with a given action url. The dialog will always provide a default "Close" button which simply dismiss it. You can also add your extra submit button text and handler.
	- width: with of the form
	- htmlId: id of the element whose's innerHTML supply the form's body
	- submitButtonText: text to appear on submit button
	- validator: validate function that must return true before submit (only if actionURL is defined)
	*/
	formDlg :function (cfg) {
		//can't proceed unless yahoo stuff defined
		if(!isDef(YAHOO))
			return;

		var onClose = function() {// close dialog
			this.cancel();
		};

		var onSubmit= function() {	//submit handler
			if(this.validate==null || this.validate()) {
				if(cfg.actionURL) {
					//host form in iframe for async submit
					var XXX="iframe"+cfg.htmlId;	//cook up some name for internal frame
					var iframe=Utils.makeHiddenFrame(XXX);
					this.form.setAttribute("target", XXX);	//change form target
					this.form.setAttribute("action", cfg.actionURL);	//change action
					this.form.parentNode.appendChild(iframe);
					this.form.submit();
				}
			}
		};

		// create
		var ret=null;
		try {
			var close_text=(cfg.closeButtonText)? cfg.closeButtonText : "Cancel";
			var close_handler = (cfg.onClose instanceof Function)? cfg.onClose : onClose;
			var submit_handler = (cfg.onSubmit instanceof Function)? cfg.onSubmit : onSubmit;
			var btns=[{text: close_text, handler:close_handler, isDefault:true }];
			if(cfg.submitButtonText) {//add extra button if text given
				btns[1]=btns[0];
				btns[0]={text : cfg.submitButtonText, handler: submit_handler};
			}

			/*Inject _CURRENTZINDEX as an extended property of the Dialog class.
			Every instantiation of a new dialog should obtain the next zindex value to ensure
			that it sits above previous dialog.
			WHY: Even though an "iframe hack" should already be applied automatically by the Dialog class when IE6 is detected,
			this extra step of explicitly defining a higher zindex value is still needed to fix the problem in IE6
			where html listbox would bleed-through other dialog.
			*/
			if(!isDef(YAHOO.widget.Dialog._CURRENTZINDEX)) {
				YAHOO.widget.Dialog._CURRENTZINDEX=12345;
			}

			ret = new YAHOO.widget.Dialog(cfg.htmlId,
																	{ width : isDef(cfg.width)? cfg.width:"auto",
																	  fixedcenter : true,
																	  visible : false,
																	  constraintoviewport : true,
																	  buttons : btns,
																	  postmethod : "manual",
																	  modal:true,
																	  close : cfg.hideCloseIcon?  false:true,
																	 zIndex: ++YAHOO.widget.Dialog._CURRENTZINDEX
																	 } );
			//field validator
			ret.validate = cfg.validator;
			ret.setHeader(cfg.captionText);
			ret.cancel = function() {
				if(cfg.onClose instanceof Function)
					cfg.onClose();
				else {
					ret.cancelEvent.fire();
					ret.hide();
				}
			}

			//render
			ret.render();
			ret.cfg.setProperty("fixedcenter", false);	//turn this off so dialog won't snap back when the user scroll the mother page
		} catch(e) {
		}
		return ret;
	}

	, addHiddenField : function(form, name, value) {	//add a hidden field of given name and value to the given form
		var e = document.createElement('input');
		e.setAttribute('type', 'hidden');
		e.setAttribute('name', name);
		e.setAttribute('value', value);
		return form.appendChild(e);
	}
	, randomId : function() {	//return a random string to be used as a dummy id
		return "ID"+Math.round(Math.random()*10000000);
	}
	, setHTML: function(id, value) {//set the innerHTML of the given element
		var e=this.elem(id);
		if(e) {
			e.innerHTML=value;
		}
		return e;
	}
	/*create and return a hidden iframe of given id/name*/
	, makeHiddenFrame : function(frameNameOrId) {
		var ret =Utils.elem(frameNameOrId);
		if(ret) ret.parentNode.removeChild(ret);
		if(true) {
			ret=document.createElement("iframe");
      		var X=frameNameOrId;
			ret.setAttribute("id", X);
			ret.setAttribute("name", X);
			ret.setAttribute("width","0");
			ret.setAttribute("height","0");
			ret.setAttribute("border","0");
			ret.setAttribute("style","width: 0; height: 0; border: none;");
			document.body.appendChild(ret);
			window.frames[X].name=X; //fix for IE
		}
		return ret;
	}
	, alertDlg : function(msg, onOK) {
		var onClose = function() {
			this.hide();
			if (Utils.ALERTDLG.userCB instanceof Function) {
				Utils.ALERTDLG.userCB();
			}
		}
		if(Utils.ALERTDLG)
			Utils.ALERTDLG.destroy();
		var box = document.createElement("div");
		box.innerHTML = "<center><br/>" + msg + "<br/><br/></center>";
		document.body.appendChild(box);
		box.id="ALERTDLG";
		Utils.ALERTDLG=Utils.formDlg({htmlId : box.id, width:"500px", captionText:"Message", closeButtonText:"OK", hideCloseIcon : true, onClose: onClose});
		Utils.ALERTDLG.userCB=onOK;
		Utils.ALERTDLG.show();
	}
	//select the first option whose value match the given one
	, selectOption : function(optionElementId, value) {
		var items=this.elem(optionElementId);
		if(typeof items == "object") {
			for(var x=0; x<items.length; ++x) {
				if(items[x].value==value) {
					items.selectedIndex=x;
					break;
				}
			}
		}
	}
	//return the value of the option currently selected in the given select element
	, getSelectedOptionValue : function(optionElementId) {
		var ret=null;
		var items=this.elem(optionElementId);
		ASSERT(typeof items=="object");
		if(items.selectedIndex>=0) {
			ret = items.options[items.selectedIndex].value;
		}
		return ret;
	}
  //resize the given iframe to fit its actual content
  , bestFitIframeHeight : function(frameId){
    try{
      elem = document.getElementById(frameId);
      elem.height=0;  //firefox hack; else it may not resize if existing frame is high enough
      if (elem.contentDocument && elem.contentDocument.body.scrollHeight) { //ns6 syntax
        elem.height = elem.contentDocument.body.scrollHeight;
      } else if (elem.Document && elem.Document.body.scrollHeight) { //ie5+ syntax
        elem.height = elem.Document.body.scrollHeight;
      } else if (elem.contentDocument && elem.contentDocument.body.offsetHeight) { //ns6 syntax
        elem.height = elem.contentDocument.body.offsetHeight;
      }
    } catch(err){
      window.status = err.message;
    }
  }

  /*
  Resize the given iframe to fit its actual content and return the height.
  The minimum height will be the content height of its parent.
  */
  , bestFitIFrameHeight : function(frameId) {
    try{
      elem = document.getElementById(frameId);
      elem.height=0;  //firefox hack; else it may not resize if existing frame is high enough
      var ret=0;
      if (elem.contentDocument && elem.contentDocument.body.scrollHeight) { //ns6 syntax
        ret = elem.contentDocument.body.scrollHeight;
      } else if (elem.Document && elem.Document.body.scrollHeight) { //ie5+ syntax
        ret = elem.Document.body.scrollHeight;
      } else if (elem.contentDocument && elem.contentDocument.body.offsetHeight) { //ns6 syntax
        ret = elem.contentDocument.body.offsetHeight;
      }
      //resize again to fit parent
      var min_elem = elem.offsetParent;
      if(min_elem && ret < min_elem.scrollHeight) {
        ret=min_elem.scrollHeight;
      }
      elem.height=ret;
    } catch(e){/*silent is gold*/}
    return ret;
  }

};


var _COMMON_JS_=1;
