function EzFocus()
{
	this.KEY_UP=38;
	this.KEY_DOWN=40;
	this.KEY_LEFT=37;
	this.KEY_RIGHT=39;
	this.KEY_ENTER=13;
	this.lastFocusElement = null;
	this.currentFocusElement = null;
	this.previousFocusElement = null;
	this.isInitFocus = false;
	this.focusTags = new Array();
	this.borderColor = "#FFA500";
	this.borderWidth = "3px";
	this.borderStyle = "solid";
	this.isMoveFocus = true;
	this.useEzFocusBorder = true;
}

EzFocus.prototype.getImageObj = function (obj){
	if (!obj)
		return false;
		
	if (obj.tagName == "IMG"){
		var imgObj = obj;
	}	else if (obj.tagName == "DIV"){
		imgs = obj.getElementsByTagName("img");
		if (imgs)
			var imgObj = imgs[0];
		else
			return false;
	}
	else
		return false;
	return imgObj;
}

EzFocus.prototype.setCurrentFocusElement = function (obj){
	if (!obj)
		return false;
	this.previousFocusElement = this.currentFocusElement;
	this.currentFocusElement = obj;
}

EzFocus.prototype.onMouseOver = function (obj){
	this.unsetTagBorder(this.currentFocusElement);
	this.setCurrentFocusElement(obj);

	if ((obj.tagName == "DIV") || (obj.tagName == "IMG")){
		this.onMouseOverSwapImage(obj);
	}
	else {
		this.setTagBorder(obj);
	}

	if (obj.userOnMouseOver != undefined){
		var userOnMouseOver = obj.userOnMouseOver;
		if (!/this/.test(userOnMouseOver))
			setTimeout(userOnMouseOver, 0);
	}
}

EzFocus.prototype.onMouseOut = function (obj){
	if ((obj.tagName == "DIV") || (obj.tagName == "IMG")){
		this.onMouseOutSwapImage(obj);
	}
	else {
		this.unsetTagBorder(obj);
	}

	if (obj.userOnMouseOut != undefined){
		var userOnMouseOut = obj.userOnMouseOut;
		if (!/this/.test(userOnMouseOut))
			setTimeout(userOnMouseOut, 0);
	}
}

EzFocus.prototype.onMouseOverSwapImage = function(obj)
{
	this.swapImage(obj);
}

EzFocus.prototype.onMouseOutSwapImage = function(obj)
{
		imgObj = this.getImageObj(obj);
		if (imgObj.lowsrc.length == 0)
			return true;

		if (imgObj.oriSrc != undefined)
			imgObj.src = imgObj.oriSrc;
}

EzFocus.prototype.debug = function(msg){
	var tagObj = document.getElementById("debug");
	tagObj.style.fontSize="15pt";
	tagObj.style.color = "red";
	if (tagObj){
		tagObj.innerHTML = msg;
	}
}

EzFocus.prototype.resetImage = function (tagObj){
	tObj = this.previousFocusElement;
	var imgObj = this.getImageObj(tObj);
	if (imgObj){
		if ((imgObj.oriSrc != undefined) && (tagObj.className != tObj.className))
			imgObj.src = imgObj.oriSrc;
	}
}

EzFocus.prototype.getTagBorder = function (tagObj){
	//if user defined border color
	if (tagObj.userBorderColor != undefined)
		var borderColor = tagObj.userBorderColor;
	else
		var borderColor = this.borderColor;

	//if user defined border width
	if (tagObj.userBorderWidth != undefined)
		var borderWidth = tagObj.userBorderWidth;
	else
		var borderWidth = this.borderWidth;
		
	if (tagObj.userBorderStyle != undefined)
		var borderStyle = tagObj.userBorderStyle;
	else
		var borderStyle = this.borderStyle;

	return borderWidth+" "+borderStyle+" "+borderColor;
}

EzFocus.prototype.swapImage = function (tagObj){

	var imgObj = this.getImageObj(tagObj);

	if (imgObj.oriSrc == undefined){
		imgObj.oriSrc = imgObj.src;
		imgObj.oriLowSrc = imgObj.lowsrc;
	}
	if (imgObj.lowsrc.length>0)
		imgObj.src = imgObj.oriLowSrc;
	else{
		if ((this.useEzFocusBorder) && (tagObj.useEzFocusBorder)){
			imgObj.style.MozOutline = this.getTagBorder(tagObj);
			imgObj.style.MozOutlineRadius = "5px";
		}
	}

	this.resetImage(tagObj);
}

