/**
 * Purpose: Create a form container
 * @param {String} id - id of the form
 * @param {String} method - Post/Get
 * @param {String} action - action of the form submission
 * @parem {String} enctype - Default is application/x-www-form-urlencoded
 * @param {String} target - Default is ""
 */
AnkhFormContainer = function(id,method,action,enctype,target){
	var form = document.createElement('form');
	form.name = form.id = id;	
	form.method = method;
	form.action = action;		
	if(enctype!=null){
		form.enctype = form.encoding = enctype;		//must be encoding for IE
	}
	if(target != null){
		form.target = target;
	}
	EventUtil.addEventHandler(form,"keydown",function(){		//prevent esc
		if (EventUtil.getEvent().keyCode == 27) {
			EventUtil.getEvent().preventDefault();
		}
	});
	return form;
};
/**
 * Purpose: Create a generic table with the stipulated number of columns and rows
 * @param {Int} numRows
 * @param {Int} numCols
 */
GenericTable = function(numRows,numCols){
	var table = document.createElement('table');
	var tbody = document.createElement('tbody');
	table.appendChild(tbody);
	
	for(var i = 0; i < numRows; i++){
		var tr = document.createElement('tr');
		tbody.appendChild(tr);
		for(var j = 0; j < numCols; j++){
			var td = document.createElement('td');
			tr.appendChild(td);
		}
	}
	return {
		Table:table, 
		TBody:tbody,
		getCell: function(row,col){
			return tbody.childNodes[row].childNodes[col];
		},
		insertIntoCell: function(row,col,HTMLObj){
			if (typeof HTMLObj == "object") {			
				tbody.childNodes[row].childNodes[col].appendChild(HTMLObj);
			}
			else{
				var txtNode = document.createTextNode(HTMLObj);
				tbody.childNodes[row].childNodes[col].appendChild(txtNode);
			}	
		}		
	};
};
/**
 * Purpose: Generate an ankh form with 2 columns
 * @param {Array} keyList - array of keys
 */
TwoColumnsAnkhTable = function(keyList,valueList){
	var table = document.createElement('table');
	var tbody = document.createElement('tbody');
	table.appendChild(tbody);
	for(var i = 0;i<keyList.length;i++){
		var row = document.createElement('tr');
		tbody.appendChild(row);	
		var cell1 = document.createElement('td');
		cell1.className = "alignRight";
		if (typeof keyList[i] == "object") {
			cell1.appendChild(keyList[i]);
		}else{
			var txtNode = document.createTextNode(keyList[i]);
			cell1.appendChild(txtNode);
		}
		row.appendChild(cell1);	
		var cell2 = document.createElement('td');
		cell2.className = "alignLeft";
		row.appendChild(cell2);
		
		if (valueList != null) {
			if (typeof valueList[i] == "object") {
				cell2.appendChild(valueList[i]);
			}else{
				var txtNode = document.createTextNode(valueList[i]);
				cell2.appendChild(txtNode);
			}
		}				
	}
	return {
		table: table,
		tBody: tbody,
		insertIntoRow: function(rowNum,HTMLobj){
			if (HTMLobj != null) {
				if (typeof HTMLobj == "object") {				
					tbody.childNodes[rowNum].childNodes[1].appendChild(HTMLobj);
				}
				else {
					var txtNode = document.createTextNode(HTMLobj);
					tbody.childNodes[rowNum].childNodes[1].appendChild(txtNode);
				}
			}
		}
	};
};

AnkhPrivacyIcon = function(directory){
	var icon;
	if(isIE && !isMinIE7){
		icon = new AnkhSprite(directory+"Image/04_AnkhControls/Privacy8.png",10,17,{x:0,y:0},{x:0,y:18},{x:0,y:18});					
	}else{
		icon = new AnkhSprite(directory+"Image/04_AnkhControls/Privacy.png",10,17,{x:0,y:0},{x:0,y:18},{x:0,y:18});		
	}
	icon.style.cursor = "pointer";
	return icon;
};

/**
 * Purpose: Create an iframe with the specified src, width and height
 * @param {String} src
 * @param {Int} width
 * @param {Int} height
 */
AnkhIframe = function(src,width,height){
	var iframe = document.createElement('iframe');
	iframe.src = src;
	iframe.frameBorder = "0";
	iframe.style.width = width+"px";
	iframe.style.height = height+"px";		
	return iframe;
};
AnkhDivBuilder = function(list){
	var container = document.createElement('div');
	for(var i = 0;i < list.length;i++){
		var inner = document.createElement('span');
		if(typeof list[i] == "object"){
			inner.appendChild(list[i]);
		}else{
			inner.innerHTML = list[i];
		}
		container.appendChild(inner);
	}
	return container;
	
};
AnkhCloseButton = function(){
	var closeButtonImg;
	if(isIE && !isMinIE7){
		closeButtonImg = "Image/04_AnkhControls/close button8.png";
	}else{
		closeButtonImg = "Image/04_AnkhControls/close button32.png";
	}
	var btn = new AnkhSprite(closeButtonImg,16,17,{x:0,y:0},{x:0,y:18},{x:0,y:18});
	btn.style.cursor = "pointer";
	return btn;
};
/**
 * Purpose: Create AJAX loading image
 * @param {String} directory - relative directory from root 
 */
AnkhAJAXLoader = function(directory){
	var ajaxLoader = document.createElement('img');
	ajaxLoader.src = directory + "Image/05_AJAXLoader/mainloading.gif";
	return ajaxLoader;
};
/**
 * Purpose: Generate a combo box
 * @param {Array} itemList - array of items which can contain "Value" and "InnerHTML" if they are different
 * @param {String} selectName - name of combo box
 * @param {String} selectedValue
 */
AnkhSelect = function(itemList,selectName,selectedValue){
	var select = document.createElement('select');
	select.id = selectName;
	select.name = selectName;
	
	for(var i = 0;i < itemList.length;i++){
		var option = document.createElement('option');		
		if (itemList[i].Value == null) {
			if(selectedValue == itemList[i]){
				option.selected = true;
			}
			option.value = itemList[i];
			option.innerHTML = itemList[i];
		}
		else {
			if(selectedValue == itemList[i].Value){
				option.selected = true;
			}
			option.value = itemList[i].Value;
			option.innerHTML = itemList[i].InnerHTML;
		}
		
		select.appendChild(option);
	}
	return select;
};

/**
 * Purpose: Generate an input textbox
 * @param {String} name
 * @param {String} value - default input value
 */
AnkhInput = function(name,value){
	var input = document.createElement('input');
	input.name = input.id = name;
	if(value){
		input.value = value;
	}
	input.type = "text";
	input.className = "textBox";
	return input;
};

AnkhInputAutoSelect = function(name,value){
	var input = new AnkhInput(name,value);
	input.readOnly = true;
	EventUtil.addEventHandler(input,"click",function(){EventUtil.getEvent().target.select();});
	return input;
}	

/**
 * Purpose: Generate a typical password textbox
 * @param {String} name
 * @param {String} value - default input value
 */
AnkhPwdInput = function(name,value){
	var input = document.createElement('input');
	input.name = input.id = name;
	if(value){
		input.value = value;
	}
	input.type = "password";
	input.className = "textBox";
	return input;
};

/**
 * Purpose: Generate a file input textboxs
 * @param {String} name
 */
AnkhFileInput = function(name){
	var file = document.createElement('input');
	file.name = file.id = name;
	file.type = "file";
	file.className = "fileUpload";
	file.size = "40";
	return file;
};
/**
 * Purpose: Textbox with max as the max. number of letters
 * @param {Object} parent
 * @param {String} name
 * @param {String} value
 * @param {Int} max
 * @param {Boolean} faint - if faint, then use the AnkhTextBoxWithContent
 */
AnkhInputWithMax = function(parent,name,value,max,faint){
	var container = document.createElement('div');
	parent.appendChild(container);
	var input;
	if(faint){		
		input = new AnkhTextBoxWithContent(name,value,"");		
	}else{
		input = new AnkhInput(name,value);		
	}
	container.appendChild(input);
	var maxCount = document.createElement('span');	
	maxCount.style.color = "#A8B6B9";
	maxCount.style.marginLeft = "5px";
	container.appendChild(maxCount);	
	var that = this;
	if(faint){
		var hidden = new AnkhHiddenInput(name+"_Real","");
		parent.appendChild(hidden);
	}else{
		var hidden = new AnkhHiddenInput(name+"_Real",value);
		parent.appendChild(hidden);
	}
	onKeyDown = function(){
		if(input.value.length > max ){
			input.value = input.value.substring(0, max);
		}
		hidden.value = input.value;
	};
	onKeyUp = function(){
		if(input.value.length > max ){
			input.value = input.value.substring(0, max);
		}	
		if(input.value.length == 0){
			maxCount.innerHTML = "Max: "+max+" letters";			
		}else{
			maxCount.innerHTML = input.value.length +"/"+max+" letters";
		}
		hidden.value = input.value;
	};	
	EventUtil.addEventHandler(input,"keydown",onKeyDown);
	EventUtil.addEventHandler(input,"keyup",onKeyUp);	
	EventUtil.addEventHandler(input,"mouseup",onKeyUp);	
	EventUtil.addEventHandler(input,"blur",onKeyUp);	
	
	this.getValue = function(){
		return input.value;
	};
	this.getInitialValue = function(){
		return input.initialValue;
	};
	this.setValue = function(value){
		input.value = value;					
		if( input.value.length != 0 && !faint){
			maxCount.innerHTML =  input.value.length +"/"+max+" letters";
		}else{
			maxCount.innerHTML = "Max: "+max+" letters";			
		}	
	}
	this.getHTML = function(){
		return container;
	};
	that.setValue(value);
};
/**
 * Purpose: Generate a textbox with content
 * @param {String} name
 * @param {String} initialValue
 * @param {String} currentValue
 */
AnkhTextBoxWithContent = function(name,initialValue,currentValue){
	var input = document.createElement('input');
	input.name = input.id = name;	
	input.initialValue = initialValue;	
	input.value = currentValue || initialValue;	
	input.type = "text";
	input.className = "AnkhTextBoxWithContent";
	
	if(currentValue){
		input.style.color = "#5E6F61";
	}
	
	init = function(){
		EventUtil.addEventHandler(input,"focus",onInputFocus);
		EventUtil.addEventHandler(input,"blur",onInputBlur);
	};
	
	onInputFocus = function(){
		if(EventUtil.getEvent().target.value == EventUtil.getEvent().target.initialValue){		
			EventUtil.getEvent().target.value = "";
			EventUtil.getEvent().target.style.color = "#5E6F61";			
		}
	};
	
	onInputBlur = function(){
		if(EventUtil.getEvent().target.value == ""){			
			EventUtil.getEvent().target.value = EventUtil.getEvent().target.initialValue;
			EventUtil.getEvent().target.style.color = "";
		}
	};
	init();
	return input;
};
/**
 * Purpose: Generate an input textbox with default content. Default content will be coloured in a light tone 
 * and it will be removed when the user has typed in new content.
 * @param {String} name
 * @param {String} value - default input value
 * @param {Boolean} password - true/false -> true, password input
 */
AnkhPasswordWithContent = function(name,value,pressEnter,parent,width){
	var pressEnter = pressEnter;	
	var parent = parent;
	var input = new AnkhTextBoxWithContent(name,value);
	if (width != null) {
		input.style.width = width + "px";
	}
	
	var pwdInput = document.createElement('input');
	pwdInput.type = "password";
	pwdInput.name = name;
	pwdInput.className = "AnkhTextBoxWithContent";
	if (width != null) {
		pwdInput.style.width = width + "px";
	}
	var pwdValue;
	
	init = function(){		
		EventUtil.addEventHandler(input,"focus",displayPasswordBox);
		//EventUtil.addEventHandler(input,"blur",displayPasswordBox);
		EventUtil.addEventHandler(pwdInput,"blur",displayInputBox);
		EventUtil.addEventHandler(pwdInput,"focus",onPwdFocus);
		EventUtil.addEventHandler(pwdInput,"keyup",function x(){
			pwdValue = EventUtil.getEvent().target.value;
			if(pressEnter != null && EventUtil.getEvent().keyCode == 13){									
				pressEnter();
				return;
			}
		});
		parent.appendChild(input);
	};

	onInputBlur = function(){
		if(EventUtil.getEvent().target.value == ""){
			EventUtil.getEvent().target.value = EventUtil.getEvent().target.initialValue;
			EventUtil.getEvent().target.style.color = "";
		}
	};
	
	displayPasswordBox = function(){			
		parent.replaceChild(pwdInput,input);
		pwdInput.focus();
		pwdInput.select();
	};
	
	onPwdFocus = function(){
		EventUtil.getEvent().target.style.color = "#5E6F61";
		EventUtil.getEvent().target.focus();
	};
		
	displayInputBox = function(){
		if (EventUtil.getEvent().target.value == "") {
			parent.replaceChild(input,pwdInput);
			input.value = input.initialValue;
		}
	};
	this.setTabIndex = function(value1,value2){		
		input.tabIndex = value1;
		pwdInput.tabIndex = value2;
	};
	this.getValue = function(){
		return pwdInput.value;
	};
	init();
};

/**
 * Purpose: Generate a generic button
 * @param {String} name
 * @param {String} value - default input value
 * @param {Boolean} confirmBtn - true if confirm/ false if cancel
 */
AnkhButton = function(name,value,confirmBtn){
	var input = document.createElement('input');
	input.name = input.id = name;
	input.value = value;
	input.type = "button";
	if (confirmBtn) {
		input.className = "normalSubmitBtn";
	}else{
		input.className = "resetBtn";
	}
	EventUtil.addEventHandler(input,"mouseover",function x(){input.style.backgroundColor = '#3f74c3'; input.style.color ='#FFFFFF'});
	EventUtil.addEventHandler(input,"mouseout",function x(){input.style.backgroundColor = ''; input.style.color = '';});		
	return input;
};
/**
 * Purpose: Generate a generic button
 * @param {String} name
 * @param {String} value - default input value
 * @param {Boolean} submitBtn - true if submit/ false if normal button
 */
AnkhSmallSubmitButton = function(name,value,submitBtn){
	var input = document.createElement('input');
	input.name = input.id = name;	
	input.className = "normalSubmitBtn";		
	if (submitBtn) {		
		input.type = "submit";
	}else{		
		input.type = "button";
	}
	input.value = value;
	EventUtil.addEventHandler(input,"mouseover",function x(){input.style.backgroundColor = '#3f74c3'; input.style.color ='#FFFFFF'});
	EventUtil.addEventHandler(input,"mouseout",function x(){input.style.backgroundColor = ''; input.style.color = '';});
	EventUtil.addEventHandler(input,"focus",function x(){input.style.backgroundColor = '#3f74c3'; input.style.color ='#FFFFFF'});
	EventUtil.addEventHandler(input,"blur",function x(){input.style.backgroundColor = ''; input.style.color = '';});
		
	return input;
};
/**
 * Purpose: Generate a textarea
 * @param {String} name
 * @param {String} value
 */
AnkhTextArea = function(name,value){
	var textarea = document.createElement('textarea');
	textarea.name = textarea.id = name;
	if(value != "" && value!=null){
		textarea.value = value;	
	}
	return textarea;
};

AnkhTextAreaWithMax = function(parent,name,defaultValue,currentValue,num,width,height){
	var container = document.createElement('div');
	parent.appendChild(container);
	var textarea = new AnkhTextAreaWithContent(container,name,defaultValue,currentValue,width,height);	
	var maxCount = document.createElement('div');
	maxCount.style.textAlign = "right";
	maxCount.innerHTML = "Max "+num+" characters";
	container.appendChild(maxCount);
	EventUtil.addEventHandler(textarea.getHTML(),"keydown",function x(){		
		if(textarea.getHTML().value.length > num ){
			textarea.getHTML().value = textarea.getHTML().value.substring(0, num);
		}		
	});
	EventUtil.addEventHandler(textarea.getHTML(),"keyup",function x(){
		if(textarea.getHTML().value.length > num ){
			textarea.getHTML().value = textarea.getHTML().value.substring(0, num);
		}	
		if(textarea.getHTML().value.length == 0){
			maxCount.innerHTML = "Max: "+num+" characters";
		}else{
			maxCount.innerHTML = textarea.getHTML().value.length +" of "+num+" characters";
		}
	});
	
	this.getValue = function(){
		return textarea.getValue();
	};
	this.setValue = function(value){
		textarea.setValue(value);	
		if( textarea.getValue().length == 0){
			maxCount.innerHTML = "Max: "+num+" characters";
		}else{
			maxCount.innerHTML =  textarea.getValue().length +" of "+num+" characters";
		}	
	}
};

AnkhTextAreaWithContent = function(parent,name,defaultValue,currentValue,width,height){

	var value = currentValue || defaultValue;
	var container = document.createElement('div');
	parent.appendChild(container);
	var textarea = new AnkhTextArea("",value);
	container.appendChild(textarea);
	var realValue = new AnkhHiddenInput(name,"");
	container.appendChild(realValue);
	textarea.defaultValue = defaultValue;
	textarea.className = "AnkhTextAreaWithContent";
	if(width){
		textarea.style.width = width + "px";
	}
	if(height){
		textarea.style.height = height +"px";
	}
	if(currentValue){
		textarea.style.color = "#5E6F61";
	}
	
	init = function(){
		EventUtil.addEventHandler(textarea,"focus",onTextAreaFocus);
		EventUtil.addEventHandler(textarea,"blur",onTextAreaBlur);
		EventUtil.addEventHandler(textarea,"keyup",changeRealValue);
	};
	changeRealValue = function(){
		if(EventUtil.getEvent().target.value == defaultValue){
			realValue.value = "";
		}else{
			realValue.value = EventUtil.getEvent().target.value;	
		}		
	};
	onTextAreaFocus = function(){
		if(EventUtil.getEvent().target.value == EventUtil.getEvent().target.defaultValue){		
			EventUtil.getEvent().target.value = "";
			EventUtil.getEvent().target.style.color = "#5E6F61";			
		}
	};
	
	onTextAreaBlur = function(){
		if(EventUtil.getEvent().target.value == ""){
			EventUtil.getEvent().target.value = EventUtil.getEvent().target.defaultValue;
			EventUtil.getEvent().target.style.color = "";
		}
	};
	
	this.getValue = function(){
		return realValue.value;
	};
	this.setValue = function(real){		
		realValue.value = real;
		textarea.value = real;				
	};
	this.getHTML = function(){
		return textarea;
	};
	init();
	
};
/**
 * Purpose: Generate a hidden input
 * @param {String} name
 * @param {String} value
 */
AnkhHiddenInput = function(name,value){
	var hiddenInput = document.createElement('input');
	hiddenInput.type = "hidden";
	if(value){
		hiddenInput.value = value;
	}
	hiddenInput.id = hiddenInput.name = name;
	return hiddenInput;
};
/**
 * Purpose: Create a single checkbox
 * @param {String} name
 * @param {String} key
 */
AnkhCheckBox = function(name,key,value){	
	var checkBox = document.createElement('input');
	checkBox.style.verticalAlign = "middle";
	checkBox.type = "checkbox";
	if (value != "" && value != null) {
		checkBox.value = value;
	}
	if (key != null && String(key) != "") {	
		checkBox.id = checkBox.name = name + "[" + key + "]";		
	}else{
		checkBox.id = checkBox.name = name;
	}
	return checkBox;
};
/**
 * Purpose: Create a toggle link to toggle fields
 * @param {String} id
 * @param {String} dataText 
 * @param {String} displayTxt - text to show to user to display text
 * @param {String} hideTxt - text to show to user to hide text
 * @param {Boolean} statusSelected - true ->selected
 * @param {Func} handler - when this object is been toggled, handler is called to return target
 * @param {Object} target - target object to be returned when this link is been toggled
 */
AnkhToggleLink = function(id,dataText,displayTxt,hideTxt,statusSelected,handler,target){
	var that = this;	
	var displayTxt = displayTxt;
	var hideTxt = hideTxt;	
	var statusSelected = statusSelected;
	var link;
	
	var container = document.createElement('div');	
	if(typeof dataText == "object"){
		data = dataText;
	}else{		
		var data = document.createElement('span');
		data.innerHTML = dataText;
	}
	var status = new AnkhHiddenInput(id,statusSelected);	
	
	init = function(){
		if(statusSelected){
			link = new AnkhLink(hideTxt, that.toggle);
		}else{			
			data.style.color = "#C1CCB5";
			link = new AnkhLink(displayTxt, that.toggle);
		}		
		link.style.cssFloat = "right";
		link.style.styleFloat = "right";
		
		container.appendChild(link);		
		container.appendChild(data);
		container.appendChild(status);
	};
	
	this.toggle = function(){
		statusSelected = !statusSelected;		
		if(statusSelected){
			link.innerHTML = hideTxt;
			data.style.color = "";
			status.value = true;
		}else{
			link.innerHTML = displayTxt;
			data.style.color = "#C1CCB5";
			status.value = false;
		}
		if(handler){
			if(target){
				handler(target,statusSelected);
			}else{
				handler(statusSelected);
			}
		}
	};
	
	init();
	return container;
};

/**
 * Purpose: Generate a Ankh Link
 * @param {String} text
 * @param {Func} mouseup - Event Handler upon mouseup
 * @param {String} href
 * @param {String} selectedClass
 * @param {Boolean} content
 * @param {Object} color -> e.g. {mouseover:#111111,mouseout:#222222}
 */
AnkhLink = function(text,mouseup,href,selectedClass,content,color){
	var that = this;
	var link = document.createElement('a');
	var defaultLinkClass;	
	var defaultMOLinkClass;
	if (content) {
		defaultLinkClass = "Link_Content";
		defaultMOLinkClass = "Link_Content_MouseOver";		
	}else{
		defaultLinkClass = "Link";
		defaultMOLinkClass = "Link_MouseOver";
	}	
	link.className = defaultLinkClass;
	link.innerHTML = text;
	link.selectedClass = selectedClass;
	if(color){
		link.customOverColor = color['mouseover'];
		link.customOutColor = color['mouseout'];
		link.style.color = link.customOutColor;
	}
	
	var mouseup = mouseup;
	if (href != null && href != "") {
		link.href = href;
	}
	init = function(){
		EventUtil.addEventHandler(link,"mouseover",that.mouseOverLink);
		EventUtil.addEventHandler(link,"mouseout",that.mouseOutLink);
		EventUtil.addEventHandler(link,"click",that.mouseupLink);
	};
	this.mouseupLink = function(){
		if (EventUtil.getEvent().target.selectedClass != null && EventUtil.getEvent().target.selectedClass != "") {
			EventUtil.getEvent().target.className = EventUtil.getEvent().target.selectedClass;
		}
		if (mouseup != null && mouseup != "") {
			mouseup(EventUtil.getEvent().target,EventUtil.getEvent());
		}				
	};
	
	this.mouseOverLink = function(){		
		if (EventUtil.getEvent().target.className != EventUtil.getEvent().target.selectedClass && 
		EventUtil.getEvent().target.className == defaultLinkClass) {
			EventUtil.getEvent().target.className = defaultMOLinkClass;
			if(EventUtil.getEvent().target.customOverColor){
				EventUtil.getEvent().target.style.color = EventUtil.getEvent().target.customOverColor;
			}
		}
	};
	this.mouseOutLink = function(){		
		if (EventUtil.getEvent().target.className != EventUtil.getEvent().target.selectedClass && 
		EventUtil.getEvent().target.className == defaultMOLinkClass) {
			EventUtil.getEvent().target.className = defaultLinkClass;
			if(EventUtil.getEvent().target.customOutColor){
				EventUtil.getEvent().target.style.color = EventUtil.getEvent().target.customOutColor;
			}
		}
	};
	
	init();
	return link;
};



/**
 * Purpose: Generae a Ankh Submit button which upon mouseover will display the ankh logo
 * @param {String} dirFromImage - directory from the image directory
 * @param {String} text - value of submit button
 * @param {String} mouseOverColour - colour upon mouseover
 */
AnkhSubmitButton = function(dirFromImage,text,mouseOverColour){
	var dirFromImage = dirFromImage;	
	var submitBtn= document.createElement('input');
	submitBtn.type = "submit";
	submitBtn.value = text;
	submitBtn.className = "submitBtn";
	var mouseOverColour = mouseOverColour;
	
	var img;
	if(isIE && !isMinIE7){
		img = dirFromImage+"Image/04_AnkhControls/white-ankh-man8.png";		
	}else{
		img = dirFromImage+"Image/04_AnkhControls/white-ankh-man.png";	
	}
	var image = new Image();
	image.src = img;
	
	initEventHandlers = function(){
		EventUtil.addEventHandler(submitBtn,"mouseover",mouseOver);
		EventUtil.addEventHandler(submitBtn,"mouseout",mouseOut);		
		EventUtil.addEventHandler(submitBtn,"focus",mouseOver);		
		EventUtil.addEventHandler(submitBtn,"blur",mouseOut);
	};
	mouseOver = function(){	
		EventUtil.getEvent().target.style.backgroundColor = mouseOverColour;		
		EventUtil.getEvent().target.style.backgroundImage = "url('"+img+"')";		
		EventUtil.getEvent().target.style.backgroundRepeat = "no-repeat";
		EventUtil.getEvent().target.style.backgroundPosition = "30% 10%";
		EventUtil.getEvent().target.style.color = "#FFFFFF";
		
	};
	mouseOut = function(){
		EventUtil.getEvent().target.style.backgroundColor = "";
		EventUtil.getEvent().target.style.backgroundImage = "";
		EventUtil.getEvent().target.style.color = "";
		
	};
	
	initEventHandlers();
	return submitBtn;
};

/**
 * Purpose: Generate a reset button
 * @param {String} text - display value of the button
 */
AnkhResetButton = function(text){
	var resetBtn = document.createElement('input');
	resetBtn.type = "reset";
	resetBtn.value = text;
	resetBtn.className = "resetBtn";
	return resetBtn;
};
/**
 * Purpose: Provide a generic method to alternate between error container and notification container
 * @param {Object} parent
 * @param {Boolean} success
 * @param {String} category
 * @param {Array} messages
 * @param {String} id
 */
AnkhStatusMessageContainer = function(parent,success,category,messages,id){
	var message;
	if(success){		
		message = new AnkhFormNotificationContainer(parent,id);				
		if(messages.length && typeof messages == "object"){
			message.showWithLayout(category,messages[0]);
		}else{
			message.showWithLayout(category,messages);			
		}			
	}else{
		message = new AnkhFormErrorContainer(parent,id);
		if(messages.length && typeof messages == "object"){
			message.showWithLayout(category,messages[0]);
		}else{
			message.showWithLayout(category,messages);	
		}
	}
	return message.getHTML();
};
/**
 * Purpose: Create a positive notification form container
 * @param {Object} parent
 * @param {String} id
 * @param {String} type - normally null => yellow, blue => blue, green => green
 */
AnkhFormNotificationContainer = function(parent,id,type){
	var notify = document.createElement('div');	
	notify.id = id;
	if (type == "blue") {
		notify.className = "ImptMsgContainerBlue";		
	}else if(type=="green"){
		notify.className = "ImptMsgContainerGreen";
	}else{
		notify.className = "ImptMsgContainer";
	}
	parent.appendChild(notify);

	this.show = function(displayText){
		AnkhUsefulMethods.removeAll(notify);				
		if (typeof displayText == "object") {			
			notify.appendChild(displayText);
		}
		else {				
			var div = document.createElement('div');
			div.innerHTML = displayText;
			notify.appendChild(div);
		}
		notify.style.visibility = "visible";
		notify.style.display = "block";
	};
	this.showWithLayout = function(header,content){
		AnkhUsefulMethods.removeAll(notify);
		var container = document.createElement('div');
		var containerHeader = document.createElement('div');		
		if(typeof header == "object"){
			containerHeader.appendChild(header);
		}else{
			containerHeader.innerHTML = "<b>"+header+"</b>";
		}
		container.appendChild(containerHeader);
		var containerContent;
		if (typeof content == "object") {
			containerContent = content;
			container.appendChild(containerContent);
		}else{
			containerContent = document.createElement('div');
			containerContent.innerHTML = content;
			container.appendChild(containerContent);
		}
		notify.appendChild(container);
		notify.style.visibility = "visible";
		notify.style.display = "block";
	};
	this.hide = function(){
		notify.style.visibility = "hidden";
		notify.style.display = "block";		
	};
	this.getHTML = function(){
		return notify;
	};
};
/**
 * Purpose: Create a error form container
 * @param {Object} parent
 * @param {String} id
 */
AnkhFormErrorContainer = function(parent,id){
	var err = document.createElement('div');	
	err.id = id;
	err.className = "ErrorContainer";	
	parent.appendChild(err);
	
	this.show = function(displayText){
		AnkhUsefulMethods.removeAll(err);		
		if (typeof displayText == "object") {
			err.appendChild(displayText);
		}
		else {				
			err.innerHTML = displayText;
		}
		err.style.visibility = "visible";
		err.style.display = "block";
	};
	this.showWithLayout = function(header,content){
		AnkhUsefulMethods.removeAll(err);
		var container = document.createElement('div');
		var containerHeader = document.createElement('div');
		containerHeader.innerHTML = "<b>"+header+"</b>";
		container.appendChild(containerHeader);
		var containerContent;
		if (typeof content == "object") {
			containerContent = content;
			container.appendChild(containerContent);
		}else{
			containerContent = document.createElement('div');
			containerContent.innerHTML = content;
			container.appendChild(containerContent);
		}		
		err.appendChild(container);
		err.style.visibility = "visible";
		err.style.display = "block";
	};
	this.hide = function(){
		err.style.visibility = "hidden";
		err.style.display = "block";		
	};
	this.getHTML = function(){
		return err;
	};
};
/**
 * Purpose: Create a radio button 
 * @param {String} groupId
 * @param {String} value
 * @param {Boolean} checked
 * @param {String} text
 */
AnkhRadioBtn = function(groupId,value,checked,text){	
	var radio;
	if(isIE && isMinIE8){
		 radio = document.createElement('input');  
	}else{
		try{  
			var creationStr;			
			if (checked) {
				
				creationStr = '<input type="radio" name="' + groupId + '" value="' + value + '" checked=true />';
			}
			else {				
				creationStr = '<input type="radio" name="' + groupId + '" value="' + value + '" />';
			}
			
		    radio = document.createElement(creationStr);  
		}catch(err){  		
			 radio = document.createElement('input');  
		}  
	}
	radio.setAttribute('type','radio');  
	radio.setAttribute('name',groupId);  
	radio.setAttribute('value',value);  
	if (checked) {
		radio.setAttribute('checked', checked);
	}	  
	if (text) {
		var radioContainer = document.createElement('div');
		radioContainer.appendChild(radio);
		var radioTxt = document.createElement('span');
		radioTxt.innerHTML = text;
		radioContainer.appendChild(radioTxt);
		return radioContainer;
	}
	else {
		return radio;
	}
};

/**
 * Purpose: Create a display picture
 * @param {String} pictureLink
 * @param {Func} removeBtnMouseup
 */
AnkhDisplayPicture= function(pictureLink){

	var container = document.createElement('div');	
	container.style.margin = "3px";	
	container.style.textAlign = "center";		
	var picture = document.createElement('img');
	picture.src = pictureLink;
	picture.style.border = "1px solid #C1CCB5";
	picture.style.padding = "3px";			
	container.appendChild(picture);	
	return container;
};


/**
 * Purpose: Create a display picture with a radio button and a checkbox. 
 * If radioTxt = null, radio button is not created.
 * If checkBoxTxt =  null, checkbox is not created. 
 * @param {String} pictureLink
 * @param {String} radioValue
 * @param {String} radioName
 * @param {String} radioTxt
 * @param {Boolean} radioSelected
 */
AnkhDisplayPicRadioCheckbox = function(pictureLink,radioValue,radioName,radioTxt,radioSelected,
checkBoxValue,checkBoxName,checkBoxTxt,onRadioChangeHandler){
	
	var container = document.createElement('div');
	container.style.textAlign = "center";

	var displayPic = new AnkhDisplayPicture(pictureLink);
	container.appendChild(displayPic);
	
	var radioCheckboxContainer = document.createElement('div');
	radioCheckboxContainer.style.marginLeft = "3px";
	radioCheckboxContainer.style.marginRight = "3px";
	radioCheckboxContainer.style.background = "#DDDFD1";
	container.appendChild(radioCheckboxContainer);
	if (radioTxt != null) {		
		var radio = new AnkhRadioBtn(radioName,radioValue,radioSelected);
		radioCheckboxContainer.appendChild(radio);	
		var textNode = document.createTextNode(radioTxt);
		radioCheckboxContainer.appendChild(textNode);
		if(onRadioChangeHandler){
			EventUtil.addEventHandler(radio,"click",onRadioChangeHandler);
		}
	}
	if (checkBoxTxt != null) {
		var checkBoxContainer = document.createElement('div');
		radioCheckboxContainer.appendChild(checkBoxContainer);
		var checkbox = new AnkhCheckBox(checkBoxName,checkBoxValue);		
		checkBoxContainer.appendChild(checkbox);
		var textNode = document.createTextNode(checkBoxTxt);
		checkBoxContainer.appendChild(textNode);		
	}	
	return container;
};


/**
 * Purpose: Generate a series of up to 3 combo boxes to display the date
 * @param {Object} parent
 * @param {Boolean} displayYr - show the year combo box
 * @param {Boolean} displayMth - show the month combo box
 * @param {Boolean} displayDay - show the day combo box
 * @param {Boolean} showCurrent - show the word current
 * @param {String} name - name of this control
 * @param {DateTime} selectedDate - JS Date time or "-". If "-", then it means that the default is "-"
 * @param {Int} startingYr - starting year. If not indicated, it will take today's year
 */
AnkhCalendarControl = function(parent,displayYr,displayMth,displayDay,showCurrent,name,selectedDate,startingYr,future){
	var ankhDate = new AnkhDate();
	var that = this;
	var currentDate = false;	
	var isBlank = false;
	
	if(selectedDate ==  "-"){
		isBlank = true;
	}
	else if(selectedDate == "" || selectedDate == null || selectedDate == "current"){
		selectedDate = new Date();
		currentDate = true;
	}	
	var container = document.createElement('div');		
	parent.appendChild(container);
	
	var months = ankhDate.getMonths();
	var mthItemList = new Array();
	if(isBlank){
		mthItemList.push({"Value":"-","InnerHTML":"-"});	
	}
	for(var i = 0;i < months.length;i++){
		mthItemList.push({"Value":i,"InnerHTML":months[i]});		
	}
	if (displayMth) {
		if (isBlank) {
			var comboMth = new AnkhSelect(mthItemList, name + "[m]", "-");
		}
		else {			
			var comboMth = new AnkhSelect(mthItemList, name + "[m]", selectedDate.getMonth());
		}
		container.appendChild(comboMth);
	}
	if (displayDay) {
		var comboDay = document.createElement('select');
		comboDay.name = comboDay.id = name + "[d]";
		if(displayMth){
			comboDay.style.marginLeft = "5px";
		}
		container.appendChild(comboDay);
	}
	
	if (displayYr) {
		var date = new Date();
		var yearList = new Array();
		if (showCurrent) {
			yearList.push("Current");
		}
		if (isBlank) {
			yearList.push("-");
		}
		var firstYr = startingYr || date.getFullYear();
		if(future){
			for (var i = firstYr; i <= firstYr + 5; i++) {
				yearList.push(i);
			}
		}else{
			for (var i = firstYr; i >= 1880; i--) {
				yearList.push(i);
			}
		}
		var comboYr;
		if (currentDate) {
			comboYr = new AnkhSelect(yearList, name + "[y]", "current");
		}
		else 
			if (isBlank) {
				comboYr = new AnkhSelect(yearList, name + "[y]", "-");
			}
			else {
				comboYr = new AnkhSelect(yearList, name + "[y]", selectedDate.getFullYear());
			}
		if(displayDay || comboMth){
			comboYr.style.marginLeft = "5px";
		}		
		container.appendChild(comboYr);
	}
	initEventHandlers = function(){
		if (displayYr && displayMth && displayDay) {
			EventUtil.addEventHandler(comboMth, "change", function x(){
				that.setDays(comboMth[comboMth.selectedIndex].value, comboYr[comboYr.selectedIndex].value);
			});
			EventUtil.addEventHandler(comboYr, "change", function x(){
				that.setDays(comboMth[comboMth.selectedIndex].value, comboYr[comboYr.selectedIndex].value);
			});
		}
	};
	
	/**
	 * Purpose: Set number of days based on the input month and year
	 * @param {Int} month
	 * @param {Int} year
	 */
	this.setDays = function(month,year){
		var days;
		if (month == "-" || year == "-") {
			days = 31;		
		}
		else {
			var month = parseInt(month, 10);
			var year = parseInt(year, 10);
			days = ankhDate.daysInAMonth(month + 1, year);
		}
		var selectedValue = "-";
		if (comboDay.selectedIndex >= 0) {
			selectedValue = comboDay.childNodes[comboDay.selectedIndex].value;
		}
		AnkhUsefulMethods.removeAll(comboDay);
		if(isBlank){
			var comboDayOption = document.createElement('option');
			comboDayOption.innerHTML = "-";
			comboDayOption.value = "-";				
			comboDay.appendChild(comboDayOption);
		}
		
		for (var i = 1; i <= days; i++) {
			var comboDayOption = document.createElement('option');
			comboDayOption.innerHTML = i;
			comboDayOption.value = i;			
			comboDay.appendChild(comboDayOption);
		}	
		
		for(var i = 0;i < comboDay.childNodes.length;i++){
			if(comboDay.childNodes[i].value == selectedValue){
				comboDay.childNodes[i].selected = true;
			}
		}
	};
			
	if (displayYr && displayMth && displayDay) {
		that.setDays(comboMth[comboMth.selectedIndex].value, comboYr[comboYr.selectedIndex].value);
		if (selectedDate == "-") {	
			comboDay.selectedIndex = 0;
		}
		else {	
			comboDay.selectedIndex = selectedDate.getDate() - 1;
		}
	}
	initEventHandlers();
	
	
	this.getDateValue = function(){		
		if (displayYr && displayMth && displayDay) {
			return new Date(comboYr[comboYr.selectedIndex].value, comboMth[comboMth.selectedIndex].value, comboDay[comboDay.selectedIndex].value);
		}else if(displayYr && displayMth && !displayDay){
			return new Date(comboYr[comboYr.selectedIndex].value, comboMth[comboMth.selectedIndex].value, 1);
		}else{
			return new Date(comboYr[comboYr.selectedIndex].value, 0, 1);
		}	
	};
	this.getYr = function(){
		return comboYr[comboYr.selectedIndex].value;
	};
	this.getMth = function(){
		return comboMth[comboMth.selectedIndex].value;
	};
	this.getDay = function(){
		return comboDay[comboDay.selectedIndex].value;
	};
	this.getTimeStamp = function(){
		return that.getDateValue().getTime();
	};
	this.reset = function(displayYr,displayMth,displayDay){
		var date = new Date();
		if (displayMth) {			
			comboMth.selectedIndex = date.getMonth();
		}
		if (displayDay) {			
			comboDay.selectedIndex = date.getDate() - 1;
		}
		
		if (displayYr) {
			for(var i = 0; i < comboYr.childNodes.length;i++){
				if(date.getFullYear() == comboYr.childNodes[i].value){
					comboYr.selectedIndex = i;
				}
			}
		}
	}
	this.getHtml = function(){
		return container;
	};
	this.disable = function(value){
		
		if(value){
			comboDay.prevSelectedIndex = comboDay.selectedIndex;
			comboMth.prevSelectedIndex = comboMth.selectedIndex;
			comboYr.prevSelectedIndex = comboYr.selectedIndex;
			var optionDay = document.createElement('option');	
			var optionMth = document.createElement('option');
			var optionYr = document.createElement('option');		
			
			if(!isIE){
				comboDay.add(optionDay,null);						
				comboMth.add(optionMth,null);			
				comboYr.add(optionYr,null);
			}else{
				comboDay.options.add(optionDay);						
				comboMth.options.add(optionMth);			
				comboYr.options.add(optionYr);
			}	
			optionDay.innerHTML = optionMth.innerHTML = optionYr.innerHTML = "-";	
			optionDay.value = optionMth.value = optionYr.value = "-";	
			comboDay.selectedIndex = comboDay.options.length - 1;
			comboMth.selectedIndex = comboMth.options.length - 1;
			comboYr.selectedIndex = comboYr.options.length - 1;			
		}else{
			if(!isIE){
				comboDay.remove(comboDay.options.length - 1);
				comboMth.remove(comboMth.options.length - 1);
				comboYr.remove(comboYr.options.length - 1);
			}else{
				comboDay.options.remove(comboDay.options.length - 1);
				comboMth.options.remove(comboMth.options.length - 1);
				comboYr.options.remove(comboYr.options.length - 1);
			}	
			
			comboDay.selectedIndex = comboDay.prevSelectedIndex;
			comboMth.selectedIndex = comboMth.prevSelectedIndex;
			comboYr.selectedIndex = comboYr.prevSelectedIndex;		
			
		}
		comboDay.disabled = value;
		comboMth.disabled = value;
		comboYr.disabled = value;
	};
};AnkhToolTip = function(parent,width){
	var ankhToolTipContainer = document.createElement('div');
	ankhToolTipContainer.id = "AnkhToolTip";
	parent.appendChild(ankhToolTipContainer);
	
	var pointer = document.createElement('img');	
	if(isIE && !isMinIE7){
		pointer.src = "Image/04_AnkhControls/tooltipPointer8.png";
	}else{
		pointer.src = "Image/04_AnkhControls/tooltipPointer.png";
	}
	ankhToolTipContainer.appendChild(pointer);
	
	var container = document.createElement('div');
	container.className = "container";
	container.style.width = width + "px";
	ankhToolTipContainer.appendChild(container);
	
	var headerObj = document.createElement('div');	
	headerObj.className = "header"		
	container.appendChild(headerObj);
	
	var contentObj = document.createElement('div');	
	contentObj.className = "content";
	container.appendChild(contentObj);
	
	/**
	 * Purpose: Display the Ankh Tool Tip at the right location
	 * @param {Object} header
	 * @param {Object} content
	 * @param {Int} top	- absolute top from parent
	 * @param {Int} left = absolute left from parent
	 * @param {Boolean} anchorleft
	 */
	this.display = function(header,content,top,left,anchorleft){
		if(header){
			if(typeof header == "object"){
				headerObj.appendChild(header);
			}else{
				headerObj.innerHTML = header;
			}
		}
		if(content){
			if(typeof content == "object"){
				contentObj.appendChild(content);
			}else{
				contentObj.innerHTML = content;	
			}		
		}
		ankhToolTipContainer.style.top = top +"px";		
		if(anchorleft){					
			ankhToolTipContainer.style.left = left + "px";
			pointer.className = "pointerLeft";
			pointer.style.left = "30px";
		}else{
			ankhToolTipContainer.style.left = left - (width - 50) + "px";
			pointer.className = "pointerRight";
			pointer.style.left = width - 20 + "px";
		}
		ankhToolTipContainer.style.display = "block";
		ankhToolTipContainer.style.visibility = "visible";
	};
	this.hide = function(){
		ankhToolTipContainer.style.display = "none";
		ankhToolTipContainer.style.visibility = "hidden";		
		AnkhUsefulMethods.removeAll(headerObj);
		AnkhUsefulMethods.removeAll(contentObj);
	};
	this.getContainer = function(){
		return ankhToolTipContainer;		
	};
};
/**
 * Purpose: Draw the auto completion box
 * @param {Object} parent - parent HTML object
 * @param {Object} dataSet
 * @param {String} keyField
 * @param {String} valueField
 * @param {Array} subKeyFields - array of subkey fields
 * @param {Boolean} strict
 * @param {String} initValue
 * @param {String} name
 * @param {String} noResult
 * @param {Boolean} showAllWhenNoResult
 */
AutoCompleteBox = function(parent,dataSet,keyField,valueField,subKeyFields,strict,initValue,name,noResult,showAllWhenNoResult,maxHeight,width,hideWhenClickOut,loose){
	var NORESULT = noResult || "No matched result";
	var dataSet = dataSet;
	var keyField = keyField;
	var valueField = valueField;
	var subKeyFields = subKeyFields;
	var that = this;
	var onConfirmed;
	var prevSelected;
	var emptyDisplayText;				//msg to be displayed when the textbox is empty
	var ajaxQueryCount = 0;		
	var prevValue = "";
	
	var container = document.createElement('div');
	container.className = "AutoCompleteBox";	
	parent.appendChild(container);

	var boxContainer = document.createElement('div');
	var box = document.createElement('input');
	box.type = "text";	
	box.name = box.id = name;	
	box.className = "textBox"
	if(width){
		box.style.width = width + "px";	
	}		
	if(initValue){			
		box.value = initValue;
	}
	
	boxContainer.appendChild(box);
	
	var hiddenBoxValue = document.createElement('input');
	hiddenBoxValue.type = "hidden";
	
	boxContainer.appendChild(hiddenBoxValue);
	container.appendChild(boxContainer);
	
	var suggestionBox = document.createElement('div');
	suggestionBox.className = "SuggestionBox";
	if(width){
		suggestionBox.style.width = width + 10 + "px";
	}
	var sugggestionBoxMaxHeight = maxHeight || 200;
	suggestionBox.style.maxHeight = sugggestionBoxMaxHeight+"px";
	suggestionBox.inputControl = box;
	suggestionBox.parent = parent;
	container.appendChild(suggestionBox);
	
	box.suggestionBox = suggestionBox;	
	
	var navigationKeyPressed = false;
	
	initEventHandler = function(){
		EventUtil.addEventHandler(box,"keyup",drawSuggestionBoxKey);
		EventUtil.addEventHandler(box,"click",drawSuggestionBox);		
		EventUtil.addEventHandler(box,"keydown",navigateSuggestionBox);
		EventUtil.addEventHandler(suggestionBox,"click",function(){
			EventUtil.getEvent().stopPropagation();
		});					
		EventUtil.addEventHandler(document.body,"click",function x(){
			if(!hideWhenClickOut){			
				that.locateOption();
			}
			that.removeSuggestionBox();
		});
	};
	/**
	 * Purpose: To remove all divs within the suggestionbox and to hide suggestionbox
	 */
	this.removeSuggestionBox = function(){					
		AnkhUsefulMethods.removeAll(suggestionBox);	
		suggestionBox.style.visibility = "hidden";
	};
	/**
	 * Purpose: to navigate the suggestion boxes
	 */
	navigateSuggestionBox = function(){
		var suggestionBox = EventUtil.getEvent().target.suggestionBox;
		navigationKeyPressed = true;
		switch(EventUtil.getEvent().keyCode){
			case 13:	var optionSelected = false;
						for(var i=0;i< suggestionBox.childNodes.length;i++){		//pressing enter
							if (suggestionBox.childNodes[i].selected) {																	
								that.confirmOption(suggestionBox.childNodes[i]);						
								optionSelected = true;
								break;
							}
						}				
						if(!optionSelected){
							that.locateOption(suggestionBox);
						}							
						EventUtil.getEvent().preventDefault();
						break;
			case 38:	var index = 0;				//moving up
						for(var i = 0;i < suggestionBox.childNodes.length;i++){
							if(suggestionBox.childNodes[i].selected){
								index = i;
								break;
							}
						}
						if(index != 0){
							var currentIndex = index - 1;
							suggestionBox.childNodes[index].style.backgroundColor = "";
							suggestionBox.childNodes[index].selected = false;
							suggestionBox.childNodes[currentIndex].style.backgroundColor = "#DDDFD1";
							suggestionBox.childNodes[currentIndex].selected = true;																		
							var prevSelectedDiv = suggestionBox.childNodes[currentIndex];
							if(prevSelectedDiv.offsetTop - suggestionBox.scrollTop  < 0){
								suggestionBox.scrollTop = suggestionBox.scrollTop - prevSelectedDiv.offsetHeight;		
							}			
							if(!loose){							
								prevSelected = prevSelectedDiv.value;
							}
						}
						break;
			case 40:	var index = -1;				//moving down
						for(var i = 0;i < suggestionBox.childNodes.length;i++){
							if(suggestionBox.childNodes[i].selected){
								index = i;
								break;
							}
						}
						if(index != suggestionBox.childNodes.length - 1){
							var currentIndex = index + 1;
							if (index != -1) {
								suggestionBox.childNodes[index].style.backgroundColor = "";
								suggestionBox.childNodes[index].selected = false;
							}
							suggestionBox.childNodes[currentIndex].style.backgroundColor = "#DDDFD1";
							suggestionBox.childNodes[currentIndex].selected = true;
							var prevSelectedDiv = suggestionBox.childNodes[currentIndex];									
							if(prevSelectedDiv.offsetTop + prevSelectedDiv.offsetHeight > suggestionBox.clientHeight){
								suggestionBox.scrollTop = suggestionBox.scrollTop + prevSelectedDiv.offsetHeight;		
							}
							if(!loose){
								prevSelected = prevSelectedDiv.value;
							}						
						}																								
						break;
						
			default:	navigationKeyPressed = false;
						break; 	
		};
	};
	/**
	 * Purpose: To draw the suggestion box under the textbox
	 */
	drawSuggestionBox = function(){	
		navigationKeyPressed = false;
		var value = box.value;	
		if(emptyDisplayText!=null && value == "" && !showAllWhenNoResult){
			that.removeSuggestionBox();	
			suggestionBox.appendChild(emptyDisplayText);
			suggestionBox.style.visibility = "visible";
		}															
		if (value != "") {		
			that.removeSuggestionBox();								
			that.addIn(value);						
		} else if(showAllWhenNoResult){
			that.removeSuggestionBox();					
			that.addInWithoutValue(value);				
		}
		
		that.drawIframe();
		EventUtil.getEvent().stopPropagation();
		EventUtil.getEvent().preventDefault();
	};
	drawSuggestionBoxKey = function(){		
		var value = box.value;	
		if(emptyDisplayText!=null && value == "" && !showAllWhenNoResult){
			that.removeSuggestionBox();	
			suggestionBox.appendChild(emptyDisplayText);
			suggestionBox.style.visibility = "visible";
		}	
		if (!navigationKeyPressed) {												
			if (value != "") {		
				that.removeSuggestionBox();								
				that.addIn(value);						
			} else if(showAllWhenNoResult){
				that.removeSuggestionBox();					
				that.addInWithoutValue();				
			}
		}
		that.drawIframe();
		EventUtil.getEvent().stopPropagation();
		EventUtil.getEvent().preventDefault();
	};

	/**
	 * Purpose: Used to add in the suggested word when there box.value is empty	 
	 */
	this.addInWithoutValue = function(){		
		for(var i = 0;i < dataSet.length;i++){
			var suggestedWord = document.createElement('div');
			suggestedWord.className = "SuggestionWord";
			
			if(keyField){		
				suggestedWord.innerHTML = dataSet[i][keyField];						
				suggestedWord.value = dataSet[i][keyField];
				suggestedWord.innerValue = dataSet[i][valueField];
			}else{
				suggestedWord.innerHTML = dataSet[i];
				suggestedWord.value = dataSet[i];
			}
			suggestionBox.appendChild(suggestedWord);
			EventUtil.addEventHandler(suggestedWord, "mouseover", mouseOverSuggestedWord);
			EventUtil.addEventHandler(suggestedWord, "mouseout", mouseOutSuggestedWord);
			EventUtil.addEventHandler(suggestedWord, "click", that.chooseOption);
		}
		suggestionBox.style.visibility = "visible";
	};

	/**
	 * Purpose: Add in the new options and highlight the portions which are similiar to the searchtext
	 * @param {String} value - search text
	 */
	this.addIn = function(value){
		var num = 0;		
		var splitValueArray = value.split(" ");
		if (dataSet != null) {
			var noOneSelected = true;
			for (var i = 0; i < dataSet.length; i++) {				
					var splitDataArray;
					if (keyField == null) {
						splitDataArray = dataSet[i].split(" ");
					}else {						
						splitDataArray = dataSet[i][keyField].split(" ");
					}
					
					var suggestedWord = null;
					var firstPartOfWord = false;
					for (var j = 0; j < splitValueArray.length; j++) { //compare each tokenised input variables with tokenised data to determine if the first few characters are the same	
						if (AnkhUsefulMethods.trim(splitValueArray[j]) != "") {
							firstPartOfWord = false;
							for (var k = 0; k < splitDataArray.length; k++) {
								if (splitDataArray[k].toUpperCase().indexOf(splitValueArray[j].toUpperCase()) == 0) {
									firstPartOfWord = true;
									break;
								}
							}
						}
						if (!firstPartOfWord) { //once searched input is not part of data, break and continue testing the next one
							break;
						}
					}
					if (firstPartOfWord) { //formatting the data list 
						suggestedWord = document.createElement('div');
						suggestedWord.className = "SuggestionWord";
						if (keyField == null) {
							suggestedWord.value = dataSet[i];							
						}else {
							suggestedWord.value = dataSet[i][keyField];
							suggestedWord.innerValue = dataSet[i][valueField];
						}
						if(prevSelected ==  suggestedWord.value){
							suggestedWord.selected = true;
							suggestedWord.style.backgroundColor = "#DDDFD1";
							noOneSelected = false;
						}else{
							suggestedWord.selected = false;
							suggestedWord.style.backgroundColor = "";
						}
						
						suggestionBox.appendChild(suggestedWord);
						EventUtil.addEventHandler(suggestedWord, "mouseover", mouseOverSuggestedWord);
						EventUtil.addEventHandler(suggestedWord, "mouseout", mouseOutSuggestedWord);
						EventUtil.addEventHandler(suggestedWord, "click", that.chooseOption);
						num = num + 1;
						
						for (var x = 0; x < splitDataArray.length; x++) {
							var isPartOfRequestedWord = false;
							for (var y = 0; y < splitValueArray.length; y++) {
								if (AnkhUsefulMethods.trim(splitValueArray[y]) != "") {
									if (splitDataArray[x].toUpperCase().indexOf(splitValueArray[y].toUpperCase()) == 0) {
										var requestedWord = document.createElement('span');
										requestedWord.className = "RequestedWord";
										var highlightedWord = splitDataArray[x].substr(0, splitValueArray[y].length)
										requestedWord.innerHTML = highlightedWord;
										suggestedWord.appendChild(requestedWord);
										
										var remainingWord = document.createElement('span');
										remainingWord.innerHTML = splitDataArray[x].substr(splitValueArray[y].length) + "\u0020 ";
										if (isIE && remainingWord.innerHTML == "") {
											remainingWord.style.marginLeft = "2px";
										}
										suggestedWord.appendChild(remainingWord);
										isPartOfRequestedWord = true;
										break;
									}
								}
							}
							if (!isPartOfRequestedWord) {
								var word = document.createElement('span');
								if (isIE) {
									word.style.marginLeft = "2px";
								}
								word.innerHTML = splitDataArray[x] + "\u0020";
								suggestedWord.appendChild(word);
							}
						}
						if (subKeyFields != null && subKeyFields.length >= 1) {
							var suggestedWordSubCategory = document.createElement('div');
							suggestedWordSubCategory.className = "SuggestedWordSubCategory";
							suggestedWord.appendChild(suggestedWordSubCategory);
							for (var j = 0; j < subKeyFields.length; j++) {
								if (j == 0) {
									suggestedWordSubCategory.innerHTML = dataSet[i][subKeyFields[j]];
								}
								else {
									suggestedWordSubCategory.innerHTML += ", " + dataSet[i][subKeyFields[j]];
								}
							}
						}
					}
			}
			
			if (num == 0) {
				if (ajaxQueryCount == 0) {
					var suggestedWord = document.createElement('div');
					suggestedWord.className = "SuggestionWord";
					suggestedWord.innerHTML = NORESULT;
					suggestionBox.appendChild(suggestedWord);
					suggestionBox.style.visibility = "visible";
				}
			}else{				
				if(!loose){
					if(noOneSelected && suggestionBox.firstChild!=null){	//if no one selected, then highlighted the first one
						prevSelected = suggestionBox.firstChild.value;
						suggestionBox.firstChild.selected = true;
						suggestionBox.firstChild.style.backgroundColor = "#DDDFD1";
					}
				}
				suggestionBox.style.visibility = "visible";
			}						
		}
	};
	/**
	 * Purpose: Create an Iframe to draw behind suggestion box to block select boxes from appearing above suggestion box
	 */
	this.drawIframe = function(){
		if (isIE && !isMinIE7) {			
			var iframe = document.createElement('iframe');
			iframe.className = "selectFree";
			iframe.style.height = suggestionBox.offsetHeight +"px";
			iframe.style.width = suggestionBox.offsetWidth +"px";
			suggestionBox.appendChild(iframe);
		}
	};
	
	/**
	 * Purpose: Set the messagebox text when the textbox is empty
	 * @param {String} value
	 */
	this.setEmptyDisplayText = function(value){		
		emptyDisplayText = document.createElement('div');
		emptyDisplayText.innerHTML = value;
		emptyDisplayText.style.backgroundColor = "#DDDFD1";
		emptyDisplayText.style.cursor = "default";
		emptyDisplayText.className = "SuggestionWord";
	}
	/**
	 * Purpose: Disable txt box 
	 */
	this.disable = function(){		
		box.disabled = true;
		box.style.backgroundColor = "#DDDFD1";
		box.value = "";				
	};
	/**
	 * Purpose: Enable txt box 
	 */
	this.enable = function(){
		box.disabled = false;
		box.style.backgroundColor = "";
	};	
	/**
	 * Purpose: Set the value of the box
	 */
	this.setValue = function(value){
		box.value = value;
	};
	/**
	 * Purpose: Mouse over the suggested word
	 */
	mouseOverSuggestedWord = function(){
		for (var i = 0; i < suggestionBox.childNodes.length; i++) {
			suggestionBox.childNodes[i].style.backgroundColor = "";
			suggestionBox.childNodes[i].style.selected = false;
		}
		if (EventUtil.getEvent().target.className == "SuggestionWord") {
			EventUtil.getEvent().target.style.backgroundColor = "#DDDFD1";
			EventUtil.getEvent().target.selected = true;
			if(!loose){
				prevSelected = EventUtil.getEvent().target.value;
			}
		
		}else{
			EventUtil.getEvent().target.parentNode.style.backgroundColor = "#DDDFD1";
			EventUtil.getEvent().target.parentNode.selected = true;
			if(!loose){
				prevSelected = EventUtil.getEvent().target.parentNode.value;
			}
			
		}		
		
	};
	/**
	 * Purpose: Mouse out the suggested word
	 */
	mouseOutSuggestedWord = function(){
		if (EventUtil.getEvent().target.className == "SuggestionWord") {
			EventUtil.getEvent().target.style.backgroundColor = "";
			EventUtil.getEvent().target.selected = false;
		}else{
			EventUtil.getEvent().target.parentNode.style.backgroundColor = "";
			EventUtil.getEvent().target.parentNode.selected = false;
		}				
		
	};
	/**
	 * Purpose: Once the user has chosen his option
	 */
	this.chooseOption = function(){		
		var option;
		if (EventUtil.getEvent().target.className == "SuggestionWord") {
			option = EventUtil.getEvent().target;
		}else{
			option = EventUtil.getEvent().target.parentNode;
		}
		that.confirmOption(option);
		
	};
	/**
	 * Purpose: Confirm the choice into the input control
	 * @param {Object} option - selected div object containing the 3 spans
	 */
	this.confirmOption = function(option){		
		if (option.innerHTML != NORESULT && option.innerHTML != emptyDisplayText.innerHTML) {				
			box.value = option.value;				
			hiddenBoxValue.value = option.innerValue || option.value;				
			if (onConfirmed != null) {
				onConfirmed(hiddenBoxValue.value,box.value,box);
			}					
			that.removeSuggestionBox();			
		}		
	};
	/**
	 * Purpose: Given whatever is indicated within the textbox, assign the appropriate representation
	 * in terms of case sensitivity
	 */
	this.locateOption = function(){
		if (dataSet != null) {
			var choice = box.value;
			var valueFound = false;
			var innerValue;
			
			for (var i = 0; i < dataSet.length; i++) {
				if (keyField == null) {
					if (dataSet[i].toUpperCase() == choice.toUpperCase()) {
						choice = dataSet[i];
						valueFound = true;
						break;
					}
				}
				else {
					if (dataSet[i][keyField].toUpperCase() == choice.toUpperCase()) {
						choice = dataSet[i][keyField];
						innerValue = dataSet[i][valueField];
						valueFound = true;						
						break;
					}
				}
			}
			
				if (valueFound || !strict) {
					box.value = choice;
					hiddenBoxValue.value = innerValue || choice;				
				}else {
					box.value = "";
					hiddenBoxValue.value = "";
				}
		
			if (onConfirmed != null) {
				onConfirmed(hiddenBoxValue.value,box.value,box);
			}
			that.removeSuggestionBox();		
		}
	};
	/**
	 * Purpose: Assign the handler function when the box has confirmed the data
	 * @param {Object} func
	 */
	this.setOnConfirmed = function(func){
		onConfirmed = func;
	};
	
	this.setOnKeyUp = function(func){
		EventUtil.addEventHandler(box,"keyup",func);
	};
	
	this.setData = function(dsValue,searchField){	
		if (ajaxQueryCount == 0) {
			if(searchField != "" ){							
				that.removeSuggestionBox();
				dataSet = dsValue;
				that.enable();				
				navigationKeyPressed = true;
				suggestionBox.style.visibility = "visible";
				that.addIn(searchField);
				that.drawIframe();
			}else if(showAllWhenNoResult){				
				that.removeSuggestionBox();
				dataSet = dsValue;
				that.enable();				
				navigationKeyPressed = true;
				suggestionBox.style.visibility = "visible";
				that.addInWithoutValue(searchField);
				that.drawIframe();	
			}
		}
	};
	/**
	 * Purpose: Get the data indicated in the textbox
	 */
	this.getBoxValue = function(){
		return  box.value;
	};
	this.getBox = function(){
		return box;
	};
	/**
	 * Purpose: Get the data which is to be posted
	 */
	this.getInnerValue = function(){
		return 	hiddenBoxValue.value;
	};
	
	this.addAJAXQueryCount = function(){
		ajaxQueryCount = ajaxQueryCount + 1;
	};
	
	this.subtractAJAXQueryCount = function(){
		ajaxQueryCount = ajaxQueryCount - 1;
	};
	this.getContainer = function(){
		return container;
	};
	initEventHandler();
	that.locateOption();			//initialise the hiddeninput value;
};



GroupTypeCompleteBox = function(parent,categorySelecter,initialValue,id,noResultTxt){
	var groupType = new AutoCompleteBox(parent,null,null,null,null,false,initialValue,id,noResultTxt);
	groupType.setEmptyDisplayText("Key in the sub-category that best describes your group");
	var groupSearchText;
	var that = this;
	this.retrieveGroup = function(){		
		if(groupSearchText != groupType.getBoxValue()){		
			var url = "php/get_Group_Sub_Category.php";				
			groupSearchText = groupType.getBoxValue();					
			var category = categorySelecter.options[categorySelecter.selectedIndex].text;
			var parameterObj = {search: groupSearchText,category: category};
			new AnkhAjax(url,"get",parameterObj,that.retrieveGroupSuccess,null);
		}		
	};
	
	this.retrieveGroupSuccess = function(transport){		
		var groupInfo = transport.responseText.evalJSON(true);	
		if (groupSearchText == groupInfo['request']['search']) {
			groupSearchText = groupType.getBoxValue();
			groupType.setData(groupInfo['list'], groupSearchText);
		}
	};	
	
	this.setGroupSearchText = function(){
		groupSearchText = groupType.getBoxValue();
	};
	this.getBox = function(){
		return groupType.getBox();
	};
	groupType.setOnKeyUp(that.retrieveGroup);
	groupType.setOnConfirmed(that.setGroupSearchText);
};

CountryAndCityCompletionBox = function(countryParent,cityParent,countryList,keyValue,codeValue,phpDirectory,countryValue,cityValue,countryBoxName,cityBoxName){
	var countryBox = new AutoCompleteBox(countryParent,countryList,keyValue,codeValue,null,true,countryValue,countryBoxName);
	countryBox.setEmptyDisplayText("Type your country");	
	var cityBox = new AutoCompleteBox(cityParent,null,null,null,null,false,cityValue,cityBoxName);
	cityBox.setEmptyDisplayText("Type your city");
	var prevCountry = countryValue || "";
	
	var citySearchText;
	if (cityValue == "" || cityValue == null) {
		cityBox.disable();
		citySearchText = "";
	}
	else {
		citySearchText = cityValue;
	}
	var that = this;
	
	/**
	 * Purpose: Retrieve City Info
	 * @param {String} countryCode 
	 */
	this.retrieveCityInfo = function(countryCode,country){	
		
		if (countryBox.getBoxValue() != "") {
			cityBox.enable();
		}else{
			cityBox.disable();
		}	

		if(prevCountry != country){
			cityBox.setValue("");
		}	
		prevCountry = country;
		if (AnkhUsefulMethods.trim(cityBox.getBoxValue().toUpperCase()) != AnkhUsefulMethods.trim(citySearchText.toUpperCase())) {			
			cityBox.addAJAXQueryCount();
			var url = phpDirectory + "php/profile_json.php";
			var type = "cityList";
			citySearchText = cityBox.getBoxValue();
			var search = citySearchText;
			var countryCd = countryCode;						
			var parameterObj = {type: type, search: search,countryCd: countryCd};
			new AnkhAjax(url,"get",parameterObj,that.retrieveCityInfoSuccess,null);
		}
	};
	
	this.retrieveCityInfoSuccess = function(transport){	
		cityBox.subtractAJAXQueryCount();	
		var cityInfo = transport.responseText.evalJSON(true);	
		if (citySearchText == cityInfo['request']['search']) {
			citySearchText = cityBox.getBoxValue();
			cityBox.setData(cityInfo['cityList'], citySearchText);
		}
	};
	this.cityBoxOnKeyUp = function(){		
		var countryCode = countryBox.getInnerValue();		
		prevCountry = countryBox.getBoxValue();
		that.retrieveCityInfo(countryCode,prevCountry);		
	};
	this.setCitySearchText = function(){
		citySearchText = cityBox.getBoxValue();
	};
	cityBox.setOnKeyUp(that.cityBoxOnKeyUp);
	cityBox.setOnConfirmed(that.setCitySearchText);
	countryBox.setOnConfirmed(that.retrieveCityInfo);
};

EducationCompletionBox = function(educationParent,phpDirectory,educationValue,educationBoxName){
	var fieldList = new Array();
	fieldList[0] = "area1";
	fieldList[1] = "area2";
	var educationBox = new AutoCompleteBox(educationParent,null,"college","college",fieldList,false,educationValue,educationBoxName);
	educationBox.setEmptyDisplayText("Type the name of your school");
	var search = "";
	var that = this;
	
	this.educationBoxOnChange = function(){							
		if (AnkhUsefulMethods.trim(educationBox.getBoxValue().toUpperCase()) != AnkhUsefulMethods.trim(search.toUpperCase())) {
			var url = phpDirectory + "php/profile_json.php";
		
			var type = "collegeList";
			search = educationBox.getBoxValue();
			educationBox.addAJAXQueryCount();			
			var parameterObj = {type: type, search: search};
			new AnkhAjax(url,"get",parameterObj,that.retrieveEduInfoSuccess,null);
		}	
	};
	
	this.retrieveEduInfoSuccess = function(transport){
		var eduInfo = transport.responseText.evalJSON(true);
		educationBox.subtractAJAXQueryCount();
		if (search == eduInfo['request']['search']) {
			educationBox.setData(eduInfo['collegeList'], search);
		}
	};
	
	this.setEduSearchText = function(){
		search = educationBox.getBoxValue();
	};
	
	this.getValue = function(){
		return educationBox.getBoxValue();
	}
	
	educationBox.setOnKeyUp(that.educationBoxOnChange);
	educationBox.setOnConfirmed(that.setEduSearchText);
};







/**
 * Purpose: Control used to allow users to add friends
 */
FriendAdder = function(){
	
	/**
	 * Purpose: Draw the user id and password boxes
	 * @param {Object} parent
	 * @param {Boolean} submitBtn
	 * @param {Func} ajaxHandler
	 */
	this.drawEmailSearch = function(parent,submitBtn,ajaxHandler){		
				
		var addFromEmailInstructions = new AnkhFormNotificationContainer(parent,"AddYourFriendsFromEmailHeader","green");
		var minorInstructions = document.createElement('div');
		minorInstructions.innerHTML = "Searching within your email contacts is the easiest way of adding friends on myTimeWall.";
										
		var supportedEmails = document.createElement('div');
		supportedEmails.style.fontSize = "9px";
		supportedEmails.innerHTML = " (Only Gmail, Hotmail, Lycos, AOL and Yahoomail are supported.)";
		minorInstructions.appendChild(supportedEmails);
		addFromEmailInstructions.showWithLayout("Find your friends that you email",minorInstructions);
		
		var addYourFriendsViaEmailform = new AnkhFormContainer("AddYourFriendsForm", "Post", "");
		parent.appendChild(addYourFriendsViaEmailform);
		var addFriendViaEmail = new GenericTable(3, 3);
		addFriendViaEmail.Table.id = "AddFriendViaEmail";		
		addYourFriendsViaEmailform.appendChild(addFriendViaEmail.Table);
		var emailTxt = document.createElement('div');
		emailTxt.innerHTML = "Your Email :";
		emailTxt.className = "alignRight";
		var emailBox = new AnkhInput("email", "");
		var pwdTxt = document.createElement('div');
		pwdTxt.innerHTML = "Password :";
		pwdTxt.className = "alignRight";
		var pwdBox = new AnkhPwdInput("pwd", "");
		var addFriendViaEmailBtn = new AnkhSmallSubmitButton("viaEmail", "Find Friends", submitBtn);
		addFriendViaEmail.TBody.childNodes[2].childNodes[1].className = "alignLeft";
		
		var ajaxLoader = new AnkhAJAXLoader("");
		addFriendViaEmail.insertIntoCell(0,0,emailTxt);
		addFriendViaEmail.insertIntoCell(0,1,emailBox);
		addFriendViaEmail.insertIntoCell(1,0,pwdTxt);
		addFriendViaEmail.insertIntoCell(1,1,pwdBox);
		addFriendViaEmail.insertIntoCell(2,1,addFriendViaEmailBtn);
		addFriendViaEmail.insertIntoCell(0,2,ajaxLoader);
		addFriendViaEmail.getCell(0,2).rowSpan = "2";
		ajaxLoader.className = "Hidden";
		
		if(ajaxHandler != null){
			EventUtil.addEventHandler(addFriendViaEmailBtn,"click",function x(){
				ajaxHandler(emailBox.value, pwdBox.value,ajaxLoader)
			});
			EventUtil.addEventHandler(addYourFriendsViaEmailform,"keydown",function x(){
				if (EventUtil.getEvent().keyCode == 13) {
					ajaxHandler(emailBox.value, pwdBox.value,ajaxLoader)
					EventUtil.getEvent().preventDefault();
				}				
			});			
		}
		EventUtil.addEventHandler(addYourFriendsViaEmailform,"submit",function x(){
			if(!isIE){
				ajaxLoader.className = "Visible";			//IE will hang and it does not look good
			}
			addFriendViaEmailBtn.disabled = true;			
		});
	};
	
	this.drawEmailSearchResults = function(friendList){				
		if (friendList.length > 0) {
			
			var consolidatedFriendList = new Array();
			for(var i = 0;i < friendList.length;i++){
				var inside = false;
				for(var j=0; j < consolidatedFriendList.length;j++){
					if(consolidatedFriendList[j].userId == friendList[i].userId){						
						consolidatedFriendList[j].email.push(friendList[i].email);
						inside = true;
						break;
					}
				}
				if(!inside){
					var friend = new Object();
					friend['userId'] = friendList[i]['userId'];
					friend['thumbnail'] = friendList[i]['thumbnail'];
					friend['displayNm'] = friendList[i]['displayNm'];
					friend['email'] = new Array();
					friend['email'].push(friendList[i]['email']);
					consolidatedFriendList.push(friend);
				}
			}
			
			var container = document.createElement('div');				
			var selectAllChkBox = new AnkhCheckBox("selectAll", "");
			container.appendChild(selectAllChkBox);
			var selectAllTxt = document.createTextNode("Select all friends");
			container.appendChild(selectAllTxt);
			
			var friendsTblStructure = new GenericTable(consolidatedFriendList.length, 3);
			container.appendChild(friendsTblStructure.Table);
			friendsTblStructure.Table.id = "FriendsTbl";
			friendsTblStructure.Table.cellSpacing = 0;
			friendsTblStructure.Table.cellPadding = 0;
			
			var checkBoxArray = new Array();
			
			for (var i = 0; i < consolidatedFriendList.length; i++) {
				var chkBox = new AnkhCheckBox("select", consolidatedFriendList[i].userId);
				checkBoxArray.push(chkBox);
				friendsTblStructure.getCell(i,0).appendChild(chkBox);
				
				var friendDetails = document.createElement('div');
				friendsTblStructure.getCell(i,1).appendChild(friendDetails);
				
				var friendName = document.createElement('div');
				friendName.className = "FriendName";
				friendName.innerHTML = consolidatedFriendList[i].displayNm;
				friendDetails.appendChild(friendName);
				
				var friendEmail = document.createElement('div');
				friendEmail.className = "FriendEmail";
				for(var j = 0;j < consolidatedFriendList[i]['email'].length;j++){
					friendEmail.innerHTML += consolidatedFriendList[i]['email'][j];
					if(j != consolidatedFriendList[i]['email'].length - 1){
						friendEmail.innerHTML += ",<br/> ";						
					}
				}
				friendDetails.appendChild(friendEmail);
				
				var friendPhoto = new FriendControl(consolidatedFriendList[i].thumbnail, "");
				friendsTblStructure.getCell(i,2).appendChild(friendPhoto);
				
			}
		}		
		
		initEvent = function(){
			EventUtil.addEventHandler(selectAllChkBox,"click",selectAllChanged);
			for(var i = 0;i < checkBoxArray.length; i++){
				EventUtil.addEventHandler(checkBoxArray[i],"click",chkBoxChanged);
			}
		};
		selectAllChanged = function(){			
			if(EventUtil.getEvent().target.checked){
				for(var i = 0;i < checkBoxArray.length; i++){
					checkBoxArray[i].checked = true;
				}
			}else{
				for(var i = 0;i < checkBoxArray.length; i++){
					checkBoxArray[i].checked = false;
				}
			}
		};
		chkBoxChanged = function(){
			if(!EventUtil.getEvent().target.checked){
				selectAllChkBox.checked = false;
			}
		};
	
		initEvent();
		return container;
		
	};
};
/**
 * Purpose - Create FriendControl
 * @param {String} picturePath - path to the image source; recommended to have absolute path
 * @param {String} name - friends' name
 * @param {String} href - friend's profile href
 * @param {Int} nameWidth - default width depends on length of name. Only affects the friend's name. If null, does not resize name.
 * @param {Int} pictureWidth - default width is original width. Affect the actual size of picture.
 * @param {Object} toolTip - {width:width,  content:content, align:align,padding:padding}
 */
FriendControl = function(picturePath,name,href,nameWidth,pictureWidth,maxHeight,click,toolTip,nameFontSize){
		
	var container = document.createElement('a');
	container.style.textDecoration = "none";
	
	if (picturePath != "" && picturePath != null) {		
		if (href != "" && href != null) {
			container.href = href;
		}
		if(click){
			EventUtil.addEventHandler(container,"click",function (){click(href)});
		}
		container.style.textAlign = "center";		
		
		var picContainer = document.createElement('div');
		picContainer.style.textAlign = "center";
		container.appendChild(picContainer);
		var picture = document.createElement('img');		
		picture.src = picturePath;	
		picture.style.padding = "3px";
		picture.style.background = "#FFFFFF";
		
		picture.style.border = "1px solid #DDDFD1";
		
		if (href != "" && href != null) {				
			picture.style.cursor = "pointer";
		}
		if (pictureWidth) {				
			var ratio = pictureWidth / picture.width ;
			picture.width = pictureWidth;			
			if(picture.height && isIE){				//for IE Bug. IE is able to resize height automatically according the specified width
													//only during first time or reload. 				
				picture.style.height = picture.height * ratio + "px";
			}			
		}
		picContainer.appendChild(picture);		
		if(name != null && name != ""){
			var friendName;
			if(typeof name == "object"){
				friendName = name;
			}else{
				friendName = document.createElement('div');			
				friendName.innerHTML = name;
				var fontSize = nameFontSize || 11;
				friendName.style.fontSize = fontSize+"px";
				friendName.style.color = "#5E6F61";
				friendName.style.verticalAlign = "top";
				friendName.style.textDecoration = "none";
				friendName.style.textAlign = "center";
			}
			container.appendChild(friendName);	
			if(nameWidth){		
				AnkhUsefulMethods.WordWrap(friendName, nameWidth);
				friendName.style.width = nameWidth + "px";
				friendName.style.lineHeight = "14px";							
			}
		}
		if(toolTip && toolTip['content'] != ""){
			var friendToolTip = document.createElement('div');
			friendToolTip.style.border = "1px solid #DDDFD1";
			friendToolTip.style.backgroundColor = "#5E6f61";
			friendToolTip.style.color = "#F4FAED";
			friendToolTip.style.lineHeight = "12px";
			friendToolTip.style.fontSize = "10px";			
			if(toolTip['width']){
				friendToolTip.style.width = toolTip['width']+"px";	
			}		
			friendToolTip.innerHTML = toolTip['content'];
			if(toolTip['align'] == "left"){
				friendToolTip.style.textAlign = "left";
			}else if(toolTip['align'] == "right"){
				friendToolTip.style.textAlign = "right";
			}
			if(toolTip['padding']){
				friendToolTip.style.padding = toolTip['padding']+"px";	
			}
			if (href != "" && href != null) {				
				friendToolTip.style.cursor = "pointer";
			}
			friendToolTip.style.visibility = "hidden";
			friendToolTip.style.display = "block";			
			friendToolTip.style.position = "absolute";			
			container.appendChild(friendToolTip);			
			EventUtil.addEventHandler(friendToolTip, "mouseover", function x(){EventUtil.getEvent().stopPropagation();});
			EventUtil.addEventHandler(friendToolTip, "mouseout", function x(){EventUtil.getEvent().stopPropagation();});
		}		
		
		EventUtil.addEventHandler(picture, "mouseover", function x(){
			picture.style.border = "1px solid #5E6F61";			
			if(friendToolTip){				
				friendToolTip.style.visibility = "visible";
				if(toolTip['width']){
					friendToolTip.style.width = toolTip['width']+"px";	
				}else{
					friendToolTip.style.width = EventUtil.getEvent().target.clientWidth+"px";
				}					
			}
				
		});
		EventUtil.addEventHandler(picture, "mouseout", function x(){
			picture.style.border = "1px solid #DDDFD1";			
			if(friendToolTip){
				friendToolTip.style.visibility = "hidden";
			}
		});				
	}
	
	return container;
};
/**
 * Purpose: Generate the friend inviter control
 * @param {Array} friendList - contains objects of {checked,displayNm,tag,thumbnail}
 * @param {Object} parent
 */
FriendInviter = function(friendList,parent,noPic){
	var that = this;
	
	var container = document.createElement('div');
	container.id = "FriendInviter";
	parent.appendChild(container);
	
	var header = document.createElement('div');
	header.innerHTML = "Type any name to filter your friend list.";
	container.appendChild(header);		
	
	var searchNameContainer = document.createElement('div');	
	var searchName = new AnkhInput("SearchName", "");
	searchName.style.marginTop = "5px";
	searchNameContainer.appendChild(searchName);
	container.appendChild(searchNameContainer);
	
	var innerContentContainer = document.createElement('div');
	if(noPic){
		innerContentContainer.id = "MiniParticipantSelector";
	}else{
		innerContentContainer.id = "ParticipantSelector";
	}
	container.appendChild(innerContentContainer);
	
	var selectedFriends = new Array();
	
	init = function(){
		EventUtil.addEventHandler(searchName, "keyup", filterNames);
		for (var i = 0; i < friendList.length; i++) {
			friendList[i].checked = false;
		}
		that.draw(friendList);
	};
	/**
	 * Purpose: Return the friends whom the user has selected
	 */
	this.getSelectedFriends = function(){
		return selectedFriends;
	};
	
	/**
	 * Purpose: Used to filter names based on names within textbox
	 */
	filterNames = function(){
		that.clear();
		var filteredFriendList = new Array();
		var value = AnkhUsefulMethods.trim(EventUtil.getEvent().target.value);
		if (value != "") {
			var filterArray = value.split(" ");
			for (var i = 0; i < friendList.length; i++) {
				var friend = friendList[i].displayNm + " " + friendList[i].tag;				
				var friendArray = friend.split(" ");
				var wanted = 0;
				
				for (var k = 0; k < filterArray.length; k++) {
					for (var j = 0; j < friendArray.length; j++) {
						if (filterArray[k] != "" && friendArray[j].toUpperCase().indexOf(filterArray[k].toUpperCase()) == 0) {
							wanted++;
							break;
						}
					}
				}
				if (wanted == filterArray.length) {
					filteredFriendList.push(friendList[i]);
				}
			}
			that.draw(filteredFriendList, value);
		}
		else {
			that.draw(friendList);
		}
	};
	/**
	 * Purpose: Draw the list of friends in the container
	 * @param {Array} friendList
	 * @param {String} filter
	 */
	this.draw = function(friendList, filter){		
		if(noPic){
			drawTwoCol(friendList, filter);
		}else{
			drawThreeCol(friendList, filter);
		}
	};
	
	drawTwoCol = function(friendList,filter){
		var tblStructure = new GenericTable(friendList.length,2);
		innerContentContainer.appendChild(tblStructure.Table);
		tblStructure.Table.id = "MiniParticipantSelectorTbl";
		tblStructure.Table.cellPadding = 0;
		tblStructure.Table.cellSpacing = 0;
		if (friendList.length > 0 ) {
			tblStructure.getCell(0,0).width = "10%";
			tblStructure.getCell(0,1).width = "90%";
		}
		for (var i = 0; i < friendList.length; i++) {
			
			var nameContainer = document.createElement('div');
			if (filter == null) {
				var name = document.createElement('div');
				name.innerHTML = friendList[i].displayNm;
				nameContainer.appendChild(name);
				var tag = document.createElement('div');
				tag.className = "tag";
				tag.innerHTML = friendList[i].tag;
				nameContainer.appendChild(tag);
				
			}
			else {
				var friendNameArray = friendList[i].displayNm.split(" ");
				var friendTagArray = friendList[i].tag.split(" ");
				var filterArray = filter.split(" ");
				
				var name = document.createElement('div');
				nameContainer.appendChild(name);
				for (var j = 0; j < friendNameArray.length; j++) {
					var highlighted = false;
					for (var k = 0; k < filterArray.length; k++) {
						highlighted = highlightWords(filterArray[k], friendNameArray[j], name);
						if (highlighted) {
							break;
						}
					}
					if (!highlighted) {
						var remainingWord = document.createElement('span');
						remainingWord.innerHTML = friendNameArray[j] + "\u0020 ";
						if (isIE) {
							remainingWord.style.marginLeft = "2px";
						}
						name.appendChild(remainingWord);
					}
				}
				var tag = document.createElement('div');
				tag.className = "tag";
				nameContainer.appendChild(tag);
				for (var j = 0; j < friendTagArray.length; j++) {
					var highlighted = false;
					for (var k = 0; k < filterArray.length; k++) {
						highlighted = highlightWords(filterArray[k], friendTagArray[j], tag);
						if (highlighted) {
							break;
						}
					}
					if (!highlighted) {
						var remainingWord = document.createElement('span');
						remainingWord.innerHTML = friendTagArray[j] + "\u0020 ";
						if (isIE) {
							remainingWord.style.marginLeft = "2px";
						}
						tag.appendChild(remainingWord);
					}
				}
			}
			tblStructure.insertIntoCell(i,1,nameContainer);			
			var checkbox = new AnkhCheckBox("friends", friendList[i].friendId);
			checkbox.friend = friendList[i];
			EventUtil.addEventHandler(checkbox, "click", checkBoxClick);
			tblStructure.insertIntoCell(i,0, checkbox);
			checkbox.checked = friendList[i].checked;
		}
	};
	
	drawThreeCol = function(friendList, filter){		
		var tblStructure = new GenericTable(friendList.length,3);
		innerContentContainer.appendChild(tblStructure.Table);
		tblStructure.Table.id = "ParticipantSelectorTbl";
		tblStructure.Table.cellPadding = 0;
		tblStructure.Table.cellSpacing = 0;
		if (friendList.length > 0 ) {
			tblStructure.getCell(0,0).width = "30%";
			tblStructure.getCell(0,1).width = "60%";
			tblStructure.getCell(0,2).width = "10%";
		}
		for (var i = 0; i < friendList.length; i++) {
			var container = document.createElement('div');
			var picDisplay = new FriendControl(friendList[i].thumbnail, "");
			picDisplay.className = "ParticipantPic";
			container.appendChild(picDisplay);
			tblStructure.insertIntoCell(i,0,container);
			
			var nameContainer = document.createElement('div');
			if (filter == null) {
				var name = document.createElement('div');
				name.innerHTML = friendList[i].displayNm;
				nameContainer.appendChild(name);
				var tag = document.createElement('div');
				tag.className = "tag";
				tag.innerHTML = friendList[i].tag;
				nameContainer.appendChild(tag);
				
			}
			else {
				var friendNameArray = friendList[i].displayNm.split(" ");
				var friendTagArray = friendList[i].tag.split(" ");
				var filterArray = filter.split(" ");
				
				var name = document.createElement('div');
				nameContainer.appendChild(name);
				for (var j = 0; j < friendNameArray.length; j++) {
					var highlighted = false;
					for (var k = 0; k < filterArray.length; k++) {
						highlighted = highlightWords(filterArray[k], friendNameArray[j], name);
						if (highlighted) {
							break;
						}
					}
					if (!highlighted) {
						var remainingWord = document.createElement('span');
						remainingWord.innerHTML = friendNameArray[j] + "\u0020 ";
						if (isIE) {
							remainingWord.style.marginLeft = "2px";
						}
						name.appendChild(remainingWord);
					}
				}
				var tag = document.createElement('div');
				tag.className = "tag";
				nameContainer.appendChild(tag);
				for (var j = 0; j < friendTagArray.length; j++) {
					var highlighted = false;
					for (var k = 0; k < filterArray.length; k++) {
						highlighted = highlightWords(filterArray[k], friendTagArray[j], tag);
						if (highlighted) {
							break;
						}
					}
					if (!highlighted) {
						var remainingWord = document.createElement('span');
						remainingWord.innerHTML = friendTagArray[j] + "\u0020 ";
						if (isIE) {
							remainingWord.style.marginLeft = "2px";
						}
						tag.appendChild(remainingWord);
					}
				}
			}
			tblStructure.insertIntoCell(i,1,nameContainer);			
			var checkbox = new AnkhCheckBox("friends", friendList[i].friendId);
			checkbox.friend = friendList[i];
			EventUtil.addEventHandler(checkbox, "click", checkBoxClick);
			tblStructure.insertIntoCell(i,2, checkbox);
			checkbox.checked = friendList[i].checked;
		}
	};
	/**
	 * Purpose: Used to highlight the words
	 * @param {String} filterPortion
	 * @param {String} friendPortion
	 * @param {Object} parent
	 */
	highlightWords = function(filterPortion, friendPortion, parent){
		var hightlighted = false;
		if (filterPortion != "" && friendPortion.toUpperCase().indexOf(filterPortion.toUpperCase()) == 0) {
			var requestWord = document.createElement('span');
			requestWord.className = "RequestedWord";
			requestWord.innerHTML = friendPortion.substr(0, filterPortion.length);
			parent.appendChild(requestWord);
			
			var remainingWord = document.createElement('span');
			remainingWord.innerHTML = friendPortion.substr(filterPortion.length) + "\u0020 ";
			parent.appendChild(remainingWord);
			hightlighted = true;
			if (isIE && remainingWord.innerHTML == "") {
				remainingWord.style.marginLeft = "2px";
			}
		}
		return hightlighted;
	};
	
	checkBoxClick = function(){
		EventUtil.getEvent().target.friend.checked = EventUtil.getEvent().target.checked;
		
	};
	
	this.clear = function(){
		AnkhUsefulMethods.removeAll(innerContentContainer);
	};
	
	this.show = function(){
		participantPopup.show();
		searchName.focus();
	};
	init();
}; /**
 * Purpose - Draw the navigation bar
 * @param {Int} totalNum - total number of entries
 * @param {Int} numOfEntryInAPage - number of entries in a page
 * @param {Func} eventHandler - event handler when a link is been clicked
 */
NavigationBar = function(totalNum,numOfEntryInAPage,eventHandler){
	
	var navigationLinkCount = 7;					//including the ... 
	var navigationMaxPage = Math.ceil(totalNum/numOfEntryInAPage);
	
	var eventHandler = eventHandler;
	
	this.getHTML = function(currentPage){
		var currentPage = parseInt(currentPage,10);
		var navigationBarHTML = document.createElement('div');
		if (totalNum > numOfEntryInAPage) {			//more than 'numOfEntryInAPage' event
			var pages = navigationMaxPage;
			if (navigationMaxPage <= navigationLinkCount) {		//if less than 7 pages, then show all
								
				for (var i = 1; i <= pages; i++) {
					var navigationLink = document.createElement('span');
					if (i == currentPage) {
						navigationLink.className = "Navigate_Selected";
					}
					else {
						navigationLink.className = "Navigate";
					}
					
					navigationLink.innerHTML = i;
					navigationBarHTML.appendChild(navigationLink);
					EventUtil.addEventHandler(navigationLink, "click", eventHandler);
				}
			}
			else{
				if(currentPage <= 3){							//if current page is less or equal to 3, show 1,2,3,4,5,...7
					for (var i = 1; i <= 5; i++) {
						var navigationLink = document.createElement('span');
						if (i == currentPage) {
							navigationLink.className = "Navigate_Selected";
						}
						else {
							navigationLink.className = "Navigate";
						}
						
						navigationLink.innerHTML = i;
						navigationBarHTML.appendChild(navigationLink);
						EventUtil.addEventHandler(navigationLink, "click", eventHandler);
					}
					var navigationLink = document.createElement('span');
					navigationLink.innerHTML = " ... ";
					navigationBarHTML.appendChild(navigationLink);
					
					var navigationLink = document.createElement('span');
					navigationLink.innerHTML = pages;
					navigationLink.className = "Navigate";
					navigationBarHTML.appendChild(navigationLink);
					EventUtil.addEventHandler(navigationLink, "click", eventHandler);
				}
				else if(currentPage >= pages - 3){				//if current page is near the end, show 1 ... 24, 25,26,27,28 (if last page is 28)
					var navigationLink = document.createElement('span');
					navigationLink.innerHTML = "1";
					navigationLink.className = "Navigate";
					navigationBarHTML.appendChild(navigationLink);
					EventUtil.addEventHandler(navigationLink, "click", eventHandler);
					
					var navigationLink = document.createElement('span');
					navigationLink.innerHTML = " ... ";
					navigationBarHTML.appendChild(navigationLink);
					for(var i = pages - 4;i <= pages;i++){
						var navigationLink = document.createElement('span');
						if (i == currentPage) {
							navigationLink.className = "Navigate_Selected";
						}
						else {
							navigationLink.className = "Navigate";
						}
						
						navigationLink.innerHTML = i;
						navigationBarHTML.appendChild(navigationLink);
						EventUtil.addEventHandler(navigationLink, "click", eventHandler);
					}
				}
				else{
					
					var navigationLink = document.createElement('span');
					navigationLink.innerHTML = "1";
					navigationLink.className = "Navigate";
					navigationBarHTML.appendChild(navigationLink);
					EventUtil.addEventHandler(navigationLink, "click", eventHandler);
					
					var navigationLink = document.createElement('span');
					navigationLink.innerHTML = " ... ";
					navigationBarHTML.appendChild(navigationLink);
					
					for(var i= currentPage - 1; i<= currentPage + 1; i++){
						var navigationLink = document.createElement('span');
						if (i == currentPage) {
							navigationLink.className = "Navigate_Selected";
						}
						else {
							navigationLink.className = "Navigate";
						}
						navigationLink.innerHTML = i;
						navigationBarHTML.appendChild(navigationLink);
						EventUtil.addEventHandler(navigationLink, "click", eventHandler);
					}
					
					var navigationLink = document.createElement('span');
					navigationLink.innerHTML = " ... ";
					navigationBarHTML.appendChild(navigationLink);
					
					var navigationLink = document.createElement('span');
					navigationLink.innerHTML = pages;
					navigationLink.className = "Navigate";
					navigationBarHTML.appendChild(navigationLink);
					EventUtil.addEventHandler(navigationLink, "click", eventHandler);
				}
			}
		}
		return navigationBarHTML;
	};
	
};/**
 * Purpose: Draw the auto completion box
 * @param {Object} parent - parent HTML object
 * @param {Object} dataSet
 * @param {String} headerTxt - e.g. "Add participants"
 * @param {String} txtField - e.g. text
 * @param {String} valueField - e.g. id
 * @param {String} picField - e.g. pic
 * @param {String} typeField - e.g. type
 * @param {Array} subKeyFields - array of subkey fields. Typically not used.
 * @param {Boolean} strict
 */
ParticipantAdder = function(parent,input){
	var dataSet = input['dataSet'];
	var headerTxt = input['headerTxt'];
	var txtField = input['txtField'];
	var valueField = input['valueField'];
	var picField = input['picField'];
	var typeField = input['typeField'];
	var subKeyFields = input['subKeyFields'];
	var strict = input['strict'];	
	var emptyDisplay = input['emptyDisplay'];
	var removeAutoSuggest = input['removeAutoSuggest'];
	
	var that = this;
	var onConfirmed;
	var prevSelected;
	var typingEmail = false;
	
	var container = document.createElement('div');
	container.id = "ParticipantAdder";	
	parent.appendChild(container);
	
	var header = document.createElement('div');	
	header.id = "Header";
	header.innerHTML = headerTxt;
	container.appendChild(header);
	var box = new AnkhInput("MatchName",""); 
	container.appendChild(box);
		
	var suggestionBox = document.createElement('div');
	suggestionBox.className = "SuggestionBox";
	suggestionBox.inputControl = box;
	suggestionBox.parent = parent;
	box.suggestionBox = suggestionBox;
	container.appendChild(suggestionBox);	
				
	var emptyDisplayText = document.createElement('div');
	emptyDisplayText.innerHTML = emptyDisplay;
	emptyDisplayText.style.backgroundColor = "#DDDFD1";
	emptyDisplayText.style.cursor = "default";
	emptyDisplayText.className = "SuggestionWord";
	
	var navigationKeyPressed = true;			
	var isInvalidEmail = false;
	var frontDataSet = new Array(); //used to store the participants in the front
	var frontDataFunc;
	
	init = function(){
		EventUtil.addEventHandler(box,"keyup",function (){
			if(box.value.indexOf("@")>=1){
				typingEmail = true;	
			}else{
				typingEmail = false;
			}
			that.drawSuggestionBox(false);});
		EventUtil.addEventHandler(box,"click",function (){
			if(frontDataFunc){
				frontDataSet = frontDataFunc();
			}
			that.drawSuggestionBox(true);});
		EventUtil.addEventHandler(box,"focus",function (){
			if(frontDataFunc){
				frontDataSet = frontDataFunc();
			}
			that.drawSuggestionBox(true);});
		EventUtil.addEventHandler(box,"mousedown",function (){
			EventUtil.getEvent().stopPropagation();});		
		EventUtil.addEventHandler(box,"keydown",navigateSuggestionBox);		
		EventUtil.addEventHandler(document.body,"mousedown",function x(){			
			that.locateOption(suggestionBox);
			that.removeSuggestionBox();								
		});
		EventUtil.addEventHandler(suggestionBox,"mousedown",function x(){EventUtil.getEvent().stopPropagation();});
		that.drawSuggestion("");						
	};
	/**
	 * Purpose: To draw the suggestion box under the textbox
	 */
	this.drawSuggestionBox = function(alwaysRedraw){						
		if (!navigationKeyPressed || alwaysRedraw) {
			
			var value = box.value;															
			that.removeSuggestionBox();	
			that.drawSuggestion(value);									
			//EventUtil.getEvent().stopPropagation();																
		}	
						
	};	
	
	this.setFrontDataFunc = function(func){
		frontDataFunc = func
	};
	this.setDataSet = function(value){
		dataSet = value;
	};
	
	this.resetPos = function(){		
		prevSelected = "";
		suggestionBox.scrollTop = 0;
	};
	
	/**
	 * Purpose: Add in the new options and highlight the portions which are similiar to the searchtext
	 * @param {String} value - search text
	 */
	this.drawSuggestion = function(value){		
		var num = 0;	
		var splitValueArray = value.split(" ");
		
		if (dataSet != null || frontDataSet.length > 0) {
			var noOneSelected = true;
			
			for (var i = 0; i < frontDataSet.length; i++) {
				var splitDataArray = frontDataSet[i][txtField].split(" ");				
				var firstPartOfWord = false;
				for (var j = 0; j < splitValueArray.length; j++) { //compare each tokenised input variables with tokenised data to determine if the first few characters are the same	
					if (AnkhUsefulMethods.trim(splitValueArray[j]) != "") {
						firstPartOfWord = false;
						for (var k = 0; k < splitDataArray.length; k++) {
							if (splitDataArray[k].toUpperCase().indexOf(splitValueArray[j].toUpperCase()) == 0) {
								firstPartOfWord = true;
								break;
							}
						}
					}else{
						firstPartOfWord = true;
					}
					if (!firstPartOfWord) { //once searched input is not part of data, break and continue testing the next one
						break;
					}
				}
				if (firstPartOfWord) { //formatting the data list 
					var suggestedWord = document.createElement('div');
					suggestedWord.className = "SuggestionWord";
					suggestedWord.value = frontDataSet[i][txtField];
					suggestedWord.innerValue = frontDataSet[i][valueField];
					suggestedWord.type = frontDataSet[i][typeField];
					suggestionBox.appendChild(suggestedWord);
					suggestedWord.suggestedWord = suggestedWord;
					
					var suggestedWordTbl = new GenericTable(1,2);
					suggestedWordTbl.Table.id = "SuggestedWordTbl";
					suggestedWordTbl.Table.cellPadding = "0";
					suggestedWordTbl.Table.cellSpacing = "0";
					suggestedWordTbl.Table.suggestedWord = suggestedWord;
					suggestedWord.appendChild(suggestedWordTbl.Table);
					suggestedWordTbl.getCell(0,0).style.width = "56px";
					suggestedWordTbl.getCell(0,1).style.width = "114px";
					suggestedWordTbl.getCell(0,0).suggestedWord = suggestedWord;
					suggestedWordTbl.getCell(0,1).suggestedWord = suggestedWord;
					var pic = document.createElement('img');						
					pic.src = frontDataSet[i][picField];						
					pic.className = "pic";
					pic.suggestedWord = suggestedWord;
					suggestedWordTbl.insertIntoCell(0,0,pic);
																	
					if(prevSelected ==  suggestedWord.value){
						suggestedWord.selected = true;
						suggestedWord.style.backgroundColor = "#DDDFD1";
						noOneSelected = false;
					}else{
						suggestedWord.selected = false;
						suggestedWord.style.backgroundColor = "";
					}																	
					
					for (var x = 0; x < splitDataArray.length; x++) {
						var isPartOfRequestedWord = false;
						for (var y = 0; y < splitValueArray.length; y++) {
							
							if (splitDataArray[x].toUpperCase().indexOf(splitValueArray[y].toUpperCase()) == 0) {
								var requestedWord = document.createElement('span');
								requestedWord.className = "RequestedWord";
								requestedWord.suggestedWord = suggestedWord;
								var highlightedWord = splitDataArray[x].substr(0, splitValueArray[y].length)
								requestedWord.innerHTML = highlightedWord;
								suggestedWordTbl.insertIntoCell(0,1,requestedWord);
										
								var remainingWord = document.createElement('span');
								remainingWord.suggestedWord = suggestedWord;
								remainingWord.innerHTML = splitDataArray[x].substr(splitValueArray[y].length) + "&nbsp;";										
								suggestedWordTbl.insertIntoCell(0,1,remainingWord);
								isPartOfRequestedWord = true;
								break;
							}
								
						}
						if (!isPartOfRequestedWord) {
							var word = document.createElement('span');								
							word.innerHTML = splitDataArray[x] + "&nbsp;";
							word.suggestedWord = suggestedWord;
							suggestedWordTbl.insertIntoCell(0,1,word);
						}
					}
					if (subKeyFields != null && subKeyFields.length >= 1) {
						var suggestedWordSubCategory = document.createElement('div');
						suggestedWordSubCategory.className = "SuggestedWordSubCategory";
						suggestedWordTbl.insertIntoCell(0,1,suggestedWordSubCategory);
						for (var j = 0; j < subKeyFields.length; j++) {
							if (j == 0) {
								suggestedWordSubCategory.innerHTML = frontDataSet[i][subKeyFields[j]];
							}
							else {
								suggestedWordSubCategory.innerHTML += ", " + frontDataSet[i][subKeyFields[j]];
							}
						}
					}
					EventUtil.addEventHandler(suggestedWordTbl.Table, "mouseover", that.mouseOverSuggestedCell);
					EventUtil.addEventHandler(pic, "mouseover", that.mouseOverSuggestedCell);
					EventUtil.addEventHandler(suggestedWord, "mouseover", that.mouseOverSuggestedCell);
					EventUtil.addEventHandler(suggestedWord, "mousedown", that.chooseOption);
					num = num + 1;
				}
			}
			
			for (var i = 0; i < dataSet.length; i++) {
				var splitDataArray = dataSet[i][txtField].split(" ");				
				var firstPartOfWord = false;
				for (var j = 0; j < splitValueArray.length; j++) { //compare each tokenised input variables with tokenised data to determine if the first few characters are the same	
					if (AnkhUsefulMethods.trim(splitValueArray[j]) != "") {
						firstPartOfWord = false;
						for (var k = 0; k < splitDataArray.length; k++) {
							if (splitDataArray[k].toUpperCase().indexOf(splitValueArray[j].toUpperCase()) == 0) {
								firstPartOfWord = true;
								break;
							}
						}
					}else{
						firstPartOfWord = true;
					}
					if (!firstPartOfWord) { //once searched input is not part of data, break and continue testing the next one
						break;
					}
				}
				if (firstPartOfWord) { //formatting the data list 
					var suggestedWord = document.createElement('div');
					suggestedWord.className = "SuggestionWord";
					suggestedWord.value = dataSet[i][txtField];
					suggestedWord.innerValue = dataSet[i][valueField];
					suggestedWord.type = dataSet[i][typeField];
					suggestionBox.appendChild(suggestedWord);
					suggestedWord.suggestedWord = suggestedWord;
					
					var suggestedWordTbl = new GenericTable(1,2);
					suggestedWordTbl.Table.id = "SuggestedWordTbl";
					suggestedWordTbl.Table.cellPadding = "0";
					suggestedWordTbl.Table.cellSpacing = "0";
					suggestedWordTbl.Table.suggestedWord = suggestedWord;
					suggestedWord.appendChild(suggestedWordTbl.Table);
					suggestedWordTbl.getCell(0,0).style.width = "56px";
					suggestedWordTbl.getCell(0,1).style.width = "114px";
					suggestedWordTbl.getCell(0,0).suggestedWord = suggestedWord;
					suggestedWordTbl.getCell(0,1).suggestedWord = suggestedWord;
					var pic = document.createElement('img');						
					pic.src = dataSet[i][picField];						
					pic.className = "pic";
					pic.suggestedWord = suggestedWord;
					suggestedWordTbl.insertIntoCell(0,0,pic);
																	
					if(prevSelected ==  suggestedWord.value){
						suggestedWord.selected = true;
						suggestedWord.style.backgroundColor = "#DDDFD1";
						noOneSelected = false;
					}else{
						suggestedWord.selected = false;
						suggestedWord.style.backgroundColor = "";
					}																	
					
					for (var x = 0; x < splitDataArray.length; x++) {
						var isPartOfRequestedWord = false;
						for (var y = 0; y < splitValueArray.length; y++) {
							
							if (splitDataArray[x].toUpperCase().indexOf(splitValueArray[y].toUpperCase()) == 0) {
								var requestedWord = document.createElement('span');
								requestedWord.className = "RequestedWord";
								requestedWord.suggestedWord = suggestedWord;
								var highlightedWord = splitDataArray[x].substr(0, splitValueArray[y].length)
								requestedWord.innerHTML = highlightedWord;
								suggestedWordTbl.insertIntoCell(0,1,requestedWord);
									
								var remainingWord = document.createElement('span');
								remainingWord.suggestedWord = suggestedWord;
								remainingWord.innerHTML = splitDataArray[x].substr(splitValueArray[y].length) + "&nbsp;";										
								suggestedWordTbl.insertIntoCell(0,1,remainingWord);
								isPartOfRequestedWord = true;
								break;
							}
								
						}
						if (!isPartOfRequestedWord) {
							var word = document.createElement('span');								
							word.innerHTML = splitDataArray[x] + "&nbsp;";
							word.suggestedWord = suggestedWord;
							suggestedWordTbl.insertIntoCell(0,1,word);
						}
					}
					if (subKeyFields != null && subKeyFields.length >= 1) {
						var suggestedWordSubCategory = document.createElement('div');
						suggestedWordSubCategory.className = "SuggestedWordSubCategory";
						suggestedWordTbl.insertIntoCell(0,1,suggestedWordSubCategory);
						for (var j = 0; j < subKeyFields.length; j++) {
							if (j == 0) {
								suggestedWordSubCategory.innerHTML = dataSet[i][subKeyFields[j]];
							}
							else {
								suggestedWordSubCategory.innerHTML += ", " + dataSet[i][subKeyFields[j]];
							}
						}
					}
					EventUtil.addEventHandler(suggestedWordTbl.Table, "mouseover", that.mouseOverSuggestedCell);
					EventUtil.addEventHandler(pic, "mouseover", that.mouseOverSuggestedCell);
					EventUtil.addEventHandler(suggestedWord, "mouseover", that.mouseOverSuggestedCell);
					EventUtil.addEventHandler(suggestedWord, "mousedown", that.chooseOption);
					num = num + 1;
				}
			}
			
			if (num == 0) {				
				if(!isInvalidEmail){
					var suggestedWord = document.createElement('div');
					suggestedWord.className = "SuggestionWord";
					suggestedWord.style.backgroundColor = "#DDDFD1";
					if(typingEmail && value != ""){
						suggestedWord.innerHTML = "Press <b>ENTER</b> to add this event for <b>"+value+"</b>";
					}else{					
						if(dataSet.length > 0){
							suggestedWord.innerHTML = "Opps... this friend is not in your friend list. Type her email address to add this event to her TimeWall.";
						}else{
							suggestedWord.innerHTML = "Type your friend's email address to add this event to her TimeWall.";
						}
					}								
					suggestionBox.appendChild(suggestedWord);
					suggestionBox.style.visibility = "visible";
				}				
			}else{				
				if(noOneSelected && suggestionBox.firstChild!=null){	//if no one selected, then highlighted the first one				
					prevSelected = suggestionBox.firstChild.value;
					suggestionBox.firstChild.selected = true;
					suggestionBox.firstChild.style.backgroundColor = "#DDDFD1";
				}
				suggestionBox.style.visibility = "visible";
			}
		}
	};
	
	/**
	 * Purpose: to navigate the suggestion boxes using keyboard keys
	 */
	navigateSuggestionBox = function(){
		var suggestionBox = EventUtil.getEvent().target.suggestionBox;
		navigationKeyPressed = true;
		
		switch(EventUtil.getEvent().keyCode){
			case 13:	var optionSelected = false;
						for(var i=0;i< suggestionBox.childNodes.length;i++){		//pressing enter
							if (suggestionBox.childNodes[i].selected) {																	
								that.confirmOption(suggestionBox.childNodes[i].value,suggestionBox.childNodes[i].innerValue,suggestionBox.childNodes[i].type);						
								optionSelected = true;
								break;
							}
						}				
						if(!optionSelected){
							that.locateOption(suggestionBox);
							that.confirmOption(box.value,"",box.type);
							
						}											
						EventUtil.getEvent().preventDefault();
						break;
			case 38:	var index = 0;				//moving up
						for(var i = 0;i < suggestionBox.childNodes.length;i++){
							if(suggestionBox.childNodes[i].selected){
								index = i;
								break;
							}
						}
						if(index != 0){
							var currentIndex = index - 1;
							suggestionBox.childNodes[index].style.backgroundColor = "";
							suggestionBox.childNodes[index].selected = false;
							suggestionBox.childNodes[currentIndex].style.backgroundColor = "#DDDFD1";
							suggestionBox.childNodes[currentIndex].selected = true;		
							var prevSelectedDiv = suggestionBox.childNodes[currentIndex];
							if(prevSelectedDiv.offsetTop - suggestionBox.scrollTop  < 0){
								suggestionBox.scrollTop = suggestionBox.scrollTop - prevSelectedDiv.offsetHeight;		
							}										
							prevSelected = prevSelectedDiv.value;
						}
						break;
			case 40:	var index = -1;				//moving down
						for(var i = 0;i < suggestionBox.childNodes.length;i++){
							if(suggestionBox.childNodes[i].selected){
								index = i;
								break;
							}
						}
						if(index != suggestionBox.childNodes.length - 1){
							var currentIndex = index + 1;
							if (index != -1) {
								suggestionBox.childNodes[index].style.backgroundColor = "";
								suggestionBox.childNodes[index].selected = false;
							}
							
							suggestionBox.childNodes[currentIndex].style.backgroundColor = "#DDDFD1";
							suggestionBox.childNodes[currentIndex].selected = true;																				
							var prevSelectedDiv = suggestionBox.childNodes[currentIndex];									
							if(prevSelectedDiv.offsetTop + prevSelectedDiv.offsetHeight > suggestionBox.clientHeight){
								suggestionBox.scrollTop = suggestionBox.scrollTop + prevSelectedDiv.offsetHeight;		
							}										
							prevSelected = prevSelectedDiv.value;					
						}
						break;
						
			default:	if(box.value == ""){
							prevSelected = "";
						}												
						navigationKeyPressed = false;
						isInvalidEmail = false;	
						break; 	
		};
	};
	/**
	 * Purpose: To remove all divs within the suggestionbox and to hide suggestionbox
	 */
	this.removeSuggestionBox = function(){			
		AnkhUsefulMethods.removeAll(suggestionBox);	
		suggestionBox.style.visibility = "hidden";
	};	
	this.mouseOverSuggestedCell = function(){
		
		if(EventUtil.getEvent().target.suggestedWord){
			
			for (var i = 0; i < suggestionBox.childNodes.length; i++) {
				if(suggestionBox.childNodes[i].value == EventUtil.getEvent().target.suggestedWord.value){					
					suggestionBox.childNodes[i].style.backgroundColor = "#DDDFD1";
					suggestionBox.childNodes[i].selected = true;
					prevSelected = suggestionBox.childNodes[i].value ;		
				}else{
					suggestionBox.childNodes[i].style.backgroundColor = "";
					suggestionBox.childNodes[i].selected = false;
				}
			}				
			EventUtil.getEvent().stopPropagation();			
		}
		
		
	};

	/**
	 * Purpose: Once the user has chosen his option
	 */
	this.chooseOption = function(){
		var option = EventUtil.getEvent().target.suggestedWord;		
		that.confirmOption(option.value,option.innerValue,option.type);
		
	};
	/**
	 * Purpose: Confirm the choice into the input control
	 * @param {String} value - selected value
	 * @param {String} innerValue - selected id, etc. 
	 */
	this.confirmOption = function(value,innerValue,type){
		if (value != emptyDisplayText.innerHTML) {				
			box.value = value;														
			if(AnkhUsefulMethods.isValidEmail(value) || innerValue != ""){
				if (onConfirmed != null) {
					onConfirmed(value,innerValue,type);
				}					
				that.removeSuggestionBox();
				box.value = "";
				that.drawSuggestion("");				
								
				
																				
			}else{
				that.drawInvalidEmail();
				isInvalidEmail = true;
			}
		}		
	};
	
	this.drawInvalidEmail = function(){
		AnkhUsefulMethods.removeAll(suggestionBox);
		var invalidEmail = document.createElement('div');
		invalidEmail.innerHTML = "Invalid email address. Are you sure you type it correctly?";	
		invalidEmail.className = "InvalidEmail";
		suggestionBox.appendChild(invalidEmail);				
	};
	
	/**
	 * Purpose: Given whatever is indicated within the textbox, assign the appropriate representation
	 * in terms of case sensitivity
	 */
	this.locateOption = function(){
		if (dataSet != null) {
			var choice = box.value;
			var valueFound = false;
			var innerValue;
			
			for (var i = 0; i < dataSet.length; i++) {								
				if (dataSet[i][txtField].toUpperCase() == choice.toUpperCase()) {
					choice = dataSet[i][txtField];
					valueFound = true;
					innerValue = dataSet[i][valueField];
					break;
				}				
			}
			if (valueFound || !strict) {
				box.value = choice;								
			}
			else {
				box.value = "";				
			}				
		}
	};
	/**
	 * Purpose: Assign the handler function when the box has confirmed the data
	 * @param {Object} func
	 */
	this.setOnConfirmed = function(func){
		onConfirmed = func;
	};		
	
	this.focus = function(){
		box.focus();
	};
	this.getContainer = function(){
		return container;
	};

	init();
	
};

/**
 * Purpose - Create the Profile Picture Object of the inserted picture
 * @param {String} picture - src of the profile image
 * @param {String} profilePicPopupDirectory - relative directory to the profile pic popup
 * @param {Object} parent - parent object
 * @param {Boolean} viewerIsOwner - true -> viewer is owner
 * @param {Int} groupId -> id of group. If profile does not have a group id, set it to null.
 */
ProfilePic = function(picture,parent,viewerIsOwner,groupId){
	
	var images = new Object();
	if (isIE && !isMinIE7) {
		images['profilePicImg'] = 'Image/02_Display_Picture/displayPicture8.png';
	}else {
		images['profilePicImg'] = 'Image/02_Display_Picture/displayPicture.png';
	}
	for(var i in images){
		var tempImg = new Image();
		tempImg.src = images[i];
	}
	init = function(){
		var container = document.createElement('table');
		container.style.position = "relative";
		container.style.left = "30px";
		
		container.cellPadding = "0";
		container.cellSpacing = "0";
		container.id = "ProfilePic";
		
		var containerBody = document.createElement('tbody');
		container.appendChild(containerBody);
		
		var firstRow = document.createElement('tr');
		containerBody.appendChild(firstRow);
		
		var displayImgContainer = document.createElement('td');
		displayImgContainer.rowSpan = "2";
		displayImgContainer.style.backgroundColor = "#C1CCB5";
		displayImgContainer.style.border = "2px solid #819284";
		displayImgContainer.style.width = "200px";
		displayImgContainer.align = "center";
		firstRow.appendChild(displayImgContainer);
		
		var displayImgContainerDiv = document.createElement('div');
		displayImgContainerDiv.style.position = "relative";
		displayImgContainer.appendChild(displayImgContainerDiv);
		
		var displayImg = document.createElement('img');
		displayImg.src = picture;
		
		displayImg.style.display = "block";
		displayImgContainerDiv.appendChild(displayImg);
		if (viewerIsOwner == true && groupId) {
			var changePicPopup = new AnkhSprite(images['profilePicImg'], 98, 16, {x: 0,y: 0}, {x: 99,y: 0}, {x: 99,y: 0});
			changePicPopup.style.position = "absolute";
			changePicPopup.style.top = "5px";
			changePicPopup.style.right = "5px";
			changePicPopup.style.visibility = "hidden";
			changePicPopup.style.display = "block";
			changePicPopup.style.cursor = "pointer";
			displayImgContainerDiv.appendChild(changePicPopup);
		}
		var rightUpperCorner = document.createElement('td');
		rightUpperCorner.style.background = "url('" + images['profilePicImg'] + "') -198px -0px no-repeat";
		rightUpperCorner.style.width = "6px";
		rightUpperCorner.style.height = "6px";
		rightUpperCorner.style.visibility = "hidden";
		firstRow.appendChild(rightUpperCorner);
		
		var secondRow = document.createElement('tr');
		containerBody.appendChild(secondRow);
		
		var rightShadow = document.createElement('td');
		rightShadow.style.background = "url('" + images['profilePicImg'] + "') -211px 0px repeat-y";
		rightShadow.style.width = "6px";
		rightShadow.style.height = "25px";
		rightShadow.style.visibility = "hidden";
		secondRow.appendChild(rightShadow);
		
		var thirdRow = document.createElement('tr');
		containerBody.appendChild(thirdRow);
		
		var bottomShadow = document.createElement('td');
		bottomShadow.colSpan = "2";
		thirdRow.appendChild(bottomShadow);
		
		var bottomShadowImg = new AnkhSprite(images['profilePicImg'], 210, 8, {x: 0,y: 17});
		bottomShadowImg.style.display = "block";
		bottomShadowImg.style.visibility = "hidden";
		bottomShadow.appendChild(bottomShadowImg);	
		parent.appendChild(container);
		
		var top = AnkhUsefulMethods.findPosY(container);
		var left = AnkhUsefulMethods.findPosX(container) + parseInt(displayImgContainer.style.width, 10);
		if(groupId){
			var profilePicPopup = new ProfilePicPopup(left, top, displayImg,groupId);
		}
	
		initEventHandlers = function(){		
			EventUtil.addEventHandler(displayImg,"load",function x(){	
				rightShadow.style.height = displayImg.height - 2 + "px";
				rightShadow.style.visibility = "visible";
				rightUpperCorner.style.visibility = "visible";
				bottomShadowImg.style.visibility = "visible";
			});
	
			displayImg.src = picture;		//place this here to force reloading
	
			if(viewerIsOwner && groupId){
				EventUtil.addEventHandler(displayImgContainer,"mouseover",function x(){
					changePicPopup.style.visibility = "visible"; 
					changePicPopup.style.display = "block";}
				);
			
				EventUtil.addEventHandler(changePicPopup,"click",function x(){profilePicPopup.show();});		
				EventUtil.addEventHandler(displayImgContainer,"mouseout",function x(){			
					changePicPopup.style.visibility = "hidden";	
					changePicPopup.style.display = "none";	
				});
			}				
		};
		initEventHandlers();
	};
	
	/*if(isIE && !isMinIE7){
		window.setTimeout(init,1);
	}else{
		init();
	}*/	
	init();
	
};

/**
 * Purpose - Display Profile Picture popup to allow user to change picture
 * @param {Int} left	- absolute left coordinates
 * @param {Int} top		- absolute top coordinates
 * @param {String} directory - relative directory from this object
 * @param {String} displayImg - display image container
 */
ProfilePicPopup = function(left,top,displayImg,groupId,announcementId){

	var formAttributes = {action:"php/uploadimage.php",method:"Post",enctype:"multipart/form-data",target:"upload_target"};
	
	var titleTxt = "Change Profile Picture";
	if(groupId){
		titleTxt = "Change Group Photo";
	}else if(announcementId){
		titleTxt = "Change Announcement Photo";
	}
	var genericPopup = new GreenPopup("SupportControls/Popup/",500,titleTxt,"Confirm","submit","Cancel",formAttributes);
	var form = genericPopup.getForm();
	if(groupId){
		var hiddenValue = new AnkhHiddenInput("type","group");
		form.appendChild(hiddenValue);	
		var groupIdValue = new AnkhHiddenInput("groupId",groupId);
		form.appendChild(groupIdValue);	
	}else if(announcementId){
		var hiddenValue = new AnkhHiddenInput("type","groupAnnouncement");
		form.appendChild(hiddenValue);	
		var groupIdValue = new AnkhHiddenInput("announcementId",announcementId);
		form.appendChild(groupIdValue);
	}else{
		var hiddenValue = new AnkhHiddenInput("type","profile");
		form.appendChild(hiddenValue);	
	}	
	
	var contentDiv = genericPopup.getContent();
	
	var selectImageText = document.createElement('div');
	if(groupId){
		selectImageText.innerHTML = "Upload a photo to represent your group (jpg file, max: 4Mb):";
	}else if(announcementId){
		selectImageText.innerHTML = "Upload a photo to showcase this announcement (jpg file, max: 4Mb):";
	}else{		
		selectImageText.innerHTML = "Upload a photo of yourself (jpg file, max: 4Mb):";
	}
	contentDiv.appendChild(selectImageText);
	
	var fileInputContainer = document.createElement('div');
	contentDiv.appendChild(fileInputContainer);
	
	var ajaxLoader = new AnkhAJAXLoader("");
	ajaxLoader.className = "Hidden";
	ajaxLoader.style.cssFloat = "right";
	ajaxLoader.style.styleFloat = "right";
	fileInputContainer.appendChild(ajaxLoader);
		
	var fileInput = new AnkhFileInput("pic");	
	fileInputContainer.appendChild(fileInput);

	var separator = document.createElement('hr');
	separator.style.marginTop = "50px";
	contentDiv.appendChild(separator);
	
	var disclaimer = document.createElement('div');
	disclaimer.innerHTML = "By uploading this picture, you certify that you have the right to distribute this image.";
	disclaimer.style.fontSize = "9px";
	contentDiv.appendChild(disclaimer);

	/**
	 * Purpose - Internal function used by ProfilePic
	 */
	ProfilePicSubmitted =	function(){
	
		var fileName = 	fileInput.value;
		if(fileName == ""){
			alert("Please select a picture to upload");			
			return;
		}
		var fileNameSplitArray = fileName.split(".");
		if(fileNameSplitArray[fileNameSplitArray.length-1].toLowerCase() == "jpg" ){								
			var upload_target = document.getElementById('upload_target');
			var response = upload_target.contentWindow.document.body.innerHTML;
			ajaxLoader.className = "visible";
			genericPopup.getConfirmBtn().disabled = true;
			genericPopup.getCancelBtn().disabled = true;
			if(response == ""){
				setTimeout(ProfilePicSubmitted,1000);			//looping until there is a response to iframe
			}else{			
				var JSONResult = response.evalJSON();
				if(JSONResult.success){
					var newPath = JSONResult['profilePic']['src_m'];							
					displayImg.src = newPath;
					EventUtil.addEventHandler(displayImg,"load",function(){		//this onload function is for IE
						genericPopup.hide();
						upload_target.contentWindow.document.body.innerHTML = "";
						genericPopup.getConfirmBtn().disabled = false;
						genericPopup.getCancelBtn().disabled = false;
						ajaxLoader.className = "Hidden";		
					});									
				}else{
					alert(JSONResult['errorMsg']);
					upload_target.contentWindow.document.body.innerHTML = "";	
					genericPopup.getConfirmBtn().disabled = false;
					genericPopup.getCancelBtn().disabled = false;
					ajaxLoader.className = "Hidden";	
				}						
			}				
		}else{
			alert("Please only upload a jpg image file.");
			EventUtil.getEvent().preventDefault();
			return;
		}	
	};
	
	genericPopup.setConfirmBtnMouseup(ProfilePicSubmitted,"submit");
	
	this.show = function(){
		genericPopup.showInCenterofBrowser();
	};

};

/**
 * Purpose - To create the status HTML control 
 * @param {Object} ownerNameText
 * @param {Object} ownerStatus
 * @param {DateTime} timeCommented - MYSQL datetime this status was updated
 * @param {Object} parent
 * @param {Object} isViewerOwner
 * @param {Object} phpDirectory - directory of the caller file, e.g. headerTester.php in reference to the php/status_write.php file
 * @param {DateTime} todayDate - today's date from server
 */
StatusControl = function(ownerNameText,ownerStatus,timeCommented,parent,isViewerOwner,phpDirectory,todayDate){
	
	var statusContainer = document.createElement('div');
	statusContainer.id = "StatusContainer";		
	parent.appendChild(statusContainer);
		
	var statusDisplay = document.createElement('div');
	statusDisplay.id = "StatusDisplay";
	statusContainer.appendChild(statusDisplay);
		
	var ankhDate = new AnkhDate();
	var JSTimeCommented = ankhDate.mysqlTimeStampToDate(timeCommented);
	
	var updateTime = document.createElement('span');
	updateTime.className = "updateTime";
	updateTime.innerHTML = ankhDate.compareWithToday(JSTimeCommented,todayDate);
		
	
	var ajaxLoader = new AnkhAJAXLoader("");
	
	if (isViewerOwner) {
				
		var statusWriteContainer = document.createElement('div');
		statusWriteContainer.id = "StatusWriteContainer";
		statusContainer.appendChild(statusWriteContainer);
		
		var statusWriteVirtualContainerTbl = document.createElement('table');
		statusWriteVirtualContainerTbl.cellPadding = 0;
		statusWriteVirtualContainerTbl.cellSpacing = 0;
		statusWriteContainer.appendChild(statusWriteVirtualContainerTbl);
		
		var statusWriteVirtualContainerTbody = document.createElement('tbody');
		statusWriteVirtualContainerTbl.appendChild(statusWriteVirtualContainerTbody);
		var statusWriteVirtualContainerRow = document.createElement('tr');
		statusWriteVirtualContainerTbody.appendChild(statusWriteVirtualContainerRow);
		var firstCell = document.createElement('td');
		firstCell.id = "StatusWriteVirtualInput";
		statusWriteVirtualContainerRow.appendChild(firstCell);
		
		var secondCell = document.createElement('td');
		statusWriteVirtualContainerRow.appendChild(secondCell);
				
		var statusDisplayName = document.createElement('span');
		statusDisplayName.id = "StatusDisplayName";
		
		firstCell.appendChild(statusDisplayName);
		statusDisplayName.innerHTML = ownerNameText;
		var fullInputWidth = parseInt(AnkhUsefulMethods.getStyle(statusWriteContainer, "Width"), 10) - (statusDisplayName.offsetWidth + 98)
		
		statusDisplayName.innerHTML = "";
		var emptyInputWidth = parseInt(AnkhUsefulMethods.getStyle(statusWriteContainer, "Width"), 10) - (statusDisplayName.offsetWidth + 98)
		
		var statusInput = document.createElement('input');
		statusInput.id = "StatusInput";
		statusInput.className = "faded";
		statusInput.type = "text";
		statusInput.style.width = emptyInputWidth + "px";
		statusInput.value = "What are you doing now?";
		statusInput.maxLength = "160";
		firstCell.appendChild(statusInput);
		
		var saveBtn = new AnkhButton("SaveBtn","Save",true);
		secondCell.appendChild(saveBtn);
	}
	
	initEventHandler = function(){
		EventUtil.addEventHandler(statusInput, "mousedown", function x(){
			if (AnkhUsefulMethods.trim(statusInput.value) == "is" || statusInput.value == "" || statusInput.value == "What are you doing now?") {
				displayStatusInput();
			}			
		});
		EventUtil.addEventHandler(statusInput, "keyup", function x(){
			if (EventUtil.getEvent().keyCode == 13){
				save();
			}		
		});
		EventUtil.addEventHandler(statusInput, "blur", function x(){
			if (AnkhUsefulMethods.trim(statusInput.value) == "is" || statusInput.value == "") {
				statusInput.value = "What are you doing now?";
				statusInput.style.color = "";
				statusDisplayName.innerHTML = "";
				var inputWidth = parseInt(AnkhUsefulMethods.getStyle(statusWriteContainer, "Width"), 10) - (statusDisplayName.offsetWidth + 98)
				statusInput.style.width = emptyInputWidth + "px";
			}			
		});
		
		EventUtil.addEventHandler(saveBtn, "mouseover", function x(){
			saveBtn.style.background = "#3f74c3";
			saveBtn.style.color = "#FFFFFF";
		});
		EventUtil.addEventHandler(saveBtn, "mouseout", function x(){
			saveBtn.style.background = "";
			saveBtn.style.color = "";
		});
		EventUtil.addEventHandler(saveBtn, "click", save);
	};
	
	displayStatus = function(ownerStatus){
		AnkhUsefulMethods.removeAll(statusDisplay);
		var statusTbl = new GenericTable(1,4);		
		statusDisplay.appendChild(statusTbl.Table);
		
		if (ownerStatus != null) {					
	
			var frontQuote = document.createElement('span');
			frontQuote.className = "doubleQuote";
			frontQuote.innerHTML = "&#147;";
			statusTbl.insertIntoCell(0,0,frontQuote);
			
			var ownerName = document.createElement('span');
			ownerName.className = "ownerName";
			ownerName.innerHTML = ownerNameText;
			statusTbl.insertIntoCell(0,1,ownerName);
			
			var status = document.createElement('span');
			status.className = "ownerStatus";
			status.innerHTML = "&nbsp;"+ownerStatus;
			statusTbl.insertIntoCell(0,1,status);	
			
			var backQuote = document.createElement('span');
			backQuote.className = "doubleQuote";
			backQuote.innerHTML = "&#148;";
			statusTbl.insertIntoCell(0,2,backQuote);
				
			statusTbl.insertIntoCell(0,1,updateTime);		
			statusTbl.insertIntoCell(0,3,ajaxLoader);		
			
			ajaxLoader.style.visibility = "hidden";		
		} else{
			var ownerName = document.createElement('span');
			ownerName.className = "ownerName";
			ownerName.innerHTML = ownerNameText;			
			statusTbl.insertIntoCell(0,0,ownerName);
			statusTbl.insertIntoCell(0,1,ajaxLoader);				
			ajaxLoader.style.visibility = "hidden";	
		}
	};
	
	save = function(){
		if (statusInput.value != "What are you doing now?" && !saveBtn.disabled ) {
			saveBtn.disabled = true;
			ajaxLoader.style.visibility = "visible";
			
			var url = phpDirectory + "php/status_write.php";
			var type = "update";
			var statusMsg = statusInput.value;			
			var parameterObj = {type: type, statusMsg: statusMsg};
			new AnkhAjax(url,"post",parameterObj,writeStatusSuccess,ajaxLoader);
		}
	};
		
	displayStatusInput = function(){
		statusInput.style.width = fullInputWidth + "px";
		statusInput.style.color = "#819284";
		statusInput.value = "is ";
		statusDisplayName.style.visibility = "visible";
		statusDisplayName.innerHTML = ownerNameText;			
		statusInput.focus();
	};
		
	hideStatusInput = function(){
		statusInput.style.width = emptyInputWidth + "px";
		statusInput.style.color = "";
		statusInput.value = "What are you doing now?";
		statusDisplayName.style.visibility = "hidden";
		statusDisplayName.innerHTML = "";			
		statusInput.blur();
	};
	/**
	 * Purpose: On successful AJAX call, this method is called
	 * @param {Object} transport
	 */
	writeStatusSuccess = function(transport){
		saveBtn.disabled = false;
		ajaxLoader.style.visibility = "hidden";
		
		var result = transport.responseText.evalJSON(true);
		if(result.success){
			status.innerHTML = result['statusInfo']['statusMsg'];
			var JSTimeCommented = ankhDate.mysqlTimeStampToDate(result['statusInfo']['lastUpdateDt']);
			var today = ankhDate.mysqlTimeStampToDate(result['currentTime']);
			updateTime.innerHTML = ankhDate.compareWithToday(JSTimeCommented,today);
			hideStatusInput();
			displayStatus(result['statusInfo']['statusMsg']);
		}					
	};
	if (isViewerOwner) {
		initEventHandler();
	}
	
	displayStatus(ownerStatus);
};
/**
 * Purpose: Generic Tab Container
 * @param {Array} headerList - list of headers
 * @param {Object} parent - parent HTML element
 * @param {Func} mouseUpEventHandler - used to activate an event upon mouse up
 */
TabContainer = function(headerList,parent,mouseUpEventHandler){
	var that = this;
	var parent = parent;
	var headerList = headerList;
	var contentArray = new Array();
	var tabHeaderContainer;	
	var tabContentContainer;
	var tabContainer;
	
	init = function(){
		tabContainer = document.createElement('div');
		tabContainer.className = "TabContainer";	
		parent.appendChild(tabContainer);
				
		tabHeaderContainer = document.createElement('div');
		tabHeaderContainer.className = "TabHeaderContainer";
		tabContainer.appendChild(tabHeaderContainer);
		
		tabContentContainer = document.createElement('div');
		tabContentContainer.className = "TabContentContainer";
		tabContainer.appendChild(tabContentContainer);
		
		
		for(var i = 0;i < headerList.length ;i++){
			//Draw the content containers
			var content = document.createElement('div');
			contentArray[i] = content;		
			if(i == 0){
				contentArray[i].className = "Visible";
			}else{
				contentArray[i].className = "Hidden";
			}	
						
			//Draw the tab headers			
			var header = new AnkhLink(headerList[i],mouseUp,"#"+headerList[i],"TabHeaderContainerLinkSelected");								
			contentArray[i].header = header;	
			
			if(i == 0){				
				header.className = "TabHeaderContainerLinkSelected";
			}else{
				header.className = "TabHeaderContainerLink";
			}
			tabHeaderContainer.appendChild(header);
			tabContentContainer.appendChild(contentArray[i]);
		}
	};
		
	mouseUp = function(target){
		var selectedIndex;
		for (var i = 0; i < contentArray.length; i++) {
			if (contentArray[i].header == target) {
				contentArray[i].header.className = "TabHeaderContainerLinkSelected";
				contentArray[i].className = "Visible";
				selectedIndex = i;
			}
			else {
				contentArray[i].header.className = "TabHeaderContainerLink";
				contentArray[i].className = "Hidden";
			}
		}
		if(mouseUpEventHandler){
			mouseUpEventHandler(target,selectedIndex);
		}
	};
	
	this.selectedIndex = function(index){
		for (var i = 0; i < contentArray.length; i++) {
			if (i == index) {
				contentArray[i].header.className = "TabHeaderContainerLinkSelected";
				contentArray[i].className = "Visible";
			}
			else {
				contentArray[i].header.className = "TabHeaderContainerLink";
				contentArray[i].className = "Hidden";
			}
		}
	};

	/**
	 * Purpose - Return the content of the tab container so that this control can be customised to whichever way required.
	 */
	this.getContentArray = function(){
		return contentArray;
	};
	/**
	 * Purpose - Set position of the tab container
	 * @param {Int} left
	 * @param {Int} top
	 */
	this.setPosition = function(left,top,width){
		tabContainer.style.left = left + "px";
		tabContainer.style.top = top + "px";
		tabContainer.style.width = width+"px";
	}
	/**
	 * Purpose - Return tabHeaderContainer to allow customisation such as "edit profile"
	 */
	this.getTabHeaderContainer = function(){
		return tabHeaderContainer;
	};
	
	this.getTabHeader = function(index){
		return tabHeaderContainer.childNodes[index];
	};
	
	/**
	 * Purpose - Set the id of the content container
	 * @param {String} id
	 */
	this.setTabContentContainerId = function(id){
		tabContentContainer.id = id;
	};
	
	this.getHTML = function(){
		return tabContainer;
	};
	/**
	 * Purpose: Used to set a standard height across all the tab contents. 
	 * To lessen disruptions on users when tab is changed
	 * @param {Int} height
	 */
	this.setStandardHeight = function(height){
		for (var i = 0; i < contentArray.length; i++){
			contentArray[i].style.height = height + "px";
		}
	};
	
	init();
};



/**
 * Purpose: Used to tag people in photos
 * @param {Object} parent
 */
Tagger = function(networkList,onConfirmFunc,lengthObj){
	var that = this;
	var length = lengthObj['length'] || 55;
	var imgWidth;
	var imgHeight;
	var imgX;
	var imgY;
	var minLength = lengthObj['minLength'] || 20;
	var maxLength = lengthObj['maxLength'] || 120;		
		
	var tagWidth = length;
	var tagHeight = length;
	
	var resizingLeft = false;
	var resizingRight = false;
	var resizingTop = false;
	var resizingBtm = false;
	
	var resizingBtmRight = false;
	var resizingTopLeft = false;
	var resizingTopRight = false;
	var resizingBtmLeft = false;
	
	var resizerWidth = 5;
	var resizerHeight = 5;
	
	var participantTaggerFields = {dataSet:networkList,headerTxt:"Type any name or email",txtField:"displayNm",valueField:"friendId",picField:"thumbnail",typeField:"type",strict:false};	
	var participantTagger = new ParticipantAdder(document.body,participantTaggerFields);
	participantTagger.setOnConfirmed(onConfirmFunc);
	participantTagger.getContainer().style.position = "absolute";
	participantTagger.getContainer().style.visibility = "hidden";
	participantTagger.getContainer().style.display = "none";
	participantTagger.getContainer().style.background = "#E0E9F5";
	participantTagger.getContainer().childNodes[0].style.borderLeft = "2px solid #A8B6B9";
	participantTagger.getContainer().childNodes[0].style.borderRight = "2px solid #A8B6B9";
	participantTagger.getContainer().childNodes[0].style.borderTop = "2px solid #A8B6B9";				
	
	var structure = new GenericTable(3,3);
	var tagSquare = structure.Table;	
	tagSquare.cellPadding = 0;
	tagSquare.cellSpacing = 0;
	tagSquare.style.display = "none";
	tagSquare.style.visibility = "hidden";
	tagSquare.id = "TagSquare";	
	tagSquare.style.width = length  + "px";
	tagSquare.style.height = length  + "px";
	document.body.appendChild(tagSquare);
	AnkhUsefulMethods.disableSelection(tagSquare);
	
	var topLeft = document.createElement('div');
	topLeft.className = "corner";
	topLeft.style.cursor = "nw-resize";
	structure.insertIntoCell(0,0,topLeft);
	var topRight = document.createElement('div');
	topRight.className = "corner";
	topRight.style.cursor = "ne-resize";
	structure.insertIntoCell(0,2,topRight);
		
	var btmLeft = document.createElement('div');
	btmLeft.className = "corner";
	btmLeft.style.cursor = "ne-resize";
	structure.insertIntoCell(2,0,btmLeft);
	var btmRight = document.createElement('div');
	btmRight.className = "corner";
	btmRight.style.cursor = "nw-resize";
	structure.insertIntoCell(2,2,btmRight);
	
	var top = document.createElement('div');
	top.style.cursor = "n-resize";
	top.className = "wide";
	structure.insertIntoCell(0,1,top);	
	var btm = document.createElement('div');
	btm.className = "wide";
	btm.style.cursor = "n-resize";
	structure.insertIntoCell(2,1,btm);
	
	var leftBar = document.createElement('div');
	leftBar.className = "tall";
	leftBar.style.cursor = "e-resize";
	structure.insertIntoCell(1,0,leftBar);
	var right = document.createElement('div');
	right.className = "tall";
	right.style.cursor = "e-resize";
	structure.insertIntoCell(1,2,right);
	
	leftBar.style.height = length + "px";
	right.style.height = length + "px";
	
	var tagDisplayInner = document.createElement('div');
	tagDisplayInner.id = "tagDisplayInner";
	if(isIE && !isMinIE7){
		tagDisplayInner.style.cursor = "pointer";
	}	
	tagDisplayInner.style.width = length - 4 + "px";
	tagDisplayInner.style.height = length - 4 + "px";	
	structure.insertIntoCell(1,1,tagDisplayInner);
	
	this.show = function(x,y,target){		
		if(isIE){
			imgWidth = target.width - 6;
			imgHeight = target.height - 6;	
		}else{
			imgWidth = target.width;
			imgHeight = target.height;
		}
				
		imgX = AnkhUsefulMethods.findPosX(target);
		imgY = AnkhUsefulMethods.findPosY(target);					
		var width = parseInt(tagSquare.style.width,10);
		var height = parseInt(tagSquare.style.height,10) ;
		
		that.draw(x - width/2 - resizerWidth, y - height/2 - resizerHeight,0,0);
	};
	this.showFromTopLeft = function(x,y,target,tagWidth,tagHeight){
		if(isIE){
			imgWidth = target.width - 6;
			imgHeight = target.height - 6;	
		}else{
			imgWidth = target.width;
			imgHeight = target.height;
		}			
		imgX = AnkhUsefulMethods.findPosX(target);
		imgY = AnkhUsefulMethods.findPosY(target);
			
		var width = tagWidth || parseInt(tagSquare.style.width,10);
		var height = tagHeight || parseInt(tagSquare.style.height,10) ;
		
		that.draw(x , y ,width,height,true);
	};

	
	this.draw = function(left,top,newWidth,newHeight,hideParticipantTagger){	
		if(left){
			if(left < imgX){
				left = imgX;
				newWidth = 0;
			}else if(left + parseInt(tagSquare.style.width,10) > imgX + imgWidth){
				left = imgWidth - parseInt(tagSquare.style.width,10) + imgX;
			}			
			tagSquare.style.left = left +"px";
		}
		if(top){
			
			if(top < imgY){
				top = imgY;
				newHeight = 0;
			}else if(top + parseInt(tagSquare.style.height,10) > imgHeight + imgY){
				top = imgHeight - parseInt(tagSquare.style.height,10) + imgY;
			}
			 
			tagSquare.style.top = top + "px";
			
		}
		
		if(newWidth){			
			if(parseInt(tagSquare.style.left,10) + newWidth > imgWidth + imgX){
				newWidth = imgWidth + imgX - parseInt(tagSquare.style.left,10);								
			}
			if(newWidth > maxLength){
				newWidth = maxLength;
			}else if(newWidth < minLength){
				newWidth = minLength;
			}
			
			tagSquare.style.width = newWidth +"px";
			tagDisplayInner.style.width = newWidth - 4 + "px";	
			tagWidth = newWidth;
		}		
		if(newHeight){
			if(parseInt(tagSquare.style.top,10) + newHeight > imgHeight + imgY){
				newHeight = imgHeight + imgY - parseInt(tagSquare.style.top,10);
			}
			if(newHeight > maxLength){
				newHeight = maxLength;
			}else if(newHeight < minLength){
				newHeight = minLength;
			}
			tagSquare.style.height = newHeight +"px";
			leftBar.style.height = newHeight + "px";
			right.style.height = newHeight + "px";							
			tagDisplayInner.style.height = newHeight - 4 + "px";
			tagHeight = newHeight;		
		}
		
					
		tagSquare.style.display = "block";
		tagSquare.style.visibility = "visible";	
		participantTagger.getContainer().style.left = AnkhUsefulMethods.findPosX(tagSquare) - 215 +"px";
		participantTagger.getContainer().style.top = AnkhUsefulMethods.findPosY(tagSquare)  +"px";
		if(!hideParticipantTagger){	
			participantTagger.getContainer().style.display = "block";
			participantTagger.getContainer().style.visibility = "visible";
			window.setTimeout(function(){participantTagger.focus()},100);
		}			
	};

	initEvents = function(){
						
		EventUtil.addEventHandler(btmRight,"mousedown",function(){resizingBtmRight = true; EventUtil.getEvent().stopPropagation(); });
		EventUtil.addEventHandler(topLeft,"mousedown",function(){resizingTopLeft = true;  EventUtil.getEvent().stopPropagation(); });								
		EventUtil.addEventHandler(topRight,"mousedown",function(){resizingTopRight = true;  EventUtil.getEvent().stopPropagation(); });
		EventUtil.addEventHandler(btmLeft,"mousedown",function(){resizingBtmLeft = true;  EventUtil.getEvent().stopPropagation(); });
		EventUtil.addEventHandler(leftBar,"mousedown",function(){resizingLeft = true; EventUtil.getEvent().stopPropagation(); });
		EventUtil.addEventHandler(right,"mousedown",function(){resizingRight = true; EventUtil.getEvent().stopPropagation(); });								
		EventUtil.addEventHandler(top,"mousedown",function(){resizingTop = true; EventUtil.getEvent().stopPropagation(); });
		EventUtil.addEventHandler(btm,"mousedown",function(){resizingBtm = true; EventUtil.getEvent().stopPropagation(); });
		
		EventUtil.addEventHandler(document,"mousemove",resizeMove);
		EventUtil.addEventHandler(document,"mouseup",resizingUp);
		EventUtil.addEventHandler(document,"mousedown",that.hide);
						
		EventUtil.addEventHandler(structure.getCell(1,1),"mousedown",function(){				
			var width = parseInt(tagSquare.style.width,10);
			var height = parseInt(tagSquare.style.height,10);
			var relativeX = EventUtil.getEvent().pageX - AnkhUsefulMethods.findPosX(EventUtil.getEvent().target);
			var relativeY = EventUtil.getEvent().pageY - AnkhUsefulMethods.findPosY(EventUtil.getEvent().target);
			var moveRight = relativeX - width/2;
			var moveDown = relativeY - height/2;			
			that.draw(parseInt(tagSquare.style.left,10) + moveRight,parseInt(tagSquare.style.top,10) + moveDown,0,0);
			EventUtil.getEvent().stopPropagation();
		});
	};
	

	
	resizeMove = function(){		
		if(resizingBtmRight){			
			var newWidth =  EventUtil.getEvent().pageX - AnkhUsefulMethods.findPosX(tagSquare) - resizerWidth;
			var newHeight = EventUtil.getEvent().pageY - AnkhUsefulMethods.findPosY(tagSquare) - resizerHeight;
			if(isIE){
				newWidth -= resizerWidth;
				newHeight -= resizerHeight;
			}
							
			if(newWidth < minLength){
				newWidth = minLength;			
			}else if(newWidth > maxLength){
				newWidth = maxLength;			
			}			
			if(newHeight < minLength){
				newHeight = minLength;				
			}else if(newHeight > maxLength){
				newHeight = maxLength;				
			}
			that.draw(0,0,newWidth,newHeight);						
				
		}else if(resizingTopLeft){
			var newWidth =  AnkhUsefulMethods.findPosX(tagSquare) - EventUtil.getEvent().pageX  + parseInt(tagSquare.style.width,10) ;
			var newHeight = AnkhUsefulMethods.findPosY(tagSquare) - EventUtil.getEvent().pageY  + parseInt(tagSquare.style.height,10) ;
			if(isIE){
				newWidth += resizerWidth;
				newHeight += resizerHeight;
			}				
			if(newWidth < minLength){
				newWidth = minLength;			
			}else if(newWidth > maxLength){
				newWidth = maxLength;			
			}			
			if(newHeight < minLength){
				newHeight = minLength;				
			}else if(newHeight > maxLength){
				newHeight = maxLength;				
			}		
			that.draw(parseInt(tagSquare.style.left,10) + parseInt(tagSquare.style.width,10) - newWidth,parseInt(tagSquare.style.top,10) + parseInt(tagSquare.style.height,10) - newHeight,newWidth,newHeight);					
			
		}else if(resizingTopRight){
			var newWidth =  EventUtil.getEvent().pageX - AnkhUsefulMethods.findPosX(tagSquare)  - resizerWidth ;
			var newHeight = AnkhUsefulMethods.findPosY(tagSquare) - EventUtil.getEvent().pageY  + parseInt(tagSquare.style.height,10);
			if(isIE){
				newWidth -= resizerWidth;
				newHeight += resizerHeight;
			}					
			if(newWidth < minLength){
				newWidth = minLength;			
			}else if(newWidth > maxLength){
				newWidth = maxLength;			
			}			
			if(newHeight < minLength){
				newHeight = minLength;				
			}else if(newHeight > maxLength){
				newHeight = maxLength;				
			}		
			that.draw(parseInt(tagSquare.style.left,10),parseInt(tagSquare.style.top,10) + parseInt(tagSquare.style.height,10) - newHeight,newWidth,newHeight);		
			
		}
		else if(resizingBtmLeft){
			var newWidth =  AnkhUsefulMethods.findPosX(tagSquare) - EventUtil.getEvent().pageX  + parseInt(tagSquare.style.width,10);
			var newHeight = EventUtil.getEvent().pageY - AnkhUsefulMethods.findPosY(tagSquare) - resizerHeight;
			if(isIE){
				newWidth += resizerWidth;
				newHeight -= resizerHeight;
			}					
			if(newWidth < minLength){
				newWidth = minLength;			
			}else if(newWidth > maxLength){
				newWidth = maxLength;			
			}			
			if(newHeight < minLength){
				newHeight = minLength;				
			}else if(newHeight > maxLength){
				newHeight = maxLength;				
			}		
			that.draw(parseInt(tagSquare.style.left,10) + parseInt(tagSquare.style.width,10) - newWidth,parseInt(tagSquare.style.top,10),newWidth,newHeight);					
		}
		else if(resizingLeft){
			var newWidth =  AnkhUsefulMethods.findPosX(tagSquare) - EventUtil.getEvent().pageX  + parseInt(tagSquare.style.width,10);
			if(isIE){
				newWidth += resizerWidth;			
			}							
			if(newWidth < minLength){
				newWidth = minLength;			
			}else if(newWidth > maxLength){
				newWidth = maxLength;			
			}							
			that.draw(parseInt(tagSquare.style.left,10) + parseInt(tagSquare.style.width,10) - newWidth,parseInt(tagSquare.style.top,10),newWidth,0);					
		}
		else if(resizingRight){
			var newWidth =  EventUtil.getEvent().pageX - AnkhUsefulMethods.findPosX(tagSquare)  - resizerWidth ;
			if(isIE){
				newWidth -= resizerWidth;			
			}						
			if(newWidth < minLength){
				newWidth = minLength;			
			}else if(newWidth > maxLength){
				newWidth = maxLength;			
			}
			that.draw(0,0,newWidth,0);														
		}
		else if(resizingTop){						
			var newHeight = AnkhUsefulMethods.findPosY(tagSquare) - EventUtil.getEvent().pageY  + parseInt(tagSquare.style.height,10);
			if(isIE){
				newHeight -= resizerHeight;
			}							
			if(newHeight < minLength){
				newHeight = minLength;				
			}else if(newHeight > maxLength){
				newHeight = maxLength;				
		}		
			that.draw(parseInt(tagSquare.style.left,10),parseInt(tagSquare.style.top,10) + parseInt(tagSquare.style.height,10) - newHeight,0,newHeight);								
		}
		else if(resizingBtm){			
			var newHeight = EventUtil.getEvent().pageY - AnkhUsefulMethods.findPosY(tagSquare) - resizerHeight;
			if(isIE){
				newHeight -= resizerHeight;
			}							
			if(newHeight < minLength){
				newHeight = minLength;				
			}else if(newHeight > maxLength){
				newHeight = maxLength;				
			}		
			that.draw(parseInt(tagSquare.style.left,10),parseInt(tagSquare.style.top,10),0,newHeight);									
		}
		
	};
	
	resizingUp = function(){
		resizingBtmRight = false;
		resizingTopLeft = false;
		resizingTopRight = false;
		resizingBtmLeft = false;
		
		resizingLeft = false;
		resizingRight = false;
		resizingTop = false;
		resizingBtm = false;
		EventUtil.getEvent().stopPropagation();
	};
	
	this.getCoor = function(){
		
		return {left:parseInt(tagSquare.style.left,10) - imgX,
				top:parseInt(tagSquare.style.top,10) - imgY,
				width:tagWidth,
				height:tagHeight};
	};
	this.setFrontDataFunc = function(func){
		participantTagger.setFrontDataFunc(func);
	};
	this.resetPos = function(){
		participantTagger.resetPos();
	};
	this.setDataSet = function(value){
		participantTagger.setDataSet(value);
	};
	
	
	this.hide = function(){
		tagSquare.style.display = "none";
		tagSquare.style.visibility = "hidden";
		participantTagger.getContainer().style.display = "none";
		participantTagger.getContainer().style.visibility = "hidden";
	};
	initEvents();
	
};
/**
 * Purpose: Create the virtual popup to let users select start and end dates of event
 * @param {Object} parent - HTML object with sDate and eDate as its attributes
 * @param {DateTime} startDt - jsDate
 * @param {DateTime} endDt - jsDate
 * @param {Boolean} announcement - true -> only for announcement
 */
EventDatePopup = function(parent,startDt,endDt,announcement){
	if(announcement){
		var eventDatePopup = new GreenPopup("SupportControls/Popup/",400,"Select activity date","Confirm","button","cancel");	
	}else{
		var eventDatePopup = new GreenPopup("SupportControls/Popup/",400,"Select event date","Confirm","button","cancel");
	}
	
	var contentContainer = eventDatePopup.getContent();		
	var that = this;
	var tableStructure = new GenericTable(5,2);
	tableStructure.Table.id = "EventDateSelectorTbl";
	tableStructure.Table.cellPadding = 0;	
	contentContainer.appendChild(tableStructure.Table);
	
	var rowNum = 0;	
	var header = document.createElement('h2');	
	header.innerHTML = "Event Date";
	if(announcement){
		header.innerHTML = "Upcoming Activity Date";
	}
	tableStructure.getCell(rowNum,0).colSpan = "2";
	tableStructure.insertIntoCell(rowNum,0,header);
	rowNum += 1;
	tableStructure.insertIntoCell(rowNum,0,"Start:");
	var sDate = new AnkhCalendarControl(tableStructure.getCell(rowNum,1),true,true,true,false,"SDate",startDt,null,announcement);
	rowNum += 1;
	tableStructure.insertIntoCell(rowNum,0,"End:");
	var eDate = new AnkhCalendarControl(tableStructure.getCell(rowNum,1),true,true,true,false,"EDate",endDt,null,announcement);
	rowNum += 1;
	
	tableStructure.getCell(rowNum,0).colSpan = "2";
	var eventDateCheckBox = new AnkhCheckBox("EventDateCheckBox","","");
	tableStructure.insertIntoCell(rowNum,0,eventDateCheckBox);
		
	if(announcement){
		tableStructure.insertIntoCell(rowNum,0,"This activity spans more than a day");	
	}else{
		tableStructure.insertIntoCell(rowNum,0,"My event spans more than a day");	
	}
	rowNum += 1;
	if(announcement){
		tableStructure.getCell(rowNum,0).colSpan = "2";
		var noParticularDayCheckBox = new AnkhCheckBox("NoParticularDayCheckBox","","");
		tableStructure.insertIntoCell(rowNum,0,noParticularDayCheckBox);
		var noParticularDayTxt = "No particular day";
		tableStructure.insertIntoCell(rowNum,0,noParticularDayTxt);
		EventUtil.addEventHandler(noParticularDayCheckBox,"click",function(){
			if(EventUtil.getEvent().target.checked){
				sDate.disable(true);
				eDate.disable(true);
			}else{
				sDate.disable(false);
				eDate.disable(false);
			}
		});		
	}
	var err = new AnkhFormErrorContainer(contentContainer,"SelectEventDateError");
	
	init = function(){		
		EventUtil.addEventHandler(eventDateCheckBox,"click",spanBoxChanged);
		
		that.hideSDED();
		eventDatePopup.setConfirmBtnMouseup(that.onConfirm,"click");
		if(endDt!="" && endDt !=null && startDt != endDt){
			eventDateCheckBox.checked = true;			
			that.showSDED();
		}
	};
	
	this.hideSDED = function(){	
		tableStructure.getCell(1,0).style.visibility = "hidden";
		tableStructure.getCell(2,0).style.visibility = "hidden";
		tableStructure.getCell(2,1).style.visibility = "hidden";
	};
	
	this.showSDED = function(){
		tableStructure.getCell(1,0).style.visibility = "visible";
		tableStructure.getCell(2,0).style.visibility = "visible";
		tableStructure.getCell(2,1).style.visibility = "visible";
	};
	
	this.onConfirm = function(){
		if(!announcement){
			if(sDate.getDateValue() > new Date()){
				that.showError("You may not create events for future dates.");
				return;
			}
			else if(eventDateCheckBox.checked &&  eDate.getDateValue() > new Date()){
				that.showError("You may not create events for future dates.");
				return;
			}
		}else{
			var currentDate = new Date();
			var yest = currentDate.setDate(currentDate.getDate() - 1);
			if(sDate.getDateValue() < yest){
				that.showError("You may not announce an activity for the past.");
				return;
			}
			else if(eventDateCheckBox.checked &&  eDate.getDateValue() < yest){
				that.showError("You may not announce an activity for the past.");
				return;
			}
		}
		if (eventDateCheckBox.checked && eDate.getDateValue() < sDate.getDateValue()) {
			that.showError("Your start date is later than the end date.");
		}	
		else {
			var ankhDate = new AnkhDate();		
			var startDt = ankhDate.formatMYSQLDate(sDate.getDateValue());
			if(announcement && noParticularDayCheckBox.checked){
				parent.innerHTML = noParticularDayTxt;
				parent.sDate.value = "";
				parent.eDate.value = "";
			}
			else if (eventDateCheckBox.checked && sDate.getTimeStamp() != eDate.getTimeStamp()) {				
				parent.innerHTML = ankhDate.getMDY(sDate.getDateValue(), " ") + " - " + ankhDate.getMDY(eDate.getDateValue(), " ");
				parent.sDate.value = startDt;
				parent.eDate.value = ankhDate.formatMYSQLDate(eDate.getDateValue());
			}
			else {
				parent.innerHTML = ankhDate.getMDY(sDate.getDateValue(), " ");
				parent.sDate.value = startDt;
				parent.eDate.value = "";
			}	
			err.hide();
			eventDatePopup.hide();		
		}
	};
	
	this.showError = function(msg){
		err.show(msg);
	};
	
	this.showInCenterofBrowser = function(){
		eventDatePopup.showInCenterofBrowser();
	};
	this.show = function(left,top){
		eventDatePopup.show(left,top);
	};
	/**
	 * Purpose: When the event more than a day box has been clicked
	 */
	spanBoxChanged = function(){
		if(EventUtil.getEvent().target.checked){
			that.showSDED();
		}else{
			that.hideSDED();
		}
	};
	init();
};FriendPopup = function(parent,directory,friendList,checkBoxClickHandler){
	var image = new Object();
	if (isIE && !isMinIE7) {
		image['popupImg'] = directory + "image/friendpopup8.png";
	}else{
		image['popupImg'] = directory + "image/friendpopup.png";
	}	
	for(var i in image){
		var tempImg = new Image();
		tempImg.src = image[i];
	}
	var that = this;
	var selectedFriends = new Array();
	var checkBoxArray = new Array();
	var container = new AnkhSprite(image['popupImg'],300,300,{x:0,y:0});
	container.style.visibility = "hidden";
	container.style.display = "none";
	container.id = "FriendPopup";
	container.style.position = "absolute";	
	parent.appendChild(container);
		
	var closeBtn = new AnkhSprite(image['popupImg'],16,17,{x:301,y:20},{x:301,y:0},{x:301,y:0});
	closeBtn.id = "CloseBtn";
	container.appendChild(closeBtn);
	
	var searchName = new AnkhTextBoxWithContent("SearchName", "Type your friend's name","");
	searchName.id = "SearchName";	
	container.appendChild(searchName);
	
	var innerFriendContainer = document.createElement('div');
	innerFriendContainer.id = "InnerFriendContainer";
	container.appendChild(innerFriendContainer);
	
	init = function(){		
		EventUtil.addEventHandler(searchName, "keyup", that.filterNames);
		EventUtil.addEventHandler(closeBtn,"click",that.hide);
		EventUtil.addEventHandler(document.body,"mouseup",that.hide);
		EventUtil.addEventHandler(container,"mouseup",function x(){
			EventUtil.getEvent().stopPropagation();
		});
		for (var i = 0; i < friendList.length; i++) {
			friendList[i].checked = false;
		}
		that.draw(friendList);
	};
	/**
	 * Purpose: Return the friends whom the user has selected. SelectedFriends is the same format as the input
	 * friendList
	 */
	this.getSelectedFriends = function(){
		return selectedFriends;
	};
	
	/**
	 * Purpose: Used to filter names based on names within textbox
	 */
	this.filterNames = function(){
		AnkhUsefulMethods.removeAll(innerFriendContainer);
		var filteredFriendList = new Array();
		var value = AnkhUsefulMethods.trim(EventUtil.getEvent().target.value);
		
		if (value != "") {
			var filterArray = value.split(" ");
			for (var i = 0; i < friendList.length; i++) {
				var friend = friendList[i].displayNm + " " + friendList[i].tag;				
				var friendArray = friend.split(" ");
				var wanted = 0;
				
				for (var k = 0; k < filterArray.length; k++) {
					for (var j = 0; j < friendArray.length; j++) {
						if (filterArray[k] != "" && friendArray[j].toUpperCase().indexOf(filterArray[k].toUpperCase()) == 0) {
							wanted++;
							break;
						}
					}
				}
				if (wanted == filterArray.length) {
					filteredFriendList.push(friendList[i]);
				}
			}
			that.draw(filteredFriendList, value);
		}
		else {
			that.draw(friendList);
		}
	};
	
	this.draw = function(friendList,filter){
		if(friendList.length > 0){
			var tblStructure = new GenericTable(friendList.length,2);
			innerFriendContainer.appendChild(tblStructure.Table);
			tblStructure.Table.id = "FriendPopupTbl";
			tblStructure.Table.cellPadding = 2;
			tblStructure.Table.cellSpacing = 0;
			if (friendList.length > 0 ) {
				tblStructure.getCell(0,0).width = "15%";
				tblStructure.getCell(0,1).width = "85%";
			}else{
				tblStructure.insertIntoCell(0,0,"No one fits into your filter.");
			}
			for (var i = 0; i < friendList.length; i++) {
				
				var nameContainer = document.createElement('div');
				if (filter == null) {
					var name = document.createElement('div');
					name.innerHTML = friendList[i].displayNm;
					nameContainer.appendChild(name);
					if(friendList[i].tag){
						var tag = document.createElement('div');
						tag.className = "tag";
						tag.innerHTML = friendList[i].tag;
						nameContainer.appendChild(tag);
					}
					
				}
				else {
					var friendNameArray = friendList[i].displayNm.split(" ");
					var friendTagArray = friendList[i].tag.split(" ");
					var filterArray = filter.split(" ");
					
					var name = document.createElement('div');
					nameContainer.appendChild(name);
					for (var j = 0; j < friendNameArray.length; j++) {
						var highlighted = false;
						for (var k = 0; k < filterArray.length; k++) {
							highlighted = that.highlightWords(filterArray[k], friendNameArray[j], name);
							if (highlighted) {
								break;
							}
						}
						if (!highlighted) {
							var remainingWord = document.createElement('span');
							remainingWord.innerHTML = friendNameArray[j] + "\u0020 ";
							if (isIE) {
								remainingWord.style.marginLeft = "2px";
							}
							name.appendChild(remainingWord);
						}
					}
					if(friendList[i].tag){
						var tag = document.createElement('div');
						tag.className = "tag";
						nameContainer.appendChild(tag);
					
						for (var j = 0; j < friendTagArray.length; j++) {
							var highlighted = false;
							for (var k = 0; k < filterArray.length; k++) {
								highlighted = that.highlightWords(filterArray[k], friendTagArray[j], tag);
								if (highlighted) {
									break;
								}
							}
							if (!highlighted) {
								var remainingWord = document.createElement('span');
								remainingWord.innerHTML = friendTagArray[j] + "\u0020 ";
								if (isIE) {
									remainingWord.style.marginLeft = "2px";
								}
								tag.appendChild(remainingWord);
							}
						}
					}
				}
				tblStructure.insertIntoCell(i,1,nameContainer);			
				var checkbox = new AnkhCheckBox("friends", friendList[i].friendId);
				checkBoxArray.push(checkbox);
				checkbox.friend = friendList[i];
				EventUtil.addEventHandler(checkbox, "click", that.checkBoxClick);
				tblStructure.insertIntoCell(i,0, checkbox);
				checkbox.checked = friendList[i].checked;
			}
		}else{
			var noFriends = new AnkhFormNotificationContainer(innerFriendContainer,"NoFriends","yellow");
			noFriends.show("You have no friends that match your filter.");		
		}
	};
	/**
	 * Purpose: Used to highlight the words
	 * @param {String} filterPortion
	 * @param {String} friendPortion
	 * @param {Object} parent
	 */
	this.highlightWords = function(filterPortion, friendPortion, parent){
		var hightlighted = false;
		if (filterPortion != "" && friendPortion.toUpperCase().indexOf(filterPortion.toUpperCase()) == 0) {
			var requestWord = document.createElement('span');
			requestWord.className = "RequestedWord";
			requestWord.innerHTML = friendPortion.substr(0, filterPortion.length);
			parent.appendChild(requestWord);
			
			var remainingWord = document.createElement('span');
			remainingWord.innerHTML = friendPortion.substr(filterPortion.length) + "\u0020 ";
			parent.appendChild(remainingWord);
			hightlighted = true;
			if (isIE && remainingWord.innerHTML == "") {
				remainingWord.style.marginLeft = "2px";
			}
		}
		return hightlighted;
	};
	
	this.checkBoxClick = function(){
		EventUtil.getEvent().target.friend.checked = EventUtil.getEvent().target.checked;	
		if(EventUtil.getEvent().target.checked){
			selectedFriends.push(EventUtil.getEvent().target.friend);
		}else{
			for(var i = 0;i < selectedFriends.length;i++){
				if(selectedFriends[i] == EventUtil.getEvent().target.friend){
					selectedFriends.splice(i,1);
					break;
				}
			}
		}
		if(checkBoxClickHandler){
			checkBoxClickHandler();
		}	
	};	
	this.hide = function(){
		container.style.visibility = "hidden";
		container.style.display = "none";
	};
	this.show = function(x,y){
		container.style.visibility = "visible";
		container.style.display = "block";
		if(x){
			container.style.left = x+"px";
		}
		if(y){
			container.style.top = y+"px";
		}
	};
	this.reset = function(){
		selectedFriends = new Array();
		for (var i = 0;i < checkBoxArray.length;i++){
			checkBoxArray[i].checked = false;
		}
	};
	init();	
	
};
GreenPopup = function(popupDir,width,titleMsg,confirmBtnText,confirmBtnType,cancelBtnText,formAttributes,okBtnTxt){
	var img = {};
	if(isIE && !isMinIE7){
		img['corners'] = popupDir + "image/Greenpopup8.png";
		img['box'] =  popupDir + "image/GreenpopupBox8.png";
	}else{
		img['corners'] = popupDir + "image/Greenpopup.png";
		img['box'] =  popupDir + "image/GreenpopupBox.png";
	}
	
	var that = this;	
	
	var container = document.createElement('div');
	container.id = "GreenPopup";
	document.body.appendChild(container);
	
	if (isIE && !isMinIE7) {			
		var iframe = document.createElement('iframe');
		iframe.className = "selectFree";		
		iframe.style.width = width+"px";
		container.appendChild(iframe);
	}
	
	var structure = new GenericTable(4,3);	
	structure.Table.cellPadding = "0";
	structure.Table.cellSpacing = "0";
	structure.Table.style.width = width+"px"; 
	if(formAttributes){		
		var form = new AnkhFormContainer("GreenPopupForm",formAttributes['method'],formAttributes['action'],formAttributes['enctype'],formAttributes['target']);
		container.appendChild(form);
		form.appendChild(structure.Table);
	}else{
		container.appendChild(structure.Table);	
	}				
	structure.getCell(0,0).colSpan = "3";
	
	var topLeft = new AnkhSprite(img['corners'],40,40,{x:0,y:0});
	topLeft.id = "TopLeft";
	structure.insertIntoCell(0,0,topLeft);
				
	var top = document.createElement('div');
	top.id = "Top";
	top.style.width = width - 40 - 10 +"px";
	top.style.background = "url('" + img['box'] + "') repeat-x";
	structure.insertIntoCell(0,0,top);
	
	var topRight = new AnkhSprite(img['corners'],10,40,{x:41,y:0});
	topRight.id = "TopRight";	
	structure.insertIntoCell(0,0,topRight);

	var left = structure.getCell(1,0);
	left.id = "Left";
	left.style.background = "url('" + img['box'] + "') repeat-y";	
	
	var content = structure.getCell(1,1);
	content.id = "ContentLayer";	
	
	var right = structure.getCell(1,2);
	right.id = "Right";		
	right.style.background = "url('" + img['box'] + "') repeat-y";
			
	var secondLeft = structure.getCell(2,0);
	secondLeft.id = "SecondLeft";	
	secondLeft.style.background = "url('" + img['box'] + "') repeat-y";	
	
	var footerContainer = structure.getCell(2,1);
	footerContainer.id = "FooterContainerLayer";
	footerContainer.style.width = width - 20 +"px";
	
	var secondRight = structure.getCell(2,2);
	secondRight.id = "SecondRight";		
	secondRight.style.background = "url('" + img['box'] + "') repeat-y";
			
	var footer = document.createElement('div');
	footer.id = "FooterLayer";
	footerContainer.appendChild(footer);
				
	var btmLeft = structure.getCell(3,0);	
	btmLeft.id = "BtmLeft"; 		 		
	btmLeft.style.background = "url('" + img['corners'] + "') 0px -41px";
				
	var btm = structure.getCell(3,1);
	btm.style.width = width - 10 - 10 +"px";
	btm.style.height = "10px";
	btm.style.background = "url('" + img['box'] + "') repeat-x";
	
	var btmRight = structure.getCell(3,2);
	btmRight.id = "BtmRight";		
	btmRight.style.background = "url('" + img['corners'] + "') -11px -41px";
					
	var icon = new AnkhSprite(img['corners'],54,54,{x:52,y:0})
	icon.id = "Icon";
	container.appendChild(icon);
	
	var titleContainer = document.createElement('div');
	titleContainer.id = "TitleContainer";
	titleContainer.style.width = width - 40 - 10 - 7 +"px";	
	container.appendChild(titleContainer);
	
	var title = document.createElement('div');
	title.id = "Title";
	title.innerHTML = titleMsg;
	titleContainer.appendChild(title);
		
	if(confirmBtnText != ""){		
		var confirmBtn;
		if (confirmBtnType == "button") {
			confirmBtn = new AnkhButton("confirmBtn", confirmBtnText, true);
		}else{
			confirmBtn = new AnkhSmallSubmitButton("confirmBtn", confirmBtnText, true);
		}					
		footer.appendChild(confirmBtn);				
	}
	if(confirmBtnText != "" && cancelBtnText != ""){
		var or = document.createElement('span');
		or.style.marginLeft = "5px";
		or.style.marginRight = "5px";
		or.innerHTML = "or";
		footer.appendChild(or);
	}
	if(cancelBtnText != ""){
		var cancelBtn = new AnkhButton("cancelBtn",cancelBtnText,false);		
		footer.appendChild(cancelBtn);
	}
	if(okBtnTxt != "" && okBtnTxt != null){
		var okBtn = new AnkhButton("okBtn",okBtnTxt,true);
		okBtn.style.visibility = "hidden";		
		footer.appendChild(okBtn);
	}
	
	init = function(){		
		if(cancelBtn){
			EventUtil.addEventHandler(cancelBtn,"click",that.hide);
		}
		if(okBtn){
			EventUtil.addEventHandler(okBtn,"click",that.hide);
		}		
		that.hide();
	};
				
	/**
	 * Purpose - Return the Content Div to be used by different callers. New lines to be added using DIV only.
	 */
	this.getContent = function(){
		return content;
	};
			
	this.addBtn = function(id,btnTxt,confirmBtn){
		var newBtn = new AnkhButton(id, btnTxt, confirmBtn);
		footer.appendChild(newBtn);
		return newBtn;		
	};
	this.showBtns = function(){		
		for(var i =0;i<footer.childNodes.length;i++){			
			//footer.childNodes[i].style.display = "block";
			footer.childNodes[i].style.visibility = "visible";
		}
	};	
	this.hideBtns = function(){		
		for(var i =0;i<footer.childNodes.length;i++){			
			//footer.childNodes[i].style.display = "none";
			footer.childNodes[i].style.visibility = "hidden";
		}
	};	
	this.hide = function(){		
		container.style.visibility = "hidden";		
		container.style.display = "none";		
	};
	this.getConfirmBtn = function(){
		return confirmBtn;
	};
	this.getCancelBtn = function(){
		return cancelBtn;
	};
	this.getForm = function(){
		return form;
	};
	
	/**
	 * Purpose: Set the function to be activated upon action
	 * @param {Function} confirmBtnMouseup - function to be called upon activation
	 * @param {String} action - e.g. "submit", "mouseup", "mousedown", etc.
	 */
	this.setConfirmBtnMouseup = function(confirmBtnMouseup,action){
		if (action == "submit") {			
			EventUtil.addEventHandler(form, "submit", confirmBtnMouseup);
		}else{
			EventUtil.addEventHandler(confirmBtn, action, confirmBtnMouseup);
		}
	};
	
	this.removeConfirmBtnMouseup = function(confirmBtnMouseup,action){
		if (action == "submit") {			
			EventUtil.removeEventHandler(form, "submit", confirmBtnMouseup);
		}else{
			EventUtil.removeEventHandler(confirmBtn, action, confirmBtnMouseup);
		}
	}
	//Show methods must be called last after the content has been created
	this.showInCenterofBrowser = function(titleTxt){
		if(titleTxt){
			title.innerHTML = titleTxt;
		}		
		container.style.display = "block";		
		var location = AnkhUsefulMethods.getCentralisedLocation(container.clientHeight,container.clientWidth);
		container.style.left = location.X +"px";			
		container.style.top = location.Y +"px";
		if(iframe){
			iframe.style.height = container.clientHeight + "px";
		}	
		that.displayBtns(true);
		container.style.visibility = "visible";		
	};
	this.show = function(left,top,titleTxt){
		if(titleTxt){
			title.innerHTML = titleTxt;
		}		
		container.style.display = "block";				
		container.style.left = left +"px";			
		container.style.top = top +"px";
		if(iframe){
			iframe.style.height = container.clientHeight + "px";
		}	
		that.displayBtns(true);
		container.style.visibility = "visible";
	};
	this.showSecondPage = function(){
		that.displayBtns(false);
	};
	this.displayBtns = function(value){
		if(value){
			confirmBtn.style.visibility = "visible";
			if(cancelBtn){ cancelBtn.style.visibility = "visible"; }				
			if(or){ or.style.visibility = "visible"; }
		}else{			
			confirmBtn.style.visibility = "hidden";
			if(cancelBtn){ cancelBtn.style.visibility = "hidden"; }				
			if(or){ or.style.visibility = "hidden"; }
		}
		if(okBtn){
			if(value){
				okBtn.style.visibility = "hidden";
			}else{
				okBtn.style.visibility = "visible";
			}
		}
	};
	init();
};
WhitePopup = function(popupDir,width,height,hideOnMouseDownOutside,friendList,profileOwner,viewer){
	var img = {};
	if(isIE && !isMinIE7){
		img['corners'] = popupDir + "image/whitePopup.gif";
		img['horizontal'] = popupDir + "image/whitePopupBoxHorizontal.gif";
		img['vertical'] = popupDir + "image/whitePopupBoxVertical.gif";		
		img['center'] = popupDir + "image/whitePopupCenterBox.gif";
	}else{
		img['corners'] = popupDir + "image/whitePopup.png";
		img['horizontal'] = popupDir + "image/whitePopupBoxHorizontal.png";
		img['vertical'] = popupDir + "image/whitePopupBoxVertical.png";
		img['center'] = popupDir + "image/whitePopupCenterBox.png";
	}				
	var originalList = new Array();
	for(var i = 0;i < friendList.length;i++){
		originalList.push(friendList[i]);
	}
	var ankhDate = new AnkhDate();
	var that = this;
	var previousClickPrev;
	var previousClickNext;
	
	var remainingLength = width - (32*2);
	var defaultHeight = height - (32*2);
	
	var container = document.createElement('div');
	container.id = "WhitePopup";
	document.body.appendChild(container);
	 
	var structure = new GenericTable(3,3);	
	structure.Table.cellPadding = "0";
	structure.Table.cellSpacing = "0";
	structure.Table.style.width = width+"px";	
	structure.Table.style.height = height+"px";
	structure.Table.style.fontSize = "11px";
	container.appendChild(structure.Table);
	
	var topLeft = new AnkhSprite(img['corners'],32,32,{x:0,y:0});
	structure.insertIntoCell(0,0,topLeft);
					
	var top = structure.getCell(0,1);
	top.style.width = remainingLength+"px";
	top.style.height = "32px";
	top.style.background = "url('" + img['horizontal'] + "') repeat-x";
	
	var topRight = new AnkhSprite(img['corners'],32,32,{x:32,y:0});
	structure.insertIntoCell(0,2,topRight);

	var left = structure.getCell(1,0);
	left.style.width = "32px";
	left.style.height = defaultHeight+"px";
	left.style.background = "url('" + img['vertical'] + "') repeat-y";	
	
	var right = structure.getCell(1,2);
	right.style.width = "32px";
	right.style.height = defaultHeight+"px";
	right.style.background = "url('" + img['vertical'] + "') -33px 0px repeat-y";

	var btmLeft = new AnkhSprite(img['corners'],32,32,{x:0,y:32});
	structure.insertIntoCell(2,0,btmLeft);			

	var btm = structure.getCell(2,1);
	btm.style.width = remainingLength+"px";
	btm.style.height = "32px";
	btm.style.background = "url('" + img['horizontal'] + "') 0px -33px repeat-x";
		
	var btmRight = new AnkhSprite(img['corners'],32,32,{x:32,y:32});	
	structure.insertIntoCell(2,2,btmRight);		
	
	var content = structure.getCell(1,1);
	content.id = "Content";
	content.style.background = "url('" + img['center'] + "') repeat"; 
		
	var closeBtn = new AnkhSprite(img['corners'],16,17,{x:68,y:0},{x:85,y:0},{x:85,y:0});
	closeBtn.id = "CloseBtn";
	content.appendChild(closeBtn);
	
	var photoCount = document.createElement('div');
	photoCount.id = "PhotoCount";
	content.appendChild(photoCount);		
		
	var prevBtn = new AnkhSprite(img['corners'],46,17,{x:66,y:70},{x:66,y:53},{x:66,y:53});
	prevBtn.id = "PrevBtn";
	content.appendChild(prevBtn);
	
	var nextBtn = new AnkhSprite(img['corners'],43,17,{x:69,y:35},{x:69,y:18},{x:69,y:18});
	nextBtn.id = "NextBtn";
	content.appendChild(nextBtn);	
	
	var loadingIcon = new AnkhAJAXLoader("");
	loadingIcon.style.left = width / 2 +"px";
	loadingIcon.id = "LoadingIcon";
	content.appendChild(loadingIcon);
	
	var uploadedBy = document.createElement('div');
	uploadedBy.id = "UploadedBy";
	content.appendChild(uploadedBy);	
	
	var captionContainer = document.createElement('div');
	captionContainer.id = "CaptionContainer"
	content.appendChild(captionContainer);
	var caption = document.createElement('div');	
	captionContainer.appendChild(caption);
	var editCaption = new AnkhLink("");
	editCaption.id = "EditCaption";
	editCaption.style.cssFloat = "none";
	editCaption.style.styleFloat = "none";	
	editCaption.style.textAlign = "left";
	editCaption.style.fontSize = "10px";
	captionContainer.appendChild(editCaption);		
	
	var tagInstruction = document.createElement('div');
	tagInstruction.id = "TagInstruction";
	content.appendChild(tagInstruction);
		
	var photoContainer = document.createElement('div');
	photoContainer.id = "PhotoContainer";
	content.appendChild(photoContainer);
	
	var tagContainer = document.createElement('div');
	tagContainer.id = "TagContainer";
	content.appendChild(tagContainer);
	
	var picLinkContainer = document.createElement('div');
	picLinkContainer.id = "PicLinkContainer";
	content.appendChild(picLinkContainer);
	var instruction = document.createElement('div');
	instruction.innerHTML = "Share this photo by passing your friends this link.";
	picLinkContainer.appendChild(instruction);
	var urlLink = new AnkhInputAutoSelect("url","");
	urlLink.style.width = "400px";
	picLinkContainer.appendChild(urlLink);

	
	var photo = document.createElement('img');
	photo.id = "Photo";
	photoContainer.appendChild(photo);
	
	var tagger;
	var hidden;	
	var originalHeight;
	var smallHeight;
	var participantList;		//array of {friendId,displayNm,thumbnail,type}
	
	/**
	 * Purpose - Return the Content Div to be used by different callers. New lines to be added using DIV only.
	 */
	this.getContent = function(){
		return content;
	};
	
	init = function(){				
		var lengthObj = {length:167,minLength:67,maxLength:400};
		tagger = new Tagger(friendList,addTag,lengthObj);
		tagger.setFrontDataFunc(that.suggestParticipants);
		EventUtil.addEventHandler(closeBtn,"mousedown",function x(){
			that.hide() 	
			EventUtil.getEvent().stopPropagation();
		});

		EventUtil.addEventHandler(container,"mousedown",function x(){
			tagger.hide();
			EventUtil.getEvent().stopPropagation();});
		if(hideOnMouseDownOutside){
			EventUtil.addEventHandler(document.body,"mousedown",that.hide);
		}		
		keyDownPic = function(){		
			if(!hidden){
				var keyCode = EventUtil.getEvent().keyCode;
				switch(keyCode){
					case 37: previousClickPrev();
							break;
					case 39: previousClickNext();
							break;
					default: break;					
				}
			}	
		};		
		if(isMoz){
			EventUtil.addEventHandler(document,"keydown",keyDownPic);
		}else{
			EventUtil.addEventHandler(document.body,"keydown",keyDownPic);
		}
				
		EventUtil.addEventHandler(photo,"load",hideLoadingIcon);
		that.hide();	
	};
	
	this.setEventHandleNextNPrev = function(clickPrev,	clickNext){
		if (previousClickPrev != null) {
			EventUtil.removeEventHandler(prevBtn, "mouseup", previousClickPrev);
		}
		if (previousClickNext != null) {
			EventUtil.removeEventHandler(nextBtn, "mouseup", previousClickNext);
		}
		previousClickPrev = clickPrev;
		previousClickNext = clickNext;
		EventUtil.addEventHandler(prevBtn,"mouseup",clickPrev);		
		EventUtil.addEventHandler(nextBtn,"mouseup",clickNext);
	};
	
	this.show = function(picLink,x,y,showBtns,picOwner,currentPhoto,currentPhotoCount,totalPhotos,showEditCaption,eventId,ownerId){
							
		var dateUploaded = ankhDate.getMDY(ankhDate.mysqlTimeStampToDate(currentPhoto.lastUpdateDt)," ");
		var captionTxt = currentPhoto.caption;
		var tags = currentPhoto.tags;	
		
		hidden = false;
		originalHeight = currentPhoto.height_l;
		smallHeight = currentPhoto.height_m;
		container.style.visibility = "visible";
		loadingIcon.style.visibility = "visible";
		loadingIcon.style.display = "block";	
		resetPhoto();							
										
		photoCount.innerHTML = "Photo : <b>"+currentPhotoCount+"</b> of "+totalPhotos;
		caption.innerHTML = captionTxt;
		
		photo.src = picLink;		
		photo.tags = tags;
		photo.id = currentPhoto['picId'];				
		
		friendList = new Array();
		for(var i = 0;i < originalList.length;i++){
			friendList.push(originalList[i]); 
		}		
		that.suggestParticipants();		
		tagger.setDataSet(friendList);
		
		if(!showBtns){
			prevBtn.style.visibility = "hidden";
			nextBtn.style.visibility = "hidden";
		}
		container.style.display = "block";
		if(!x && !y){
			var location = AnkhUsefulMethods.getCentralisedLocation(container.clientHeight,container.clientWidth);		
			container.style.left = location.X +"px";			
			container.style.top = location.Y +"px";
		}else{
			container.style.left = x +"px";			
			container.style.top = y +"px";
		}
			
		if(profileOwner){
			urlLink.value = "http://www.mytimewall.com/Profile.php?id="+profileOwner['friendId'] +"&eventId="+eventId+"&picId="+currentPhoto['picId'];			
		}else{
			urlLink.value = "http://www.mytimewall.com/Profile.php?id="+viewer['friendId']+"&eventId="+eventId+"&picId="+currentPhoto['picId'];
		}		
		
				
		uploadedBy.innerHTML = "Uploaded by: "+picOwner+" on "+dateUploaded+".";
		editCaption.href = "EditEventPhotos.php?eId="+eventId+"&WhitePopup";
				
		if(showEditCaption){
			if(captionTxt != ""){
				editCaption.innerHTML = "Change Caption";
			}else{
				editCaption.innerHTML = "Add Caption";
			}
			that.enable();
		}else{
			editCaption.innerHTML = "";
			tagInstruction.innerHTML = "";
		}		
		updateInThisPhoto(photo);			
		
	};
	
	this.enable = function(){		
		if(isIE && !isMinIE7){
			photo.style.cursor = "pointer";
		}else{
			photo.style.cursor = "crosshair";
		}
		EventUtil.addEventHandler(photo,"mousedown",function(){
			if(EventUtil.getEvent().button != 2){							
				tagger.show(EventUtil.getEvent().pageX,EventUtil.getEvent().pageY,photo);
				EventUtil.getEvent().stopPropagation();	
			}																	
		});	
		tagInstruction.innerHTML = "Click on photo to tag your friends to this event.";	
	};
	
	this.setParticipantList = function(value){
		participantList = value;
	}
	this.suggestParticipants = function(){
		var frontFriends = new Array();
		var insertViewer = true;
		for(var i = 0;i < photo.tags.length;i++){		
			if(photo.tags[i]['id'] == viewer['friendId']){
				insertViewer = false;
				break;		
			}						
		}
		if(insertViewer){
			frontFriends.push(viewer);
			removeParticipantFromFriend(viewer['friendId']);
				
		}				
		var tags = photo.tags;
		if(profileOwner){		
			var insertMe = true;			
			for(var i = 0;i < tags.length;i++){		
				if(tags[i]['id'] == profileOwner['friendId']){
					insertMe = false;
					break;		
				}						
			}
			if(insertMe){
				frontFriends.push(profileOwner);
				
			}		
		}
		
		if(participantList){					
			for(var i = 0;i < participantList.length;i++){
				var insert = true;
				if(participantList[i]['friendId'] == viewer['friendId']){
					insert = false;
				}else{
					for(var j = 0;j < tags.length;j++){					
						if(participantList[i]['friendId'] == tags[j]['id']){
							insert = false;
							break;
						}
					}
				}
				if(insert){
					frontFriends.push(participantList[i]);				
					removeParticipantFromFriend(participantList[i]['friendId']);		
				}
			}
							
		}
				
		return frontFriends; 
	};	
	/**
	 * Purpose: Remove participant to friend list
	 * @param {Int} value - id
	 */
	removeParticipantFromFriend = function(value){
		for(var i = 0; i < friendList.length;i++){
			if(friendList[i]['friendId'] == value){	
				friendList.splice(i,1);		
				break;
			}
		}		
	
	};
	/**
	 * Purpose: Add participant to friend list
	 * @param {Int} value - id
	 */
	addParticipantToFriend = function(value){
		for(var i = 0; i < originalList.length;i++){
			if(originalList[i]['friendId'] == value){
				friendList.push(originalList[i]);
				break;
			}
		}		
	};
	
	/**
	 * Purpose: Add new participant to participantlist
	 * @param {Object} id
	 * @param {Object} name
	 */
	addParticipant = function(id,name){
		
		var removed = false;
		for(var i = 0; i < friendList.length;i++){
			if(friendList[i]['friendId'] == id){
				participantList.push(friendList[i]);
				friendList.splice(i,1);
				removed = true;				
				break;
			}
		}
		if(profileOwner){
			if(id == profileOwner['friendId']){
				removed = true;
			}
		}				
		if(id == viewer['friendId']){
			removed = true;
		}
		if(!removed){
			var insert = true;
			for(var i = 0;i < participantList.length;i++){				
				if(participantList[i]['friendId'] == id || participantList[i]['displayNm'] == name){
					insert = false;
					break;	
				}
			}
			if(insert){				
				participantList.push({friendId:name,displayNm:name,thumbnail:"Image/02_Display_Picture/female_default_pic_thumbnail.png",type:"friend"});
			}
		}
	};

	/**
	 * Purpose: This function indicates what happens when the tag has been added
	 * @param {Object} name
	 * @param {Object} id
	 * @param {Object} type
	 */
	addTag = function(name,id,type){
		var coordinates = tagger.getCoor();
		tagger.hide();		
		addParticipant(id,name);	
		var left = convertToSmallPhoto(coordinates.left);
		var top = convertToSmallPhoto(coordinates.top);
		var width = convertToSmallPhoto(coordinates.width);
		var height = convertToSmallPhoto(coordinates.height);
		
		photo.tags.push({name:name,id:id,left:left,top:top,width:width,height:height});			
		updateInThisPhoto();
		var participantId = id || name;		
		var url = "php/add_tag.php";
		var parameterObj = {photoId:photo.id,userId:participantId,left:left,top:top,width:width,height:height};						
		new AnkhAjax(url,"post",parameterObj);
		tagger.resetPos();		
	};
	
	removeTag = function(){
		var target = EventUtil.getEvent().target;
		var tag = target.nameObj.tag;
		var pic = target.nameObj.pic;
		AnkhUsefulMethods.removeAll(target.nameObj);
		AnkhUsefulMethods.removeAll(target);				
		for(var i = 0;i < pic.tags.length;i++){
			if(pic.tags[i] == tag){
				addParticipantToFriend(pic.tags[i]['id']);																		
				var participantId = pic.tags[i]['id'] || pic.tags[i]['name']; 
				pic.tags.splice(i,1);
				updateInThisPhoto();
				var url = "php/remove_tag.php";		
				var parameterObj = {photoId:photo.id,userId:participantId};			
				new AnkhAjax(url,"post",parameterObj);				
				break;
			}
		}
	};
	updateInThisPhoto = function(){
		AnkhUsefulMethods.removeAll(tagContainer);
		var tags = photo.tags;
		var parts = new Array();	
		parts[0] = "In this photo: ";
		if(tags.length == 0){
			parts[1] = "No one";	
		}				
		for(var i = 0;i < tags.length;i++){			
			var name = tags[i]['name'];			
			var index = name.indexOf("@");			
			if(index >= 1){
				name = name.substring(0,index);
			}
			var nameObj = new AnkhLink(name,null,null,null,true,{mouseover:"#3f74C3",mouseout:"#3f74C3"});
			nameObj.style.fontWeight = "normal";						
			nameObj.tag = tags[i];
			nameObj.pic = photo;
			EventUtil.addEventHandler(nameObj,"mousemove",displayTag);
			EventUtil.addEventHandler(nameObj,"mouseout",tagger.hide);
			parts.push(nameObj);
			
			var removeLink = new AnkhLink("remove",null,null,null,true,{mouseover:"#A8B6B9",mouseout:"#A8B6B9"});
			removeLink.style.fontWeight = "normal";
			removeLink.style.fontSize = "9px";
			removeLink.style.marginLeft = "2px";
			removeLink.nameObj = nameObj;
			EventUtil.addEventHandler(removeLink,"click",removeTag);
			parts.push(removeLink);						
			if(i <= tags.length - 2){
				parts.push(", ");
			}		
		}		
		tagContainer.appendChild(new AnkhDivBuilder(parts));
	};
	
	displayTag = function(){
		tagger.hide();
		var tag = EventUtil.getEvent().target.tag;		
		var left = convertToBigPhoto(tag.left);
		var top = convertToBigPhoto(tag.top);
		var width = convertToBigPhoto(tag.width);
		var height = convertToBigPhoto(tag.height);
		
		var pic = EventUtil.getEvent().target.pic;		
		tagger.showFromTopLeft(left + AnkhUsefulMethods.findPosX(pic),top + AnkhUsefulMethods.findPosY(pic),pic,width,height);
		
	};
	
	convertToBigPhoto = function(value){
		return Math.ceil(value * originalHeight /smallHeight);
	};
	convertToSmallPhoto = function(value){
		return Math.ceil(value / originalHeight *smallHeight);
	};
	
	this.hide = function(){
		tagger.hide();
		container.style.visibility = "hidden";
		container.style.display = "none";
		hidden = true;		
		resetPhoto();
	};
	
	resetPhoto = function(){		
		photoContainer.removeChild(photo);
		EventUtil.removeEventHandler(photo,"load",hideLoadingIcon);
		photo = document.createElement('img');
		photoContainer.appendChild(photo);	
		EventUtil.addEventHandler(photo,"load",hideLoadingIcon);			
	};
	
	hideLoadingIcon = function(){
		loadingIcon.style.visibility = "hidden";
		loadingIcon.style.display = "none";
	};
	init();
};
/**
 * Purpose: Create a rich text editor
 * @param {Function} saveHandler - save handler function to return a message
 * @param {String} directory - directory of texteditor from calling file. 
 * @param {Object} parent - parent object 
 * @param {Int} width 
 * @param {Int} height
 * @param {Boolean} drawCloseBtn - true/false -> draw/ don't draw closeBtn
 * @param {String} postName - name of the data when posted
 * @param {String} initialValue - initial value of the rich text editor  
 * @param {Boolean} keepFirstContent - true/false -> click to retain initial value/click to remove initial value 
 * @param {String} submitBtnTxt 
 * @param {Func} resizeHandler
 * @param {Object} label - {user:[],existing:[]}
 */
AnkhTextEditor = function(saveHandler,directory,parent,width,height,drawCloseBtn,postName,initialValue,keepFirstContent,submitBtnTxt,resizeHandler,label){
	var images = new Object();
	images['Close Btn'] = directory+"button/close button.jpg";
	images['Close Btn MO'] = directory+"button/close button mouseover.jpg";
	images['Bold Btn'] = directory+"button/bold.gif";
	images['Bold Btn MO'] = directory+"button/bold_on.gif";
	images['UnderLine Btn'] = directory+"button/underline.gif";
	images['UnderLine Btn MO'] = directory+"button/underline_on.gif";
	images['Italic Btn'] = directory+"button/italics.gif";
	images['Italic Btn MO'] = directory+"button/italics_on.gif";
	images['Color Palette'] = directory+"button/colorPalette button.gif";
	images['Font Color Panel'] = directory+"button/fontcolorpanel.png";
	images['Spacer'] = directory+"button/spacer.gif";
	
	for(var i in images){
		var img = new Image();
		img.src = images[i];
	}
	
	var invalidHTMLTags = {form: true, input: true, button: true, select: true,link: true,html: true, body: true, iframe: true,script: true,style: true,textarea: true};

	var colorArray = new Array("#000000","#CCCCCC","#4E81BD","#9BBB59","#8064A2","#C00000","#FF0000","#FEBD00","#FEFE00","#00B050","#00B0F0","#FF33CC");
	var colorRowNum = 6;
		
	var initialValue = initialValue;	
	
	var saveHandler = saveHandler; 
	var directory = directory;
	var width = width;
	var height = height;
	var that = this;
	var toolbarBtns = new Object();
	var isActivatedOnce = false;
	var container = document.createElement('div');
	container.className = "AnkhRichTextContainer";
	container.style.width = width  + "px";
	parent.appendChild(container);
	var iframe = document.createElement('iframe');
	iframe.className = "TextPad";
	iframe.frameBorder = "0";
	iframe.style.width = width + "px";
	iframe.style.height = height + "px";
	iframe.scrolling = "no";

	var colorsPanel;
	var hiddenMsg;
	if (!keepFirstContent) {
		hiddenMsg  = new  AnkhHiddenInput(postName, "");
	}else {
		hiddenMsg = new AnkhHiddenInput(postName, initialValue);
	}
	container.appendChild(hiddenMsg);
	
	var hiddenLabels = document.createElement('div');
	container.appendChild(hiddenLabels);

	if(label){
		var labelContainer = new GenericTable(2,2);
		labelContainer.Table.id = "LabelContainer";
		labelContainer.Table.style.width = width + 2+"px";
		labelContainer.getCell(0,0).style.width = "160px";
		labelContainer.getCell(0,1).style.verticalAlign = "bottom";
		labelContainer.getCell(1,0).colSpan = "2";
				
		var labelsHeader = document.createElement('div');
		labelsHeader.innerHTML = "<b>Labels:</b><br />E.g. Holiday, Stocks";
		labelContainer.insertIntoCell(0,0,labelsHeader);
		var labelBox = new AutoCompleteBox(labelContainer.getCell(0,1),label['user'],null,null,null,false,null,"","Press ENTER to add this label.",true,100,null,true,true);
		labelBox.setEmptyDisplayText("");					
	}
	
	var keepContent = keepFirstContent;
	
	init = function(){
									
		var buttons = createStdButtons();		
		toolbarBtns['colourSelecter'] = createColorsButton();
		for(var i in buttons){
			toolbarBtns[i] = buttons[i];
		}				
		toolbarBtns['fontSelecter'] = createFontSelecter();
						
		var toolBar = new GenericTable(1,5);		
		toolBar.Table.className = "Toolbar";
		var index = 0;
		for(var i in toolbarBtns){
			toolBar.insertIntoCell(0,index,toolbarBtns[i]);
			index ++;
		}
		if (saveHandler != null) {
			var submitBtn = createSubmitButton(submitBtnTxt);
		}
		if (drawCloseBtn) {
			var closeBtn = document.createElement('img');
			closeBtn.src = images['Close Btn'];
			closeBtn.className = "EditorCloseButton";
			EventUtil.addEventHandler(closeBtn, "mouseover", function x(){
				EventUtil.getEvent().target.src = images['Close Btn MO'];
			});
			EventUtil.addEventHandler(closeBtn, "mouseout", function x(){
				EventUtil.getEvent().target.src = images['Close Btn'];
			});
			EventUtil.addEventHandler(closeBtn, "click", function x(){
				that.setVisible(false);
			});	
			container.appendChild(closeBtn);
		}			
		container.appendChild(createColourPanel());
		container.appendChild(toolBar.Table);
		container.appendChild(iframe);
		if(label){
			container.appendChild(labelContainer.Table);
			labelBox.setOnConfirmed(addLabel);
			if(label['existing']){
				for(var i = 0;i < label['existing'].length;i++){
					addLabel(null,label['existing'][i]);
				}
			}
		}
		
		if (submitBtn != null) {
			container.appendChild(submitBtn);
		}		
	};
	/** 
	 * Purpose: Activate design mode of the iframe
	 */
	this.activateDesignMode = function(){
		this.setVisible(true);				//this is required for Firefox due to its bug
		if (!isActivatedOnce) {
			iframe.contentWindow.document.open();
			if (!keepContent) {
				iframe.contentWindow.document.write('<head><style type="text/css">body{ font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;  font-size:10pt; color:#C1CCB5;} .EditMode{ font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;  font-size:10pt; color:#000000;} </style> </head>');				
			}
			else {
				iframe.contentWindow.document.write('<head><style type="text/css">body{ font-family:Verdana, Geneva, Arial, Helvetica, sans-serif;  font-size:10pt; }</style> </head>');
			}
			if(initialValue){
				iframe.contentWindow.document.write(initialValue);
			}
			iframe.contentWindow.document.close();
			iframe.contenteditable = true;
			
			if (isMoz && !isMinMoz1_9) {
				EventUtil.addEventHandler(iframe.contentWindow.document, "focus", function x(){
					if (iframe.contentWindow.document.designMode != "on") {
						iframe.contentWindow.document.designMode = "on";
					}
				});
			}
			else {
				iframe.contentWindow.document.designMode = "on";
			}
			
			EventUtil.addEventHandler(iframe.contentWindow.document, "keydown", function(){
				if (isIE) {
					invertIELineBreakCapability(iframe, EventUtil.getEvent(iframe));
				}
				if (EventUtil.getEvent(iframe).ctrlKey) {
					var key = EventUtil.getEvent(iframe).keyCode;
					switch (key) {
						case 66:
							that.activateBtn(toolbarBtns['bold']);
							EventUtil.getEvent(iframe).preventDefault();
							break;
						case 73:						
							that.activateBtn(toolbarBtns['italic']);
							EventUtil.getEvent(iframe).preventDefault();
							break;
						case 85:
							that.activateBtn(toolbarBtns['underline']);
							EventUtil.getEvent(iframe).preventDefault();
							break;
						default:													
							break;
					}
				}
				that.resizeHeight();										
			});						
			var doc;
			if(!isMoz){
				doc = iframe.contentWindow;
			}else{
				doc = iframe.contentWindow.document;
			}				
			EventUtil.addEventHandler(doc, "focus", function x(){																										
				if (!keepContent) {						
					iframe.contentWindow.document.getElementsByTagName("body")[0].innerHTML = "";
					iframe.contentWindow.document.getElementsByTagName("body")[0].className = "EditMode";			
					var fontSelecter = toolbarBtns['fontSelecter'];
					that.iframeEdit('fontsize', fontSelecter[fontSelecter.selectedIndex].value);
					iframe.contentWindow.focus();						
					keepContent = true;						
				}
			});				
			EventUtil.addEventHandler(doc, "blur", function x(){					
				var txt = iframe.contentWindow.document.body.innerText || iframe.contentWindow.document.body.textContent;					
				if (!txt || AnkhUsefulMethods.trim(txt) == "") {				
					keepContent = false;
				}						
			});									
			EventUtil.addEventHandler(iframe.contentWindow.document, "keyup", that.checkCurrentStatus);
			EventUtil.addEventHandler(iframe.contentWindow.document, "click", that.checkCurrentStatus);
			EventUtil.addEventHandler(iframe.contentWindow.document, "keyup", that.setPostValue);	
			EventUtil.addEventHandler(iframe.contentWindow.document, "keyup", that.resizeHeight);
										
			isActivatedOnce = true;
			if(isIE){				//for a bug in IE
				iframe.contentWindow.focus();
			}
		}
		else {
			iframe.contentWindow.focus();
		}		
		EventUtil.addEventHandler(iframe,"load",function (){
			if(isIE && !isMinIE7){
				window.setTimeout(that.resizeHeight,100);		//needs more time to load finish for ie6
			}else{
				that.resizeHeight();
			}
			}
		);
	};
	
	addLabel = function(type,value,box){
		if(box){
			box.value = "";
		}				
		var isSelected = false;
		for(var i = 0;i < hiddenLabels.childNodes.length;i++){
			if(hiddenLabels.childNodes[i].value.toUpperCase() == value.toUpperCase()){
				isSelected = true;
				break;
			}			
		}
		if(!isSelected && AnkhUsefulMethods.trim(value) != ""){
			var newLabel = new AnkhHiddenInput("label[]",value);
			hiddenLabels.appendChild(newLabel);
			
			var area = labelContainer.getCell(1,0);				
			var labelSnipParts = new Array();				
			var closeBtn = new AnkhCloseButton();
			closeBtn.className = "closeButton";		
			labelSnipParts[0] = closeBtn;
			labelSnipParts[1] = value;
			var labelSnip = new AnkhDivBuilder(labelSnipParts);
			labelSnip.className = "labelSnip";
			area.appendChild(labelSnip);
			closeBtn.labelSnip = labelSnip;
			closeBtn.newLabel = newLabel;
			
			EventUtil.addEventHandler(closeBtn,"click",function(){
				EventUtil.getEvent().target.labelSnip.style.display = "none";
				hiddenLabels.removeChild(EventUtil.getEvent().target.newLabel);
				that.resizeHeight();
			});
			that.resizeHeight();
		}		
	};

	this.resizeHeight = function(){		
		var newHeight;								
		if(isIE){
			if(iframe.contentWindow.document.body){
				newHeight = iframe.contentWindow.document.body.scrollHeight + 50;
			}
		}else if(isChrome || isSafari){			
			newHeight = iframe.contentWindow.document.body.offsetHeight;		//Chrome still does not work properly with this implementation. Need to improve once Chrome solves this bug.
		}else{
			newHeight = iframe.contentWindow.document.body.offsetHeight + 50;	
		}						
		if(newHeight > height){		
			iframe.style.height = newHeight + "px";
			if(resizeHandler){
				resizeHandler(container.clientHeight);
			}
		}else{
			iframe.style.height = height + "px";
			if(resizeHandler){
				resizeHandler(container.clientHeight);
			}
		}
		
	};
	
	this.getLabels = function(){
		var temp = new Array();
		for(var i = 0;i < hiddenLabels.childNodes.length;i++){
			temp.push(hiddenLabels.childNodes[i].value);			
		}
		return temp;
	};
		
	 /**
        * @method cleanHTML
        * @param {String} html The unfiltered HTML
        * @description Process the HTML with a few regexes to clean it up and stabilize the output
        * @return {String} The filtered HTML
        */
    cleanHTML = function(html) {
		html = pre_filter_linebreaks(html);
		html = html.replace(/<img([^>]*)\/>/gi, '<img$1>');
		html = html.replace(/<img([^>]*)>/gi, '<img$1>');
		html = html.replace(/<input([^>]*)\/>/gi, '<input$1>');
		html = html.replace(/<input([^>]*)>/gi, '<input$1>');
		html = html.replace(/<ul([^>]*)>/gi, '<ul$1>');
		html = html.replace(/<\/ul>/gi, '<\/ul>');
		html = html.replace(/<blockquote([^>]*)>/gi, '<blockquote$1>');
		html = html.replace(/<\/blockquote>/gi, '<\/blockquote>');
		html = html.replace(/<embed([^>]*)>/gi, '<embed$1>');
		html = html.replace(/<\/embed>/gi, '<\/embed>');

		var startBold = '<span style="font-weight: bold;">';
		var endBold = '</span>';				
		html = html.replace(/<strong([^>]*)>/gi, startBold);
       	html = html.replace(/<\/strong>/gi, endBold);
		html = html.replace(/<b(\s+[^>]*)?>/gi, startBold);
        html = html.replace(/<\/b>/gi, endBold);
		
		var startItalic = '<span style="font-style: italic;">';
		var endItalic = '</span>';
		html = html.replace(/<em([^>]*)>/gi, startItalic);
       	html = html.replace(/<\/em>/gi, endItalic);
		html = html.replace(/<i(\s+[^>]*)?>/gi, startItalic);
        html = html.replace(/<\/i>/gi, endItalic);
		
		var startUnderline = '<span style="text-decoration: underline;">';
		var endUnderline = '</span>';				
		html = html.replace(/<strong([^>]*)>/gi, startBold);
       	html = html.replace(/<\/strong>/gi, endUnderline);
		html = html.replace(/<u(\s+[^>]*)?>/gi, startUnderline);
        html = html.replace(/<\/u>/gi, endUnderline);

        //normalize strikethrough
		html = html.replace(/<strike/gi, '<span style="text-decoration: line-through;"');
		html = html.replace(/\/strike>/gi, '/span>');
		if(isIE){
			var href = document.location.href;
            if (href.indexOf('?') !== -1) { //Remove the query string
                href = href.substring(0, href.indexOf('?'));
            }
            href = href.substring(0, href.lastIndexOf('/')) + '/';
			var url = href.replace(/\//gi, '\\/');
	        var re = new RegExp('src="' + url, 'gi');
	        html = html.replace(re, 'src="');
		}
		html = filter_all_rgb(html);
		html = filter_safari(html);
		html = filterMouseEvents(html);		
		html = filter_invalid_lists(html);
		
		//MUST filter rgb into hexidecimal format first
		html = html.replace(/(<[\w-:=\"' ]*)(javascript)*([^>]+)\)/gi,"$1");		// remove only javascript if it is within < >
		html = html.replace(/-moz-(\w[^>]*)-initial;/gi,'');
		html = html.replace(/_moz_dirty=""/gi, '');
		
		
       	html = html.replace(/&amp;/gi, '&');
		html = AnkhUsefulMethods.trim(html);
		html = html.replace(/\n/g, '').replace(/\r/g, '');
        html = html.replace(/ +/gi, ' '); //Replace all double spaces and replace with a single
		//First empty span
        if (html.substring(0, 6).toLowerCase() == '<span>')  {
			html = html.substring(6);
			//Last empty span
			if (html.substring(html.length - 7, html.length).toLowerCase() == '</span>')  {
 				html = html.substring(0, html.length - 7);
			}
		}
		return html;
   	};
	
	pre_filter_linebreaks = function(html) {
		var br = '<br>';
      
		html = html.replace(/<br class="khtml-block-placeholder">/gi, br);
		html = html.replace(/<br class="webkit-block-placeholder">/gi, br);
						
		html = html.replace(/<br>/gi, br);
		html = html.replace(/<br (.*?)>/gi, br);
		html = html.replace(/<br\/>/gi, br);
		html = html.replace(/<br \/>/gi, br);
		html = html.replace(/<div><br><\/div>/gi, br);
		html = html.replace(/<p>(&nbsp;|&#160;)<\/p>/g, br);            
		html = html.replace(/<p><br>&nbsp;<\/p>/gi, br);
		html = html.replace(/<p>&nbsp;<\/p>/gi, br);
		return html;
    };
	
	filter_safari = function(html) {
		if(isSafari || isChrome){
        	//<span class="Apple-tab-span" style="white-space:pre">	</span>
			html = html.replace(/<span class="Apple-tab-span" style="white-space:pre">([^>])<\/span>/gi, '&nbsp;&nbsp;&nbsp;&nbsp;');
            html = html.replace(/class=["]?Apple-style-span["]?/gi, '');
			html = html.replace(/-webkit-text-decorations-in-effect: underline;/gi,'');
			html = html.replace(/background-repeat: initial;/gi,'');
			html = html.replace(/background-attachment: initial;/gi,'');
			html = html.replace(/(<[\w:=\"\' ])*(-webkit-[\w-: ]*)(;)?/gi,'');
			html = html.replace(/background-color: initial;/gi,'');
			html = html.replace(/background-position: initial initial;/gi,'');
			  
            html = html.replace(/style="line-height: normal;"/gi, '');
            html = html.replace(/yui-wk-div/gi, '');
            html = html.replace(/yui-wk-p/gi, '');
            //Remove bogus LI's
            html = html.replace(/<li><\/li>/gi, '');
            html = html.replace(/<li> <\/li>/gi, '');
            html = html.replace(/<li>  <\/li>/gi, '');
		}
		return html;
	};
	

	filterMouseEvents = function(html){
		var eventList = new Array("onactivate","onbeforeactivate","onbeforecopy","onbeforecut","onbeforedeactivate","onbeforeeditfocus","onbeforepaste","onblur","onclick","oncontextmenu","oncontrolselect"
		,"oncopy","oncut","ondblclick","ondeactivate","ondrag","ondragend","ondragenter","ondragleave","ondragover","ondragstart","ondrop","onfocus","onfocusin","onfocusout","onhelp","onkeydown","onkeypress","onkeyup",
		"onlosecapture","onmousedown","onmouseenter","onmousemove","onmouseleave","onmouseout","onmouseover","onmouseout","onmousewheel","onmove","onmoveend","onmousestart","onpaste","onpropertychange","onreadystatechange",
		"onresize","onresizestart","onresizeend","onselectstart","ontimeerror");
		for(var i = 0;i < eventList.length;i++){
			//var exp = new RegExp('<(\w[^>]*) '+eventList[i]+'="([^\"]*)"([^>]*)', 'gi');
			//html = html.replace(exp, "[replace]");
		//	html = html.replace(/(<[\w-:=\"' ]*)(javascript)*([^>]+)\)/gi,"$1");		// remove only javascript if it is within < >
			
			var exp =  new RegExp(eventList[i],'gi');			//replace with single quote
			html = html.replace(exp, "\'"+eventList[i]+"\'");
					
		}
		return html;
	};
	
	filter_invalid_lists = function(html) {
		html = html.replace(/<\/li>\n/gi, '</li>');

		html = html.replace(/<\/li><ol>/gi, '</li><li><ol>');
		html = html.replace(/<\/ol>/gi, '</ol></li>');
		html = html.replace(/<\/ol><\/li>\n/gi, "</ol>");

		html = html.replace(/<\/li><ul>/gi, '</li><li><ul>');
		html = html.replace(/<\/ul>/gi, '</ul></li>');
		html = html.replace(/<\/ul><\/li>\n?/gi, "</ul>");

		html = html.replace(/<\/li>/gi, "</li>");
		html = html.replace(/<\/ol>/gi, "</ol>");
		html = html.replace(/<ol>/gi, "<ol>");
		html = html.replace(/<ul>/gi, "<ul>");
		return html;
	};
	/**
	* @method filter_all_rgb
	* @param String str The HTML string to filter
	* @description Converts all RGB color strings found in passed string to a hex color, example: style="color: rgb(0, 255, 0)" converts to style="color: #00ff00"
	* @return String
	*/
	filter_all_rgb = function(str) {
		var exp = new RegExp("rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)", "gi");
		var arr = str.match(exp);			
		if(arr){
			for (var i = 0; i < arr.length; i++) {
				var color = this.filter_rgb(arr[i]);
				str = str.replace(arr[i].toString(), color);
			}
		}            
		return str;
	};
	/**
	* @method filter_rgb
	* @param String css The CSS string containing rgb(#,#,#);
	* @description Converts an RGB color string to a hex color, example: rgb(0, 255, 0) converts to #00ff00
	* @return String
	*/
	filter_rgb = function(css) {
		if (css.toLowerCase().indexOf('rgb') != -1) {
			var exp = new RegExp("(.*?)rgb\\s*?\\(\\s*?([0-9]+).*?,\\s*?([0-9]+).*?,\\s*?([0-9]+).*?\\)(.*?)", "gi");
			var rgb = css.replace(exp, "$1,$2,$3,$4,$5").split(',');
            
			if (rgb.length == 5) {
				var r = parseInt(rgb[1], 10).toString(16);
				var g = parseInt(rgb[2], 10).toString(16);
				var b = parseInt(rgb[3], 10).toString(16);

				r = r.length == 1 ? '0' + r : r;
				g = g.length == 1 ? '0' + g : g;
				b = b.length == 1 ? '0' + b : b;

				css = "#" + r + g + b;
			}
		}
		return css;
	};
	
	filterInvalidHTML = function(html){		
		for (var x in invalidHTMLTags){             
			if (invalidHTMLTags[x]) {				
             	//html = html.replace(new RegExp('<' + x + '([^>]*)>(.*?)<\/' + x + '>', 'gi'), '');
				html = html.replace(new RegExp('<' + x +'([^>]*)>', 'gi'), '');
			} else {
                html = html.replace(new RegExp('<' + x + '([^>]*)>(.*?)<\/' + x + '>', 'gi'), '');
            }
		}  
		return html;
	};
	/**
	 * Purpose: Create font selecter
	 */
	createFontSelecter = function(){
		var fontSizes = new Array(	{Value:1,InnerHTML:"Tiny"},
									{Value:2,InnerHTML:"Small"},
									{Value:3,InnerHTML:"Medium"},
									{Value:4,InnerHTML:"Large"},
									{Value:5,InnerHTML:"Huge"}
									);
		var fontSelecter = new AnkhSelect(fontSizes,"fontSize",2);		
		fontSelecter.className = "FontSelecter";
		EventUtil.addEventHandler(fontSelecter,"change",function (){ 	
		that.iframeEdit('fontsize',fontSelecter[fontSelecter.selectedIndex].value); that.resizeHeight();});
		return fontSelecter;
	};
	
	/**
	 * Purpose: Used to create bold, italic, underline buttons
	 */
	createStdButtons = function(){
		var buttons = new Object();		
		var buttonsConfig = new Object();
		buttonsConfig['bold'] = {mouseOver:"Bold Btn MO",mouseOut:"Bold Btn",mouseUp:"Bold Btn MO"};
		buttonsConfig['underline'] = {mouseOver:"UnderLine Btn MO",mouseOut:"UnderLine Btn",mouseUp:"UnderLine Btn MO"};
		buttonsConfig['italic'] = {mouseOver:"Italic Btn MO",mouseOut:"Italic Btn",mouseUp:"Italic Btn MO"};
		for(var x in buttonsConfig){
			buttons[x] = createBtn(buttonsConfig[x],x);
		}
		return buttons;
	};
	
	/**
	 * Purpose: Create any button
	 * @param {Object} buttonObj - need to have mouseOut, mouseUp, mouseOver
	 * @param {String} editMode - iframe edit mode command
	 */
	createBtn = function(buttonObj,editMode){
		var btn = document.createElement('img');
		btn.src = images[buttonObj['mouseOut']];		
		btn.className = "buttons";
		btn.editMode = editMode;
		btn.selected = false;
		btn.mouseOverImg = images[buttonObj['mouseOver']];
		btn.mouseOutImg = images[buttonObj['mouseOut']];
		EventUtil.addEventHandler(btn,"mouseover",function x(){EventUtil.getEvent().target.src = images[buttonObj['mouseOver']];});
		EventUtil.addEventHandler(btn,"mouseout",function x(){
			if (!EventUtil.getEvent().target.selected) {
				EventUtil.getEvent().target.src = images[buttonObj['mouseOut']];
			}else{
				EventUtil.getEvent().target.src = images[buttonObj['mouseOver']];
			}
		});
		EventUtil.addEventHandler(btn,"click",function x(){
			that.activateBtn(EventUtil.getEvent().target);
		});
		return btn;
	};
	
	/**
	 * Purpose: To set the background when the button is pressed
	 * @param {Object} target - the button
	 */
	this.activateBtn = function(target){
		if (!target.selected) {
				target.style.backgroundColor = "#F4FAED";
				target.src = target.mouseOverImg;
				target.selected = true;				
			}else{
				target.style.backgroundColor = "";
				target.src = target.mouseOutImg;
				target.selected = false;	
			}
		if (target.editMode != null) {
			that.iframeEdit(target.editMode);
		}
	};
	
	/**
	 * Purpose: Create the colours button
	 */
	createColorsButton = function(){
		var colourBtnConfig = {mouseOver:"Color Palette",mouseOut:"Color Palette",mouseUp:"Color Palette"};
		var colourBtn = createBtn(colourBtnConfig);		
		colourBtn.style.padding = "2px";
		EventUtil.addEventHandler(colourBtn,"click",drawColourPanel); 
		return colourBtn;
	};

	drawColourPanel = function(){
		var left = EventUtil.getEvent().target.parentNode.offsetLeft + EventUtil.getEvent().target.offsetLeft + 2;		
		var top = EventUtil.getEvent().target.offsetTop + EventUtil.getEvent().target.offsetHeight + 5;
		if(!isChrome && !isSafari){
			colorsPanel.style.left = left + "px";
			colorsPanel.style.top = top + "px";
		}		
		colorsPanel.style.visibility = "visible";
		colorsPanel.style.display = "block";
	};
	
	/**
	 * Purpose: Draw the colour panel
	 */
	createColourPanel = function(){											
		colorsPanel = document.createElement('div');			
		colorsPanel.style.position = "absolute";						
		colorsPanel.style.backgroundImage = "url('"+ images['Font Color Panel']+"')";
		colorsPanel.style.width = 152 + "px";
		colorsPanel.style.height = 102 + "px";
							
		var colorCloseButton = document.createElement('img');		
		colorCloseButton.className = "closeBtn";
		colorCloseButton.src = images['Close Btn'];		
		colorsPanel.appendChild(colorCloseButton);
		
		EventUtil.addEventHandler(colorCloseButton,"mouseover",function x(){colorCloseButton.src = images['Close Btn MO'];});
		EventUtil.addEventHandler(colorCloseButton,"mouseout",function x(){colorCloseButton.src = images['Close Btn'];});
		EventUtil.addEventHandler(colorCloseButton,"click",function x(){					
			colorsPanel.style.visibility = "hidden";
			colorsPanel.style.display = "none";
		});
			
		var table = document.createElement('table');	
		table.cellpadding = 0;
		table.cellspacing = 2;
		table.className = "panelTbl";
		colorsPanel.appendChild(table);
		
		var tbody = document.createElement('tbody');	
		table.appendChild(tbody);
		var row;
		var rowIndex = 0;
		for(var i =0;i<colorArray.length;i++){
			if(rowIndex%colorRowNum == 0){
				row = document.createElement('tr');
				tbody.appendChild(row);
				rowIndex = 0;				
			}
			var cell = document.createElement('td');
			var cellimg = document.createElement('img');					
			cellimg.style.backgroundColor = colorArray[i];
			cellimg.src = images['Spacer'];			
			cellimg.className = "colorPaletteImg";
			cellimg.panel = colorsPanel;
			EventUtil.addEventHandler(cellimg,"click",that.addColor);
			EventUtil.addEventHandler(cellimg,"mouseover",function x(){EventUtil.getEvent().target.style.border = "1px solid #5E6F61";});
			EventUtil.addEventHandler(cellimg,"mouseout",function x(){EventUtil.getEvent().target.style.border = "1px solid #DDDFD1";});
			cell.appendChild(cellimg);
			row.appendChild(cell);
			rowIndex = rowIndex + 1;
		}
		colorsPanel.style.visibility = "hidden";
		colorsPanel.style.display = "none";		
		return colorsPanel;				
	};
	
	/**
	 * Purpose: Add colour to the font
	 */
	this.addColor = function(){
		var target = EventUtil.getEvent().target;	
		that.iframeEdit('ForeColor',target.style.backgroundColor);
		target.panel.style.visibility = "hidden";
		target.panel.style.display = "none";	
	};
	/**
	 * Purpose: Execute edit command on iframe
	 * @param {String} x - command
	 * @param {String} y - variable
	 */
	this.iframeEdit = function(x,y){
		iframe.contentWindow.focus();
		iframe.contentWindow.document.execCommand(x,false,y);
		that.setPostValue();				
	};
	
	/**
	 * Purpose: Set the hidden input post value
	 */
	this.setPostValue = function(){
		var txt = iframe.contentWindow.document.body.innerText || iframe.contentWindow.document.body.textContent;	
		if (txt != "") {
			var content = iframe.contentWindow.document.body.innerHTML;			
			hiddenMsg.value = content;
		}else{
			hiddenMsg.value = "";
		}
	};
	this.reset = function(){
		iframe.contentWindow.document.body.innerHTML = "";
		hiddenMsg.value = "";
	};
	/**
	 * Purpose: This function MUST be called before form is submitted to filter away some HTML formatting
	 */
	this.onSubmit = function(){		
		hiddenMsg.value = filterHTML(hiddenMsg.value);
	};
	
	/**
	 * Purpose: Filter HTML
	 * @param {String} message
	 */
	filterHTML = function(message){
		message = removeTrailingBr(message);
		message = filterMouseEvents(message);		
		message = filterInvalidHTML(message);
		message = replaceWhiteSpace(message);
		message = AnkhUsefulMethods.trim(message);
		return message;		
	};
	
	/**
	 * Purpose: Remove trailing item
	 * @param {String} message
	 * @param {String} item
	 */
	removeTrailingBr = function(message,item){		
		var brRegex = /<BR>$|<br>$|<P>$|<\/P>$/;
		while (message.search(brRegex) != -1) {			
			message = message.replace(brRegex, "");
		}
		return message;
	};
	
	replaceWhiteSpace = function(message){
		message = message.replace(/&nbsp;/gi," ");
		return message;
	};
	
	/**
	 * Purpose: Check the current highlighted state of the text within the iframe
	 */
	this.checkCurrentStatus = function(){		
		if (container.style.visibility == "visible") {
			
			var boldState = iframe.contentWindow.document.queryCommandState('bold');
			var italicState = iframe.contentWindow.document.queryCommandState('italic');
			var underlineState = iframe.contentWindow.document.queryCommandState('underline');
			var fontSizeState = iframe.contentWindow.document.queryCommandValue('fontsize');
			
			for (var i = 0; i < toolbarBtns['fontSelecter'].childNodes.length; i++) {
				
				if (toolbarBtns['fontSelecter'].childNodes[i].value == fontSizeState) {
					
					toolbarBtns['fontSelecter'].childNodes[i].selected = true;
				}
				
			}
			if (boldState) {
				toolbarBtns['bold'].src = images['Bold Btn MO'];
				toolbarBtns['bold'].style.backgroundColor = "#F4FAED";
			}
			else {
				toolbarBtns['bold'].src = images['Bold Btn'];
				toolbarBtns['bold'].style.backgroundColor = "";
			}
			if (italicState) {
				toolbarBtns['italic'].src = images['Italic Btn MO'];
				toolbarBtns['italic'].style.backgroundColor = "#F4FAED";
			}
			else {
				toolbarBtns['italic'].src = images['Italic Btn'];
				toolbarBtns['italic'].style.backgroundColor = "";
			}
			if (underlineState) {
				toolbarBtns['underline'].src = images['UnderLine Btn MO'];
				toolbarBtns['underline'].style.backgroundColor = "#F4FAED";
			}
			else {
				toolbarBtns['underline'].src = images['UnderLine Btn'];
				toolbarBtns['underline'].style.backgroundColor = "";
			}					
		}		
	};
	
	
	/**
	 * Purpose: Create submit button
	 */
	createSubmitButton = function(submitBtnTxt){
		var submitBtnContainer = document.createElement('div');
		submitBtnContainer.style.marginTop = "10px";
		var submitButton = document.createElement('input');
		submitButton.type = "button";
		var submitTxt = submitBtnTxt || "Save";
		submitButton.value = submitTxt;
		submitButton.className = "btn";
		submitBtnContainer.appendChild(submitButton);
		
		EventUtil.addEventHandler(submitButton,"mouseover",function x(){submitButton.style.backgroundColor = '#3f74c3'; submitButton.style.color = '#FFFFFF';});
		EventUtil.addEventHandler(submitButton,"mouseout",function x(){			
			submitButton.style.backgroundColor = ''; submitButton.style.color = '';});
		EventUtil.addEventHandler(submitButton,"click",saveToDB);
		return submitBtnContainer;
	};
	
	/**
	 * Purpose: Set rich text editor visiblity
	 * @param {Boolean} visible
	 */
	this.setVisible = function(visible){		
		if(visible){
			container.style.visibility = "visible";
			container.style.display = "block";
		}else{
			container.style.visibility = "hidden";
			container.style.display = "none";
		}
	};	
	
	
	/**
	 * Purpose; Return the inner HTML of iframe
	 */
	this.getValue = function(){
		return iframe.contentWindow.document.body.innerHTML;
	};
	
	this.getFilteredValue = function(){
		var message = iframe.contentWindow.document.body.innerHTML;
		message = filterHTML(message);
		return message;
	};
	/**
	 * Purpose: Return container
	 */
	this.getContainer = function(){
		return container;
	};
		
	/**
	 * Purpose: Call the savehandler to return the message 
	 */
	saveToDB = function(){
		
		var message = iframe.contentWindow.document.body.innerHTML;
		message = filterHTML(message);
		if (saveHandler != null) {
			saveHandler(message);
		} 
		
	};
	
	/**
	 * Purpose: Format <p> in IE to <br>
	 * @param {Object} iframe
	 * @param {Object} e
	 */
	invertIELineBreakCapability = function(iframe,e){		
		var editor = iframe.contentwindow;
		var sel;
		// validate if the press key is the carriage return key
		if (e.keyCode==13) {
			if (!e.shiftKey) {
				sel = getRange(getSelection(iframe));
				sel.pasteHTML("<br>");
			}
			else {
				sel = getRange(getSelection(iframe));
				sel.pasteHTML("<p>");
				}
			e.cancelBubble = true;
			e.returnValue = false;
			sel.select();
			sel.moveEnd("character", 1);
			sel.moveStart("character", 1);
			sel.collapse(false);
			
			return false;
		}  
	};
	
	getSelection = function(iframe) {
		var ifrm = iframe.contentWindow;
		var doc = iframe.contentWindow.document;
		var sel = null;
		if(ifrm.getSelection){
			sel = ifrm.getSelection();
		}
		else if (doc.getSelection) {
			sel = doc.getSelection();
		}
		else if (doc.selection) {
			sel = doc.selection;
		}
		return sel;
	};
	getRange = function(sel) {
		if(sel.createRange){
			return sel.createRange();	
		}
		return sel.getRangeAt(0);
	}		
	
	init();
};
AnkhAjax = function(ajaxUrl,method,parameterObj,onSuccessFunc,ajaxLoadingImg){	
	parameterObj['differentiator'] = Math.floor(Math.random()*50000);	
	tryagain = function(){
		new Ajax.Request(ajaxUrl, {method:method,parameters:parameterObj,onSuccess: onSuccessFunc,
			onFailure: function(){
				if(ajaxLoadingImg){
					ajaxLoadingImg.style.visibility = "hidden";
					ajaxLoadingImg.style.display = "none";
				}
				alert("Opps... it seems that your internet connection is down. Please try again when it is back.");			
			}});
	};
	if(method.toLowerCase() == "post"){	
		tryagain();
	}else{
		new Ajax.Request(ajaxUrl, {method:method,parameters:parameterObj,onSuccess: onSuccessFunc,onFailure: function(){window.setTimeout(tryagain,2000);}});		
	}
};
/**
 * myTimeWall's Date object class - to simplify date manipulation
 */
AnkhDate = function(){
	var months = new Array("Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec");		
	var weekday = new Array("Sun","Mon","Tue","Wed","Thu","Fri","Sat");		
	var that = this;	
	/**
	 * Purpose: Subtract days based on Javascript in-built date object
	 * @param {Object} date - current date
	 * @param {Object} days - number of days to be subtracted
	 */
	this.subtractDays = function(date,days){		
		var t = new Date(date);
		var a = t.setDate(t.getDate()-days);
		newDate = new Date(a);	
		return newDate;
	};
	/**
	 * Purpose: Add days based on Javascript in-built date object
	 * @param {Object} date - current date
	 * @param {Object} days - number of days to be added
	 */
	this.addDays = function(date,days){				
		var t = new Date(date);
		var a = t.setDate(t.getDate()+days);
		newDate = new Date(a);
		return newDate;	
	};
	/**
	 * Purpose: Add days in a particular format
	 * @param {Object} date - original date to be added
	 * @param {Object} days - number of days to be added
	 * @param {Object} dayType - year/month/day
	 */
	this.addDaysFormat = function(date,days,dayType){
		var newDate;

		if(days < 1){
			if(dayType == "year"){
				dayType = "month";	
				days = 12 * days;
			}else if(dayType=="month"){								
				dayType = "day";
				if(days == 0.5){
					if (date.getDate()==1) {
						days = 15;							
					}
					else{
						days = this.daysInAMonth(date.getMonth()+1,date.getFullYear()) - 15;		
					}
				}else if(days == 0.25){
					if (date.getDate() <= 15) {		//if current date = 1st of the month, then the number of days to decrease is NumOfDaysInPreviousMonth - Days. E.g. now is 1st Apr, then days = 31 - 21 => 10. 
						days = 7;			
					}else{						
						days = this.daysInAMonth(date.getMonth()+1,date.getFullYear()) - 21;
					}
				}								
			}
		}
		if(dayType == "year"){
			newDate = new Date(date.getFullYear() + days,date.getMonth(),date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds(),date.getMilliseconds());
		}
		else if(dayType == "month"){
			var month = date.getMonth()+days;
			if(month < 0){
				month = month + 12;
				newDate = new Date(date.getFullYear() + 1, month, date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds(), date.getMilliseconds());
			}
			else{				
				newDate = new Date(date.getFullYear(),month,date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds(),date.getMilliseconds());
			}
		}
		else{
			newDate = this.addDays(date,days);
		}
		
		return newDate;
	};
	/**
	 * Purpose: Subtract days in a particular format
	 * @param {Object} date - original date to be subtracted
	 * @param {Object} days - number of days to be subtracted
	 * @param {Object} dayType - year/month/day
	 */
	this.subtractDaysFormat = function(date,days,dayType){
		var newDate;
		if(days < 1){
			if(dayType == "year"){
				dayType = "month";	
				days = 12 * days;
			}
			else if(dayType=="month"){				
				dayType = "day";
				if(days == 0.5){
					if (date.getDate()==1) {		//if current date = 1st of the month, then the number of days to decrease is NumOfDaysInPreviousMonth - Days. E.g. now is 1st Apr, then days = 31 - 15 => 16. 
						days = this.daysInAMonth(date.getMonth(),date.getFullYear()) - 15;			
					}else{
						days = 15;
					}
				}else if(days == 0.25){
					if (date.getDate()== 1) {		//if current date = 1st of the month, then the number of days to decrease is NumOfDaysInPreviousMonth - Days. E.g. now is 1st Apr, then days = 31 - 21 => 10. 
						days = this.daysInAMonth(date.getMonth(),date.getFullYear()) - 21;			
					}else{
						days = 7;
					}					
				}
			}
		}
		if(dayType == "year"){
			newDate = new Date(date.getFullYear() - days,date.getMonth(),date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds(),date.getMilliseconds());
		}
		else if(dayType == "month"){
			var month = date.getMonth()-days;
			if(month < 0){			
				month = month + 12;				
				newDate = new Date(date.getFullYear() - 1,month,date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds(),date.getMilliseconds());
			}
			else{			
				newDate = new Date(date.getFullYear(),month,date.getDate(),date.getHours(),date.getMinutes(),date.getSeconds(),date.getMilliseconds());				
			}			
		}
		else{
			newDate = this.subtractDays(date,days);	
		}				
		return newDate;
	};
	/**
	 * Purpose: Used to subtract many days 
	 * @param {Int} iteration - number of iteration to subtract days
	 * @param {DateTime} date - the date to be subtracted
	 * @param {Int} days - number of days to subtract at each iteration
	 * @param {String} dayType - year/month/day
	 */
	this.subtractManyDays = function(iteration,date,days,dayType){
		var temp = date;
		for(var i=0;i<iteration;i++){
			temp = this.subtractDaysFormat(temp,days,dayType);
		}
		return temp;
	};

	/**
	 * Purpose: method used to compute the number of divs between firstStartDate and secondStartDate. 
	 * @param {DateTime} firstStartDate 
	 * @param {DateTime} secondStartDate
	 * @param {String} granularityType - year, month,day
	 * @param {Decimal} granularity - number of granularityType.
	 */
	this.divNumBetweenDates = function(firstStartDate,secondStartDate,granularityType,granularity){
		if(granularityType == "year"){
			var startYear = firstStartDate.getFullYear();
			var endYear = secondStartDate.getFullYear();
			var temp = (endYear - startYear) / granularity;
			if(secondStartDate.getMonth() - firstStartDate.getMonth() > 0){
				temp += 1;
			}else if(secondStartDate.getMonth() - firstStartDate.getMonth() < 0){
				temp -= 1;
			}
			return temp;
		}
		if (granularityType == "month") {
			var startYear = firstStartDate.getFullYear();
			var endYear = secondStartDate.getFullYear();
			var startMonth = firstStartDate.getMonth();
			var endMonth = secondStartDate.getMonth();			
			var temp = ((endYear - startYear) * 12 + (endMonth - startMonth)) / granularity;				
			if(granularity != 0.25){	
				if( secondStartDate.getDate() - firstStartDate.getDate() > 0){
					temp += 1;
				}else if( secondStartDate.getDate() - firstStartDate.getDate() < 0){
					temp -= 1;
				}
			}else{				
				temp += (secondStartDate.getDate() - firstStartDate.getDate()) / 7;				
			}
			return temp;		
		}
		if (granularityType == "day") {
			return (secondStartDate - firstStartDate)/86400000 	/ granularity;				// 60*60*24*1000
		}
	};
	/**
	 * Purpose: Return the number of days in a year
	 * @param {Int} year
	 */
	this.daysInAYear = function(year){
		if(year%4 == 0 && year %100 != 0 || year %400 ==0)			//leap year
		{
			return 366;
		}
		return 356;
	};
	/**
	 * Purpose: Return the number of days in a month
	 * @param {Int} month - 1 - 12
	 * @param {Int} year
	 */
	this.daysInAMonth = function(month,year){
		var dd = new Date(year, month, 0);		
		return dd.getDate();
	}	
	/**
	 * Purpose: Round date down to the first day of granularity
	 * @param {DateTime} date - JS date
	 * @param {String} level - Year/Month/Day
	 * @param {Int} days - granularity days
	 */
	this.roundDownToFirstDay = function(date,level,days){
		var newDate;
		if(level == "year"){
			if (days == 0.5 && date.getMonth() >= 6) {
				newDate = new Date(date.getFullYear(), 6, 1, 0, 0, 0);
			}else{
				newDate = new Date(date.getFullYear(), 0, 1, 0, 0, 0);
			}
		}
		else if(level == "month"){
			if(days == 0.25){				
				if(date.getDate() >= 8 && date.getDate() < 15){
					newDate = new Date(date.getFullYear(), date.getMonth(), 8, 0, 0, 0);	
				}else if(date.getDate() >= 15 && date.getDate() < 22){
					newDate = new Date(date.getFullYear(), date.getMonth(), 15, 0, 0, 0);
				}else if(date.getDate() >= 22){
					newDate = new Date(date.getFullYear(), date.getMonth(), 22, 0, 0, 0);
				}else{
					newDate = new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0);
				}
			}else if(days == 0.5 && date.getDate() >= 16){				
				newDate = new Date(date.getFullYear(), date.getMonth(), 16, 0, 0, 0);			
			}else{				
				newDate = new Date(date.getFullYear(), date.getMonth(), 1, 0, 0, 0);				
			}		
		}
		else if(level == "day"){
			newDate = new Date(date.getFullYear(),date.getMonth(),date.getDate(),0,0,0);
		}
		return newDate;
	};
	/**
	 * Purpose: Round date up to the first day of granularity
	 * @param {DateTime} date - JS date
	 * @param {String} level - Year/Month/Day
	 * @param {Int} days - granularity days
	 */
	this.roundUpToFirstDay = function(date,level,days){
		var newDate;
		if(level == "year"){
			if (days == 0.5 && date.getMonth() >= 6) {
				newDate = new Date(date.getFullYear()+1, 0, 1, 0, 0, 0);
			}else{
				newDate = new Date(date.getFullYear(), 6, 1, 0, 0, 0);
			}
		}
		else if(level == "month"){
			if(days == 0.25){
				if(date.getDate() < 8){
					newDate = new Date(date.getFullYear(),date.getMonth(),8,0,0,0);
				}else if(date.getDate() < 15){
					newDate = new Date(date.getFullYear(),date.getMonth(),15,0,0,0);
				}else if(date.getDate() < 22){
					newDate = new Date(date.getFullYear(),date.getMonth(),22,0,0,0);
				}else{
					newDate = new Date(date.getFullYear(),date.getMonth()+1,1,0,0,0);
				}
			}
			else if(days == 0.5 && date.getDate() < 16){
				newDate = new Date(date.getFullYear(),date.getMonth(),16,0,0,0);
			}else{		
				newDate = new Date(date.getFullYear(),date.getMonth()+1,1,0,0,0);		
			}			
		}
		else if(level == "day"){
			newDate = new Date(date.getFullYear(),date.getMonth(),date.getDate()+1,0,0,0);
		}		
		return newDate;
	};
	/**
	 * Purpose: Return date based on granularity. 
	 * If granularity = year, return e.g. grid:2003
	 * If granularity = month, return e.g. grid:Jan, major: 2003
	 * If granularity = day, return e.g. grid:12, major:Jan 03
	 * @param {Object} minorGranularity - year/month/day
	 * @param {Object} date
	 */
	this.parseDate = function(minorGranularity,date)	{		
		if(minorGranularity == "year"){
			return {"grid":date.getFullYear()};
		}			
		else if(minorGranularity == "month"){
			return {"grid":months[date.getMonth()],"major":date.getFullYear()};
		}
		else if(minorGranularity == "day"){
			var yearStr = date.getYear().toString();
			var shortYear = yearStr.slice(yearStr.length-2,yearStr.length);
			var major = months[date.getMonth()]+" '"+shortYear;
			return {"grid":date.getDate(),"major":major};
		}
	};
	
	/**
	 * Purpose: Return the translated month given the month index
	 * @param {Int} month - index of the month, starting from 0 - Jan
	 */
	this.getTranslatedMonth = function(month){
		return months[month];	
	};
	
	/**
	 * Purpose: Return the given javascript date in MYSQL type
	 * @param {Object} tempDate - JS input date
	 */
	this.formatMYSQLDate = function(tempDate) {
		return tempDate.getFullYear() + '-' + (tempDate.getMonth() < 9 ? '0' : '') + (tempDate.getMonth()+1) + '-' + (tempDate.getDate() < 10 ? '0' : '') + tempDate.getDate();
	}
	/**
	 * Purpose - Parse mysql datetime string and returns javascript Date object. E.g of MYSQL datetime - 2007-06-05 15:26:02
	 * @param {Object} mysqlDateInput - MYSQL input
	 */
	this.mysqlTimeStampToDate = function(mysqlDateInput) {			
		if (mysqlDateInput != null) {
			if(mysqlDateInput.split(' ').length > 1){		
				var regex = /^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9]) (?:([0-2][0-9]):([0-5][0-9]):([0-5][0-9]))?$/;
		   	 	var parts=mysqlDateInput.replace(regex,"$1 $2 $3 $4 $5 $6").split(' ');
				return new Date(parts[0], parts[1] - 1, parts[2], parts[3], parts[4],parts[5]);
			}else{												
				var regex = /^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9])?$/;
		   	 	var parts=mysqlDateInput.replace(regex,"$1 $2 $3 $4 $5 $6").split(' ');
				return new Date(parts[0], parts[1] - 1, parts[2]);
			}
		}else{
			return "";
		}
	};
	
	this.getDMY = function(date,delimiter){
		if(date == null || date == ""){
			return "";
		}
		return date.getDate()+delimiter+months[date.getMonth()]+delimiter+date.getFullYear();
	};
	/**
	 * Purpose:Special function for converting MYSQL datetime to DOB display
	 * @param {String} mysqlDateInput
	 * @param {String} delimiter
	 */
	this.getDOBDMY = function(mysqlDateInput,delimiter){
		if (mysqlDateInput != null) {											
			var parts= mysqlDateInput.split("-");							
			var temp = new Date(parts[0], parts[1] - 1, parts[2]);
			if(mysqlDateInput.indexOf("0000") == 0){	
				return months[temp.getMonth()]+delimiter+temp.getDate();
			}else{
				return temp.getDate()+delimiter+months[temp.getMonth()]+delimiter+temp.getFullYear();
			}							
		}
		return "";		
	}
	this.getMDY = function(date,delimiter){
		if(date == null || date == ""){
			return "";
		}
		return months[date.getMonth()]+delimiter+date.getDate()+delimiter+date.getFullYear();
	};
	this.getMY = function(date,delimiter){
		if(date == null || date == ""){
			return "";
		}
		return months[date.getMonth()]+delimiter+date.getFullYear();
	}
	
	this.getDayDateMth = function(date,delimiter){
		if(date == null || date == ""){
			return "";
		}
		return weekday[date.getDay()]+delimiter+date.getDate()+delimiter+months[date.getMonth()]+delimiter+date.getFullYear();	
	};
	this.getTime = function(date,delimiter){
		if(date == null || date == ""){
			return "";
		}
		var txt;
		var hours =date.getHours();
		if(hours > 12){
			txt = "pm";
			hours -= 12;
		}else{
			txt = "am";
		}
		var mins = date.getMinutes();
		if (mins < 10) {
		  	mins="0" + mins;
		 }
		return hours+":"+mins+txt;
	}
	
	this.getMonths = function(){
		return months;
	};
	
	secsDiff = function(start,end){
		var startTimeStamp = start.getTime();
		var endTimeStamp = end.getTime();	
		var days = (endTimeStamp - startTimeStamp )/1000;		// 1000ms
		return days;
	};	
	/**
	 * Purpose: Compare input date with today's date. If input date is more than 1 month, display e.g. Nov 08.
	 * @param {DateTime} inputDate
	 * @param {DateTime} todayDate
	 */
	this.compareWithToday = function(inputDate,todayDate){		
		var secsdiff = secsDiff(inputDate,todayDate);
		if(secsdiff < 60){
			return "seconds ago";
		}else{
			var minDiff = secsdiff / 60;
			if(minDiff < 60){
				if (parseInt(minDiff,10) == 1) {
					return parseInt(minDiff, 10) + " minute ago";
				}
				else {									
					return parseInt(minDiff, 10) + " minutes ago";
				}
			}
			else{
				var hourDiff = parseInt(minDiff/60,10);
				if(hourDiff < 24){
					if(hourDiff == 1){
						return hourDiff + " hour ago";
					}else{							
						return hourDiff + " hours ago";						
					}
				}else{
					var dayDiff = parseInt(hourDiff/24,10);
					if (dayDiff < 7) {
						if(dayDiff == 1){
							return dayDiff + " day ago";
						}else{
							return dayDiff + " days ago";
						}							
					}
					else if (dayDiff >= 7 && dayDiff < 14) {
						return "more than a week ago";
					}
					else if (dayDiff >= 14 && dayDiff < 21) {
						return "more than 2 weeks ago";
					}
					else if (dayDiff >= 21 && dayDiff <= 30){
						return "less than 1 month ago";
					}
					else{				//more than 1 month
						return 	this.getMY(inputDate," ")
					}						
				}
			}
		}
		return diff;
	};
};


AnkhDrag = function(dragObj,onlyMoveVertical,onlyMoveHorizontal,dragStartHandler,preMoveXHandler,preMoveYHandler,postMoveXHandler,postMoveYHandler,dragEndXHandler,dragEndYHandler){
	var dragObj = dragObj;
	if (!isIE || isMinIE7) {
		dragObj.style.cursor = "url('TimeWallv7/wallimage/cursor-openhand.cur'),auto";
	}	
						
	var moving = false;
	var that = this;
	
	var coordFrmLeftCorner = {};
	var dragStartHandler = dragStartHandler;
	var preMoveXHandler = preMoveXHandler;
	var preMoveYHandler = preMoveYHandler;
	var postMoveHandler = postMoveHandler;
	var dragEndHandler = dragEndHandler;
	var onlyMoveVertical = onlyMoveVertical;
	var onlyMoveHorizontal = onlyMoveHorizontal;
	
	var parentNode;
	var prevX;
	var prevY;
	
	
	init = function(){
		EventUtil.addEventHandler(dragObj, "mousedown", that.dragStart);
		EventUtil.addEventHandler(document.body, "mouseup", that.dragEnd);
		EventUtil.addEventHandler(document.body, "mousemove", that.dragMoving);
		
	};
	
	this.dragStart = function(){
		that.dragEnd();		
		if (!isIE || isMinIE7) {
			dragObj.style.cursor = "url('TimeWallv7/wallimage/cursor-closedhand.cur'),auto";
		}else{
			dragObj.style.cursor = "default";
		}
		var dragObjLeft = AnkhUsefulMethods.findPosX(dragObj);
		var dragObjTop = AnkhUsefulMethods.findPosY(dragObj);		
		coordFrmLeftCorner.x = EventUtil.getEvent().pageX - dragObjLeft ;
		coordFrmLeftCorner.y = EventUtil.getEvent().pageY - dragObjTop ;		
		
		prevX = dragObjLeft;
		prevY = dragObjTop;
		dragObj.style.position = "absolute";
		dragObj.style.zIndex = "10";		
		dragObj.style.top = dragObjTop +"px";
		dragObj.style.left = dragObjLeft +"px";
		parentNode = dragObj.parentNode;
		dragObj.parentNode.removeChild(dragObj);
		document.body.appendChild(dragObj);
		moving = true;
		EventUtil.getEvent().preventDefault();
		if(dragStartHandler!= null){
			dragStartHandler(EventUtil.getEvent());
		}
	};
	this.dragMoving = function(){		
		if(moving){					
			var currentX = EventUtil.getEvent().pageX - coordFrmLeftCorner.x;
			var currentY = EventUtil.getEvent().pageY - coordFrmLeftCorner.y;
			if (!onlyMoveVertical) {
				if (preMoveXHandler == null || preMoveXHandler(EventUtil.getEvent(), currentX, prevX)) {
					dragObj.style.left = currentX + "px";
				}
			}
			if (!onlyMoveHorizontal) {
				if (preMoveYHandler == null || preMoveYHandler(EventUtil.getEvent(), currentY, prevY)) {
					dragObj.style.top = currentY + "px";
				}
			}								
			if(postMoveXHandler != null){
				postMoveXHandler(EventUtil.getEvent(),currentX);
			}
			if(postMoveYHandler != null){
				postMoveYHandler(EventUtil.getEvent(),currentY);
			}
			prevX = currentX;
			prevY = currentY;
			if (!isIE || isMinIE7) {
			dragObj.style.cursor = "url('TimeWallv7/wallimage/cursor-closedhand.cur'),auto";
			}else{
				dragObj.style.cursor = "default";
			}
			EventUtil.getEvent().preventDefault();
			EventUtil.getEvent().stopPropagation();
			
		}
	};
	this.dragEnd = function(){
		if (moving) {
			dragObj.style.top = "0px";				//reset the top and left to 0px. The new top and left to be assigned by the respective event handlers
			dragObj.style.left = "0px";
			if (dragEndXHandler != null) {
				var currentX = EventUtil.getEvent().pageX - coordFrmLeftCorner.x;
				dragEndXHandler(EventUtil.getEvent().target, currentX);
			}
			
			if (dragEndYHandler != null) {
				var currentY = EventUtil.getEvent().pageY - coordFrmLeftCorner.y;
				dragEndYHandler(EventUtil.getEvent().target, currentY);
			}
			EventUtil.getEvent().preventDefault();
			parentNode.appendChild(dragObj);
		}
		if (!isIE || isMinIE7) {
			dragObj.style.cursor = "url('TimeWallv7/wallimage/cursor-closedhand.cur'),auto";
		}else{
				dragObj.style.cursor = "default";
		}
		moving = false;		
		
	};
	init();
};

AnkhEffects = function(){
	
	var that = this;
	var toInterruptMove = false;
	var toExecuteMove = false;
	var residual;
	var waitingQueueToMove = new Array();
	/**
	 * Purpose: To provide fading off effects
	 * @param {Object} obj - HTML object to be faded  
	 * @param {Int} duration - total duration
	 * @param {Func} onTerminateFunc - on termination function
	 * @param {Int} intervalNum - number of intervals
	 * @param {String} backgroundColor - optional
	 */
	this.fadeOff = function(obj, duration, intervalNum, onTerminateFunc,backgroundColor){
		var obj = obj;
		
		var duration = duration;
		var intervalNum = intervalNum;
		var onTerminateFunc = onTerminateFunc;
		
		var minValue = 0;
		var value = 10;
		var backgroundColor = backgroundColor || "#F4FAED";
		obj.style.backgroundColor = backgroundColor;
		var increment = value / intervalNum;
		var interval = duration / intervalNum;
				
		setOpacity = function(value){
			if (value < minValue) {				
				if (onTerminateFunc != null) {
					onTerminateFunc(obj);
				}
				return;
			}
			value -= increment;			
		
			obj.style.opacity = value / 10;
			obj.style.filter = 'alpha(opacity=' + value * 10 + ')';			
			setTimeout(function x(){
				setOpacity(value);
			}, interval);			
		}
		setTimeout(function x(){
			setOpacity(value);
		}, interval);
	};
	/**
	 * Purpose: Used to get preview message. Function commonly used prelude to expand.
	 * @param {String} originalMsg
	 * @param {Int} length - the length of the preview message
	 */
	this.getPreviewMsg = function(originalMsg,length){
		var stripHTML = /<\S[^><]*>/g;			//Regular expression tag to be used to strip
		var previewMsg = originalMsg.replace(/<br>/gi, '\n').replace(stripHTML, '');
		previewMsg = previewMsg.replace(/&nbsp;/gi," ");
		if(length){
			previewMsg =  previewMsg.substr(0, length);
		}
		if(originalMsg != previewMsg){		
			if (previewMsg.length == length) {
				var previewMsgWithDots = "\"" + previewMsg + " ... \"";
				var msgWithDotsWODblQuote = previewMsg +" ... ";			
			}else{
				var previewMsgWithDots = "\"" + previewMsg +" ...\""
				var msgWithDotsWODblQuote = previewMsg;
				
			}		
		}else{
			var previewMsgWithDots = "\"" + previewMsg +"\""
			var msgWithDotsWODblQuote = previewMsg;
		}
		return {
			msg: previewMsg,		
			msgWithDots: previewMsgWithDots,
			msgWithDotsWODblQuote: msgWithDotsWODblQuote
		};
	};
	/**
	 * Purpose: Used to contract HTML controls. Used commonly with Div. Td cannot work. 
	 * Contract does not handle the things to do after the targetobj has been contracted if the contractchild is an object
	 * @param {Int} iterations
	 * @param {Object} targetObj - HTML object - object cannot use padding. If need to, use margin instead.
	 * @param {String} contractChild
	 * @param {Int} totalTravelTime
	 * @param {Int} contractedHeight - or original height
	 */
	this.contract = function(iterations,targetObj,contractChild,totalTravelTime,contractedHeight,handler){
		var originalHeight = targetObj.scrollHeight;	
	//	alert(originalHeight+" "+targetObj.id+" "+targetObj.scrollHeight);				
		targetObj.style.height = originalHeight+"px";
		targetObj.style.overflow = "hidden";	
		
		var totalDistance = contractedHeight - originalHeight;		
		if (Math.abs(totalDistance) < 50) {
			targetObj.style.height = "auto";
			targetObj.style.overflow = "auto";

			if(typeof contractChild != "object"){				
				targetObj.innerHTML = contractChild;		
			}
		}
		else {			
			var k = new that.kinematics(totalDistance, 0, totalTravelTime);					
			that.reveal(0, targetObj, k, totalTravelTime / iterations, iterations,contractChild,handler);			
		}
	};
	
	
	/**
	 * Purpose: Used to expand HTML controls. Used commonly with Div. Td cannot work.
	 * @param {Int} iterations
	 * @param {Object} targetObj	- object cannot use padding. If need to, use margin instead.
	 * @param {Object} expandChild
	 * @param {Int} totalTravelTime
	 */
	this.expand = function(iterations,targetObj,expandChild,totalTravelTime){
		targetObj.style.height = "auto";			//necessary to get clientheight for IE
		targetObj.style.overflow = "auto";	
		var originalHeight = targetObj.clientHeight;					
		targetObj.style.height = originalHeight+"px";		
		targetObj.style.overflow = "hidden";
		
		if(typeof expandChild == "object"){
			targetObj.appendChild(expandChild);
		}else{		
			targetObj.innerHTML = expandChild;		
		}
		
		var newHeight = targetObj.scrollHeight;
		var totalDistance = newHeight - originalHeight;
		
		if (Math.abs(totalDistance) < 50) {
			targetObj.style.height = "auto";
			targetObj.style.overflow = "auto";
		}
		else {
			
			var k = new that.kinematics(totalDistance, 0, totalTravelTime);			
			that.reveal(0, targetObj, k, totalTravelTime / iterations, iterations);			
		}
	};
	/**
	 * Purpose: Internal function used by expand and contract to morph the HTML control
	 * @param {Int} count
	 * @param {Object} obj
	 * @param {Object} kinematics
	 * @param {Int} travelInterval - an interval
	 * @param {Int} maxIteration
	 * @param {String} revealCompleteText
	 */
	this.reveal = function(count,obj,kinematics,travelInterval,maxIteration,revealCompleteText,handler){		
		if(count == maxIteration){			
			obj.style.height = "auto";
			obj.style.overflow = "auto";	
			if(revealCompleteText != null && revealCompleteText != ""){		//used by contract function
				if (typeof revealCompleteText != "object") {											
					obj.innerHTML = revealCompleteText;
				}
			}
			if(handler){
				handler();
			}
			return;
		}
		if(count == maxIteration/2){
			kinematics.setAcceleration(-kinematics.getAcceleration());
		}
		var kinematicsResult = kinematics.getNextDistanceVelocity(travelInterval);
		var incrementDistance = kinematics.addCumulativeDistance(kinematicsResult.distance)+ kinematics.getCumulativeDistance();
		
		obj.style.height = parseInt(obj.clientHeight,10) + incrementDistance +"px";		
		
		window.setTimeout(function x(){that.reveal(count+1,obj,kinematics,travelInterval,maxIteration,revealCompleteText,handler);},travelInterval)
	};
	/**
	 * Purpose: Used to move objects up and down
	 * @param {Int} iterations
	 * @param {Object} objToMove 
	 * @param {Int} destination - destination
	 * @param {Int} totalTravelTime - total travel time
	 */
	this.moveUpDown = function(iterations,objToMove,totalTravelTime,min,max,handler){	
		waitingQueueToMove.push(objToMove);		
		window.setTimeout(function(){that.start(iterations,objToMove,totalTravelTime,min,max,handler),totalTravelTime/iterations});					
	};
	
	this.start = function(iterations,objToMove,totalTravelTime,min,max,handler){		
		if (waitingQueueToMove.length > 0) {
			var obj = waitingQueueToMove[waitingQueueToMove.length - 1];	
			waitingQueueToMove.length = 0;		
			var totalDistance = obj.destination - parseInt(obj.style.top, 10);				
			var k = new that.constantKinematics(totalDistance, iterations);
			moveUpDownConstantHelper(0, obj, k, totalTravelTime / iterations, iterations, obj.destination, min, max,handler);
		}	
	};
	/**
	 * Purpose: Internal function used by moveUpDown to morph movement of objects in constant speed
	 * @param {Object} count
	 * @param {Object} obj
	 * @param {Object} distance
	 * @param {Object} travelInterval
	 * @param {Object} maxIteration
	 * @param {Object} finalTop
	 * @param {Object} min
	 * @param {Object} max
	 */
	moveUpDownConstantHelper = function(count,obj,constantKinematics,travelInterval,maxIteration,finalTop,min,max,handler){
		if(waitingQueueToMove.length > 0){			
	
			return;
		}
		
		if(count == maxIteration){
			//obj.style.top = finalTop + "px";
			if(handler){
				handler();
			}	
			return;
		}
		var distance = constantKinematics.getNextDistance();		
		var incrementDistance = constantKinematics.addCumulativeDistance(distance)+ constantKinematics.getCumulativeDistance();
		var newTop = parseInt(obj.style.top,10) + incrementDistance;
				
		if(newTop >= min && newTop <= max){
			obj.style.top = newTop +"px";					
		}else if(newTop < min){
			obj.style.top = min +"px";
		}
		else if(newTop > max){
			obj.style.top = max +"px";
		}
		
		window.setTimeout(function x(){moveUpDownConstantHelper(count + 1,obj,constantKinematics,travelInterval,maxIteration,finalTop,min,max,handler);},travelInterval)
	};
	
	
		/**
	 * Purpose: Initiate scrolling with animation
	 * @param {Int} distance - total distance to be moved
	 * @param {Int} travelTime - total travel time
	 * @param {Int} Iteration - number of morphing iteration 
	 * @param {Func} endFunc - function to call when animation is over
	 */
	this.moveRight = function(distance,travelTime,Iteration,moveRightFunc,endFunc){										
		residual = 0;
		var kinematics = new that.kinematics(distance,0,travelTime);
		moveRightHelper(0,travelTime,kinematics,Iteration,moveRightFunc,endFunc);		
	};

	/**
	 * Purpose: Animation capability (Helper function for animatedScrollRight)
	 * @param {Int} count - current iteration number
	 * @param {Int} travelTime - total animation time
	 * @param {Int} Iteration - number of morphing iteration
	 * @param {Func} endFunc - function to call when animation is over
	 */
	moveRightHelper = function(count,travelTime,kinematics,Iteration,moveRightFunc,endFunc){
		if(count == Iteration){	
			if(endFunc){				
				endFunc();
			}
			return;
		}
		if(count == Iteration/2){
			kinematics.setAcceleration(-kinematics.getAcceleration());			
		}
		var distanceVelocity = kinematics.getNextDistanceVelocity(travelTime/Iteration);	
		var distance = distanceVelocity.distance;	
		residual += distance - parseInt(distance,10);
		
		if (residual <= -1) {
			moveRightFunc(parseInt(distance,10) - parseInt(residual,10));
			residual -= parseInt(residual,10);
		}else{
			moveRightFunc(parseInt(distance,10));
		}
		window.setTimeout(function(){moveRightHelper(count+1,travelTime,kinematics,Iteration,moveRightFunc,endFunc)},travelTime/Iteration);	
	};

	
	this.constantKinematics = function(totalDistance,totalIteration){
		var cumulativeDistance = 0;
		var distance = totalDistance/totalIteration;
		
		
		this.addCumulativeDistance = function(rawDistance){						
			var roundedDistance = parseInt(rawDistance, 10);
			cumulativeDistance += rawDistance - roundedDistance;			
			return roundedDistance;
		};
		this.getCumulativeDistance = function(){
			if(cumulativeDistance >= 1 || cumulativeDistance <= -1){
				var roundedUpCumulativeDistance = parseInt(cumulativeDistance,10);
				cumulativeDistance -= roundedUpCumulativeDistance;
				return roundedUpCumulativeDistance;
			}
			return 0;
		};
		//Method used to get subsequent Kinematics object
		this.getNextDistance= function(){
			return distance;
		};
	};

	/**
	 * Purpose: Create the kinematics object
	 * @param {Int} totalDistance - total travel distance
	 * @param {Int} initialVelocity - typically 0
	 * @param {Int} totalTime - total travel time
	 */
	this.kinematics = function(totalDistance,initialVelocity,totalTime){
		var velocity = initialVelocity;
		var distance = 0;
		var acceleration;		
		var cumulativeDistance = 0;
		
		this.addCumulativeDistance = function(rawDistance){						
			var roundedDistance = parseInt(rawDistance, 10);
			cumulativeDistance += rawDistance - roundedDistance;			
			return roundedDistance;
		};
		this.getCumulativeDistance = function(){
			if(cumulativeDistance >= 1 || cumulativeDistance <= -1){
				var roundedUpCumulativeDistance = parseInt(cumulativeDistance,10);
				cumulativeDistance -= roundedUpCumulativeDistance;
				return roundedUpCumulativeDistance;
			}
			return 0;
		};
	
		//Method used to get subsequent Kinematics object
		this.getNextDistanceVelocity = function(travelInterval){
			distance = getDistanceMoved(velocity,acceleration,travelInterval);
			velocity = getFinalVelocity(velocity,acceleration,travelInterval);
			return {distance:distance, velocity:velocity};
		};
		this.getAcceleration = function(){
			return acceleration;
		};		
		this.setAcceleration = function(value){
			acceleration = value;
		};
		//method used to find the required acceleration/decceleration given required travel distance, initial speed and time
		findRequiredAcceleration = function(travelDistance, initialSpeed, travelTime){
			return 2 * travelDistance / (travelTime * travelTime) - 2 * (initialSpeed / travelTime);
		};
		//method used to find distance moved given initial velocity, acceleration and traveltime
		getDistanceMoved = function(initialVelocity, acceleration, travelTime){
			return initialVelocity * travelTime + acceleration * (travelTime * travelTime) / 2;
		};
		//method used to find required final velocity given initial velocity, acceleration and traveltime
		getFinalVelocity = function(initialVelocity, acceleration, travelTime){
			return initialVelocity + acceleration * travelTime;
		};					
		acceleration = findRequiredAcceleration(totalDistance/2,velocity,totalTime/2);
		
	};
};
var sUserAgent = navigator.userAgent;
var fAppVersion = parseFloat(navigator.appVersion);

function compareVersions(sVersion1, sVersion2) {

    var aVersion1 = sVersion1.split(".");
    var aVersion2 = sVersion2.split(".");
    
    if (aVersion1.length > aVersion2.length) {
        for (var i=0; i < aVersion1.length - aVersion2.length; i++) {
            aVersion2.push("0");
        }
    } else if (aVersion1.length < aVersion2.length) {
        for (var i=0; i < aVersion2.length - aVersion1.length; i++) {
            aVersion1.push("0");
        }    
    }
    
    for (var i=0; i < aVersion1.length; i++) {
 
        if (aVersion1[i] < aVersion2[i]) {
            return -1;
        } else if (aVersion1[i] > aVersion2[i]) {
            return 1;
        }    
    }
    return 0;

}

var isOpera = sUserAgent.indexOf("Opera") > -1;
var isMinOpera4 = isMinOpera5 = isMinOpera6 = isMinOpera7 = isMinOpera7_5 = false;
var isChrome = sUserAgent.indexOf("Chrome") > -1;

if (isOpera) {
    var fOperaVersion;
    if(navigator.appName == "Opera") {
        fOperaVersion = fAppVersion;
    } else {
        var reOperaVersion = new RegExp("Opera (\\d+\\.\\d+)");
        reOperaVersion.test(sUserAgent);
        fOperaVersion = parseFloat(RegExp["$1"]);
    }

    isMinOpera4 = fOperaVersion >= 4;
    isMinOpera5 = fOperaVersion >= 5;
    isMinOpera6 = fOperaVersion >= 6;
    isMinOpera7 = fOperaVersion >= 7;
    isMinOpera7_5 = fOperaVersion >= 7.5;
}

var isKHTML = sUserAgent.indexOf("KHTML") > -1 
              || sUserAgent.indexOf("Konqueror") > -1 
              || sUserAgent.indexOf("AppleWebKit") > -1; 
              
var isMinSafari1 = isMinSafari1_2 = false;
var isMinKonq2_2 = isMinKonq3 = isMinKonq3_1 = isMinKonq3_2 = false;
var isSafari;
if (isKHTML) {
    isSafari = sUserAgent.indexOf("AppleWebKit") > -1;
    isKonq = sUserAgent.indexOf("Konqueror") > -1;

    if (isSafari) {
        var reAppleWebKit = new RegExp("AppleWebKit\\/(\\d+(?:\\.\\d*)?)");
        reAppleWebKit.test(sUserAgent);
        var fAppleWebKitVersion = parseFloat(RegExp["$1"]);

        isMinSafari1 = fAppleWebKitVersion >= 85;
        isMinSafari1_2 = fAppleWebKitVersion >= 124;
    } else if (isKonq) {

        var reKonq = new RegExp("Konqueror\\/(\\d+(?:\\.\\d+(?:\\.\\d)?)?)");
        reKonq.test(sUserAgent);
        isMinKonq2_2 = compareVersions(RegExp["$1"], "2.2") >= 0;
        isMinKonq3 = compareVersions(RegExp["$1"], "3.0") >= 0;
        isMinKonq3_1 = compareVersions(RegExp["$1"], "3.1") >= 0;
        isMinKonq3_2 = compareVersions(RegExp["$1"], "3.2") >= 0;
    } 
    
}

var isIE = sUserAgent.indexOf("compatible") > -1 
           && sUserAgent.indexOf("MSIE") > -1
           && !isOpera;
           
var isMinIE4 = isMinIE5 = isMinIE5_5 = isMinIE6 = false;

if (isIE) {
    var reIE = new RegExp("MSIE (\\d+\\.\\d+);");
    reIE.test(sUserAgent);
    var fIEVersion = parseFloat(RegExp["$1"]);
	
    isMinIE4 = fIEVersion >= 4;
    isMinIE5 = fIEVersion >= 5;
    isMinIE5_5 = fIEVersion >= 5.5;
    isMinIE6 = fIEVersion >= 6.0;
	isMinIE7 = fIEVersion >= 7.0;
	isMinIE8 = fIEVersion >= 8.0;

}

var isMoz = sUserAgent.indexOf("Gecko") > -1
            && !isKHTML;

var isMinMoz1 = sMinMoz1_4 = isMinMoz1_5 = false;

if (isMoz) {
    var reMoz = new RegExp("rv:(\\d+\\.\\d+(?:\\.\\d+)?)");
    reMoz.test(sUserAgent);
    isMinMoz1 = compareVersions(RegExp["$1"], "1.0") >= 0;
    isMinMoz1_4 = compareVersions(RegExp["$1"], "1.4") >= 0;
    isMinMoz1_5 = compareVersions(RegExp["$1"], "1.5") >= 0;
	isMinMoz1_8 = compareVersions(RegExp["$1"], "1.8") >= 0;		//mainly used by firefox 2.0
	isMinMoz1_9 = compareVersions(RegExp["$1"], "1.9") >= 0;		//mainly used by firefox 3.0
}

var isNS4 = !isIE && !isOpera && !isMoz && !isKHTML 
            && (sUserAgent.indexOf("Mozilla") == 0) 
            && (navigator.appName == "Netscape") 
            && (fAppVersion >= 4.0 && fAppVersion < 5.0);

var isMinNS4 = isMinNS4_5 = isMinNS4_7 = isMinNS4_8 = false;

if (isNS4) {
    isMinNS4 = true;
    isMinNS4_5 = fAppVersion >= 4.5;
    isMinNS4_7 = fAppVersion >= 4.7;
    isMinNS4_8 = fAppVersion >= 4.8;
}

var isWin = (navigator.platform == "Win32") || (navigator.platform == "Windows");
var isMac = (navigator.platform == "Mac68K") || (navigator.platform == "MacPPC") 
            || (navigator.platform == "Macintosh");

var isUnix = (navigator.platform == "X11") && !isWin && !isMac;

var isWin95 = isWin98 = isWinNT4 = isWin2K = isWinME = isWinXP = false;
var isMac68K = isMacPPC = false;
var isSunOS = isMinSunOS4 = isMinSunOS5 = isMinSunOS5_5 = false;

if (isWin) {
    isWin95 = sUserAgent.indexOf("Win95") > -1 
              || sUserAgent.indexOf("Windows 95") > -1;
    isWin98 = sUserAgent.indexOf("Win98") > -1 
              || sUserAgent.indexOf("Windows 98") > -1;
    isWinME = sUserAgent.indexOf("Win 9x 4.90") > -1 
              || sUserAgent.indexOf("Windows ME") > -1;
    isWin2K = sUserAgent.indexOf("Windows NT 5.0") > -1 
              || sUserAgent.indexOf("Windows 2000") > -1;
    isWinXP = sUserAgent.indexOf("Windows NT 5.1") > -1 
              || sUserAgent.indexOf("Windows XP") > -1;
    isWinNT4 = sUserAgent.indexOf("WinNT") > -1 
              || sUserAgent.indexOf("Windows NT") > -1 
              || sUserAgent.indexOf("WinNT4.0") > -1 
              || sUserAgent.indexOf("Windows NT 4.0") > -1 
              && (!isWinME && !isWin2K && !isWinXP);
} 

if (isMac) {
    isMac68K = sUserAgent.indexOf("Mac_68000") > -1 
               || sUserAgent.indexOf("68K") > -1;
    isMacPPC = sUserAgent.indexOf("Mac_PowerPC") > -1 
               || sUserAgent.indexOf("PPC") > -1;  
}

if (isUnix) {
    isSunOS = sUserAgent.indexOf("SunOS") > -1;

    if (isSunOS) {
        var reSunOS = new RegExp("SunOS (\\d+\\.\\d+(?:\\.\\d+)?)");
        reSunOS.test(sUserAgent);
        isMinSunOS4 = compareVersions(RegExp["$1"], "4.0") >= 0;
        isMinSunOS5 = compareVersions(RegExp["$1"], "5.0") >= 0;
        isMinSunOS5_5 = compareVersions(RegExp["$1"], "5.5") >= 0;
    }
}


var EventUtil = new Object;

EventUtil.addEventHandler = function (oTarget, sEventType, fnHandler) {
    if (oTarget.addEventListener) {
		if(isMoz && sEventType == "mousewheel"){
			oTarget.addEventListener("DOMMouseScroll", fnHandler, false);
		}
		else
		{
        	oTarget.addEventListener(sEventType, fnHandler, false);
		}
    } else if (oTarget.attachEvent) {
        oTarget.attachEvent("on" + sEventType, fnHandler);
    } else {
        oTarget["on" + sEventType] = fnHandler;
    }
};
        
EventUtil.removeEventHandler = function (oTarget, sEventType, fnHandler) {
    if (oTarget.removeEventListener) {
        oTarget.removeEventListener(sEventType, fnHandler, false);
    } else if (oTarget.detachEvent) {
        oTarget.detachEvent("on" + sEventType, fnHandler);
    } else { 
        oTarget["on" + sEventType] = null;
    }
};

EventUtil.formatEventForIE = function (oEvent) {
    if (isIE && isWin) {
        oEvent.charCode = (oEvent.type == "keypress") ? oEvent.keyCode : 0;
        oEvent.eventPhase = 2;
        oEvent.isChar = (oEvent.charCode > 0);
		
		oEvent.pageX = oEvent.clientX + document.documentElement.scrollLeft;
		oEvent.pageY = oEvent.clientY + document.documentElement.scrollTop;
		
        oEvent.preventDefault = function () {
            this.returnValue = false;
        };

        if (oEvent.type == "mouseout") {
            oEvent.relatedTarget = oEvent.toElement;
        } else if (oEvent.type == "mouseover") {
            oEvent.relatedTarget = oEvent.fromElement;
        }
		oEvent.relativeX = oEvent.x;
		oEvent.relativeY = oEvent.y;
		oEvent.mouseDelta = -oEvent.wheelDelta / 120;
		
        oEvent.stopPropagation = function () {
            this.cancelBubble = true;
        };

        oEvent.target = oEvent.srcElement;
        oEvent.time = (new Date).getTime();
    }
	
    return oEvent;
};

EventUtil.formatEventForDOMCompilant = function (oEvent) {
	// this is written for a bug in firefox 2.0. DomMouseScroll returns the right coordinates using screenX instead of pageX.
	if(oEvent.type == "DOMMouseScroll" && isMoz && !isMinMoz1_9){		
		if (AnkhUsefulMethods.getStyle(oEvent.currentTarget, "overflow") == "hidden") {
			//this is required if overflow = hidden
			oEvent.relativeX = oEvent.screenX + window.pageXOffset - this.findPosX(oEvent.currentTarget);
			oEvent.relativeY = oEvent.screenY + window.pageYOffset - this.findPosY(oEvent.currentTarget);
		}
		else {			//this is required if overflow = auto. Not tested with scroll yet.
			oEvent.relativeX = oEvent.screenX + window.pageXOffset;
			oEvent.relativeY = oEvent.screenY + window.pageYOffset;
		}
	}
	else{
		oEvent.relativeX = oEvent.pageX - this.findPosX(oEvent.currentTarget) ;		
		oEvent.relativeY = oEvent.pageY - this.findPosY(oEvent.currentTarget) ;
	}
	if(isMoz){
		oEvent.mouseDelta = oEvent.detail / 3;
	}else if(isKHTML) {
		oEvent.mouseDelta = -oEvent.wheelDelta / 120;
	}		
	else if(isOpera) {
		oEvent.mouseDelta = oEvent.wheelDelta / 120;
	}
	return oEvent;
};

EventUtil.findPosY = function(obj) {
	var curtop = 0;	
	if (obj != null) {
		if (obj.offsetParent != null) {
			while (obj.offsetParent) {
				curtop += obj.offsetTop
				obj = obj.offsetParent;
			}
		}
		else 
			if (obj.y) {
				curtop += obj.y;
			}
	}
	return curtop;
};

EventUtil.findPosX =function(obj) {
	var curleft = 0;
	if (obj != null) {
		if (obj.offsetParent != null) {
			while (obj.offsetParent) {
				curleft += obj.offsetLeft
				obj = obj.offsetParent;
			}
		}
		else 
			if (obj.x) {
				curleft += obj.x;
			}
	}
	return curleft;
};

EventUtil.getEvent = function(iframe) {
    if (isIE) {
		if(window.event){
        	return this.formatEventForIE(window.event);
		}
		else{
			return this.formatEventForIE(iframe.contentWindow.event);	
		}
    }
	else {
        return this.formatEventForDOMCompilant(EventUtil.getEvent.caller.arguments[0]);
    }
};AnkhUsefulMethods = {};
AnkhUsefulMethods.getStyle = function(element,styleProp){		//not totally useful for Safari
	
	if (element.currentStyle) {		// for IE
		if (styleProp == "Width") {
			if (element.tagName == "IMG") {
				return element.width;
			}
			return element.currentStyle['width'];
		}
		else if (styleProp == "Height") {
			if (element.tagName == "IMG") {
				return element.height;
			}
			return element.currentStyle['height'];
		}
		else if (styleProp == "Right") {
				return element.currentStyle['right'];
		}
		else if (styleProp == "Left") {						
			return element.currentStyle['left'];
		}
		else if (styleProp = "Top") {
			return element.currentStyle['top'];
		}
		else{
			return element.currentStyle[styleProp];
		}
	}	
	else if (window.getComputedStyle){			
		return document.defaultView.getComputedStyle(element,null).getPropertyValue(styleProp);
	}
}
AnkhUsefulMethods.disableSelection = function(target){
	if (typeof target.onselectstart != "undefined") //IE route
	{
		target.onselectstart = function(){
			return false;
		}
	}
	else 
		if (typeof target.style.MozUserSelect != "undefined") //Firefox route
		{
			target.style.MozUserSelect = "none";
		}
		else //All other route (ie: Opera)
 			target.onmousedown = function(){
				return true;
			}
};

 AnkhUsefulMethods.getViewPort = function(){
 	var viewportwidth;
 	var viewportheight;
 	
 	// the more standards compliant browsers (mozilla/netscape/opera/IE7) use window.innerWidth and window.innerHeight
		
	if (typeof window.innerWidth != 'undefined') {
		viewportwidth = window.innerWidth;
		viewportheight = window.innerHeight;
	}
	
	// IE6 in standards compliant mode (i.e. with a valid doctype as the first line in the document)	
	else {
		if (typeof document.documentElement != 'undefined' && typeof document.documentElement.clientWidth != 'undefined' &&
		document.documentElement.clientWidth != 0) {
			viewportwidth = document.documentElement.clientWidth, viewportheight = document.documentElement.clientHeight
		}
		// older versions of IE		
		else {
			viewportwidth = document.getElementsByTagName('body')[0].clientWidth, viewportheight = document.getElementsByTagName('body')[0].clientHeight
		}
	}
	return {
		width: viewportwidth,
		height: viewportheight
	};
};

/**
 * Purpose: Create a sentence from a list of words. Sentence consists of "," and "and".
 * @param {Array} wordList
 * @param {String} index
 */
AnkhUsefulMethods.formSentence = function(wordList,index,notEndOfSentence){
	var sentence = "";
	for (var j = 0; j < wordList.length; j++) {
		if (index != null) {
			sentence += wordList[j][index];
		}
		else {
			sentence += wordList[j];
		}
		if(j < wordList.length - 2){
			sentence += ", ";
		}else if(j == wordList.length - 2){
			sentence += " and ";
		}
		else if( j == wordList.length - 1){
			if (!notEndOfSentence) {
				sentence += ".";
			}
		}				
	}
	return sentence;
};
AnkhUsefulMethods.isInArray = function(arr,item){
	for(var i = 0;i < arr.length;i++){
		if(arr[i] == item){
			return true;
		}
	}
	return false;
}
/**
 * Purpose: Return "," for less than wordList.length - 2 and return "and" for wordList.length - 1
 * @param {Array} wordList
 * @param {Int} rank
 * @param {Int} max
 * @param {Boolean} html - true->return &nbsp; false->return " ";
 */
AnkhUsefulMethods.getConnectWords = function(wordList,rank,max,html){

	var wordIndex = wordList.length - 2;		
	if(max !=null){
		var maxIndex = max - 2;
		if (maxIndex < wordIndex) {
			wordIndex = maxIndex;			
		}
	} 	
	if(rank < wordIndex){
		return ", ";
	}else if(rank == wordIndex){
		if (html || html == null) {
			return "&nbsp;and ";			
		}
		else {
			return " and ";
		}
	}
	return "";
};

/**
 * Purpose: Get the centralised location of the browser
 * @param {Int} controlHeight - height of the control
 * @param {Int} controlWidth - width of the control
 */
 AnkhUsefulMethods.getCentralisedLocation = function(controlHeight,controlWidth){
	var windowHeight = document.documentElement.clientHeight;		
	var posY;
	var scrollTop = document.documentElement.scrollTop || document.body.scrollTop  ;	
	if(windowHeight <= controlHeight){		
		posY = scrollTop;
	}else{
		posY = scrollTop+ (windowHeight - controlHeight) /2;
	}
	var windowWidth = document.documentElement.clientWidth;
	var posX;	
	if(windowWidth <= controlWidth){
		posX = 0;
	}else{
		posX = (windowWidth - controlWidth)/2;
	}
	return {X:posX,Y:posY};
 };
/**
 * Purpose - Remove all children nodes of obj
 * @param {Object} obj - the object which is subjected to be removed
 */
AnkhUsefulMethods.removeAll = function(obj){
	if(obj){
		while (obj.hasChildNodes()){
		  obj.removeChild(obj.firstChild);
		}
	}
};
/**
 * Purpose: Find pageY coordinates of object including border. Condition: border must be specified inline.
 * @param {Object} obj - the object to locate absolute position y
 */
AnkhUsefulMethods.findPosY = function(obj) {
	var curtop = 0;	
	if (obj.offsetParent) {
		while (obj.offsetParent) {
		curtop += obj.offsetTop;
		if (obj.style.borderTopWidth) {
			if (isMoz && !isMinMoz1_9) {
				curtop += parseInt(obj.style.borderTopWidth, 10) * 2;
			}else{
				curtop += parseInt(obj.style.borderTopWidth, 10);
			}			
		}			
		obj = obj.offsetParent;
		}
	} 	
	else if (obj.y) {
	curtop += obj.y;
	}
	return curtop;
};
/**
 * Purpose: Find pageX coordinates of object including border. Condition: border must be specified inline.
 * @param {Object} obj - the object to locate absolute position x
 */
AnkhUsefulMethods.findPosX =function(obj) {
	var curleft = 0;
	if ( obj.offsetParent) {
		while (obj.offsetParent) {
		curleft += obj.offsetLeft;
		if (obj.style.borderLeftWidth) {
			if (isMoz && !isMinMoz1_9) {
				curleft += parseInt(obj.style.borderLeftWidth, 10) * 2;
			}
			else {						
				curleft += parseInt(obj.style.borderLeftWidth, 10);
			}
		}
		obj = obj.offsetParent;		
		}
	} 
	else if (obj.x) {
		curleft += obj.x;
	}	
	return curleft;
};
/**
 * Purpose: Return the english words associated with gender
 * @param {Char} gender  - m/f or male/female
 */
AnkhUsefulMethods.genderStr = function(gender){
	if(gender.toLowerCase() == "m" || gender.toLowerCase() == "male"){
		return {noun:"He",action:"his",action2:"him",actionCap:"His"};
	}else{
		return {noun:"She",action:"her",action2:"her",actionCap:"Her"};
	}
};

/**
 * Purpose: Remove duplicates from an array using a comparisonField
 * @param {Array} array
 * @param {String} comparisonField
 */
AnkhUsefulMethods.removeDuplicatesInArray = function(array,comparisonField){
	if (array.length > 0) {	
		for (var j = 0; j < array.length; j++) {
			for (var k = j + 1; k < array.length; k++) {				
				if (array[j][comparisonField] == array[k][comparisonField]) {
					array.splice(k, 1);
				}
			}
		}
	}
	return array;	
};

/**
 * Purpose - Word Wrap the input control
 * @param {HTMLObject} inputControl - the object to be word wrapped 
 */
AnkhUsefulMethods.WordWrap = function(inputControl,inputControlWidth){	
	//only Opera and Firefox does not word wrap. 
	//And IE does not word-wrap very well. If the word is too long, it will cause dynamic table to be out of width 
	var numOfCharsToWrap = Math.ceil(inputControlWidth/7) || 7;		
	var input = inputControl.innerHTML;
	var temp = "";
	var inputArray = input.split(" ");
	for (var i = 0; i < inputArray.length; i++) {		
		while (inputArray[i].length >= numOfCharsToWrap) {
			temp += inputArray[i].substring(0, numOfCharsToWrap) + " ";
			inputArray[i] = inputArray[i].substring(numOfCharsToWrap, inputArray[i].length);
		}
		temp += inputArray[i] + " ";		
	}	
	inputControl.innerHTML = temp;	
};

/**
 * Purpose - Used to set cookie in user's browser
 * @param {Object} sName - cookie's key
 * @param {Object} sValue - cookie's value
 * @param {Object} oExpires - expiry date in JS Date object
 * @param {Object} sPath - relative path where the cookie can be applied, usually leave it blank
 * @param {Object} sDomain - the domain where this cookied can be applied, usually leave it blank
 */
AnkhUsefulMethods.setCookie = function(sName, sValue, oExpires, sPath, sDomain) {
	var sCookie = sName + "=" + encodeURIComponent(sValue);
	if (oExpires) {
		sCookie += "; expires=" + oExpires.toGMTString();
	}
	if (sPath) {
		sCookie += "; path=" + sPath;
	}
	if (sDomain) {
		sCookie += "; domain=" + sDomain;
	}
	document.cookie = sCookie;
}

/**
 * Purpose - Get cookie's value given its key value
 * @param {Object} sName - key value
 */
AnkhUsefulMethods.getCookie = function(sName) {
	var sRE = "(?:; )?" + sName + "=([^;]*);?";
	var oRE = new RegExp(sRE);
	if (oRE.test(document.cookie)) {
		return decodeURIComponent(RegExp["$1"]);
	} else {
		return null;
	}
}
/**
 * Purpose - Used to trim str of whitespaces
 * @param {String}  
 */
AnkhUsefulMethods.trim = function(str){
	var trimmed = str.replace(/^\s+|\s+$/g, '') ;
	return trimmed;
};

AnkhUsefulMethods.isValidEmail = function(email){
	var arr = new Array("@",".");
	for(var i = 0;i < arr.length;i++){
		if(email.indexOf(arr[i]) < 0){
			return false;
		}
	}
	return true;		
};

/**
 * Purpose: Purge objects so that memory leak issue caused by AJAX calls can be minimised. 
 * Used more to remove event handlers in IE6.
 * @param {Object} d - the object to be purged
 */
AnkhUsefulMethods.purge = function(d){    
	var a = d.attributes, i, l, n;    
	if (a) {        
		l = a.length;        
		for (i = 0; i < l; i += 1) {            
			n = a[i].name;            
			if (typeof d[n] === 'function') {                
				d[n] = null;            
			}        
		}    
	}   
	a = d.childNodes;    
	if (a) {        
		l = a.length;        
		for (i = 0; i < l; i += 1) {            
			purge(d.childNodes[i]);        
		}    
	}
};
	eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('G 1g={86:\'1.6.0.2\',1V:{3T:!!(1A.6Z&&!1A.87),4O:!!1A.87,4n:4P.4Q.3U(\'d6/\')>-1,70:4P.4Q.3U(\'70\')>-1&&4P.4Q.3U(\'a1\')==-1,a2:!!4P.4Q.1f(/d7.*d8.*a3/)},3V:{71:!!1b.2L,6a:!!1A.6b,72:1b.3W(\'1S\').4R&&1b.3W(\'1S\').4R!==1b.3W(\'1x\').4R},73:\'<4S[^>]*>([\\\\S\\\\s]*?)<\\/4S>\',a4:/^\\/\\*-d9-([\\s\\S]*)\\*\\/\\s*$/,3o:q(){},K:q(x){o x}};E(1g.1V.a2)1g.3V.72=1r;G 2b={2o:q(){G 2M=1j,3e=$A(1p);E(M.2p(3e[0]))2M=3e.4T();q 1N(){C.2G.3G(C,1p)}M.15(1N,2b.1d);1N.88=2M;1N.a5=[];E(2M){G 89=q(){};89.1l=2M.1l;1N.1l=1s 89;2M.a5.1h(1N)}17(G i=0;i<3e.O;i++)1N.6c(3e[i]);E(!1N.1l.2G)1N.1l.2G=1g.3o;1N.1l.da=1N;o 1N}};2b.1d={6c:q(22){G 2V=C.88&&C.88.1l;G 3e=M.48(22);E(!M.48({2H:1u}).O)3e.1h("2H","a6");17(G i=0,O=3e.O;i<O;i++){G 1y=3e[i],I=22[1y];E(2V&&M.2p(I)&&I.a7().3H()=="$49"){G 1D=I,I=M.15((q(m){o q(){o 2V[m].3G(C,1p)}})(1y).4U(1D),{a6:q(){o 1D},2H:q(){o 1D.2H()}})}C.1l[1y]=I}o C}};G 4V={};M.15=q(5p,22){17(G 1y 1Q 22)5p[1y]=22[1y];o 5p};M.15(M,{2z:q(W){2q{E(M.2A(W))o\'4o\';E(W===1j)o\'1j\';o W.2z?W.2z():24(W)}2B(e){E(e a8 db)o\'...\';4p e;}},3p:q(W){G 1B=3X W;5q(1B){2r\'4o\':2r\'q\':2r\'dc\':o;2r\'dd\':o W.2H()}E(W===1j)o\'1j\';E(W.3p)o W.3p();E(M.4a(W))o;G V=[];17(G 1y 1Q W){G I=M.3p(W[1y]);E(!M.2A(I))V.1h(1y.3p()+\': \'+I)}o\'{\'+V.2s(\', \')+\'}\'},4q:q(W){o $H(W).4q()},4b:q(W){o W&&W.4b?W.4b():24.5r(W)},48:q(W){G 48=[];17(G 1y 1Q W)48.1h(1y);o 48},1T:q(W){G 1T=[];17(G 1y 1Q W)1T.1h(W[1y]);o 1T},2C:q(W){o M.15({},W)},4a:q(W){o W&&W.3q==1},4r:q(W){o W!=1j&&3X W=="W"&&\'de\'1Q W&&\'2s\'1Q W},8a:q(W){o W a8 3Y},2p:q(W){o 3X W=="q"},3f:q(W){o 3X W=="3g"},4W:q(W){o 3X W=="4s"},2A:q(W){o 3X W=="4o"}});M.15(8b.1l,{a7:q(){G 3r=C.2H().1f(/^[\\s\\(]*q[^(]*\\((.*?)\\)/)[1].4c(",").74("3Z");o 3r.O==1&&!3r[0]?[]:3r},1J:q(){E(1p.O<2&&M.2A(1p[0]))o C;G 3h=C,20=$A(1p),W=20.4T();o q(){o 3h.3G(W,20.21($A(1p)))}},df:q(){G 3h=C,20=$A(1p),W=20.4T();o q(1c){o 3h.3G(W,[1c||1A.1c].21(20))}},75:q(){E(!1p.O)o C;G 3h=C,20=$A(1p);o q(){o 3h.3G(C,20.21($A(1p)))}},8c:q(){G 3h=C,20=$A(1p),a9=20.4T()*aa;o 1A.dg(q(){o 3h.3G(3h,20)},a9)},4U:q(1K){G 3h=C;o q(){o 1K.3G(C,[3h.1J(C)].21($A(1p)))}},4t:q(){E(C.8d)o C.8d;G 3h=C;o C.8d=q(){o 3h.3G(1j,[C].21($A(1p)))}}});8b.1l.4u=8b.1l.8c.75(0.dh);di.1l.3p=q(){o\'"\'+C.dj()+\'-\'+(C.dk()+1).4v(2)+\'-\'+C.dl().4v(2)+\'T\'+C.dm().4v(2)+\':\'+C.dn().4v(2)+\':\'+C.dp().4v(2)+\'Z"\'};G ab={ac:q(){G 76;17(G i=0,O=1p.O;i<O;i++){G ad=1p[i];2q{76=ad();2c}2B(e){}}o 76}};4d.1l.1f=4d.1l.2N;4d.ae=q(5s){o 24(5s).1W(/([.*+?^=!:${}()|[\\]\\/\\\\])/g,\'\\\\$1\')};G af=2b.2o({2G:q(2W,4e){C.2W=2W;C.4e=4e;C.77=1r;C.6d()},6d:q(){C.41=ag(C.6e.1J(C),C.4e*aa)},8e:q(){C.2W(C)},8f:q(){E(!C.41)o;ah(C.41);C.41=1j},6e:q(){E(!C.77){2q{C.77=1u;C.8e()}dq{C.77=1r}}}});M.15(24,{5r:q(I){o I==1j?\'\':24(I)},ai:{\'\\b\':\'\\\\b\',\'\\t\':\'\\\\t\',\'\\n\':\'\\\\n\',\'\\f\':\'\\\\f\',\'\\r\':\'\\\\r\',\'\\\\\':\'\\\\\\\\\'}});M.15(24.1l,{3i:q(25,3s){G 1q=\'\',22=C,1f;3s=1p.5t.8g(3s);1O(22.O>0){E(1f=22.1f(25)){1q+=22.3t(0,1f.1i);1q+=24.5r(3s(1f));22=22.3t(1f.1i+1f[0].O)}1m{1q+=22,22=\'\'}}o 1q},aj:q(25,3s,3u){3s=C.3i.8g(3s);3u=M.2A(3u)?1:3u;o C.3i(25,q(1f){E(--3u<0)o 1f[0];o 3s(1f)})},ak:q(25,Y){C.3i(25,Y);o 24(C)},dr:q(O,5u){O=O||30;5u=M.2A(5u)?\'...\':5u;o C.O>O?C.3t(0,O-5u.O)+5u:24(C)},3Z:q(){o C.1W(/^\\s+/,\'\').1W(/\\s+$/,\'\')},al:q(){o C.1W(/<\\/?[^>]+>/gi,\'\')},4f:q(){o C.1W(1s 4d(1g.73,\'am\'),\'\')},an:q(){G ao=1s 4d(1g.73,\'am\');G ap=1s 4d(1g.73,\'ds\');o(C.1f(ao)||[]).2O(q(aq){o(aq.1f(ap)||[\'\',\'\'])[1]})},4X:q(){o C.an().2O(q(4S){o 78(4S)})},79:q(){G 5v=1p.5t;5v.42.7a=C;o 5v.1S.4w},ar:q(){G 1S=1s J(\'1S\');1S.4w=C.al();o 1S.3j[0]?(1S.3j.O>1?$A(1S.3j).3I(\'\',q(2P,L){o 2P+L.4g}):1S.3j[0].4g):\'\'},7b:q(at){G 1f=C.3Z().1f(/([^?#]*)(#.*)?$/);E(!1f)o{};o 1f[1].4c(at||\'&\').3I({},q(3v,1G){E((1G=1G.4c(\'=\'))[0]){G 1w=8h(1G.4T());G I=1G.O>1?1G.2s(\'=\'):1G[0];E(I!=4o)I=8h(I);E(1w 1Q 3v){E(!M.4r(3v[1w]))3v[1w]=[3v[1w]];3v[1w].1h(I)}1m 3v[1w]=I}o 3v})},3w:q(){o C.4c(\'\')},8i:q(){o C.3t(0,C.O-1)+24.dt(C.au(C.O-1)+1)},7c:q(3u){o 3u<1?\'\':1s 2i(3u+1).2s(C)},8j:q(){G 4x=C.4c(\'-\'),8k=4x.O;E(8k==1)o 4x[0];G 8l=C.7d(0)==\'-\'?4x[0].7d(0).2Q()+4x[0].5w(1):4x[0];17(G i=1;i<8k;i++)8l+=4x[i].7d(0).2Q()+4x[i].5w(1);o 8l},6f:q(){o C.7d(0).2Q()+C.5w(1).2d()},du:q(){o C.3i(/::/,\'/\').3i(/([A-Z]+)([A-Z][a-z])/,\'#{1}6g#{2}\').3i(/([a-z\\d])([A-Z])/,\'#{1}6g#{2}\').3i(/-/,\'6g\').2d()},dv:q(){o C.3i(/6g/,\'-\')},2z:q(av){G 8m=C.3i(/[\\dw-\\dx\\\\]/,q(1f){G 8n=24.ai[1f[0]];o 8n?8n:\'\\\\dy\'+1f[0].au().4v(2,16)});E(av)o\'"\'+8m.1W(/"/g,\'\\\\"\')+\'"\';o"\'"+8m.1W(/\'/g,\'\\\\\\\'\')+"\'"},3p:q(){o C.2z(1u)},8o:q(2e){o C.aj(2e||1g.a4,\'#{1}\')},aw:q(){G 5s=C;E(5s.4Y())o 1r;5s=C.1W(/\\\\./g,\'@\').1W(/"[^"\\\\\\n\\r]*"/g,\'\');o(/^[,:{}\\[\\]0-9.\\-+dz-u \\n\\r\\t]*$/).2N(5s)},5x:q(ax){G 3k=C.8o();2q{E(!ax||3k.aw())o 78(\'(\'+3k+\')\')}2B(e){}4p 1s dA(\'dB dC ay 3g: \'+C.2z());},1L:q(25){o C.3U(25)>-1},8p:q(25){o C.3U(25)===0},az:q(25){G d=C.O-25.O;o d>=0&&C.8q(25)===d},5y:q(){o C==\'\'},4Y:q(){o/^\\s*$/.2N(C)},aA:q(W,25){o 1s 2X(C,25).2L(W)}});E(1g.1V.4n||1g.1V.3T)M.15(24.1l,{79:q(){o C.1W(/&/g,\'&aB;\').1W(/</g,\'&aC;\').1W(/>/g,\'&gt;\')},ar:q(){o C.1W(/&aB;/g,\'&\').1W(/&aC;/g,\'<\').1W(/&gt;/g,\'>\')}});24.1l.3i.8g=q(3s){E(M.2p(3s))o 3s;G 5z=1s 2X(3s);o q(1f){o 5z.2L(1f)}};24.1l.dD=24.1l.7b;M.15(24.1l.79,{1S:1b.3W(\'1S\'),42:1b.aD(\'\')});aE(24.1l.79)1S.5A(42);G 2X=2b.2o({2G:q(5z,25){C.5z=5z.2H();C.25=25||2X.aF},2L:q(W){E(M.2p(W.8r))W=W.8r();o C.5z.3i(C.25,q(1f){E(W==1j)o\'\';G 4Z=1f[1]||\'\';E(4Z==\'\\\\\')o 1f[2];G 6h=W,6i=1f[3];G 25=/^([^.[]+|\\[((?:.*?[^\\\\])?)\\])(\\.|\\[|$)/;1f=25.aG(6i);E(1f==1j)o 4Z;1O(1f!=1j){G aH=1f[1].8p(\'[\')?1f[2].3i(\'\\\\\\\\]\',\']\'):1f[1];6h=6h[aH];E(1j==6h||\'\'==1f[3])2c;6i=6i.5w(\'[\'==1f[3]?1f[1].O:1f[0].O);1f=25.aG(6i)}o 4Z+24.5r(6h)})}});2X.aF=/(^|.|\\r|\\n)(#\\{(.*?)\\})/;G $2c={};G 2I={1E:q(Y,1M){G 1i=0;Y=Y.1J(1M);2q{C.4h(q(I){Y(I,1i++)})}2B(e){E(e!=$2c)4p e;}o C},aI:q(4s,Y,1M){Y=Y?Y.1J(1M):1g.K;G 1i=-4s,8s=[],2D=C.3w();1O((1i+=4s)<2D.O)8s.1h(2D.3t(1i,1i+4s));o 8s.8t(Y,1M)},8u:q(Y,1M){Y=Y?Y.1J(1M):1g.K;G 1q=1u;C.1E(q(I,1i){1q=1q&&!!Y(I,1i);E(!1q)4p $2c;});o 1q},aJ:q(Y,1M){Y=Y?Y.1J(1M):1g.K;G 1q=1r;C.1E(q(I,1i){E(1q=!!Y(I,1i))4p $2c;});o 1q},8t:q(Y,1M){Y=Y?Y.1J(1M):1g.K;G V=[];C.1E(q(I,1i){V.1h(Y(I,1i))});o V},7e:q(Y,1M){Y=Y.1J(1M);G 1q;C.1E(q(I,1i){E(Y(I,1i)){1q=I;4p $2c;}});o 1q},5B:q(Y,1M){Y=Y.1J(1M);G V=[];C.1E(q(I,1i){E(Y(I,1i))V.1h(I)});o V},dE:q(2e,Y,1M){Y=Y?Y.1J(1M):1g.K;G V=[];E(M.3f(2e))2e=1s 4d(2e);C.1E(q(I,1i){E(2e.1f(I))V.1h(Y(I,1i))});o V},1L:q(W){E(M.2p(C.3U))E(C.3U(W)!=-1)o 1u;G 8v=1r;C.1E(q(I){E(I==W){8v=1u;4p $2c;}});o 8v},dF:q(4s,6j){6j=M.2A(6j)?1j:6j;o C.aI(4s,q(3t){1O(3t.O<4s)3t.1h(6j);o 3t})},3I:q(2P,Y,1M){Y=Y.1J(1M);C.1E(q(I,1i){2P=Y(2P,I,1i)});o 2P},74:q(1D){G 20=$A(1p).3t(1);o C.2O(q(I){o I[1D].3G(I,20)})},dG:q(Y,1M){Y=Y?Y.1J(1M):1g.K;G 1q;C.1E(q(I,1i){I=Y(I,1i);E(1q==1j||I>=1q)1q=I});o 1q},dH:q(Y,1M){Y=Y?Y.1J(1M):1g.K;G 1q;C.1E(q(I,1i){I=Y(I,1i);E(1q==1j||I<1q)1q=I});o 1q},dI:q(Y,1M){Y=Y?Y.1J(1M):1g.K;G 8w=[],8x=[];C.1E(q(I,1i){(Y(I,1i)?8w:8x).1h(I)});o[8w,8x]},5C:q(1y){G V=[];C.1E(q(I){V.1h(I[1y])});o V},dJ:q(Y,1M){Y=Y.1J(1M);G V=[];C.1E(q(I,1i){E(!Y(I,1i))V.1h(I)});o V},aK:q(Y,1M){Y=Y.1J(1M);o C.2O(q(I,1i){o{I:I,6k:Y(I,1i)}}).dK(q(2t,5D){G a=2t.6k,b=5D.6k;o a<b?-1:a>b?1:0}).5C(\'I\')},3w:q(){o C.2O()},dL:q(){G Y=1g.K,20=$A(1p);E(M.2p(20.2u()))Y=20.dM();G aL=[C].21(20).2O($A);o C.2O(q(I,1i){o Y(aL.5C(1i))})},aM:q(){o C.3w().O},2z:q(){o\'#<2I:\'+C.3w().2z()+\'>\'}};M.15(2I,{2O:2I.8t,8y:2I.7e,2E:2I.5B,2e:2I.5B,dN:2I.1L,dO:2I.3w,dP:2I.8u,dQ:2I.aJ});q $A(2Y){E(!2Y)o[];E(2Y.3w)o 2Y.3w();G O=2Y.O||0,V=1s 2i(O);1O(O--)V[O]=2Y[O];o V}E(1g.1V.4n){$A=q(2Y){E(!2Y)o[];E(!(M.2p(2Y)&&2Y==\'[W dR]\')&&2Y.3w)o 2Y.3w();G O=2Y.O||0,V=1s 2i(O);1O(O--)V[O]=2Y[O];o V}}2i.aN=$A;M.15(2i.1l,2I);E(!2i.1l.8z)2i.1l.8z=2i.1l.4i;M.15(2i.1l,{4h:q(Y){17(G i=0,O=C.O;i<O;i++)Y(C[i])},aO:q(){C.O=0;o C},3H:q(){o C[0]},2u:q(){o C[C.O-1]},dS:q(){o C.2E(q(I){o I!=1j})},aP:q(){o C.3I([],q(2D,I){o 2D.21(M.4r(I)?I.aP():[I])})},6l:q(){G 1T=$A(1p);o C.2E(q(I){o!1T.1L(I)})},4i:q(aQ){o(aQ!==1r?C:C.3w()).8z()},dT:q(){o C.O>1?C:C[0]},aR:q(aS){o C.3I([],q(2D,I,1i){E(0==1i||(aS?2D.2u()!=I:!2D.1L(I)))2D.1h(I);o 2D})},dU:q(2D){o C.aR().5B(q(5E){o 2D.7e(q(I){o 5E===I})})},2C:q(){o[].21(C)},aM:q(){o C.O},2z:q(){o\'[\'+C.2O(M.2z).2s(\', \')+\']\'},3p:q(){G V=[];C.1E(q(W){G I=M.3p(W);E(!M.2A(I))V.1h(I)});o\'[\'+V.2s(\', \')+\']\'}});E(M.2p(2i.1l.aT))2i.1l.4h=2i.1l.aT;E(!2i.1l.3U)2i.1l.3U=q(5E,i){i||(i=0);G O=C.O;E(i<0)i=O+i;17(;i<O;i++)E(C[i]===5E)o i;o-1};E(!2i.1l.8q)2i.1l.8q=q(5E,i){i=dV(i)?C.O:(i<0?C.O+i:i)+1;G n=C.3t(0,i).4i().3U(5E);o(n<0)?n:i-n-1};2i.1l.3w=2i.1l.2C;q $w(3g){E(!M.3f(3g))o[];3g=3g.3Z();o 3g?3g.4c(/\\s+/):[]}E(1g.1V.4O){2i.1l.21=q(){G 2D=[];17(G i=0,O=C.O;i<O;i++)2D.1h(C[i]);17(G i=0,O=1p.O;i<O;i++){E(M.4r(1p[i])){17(G j=0,aU=1p[i].O;j<aU;j++)2D.1h(1p[i][j])}1m{2D.1h(1p[i])}}o 2D}}M.15(50.1l,{dW:q(){o C.4v(2,16)},8i:q(){o C+1},7c:q(Y){$R(0,C,1u).1E(Y);o C},4v:q(O,aV){G 3g=C.2H(aV||10);o\'0\'.7c(O-3g.O)+3g},3p:q(){o dX(C)?C.2H():\'1j\'}});$w(\'dY dZ e0 e1\').1E(q(1D){50.1l[1D]=e2[1D].4t()});q $H(W){o 1s 3Y(W)};G 3Y=2b.2o(2I,(q(){q 8A(1w,I){E(M.2A(I))o 1w;o 1w+\'=\'+aW(24.5r(I))}o{2G:q(W){C.4y=M.8a(W)?W.6m():M.2C(W)},4h:q(Y){17(G 1w 1Q C.4y){G I=C.4y[1w],1G=[1w,I];1G.1w=1w;1G.I=I;Y(1G)}},6n:q(1w,I){o C.4y[1w]=I},8B:q(1w){o C.4y[1w]},e3:q(1w){G I=C.4y[1w];8C C.4y[1w];o I},6m:q(){o M.2C(C.4y)},48:q(){o C.5C(\'1w\')},1T:q(){o C.5C(\'I\')},1i:q(I){G 1f=C.7e(q(1G){o 1G.I===I});o 1f&&1f.1w},e4:q(W){o C.2C().51(W)},51:q(W){o 1s 3Y(W).3I(C,q(1q,1G){1q.6n(1G.1w,1G.I);o 1q})},4q:q(){o C.2O(q(1G){G 1w=aW(1G.1w),1T=1G.I;E(1T&&3X 1T==\'W\'){E(M.4r(1T))o 1T.2O(8A.75(1w)).2s(\'&\')}o 8A(1w,1T)}).2s(\'&\')},2z:q(){o\'#<3Y:{\'+C.2O(q(1G){o 1G.2O(M.2z).2s(\': \')}).2s(\', \')+\'}>\'},3p:q(){o M.3p(C.6m())},2C:q(){o 1s 3Y(C)}}})());3Y.1l.8r=3Y.1l.6m;3Y.aN=$H;G aX=2b.2o(2I,{2G:q(4j,52,5F){C.4j=4j;C.52=52;C.5F=5F},4h:q(Y){G I=C.4j;1O(C.1L(I)){Y(I);I=I.8i()}},1L:q(I){E(I<C.4j)o 1r;E(C.5F)o I<C.52;o I<=C.52}});G $R=q(4j,52,5F){o 1s aX(4j,52,5F)};G 1R={aY:q(){o ab.ac(q(){o 1s aZ()},q(){o 1s b0(\'e5.b1\')},q(){o 1s b0(\'e6.b1\')})||1r},8D:0};1R.5G={6o:[],4h:q(Y){C.6o.4h(Y)},b2:q(4k){E(!C.1L(4k))C.6o.1h(4k)},e7:q(4k){C.6o=C.6o.6l(4k)},7f:q(2W,2R,1X,3k){C.1E(q(4k){E(M.2p(4k[2W])){2q{4k[2W].3G(4k,[2R,1X,3k])}2B(e){}}})}};M.15(1R.5G,2I);1R.5G.b2({7g:q(){1R.8D++},3J:q(){1R.8D--}});1R.8E=2b.2o({2G:q(U){C.U={1D:\'6p\',7h:1u,6q:\'7i/x-e8-1x-e9\',8F:\'ea-8\',3x:\'\',5x:1u,8G:1u};M.15(C.U,U||{});C.U.1D=C.U.1D.2d();E(M.3f(C.U.3x))C.U.3x=C.U.3x.7b();1m E(M.8a(C.U.3x))C.U.3x=C.U.3x.6m()}});1R.53=2b.2o(1R.8E,{8H:1r,2G:q($49,2S,U){$49(U);C.1X=1R.aY();C.2R(2S)},2R:q(2S){C.2S=2S;C.1D=C.U.1D;G 2Z=M.2C(C.U.3x);E(![\'8B\',\'6p\'].1L(C.1D)){2Z[\'eb\']=C.1D;C.1D=\'6p\'}C.3x=2Z;E(2Z=M.4q(2Z)){E(C.1D==\'8B\')C.2S+=(C.2S.1L(\'?\')?\'&\':\'?\')+2Z;1m E(/ec|a3|a1/.2N(4P.4Q))2Z+=\'&6g=\'}2q{G 2v=1s 1R.8I(C);E(C.U.7g)C.U.7g(2v);1R.5G.7f(\'7g\',C,2v);C.1X.ed(C.1D.2Q(),C.2S,C.U.7h);E(C.U.7h)C.8J.1J(C).4u(1);C.1X.7j=C.8K.1J(C);C.b3();C.2w=C.1D==\'6p\'?(C.U.ee||2Z):1j;C.1X.ef(C.2w);E(!C.U.7h&&C.1X.b4)C.8K()}2B(e){C.54(e)}},8K:q(){G 2T=C.1X.2T;E(2T>1&&!((2T==4)&&C.8H))C.8J(C.1X.2T)},b3:q(){G 55={\'X-eg-eh\':\'aZ\',\'X-1g-86\':1g.86,\'ei\':\'42/ej, 42/7k, 7i/6r, 42/6r, */*\'};E(C.1D==\'6p\'){55[\'8L-1B\']=C.U.6q+(C.U.8F?\'; ek=\'+C.U.8F:\'\');E(C.1X.b4&&(4P.4Q.1f(/70\\/(\\d{4})/)||[0,b5])[1]<b5)55[\'el\']=\'em\'}E(3X C.U.b6==\'W\'){G 5H=C.U.b6;E(M.2p(5H.1h))17(G i=0,O=5H.O;i<O;i+=2)55[5H[i]]=5H[i+1];1m $H(5H).1E(q(1G){55[1G.1w]=1G.I})}17(G 1e 1Q 55)C.1X.eo(1e,55[1e])},56:q(){G 4z=C.6s();o!4z||(4z>=ep&&4z<eq)},6s:q(){2q{o C.1X.4z||0}2B(e){o 0}},8J:q(2T){G 6t=1R.53.b7[2T],2v=1s 1R.8I(C);E(6t==\'8M\'){2q{C.8H=1u;(C.U[\'5I\'+2v.4z]||C.U[\'5I\'+(C.56()?\'er\':\'es\')]||1g.3o)(2v,2v.7l)}2B(e){C.54(e)}G 6q=2v.5J(\'8L-1B\');E(C.U.8G==\'b8\'||(C.U.8G&&C.7m()&&6q&&6q.1f(/^\\s*(42|7i)\\/(x-)?(et|eu)4S(;.*)?\\s*$/i)))C.b9()}2q{(C.U[\'5I\'+6t]||1g.3o)(2v,2v.7l);1R.5G.7f(\'5I\'+6t,C,2v,2v.7l)}2B(e){C.54(e)}E(6t==\'8M\'){C.1X.7j=1g.3o}},7m:q(){G m=C.2S.1f(/^\\s*ev?:\\/\\/[^\\/]*/);o!m||(m[0]==\'#{8N}//#{8O}#{7n}\'.aA({8N:7o.8N,8O:1b.8O,7n:7o.7n?\':\'+7o.7n:\'\'}))},5J:q(1e){2q{o C.1X.8P(1e)||1j}2B(e){o 1j}},b9:q(){2q{o 78((C.1X.31||\'\').8o())}2B(e){C.54(e)}},54:q(8Q){(C.U.ba||1g.3o)(C,8Q);1R.5G.7f(\'ba\',C,8Q)}});1R.53.b7=[\'ew\',\'ex\',\'ey\',\'ez\',\'8M\'];1R.8I=2b.2o({2G:q(2R){C.2R=2R;G 1X=C.1X=2R.1X,2T=C.2T=1X.2T;E((2T>2&&!1g.1V.3T)||2T==4){C.4z=C.6s();C.8R=C.bb();C.31=24.5r(1X.31);C.7l=C.bc()}E(2T==4){G 6r=1X.bd;C.bd=M.2A(6r)?1j:6r;C.eA=C.be()}},4z:0,8R:\'\',6s:1R.53.1l.6s,bb:q(){2q{o C.1X.8R||\'\'}2B(e){o\'\'}},5J:1R.53.1l.5J,eB:q(){2q{o C.8S()}2B(e){o 1j}},8P:q(1e){o C.1X.8P(1e)},8S:q(){o C.1X.8S()},bc:q(){G 3k=C.5J(\'X-ay\');E(!3k)o 1j;3k=8h(ae(3k));2q{o 3k.5x(C.2R.U.bf||!C.2R.7m())}2B(e){C.2R.54(e)}},be:q(){G U=C.2R.U;E(!U.5x||(U.5x!=\'b8\'&&!(C.5J(\'8L-1B\')||\'\').1L(\'7i/3k\'))||C.31.4Y())o 1j;2q{o C.31.5x(U.bf||!C.2R.7m())}2B(e){C.2R.54(e)}}});1R.bg=2b.2o(1R.53,{2G:q($49,3y,2S,U){C.3y={56:(3y.56||3y),8T:(3y.8T||(3y.56?1j:3y))};U=M.2C(U);G 3J=U.3J;U.3J=(q(2v,3k){C.bh(2v.31);E(M.2p(3J))3J(2v,3k)}).1J(C);$49(2S,U)},bh:q(31){G 5K=C.3y[C.56()?\'56\':\'8T\'],U=C.U;E(!U.4X)31=31.4f();E(5K=$(5K)){E(U.57){E(M.3f(U.57)){G 57={};57[U.57]=31;5K.3z(57)}1m U.57(5K,31)}1m 5K.51(31)}}});1R.eC=2b.2o(1R.8E,{2G:q($49,3y,2S,U){$49(U);C.3J=C.U.3J;C.4e=(C.U.4e||2);C.58=(C.U.58||1);C.8U={};C.3y=3y;C.2S=2S;C.4j()},4j:q(){C.U.3J=C.bi.1J(C);C.6e()},8f:q(){C.8U.U.3J=4o;eD(C.41);(C.3J||1g.3o).3G(C,1p)},bi:q(2v){E(C.U.58){C.58=(2v.31==C.bj?C.58*C.U.58:1);C.bj=2v.31}C.41=C.6e.1J(C).8c(C.58*C.4e)},6e:q(){C.8U=1s 1R.bg(C.3y,C.2S,C.U)}});q $(k){E(1p.O>1){17(G i=0,1Y=[],O=1p.O;i<O;i++)1Y.1h($(1p[i]));o 1Y}E(M.3f(k))k=1b.eE(k);o J.15(k)}E(1g.3V.71){1b.8V=q(1t,7p){G V=[];G 8W=1b.2L(1t,$(7p)||1b,1j,eF.eG,1j);17(G i=0,O=8W.eH;i<O;i++)V.1h(J.15(8W.eI(i)));o V}}E(!1A.6u)G 6u={};E(!6u.bk){M.15(6u,{bk:1,eJ:2,bl:3,eK:4,eL:5,eM:6,eN:7,eO:8,eP:9,eQ:10,eR:11,eS:12})}(q(){G k=C.J;C.J=q(1a,2j){2j=2j||{};1a=1a.2d();G 2U=J.2U;E(1g.1V.3T&&2j.1e){1a=\'<\'+1a+\' 1e="\'+2j.1e+\'">\';8C 2j.1e;o J.6v(1b.3W(1a),2j)}E(!2U[1a])2U[1a]=J.15(1b.3W(1a));o J.6v(2U[1a].eT(1r),2j)};M.15(C.J,k||{})}).8X(1A);J.2U={};J.1d={8Y:q(k){o $(k).14.3A!=\'7q\'},bm:q(k){k=$(k);J[J.8Y(k)?\'bn\':\'bo\'](k);o k},bn:q(k){$(k).14.3A=\'7q\';o k},bo:q(k){$(k).14.3A=\'\';o k},bp:q(k){k=$(k);k.1P.6w(k);o k},51:q(k,18){k=$(k);E(18&&18.3B)18=18.3B();E(M.4a(18))o k.51().3z(18);18=M.4b(18);k.4w=18.4f();18.4X.1J(18).4u();o k},1W:q(k,18){k=$(k);E(18&&18.3B)18=18.3B();1m E(!M.4a(18)){18=M.4b(18);G 8Z=k.eU.eV();8Z.eW(k);18.4X.1J(18).4u();18=8Z.eX(18.4f())}k.1P.90(18,k);o k},3z:q(k,3K){k=$(k);E(M.3f(3K)||M.4W(3K)||M.4a(3K)||(3K&&(3K.3B||3K.4b)))3K={59:3K};G 18,3z,1a,3j;17(G 1v 1Q 3K){18=3K[1v];1v=1v.2d();3z=J.5L[1v];E(18&&18.3B)18=18.3B();E(M.4a(18)){3z(k,18);3L}18=M.4b(18);1a=((1v==\'4Z\'||1v==\'7r\')?k.1P:k).1a.2Q();3j=J.7s(1a,18.4f());E(1v==\'2k\'||1v==\'7r\')3j.4i();3j.1E(3z.75(k));18.4X.1J(18).4u()}o k},4U:q(k,1K,2j){k=$(k);E(M.4a(1K))$(1K).6v(2j||{});1m E(M.3f(1K))1K=1s J(1K,2j);1m 1K=1s J(\'1S\',1K);E(k.1P)k.1P.90(1K,k);1K.5A(k);o 1K},2z:q(k){k=$(k);G 1q=\'<\'+k.1a.2d();$H({\'1o\':\'1o\',\'1k\':\'6x\'}).1E(q(1G){G 1y=1G.3H(),1U=1G.2u();G I=(k[1y]||\'\').2H();E(I)1q+=\' \'+1U+\'=\'+I.2z(1u)});o 1q+\'>\'},7t:q(k,1y){k=$(k);G 1Y=[];1O(k=k[1y])E(k.3q==1)1Y.1h(J.15(k));o 1Y},5M:q(k){o $(k).7t(\'1P\')},bq:q(k){o $(k).2E("*")},br:q(k){k=$(k).5N;1O(k&&k.3q!=1)k=k.3M;o $(k)},bs:q(k){E(!(k=$(k).5N))o[];1O(k&&k.3q!=1)k=k.3M;E(k)o[k].21($(k).4A());o[]},5O:q(k){o $(k).7t(\'bt\')},4A:q(k){o $(k).7t(\'3M\')},eY:q(k){k=$(k);o k.5O().4i().21(k.4A())},1f:q(k,43){E(M.3f(43))43=1s 19(43);o 43.1f($(k))},eZ:q(k,1t,1i){k=$(k);E(1p.O==1)o $(k.1P);G 5M=k.5M();o M.4W(1t)?5M[1t]:19.5P(5M,1t,1i)},f0:q(k,1t,1i){k=$(k);E(1p.O==1)o k.br();o M.4W(1t)?k.bq()[1t]:k.2E(1t)[1i||0]},f1:q(k,1t,1i){k=$(k);E(1p.O==1)o $(19.26.6y(k));G 5O=k.5O();o M.4W(1t)?5O[1t]:19.5P(5O,1t,1i)},6z:q(k,1t,1i){k=$(k);E(1p.O==1)o $(19.26.6A(k));G 4A=k.4A();o M.4W(1t)?4A[1t]:19.5P(4A,1t,1i)},2E:q(){G 20=$A(1p),k=$(20.4T());o 19.7u(k,20)},5a:q(){G 20=$A(1p),k=$(20.4T());o 19.7u(k.1P,20).6l(k)},bu:q(k){k=$(k);G 1o=k.5b(\'1o\'),5v=1p.5t;E(1o)o 1o;do{1o=\'f2\'+5v.bv++}1O($(1o));k.6v(\'1o\',1o);o 1o},5b:q(k,1e){k=$(k);E(1g.1V.3T){G t=J.3N.7v;E(t.1T[1e])o t.1T[1e](k,1e);E(t.3r[1e])1e=t.3r[1e];E(1e.1L(\':\')){o(!k.2j||!k.2j[1e])?1j:k.2j[1e].I}}o k.91(1e)},6v:q(k,1e,I){k=$(k);G 2j={},t=J.3N.6B;E(3X 1e==\'W\')2j=1e;1m 2j[1e]=M.2A(I)?1u:I;17(G 29 1Q 2j){1e=t.3r[29]||29;I=2j[29];E(t.1T[29])1e=t.1T[29](k,I);E(I===1r||I===1j)k.92(1e);1m E(I===1u)k.bw(1e,1e);1m k.bw(1e,I)}o k},bx:q(k){o $(k).5Q().32},by:q(k){o $(k).5Q().2f},6C:q(k){o 1s J.7w(k)},7x:q(k,1k){E(!(k=$(k)))o;G 7y=k.1k;o(7y.O>0&&(7y==1k||1s 4d("(^|\\\\s)"+1k+"(\\\\s|$)").2N(7y)))},bz:q(k,1k){E(!(k=$(k)))o;E(!k.7x(1k))k.1k+=(k.1k?\' \':\'\')+1k;o k},bA:q(k,1k){E(!(k=$(k)))o;k.1k=k.1k.1W(1s 4d("(^|\\\\s+)"+1k+"(\\\\s+|$)"),\' \').3Z();o k},f3:q(k,1k){E(!(k=$(k)))o;o k[k.7x(1k)?\'bA\':\'bz\'](1k)},f4:q(k){k=$(k);G L=k.5N;1O(L){G bB=L.3M;E(L.3q==3&&!/\\S/.2N(L.4g))k.6w(L);L=bB}o k},5y:q(k){o $(k).4w.4Y()},7z:q(k,2V){k=$(k),2V=$(2V);G bC=2V;E(k.bD)o(k.bD(2V)&8)===8;E(k.6D&&!1g.1V.4O){G e=k.6D,a=2V.6D,5R=2V.3M;E(!5R){do{2V=2V.1P}1O(!(5R=2V.3M)&&2V.1P)}E(5R&&5R.6D)o(e>a&&e<5R.6D)}1O(k=k.1P)E(k==bC)o 1u;o 1r},bE:q(k){k=$(k);G 5S=k.5c();1A.bE(5S[0],5S[1]);o k},2a:q(k,14){k=$(k);14=14==\'93\'?\'7A\':14.8j();G I=k.14[14];E(!I){G 94=1b.f5.f6(k,1j);I=94?94[14]:1j}E(14==\'3O\')o I?5T(I):1.0;o I==\'7B\'?1j:I},f7:q(k){o $(k).2a(\'3O\')},5U:q(k,4B){k=$(k);G 95=k.14,1f;E(M.3f(4B)){k.14.96+=\';\'+4B;o 4B.1L(\'3O\')?k.5V(4B.1f(/3O:\\s*(\\d?\\.?\\d*)/)[1]):k}17(G 1y 1Q 4B)E(1y==\'3O\')k.5V(4B[1y]);1m 95[(1y==\'93\'||1y==\'7A\')?(M.2A(95.97)?\'7A\':\'97\'):1y]=4B[1y];o k},5V:q(k,I){k=$(k);k.14.3O=(I==1||I===\'\')?\'\':(I<0.7C)?0:I;o k},5Q:q(k){k=$(k);G 3A=$(k).2a(\'3A\');E(3A!=\'7q\'&&3A!=1j)o{2f:k.5W,32:k.5X};G 44=k.14;G bF=44.98;G bG=44.1v;G bH=44.3A;44.98=\'7D\';44.1v=\'5Y\';44.3A=\'f8\';G bI=k.bJ;G bK=k.bL;44.3A=bH;44.1v=bG;44.98=bF;o{2f:bI,32:bK}},f9:q(k){k=$(k);G 5S=J.2a(k,\'1v\');E(5S==\'5Z\'||!5S){k.99=1u;k.14.1v=\'6E\';E(1A.87){k.14.2k=0;k.14.2t=0}}o k},fa:q(k){k=$(k);E(k.99){k.99=4o;k.14.1v=k.14.2k=k.14.2t=k.14.59=k.14.5D=\'\'}o k},fb:q(k){k=$(k);E(k.5d)o k;k.5d=J.2a(k,\'9a\')||\'7B\';E(k.5d!==\'7D\')k.14.9a=\'7D\';o k},fc:q(k){k=$(k);E(!k.5d)o k;k.14.9a=k.5d==\'7B\'?\'\':k.5d;k.5d=1j;o k},5c:q(k){G 2J=0,2K=0;do{2J+=k.5e||0;2K+=k.5f||0;k=k.3l}1O(k);o J.5g(2K,2J)},6F:q(k){G 2J=0,2K=0;do{2J+=k.5e||0;2K+=k.5f||0;k=k.3l;E(k){E(k.1a==\'bM\')2c;G p=J.2a(k,\'1v\');E(p!==\'5Z\')2c}}1O(k);o J.5g(2K,2J)},9b:q(k){k=$(k);E(k.2a(\'1v\')==\'5Y\')o;G 9c=k.6F();G 2k=9c[1];G 2t=9c[0];G 2f=k.bJ;G 32=k.bL;k.bN=2t-5T(k.14.2t||0);k.bO=2k-5T(k.14.2k||0);k.bP=k.14.2f;k.bQ=k.14.32;k.14.1v=\'5Y\';k.14.2k=2k+\'3m\';k.14.2t=2t+\'3m\';k.14.2f=2f+\'3m\';k.14.32=32+\'3m\';o k},9d:q(k){k=$(k);E(k.2a(\'1v\')==\'6E\')o;k.14.1v=\'6E\';G 2k=5T(k.14.2k||0)-(k.bO||0);G 2t=5T(k.14.2t||0)-(k.bN||0);k.14.2k=2k+\'3m\';k.14.2t=2t+\'3m\';k.14.32=k.bQ;k.14.2f=k.bP;o k},9e:q(k){G 2J=0,2K=0;do{2J+=k.4C||0;2K+=k.4D||0;k=k.1P}1O(k);o J.5g(2K,2J)},60:q(k){E(k.3l)o $(k.3l);E(k==1b.2w)o $(k);1O((k=k.1P)&&k!=1b.2w)E(J.2a(k,\'1v\')!=\'5Z\')o $(k);o $(1b.2w)},6G:q(9f){G 2J=0,2K=0;G k=9f;do{2J+=k.5e||0;2K+=k.5f||0;E(k.3l==1b.2w&&J.2a(k,\'1v\')==\'5Y\')2c}1O(k=k.3l);k=9f;do{E(!1g.1V.4O||k.1a==\'bM\'){2J-=k.4C||0;2K-=k.4D||0}}1O(k=k.1P);o J.5g(2K,2J)},bR:q(k,22){G U=M.15({bS:1u,bT:1u,bU:1u,bV:1u,5e:0,5f:0},1p[2]||{});22=$(22);G p=22.6G();k=$(k);G 61=[0,0];G 2M=1j;E(J.2a(k,\'1v\')==\'5Y\'){2M=k.60();61=2M.6G()}E(2M==1b.2w){61[0]-=1b.2w.5f;61[1]-=1b.2w.5e}E(U.bS)k.14.2t=(p[0]-61[0]+U.5f)+\'3m\';E(U.bT)k.14.2k=(p[1]-61[1]+U.5e)+\'3m\';E(U.bU)k.14.2f=22.5W+\'3m\';E(U.bV)k.14.32=22.5X+\'3m\';o k}};J.1d.bu.bv=1;M.15(J.1d,{fd:J.1d.2E,fe:J.1d.bs});J.3N={6B:{3r:{1k:\'6x\',bW:\'17\'},1T:{}}};E(1g.1V.4O){J.1d.2a=J.1d.2a.4U(q(3n,k,14){5q(14){2r\'2t\':2r\'2k\':2r\'5D\':2r\'59\':E(3n(k,\'1v\')===\'5Z\')o 1j;2r\'32\':2r\'2f\':E(!J.8Y(k))o 1j;G 7E=bX(3n(k,14),10);E(7E!==k[\'3a\'+14.6f()])o 7E+\'3m\';G 3e;E(14===\'32\'){3e=[\'7F-2k-2f\',\'7G-2k\',\'7G-59\',\'7F-59-2f\']}1m{3e=[\'7F-2t-2f\',\'7G-2t\',\'7G-5D\',\'7F-5D-2f\']}o 3e.3I(7E,q(2P,1y){G 9g=3n(k,1y);o 9g===1j?2P:2P-bX(9g,10)})+\'3m\';6H:o 3n(k,14)}});J.1d.5b=J.1d.5b.4U(q(3n,k,1U){E(1U===\'7H\')o k.7H;o 3n(k,1U)})}1m E(1g.1V.3T){J.1d.60=J.1d.60.4U(q(3n,k){k=$(k);G 1v=k.2a(\'1v\');E(1v!==\'5Z\')o 3n(k);k.5U({1v:\'6E\'});G I=3n(k);k.5U({1v:1v});o I});$w(\'6F 6G\').1E(q(1D){J.1d[1D]=J.1d[1D].4U(q(3n,k){k=$(k);G 1v=k.2a(\'1v\');E(1v!==\'5Z\')o 3n(k);G 3l=k.60();E(3l&&3l.2a(\'1v\')===\'ff\')3l.5U({9h:1});k.5U({1v:\'6E\'});G I=3n(k);k.5U({1v:1v});o I})});J.1d.2a=q(k,14){k=$(k);14=(14==\'93\'||14==\'7A\')?\'97\':14.8j();G I=k.14[14];E(!I&&k.5h)I=k.5h[14];E(14==\'3O\'){E(I=(k.2a(\'2e\')||\'\').1f(/9i\\(3O=(.*)\\)/))E(I[1])o 5T(I[1])/bY;o 1.0}E(I==\'7B\'){E((14==\'2f\'||14==\'32\')&&(k.2a(\'3A\')!=\'7q\'))o k[\'3a\'+14.6f()]+\'3m\';o 1j}o I};J.1d.5V=q(k,I){q 9j(2e){o 2e.1W(/9i\\([^\\)]*\\)/gi,\'\')}k=$(k);G 5h=k.5h;E((5h&&!5h.fg)||(!5h&&k.14.9h==\'fh\'))k.14.9h=1;G 2e=k.2a(\'2e\'),14=k.14;E(I==1||I===\'\'){(2e=9j(2e))?14.2e=2e:14.92(\'2e\');o k}1m E(I<0.7C)I=0;14.2e=9j(2e)+\'9i(3O=\'+(I*bY)+\')\';o k};J.3N={7v:{3r:{\'6x\':\'1k\',\'17\':\'bW\'},1T:{7I:q(k,1U){o k.91(1U,2)},bZ:q(k,1U){G L=k.c0(1U);o L?L.I:""},2l:q(k,1U){1U=k.91(1U);o 1U?1U.2H().3t(23,-2):1j},6I:q(k,1U){o $(k).3P(1U)?1U:1j},14:q(k){o k.14.96.2d()},7H:q(k){o k.7H}}}};J.3N.6B={3r:M.15({fi:\'fj\',fk:\'fl\'},J.3N.7v.3r),1T:{3Q:q(k,I){k.3Q=!!I},14:q(k,I){k.14.96=I?I:\'\'}}};J.3N.9k={};$w(\'fm fn fo fp fq 7J \'+\'fr fs ft fu\').1E(q(29){J.3N.6B.3r[29.2d()]=29;J.3N.9k[29.2d()]=29});(q(v){M.15(v,{c1:v.7I,c2:v.7I,1B:v.7I,62:v.bZ,3C:v.6I,3Q:v.6I,fv:v.6I,fw:v.6I,fx:v.2l,c3:v.2l,fy:v.2l,fz:v.2l,fA:v.2l,fB:v.2l,fC:v.2l,fD:v.2l,fE:v.2l,fF:v.2l,fG:v.2l,fH:v.2l,fI:v.2l,fJ:v.2l,fK:v.2l,fL:v.2l,fM:v.2l,fN:v.2l})})(J.3N.7v.1T)}1m E(1g.1V.70&&/fO:1\\.8\\.0/.2N(4P.4Q)){J.1d.5V=q(k,I){k=$(k);k.14.3O=(I==1)?0.fP:(I===\'\')?\'\':(I<0.7C)?0:I;o k}}1m E(1g.1V.4n){J.1d.5V=q(k,I){k=$(k);k.14.3O=(I==1||I===\'\')?\'\':(I<0.7C)?0:I;E(I==1)E(k.1a==\'c4\'&&k.2f){k.2f++;k.2f--}1m 2q{G n=1b.aD(\' \');k.5A(n);k.6w(n)}2B(e){}o k};J.1d.5c=q(k){G 2J=0,2K=0;do{2J+=k.5e||0;2K+=k.5f||0;E(k.3l==1b.2w)E(J.2a(k,\'1v\')==\'5Y\')2c;k=k.3l}1O(k);o J.5g(2K,2J)}}E(1g.1V.3T||1g.1V.4O){J.1d.51=q(k,18){k=$(k);E(18&&18.3B)18=18.3B();E(M.4a(18))o k.51().3z(18);18=M.4b(18);G 1a=k.1a.2Q();E(1a 1Q J.5L.4E){$A(k.3j).1E(q(L){k.6w(L)});J.7s(1a,18.4f()).1E(q(L){k.5A(L)})}1m k.4w=18.4f();18.4X.1J(18).4u();o k}}E(\'c5\'1Q 1b.3W(\'1S\')){J.1d.1W=q(k,18){k=$(k);E(18&&18.3B)18=18.3B();E(M.4a(18)){k.1P.90(18,k);o k}18=M.4b(18);G 2M=k.1P,1a=2M.1a.2Q();E(J.5L.4E[1a]){G 3M=k.6z();G 9l=J.7s(1a,18.4f());2M.6w(k);E(3M)9l.1E(q(L){2M.7K(L,3M)});1m 9l.1E(q(L){2M.5A(L)})}1m k.c5=18.4f();18.4X.1J(18).4u();o k}}J.5g=q(l,t){G 1q=[l,t];1q.2t=l;1q.2k=t;o 1q};J.7s=q(1a,7k){G 1S=1s J(\'1S\'),t=J.5L.4E[1a];E(t){1S.4w=t[0]+7k+t[1];t[2].7c(q(){1S=1S.5N})}1m 1S.4w=7k;o $A(1S.3j)};J.5L={4Z:q(k,L){k.1P.7K(L,k)},2k:q(k,L){k.7K(L,k.5N)},59:q(k,L){k.5A(L)},7r:q(k,L){k.1P.7K(L,k.3M)},4E:{fQ:[\'<4F>\',\'</4F>\',1],7L:[\'<4F><63>\',\'</63></4F>\',2],c6:[\'<4F><63><7M>\',\'</7M></63></4F>\',3],9m:[\'<4F><63><7M><c7>\',\'</c7></7M></63></4F>\',4],c8:[\'<2E>\',\'</2E>\',1]}};(q(){M.15(C.4E,{c9:C.4E.7L,ca:C.4E.7L,cb:C.4E.9m})}).8X(J.5L);J.1d.7N={3P:q(k,1U){1U=J.3N.9k[1U]||1U;G L=$(k).c0(1U);o L&&L.fR}};J.1d.3D={};M.15(J,J.1d);E(!1g.3V.6a&&1b.3W(\'1S\').4R){1A.6b={};1A.6b.1l=1b.3W(\'1S\').4R;1g.3V.6a=1u}J.15=(q(){E(1g.3V.72)o 1g.K;G 1d={},3D=J.1d.3D;G 15=M.15(q(k){E(!k||k.7O||k.3q!=1||k==1A)o k;G 2F=M.2C(1d),1a=k.1a,1y,I;E(3D[1a])M.15(2F,3D[1a]);17(1y 1Q 2F){I=2F[1y];E(M.2p(I)&&!(1y 1Q k))k[1y]=I.4t()}k.7O=1g.3o;o k},{7P:q(){E(!1g.3V.6a){M.15(1d,J.1d);M.15(1d,J.1d.7N)}}});15.7P();o 15})();J.3P=q(k,1U){E(k.3P)o k.3P(1U);o J.1d.7N.3P(k,1U)};J.6c=q(2F){G F=1g.3V,T=J.1d.3D;E(!2F){M.15(1C,1C.1d);M.15(1C.J,1C.J.1d);M.15(J.1d.3D,{"fS":M.2C(1C.1d),"fT":M.2C(1C.J.1d),"c8":M.2C(1C.J.1d),"cc":M.2C(1C.J.1d)})}E(1p.O==2){G 1a=2F;2F=1p[1]}E(!1a)M.15(J.1d,2F||{});1m{E(M.4r(1a))1a.1E(15);1m 15(1a)}q 15(1a){1a=1a.2Q();E(!J.1d.3D[1a])J.1d.3D[1a]={};M.15(J.1d.3D[1a],2F)}q 7Q(2F,5p,7R){7R=7R||1r;17(G 1y 1Q 2F){G I=2F[1y];E(!M.2p(I))3L;E(!7R||!(1y 1Q 5p))5p[1y]=I.4t()}}q cd(1a){G 1N;G 9n={"fU":"fV","cc":"fW","P":"fX","fY":"fZ","g0":"g1","g2":"g3","g4":"g5","g6":"g7","g8":"64","g9":"64","ga":"64","gb":"64","gc":"64","gd":"64","Q":"ge","gf":"ce","gg":"ce","A":"gh","c4":"gj","gk":"gl","gm":"cf","gn":"cf","c9":"9o","ca":"9o","7L":"9o","c6":"go","cb":"cg","9m":"cg","gp":"gq","gr":"gs"};E(9n[1a])1N=\'9p\'+9n[1a]+\'J\';E(1A[1N])o 1A[1N];1N=\'9p\'+1a+\'J\';E(1A[1N])o 1A[1N];1N=\'9p\'+1a.6f()+\'J\';E(1A[1N])o 1A[1N];1A[1N]={};1A[1N].1l=1b.3W(1a).4R;o 1A[1N]}E(F.6a){7Q(J.1d,6b.1l);7Q(J.1d.7N,6b.1l,1u)}E(F.72){17(G 9q 1Q J.1d.3D){G 1N=cd(9q);E(M.2A(1N))3L;7Q(T[9q],1N.1l)}}M.15(J,J.1d);8C J.3D;E(J.15.7P)J.15.7P();J.2U={}};1b.gu={5Q:q(){G 9r={};G B=1g.1V;$w(\'2f 32\').1E(q(d){G D=d.6f();9r[d]=(B.4n&&!1b.2L)?5v[\'gv\'+D]:(B.4O)?1b.2w[\'ch\'+D]:1b.4G[\'ch\'+D]});o 9r},by:q(){o C.5Q().2f},bx:q(){o C.5Q().32},gw:q(){o J.5g(1A.ci||1b.4G.4D||1b.2w.4D,1A.cj||1b.4G.4C||1b.2w.4C)}};G 19=2b.2o({2G:q(1t){C.1t=1t.3Z();C.ck()},cl:q(){E(!1g.3V.71)o 1r;G e=C.1t;E(1g.1V.4n&&(e.1L("-2x-1B")||e.1L(":5y")))o 1r;E((/(\\[[\\w-]*?:|:3Q)/).2N(C.1t))o 1r;o 1u},ck:q(){E(C.cl())o C.cm();G e=C.1t,4l=19.6J,h=19.26,c=19.6k,3E,p,m;E(19.5i[e]){C.3R=19.5i[e];o}C.3R=["C.3R = q(1n) {","G r = 1n, h = 19.26, c = 1r, n;"];1O(e&&3E!=e&&(/\\S/).2N(e)){3E=e;17(G i 1Q 4l){p=4l[i];E(m=e.1f(p)){C.3R.1h(M.2p(c[i])?c[i](m):1s 2X(c[i]).2L(m));e=e.1W(m[0],\'\');2c}}}C.3R.1h("o h.9s(n);\\n}");78(C.3R.2s(\'\\n\'));19.5i[C.1t]=C.3R},cm:q(){G e=C.1t,4l=19.6J,x=19.2y,3E,m;E(19.5i[e]){C.2y=19.5i[e];o}C.3R=[\'.//*\'];1O(e&&3E!=e&&(/\\S/).2N(e)){3E=e;17(G i 1Q 4l){E(m=e.1f(4l[i])){C.3R.1h(M.2p(x[i])?x[i](m):1s 2X(x[i]).2L(m));e=e.1W(m[0],\'\');2c}}}C.2y=C.3R.2s(\'\');19.5i[C.1t]=C.2y},7S:q(1n){1n=1n||1b;E(C.2y)o 1b.8V(C.2y,1n);o C.3R(1n)},1f:q(k){C.9t=[];G e=C.1t,4l=19.6J,as=19.9u;G 3E,p,m;1O(e&&3E!==e&&(/\\S/).2N(e)){3E=e;17(G i 1Q 4l){p=4l[i];E(m=e.1f(p)){E(as[i]){C.9t.1h([i,M.2C(m)]);e=e.1W(m[0],\'\')}1m{o C.7S(1b).1L(k)}}}}G 1f=1u,1e,2m;17(G i=0,7T;7T=C.9t[i];i++){1e=7T[0],2m=7T[1];E(!19.9u[1e](k,2m)){1f=1r;2c}}o 1f},2H:q(){o C.1t},2z:q(){o"#<19:"+C.1t.2z()+">"}});M.15(19,{5i:{},2y:{4H:"//*",1H:"/*",5a:"/6K-4I::*[1]",6L:\'/6K-4I::*\',1a:q(m){E(m[1]==\'*\')o\'\';o"[co-1e()=\'"+m[1].2d()+"\' 9v co-1e()=\'"+m[1].2Q()+"\']"},1k:"[6M(21(\' \', @6x, \' \'), \' #{1} \')]",1o:"[@1o=\'#{1}\']",65:q(m){m[1]=m[1].2d();o 1s 2X("[@#{1}]").2L(m)},29:q(m){m[1]=m[1].2d();m[3]=m[5]||m[6];o 1s 2X(19.2y.6N[m[2]]).2L(m)},6O:q(m){G h=19.2y.2g[m[1]];E(!h)o\'\';E(M.2p(h))o h(m);o 1s 2X(19.2y.2g[m[1]]).2L(m)},6N:{\'=\':"[@#{1}=\'#{3}\']",\'!=\':"[@#{1}!=\'#{3}\']",\'^=\':"[gx-aE(@#{1}, \'#{3}\')]",\'$=\':"[5w(@#{1}, (3g-O(@#{1}) - 3g-O(\'#{3}\') + 1))=\'#{3}\']",\'*=\':"[6M(@#{1}, \'#{3}\')]",\'~=\':"[6M(21(\' \', @#{1}, \' \'), \' #{3} \')]",\'|=\':"[6M(21(\'-\', @#{1}, \'-\'), \'-#{3}-\')]"},2g:{\'3H-1H\':\'[4J(9w-4I::*)]\',\'2u-1H\':\'[4J(6K-4I::*)]\',\'6P-1H\':\'[4J(9w-4I::* 9v 6K-4I::*)]\',\'5y\':"[3u(*) = 0 9x (3u(42()) = 0 9v gy(42(), \' \\t\\r\\n\', \'\') = \'\')]",\'3Q\':"[@3Q]",\'3C\':"[@3C]",\'cp\':"[4J(@3C)]",\'4J\':q(m){G e=m[6],p=19.6J,x=19.2y,3E,v;G 9y=[];1O(e&&3E!=e&&(/\\S/).2N(e)){3E=e;17(G i 1Q p){E(m=e.1f(p[i])){v=M.2p(x[i])?x[i](m):1s 2X(x[i]).2L(m);9y.1h("("+v.5w(1,v.O-1)+")");e=e.1W(m[0],\'\');2c}}}o"[4J("+9y.2s(" 9x ")+")]"},\'1Z-1H\':q(m){o 19.2y.2g.1Z("(3u(./9w-4I::*) + 1) ",m)},\'1Z-2u-1H\':q(m){o 19.2y.2g.1Z("(3u(./6K-4I::*) + 1) ",m)},\'1Z-2x-1B\':q(m){o 19.2y.2g.1Z("1v() ",m)},\'1Z-2u-2x-1B\':q(m){o 19.2y.2g.1Z("(2u() + 1 - 1v()) ",m)},\'3H-2x-1B\':q(m){m[6]="1";o 19.2y.2g[\'1Z-2x-1B\'](m)},\'2u-2x-1B\':q(m){m[6]="1";o 19.2y.2g[\'1Z-2u-2x-1B\'](m)},\'6P-2x-1B\':q(m){G p=19.2y.2g;o p[\'3H-2x-1B\'](m)+p[\'2u-2x-1B\'](m)},1Z:q(66,m){G 47,1I=m[6],9z;E(1I==\'cq\')1I=\'2n+0\';E(1I==\'cr\')1I=\'2n+1\';E(47=1I.1f(/^(\\d+)$/))o\'[\'+66+"= "+47[1]+\']\';E(47=1I.1f(/^(-?\\d*)?n(([+-])(\\d+))?/)){E(47[1]=="-")47[1]=-1;G a=47[1]?50(47[1]):1;G b=47[2]?50(47[2]):0;9z="[((#{66} - #{b}) gz #{a} = 0) 9x "+"((#{66} - #{b}) 1S #{a} >= 0)]";o 1s 2X(9z).2L({66:66,a:a,b:b})}}}},6k:{1a:\'n = h.1a(n, r, "#{1}", c);      c = 1r;\',1k:\'n = h.1k(n, r, "#{1}", c);    c = 1r;\',1o:\'n = h.1o(n, r, "#{1}", c);           c = 1r;\',65:\'n = h.65(n, r, "#{1}", c); c = 1r;\',29:q(m){m[3]=(m[5]||m[6]);o 1s 2X(\'n = h.29(n, r, "#{1}", "#{3}", "#{2}", c); c = 1r;\').2L(m)},6O:q(m){E(m[6])m[6]=m[6].1W(/"/g,\'\\\\"\');o 1s 2X(\'n = h.6O(n, "#{1}", "#{6}", r, c); c = 1r;\').2L(m)},4H:\'c = "4H";\',1H:\'c = "1H";\',5a:\'c = "5a";\',6L:\'c = "6L";\'},6J:{6L:/^\\s*~\\s*/,1H:/^\\s*>\\s*/,5a:/^\\s*\\+\\s*/,4H:/^\\s/,1a:/^\\s*(\\*|[\\w\\-]+)(\\b|$)?/,1o:/^#([\\w\\-\\*]+)(\\b|$)/,1k:/^\\.([\\w\\-\\*]+)(\\b|$)/,6O:/^:((3H|2u|1Z|1Z-2u|6P)(-1H|-2x-1B)|5y|3Q|(en|gA)gB|4J)(\\((.*?)\\))?(\\b|$|(?=\\s|[:+~>]))/,65:/^\\[([\\w]+)\\]/,29:/\\[((?:[\\w-]*:)?[\\w-]+)\\s*(?:([!^$*~|]?=)\\s*(([\'"])([^\\4]*?)\\4|([^\'"][^\\]]*?)))?\\]/},9u:{1a:q(k,2m){o 2m[1].2Q()==k.1a.2Q()},1k:q(k,2m){o J.7x(k,2m[1])},1o:q(k,2m){o k.1o===2m[1]},65:q(k,2m){o J.3P(k,2m[1])},29:q(k,2m){G 4g=J.5b(k,2m[1]);o 4g&&19.6N[2m[2]](4g,2m[5]||2m[6])}},26:{21:q(a,b){17(G i=0,L;L=b[i];i++)a.1h(L);o a},7U:q(N){G cs=1g.3o;17(G i=0,L;L=N[i];i++)L.3S=cs;o N},5j:q(N){17(G i=0,L;L=N[i];i++)L.3S=4o;o N},1i:q(1P,4i,6Q){1P.3S=1g.3o;E(4i){17(G N=1P.3j,i=N.O-1,j=1;i>=0;i--){G L=N[i];E(L.3q==1&&(!6Q||L.3S))L.7V=j++}}1m{17(G i=0,j=1,N=1P.3j;L=N[i];i++)E(L.3q==1&&(!6Q||L.3S))L.7V=j++}},9s:q(N){E(N.O==0)o N;G V=[],n;17(G i=0,l=N.O;i<l;i++)E(!(n=N[i]).3S){n.3S=1g.3o;V.1h(J.15(n))}o 19.26.5j(V)},4H:q(N){G h=19.26;17(G i=0,V=[],L;L=N[i];i++)h.21(V,L.4m(\'*\'));o V},1H:q(N){G h=19.26;17(G i=0,V=[],L;L=N[i];i++){17(G j=0,1H;1H=L.3j[j];j++)E(1H.3q==1&&1H.1a!=\'!\')V.1h(1H)}o V},5a:q(N){17(G i=0,V=[],L;L=N[i];i++){G 6z=C.6A(L);E(6z)V.1h(6z)}o V},6L:q(N){G h=19.26;17(G i=0,V=[],L;L=N[i];i++)h.21(V,J.4A(L));o V},6A:q(L){1O(L=L.3M)E(L.3q==1)o L;o 1j},6y:q(L){1O(L=L.bt)E(L.3q==1)o L;o 1j},1a:q(N,1n,1a,28){G ct=1a.2Q();G V=[],h=19.26;E(N){E(28){E(28=="4H"){17(G i=0,L;L=N[i];i++)h.21(V,L.4m(1a));o V}1m N=C[28](N);E(1a=="*")o N}17(G i=0,L;L=N[i];i++)E(L.1a.2Q()===ct)V.1h(L);o V}1m o 1n.4m(1a)},1o:q(N,1n,1o,28){G 3b=$(1o),h=19.26;E(!3b)o[];E(!N&&1n==1b)o[3b];E(N){E(28){E(28==\'1H\'){17(G i=0,L;L=N[i];i++)E(3b.1P==L)o[3b]}1m E(28==\'4H\'){17(G i=0,L;L=N[i];i++)E(J.7z(3b,L))o[3b]}1m E(28==\'5a\'){17(G i=0,L;L=N[i];i++)E(19.26.6y(3b)==L)o[3b]}1m N=h[28](N)}17(G i=0,L;L=N[i];i++)E(L==3b)o[3b];o[]}o(3b&&J.7z(3b,1n))?[3b]:[]},1k:q(N,1n,1k,28){E(N&&28)N=C[28](N);o 19.26.cu(N,1n,1k)},cu:q(N,1n,1k){E(!N)N=19.26.4H([1n]);G cv=\' \'+1k+\' \';17(G i=0,V=[],L,6R;L=N[i];i++){6R=L.1k;E(6R.O==0)3L;E(6R==1k||(\' \'+6R+\' \').1L(cv))V.1h(L)}o V},65:q(N,1n,29,28){E(!N)N=1n.4m("*");E(N&&28)N=C[28](N);G V=[];17(G i=0,L;L=N[i];i++)E(J.3P(L,29))V.1h(L);o V},29:q(N,1n,29,I,cw,28){E(!N)N=1n.4m("*");E(N&&28)N=C[28](N);G 2h=19.6N[cw],V=[];17(G i=0,L;L=N[i];i++){G 4g=J.5b(L,29);E(4g===1j)3L;E(2h(4g,I))V.1h(L)}o V},6O:q(N,1e,I,1n,28){E(N&&28)N=C[28](N);E(!N)N=1n.4m("*");o 19.2g[1e](N,I,1n)}},2g:{\'3H-1H\':q(N,I,1n){17(G i=0,V=[],L;L=N[i];i++){E(19.26.6y(L))3L;V.1h(L)}o V},\'2u-1H\':q(N,I,1n){17(G i=0,V=[],L;L=N[i];i++){E(19.26.6A(L))3L;V.1h(L)}o V},\'6P-1H\':q(N,I,1n){G h=19.26;17(G i=0,V=[],L;L=N[i];i++)E(!h.6y(L)&&!h.6A(L))V.1h(L);o V},\'1Z-1H\':q(N,1I,1n){o 19.2g.1Z(N,1I,1n)},\'1Z-2u-1H\':q(N,1I,1n){o 19.2g.1Z(N,1I,1n,1u)},\'1Z-2x-1B\':q(N,1I,1n){o 19.2g.1Z(N,1I,1n,1r,1u)},\'1Z-2u-2x-1B\':q(N,1I,1n){o 19.2g.1Z(N,1I,1n,1u,1u)},\'3H-2x-1B\':q(N,1I,1n){o 19.2g.1Z(N,"1",1n,1r,1u)},\'2u-2x-1B\':q(N,1I,1n){o 19.2g.1Z(N,"1",1n,1u,1u)},\'6P-2x-1B\':q(N,1I,1n){G p=19.2g;o p[\'2u-2x-1B\'](p[\'3H-2x-1B\'](N,1I,1n),1I,1n)},cx:q(a,b,cy){E(a==0)o b>0?[b]:[];o $R(1,cy).3I([],q(2P,i){E(0==(i-b)%a&&(i-b)/a>=0)2P.1h(i);o 2P})},1Z:q(N,1I,1n,4i,6Q){E(N.O==0)o[];E(1I==\'cq\')1I=\'2n+0\';E(1I==\'cr\')1I=\'2n+1\';G h=19.26,V=[],9A=[],m;h.7U(N);17(G i=0,L;L=N[i];i++){E(!L.1P.3S){h.1i(L.1P,4i,6Q);9A.1h(L.1P)}}E(1I.1f(/^\\d+$/)){1I=50(1I);17(G i=0,L;L=N[i];i++)E(L.7V==1I)V.1h(L)}1m E(m=1I.1f(/^(-?\\d*)?n(([+-])(\\d+))?/)){E(m[1]=="-")m[1]=-1;G a=m[1]?50(m[1]):1;G b=m[2]?50(m[2]):0;G 9B=19.2g.cx(a,b,N.O);17(G i=0,L,l=9B.O;L=N[i];i++){17(G j=0;j<l;j++)E(L.7V==9B[j])V.1h(L)}}h.5j(N);h.5j(9A);o V},\'5y\':q(N,I,1n){17(G i=0,V=[],L;L=N[i];i++){E(L.1a==\'!\'||(L.5N&&!L.4w.1f(/^\\s*$/)))3L;V.1h(L)}o V},\'4J\':q(N,43,1n){G h=19.26,gC,m;G 9C=1s 19(43).7S(1n);h.7U(9C);17(G i=0,V=[],L;L=N[i];i++)E(!L.3S)V.1h(L);h.5j(9C);o V},\'cp\':q(N,I,1n){17(G i=0,V=[],L;L=N[i];i++)E(!L.3C)V.1h(L);o V},\'3C\':q(N,I,1n){17(G i=0,V=[],L;L=N[i];i++)E(L.3C)V.1h(L);o V},\'3Q\':q(N,I,1n){17(G i=0,V=[],L;L=N[i];i++)E(L.3Q)V.1h(L);o V}},6N:{\'=\':q(3c,v){o 3c==v},\'!=\':q(3c,v){o 3c!=v},\'^=\':q(3c,v){o 3c.8p(v)},\'$=\':q(3c,v){o 3c.az(v)},\'*=\':q(3c,v){o 3c.1L(v)},\'~=\':q(3c,v){o(\' \'+3c+\' \').1L(\' \'+v+\' \')},\'|=\':q(3c,v){o(\'-\'+3c.2Q()+\'-\').1L(\'-\'+v.2Q()+\'-\')}},4c:q(1t){G 4K=[];1t.ak(/(([\\w#:.~>+()\\s-]+|\\*|\\[.*?\\])+)\\s*(,|$)/,q(m){4K.1h(m[1].3Z())});o 4K},cz:q(1Y,1t){G 2m=$$(1t),h=19.26;h.7U(2m);17(G i=0,V=[],k;k=1Y[i];i++)E(k.3S)V.1h(k);h.5j(2m);o V},5P:q(1Y,1t,1i){E(M.4W(1t)){1i=1t;1t=1r}o 19.cz(1Y,1t||\'*\')[1i||0]},7u:q(k,4K){4K=19.4c(4K.2s(\',\'));G V=[],h=19.26;17(G i=0,l=4K.O,43;i<l;i++){43=1s 19(4K[i].3Z());h.21(V,43.7S(k))}o(l>1)?h.9s(V):V}});E(1g.1V.3T){M.15(19.26,{21:q(a,b){17(G i=0,L;L=b[i];i++)E(L.1a!=="!")a.1h(L);o a},5j:q(N){17(G i=0,L;L=N[i];i++)L.92(\'3S\');o N}})}q $$(){o 19.7u(1b,$A(1p))}G 1C={9D:q(1x){$(1x).9D();o 1x},cA:q(1Y,U){E(3X U!=\'W\')U={3v:!!U};1m E(M.2A(U.3v))U.3v=1u;G 1w,I,9E=1r,5k=U.5k;G 7a=1Y.3I({},q(1q,k){E(!k.3C&&k.1e){1w=k.1e;I=$(k).3d();E(I!=1j&&(k.1B!=\'5k\'||(!9E&&5k!==1r&&(!5k||1w==5k)&&(9E=1u)))){E(1w 1Q 1q){E(!M.4r(1q[1w]))1q[1w]=[1q[1w]];1q[1w].1h(I)}1m 1q[1w]=I}}o 1q});o U.3v?7a:M.4q(7a)}};1C.1d={6S:q(1x,U){o 1C.cA(1C.67(1x),U)},67:q(1x){o $A($(1x).4m(\'*\')).3I([],q(1Y,1H){E(1C.J.68[1H.1a.2d()])1Y.1h(J.15(1H));o 1Y})},gD:q(1x,7W,1e){1x=$(1x);G 7X=1x.4m(\'4L\');E(!7W&&!1e)o $A(7X).2O(J.15);17(G i=0,9F=[],O=7X.O;i<O;i++){G 4L=7X[i];E((7W&&4L.1B!=7W)||(1e&&4L.1e!=1e))3L;9F.1h(J.15(4L))}o 9F},9G:q(1x){1x=$(1x);1C.67(1x).74(\'9G\');o 1x},9H:q(1x){1x=$(1x);1C.67(1x).74(\'9H\');o 1x},cB:q(1x){G 1Y=$(1x).67().5B(q(k){o\'7D\'!=k.1B&&!k.3C});G 9I=1Y.5B(q(k){o k.3P(\'7J\')&&k.7J>=0}).aK(q(k){o k.7J}).3H();o 9I?9I:1Y.8y(q(k){o[\'4L\',\'2E\',\'9J\'].1L(k.1a.2d())})},gE:q(1x){1x=$(1x);1x.cB().cC();o 1x},2R:q(1x,U){1x=$(1x),U=M.2C(U||{});G 2Z=U.3x,62=1x.5b(\'62\')||\'\';E(62.4Y())62=1A.7o.c1;U.3x=1x.6S(1u);E(2Z){E(M.3f(2Z))2Z=2Z.7b();M.15(U.3x,2Z)}E(1x.3P(\'1D\')&&!U.1D)U.1D=1x.1D;o 1s 1R.53(62,U)}};1C.J={9K:q(k){$(k).9K();o k},2E:q(k){$(k).2E();o k}};1C.J.1d={6S:q(k){k=$(k);E(!k.3C&&k.1e){G I=k.3d();E(I!=4o){G 1G={};1G[k.1e]=I;o M.4q(1G)}}o\'\'},3d:q(k){k=$(k);G 1D=k.1a.2d();o 1C.J.68[1D](k)},gF:q(k,I){k=$(k);G 1D=k.1a.2d();1C.J.68[1D](k,I);o k},aO:q(k){$(k).I=\'\';o k},gG:q(k){o $(k).I!=\'\'},cC:q(k){k=$(k);2q{k.9K();E(k.2E&&(k.1a.2d()!=\'4L\'||![\'9L\',\'9D\',\'5k\'].1L(k.1B)))k.2E()}2B(e){}o k},9G:q(k){k=$(k);k.gH();k.3C=1u;o k},9H:q(k){k=$(k);k.3C=1r;o k}};G gI=1C.J;G $F=1C.J.1d.3d;1C.J.68={4L:q(k,I){5q(k.1B.2d()){2r\'cD\':2r\'cE\':o 1C.J.68.cF(k,I);6H:o 1C.J.68.9J(k,I)}},cF:q(k,I){E(M.2A(I))o k.3Q?k.I:1j;1m k.3Q=!!I},9J:q(k,I){E(M.2A(I))o k.I;1m k.I=I},2E:q(k,1i){E(M.2A(1i))o C[k.1B==\'2E-gJ\'?\'cG\':\'cH\'](k);1m{G 3F,I,cI=!M.4r(1i);17(G i=0,O=k.O;i<O;i++){3F=k.U[i];I=C.7Y(3F);E(cI){E(I==1i){3F.9M=1u;o}}1m 3F.9M=1i.1L(I)}}},cG:q(k){G 1i=k.gK;o 1i>=0?C.7Y(k.U[1i]):1j},cH:q(k){G 1T,O=k.O;E(!O)o 1j;17(G i=0,1T=[];i<O;i++){G 3F=k.U[i];E(3F.9M)1T.1h(C.7Y(3F))}o 1T},7Y:q(3F){o J.15(3F).3P(\'I\')?3F.I:3F.42}};4V.9N=2b.2o(af,{2G:q($49,k,4e,2W){$49(2W,4e);C.k=$(k);C.4M=C.3d()},8e:q(){G I=C.3d();E(M.3f(C.4M)&&M.3f(I)?C.4M!=I:24(C.4M)!=24(I)){C.2W(C.k,I);C.4M=I}}});1C.J.cJ=2b.2o(4V.9N,{3d:q(){o 1C.J.3d(C.k)}});1C.cJ=2b.2o(4V.9N,{3d:q(){o 1C.6S(C.k)}});4V.6T=2b.2o({2G:q(k,2W){C.k=$(k);C.2W=2W;C.4M=C.3d();E(C.k.1a.2d()==\'1x\')C.cK();1m C.6d(C.k)},9O:q(){G I=C.3d();E(C.4M!=I){C.2W(C.k,I);C.4M=I}},cK:q(){1C.67(C.k).1E(C.6d,C)},6d:q(k){E(k.1B){5q(k.1B.2d()){2r\'cD\':2r\'cE\':1F.4N(k,\'gL\',C.9O.1J(C));2c;6H:1F.4N(k,\'gM\',C.9O.1J(C));2c}}}});1C.J.6T=2b.2o(4V.6T,{3d:q(){o 1C.J.3d(C.k)}});1C.6T=2b.2o(4V.6T,{3d:q(){o 1C.6S(C.k)}});E(!1A.1F)G 1F={};M.15(1F,{gN:8,gO:9,gP:13,gQ:27,gR:37,gS:38,gT:39,gU:40,gV:46,gW:36,gX:35,gY:33,gZ:34,h0:45,2U:{},9P:q(1c){G k;5q(1c.1B){2r\'h1\':k=1c.h2;2c;2r\'h3\':k=1c.3B;2c;6H:o 1j}o J.15(k)}});1F.1d=(q(){G 5l;E(1g.1V.3T){G cL={0:1,1:4,2:2};5l=q(1c,5m){o 1c.9L==cL[5m]}}1m E(1g.1V.4n){5l=q(1c,5m){5q(5m){2r 0:o 1c.7Z==1&&!1c.cM;2r 1:o 1c.7Z==1&&1c.cM;6H:o 1r}}}1m{5l=q(1c,5m){o 1c.7Z?(1c.7Z===5m+1):(1c.9L===5m)}}o{h4:q(1c){o 5l(1c,0)},h5:q(1c){o 5l(1c,1)},h6:q(1c){o 5l(1c,2)},k:q(1c){G L=1F.15(1c).80;o J.15(L.3q==6u.bl?L.1P:L)},5P:q(1c,1t){G k=1F.k(1c);E(!1t)o k;G 1Y=[k].21(k.5M());o 19.5P(1Y,1t,0)},5n:q(1c){o{x:1c.cN||(1c.h7+(1b.4G.4D||1b.2w.4D)),y:1c.cO||(1c.h8+(1b.4G.4C||1b.2w.4C))}},h9:q(1c){o 1F.5n(1c).x},ha:q(1c){o 1F.5n(1c).y},8f:q(1c){1F.15(1c);1c.cP();1c.cQ();1c.hb=1u}}})();1F.15=(q(){G 2F=M.48(1F.1d).3I({},q(m,1e){m[1e]=1F.1d[1e].4t();o m});E(1g.1V.3T){M.15(2F,{cQ:q(){C.hc=1u},cP:q(){C.76=1r},2z:q(){o"[W 1F]"}});o q(1c){E(!1c)o 1r;E(1c.7O)o 1c;1c.7O=1g.3o;G 5n=1F.5n(1c);M.15(1c,{80:1c.hd,9P:1F.9P(1c),cN:5n.x,cO:5n.y});o M.15(1c,2F)}}1m{1F.1l=1F.1l||1b.6U("cR").4R;M.15(1F.1l,2F);o 1g.K}})();M.15(1F,(q(){G 2U=1F.2U;q 9Q(k){E(k.9R)o k.9R[0];1p.5t.1o=1p.5t.1o||1;o k.9R=[++1p.5t.1o]}q 9S(1z){E(1z&&1z.1L(\':\'))o"cS";o 1z}q 81(1o){o 2U[1o]=2U[1o]||{}}q 82(1o,1z){G c=81(1o);o c[1z]=c[1z]||[]}q cT(k,1z,2h){G 1o=9Q(k);G c=82(1o,1z);E(c.5C("2h").1L(2h))o 1r;G 1K=q(1c){E(!1F||!1F.15||(1c.1z&&1c.1z!=1z))o 1r;1F.15(1c);2h.8X(k,1c)};1K.2h=2h;c.1h(1K);o 1K}q 9T(1o,1z,2h){G c=82(1o,1z);o c.8y(q(1K){o 1K.2h==2h})}q cU(1o,1z,2h){G c=81(1o);E(!c[1z])o 1r;c[1z]=c[1z].6l(9T(1o,1z,2h))}q cV(){17(G 1o 1Q 2U)17(G 1z 1Q 2U[1o])2U[1o][1z]=1j}E(1A.6Z){1A.6Z("c3",cV)}o{4N:q(k,1z,2h){k=$(k);G 1e=9S(1z);G 1K=cT(k,1z,2h);E(!1K)o k;E(k.83){k.83(1e,1K,1r)}1m{k.6Z("5I"+1e,1K)}o k},5o:q(k,1z,2h){k=$(k);G 1o=9Q(k),1e=9S(1z);E(!2h&&1z){82(1o,1z).1E(q(1K){k.5o(1z,1K.2h)});o k}1m E(!1z){M.48(81(1o)).1E(q(1z){k.5o(1z)});o k}G 1K=9T(1o,1z,2h);E(!1K)o k;E(k.cW){k.cW(1e,1K,1r)}1m{k.he("5I"+1e,1K)}cU(1o,1z,2h);o k},69:q(k,1z,2P){k=$(k);E(k==1b&&1b.6U&&!k.cX)k=1b.4G;G 1c;E(1b.6U){1c=1b.6U("cR");1c.hf("cS",1u,1u)}1m{1c=1b.hg();1c.cY="hh"}1c.1z=1z;1c.2P=2P||{};E(1b.6U){k.cX(1c)}1m{k.hi(1c.cY,1c)}o 1F.15(1c)}}})());M.15(1F,1F.1d);J.6c({69:1F.69,4N:1F.4N,5o:1F.5o});M.15(1b,{69:J.1d.69.4t(),4N:J.1d.4N.4t(),5o:J.1d.5o.4t(),6V:1r});(q(){G 41;q 6W(){E(1b.6V)o;E(41)1A.ah(41);1b.69("hj:6V");1b.6V=1u}E(1b.83){E(1g.1V.4n){41=1A.ag(q(){E(/6V|cZ/.2N(1b.2T))6W()},0);1F.4N(1A,"hk",6W)}1m{1b.83("hl",6W,1r)}}1m{1b.6B("<4S 1o=d0 4u c2=//:><\\/4S>");$("d0").7j=q(){E(C.2T=="cZ"){C.7j=1j;6W()}}}})();3Y.4q=M.4q;G hm={3A:J.bm};J.1d.hn=J.1d.7z;G ho={hp:q(k,18){o J.3z(k,{4Z:18})},hq:q(k,18){o J.3z(k,{2k:18})},hr:q(k,18){o J.3z(k,{59:18})},hs:q(k,18){o J.3z(k,{7r:18})}};G $3L=1s ht(\'"4p $3L" hu hv, hw "o" hx\');G 9U={d1:1r,9V:q(){C.d2=1A.ci||1b.4G.4D||1b.2w.4D||0;C.d3=1A.cj||1b.4G.4C||1b.2w.4C||0},hy:q(k,x,y){E(C.d1)o C.d4(k,x,y);C.6X=x;C.6Y=y;C.3a=J.5c(k);o(y>=C.3a[1]&&y<C.3a[1]+k.5X&&x>=C.3a[0]&&x<C.3a[0]+k.5W)},d4:q(k,x,y){G 9W=J.9e(k);C.6X=x+9W[0]-C.d2;C.6Y=y+9W[1]-C.d3;C.3a=J.5c(k);o(C.6Y>=C.3a[1]&&C.6Y<C.3a[1]+k.5X&&C.6X>=C.3a[0]&&C.6X<C.3a[0]+k.5W)},hz:q(84,k){E(!84)o 0;E(84==\'hA\')o((C.3a[1]+k.5X)-C.6Y)/k.5X;E(84==\'hB\')o((C.3a[0]+k.5W)-C.6X)/k.5W},5c:J.1d.5c,6F:J.1d.6F,9b:q(k){9U.9V();o J.9b(k)},9d:q(k){9U.9V();o J.9d(k)},hC:J.1d.9e,3l:J.1d.60,hD:J.1d.6G,2C:q(22,80,U){U=U||{};o J.bR(80,22,U)}};E(!1b.85)1b.85=q(d5){q 9X(1e){o 1e.4Y()?1j:"[6M(21(\' \', @6x, \' \'), \' "+1e+" \')]"}d5.85=1g.3V.71?q(k,1k){1k=1k.2H().3Z();G 9Y=/\\s/.2N(1k)?$w(1k).2O(9X).2s(\'\'):9X(1k);o 9Y?1b.8V(\'.//*\'+9Y,k):[]}:q(k,1k){1k=1k.2H().3Z();G 1Y=[],6C=(/\\s/.2N(1k)?$w(1k):1j);E(!6C&&!1k)o 1Y;G N=$(k).4m(\'*\');1k=\' \'+1k+\' \';17(G i=0,1H,cn;1H=N[i];i++){E(1H.1k&&(cn=\' \'+1H.1k+\' \')&&(cn.1L(1k)||(6C&&6C.8u(q(1e){o!1e.2H().4Y()&&cn.1L(\' \'+1e+\' \')}))))1Y.1h(J.15(1H))}o 1Y};o q(1k,7p){o $(7p||1b.2w).85(1k)}}(J.1d);J.7w=2b.2o();J.7w.1l={2G:q(k){C.k=$(k)},4h:q(Y){C.k.1k.4c(/\\s+/).2E(q(1e){o 1e.O>0}).4h(Y)},6n:q(1k){C.k.1k=1k},hE:q(9Z){E(C.1L(9Z))o;C.6n($A(C).21(9Z).2s(\' \'))},bp:q(a0){E(!C.1L(a0))o;C.6n($A(C).6l(a0).2s(\' \'))},2H:q(){o $A(C).2s(\' \')}};M.15(J.7w.1l,2I);J.6c();',62,1095,'||||||||||||||||||||element||||return||function||||||||||||this||if||var||value|Element||node|Object|nodes|length||||||options|results|object||iterator||||||style|extend||for|content|Selector|tagName|document|event|Methods|name|match|Prototype|push|index|null|className|prototype|else|root|id|arguments|result|false|new|expression|true|position|key|form|property|eventName|window|type|Form|method|each|Event|pair|child|formula|bind|wrapper|include|context|klass|while|parentNode|in|Ajax|div|values|attribute|Browser|replace|transport|elements|nth|args|concat|source||String|pattern|handlers||combinator|attr|getStyle|Class|break|toLowerCase|filter|width|pseudos|handler|Array|attributes|top|_getEv|matches||create|isFunction|try|case|join|left|last|response|body|of|xpath|inspect|isUndefined|catch|clone|array|select|methods|initialize|toString|Enumerable|valueT|valueL|evaluate|parent|test|map|memo|toUpperCase|request|url|readyState|cache|ancestor|callback|Template|iterable|params||responseText|height||||||||offset|targetNode|nv|getValue|properties|isString|string|__method|gsub|childNodes|json|offsetParent|px|proceed|emptyFunction|toJSON|nodeType|names|replacement|slice|count|hash|toArray|parameters|container|insert|display|toElement|disabled|ByTag|le|opt|apply|first|inject|onComplete|insertions|continue|nextSibling|_attributeTranslations|opacity|hasAttribute|checked|matcher|_countedByPrototype|IE|indexOf|BrowserFeatures|createElement|typeof|Hash|strip||timer|text|selector|els|||mm|keys|super|isElement|toHTML|split|RegExp|frequency|stripScripts|nodeValue|_each|reverse|start|responder|ps|getElementsByTagName|WebKit|undefined|throw|toQueryString|isArray|number|methodize|defer|toPaddedString|innerHTML|parts|_object|status|nextSiblings|styles|scrollTop|scrollLeft|tags|table|documentElement|descendant|sibling|not|expressions|input|lastValue|observe|Opera|navigator|userAgent|__proto__|script|shift|wrap|Abstract|isNumber|evalScripts|blank|before|Number|update|end|Request|dispatchException|headers|success|insertion|decay|bottom|adjacent|readAttribute|cumulativeOffset|_overflow|offsetTop|offsetLeft|_returnOffset|currentStyle|_cache|unmark|submit|isButton|code|pointer|stopObserving|destination|switch|interpret|str|callee|truncation|self|substring|evalJSON|empty|template|appendChild|findAll|pluck|right|item|exclusive|Responders|extras|on|getHeader|receiver|_insertionTranslations|ancestors|firstChild|previousSiblings|findElement|getDimensions|nextAncestor|pos|parseFloat|setStyle|setOpacity|offsetWidth|offsetHeight|absolute|static|getOffsetParent|delta|action|tbody|Heading|attrPresence|fragment|getElements|Serializers|fire|ElementExtensions|HTMLElement|addMethods|registerCallback|onTimerEvent|capitalize|_|ctx|expr|fillWith|criteria|without|toObject|set|responders|post|contentType|xml|getStatus|state|Node|writeAttribute|removeChild|class|previousElementSibling|next|nextElementSibling|write|classNames|sourceIndex|relative|positionedOffset|viewportOffset|default|_flag|patterns|following|laterSibling|contains|operators|pseudo|only|ofType|nodeClassName|serialize|EventObserver|createEvent|loaded|fireContentLoadedEvent|xcomp|ycomp|attachEvent|Gecko|XPath|SpecificElementExtensions|ScriptFragment|invoke|curry|returnValue|currentlyExecuting|eval|escapeHTML|data|toQueryParams|times|charAt|detect|dispatch|onCreate|asynchronous|application|onreadystatechange|html|headerJSON|isSameOrigin|port|location|parentElement|none|after|_getContentFromAnonymousElement|recursivelyCollect|findChildElements|read|ClassNames|hasClassName|elementClassName|descendantOf|cssFloat|auto|00001|hidden|dim|border|padding|title|_getAttr|tabIndex|insertBefore|TBODY|tr|Simulated|_extendedByPrototype|refresh|copy|onlyIfAbsent|findElements|token|mark|nodeIndex|typeName|inputs|optionValue|which|target|getCacheForID|getWrappersForEventName|addEventListener|mode|getElementsByClassName|Version|opera|superclass|subclass|isHash|Function|delay|_methodized|execute|stop|prepareReplacement|decodeURIComponent|succ|camelize|len|camelized|escapedString|character|unfilterJSON|startsWith|lastIndexOf|toTemplateReplacements|slices|collect|all|found|trues|falses|find|_reverse|toQueryPair|get|delete|activeRequestCount|Base|encoding|evalJS|_complete|Response|respondToReadyState|onStateChange|Content|Complete|protocol|domain|getResponseHeader|exception|statusText|getAllResponseHeaders|failure|updater|_getElementsByXPath|query|call|visible|range|replaceChild|getAttribute|removeAttribute|float|css|elementStyle|cssText|styleFloat|visibility|_madePositioned|overflow|absolutize|offsets|relativize|cumulativeScrollOffset|forElement|val|zoom|alpha|stripAlpha|has|fragments|TD|trans|TableSection|HTML|tag|dimensions|unique|tokens|assertions|or|preceding|and|exclusion|predicate|indexed|indices|exclusions|reset|submitted|matchingInputs|disable|enable|firstByIndex|textarea|focus|button|selected|TimedObserver|onElementEvent|relatedTarget|getEventID|_prototypeEventID|getDOMEventName|findWrapper|Position|prepare|offsetcache|iter|cond|classNameToAdd|classNameToRemove|KHTML|MobileSafari|Safari|JSONFilter|subclasses|valueOf|argumentNames|instanceof|timeout|1000|Try|these|lambda|escape|PeriodicalExecuter|setInterval|clearInterval|specialChar|sub|scan|stripTags|img|extractScripts|matchAll|matchOne|scriptTag|unescapeHTML||separator|charCodeAt|useDoubleQuotes|isJSON|sanitize|JSON|endsWith|interpolate|amp|lt|createTextNode|with|Pattern|exec|comp|eachSlice|any|sortBy|collections|size|from|clear|flatten|inline|uniq|sorted|forEach|arrayLength|radix|encodeURIComponent|ObjectRange|getTransport|XMLHttpRequest|ActiveXObject|XMLHTTP|register|setRequestHeaders|overrideMimeType|2005|requestHeaders|Events|force|evalResponse|onException|getStatusText|_getHeaderJSON|responseXML|_getResponseJSON|sanitizeJSON|Updater|updateContent|updateComplete|lastText|ELEMENT_NODE|TEXT_NODE|toggle|hide|show|remove|descendants|firstDescendant|immediateDescendants|previousSibling|identify|counter|setAttribute|getHeight|getWidth|addClassName|removeClassName|nextNode|originalAncestor|compareDocumentPosition|scrollTo|originalVisibility|originalPosition|originalDisplay|originalWidth|clientWidth|originalHeight|clientHeight|BODY|_originalLeft|_originalTop|_originalWidth|_originalHeight|clonePosition|setLeft|setTop|setWidth|setHeight|htmlFor|parseInt|100|_getAttrNode|getAttributeNode|href|src|onunload|IMG|outerHTML|TR|td|SELECT|THEAD|TFOOT|TH|TEXTAREA|findDOMClass|Mod|TableCol|TableCell|client|pageXOffset|pageYOffset|compileMatcher|shouldUseXPath|compileXPathMatcher||local|enabled|even|odd|_true|uTagName|byClassName|needle|operator|getIndices|total|matchElements|serializeElements|findFirstElement|activate|checkbox|radio|inputSelector|selectOne|selectMany|single|Observer|registerFormCallbacks|buttonMap|metaKey|pageX|pageY|preventDefault|stopPropagation|HTMLEvents|dataavailable|createWrapper|destroyWrapper|destroyCache|removeEventListener|dispatchEvent|eventType|complete|__onDOMContentLoaded|includeScrollOffsets|deltaX|deltaY|withinIncludingScrolloffsets|instanceMethods|AppleWebKit|Apple|Mobile|secure|constructor|RangeError|unknown|boolean|splice|bindAsEventListener|setTimeout|01|Date|getUTCFullYear|getUTCMonth|getUTCDate|getUTCHours|getUTCMinutes||getUTCSeconds|finally|truncate|im|fromCharCode|underscore|dasherize|x00|x1f|u00|Eaeflnr|SyntaxError|Badly|formed|parseQuery|grep|inGroupsOf|max|min|partition|reject|sort|zip|pop|member|entries|every|some|NodeList|compact|reduce|intersect|isNaN|toColorPart|isFinite|abs|round|ceil|floor|Math|unset|merge|Msxml2|Microsoft|unregister|www|urlencoded|UTF|_method|Konqueror|open|postBody|send|Requested|With|Accept|javascript|charset|Connection|close||setRequestHeader|200|300|Success|Failure|java|ecma|https|Uninitialized|Loading|Loaded|Interactive|responseJSON|getAllHeaders|PeriodicalUpdater|clearTimeout|getElementById|XPathResult|ORDERED_NODE_SNAPSHOT_TYPE|snapshotLength|snapshotItem|ATTRIBUTE_NODE|CDATA_SECTION_NODE|ENTITY_REFERENCE_NODE|ENTITY_NODE|PROCESSING_INSTRUCTION_NODE|COMMENT_NODE|DOCUMENT_NODE|DOCUMENT_TYPE_NODE|DOCUMENT_FRAGMENT_NODE|NOTATION_NODE|cloneNode|ownerDocument|createRange|selectNode|createContextualFragment|siblings|up|down|previous|anonymous_element_|toggleClassName|cleanWhitespace|defaultView|getComputedStyle|getOpacity|block|makePositioned|undoPositioned|makeClipping|undoClipping|getElementsBySelector|childElements|fixed|hasLayout|normal|cellpadding|cellPadding|cellspacing|cellSpacing|colSpan|rowSpan|vAlign|dateTime|accessKey|encType|maxLength|readOnly|longDesc|readonly|multiple|onload|onclick|ondblclick|onmousedown|onmouseup|onmouseover|onmousemove|onmouseout|onfocus|onblur|onkeypress|onkeydown|onkeyup|onsubmit|onreset|onselect|onchange|rv|999999|TABLE|specified|FORM|INPUT|OPTGROUP|OptGroup|TextArea|Paragraph|FIELDSET|FieldSet|UL|UList|OL|OList|DL|DList|DIR|Directory|H1|H2|H3|H4|H5|H6|Quote|INS|DEL|Anchor||Image|CAPTION|TableCaption|COL|COLGROUP|TableRow|FRAMESET|FrameSet|IFRAME|IFrame||viewport|inner|getScrollOffsets|starts|translate|mod|dis|abled|selectorType|getInputs|focusFirstElement|setValue|present|blur|Field|one|selectedIndex|click|change|KEY_BACKSPACE|KEY_TAB|KEY_RETURN|KEY_ESC|KEY_LEFT|KEY_UP|KEY_RIGHT|KEY_DOWN|KEY_DELETE|KEY_HOME|KEY_END|KEY_PAGEUP|KEY_PAGEDOWN|KEY_INSERT|mouseover|fromElement|mouseout|isLeftClick|isMiddleClick|isRightClick|clientX|clientY|pointerX|pointerY|stopped|cancelBubble|srcElement|detachEvent|initEvent|createEventObject|ondataavailable|fireEvent|dom|load|DOMContentLoaded|Toggle|childOf|Insertion|Before|Top|Bottom|After|Error|is|deprecated|use|instead|within|overlap|vertical|horizontal|realOffset|page|add'.split('|'),0,{}))/**
 * Purpose: Header can be used across multiple pages of myTimeWall
 * @param {int} btnSelected - 1 -> HOME, 2 -> PROFILE, 3 -> FRIEND, 4->Message -1 -> no selection 
 * @param {Object} parent - parent object
 * @param {Boolean} isPublic - true -> isPublic
 * @param {Boolean} hideLoginControl
 * @param {Int} newMsgNum
 */
Header = function(btnSelected,parent,isPublic,hideLoginControl,newMsgNum){	
	var mainImg;
	if(isIE && !isMinIE7){
		try {
			document.execCommand("BackgroundImageCache", false, true);			
		}catch(err) {}
		mainImg = "Image/01_Header/Header8_310809.png";
	}else{
		mainImg = "Image/01_Header/Header32_310809.png";
	} 
	var img = new Image();
	img.src = mainImg;
	var messageDisplay = document.createElement('div');		
	messageDisplay.id = "MessageDisplay";
	
	init = function(){
		var ankhHeader = document.createElement('div');
		ankhHeader.id = "AnkhHeader";
		parent.appendChild(ankhHeader);
		
		var logoList = new Object();
		logoList['front'] = {normSrc: {x: 0,y: 0},width: 23,height: 79};
		logoList['logo'] = {normSrc: {x: 25,y: 0},width: 155,height: 79};
		logoList['back'] = {normSrc: {x: 0,y: 84},width: 786,height: 79};
		
		for (var i in logoList) {			
			if(i == "logo"){			
				var link = new AnkhLink("",null,"index.php");	
				link.style.display = "block";
				var logo = new AnkhSprite(mainImg, logoList[i].width, logoList[i].height, logoList[i].normSrc);
				logo.className = "logo";
				link.appendChild(logo);			
				ankhHeader.appendChild(link);
			}else{
				var logo = new AnkhSprite(mainImg, logoList[i].width, logoList[i].height, logoList[i].normSrc);
				logo.className = "logo";
				ankhHeader.appendChild(logo);				
			}
		}
		if(!isPublic){
			var buttonsList = new Object();
			buttonsList['Home'] = {anchor: "Home.php",width: 85,height: 41,normSrc: {x: 185,y: 42},moSrc: {x: 275,y: 42}};
			buttonsList['Profile'] = {anchor: "Profile.php",width: 93,height: 41,normSrc: {x: 365,y: 42},moSrc: {x: 465,y: 42}};
			buttonsList['Friend'] = {anchor: "Friend.php",width: 91,height: 41,normSrc: {x: 565,y: 42},moSrc: {x: 660,y: 42}};
			buttonsList['Message'] = {anchor: "MessageCentre.php",width: 105,height: 41,normSrc: {x: 555,y: 0},moSrc: {x: 660,y: 0}};
			
			var sideToolBarBgImg = {normSrc: {x: 180,y: 0},width: 375,height: 38};	
			var sideToolBarLinks = new Object();			
			sideToolBarLinks['settings'] = "AccountSettings.php";
			sideToolBarLinks['feedback'] = "feedback.php";
			sideToolBarLinks['logout'] = "logout.php";
			
			var toolBar = document.createElement('div');
			toolBar.id = "ToolBar";
			ankhHeader.appendChild(toolBar);			
			var index = 1;			
			for (var i in buttonsList) {			
				var anchor = new AnkhLink("",null,buttonsList[i].anchor);	
				anchor.style.border = "0px";			
				toolBar.appendChild(anchor);				
				var select = false;
				if (index == btnSelected) {
					select = true;
				}
				
				var button = new AnkhSprite(mainImg, buttonsList[i].width, buttonsList[i].height, buttonsList[i].normSrc, buttonsList[i].moSrc, buttonsList[i].moSrc, select, true);				
				anchor.appendChild(button);		
				if(i == "Message" && newMsgNum > 0){																							
					var messageNum = document.createTextNode("("+newMsgNum+")");
					messageDisplay.appendChild(messageNum);										
					button.appendChild(messageDisplay);

					if(select){										//if my default, button is selected, then the word should always be white
						messageDisplay.style.color = "#F4FAED";
						buttonActivate = true;
					}else{					
						var msgActivate;				
						var buttonActivate;
						EventUtil.addEventHandler(button,"mouseover",function x(){								
							buttonActivate = true;				
							messageDisplay.style.color = "#F4FAED";
						});
						EventUtil.addEventHandler(button,"mouseout",function x(){
							buttonActivate = false;
							if(msgActivate){
								button.activateMouseOver();
							}else{
								messageDisplay.style.color = "#5E6F61";
								button.activateMouseOut();
							}						
						});
						EventUtil.addEventHandler(messageDisplay,"mouseover",function x(){
							msgActivate = true;
							messageDisplay.style.color = "#F4FAED";
							button.activateMouseOver();						
						});
						EventUtil.addEventHandler(messageDisplay,"mouseout",function x(){
							msgActivate = false;
							if(buttonActivate){
								button.activateMouseOver();
							}else{
								messageDisplay.style.color = "#5E6F61";
								button.activateMouseOut();
							}
						});
					}
				}		
				index += 1;				
			}			
			var sideToolBar = new AnkhSprite(mainImg, sideToolBarBgImg.width, sideToolBarBgImg.height, sideToolBarBgImg.normSrc);
			toolBar.appendChild(sideToolBar);
			sideToolBar.id = "SideToolBar";
			sideToolBar.align = "right";
			
			var tblStructure = new GenericTable(1, 4);
			tblStructure.Table.id = "SideToolBarTbl";	
			tblStructure.Table.cellPadding = 0;
			tblStructure.Table.cellSpacing = 0;		
			sideToolBar.appendChild(tblStructure.Table);
			
			var index = 0;
			for (var i in sideToolBarLinks) {				
				var cell = tblStructure.getCell(0, index);														
				var link = new AnkhLink(i, null, sideToolBarLinks[i], null);
				cell.appendChild(link);				
				index += 1;
				EventUtil.addEventHandler(link,"mouseover",function x(){ EventUtil.getEvent().target.style.textDecoration = "underline"; });
				EventUtil.addEventHandler(link,"mouseout",function x(){ EventUtil.getEvent().target.style.textDecoration = "none"; });
			}						
		}else if(!hideLoginControl){
			var queryStr = window.location.search;
			var loginForm = new AnkhFormContainer("LoginForm","Post","Login.php"+queryStr);
			parent.appendChild(loginForm);
			
			var loginContainer = document.createElement('div');
			loginForm.appendChild(loginContainer);
			createLoginControls(loginContainer);	
		}
		var clearLeftDiv = document.createElement('div');
		clearLeftDiv.style.clear = "left";
		clearLeftDiv.style.paddingTop = "5px";
		parent.appendChild(clearLeftDiv);
	};
	
	createLoginControls = function(parent){
		
		var tblStructure = new GenericTable(2,3);
		parent.appendChild(tblStructure.Table);
		
		var emailControl = new AnkhTextBoxWithContent("login[email]","Email");		
		emailControl.style.width = "140px";
		emailControl.tabIndex = "1";	
		tblStructure.insertIntoCell(0,0,emailControl);		
		var pwdControl = new AnkhPasswordWithContent("login[password]","Password",null,tblStructure.getCell(0,1),140);
		pwdControl.setTabIndex("2","3");	
		tblStructure.TBody.childNodes[1].style.verticalAlign = "top";		
		var rememberContainer = document.createElement('div');
		rememberContainer.className = "FloatLeft";
		tblStructure.insertIntoCell(1,0,rememberContainer);			
		var remMe = new AnkhCheckBox("login","remember");
		remMe.tabIndex = "4";		
		rememberContainer.appendChild(remMe);
						
		var remMeTxt = document.createTextNode("Remember me");
		rememberContainer.appendChild(remMeTxt);
		
		var register = new AnkhLink("Register as user",null,"Signup.php",null);
		register.style.display = "block";
		register.style.cssFloat = "none";
		register.style.styleFloat = "none";
		tblStructure.insertIntoCell(1,1,register);	
						
		var forgetPwd = new AnkhLink("Forgot password?",null,"ForgetPassword.php",null);
		forgetPwd.style.display = "block";		
		forgetPwd.style.cssFloat = "none";
		forgetPwd.style.styleFloat = "none";
		forgetPwd.style.marginTop = "5px";
		tblStructure.insertIntoCell(1,1,forgetPwd);		
		tblStructure.getCell(1,1).style.textAlign = "right";
		
		var submitBtn = new AnkhSubmitButton("","login","#3f74c3");
		submitBtn.tabIndex = "5";
		tblStructure.getCell(0,2).rowSpan = "2";
		tblStructure.insertIntoCell(0,2,submitBtn);		
		
		var signUpErrorContainer = new AnkhFormErrorContainer(parent,"LoginError");	
	};
	
	this.newMsgNum = function(value){
		AnkhUsefulMethods.removeAll(messageDisplay);					
		if(value > 0){
			var messageNum = document.createTextNode("("+value+")");
			messageDisplay.appendChild(messageNum);
		}else{
			messageDisplay.innerHTML  = "";
		}
	};
	
	init();	
};
/**
 * Purpose: Draw AnkhSprite
 * @param {String} spriteImg
 * @param {Int} width
 * @param {Int} height
 * @param {Object} normSrcXY - {x,y} object
 * @param {Object} mouseOverSrcXY  - {x,y} object
 * @param {Object} mouseDownSrcXY  - {x,y} object
 * @param {Boolean} selected  - currently mouse-down
 * @param {Boolean} onceDownAlwaysDown - once mouse down, it will forever be mouse down
 */
AnkhSprite = function(spriteImg,width,height,normSrcXY,mouseOverSrcXY,mouseDownSrcXY,selected,onceDownAlwaysDown){
	var sprite = document.createElement('div');		
	sprite.mouseOverSrcXY = mouseOverSrcXY;
	sprite.normSrcXY = normSrcXY;
	sprite.mouseDownSrcXY = mouseDownSrcXY;
	sprite.selected = selected;
	sprite.isMouseOver = selected;
	var x;
	var y;
	if (sprite.selected) {
		x = -mouseDownSrcXY.x;
		y = -mouseDownSrcXY.y;	
	}
	else{
		x = -normSrcXY.x;
		y = -normSrcXY.y;	
	}
	sprite.style.background = "url('" + spriteImg + "') "+x+"px"+" "+y+"px "+" no-repeat";		
	sprite.style.width = width + "px";
	sprite.style.height = height + "px";		
	
	if (normSrcXY && mouseOverSrcXY && mouseDownSrcXY) {
		EventUtil.addEventHandler(sprite, "mouseover", function x(){
			if (!EventUtil.getEvent().target.selected && EventUtil.getEvent().target.mouseOverSrcXY) {
				var x = -EventUtil.getEvent().target.mouseOverSrcXY.x;
				var y = -EventUtil.getEvent().target.mouseOverSrcXY.y;			
				if (isIE) {
					EventUtil.getEvent().target.style.backgroundPositionX = x + "px";
					EventUtil.getEvent().target.style.backgroundPositionY = y + "px";
				}
				else {
					EventUtil.getEvent().target.style.background = "url('" + spriteImg + "') " + x + "px" + " " + y + "px " + " no-repeat";
				}
				sprite.isMouseOver = true;				
			}
		});
	
		EventUtil.addEventHandler(sprite, "mouseout", function x(){
			if (!EventUtil.getEvent().target.selected && EventUtil.getEvent().target.normSrcXY) {								
				var x = -EventUtil.getEvent().target.normSrcXY.x;
				var y = -EventUtil.getEvent().target.normSrcXY.y;				
				if (isIE) {
					EventUtil.getEvent().target.style.backgroundPositionX = x + "px";
					EventUtil.getEvent().target.style.backgroundPositionY = y + "px";
				}
				else {
					EventUtil.getEvent().target.style.background = "url('" + spriteImg + "') " + x + "px" + " " + y + "px " + " no-repeat";
				}
				sprite.isMouseOver = false;				
			}
		});
			
		EventUtil.addEventHandler(sprite, "mousedown", function x(){
			
			if((EventUtil.getEvent().button == 1 && isIE) || (EventUtil.getEvent().button == 0 && !isIE)){			//if left mouse button
				if (!EventUtil.getEvent().target.selected && EventUtil.getEvent().target.mouseDownSrcXY) {				
					var x = -EventUtil.getEvent().target.mouseDownSrcXY.x;
					var y = -EventUtil.getEvent().target.mouseDownSrcXY.y;			
					if (isIE) {
						EventUtil.getEvent().target.style.backgroundPositionX = x + "px";
						EventUtil.getEvent().target.style.backgroundPositionY = y + "px";
					}
					else {
						EventUtil.getEvent().target.style.background = "url('" + spriteImg + "') " + x + "px" + " " + y + "px " + " no-repeat";
					}
				}
				if(onceDownAlwaysDown){
					EventUtil.getEvent().target.selected = true;
				}
			}
		});
		if (!onceDownAlwaysDown) {
			EventUtil.addEventHandler(sprite, "mouseup", function x(){
				if (!EventUtil.getEvent().target.selected) {
					var x = -EventUtil.getEvent().target.normSrcXY.x;
					var y = -EventUtil.getEvent().target.normSrcXY.y;					
					if (isIE) {
						EventUtil.getEvent().target.style.backgroundPositionX = x + "px";
						EventUtil.getEvent().target.style.backgroundPositionY = y + "px";
					}
					else {
						EventUtil.getEvent().target.style.background = "url('" + spriteImg + "') " + x + "px" + " " + y + "px " + " no-repeat";
					}
				}
			});
		}
	}
	sprite.activateMouseOver = function(){
		if (!sprite.selected) {
			var x = -sprite.mouseOverSrcXY.x;
			var y = -sprite.mouseOverSrcXY.y;			
			if (isIE) {
				sprite.style.backgroundPositionX = x + "px";
				sprite.style.backgroundPositionY = y + "px";
			}
			else {
				sprite.style.background = "url('" + spriteImg + "') " + x + "px" + " " + y + "px " + " no-repeat";
			}
			sprite.isMouseOver = true;
		}
	};
	sprite.activateMouseOut = function(){
		if (!sprite.selected) {								
			var x = -sprite.normSrcXY.x;
			var y = -sprite.normSrcXY.y;				
			if (isIE) {
				sprite.style.backgroundPositionX = x + "px";
				sprite.style.backgroundPositionY = y + "px";
			}
			else {
				sprite.style.background = "url('" + spriteImg + "') " + x + "px" + " " + y + "px " + " no-repeat";
			}
			sprite.isMouseOver = false;
		}
	};
	sprite.activateMouseClick = function(){
		if (!sprite.selected) {								
			var x = -sprite.mouseDownSrcXY.x;
			var y = -sprite.mouseDownSrcXY.y;				
			if (isIE) {
				sprite.style.backgroundPositionX = x + "px";
				sprite.style.backgroundPositionY = y + "px";
			}
			else {
				sprite.style.background = "url('" + spriteImg + "') " + x + "px" + " " + y + "px " + " no-repeat";
			}
			sprite.isMouseOver = false;
		}
	};
	return sprite;
};

