/*
 * GTK Suggestion
 */

//v1.0
GTK = {version: '1.0'};

//Suggestion Constructor
GTK.Suggestion = function(dataSource,matchMode,pageSize,pageNo,dismissValues){
	if(!dataSource)
		return null;
	this.xDataSource = dataSource;
	if(dismissValues)
		this.xDismissValues = dismissValues;
	
	if(!matchMode){this.xMatchMode = 0;}else{this.xMatchMode = matchMode;}
	if(!pageSize){this.xPageSize = 15;}else{this.xPageSize = pageSize;}
	if(!pageNo){this.xPageNo = 1;}else{this.xPageNo = pageNo;}
	
	this.inputValue = "";
	this.items = new Array();
	this.activeItem = null;
	this.sequence = 0;
};

//Suggestion property and function
GTK.Suggestion.prototype = {
	//public
	attachTo : function(targetObject,action,defaultValue){
        this.xTargetObject = targetObject;
		this.xAction = action;
		this.xDefaultValue = defaultValue;
        //initialize
        this.initialize();
        
        var thisHandler=this;
        this.xTargetObject.onfocus = function(e){if(!e) e=window.event; thisHandler.onFocus(e);};
        this.xTargetObject.onblur = function(e){if(!e) e=window.event; thisHandler.onBlur(e);};
        this.xTargetObject.onkeyup = function(e){if(!e) e=window.event; thisHandler.onKeyUp(e);};
    },
	
    /** Event handlers **/
    
    // private
    onFocus : function(e){
    	this.isVisible = true;
			this.isSelected = false;
			if(this.isSubmit||(this.xDefaultValue&&this.xTargetObject.value==this.xDefaultValue)){
				this.xTargetObject.value = "";
				this.isSubmit = false;
			}
    	this.freshItems();
    	this.show();
    },
    
    // private
    onBlur : function(e){
    	this.isVisible = false;
    	var thisHandler=this;
    	if(thisHandler.xDefaultValue&&(thisHandler.xTargetObject.value==null||thisHandler.xTargetObject.value==""))
    		thisHandler.setTargetValue(thisHandler.xDefaultValue);
    	this.hideTimer = window.setTimeout(function() {
            	thisHandler.hide();
            	if(thisHandler.inputValue != thisHandler.xTargetObject.value){
            		thisHandler.isDirty = true;
            	}
        	},300);
    },
    
    // private
    onKeyUp : function(e){
    	//Switch keyCode
    	if(e.keyCode == 38){
    		//up
    		this.previousItem();
    	}
    	else if(e.keyCode == 40){
    		//down
    		this.nextItem();
    	}
    	else {
    		//value change
			this.xPageNo = 1;
    		this.freshItems();
    		this.show();
			if(e.keyCode == 13){
    			//enter
				var thisHandler=this;
				thisHandler.submit(e,this.activeItem);
    		}
    	}
    },
	
    // private
    onClick : function(e,itemid){
		var thisHandler=this;
		thisHandler.submit(e,itemid);
    },
	
    // private
    onMouseOver : function(e,itemid){
        this.setActiveItem(itemid);
    },

    // private
    onMouseOut : function(e,itemid){
        
    },
	
	submit : function(e,itemid){
		
		if(!itemid) return;
		this.isSelected = true;
		var item = this.findItem(itemid);
		if(item != null){
			if(item.value==null||item.value==''){
				this.isSelected = false;
				return;
			}
			this.inputValue = item.name;
			this.setTargetValue(this.inputValue);
			this.isDirty = true;
		}
		this.isSubmit=true;
		this.xPageNo = 1;
		var thisHandler=this;
		this.xTargetObject.blur();
		thisHandler.hide();
		//action
		if(this.xAction){
			var aAction = this.xAction.replace("&0","'"+item.value+"'"); 
			eval(aAction);
		}
    },
	
	gotoPage : function(e,pageNo){
		this.cancelHide(e);
		if(!pageNo){return;}else{this.xPageNo = pageNo;}
		
		this.isDirty = true;
		this.isVisible = true;
    	this.freshItems();
    },
	
	cancelHide : function(e){
		window.clearTimeout(this.hideTimer);
		this.hideTimer = null;
		this.isVisible = true;
		if(!this.isSelected){
			this.xTargetObject.focus();
			this.xTargetObject.value = this.xTargetObject.value;
		}
    },
	
    /** suggestion entity propers methods **/
    
    // private
    initialize : function(){
    	this.createElement();
    	
    	this.inputValue = "";
		this.items = new Array();
		this.activeItem = null;
		
		this.isVisible = true;
    	this.isDirty = true;
    },
    
    // private
    createElement : function(){
    	if(this.el){
    		this.removeAll();
    		this.adjustElement();
    		return;
    	}
    	
    	var el = this.el = document.createElement("div");
       	el.id = "suggestion-" + this.xTargetObject.id + "-" + this.nextSequence();
       	
       	var iframe = this.iframe = document.createElement("iframe");
       	iframe.id = "suggestion-iframe-" + this.xTargetObject.id + "-" + this.nextSequence();
        this.adjustElement();
        
        var ul = this.ul = document.createElement("ul");
        ul.className = "x-suggestion-list";
        ul.id = "suggestion-list-" + this.xTargetObject.id + "-" + this.nextSequence();
        el.appendChild(ul);
        
        document.body.appendChild(el);
        document.body.appendChild(iframe);
		var thisHandler=this;
        el.onclick = function(e){if(!e) e=window.event; thisHandler.cancelHide(e);};
        iframe.onclick = function(e){if(!e) e=window.event; thisHandler.cancelHide(e);};
		ul.onclick = function(e){if(!e) e=window.event; thisHandler.cancelHide(e);};
		//adjustPosition
		window.setTimeout(function() {thisHandler.adjustPosition();},500);
    },
    
    //private
    adjustElement : function(){
    	var xPos = GTK.Dom.getXY(this.xTargetObject);
    	var xWidth = this.xTargetObject.offsetWidth;
    	var xHeight = this.xTargetObject.offsetHeight;
    	
    	this.el.className = "x-suggestion";
        this.el.style.position = "absolute";
        this.el.style.visibility = "hidden";
        this.el.style.left = xPos.x+"px";
        this.el.style.top = xPos.y+xHeight+"px";
        this.el.style.width = xWidth+"px";
        this.el.style.zIndex = "15000";
        
        this.iframe.src = "about:blank";
        this.iframe.frameborder = "0";
        this.iframe.scrolling = "no";
        this.iframe.style.position = "absolute";
        this.iframe.style.visibility = "hidden";
        this.iframe.style.left = this.el.style.left;
		this.iframe.style.top = this.el.style.top;
		this.iframe.style.width = this.el.offsetWidth + "px";
		this.iframe.style.height = this.el.offsetHeight + "px";
		this.iframe.style.zIndex = this.el.style.zIndex-1;
    },
	
	    //private
    adjustPosition : function(){
    	var xPos = GTK.Dom.getXY(this.xTargetObject);
    	var xWidth = this.xTargetObject.offsetWidth;
    	var xHeight = this.xTargetObject.offsetHeight;
    	var yHeight = this.el.offsetHeight;
    	
        this.el.style.position = "absolute";
        this.el.style.left = xPos.x+"px";
        this.el.style.top = xPos.y-yHeight+"px";
        
        this.iframe.style.position = "absolute";
        this.iframe.style.left = this.el.style.left;
		this.iframe.style.top = this.el.style.top;
		var thisHandler = this;
		this.adjustPositionTimer = window.setTimeout(function() {thisHandler.adjustPosition();},500);
    },
    
    //private
    show : function(){
    	if(this.isVisible && !this.isDirty && this.items.length > 0){
    			this.adjustPosition();
        	this.el.style.visibility = "visible";
        	this.iframe.style.visibility = "visible";
    	}
    	else{
    		this.el.style.visibility = "hidden";
    		this.iframe.style.visibility = "hidden";
    	}
    },
    
    //private
    hide : function(){
       this.el.style.visibility = "hidden";
       this.iframe.style.visibility = "hidden";
    },
   
    // private
    autoWidth : function(){
        this.el.style.width = "";
        var sWidth = this.el.offsetWidth;
        var xWidth = this.xTargetObject.offsetWidth;
        if(sWidth < xWidth){
        	this.el.style.width = xWidth+"px";
        }
        
        this.iframe.style.width = (this.el.offsetWidth-6) + "px";
		this.iframe.style.height = (this.el.offsetHeight-6) + "px";
		this.iframe.style.zIndex = this.el.style.zIndex-1;
    },
    
    //private
    findItem : function(id){
    	var item = null;
        for (var i=0; i<this.items.length; i++) {
			if(this.items[i].id == id){
				item = this.items[i];
				break;
			}
		}
		return item;
    },
    
    //private item = {id:"item1",name:"itemname",sequence:1,isActive:false},
    addItem : function(item){
       	item.sequence = this.nextSequence();
       	item.id = "suggestion-list-item-" + this.xTargetObject.id + "-" + this.sequence;
       	item.isActive = false;
       	this.items[this.items.length] = item;
       	
       	var li = document.createElement("li");
       	li.id = item.id;
       	li.className = "x-suggestion-list-item";
       	this.ul.appendChild(li);
       	
       	var thisHandler=this;
       	li.onmouseover = function(e){if(!e) e=window.event; thisHandler.onMouseOver(e,li.id);};
        li.onmouseout = function(e){if(!e) e=window.event; thisHandler.onMouseOut(e,li.id);};
        li.onclick = function(e){if(!e) e=window.event; thisHandler.onClick(e,li.id);};
       	
       	var a = document.createElement("a");
       	a.id = "suggestion-item-" + this.xTargetObject.id + "-" + this.sequence;
       	a.className = "x-suggestion-item";
        a.href = "javascript:;";
        a.innerHTML = item.name;
        li.appendChild(a);
        
        var img = document.createElement("img");
        img.className = "x-suggestion-item-icon";
        img.id = "suggestion-item-icon-" + this.xTargetObject.id + "-" + this.sequence;
        img.src = "#";
        img.style.width = "1px";
        img.style.visibility = "hidden";
        a.appendChild(img);
        
        this.autoWidth();
        
        return item.id;
    },
	
	addPageBar : function(pageObj){
		var aTotalPage = pageObj.totalPage;
		var aCurrentPage = pageObj.currentPage;
       	
       	var li = document.createElement("li");
       	li.id = "suggestion-pagebar-" + this.xTargetObject.id + "-" + this.nextSequence();;
       	li.className = "x-suggestion-pagebar";
       	this.ul.appendChild(li);
       	
       	var span = document.createElement("span");
		li.appendChild(span);
		
		delete this.pageBarSpan;
		this.pageBarSpan = span;
		
		for (var i=1; i<=aTotalPage; i++) {
			if(i==aCurrentPage){
				var aSpan = document.createElement("span");
				aSpan.className = "x-suggestion-red"; 
				aSpan.innerHTML = i;
				span.appendChild(aSpan);
			}
			else{
				this.addPageBarItem(i);
			}
		}
        
        this.autoWidth();
    },
    
	addPageBarItem : function(pageNo){
		var a = document.createElement("a");
		a.id = "suggestion-pagebar-item-" + this.xTargetObject.id + "-" + this.nextSequence();;
		a.className = "x-suggestion-red";
		a.href = "javascript:;";
		a.innerHTML = pageNo;
		this.pageBarSpan.appendChild(a);
		
		var thisHandler=this;
		a.onclick = function(e){if(!e) e=window.event; thisHandler.gotoPage(e,pageNo);};
    },
	
    //private
    removeItem : function(id){
        for (var i=0; i<this.items.length; i++) {
			if(this.items[i].id == id){
				var item = document.getElementById(id);
				this.ul.removeChild(item);
				
				var temp = new Array();
				for (var j=0; j<i; j++) {
					temp[j] = this.items[j]
				}
				for (var j=i+1; j<this.items.length; j++) {
					temp[j] = this.items[j]
				}
				delete this.items;
				this.items = temp;
				
				if(this.activeItem == id)
					this.activeItem = null;
					
				this.autoWidth();
				
				break;
			}
		}
    },

    //private
    removeAll : function(){
		this.ul.innerHTML = "";
				
		this.activeItem = null;	
		delete this.items;
		this.items = new Array();
    },
    
    //private
    freshItems : function(){
       if(this.inputValue != this.getTargetValue() || this.isDirty){
    		//value change
    		if(this.xDefaultValue==this.getTargetValue()){
    			this.inputValue = "";
    		}else{
    			this.inputValue = this.getTargetValue();
    		}
    		if(this.inputValue == null){
				this.inputValue == "";
       		}
       		
			var thisHandler=this;
    		var aReturn=GTK.Data.request({ ds:this.xDataSource,
				matchKey:this.inputValue,
				pageSize:this.xPageSize,
				pageNo:this.xPageNo,
				disValues:this.xDismissValues
    		});
				
			thisHandler.removeAll();
			if(aReturn.totalData>0){
				var aData = aReturn.data;
				for (var i=0; i<aData.length && i < thisHandler.xPageSize; i++) {
					thisHandler.addItem(aData[i]);
				}
				for (var i=0; i<this.items.length; i++) {
					if(this.items[i].name == this.inputValue){
						this.setActiveItem(this.items[i].id);
						break;
					}
				}
			}
			if(aReturn.totalPage>1){
				thisHandler.addPageBar(aReturn);
			}
			thisHandler.isDirty = false;
			thisHandler.show();
       }
    },
    
    //private
    setActiveItem : function(id){
		var item = this.findItem(id);
		if(item&&(item.value==null||item.value==''))
			return;
        for (var i=0; i<this.items.length; i++) {
        	var item = document.getElementById(this.items[i].id);
			if(this.items[i].id == id){
				item.className = "x-suggestion-list-item x-suggestion-item-active";
			}
			else{
				item.className = "x-suggestion-list-item";
			}
		}
		this.activeItem = id;
    },
    
    //private
    previousItem : function(){
        if(this.items && this.items !=null && this.items.length > 0){
    		var pItem = null;
    		if(!this.activeItem || this.activeItem==null || this.activeItem==''){
    			//start
    			pItem = this.items[this.items.length-1];;
    		}
    		else{
    			for (var i=0; i<this.items.length; i++) {
        			var item = document.getElementById(this.items[i].id);
					if(this.items[i].id == this.activeItem){
						item.className = "x-suggestion-list-item";
						this.setTargetValue(this.inputValue);
						this.activeItem = null;
						if(i != 0){
							//pItem = this.items[i-1];
							for (var j=i-1; j>=0; j--) {
								if(this.items[j].value!=null && this.items[j].value!='')
								{
									pItem = this.items[j];
									break;
								}
							}
							break;
						}
					}
				}
    		}
    		
    		if(pItem == null){
				//start
				var item = document.getElementById(this.items[0].id);
				item.className = "x-suggestion-list-item";
				this.setTargetValue(this.inputValue);
				this.activeItem = null;
			}
			else{
				//on
				if(pItem.value!=null&&pItem.value!=''){
					this.setActiveItem(pItem.id);
					this.setTargetValue(pItem.name);
				}
			}
    	}
    },
    
    //private
    nextItem : function(){
    	if(this.items && this.items !=null && this.items.length > 0){
    		var nItem = null;
    		if(!this.activeItem || this.activeItem==null || this.activeItem==''){
    			//start
    			nItem = this.items[0];
				for (var i=0; i<this.items.length; i++) {
					if(this.items[i].value!=null && this.items[i].value!='')
					{
						nItem = this.items[i];
						break;
					}
				}
    		}
    		else{
    			for (var i=0; i<this.items.length; i++) {
        			var item = document.getElementById(this.items[i].id);
					if(this.items[i].value!=null && this.items[i].value!='' && this.items[i].id == this.activeItem){
						if(i != this.items.length-1)
							nItem = this.items[i+1];
						break;
					}
				}
    		}
    		
    		if(nItem == null){
				//end
				var item = document.getElementById(this.items[this.items.length-1].id);
				item.className = "x-suggestion-list-item";
				this.setTargetValue(this.inputValue);
				this.activeItem = null;
			}
			else{
				//on
				if(nItem.value!=null&&nItem.value!=''){
					this.setActiveItem(nItem.id);
					this.setTargetValue(nItem.name);
				}
			}
    	}
    },
    
    //private
    getTargetValue : function(){
        var tValue = null;
        
        if(this.xMatchMode == 1){
        	oValue = this.xTargetObject.value;
        	var osValue=oValue.split(" ");
        	if(osValue && osValue != null){
        		tValue = osValue[osValue.length-1];
        	}
        }
        else{
        	tValue = this.xTargetObject.value;
        }
        return tValue;
    },
    
    //private
    setTargetValue : function(iValue){
        if(this.xMatchMode == 1){
        	oValue = this.xTargetObject.value;
        	var osValue=oValue.split(" ");
        	if(osValue && osValue != null){
        		osValue[osValue.length-1] = iValue;
        	}
        	this.xTargetObject.value = osValue.join(" ");
        }
        else{
        	this.xTargetObject.value = iValue;
        }
    },
    
    //private
    nextSequence : function(){
    	this.sequence = this.sequence + 1;
    	return this.sequence;
    },
    
    //private
    destroy : function(){
        
    }
};