EzFocus.prototype.setImgsBorder = function(tagObj, mozOutlineValue){
	if (tagObj.tagName == "INPUT")
		return;
		
	var imgs = tagObj.getElementsByTagName("img");
	for(var i = 0; i < imgs.length; i++){
		var imgObj = imgs[i];
		imgObj.style.MozOutline = mozOutlineValue;
	}
}

EzFocus.prototype.unsetTagBorder = function(tagObj){
	if (!tagObj)
		return false;
		
	tagObj.style.MozOutline = "";
	this.setImgsBorder(tagObj, "");
	if ((tagObj.tagName == "A") || (tagObj.tagName == "INPUT"))
		tagObj.blur();
}

EzFocus.prototype.setTagBorder = function(tagObj){

	if ((tagObj.tagName == "INPUT") || (tagObj.tagName == "A")){
		if ((this.useEzFocusBorder) && (tagObj.useEzFocusBorder)){		
			var mozOutlineVlaue = this.getTagBorder(tagObj);
			tagObj.style.MozOutline = mozOutlineVlaue;
			tagObj.style.MozOutlineRadius = "5px";
		}
		
		tagObj.focus();
		if (tagObj.tagName == "INPUT"){
			if (tagObj.type == "text")
				tagObj.select();
		}

		this.resetImage(tagObj);
	}
	else if((tagObj.tagName == "DIV") || (tagObj.tagName == "IMG")){
		this.swapImage(tagObj);
	}
	else if (tagObj.tagName == "AREA"){
		if (!/this/.test(tagObj.userOnMouseOver)){
			setTimeout(tagObj.userOnMouseOver, 0);
		}
	}
}

EzFocus.prototype.getTagLocation = function(className){
	var m = className.match(/^([\d]+)-([\d]+)$/);
	var fl = new Array();
	if (m){
		fl[0] = m[1];
		fl[1] = m[2];
		return fl;
	}else{
		return false;
	}
}

EzFocus.prototype.getTagObj = function (l, ln){
	if (!this.focusTags[l])
		return false;
		
	tagObj = this.focusTags[l][ln];
	if (tagObj)
		return tagObj;
	else
		return false;	
}

