/**
* autocompleter for webT::CMS 
*
* @version 0.4
* @author goshi
* @package javascript::CMS
*	
* Changelog:
*	0.4	25.12.10/goshi	fixes bugs with repostion loader, add 'no_wait' mode, fix checkTout bug, fix loader hidden bug
*	0.3	23.11.10/goshi	some refactoring for using cursor, remove some bugs
*	0.2	30.07.10/goshi	add new callback support
*	0.1	13.06.10/goshi	
*
*/

/* control tabs switcher */
function objAutocompleter(params){
	this._init(params);
	this._thisid = objAutoInstances.length;
	objAutoInstances[objAutoInstances.length] = this;	
}

objAutocompleter.prototype = {

	_objid : null,
	_loader_show : true,	// show loader
	_loader_align : true, // aligning loader to the right of the input field
	_ajxhref : null,
	_minchars : 3,
	_no_wait : false,	// flag for waiting for another key press before sending request
	_callbacks : {},	// callbacks stack, now supporting 'before' and 'apply' methods. see below
	_checkTout : 2000,	// timeout for complite
	_params : {},		// additional parameters for query

	// internal values
	_checkTimer : null,
	_checkTicket : null,
	_loader : null,
	_thisid : null,
	_results : null,	// string with results
	_results_cnt : 0, // integer with results count
	_bg : null,
	_cursor: null,		// current cursor position of the result
		
	addParams : function(params){
		
		if (typeof params == 'object' && params != null){
			
			for (var k in params){
				if (this['_'+k] != 'undefined'){
					this['_'+k] = params[k];
				}
			}			
		}	
	},
		
	_init : function (params){
	
		this.addParams(params);
	
		if (!this._objid || !$_(this._objid)) return;
		
		var athis = this;
		var callComplite = function (e){
		
			// stoping standart event
			return athis._callComplete(e, athis);
		
		}
		
		// attach events to the field
		//portal.events.attach($_(this._objid), 'keyup', _callback_up, false);
		portal.events.attach($_(this._objid), 'keyup', callComplite, false);
			
	},
	
	/**
	* moving cursor throw results
	*/
	_moveCursor : function(obj, cursor){
		var childs = obj._results.getElementsByTagName('li');
		for (var i=0,len=childs.length; i<len; i++){
			if (i != cursor || cursor == null)
				portal.css.removeClass(childs[i], 'active');
			else
				portal.css.addClass(childs[i], 'active');
		}
	},
	
	/* field checker part 
	force_caller need ,if we call this function from outside */
	_callComplete : function(e, obj){
		
		// protect for empty value
		if ($_(obj._objid).value == '' || $_(obj._objid).value.length < obj._minchars) return;
		
		// remove timer
		if (obj._checkTimer){
			if (typeof obj._checkTicket != "undefined" && obj._checkTicket)
				portal.loader.destroy(obj._checkTicket);
			clearTimeout(obj._checkTimer);
		}
		
		// for Enter key - return
		switch (portal.events.getKey(e)){
		
		// enter press
		case 13:
		case 3:
			obj._hideResults(obj._thisid);
			if (obj._cursor != null){
				
				obj._applyValue(obj._thisid, 'ac-'+obj._thisid+'-'+obj._cursor, strip_tags($_('ac-'+obj._thisid+'-'+obj._cursor).innerHTML));
				return false;
			} else
				return;
			break;
		
		// up	
		case 38:
			var cursor = obj._cursor == null ? 0 : obj._cursor-1;
			if (cursor >= 0){
				obj._cursor = cursor;
				obj._moveCursor(obj, obj._cursor);
			}
			return false;
			break;
		
		// down	
		case 40:
			// check for results present
			var cursor = obj._cursor == null ? 0 : obj._cursor+1;
			if (cursor < obj._results_cnt){
				obj._cursor = cursor;
				obj._moveCursor(obj, obj._cursor);
			}
			return false;
			break;
		
		// escape	
		case 27:
			// cleanup field
			$_(this._objid).value = '';
			return false;
			break;
			
		case 91: // apple command
		case 18: // apple alt
		case 17: // apple ctlr
		case 16: // apple shift
		case 20: // apple CAPS
		case 37: // apple left
		case 39: // apple right
		case 112: // apple F1
		case 113: // apple F2
		case 114: // apple F3
		case 115: // apple F4
		case 116: // apple F5
		case 117: // apple F6
		case 118: // apple F7
			return false;
			break;
		
		}
		
		var target = window.event ? window.event.srcElement : e.target;
		
		// remove ticket
		if (typeof obj._checkTicket != "undefined" && obj._checkTicket)
			portal.loader.destroy(obj._checkTicket);
		
		// setting loader ticket
		if (obj._loader_show){
			if (obj._loader == null){
				obj._loader = elem('ins', {'id' : '_acl_'+obj._thisid}, {'position': 'absolute', 'z-index': '1000000'});
				document.body.appendChild(obj._loader);
				obj._loader.style.display = 'block';
			} else
				obj._loader.style.display = 'block';
				
			obj._checkTicket = portal.loader.create(obj._loader, {"mode" : "mini"});
		}
		
		// checking for align loader
		if (obj._loader_align && obj._loader_show){
			
			setTimeout(function(){obj.get(obj._thisid)
				var pos = portal.dom.getAbsPosition(obj._objid);
				try{
					var border = document.defaultView.getComputedStyle($_(obj._objid), '').getPropertyValue('border-right-width');
				} catch(e){
					var border = $_(obj._objid).currentStyle.borderWidth;
				}
				obj._loader.style.left = (pos.x + pos.w - obj._loader.offsetWidth - 2*parseInt(border)) + 'px';
				obj._loader.style.top = (pos.y + pos.h - obj._loader.offsetHeight - parseInt(border)) + 'px';
			}, 100);

		}
		
		obj._checkTimer = setTimeout(function(){obj.get(obj._thisid)}, obj._no_wait ? 0 : obj._checkTout);
		//obj.get(obj._thisid);
		
	},
	
	_applyValue : function (id, elem_id, value){

		var athis = objAutoInstances[id];
		$_(athis._objid).value = value.replace(/(<([^>])*>|>|<)/gi, '');
		$_(athis._objid).focus();
		
		athis._hideResults(id);
		athis._cursor = null;
		
		// checking for callback
		if (typeof athis._callbacks['apply'] == 'function')
			athis._callbacks['apply'](athis, {'id' : elem_id, 'value' : value});

	},
	
	_connectEventsToResult : function(id, obj){
		
		var athis = objAutoInstances[id];
		portal.events.attach(obj, 'click', function(){athis._applyValue(id, obj.id, strip_tags(obj.innerHTML))});
		portal.events.attach(obj, 'mouseover', function(){athis._cursor = null; athis._moveCursor(athis, athis._cursor)});
	
	},
	
	_insertResults : function (id, results){
	
		var athis = objAutoInstances[id];
		
		if (athis._results == null){
			
			athis._results = elem('div', {'id' : '_acr_'+athis._thisid, 'class' : 'auto_complete'}, {'position' : 'absolute', 'display' : 'none', 'z-index' : '1000001'});
			athis._bg = elem('div', {'id' : '_acb_'+athis._thisid}, {'position' : 'absolute', 'display' : 'none', 'z-index' : '1000000', 'width' : getClientWidth() + 'px', 'height' : getDocumentHeight() +'px', 'left' : '0px', 'top' : '0px'}, ' ');
			document.body.appendChild(athis._bg);
			document.body.appendChild(athis._results);
			
			portal.events.attach(athis._bg, 'click', function(){athis._hideResults(id)});
		}
		
		if (typeof results != 'undefined' && results){
			athis._results.innerHTML = results;
			athis._results.style.display = 'block';
			
			// reposition results
			var pos = portal.dom.getAbsPosition(athis._objid);
			athis._results.style.top = (pos.y + $_(athis._objid).offsetHeight) + 'px';
			athis._results.style.width = $_(athis._objid).offsetWidth + 'px';
			athis._results.style.left = pos.x + 'px';
			athis._bg.style.width = getClientWidth() + 'px';
			athis._bg.style.height = getDocumentHeight() +'px';
			
			// attaching events for each
			var childs = athis._results.getElementsByTagName('li');
			for (var i=0,len=childs.length; i<len; i++){
				athis._connectEventsToResult(id, childs[i]);
				childs[i].setAttribute('id', 'ac-'+athis._thisid+'-'+i);
			}
			// saving results count
			athis._results_cnt = childs.length;
			
			// add bg for clicking
			athis._bg.style.display = 'block';
		}
	
	},
	
	_hideResults : function (id){
		
		var athis = objAutoInstances[id];
		
		if (athis._results)
			athis._results.style.display = 'none';
		if (athis._bg)	
			athis._bg.style.display = 'none';
	
	},
	
	/* for cheking field */
	get : function(id){
		
		var req = new JsHttpRequest();			
		var athis = objAutoInstances[id];
		req.onreadystatechange = function (){
					
			if (req.readyState == 4){
				
				// remove ticket
				if (athis._loader_show){
					if (typeof athis._checkTicket != "undefined" && athis._checkTicket)
						portal.loader.destroy(athis._checkTicket);
					athis._loader.style.display = 'none';
				}				
				// checking response from REST controller
				if (req.responseJS.status == 200){
					athis._insertResults(id, req.responseJS.response);
				}
				
			}
			
		}
				
		req.open("POST", athis._ajxhref, true);
	
		//combining parameters
		var params = {};
		if (typeof athis._params == "object"){
			for (var i in athis._params){
				params[i] = athis._params[i];
			}
		}
		
		params[$_(athis._objid).getAttribute('name')] = $_(athis._objid).value;
		// checking for callback
		if (typeof athis._callbacks['before'] == 'function'){		
			params = athis._callbacks['before'](params);
		}
		
		// trying to understand what we have to load
		req.send(params);
	}
	
	

}

objAutoInstances = [];