GTK.lib = {};
GTK.lib.Dom = function(){};
GTK.lib.Dom.prototype = {
	//public
	getXY : function(targetObject){
		var ua = navigator.userAgent.toLowerCase();
		var isOpera = (ua.indexOf('opera') != -1);
		var isIE = (ua.indexOf('msie') != -1 && !isOpera); 
		var el = targetObject;
		if(el.parentNode === null || el.style.display == 'none')
		{
			return false;
		}
		var parent = null;
		var pos = []; 
		var box;
		if(el.getBoundingClientRect)    //IE 
		{
			box = el.getBoundingClientRect();
			var scrollTop = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
			var scrollLeft = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
			if(isIE)
				return {x:box.left + scrollLeft-2, y:box.top + scrollTop-2};
			else
				return {x:box.left + scrollLeft, y:box.top + scrollTop};
		}
		else if(document.getBoxObjectFor)    // gecko
		{
			box = document.getBoxObjectFor(el);
			var borderLeft = (el.style.borderLeftWidth)?parseInt(el.style.borderLeftWidth):0;
			var borderTop = (el.style.borderTopWidth)?parseInt(el.style.borderTopWidth):0;
			pos = [box.x - borderLeft, box.y - borderTop];
		}
		else    // safari & opera 
		{
			pos = [el.offsetLeft, el.offsetTop];
			parent = el.offsetParent; 
			if (parent != el) {
				while (parent) {
					pos[0] += parent.offsetLeft;
					pos[1] += parent.offsetTop;
					parent = parent.offsetParent;
				}
			}
			if (ua.indexOf('opera') != -1 || ( ua.indexOf('safari') != -1 && el.style.position == 'absolute' )){
				pos[0] -= document.body.offsetLeft;
				pos[1] -= document.body.offsetTop;
			}
		}
		if (el.parentNode) { parent = el.parentNode; }
		else { parent = null; }
		while (parent && parent.tagName != 'BODY' && parent.tagName != 'HTML')
		{ 
			pos[0] -= parent.scrollLeft;
			pos[1] -= parent.scrollTop;
			if (parent.parentNode) { parent = parent.parentNode; }
			else { parent = null; }
		}
		return {x:pos[0], y:pos[1]}; 
    }
};
GTK.Dom = new GTK.lib.Dom();