EzFocus.prototype.getFirstLineFocusTag = function(){
	//first line focus
	var fl = this.getTagLocation(this.currentFocusElement.tagLocation);
	l = "1";
	
	if (!this.focusTags[l])
		return false;	
	
	if (parseInt(fl[1])>= (this.focusTags[l].length - 1))
		ln = this.focusTags[l].length - 1;
	else
		ln = fl[1];
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getLastLineFocusTag = function(){
	//last line focus
	fl = this.getTagLocation(this.lastFocusElement.tagLocation);
	l = fl[0];

	if (!this.focusTags[l])
		return false;	
	
	if (parseInt(fl[1])>= (this.focusTags[l].length - 1))
		ln = this.focusTags[l].length - 1;
	else
		ln = fl[1];
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getFirstFocusTag = function(){
	l = "1";
	ln = "1";
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getLastFocusTag = function(){
	fl = this.getTagLocation(this.lastFocusElement.tagLocation);
	l = fl[0];
	ln = fl[1];
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getPrevLineFocusTag = function(){
	//prenext line focus
	var fl = this.getTagLocation(this.currentFocusElement.tagLocation);
	var l = parseInt(fl[0])-1;

	if (!this.focusTags[l])
		return false;	
	
	if (parseInt(fl[1])>= (this.focusTags[l].length - 1))
		ln = this.focusTags[l].length - 1;
	else
		ln = fl[1];
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getNextLineFocusTag = function(){
	//prenext line foucs
	var fl = this.getTagLocation(this.currentFocusElement.tagLocation);
	var l = parseInt(fl[0])+1;

	if (!this.focusTags[l])
		return false;
	
	if (parseInt(fl[1])>= (this.focusTags[l].length - 1))
		ln = this.focusTags[l].length - 1;
	else
		ln = fl[1];
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getPrevLineFirstFocusTag = function(){
	var fl = this.getTagLocation(this.currentFocusElement.tagLocation);
	l = parseInt(fl[0])-1;
	ln = parseInt(1);
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getNextLineFirstFocusTag = function(){
	var fl = this.getTagLocation(this.currentFocusElement.tagLocation);
	l = parseInt(fl[0])+1;
	ln = parseInt(1);
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getPrevLineLastFocusTag = function(){
	var fl = this.getTagLocation(this.currentFocusElement.tagLocation);	
	l = parseInt(fl[0])-1;
	
	if (!this.focusTags[l])
		return false;	
	
	ln = this.focusTags[l].length - 1;	
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getNextLineLastFocusTag = function(){
	var fl = this.getTagLocation(this.currentFocusElement.tagLocation);	
	l = parseInt(fl[0])+1;
	
	if (!this.focusTags[l])
		return false;	
	
	ln = this.focusTags[l].length - 1;	
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getPrevFocusTag = function(){
	var fl = this.getTagLocation(this.currentFocusElement.tagLocation);
	l = fl[0];
	ln = parseInt(fl[1])-1;
	return this.getTagObj(l, ln);
}

EzFocus.prototype.getNextFocusTag = function(){
	var fl = this.getTagLocation(this.currentFocusElement.tagLocation);
	l = fl[0];
	ln = parseInt(fl[1])+1;
	return this.getTagObj(l, ln);
}

EzFocus.prototype.runImageDivOnMouseEvent = function (tagObj, eventType){
	divsObj = tagObj.getElementsByTagName("DIV");

	if (divsObj.length>0){
		divObj = divsObj[0];
		if ((eventType == 'onmouseover') && (divObj.onmouseover != undefined)){
			if (!/this/.test(divObj.onmouseover)){
				setTimeout(divObj.onmouseover, 0);
			}
		}
		else if ((eventType == 'onmouseout') && (divObj.onmouseover != undefined)){
			if (!/this/.test(divObj.onmouseout))
				setTimeout(divObj.onmouseout, 0);
		}
	}
}

EzFocus.prototype.focusWithKeyboard = function (tagObj, evt){
	if (!tagObj)
		return false;

	this.setCurrentFocusElement(tagObj);

	this.runImageDivOnMouseEvent(this.previousFocusElement, 'onmouseout');
	//run user define onmouseout function.
	if (!/this/.test(this.previousFocusElement.userOnMouseOut) && (this.previousFocusElement.userOnMouseOut != undefined))
		setTimeout(this.previousFocusElement.userOnMouseOut, 0);
	this.unsetTagBorder(this.previousFocusElement);
		
	this.runImageDivOnMouseEvent(tagObj, 'onmouseover');
	if (!/this/.test(tagObj.userOnMouseOver) && (tagObj.userOnMouseOver != undefined))
		setTimeout(tagObj.userOnMouseOver, 0);
	this.setTagBorder(tagObj);

	if (tagObj.style.visibility == "hidden"){
		this.checkKeyCode(evt);
	}	
}

EzFocus.prototype.setUserBorder = function (tagObj, v){
	var bv = v.split(" ");

	if (bv.length == 3){
		bw = bv[0];
		if (bw != 0)
			tagObj.userBorderWidth = bw;
			
		bs = bv[1]
		if (bs != 0)
			tagObj.userBorderStyle = bs;
		
		bc = bv[2];
		if (bc != 0)
			tagObj.userBorderColor = bc;
	}
	else if (bv.length == 2){
		bw = bv[0];
		if (bw != 0)
			tagObj.userBorderWidth = bw;
			
		bs = bv[1]
		if (bs != 0)
			tagObj.userBorderStyle = bs;
	}
	else if (bv.length == 1){
		bw = bv[0];
		if (bw != 0)
			tagObj.userBorderWidth = bw;
	}
}

EzFocus.prototype.setBorderById = function (tagId, v){
	tagObj = document.getElementById(tagId);
	this.setUserBorder(tagObj, v);
}

EzFocus.prototype.setBorderByClassName = function (tagClassName, v){
	for (var l in this.focusTags){
		for(var ln in this.focusTags[l]){
			if (tagClassName == this.focusTags[l][ln].className){

				this.setUserBorder(this.focusTags[l][ln], v);
				break;
			}
		}
	}
}

EzFocus.prototype.setUseEzFocusBorderById = function (tagId, v){
	tagObj = document.getElementById(tagId);
	if (tagObj)
		tagObj.useEzFocusBorder = v;
}

EzFocus.prototype.setUseEzFocusBorderByClassName = function (tagClassName, v){
	for (var l in this.focusTags){
		for(var ln in this.focusTags[l]){
			if (tagClassName == this.focusTags[l][ln].className){

				this.focusTags[l][ln].useEzFocusBorder = v;
				break;
			}
		}
	}
}

EzFocus.prototype.setFocus = function (tagObj){
	this.onMouseOver(tagObj);
}

/*  */
EzFocus.prototype.setEzFocus = function (tagObj){
	ezFocus.isMoveFocus = false;
	ezFocus.onMouseOver(tagObj);
}

EzFocus.prototype.setFocusStopMove = function (tagObj){
	this.isMoveFocus = false;
	this.onMouseOver(tagObj);
}

EzFocus.prototype.checkKeyCode = function (event){
	try{

		if (!this.isInitFocus){
			//init array
			var focusTags = new Array();
			
			var allTags = document.getElementsByTagName('*');

			var l = 0;
			var ln = 0;
			for(var i = 0; i < allTags.length; i++){
				var tagObj = allTags[i];
				var className = tagObj.className;
				if (className.length>0){
					if (/^[\d]+-[\d]+$/.test(className)){
						//
						tagObj.useEzFocusBorder = 1;
						if (tagObj.onmouseover != undefined){
							tagObj.userOnMouseOver = tagObj.onmouseover;
						}
						tagObj.onmouseover = function (){ezFocus.onMouseOver(this)};

						if (tagObj.onmouseout != undefined)
							tagObj.userOnMouseOut = tagObj.onmouseout;
						tagObj.onmouseout = function (){ezFocus.onMouseOut(this)};

						var fl = this.getTagLocation(className);
						l = fl[0];
						ln = fl[1];
						if (!focusTags[l])
							focusTags[l] = new Array();
							
						focusTags[l][ln] = tagObj;
					}
				}
			}

			//sort line
			var newFocusTags = new Array();
			var keys = new Array();
			for(var i in focusTags){
				keys.push(i);
			}
			keys.sort(function (a,b){return a - b});
			for(var k in keys){
				newFocusTags[keys[k]] = focusTags[keys[k]];
			}
			
			var l = 1;
			for(var i in newFocusTags){
				if (newFocusTags[i].length == 0)
					continue;
				
				//for sort array
				var keys = new Array();
				for (k in newFocusTags[i]){
					keys.push(k);
				}
				keys.sort(function (a,b){return a - b});

				var c = 1;
				var newCols = new Array();
				for(var j = 0; j < keys.length; j++){
					var e = newFocusTags[i][keys[j]];
					e.tagLocation = l+'-'+c;
					newCols[c] = e;
					c++;
				}
				if (!this.focusTags[l]){
					this.focusTags[l] = new Array();
				}

				this.focusTags[l] = newCols;
				l++;
			}
			
			this.lastFocusElement = this.focusTags[l-1][c-1];
			this.isInitFocus = true;
		}

		if (event == null)
			return true;
		
		if (this.currentFocusElement == null){
			this.setCurrentFocusElement(this.focusTags[1][1]);
			this.setTagBorder(this.currentFocusElement);
			return;
		}

		if (!this.isMoveFocus){
			this.isMoveFocus = true;
			return true;
		}

		switch (event.keyCode) {
			case this.KEY_UP:
				var focusTag = null
				if (prevLineFocusTag = this.getPrevLineFocusTag()){
					focusTag = prevLineFocusTag;
				} else if (lastLineFocusTag = this.getLastLineFocusTag()){
					focusTag = lastLineFocusTag;
				}
				this.focusWithKeyboard(focusTag, event);
				break;
				
			case this.KEY_DOWN:
				var focusTag = null;
				if (nextLineFocusTag = this.getNextLineFocusTag()){
					focusTag = nextLineFocusTag;
				} else if (firstLineFocusTag = this.getFirstLineFocusTag()){
					focusTag = firstLineFocusTag;
				}
				this.focusWithKeyboard(focusTag, event);
				break;
				
			case this.KEY_LEFT:
				var focusTag = null;
				if (prevFocusTag = this.getPrevFocusTag()){
					focusTag = prevFocusTag;
				} else if (prevLineLastFocusTag = this.getPrevLineLastFocusTag()){
					focusTag = prevLineLastFocusTag;
				} else {
					focusTag = this.getLastFocusTag();
				}
				this.focusWithKeyboard(focusTag, event);
				break;

			case this.KEY_RIGHT:
				var focusTag = null
				if (nextFocusTag = this.getNextFocusTag()){
					focusTag = nextFocusTag;
				} else if (nextLineFirstFocusTag = this.getNextLineFirstFocusTag()){
					focusTag = nextLineFirstFocusTag;
				} else {
					focusTag = this.getFirstFocusTag();
				}
				this.focusWithKeyboard(focusTag, event);
				break;

			case this.KEY_ENTER:
				if (this.currentFocusElement.onmousedown != undefined){
					var fnc = this.currentFocusElement.onmousedown;
					if (!/this/.test(fnc))
						setTimeout(fnc, 0);
				}
				else if (this.currentFocusElement.onclick != undefined){
					var fnc = this.currentFocusElement.onclick;
					if (!/this/.test(fnc))
						setTimeout(fnc, 0);
				}
				break;
		}
	} catch(e){
			this.debug(e.toString());
	}
}

var ezFocus = new EzFocus;
document.onkeyup = function keyUp(event){
	ezFocus.checkKeyCode(event);
}

function initEzFocus(){
	ezFocus.checkKeyCode(null);
}
window.addEventListener("DOMContentLoaded", initEzFocus, false);
