// define the page info
emmapp.page = {
		
	childDialog: null,
	pageName: null,
	pageKey: null,
	isPublicPage: null,
	
	saveUrl: null,  // will be updated in jspPageInclude.jspf
	saveAddBaseUrl: null,
	saveDelBaseUrl: null,
	getPageBaseUrl: null,
	loginRequiredUrl: null, 
	contextPath: null,
	captchaImgUrl: null,
	_ajaxActionUrlPattern: null,
	ajaxElementBaseUrl: null,
	ajaxStoreUpdateBaseUrl: null,
	defaultSubmitAction: [],
	formId: "", // will be reset by jsp to append the page name
	dialogFormId: "FORM_APP_DIALOG_CONTENT",
	//loading image url
	smallLoadingImageUrl:"/images/loading_small.gif",
	middleLoadingImageUrl:"/images/loading_middle.gif",
	largeLoadingImageUrl:"/images/loading_large.gif",
	
	__clearedTiptext: [], 
	msgBuffer: [],
	oldFormData: null,
	getUpdatesNewCountInterval:60000, // mini-seconds
	getGuestHomeNewestNews:60000,
	// confirm callback - when server send a confirm message and user answer YES, 
	// call this callback to process the specific action
	// each page that needs to handle confirm callbacks shoudl set the callback at the end of the page template 
	// and before the dojo.onLoad event is processed (so don't add into dojo.onload())
	// the function take one boolean parameter, the answer
	serverConfirmCallback: null,
	
	// falg to check error if there is error message from server, set in checkError.jspf
	checkError: "",
	messageBoardId : "PAGE_CONTENT_MESSAGEBOARD",
	topHeight:41,
//	// make the fromID page specific
//	getFormId: function() {
//		return this._formId + "__" + this.pageName;
//	},

	init: function() {
		console.debug("emmapp.page.init() ...");
		
		var validationData = emmapp.getValidationData();
		
		console.debug("emmapp.page.__attachTiptextEvents() ...");
		if(emmapp.disableTooltip != true) {
			this.attachTiptextEvents(validationData);
		}
		
		// note: this is the onblur event for all the fields that need validation
		// may cause usability issue since when u leave an element you will get an alert message
		// better set on specific pages only
		// still attach the onblur event, let each method to handle if the event needs to be processed or not

		console.debug("emmapp.page.__attachValidatorEvents() ...");
		this.attachValidatorEvents(validationData);
		
		this.__menuLineShowOrHide();
		console.debug("emmapp.page.__attachSubmitEvent() ...");

		this.__attachSubmitEvent();
		
		// set the attributes
		this.__processValidationAttributes(validationData);
		
		//ie ul li blank
		this.scanAndHideEmptySpace("ul","li");
		this.scanAndHideEmptySpace("dl","dd");
		//if pagination [sort by] is null,hide the [sort by] parentNode
		this.__paginationHideLeft();

		console.debug("emmapp.page.__doFormSmokeCheck() ...");
		this.__doFormSmokeCheck();

		// show any error messages from server
		this.__checkServerError();
		
		this.__setDivTop();
		this.oldFormData = dojo.formToQuery(this.formId);
		console.debug("Old Form Data:");
		///console.debug(this.oldFormData);
		//set the cursor to normal cursor
		//emmapp.showArrowCursor();

		console.debug("emmapp.page.init() ... done");		
	},
	//now ,we want to fixed the page header ,so we know the header height
	__setDivTop: function(){
		var msgBoardObj = dojo.byId("PAGE_CONTENT_MESSAGEBOARD");
		var top = this.topHeight +"px";
		var footerWarpperObj = dojo.byId("PAGE_FOOTER_WRAPPER");
				
		if(emmapp.isGuestUser || this.pageName == "GuestHome"){
			top = 0;
		}
		var layoutObj = dojo.byId("PAGE_CONTENT_TOP_WRAPPER");
	
		if(layoutObj){
			dojo.style(layoutObj,{top: top});
		}
		if(msgBoardObj){
			dojo.style(msgBoardObj,{top: top});
		}
		
		if(footerWarpperObj){
			dojo.style(footerWarpperObj,{top: top});	
		}

	},
	setMsgNotification: function(gmsid /*gmsid*/){
		var url = emmapp.url.addParameters(emmapp.page.getAjaxActionUrl("set_msgnotification"), "gmsid", gmsid);
		var callback = function(response, ioArgs) {
			
			if ( !emmapp.ajax.checkJsonState(response) ) {
				return response;
			}
			if ( response.status == emmapp.ajax.JSON_STATUS_VALUE_SUCCESS ) {
				//TODO hidden messageboard
				var e_message_boardid = dojo.byId(emmapp.page.messageBoardId);
				e_message_boardid.style.display = "none";
				//when we close messageboard ,destory it
				dojo.destroy(e_message_boardid);
				return response;
			}
		};
		emmapp.ajax.doAjaxGet(url, callback);
	},
	/**
	 * ajax call to check the server error on page load.
	 * we can't show the error statically since that will cause the error to show if user click browser back button
	 */
	__checkServerError: function() {
		
		if ( !this.checkError ) {
			return;
		}
	
		// clear the error flag
		this.checkError = false;

		var callback = function(response, ioArgs) {
			//alert(response.errMsg);

			 // show the error message
			if ( response.errMsg && response.errMsg != "" ) {
				alert(response.errMsg);
			}

			// show the confirm message and record the answer
			if ( response.confirmMsg && response.confirmMsg != "" ) {
				var e_request_confirmed = dojo.byId("e_emm_server_question_confirmed");
				var answer = confirm(response.confirmMsg);
				if ( answer ) {
					e_request_confirmed.value = "true";
					console.log("server question confirmed.");
				} else {
					e_request_confirmed.value = "false";
					console.log("server question ignored.");
				}
			
				if ( emmapp.page.serverConfirmCallback ) {
					console.log("calling the confirmm callback function with answer = " + answer);
					emmapp.page.serverConfirmCallback(answer);
				}
				
			}
						return response;
		};

		var url = emmapp.url.addAutoAjax(emmapp.page.getAjaxActionUrl("getErrorMsg")); 
		emmapp.ajax.doAjaxPost(url, callback);
		
	},
	//if pagination [sort by] is null,hide the [sort by] parentNode
	//when a page stated up,we can hide the [sort by] Node calling this method
	__paginationHideLeft:function(){
		dojo.query("div.pagination").forEach(function(thisObject){
			var paginationText = emmapp.string.getPlainText(thisObject.innerHTML);
			if(paginationText== "" || paginationText.length == 0 || paginationText == null){
				thisObject.style.display = "none";
				return;
			}
			var pageObj = dojo.query("div.float_left",thisObject)[0];
			if(pageObj){
				var text = emmapp.string.getPlainText(pageObj.innerHTML);
				if(text== "" || text.length == 0 || text == null){
					pageObj.style.display = 'none';
				}
			}
		})
	},
	__menuLineShowOrHide:function(){
		dojo.query("div.line_is_last").forEach(function(thisObject){
			var text = emmapp.string.getPlainText(thisObject.innerHTML);
			if(text== "" || text.length == 0 || text == null){
				thisObject.style.display = 'none';				
				dojo.query("div.line_have_last ",thisObject.parentNode).forEach(function(obj){
					obj.className = "menu_line_btm line_have_last menu_line_btm_last";
				});
			}
		});
	},
	scanAndHideEmptySpace:function(/*parent tag*/parentTag,/*child tag*/childTag){
		console.debug("emmapp.page._scanAndHideEmptySpace() ... done ,about the blank of <ul>,<li> on IE");
		if(typeof(parentTag) == 'undefined'){
			parentTag = "ul";
		}
		if(typeof(childTag) == 'undefined'){
			childTag = "li";
		}
		dojo.query(parentTag+".RemoveBlank").forEach(function(thisObject){
			dojo.query(childTag,thisObject).forEach(function(thisObject){
				var content = thisObject.innerHTML;
				var text = emmapp.string.getPlainText(content);
				if(text== "" || text.length == 0){
					thisObject.style.display = 'none';
				}
				dojo.query("a",thisObject).forEach(function(thisObject){
					if(thisObject.className == "nodisplay" || thisObject.style.display == "none"){
						thisObject.parentNode.style.display = 'none';
					}
					if (thisObject.className == "nohide"){
						thisObject.parentNode.parentNode.style.display = '';
					}
				});
				dojo.query("span",thisObject).forEach(function(thisObject){
					if(thisObject.className == "nodisplay" || thisObject.style.display == "none"){
						thisObject.parentNode.style.display = 'none';
					}
					if (thisObject.className == "nohide"){
						thisObject.parentNode.parentNode.style.display = '';
					}
				});
			})						
		});		
	},	
	/**
	 * process the PostValidationData and attach the post load events 
	 * return the page names in an array.
	 */
	attachPostLoadEvents: function() {
		
		var pageNames = [];
		
		var validationData = emmapp.getPostValidationData();
		
		if ( validationData.length > 0 ) {
			
			for (x in validationData) {
				var data = validationData[x].data;
				pageNames.push(data.pageName);
			}
			
			console.debug("emmapp.page.attachPostLoadEvents: attachTiptextEvents() ...");
			this.attachTiptextEvents(validationData);
			
			// note: this is the onblur event for all the fields that need validation
			// may cause usability issue since when u leave an element you will get an alert message
			// better set on specific pages only
			// still attach the onblur event, let each method to handle if the event needs to be processed or not
	
			console.debug("emmapp.page.attachPostLoadEvents: attachValidatorEvents() ...");
			this.attachValidatorEvents(validationData);
	
			// clear the data since we only need to attach once
			console.debug("emmapp.page.attachPostLoadEvents: clearPostValidationData() ...");
			emmapp.clearPostValidationData();
		}
		
		return pageNames;
	},
	
	isFormChanged: function() {
		var newFormData = dojo.formToQuery(this.formId);
		
		console.debug("Old Form Data:");
		console.debug(this.oldFormData);
		console.debug("New Form Data:");
		console.debug(newFormData);
		return newFormData != this.oldFormData;

	},
	
	hasMsg: function() {
		return this.msgBuffer.length > 0;
	},
	
	clearMsg: function() {
		this.msgBuffer = [];
	},
	
	showMsg: function() {
		if ( this.msgBuffer.length > 0 ) {
			alert(this.msgBuffer.join("\r\n"));
		}
	},
	
	addMsg:  function(msg) {

		this.msgBuffer[this.msgBuffer.length] = msg;
	},
	
	checkCharacter: function(id){
		
		var e = emmapp.byId(id);
		var tempName = emmapp.getObjectValue(e);
		var count =0;
		if(typeof(tempName)!="undefined"&&tempName!=null&&tempName.length>=2){
			tempName = tempName.replace(/\s/g,'');
			for(var i=0;i<tempName.length-1;i++){
				//Filtering Spaces
				if(tempName.charAt(i).toUpperCase()==tempName.charAt(i+1).toUpperCase()){
					count++;
				}
			}
			if((count+1)==tempName.length){
				var name = dojo.attr(e, emmapp.ATTR_nameText);
				var text = emmapp.msg.sameRepeatingCharacter(name);
				emmapp.page.addMsg(text);

			}
		}
		
	},
	
	selectAllCheckBoxes: function(/*dom*/field) {
		console.log("selectAllCheckBoxes called with: " + field);
		//why?do nothing,remove it (tbody)
		//var tbody = field.parentNode.parentNode.parentNode;
		var myName = field.name;
		//console.log("selectAllCheckBoxes in: " + tbody.className);
		var checkBoxes = document.getElementsByTagName("input");
		for (var i=0; i<checkBoxes.length; i++) {
			var name = checkBoxes[i].name;
			if (name != myName) {
				var checked = field.checked;
				checkBoxes[i].checked = checked;
			}
		}
	},
	

	
	getSaveWithAddUrl: function(actionTarget) {
		var x = this.saveAddBaseUrl.indexOf("?");
		if ( x > 0 ) {
				return this.saveAddBaseUrl.substring(0, x) + actionTarget + this.saveAddBaseUrl.substring(x);
		} else {
			return this.saveAddBaseUrl + actionTarget;
		}
	},
	
	getSaveWithDeleteUrl: function(actionTarget) {
		
		var x = this.saveDelBaseUrl.indexOf("?");
		if ( x > 0 ) {
				return this.saveDelBaseUrl.substring(0, x) + actionTarget + this.saveDelBaseUrl.substring(x);
		} else {
			return this.saveDelBaseUrl + actionTarget;
		}
			
	},
	
	getPageUrl: function(/*String*/pageName, /*boolean*/createNewRow) {
		var url = this.getPageBaseUrl + pageName;
		if ( createNewRow ) {
			url = url + "/true";
		}
		
		return url;
	},
	
	getAjaxActionUrl: function(/*String*/actionName) {
		var url = this._ajaxActionUrlPattern.replace("{0}", actionName);	
		return url;
	},
	
	
	setActionId: function(/*String*/actionId) {
		if ( actionId != null && actionId != "" && typeof actionId != 'undefined') {
			var form = dojo.byId(this.formId);
			form.pageActionId.value = actionId;
		}
		
	},
	
	setActionPageName: function(/*String*/actionPageName, /*boolean*/setPageKey) {
		if ( actionPageName == null || actionPageName == "" || typeof actionPageName == "undefined") {
			actionPageName = "";
		}
		
		var form = dojo.byId(this.formId);
		form.actionPageName.value = actionPageName;
		
		if ( setPageKey ) {
			form.actionPageKey.value = emmapp.getPageKeyForPage(actionPageName);
		} else {
			form.actionPageKey.value = "";  // make sure to clear the value
		}

		console.debug("emmapp.page.setActionPageName: name-key =>" + actionPageName + " -> " + form.actionPageKey.value);
	},
	
	/**
	 * actionId - the page action ID that triggered the submit action
	 * actionUrl -  the actionUrl, if not specified, or empty, then the default SavePage url is used
	 * actionPage - the page that triggered the action. This parameter is used to get the page action from the specified page.
	 * if not specified, use the default main page
	 * setPageKey - if specified, set the page associated with the specified actionPageName. 
	 * The pageKey wil be used to get the page controller
	 * ajaxCallback - if specified, perform an ajax call to submit the action and pass the response to the calback function.
	 * handleAs - handle as ajax, text, etc. see emmapp.ajax for detail
	 */
	validateAndSubmit: function(actionId, actionUrl, actionPage, /*boolean*/setPageKey, ajaxCallback, handleAs) {
		if ( this.validateForm(null, actionPage) ) {
			this.submitForm(actionId, actionUrl, actionPage, setPageKey, ajaxCallback, handleAs);
		}
	},
	
	/**
	 * actionId - the page action ID that triggered the submit action
	 * actionUrl -  the actionUrl, if not specified, or empty, then the default SavePage url is used
	 * actionPage - the page that triggered the action. This parameter is used to get the page action from the specified page.
	 * if not specified, use the default main page
	 * setPageKey - if specified, set the page associated with the specified actionPageName. 
	 * The pageKey wil be used to get the page controller
	 * ajaxCallback - if specified, perform an ajax call to submit the action and pass the response to the calback function.
	 * handleAs - handle as ajax, text, etc. see emmapp.ajax for detail
	 */
	submitForm: function (/*String*/actionId, /*String*/actionUrl, /*String*/actionPage, /*boolean*/setPageKey, ajaxCallback, handleAs) {
		
		 console.debug("emmapp.submitForm: actionId = " + actionId);
		 console.debug("emmapp.submitForm: actionUrl = " + actionUrl);
		 console.debug("emmapp.submitForm: actionPage = " + actionPage);
		 console.debug("emmapp.submitForm: setPageKey = " + setPageKey);
		 console.debug("emmapp.submitForm: ajaxCallback = " + ajaxCallback);
		 
		var form = dojo.byId(this.formId);
		
		this.setActionId(actionId);
		
//			if ( actionId != null && actionId != "" && typeof actionId != 'undefined') {
//				//this._setPageAction(form, actionId, actionPage);
//				form.pageActionId.value = actionId;
//			}
	  
		// the action page is the page that triggered the action,
		// if this is the page of the controller, you do not need to set this 
		// only needed when the action is from a sidebar page
//		if ( actionPage != null && actionPage != "" && typeof actionPage != "undefined") {
//			form.actionPageName.value = actionPage;
//			form.actionPageKey.value = emmapp.getPageKeyForPage(actionPage);
//		} else {
//			form.actionPageName.value = "";
//			form.actionPageKey.value = "";			
//		}

		// note: we don't auto-trigger the actionPageKey from action page name.
		// since the actionPageName only means the action is triggered by thap page,
		// but does not mean to use the actionpage's controller
		// if you want to use the action page's controller, the call setActionPageKey directly
		this.setActionPageName(actionPage, setPageKey);
		
		// if url is not specified, use default form action
		if ( actionUrl != null && actionUrl != "" && typeof actionUrl != 'undefined') {
			form.action = actionUrl;
		} else {
			form.action = emmapp.page.saveUrl;
		}
				
		this.__clearAllTipText();
		
		if ( ajaxCallback ) {
			
			// for page submit ajax, the default return content should be html.
			if ( handleAs == null || handleAs == "" || typeof handleAs == 'undefined' ) {
				handleAs = "text";
			}
			
			// do ajax submit
			emmapp.ajax.doAjaxPost(form.action, ajaxCallback, handleAs);
		} else {
			form.submit();
			emmapp.showWaitCursor();
		}
		//after submit , restore tips again
		this.restoreClearedTipText();
			
	},
	
	
	validateForm: function(/*Array*/msgBuffer, /*String*/actionPage) {
		console.debug("emmapp.page.validateForm: with actionPage - " + actionPage);
		
		return emmapp.validator.validateData(emmapp.getValidationData(actionPage), msgBuffer);
	},
	
	__processValidationAttributes: function(validationData) {
		for (x in validationData) {
			var data = validationData[x].data;
			var items;
			
			// process the attributes
			items = data.attributeItems;	
			if ( items ) {
				for (y in items){
					
					var item = items[y];
					//{id:'id',attr1: 'attr1', attr2:'attr2'}
					this.setAttributes(item);
				}
			}
		}
	},
	
	setAttributes: function(/*{id:'id',attr1: 'attr1', attr2:'attr2'}*/item) {
		
		var id = item.id;
		if ( emmapp.validator.isInvalid(id) ) {			
			return;
		}
			
		var node = null;
		var node2 = null;
		var w = dijit.byId(id);
		if ( w == null ) {			
			node = dojo.byId(id);
		} else {
			node = w.domNode;
		}
		
		w = dijit.byId( id + emmapp.SUFFIX_DOJO);
		if ( w ) {
			node2 = w.domNode;
		}
		
		// now you need to check all attributes supported
		if ( item.bgcolor ) {		
			node.style.background = item.bgcolor;
			//if(item.bgcolor=="#FF0000") node.style.color = "white";
			if ( node2 != null ){ 
				node2.style.background = item.bgcolor;
				node = dojo.byId(id + emmapp.SUFFIX_DOJO);
				//if(item.bgcolor=="#FF0000" && node){ node.style.color = "white"; }
			}
		}
		
	},
	
	
	checkMissingFields: function() {
		var validationData = emmapp.getValidationData();
		for (x in validationData) {
			var data = validationData[x].data;
			var items;
			
			// process required
			items = data.requiredItems;
			
			//alert(items.length);
			if ( items ) {
				//alert(items);
				for (y in items){
					
					var item = items[y];
					//alert(item.id);
					this.markMissingField(item.id);
				}				
			}								
		}
			
		return true;
	},
	
	markMissingField: function (/*string*/id) {
				
		if ( emmapp.validator.isInvalid(id) ) {			
			return;
		}
				
		var v = null;
		var text = null;
		var w = dijit.byId(id);
				
		if ( w != null ) {			
			//alert("id=" + id + ", w=" + w);
			text = w.attr(emmapp.ATTR_nameText);
			v = w.getValue();				
			// if display value is an valid attribute, it can't be empty
			if ( w.declaredClass == 'emm.widget.FilteringSelect' ) {
				v = w.getDisplayedValue();
			}		
		} else {						
			w = dojo.byId(id);						
			v = emmapp.getObjectValue(w);			
			text = dojo.attr(w,emmapp.ATTR_nameText);
		}
				
		if ( null == v || v == "" || v == emmapp.getTipText(id) ) {			
			//w.style.background = "#FFFF99";
			//console.debug(msg + ", the value is " + v);
			var did = id + emmapp.SUFFIX_DOJO;
			w = dijit.byId(did);
			if ( w ) {
				//alert(did + "=" + w.domNode);
				if ( w.domNode ) {
					w = w.domNode;
				}			
				//w.style.background = "#FFFF99";
			}
		}		
	},
	
	__attachSubmitEvent: function() {
		
//		if ( !dojo.isFunction(this.defaultSubmitAction) ) {
//			return;
//		}

		var form = dojo.byId(this.formId);
		var self = this;
		var fun = function(evt) {
			if ( evt.keyCode == dojo.keys.ENTER) {
				var e = evt.target;
//					this.submitForm(actionId, actionUrl, actionPage)
//					alert("submit");
									
				// if the control is a dojo store, may need to set the hidden text 
				// since that depsnds on onblur to set the value
				// TODO
				if (e.form == form ) {
					//alert("submit: " + e.id);
					var pageName = emmapp.getElementPageName(e.id);
					if ( pageName ) {
						var func = self.defaultSubmitAction[pageName];
						if ( func ) {
							//alert(pageName + "=" + func);
							func();
						}
					}				
				}
			}
		};
		
		
		for (var i = 0; i < form.length; i++ ) {
			var e = form[i];
	
			
			// special handling hehe
			// these two items handled by them self 
			// better handle later
			if ( e.id == "buz_sortby" || e.id =="mem_sortby") {
				continue;
			}

			if ( e.type != "hidden" && e.type != 'textarea') {
//					alert("onkeyup: " + e.id + " - " + e.type);
				dojo.connect(e, "onkeyup", fun);
			}				
		}

	},
	
	__doFormSmokeCheck: function() {
		var form = dojo.byId(this.formId);
		if(form!=null && form!=""){
			console.debug("form.length=" + form.length);		
			for (var i = 0; i < form.length; i++ ) {
				var e = form[i];
				// if list does not have option, set as invalid
				//console.debug(e.type);
				if ( e.type == 'select-one' || e.type == 'select-multiple') {
					if ( dijit.byId(e.id) == null && e.options.length == 0 ) {
						emmapp.selectionlist.setSelectOptionHtml(e, "");
						emmapp.validator.setInvalid(e.id, true);
					}
				}
			}
		}
	},
		
	__clearAllTipText: function() {
		var validationData = emmapp.getValidationData();
		for (x in validationData) {
			var data = validationData[x].data;
			var items;
			
			// process the tipTextItems
			items = data.tipTextItems;
			if ( items ) {
				for (x in items){
					var item = items[x];
					emmapp.hideTipText(item.id, item.tipText);
					
					// save the cleared tiptext so we can restore later
					this.__clearedTiptext[item.id] = item.tipText;
				}				
			}					
		} // end for		
	},
		
	restoreClearedTipText: function() {
		for (id in this.__clearedTiptext) {
			var tipText = this.__clearedTiptext[id];
			emmapp.showTipText(id, tipText);			
		} // end for	
		
		this.__clearedTiptext = [];
	},
		
	attachTiptextEvents: function(/*Array*/validationData) {
		var self = this;
		for (x in validationData) {
			var data = validationData[x].data;
			var items;
			
			// process the tipTextItems
			items = data.tipTextItems;
			if ( items ) {
				for (x in items){
					var item = items[x];
					this.__attachTiptextEvt(item.id, item.tipText);
				}				
			}					
		} // end for
	},
	
	attachValidatorEvents: function(/*Array*/validationData) {
		var forAll = emmapp.enableOnBlurValidation;
		var self = this;
		for (x in validationData) {
			var data = validationData[x].data;
			var items;
			
			// process the typped item
			items = data.typeItems;
			if ( items ) {
				for (x in items){
					var item = items[x];
					this.__attachvalidateTypeEvt(item.id, item.type);
				}				
			}

			// if not for all, don't attach onBlur for required and length
			if ( !forAll ) {
				return;
			}
			
			// process required
			items = data.requiredItems;
			if ( items ) {
				for (x in items){
					var item = items[x];
					this.__attachvalidateRequiredEvt(item.id);
				}				
			}

			// process size
			items = data.sizeItems;
			if ( items ) {
				for (x in items){
					var item = items[x];
					this.__attachvalidateLengthEvt(item.id, item.minSize, item.maxSize);					
				}				
			}						
		} // end for
	},
	
	__attachvalidateTypeEvt: function(id, type) {
		var _id = emmapp.getInputId(id);
		dojo.connect(emmapp.byId(_id), "onblur", function(evt){
			emmapp.validator.validateType(_id, type, null);
		});

	},
	
	__attachvalidateLengthEvt: function(id, minSize, maxSize) {
		
		var _id = emmapp.getInputId(id);
		dojo.connect(emmapp.byId(_id), "onblur", function(evt){
			emmapp.validator.validateLength(_id, minSize, maxSize, null);
		});

	},
	
	__attachvalidateRequiredEvt: function(id) {
			
		var _id = emmapp.getInputId(id);
		dojo.connect(emmapp.byId(_id), "onblur", function(evt){
			emmapp.validator.validateRequired(_id, null);
		});

	},
	
	__attachTiptextEvt: function(id, text) {
		var _id = emmapp.getInputId(id);

		/* GAGI-806 */
		dojo.connect(emmapp.byId(_id), "onblur", function(evt){
			emmapp.showTipText(_id, text);
		});
		
		/* GAGI-806 */
		dojo.connect(emmapp.byId(_id), "onfocus", function(evt){
			emmapp.hideTipText(_id, text);
		});
		
		// initially show tip as needed
		emmapp.showTipText(_id, text);
		
		console.log("tipText processed: " + _id + ", " + text);
	},
	/**
	 * perform a sorting operation. The page should have a doSort() method to handle the detail action.
	 */
	sort: function(/*dom*/field, /*string*/sortElement) {
		
		// set the hidden sort element value
		// note: the element that triggered the sorting is the sorting element as a list. 
		// And we have one sorting list element on each sorting/panigation bar, 
		// and we only want to have one sorting element, so use the hidden element 
		// See GAGI-3312.
		var sortValue =  emmapp.getObjectValue(field);
		emmapp.setElementValue(dojo.byId(sortElement), sortValue);
		
		if ( doSort ) {
			doSort();
		} else {
			alert("doSort() not defined!" )
		}
	},
	
	/**
	 * perform a reverse-sorting operation. The page should have a doReverseSort() method to handle the detail action.
	 */	
	sortReverse: function() {
		if ( doReverseSort ) {
			doReverseSort();
		} else {
			alert("doReverseSort() not defined!" )
		}
	},
	
	deleteEntireRowById: function(id,className){
		var topClass;
		if(typeof className == "undefined" || className == null || className == ""){
			topClass = "repeater_item";
		}else{
			topClass = className;
		}
		var node = emmapp.byId(id);
		for(var n = node ;n;n=n.parentNode){
			if(n.className == topClass){
				n.style.display = "none";
				break;
			}
		}
	},

	deleteEntireRowByNameAndKey: function(name,rowKey){
		this.deleteEntireRowById(emmapp.getId(name,rowKey));
	},
	
	//get scroll x,y 
	getScrollXY: function(){
		var scrOfX = 0, scrOfY = 0;
		if( typeof( window.pageYOffset ) == 'number' ) {
		    //Netscape compliant
		    scrOfY = window.pageYOffset;
		    scrOfX = window.pageXOffset;
		} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
		    //DOM compliant
		    scrOfY = document.body.scrollTop;
		    scrOfX = document.body.scrollLeft;
		} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
		    //IE6 standards compliant mode
		    scrOfY = document.documentElement.scrollTop;
		    scrOfX = document.documentElement.scrollLeft;
		}
		  return [ scrOfX, scrOfY ];
	}
};