//data
GTK.lib.data =  function(){};
GTK.lib.data.prototype = {
	//public
	request : function(dsObject){
		if(!dsObject || !dsObject.ds || !dsObject.pageSize || !dsObject.pageNo)
			return null;
		
		var ds = dsObject.ds ;
		var matchKey = !dsObject.matchKey?"":dsObject.matchKey ;
		var pageSize = dsObject.pageSize ;
		var pageNo = dsObject.pageNo;
		
		var startPos = pageSize*(pageNo-1);
		var endPos = startPos+pageSize;
	//	var aKeyExp= new RegExp(matchKey,"i");
		var returnData = new Array();
		var index=0;
		for (var i=0; i<ds.length; i++) {
			if(!matchKey||(!this.dismiss(ds[i].name,dsObject.disValues)&&ds[i].matchKey)){
				var aMatchExp = ds[i].matchKey;
				if(this.toMatch(matchKey,aMatchExp)){
					if(index>=startPos&&index<endPos){
						returnData[returnData.length] = {id:ds[i].id,name:ds[i].name,value:ds[i].value,isActive:false};
					}
					index++;
				}
			}
		}
		var aTotalPage = Math.ceil(index/pageSize);
		
		return {totalData:index,data:returnData,totalPage:aTotalPage,pageSize:pageSize,currentPage:pageNo};
    },
	//private
	toMatch : function (val,aMatchExp){
		if(!val||!aMatchExp) return true;
	
		var aMatchName = new Array();
		var aMatchType = new Array();
		var aMatchTypeFull = new Array();
		var aMatchArr = aMatchExp.split("@");
		if(aMatchArr.length>0){
			aMatchName = aMatchArr[0].split("&");
		}
		if(aMatchArr.length>1){
			var aType = aMatchArr[1].split("#");
			if(aType.length>0){
				var aMatchType = aType[0].split("&");
			}
			if(aType.length>1){
				aMatchTypeFull = aType[1].split("&");
			}
		}
		
		var aIsMatch = false;
		var aMatchNameAll = new Array();
		for (var i=0; i<aMatchName.length; i++) {
			aMatchNameAll[aMatchNameAll.length] = aMatchName[i];
		}
		for (var i=0; i<aMatchType.length; i++) {
			aMatchNameAll[aMatchNameAll.length] = aMatchType[i];
		}
		for (var i=0; i<aMatchName.length; i++) {
			for (var j=i; j<aMatchNameAll.length; j++) {
				var matchKey = aMatchNameAll[i];
				for (var k=i+1; k<=j; k++) {
					if(aMatchNameAll[k])
						matchKey = matchKey+"\\s*"+aMatchNameAll[k];
				}
				matchKey = "^"+"\\s*"+matchKey+"\\s*"+"$";
				var aKeyExp = new RegExp(matchKey,"i");
				if(aKeyExp.test(val)){
					aIsMatch=true;
					break;
				}
			}
			if(aIsMatch){
				break;
			}
		}
		if(!aIsMatch){
			for (var i=0; i<aMatchTypeFull.length; i++) {
				for (var j=0; j<aMatchTypeFull.length; j++) {
					var matchKey = aMatchTypeFull[i];
					for (var k=i+1; k<=j; k++) {
						if(aMatchNameAll[k])
							matchKey = matchKey+"\\s*"+aMatchTypeFull[k];
					}
					matchKey = "^"+"\\s*"+matchKey+"\\s*"+"$";
					var aKeyExp = new RegExp(matchKey,"i");
					if(aKeyExp.test(val)){
						aIsMatch=true;
						break;
					}
				}
				if(aIsMatch){
					break;
				}
			}
		}
		return aIsMatch;
	},
	dismiss : function(val,disValues){
		if(!disValues)
			return false;
		for (var i=0; i<disValues.length; i++) {
			var tmp = disValues[i];
			if(val==tmp){
			   //alert(val);alert(tmp);
			   return true;
			}
		}
		return false;
	}
};
GTK.Data = new GTK.lib.data();