//
//			A.St. Suggest Box
// 			2010-08-30
//
Suggest = function( obj, src, pic, params) {						// конструктор
    this.obj 						= obj;
    this.serverScript 		= src;
	this.loadPic				= new Image();
	this.loadPic.src 		= pic || null;
    this.params				= params;
    this.suggestBox 		= null;
    this.lastQueryTime 	= null;
    this.minDelay				= 100;																// минимальная задержка выполнения на случай работы с быстро печатающим товарищем.
    this.obj.suggest 		= this;
    this.ajax 						= new Ajax( this.requestHandler);
    this.box 						= null;
	this.counter				= 0;
	this.currentValues 	= {};
	this.currentValues.length = 0;
	this.stopBlur 				= false;
	this.initFlag				= false;
// 		:KLUDGE:
	this.formElem			= document.forms[0];

	// этот элемент будет принимать значения
	this.result = document.createElement( "input");
	this.result.setAttribute( "type", "hidden");
	this.result.setAttribute( "name", this.obj.name);
	this.obj.name += "__old";					// меняем название
	this.obj.parentNode.appendChild( this.result);
	Event.add( this.obj, "keyup", this.keyPressHandler);
	Event.add( this.obj, "focus", this.focusHandler);
	Event.add( this.obj, "blur", this.blurHandler);
}
Suggest.prototype = {
	init: function() {
		this.initFlag = true;
		this.sendRequest();
	},
    sendRequest: function() {
		this.ajax.sendRequest( this.serverScript, "post", "value="+ this.obj.value + ( this.params > "" ? "&" + this.params : ""), this);
	   if ( this.loadPic.src ) {
		   this.obj.style.background = "url("+ this.loadPic.src +") 100% 0% no-repeat";
	   }
    },
    requestHandler: function( data, obj) {
		if ( data != "{}" ) {
	       answer = get_JSON( data);
	       obj.addList( answer);
		} else {
			obj.delBox();
		}
		if ( obj.loadPic.src) {
			obj.obj.style.background = "none";
		}
    },
    addBox: function() {
		if ( !this.box) {
		    this.box = document.createElement( "div");
		    this.box.className = "box";
		    this.box.style.width = (parseInt( this.obj.offsetWidth) - 4) + "px";
		    document.body.appendChild( this.box);
			thisObj = this;
			Event.add( this.box, "mousedown", function() {thisObj.stopBlur = true});
// 			Event.add( this.box, "mouseup", function() {thisObj.stopBlur = false; alert( thisObj.obj); thisObj.obj.focus()});

		} else {
			this.box.style.display = "block";
		    delete_children( this.box);
		}
    },
    addString: function( value) {
		div = document.createElement( "div");
		div.className = "line";
		div.innerHTML = value;
		this.box.appendChild( div);
		div.suggest = this;
		Event.add( div, "mouseover", this.mOverStringHandler);
		Event.add( div, "mouseout", this.mOutStringHandler);
 		Event.add( div, "click", this.clickStringHandler);
		return div;
    },
	addList: function( data) {
		this.currentValues = {};
		this.counter = 0;
		this.addBox();
		counter = 1;
		for ( var i in data) {
		    div = this.addString( data[i]);
			this.currentValues[counter] = {"id": i, "value": data[i], "obj": div}
			div.num = counter;
			counter ++;
		}
	    if ( this.initFlag) {
			this.chooseString( 1);
	    }
		this.currentValues.length = counter;
		this.moveBox();
    },
    moveBox: function() {
	    if ( this.box) {
			coord = getOffset( this.obj);
			this.box.style.left 	= coord.left;
			this.box.style.top 	= coord.top + this.obj.offsetHeight;
	    }
    },
    delBox: function() {
		if ( this.box && this.box.style.display != "none") {
			this.box.style.display = "none";
			delete_children( this.box);
		}
	},
	selectString: function( string) {
		string.className = string.className + " selected";
	},
	blurString: function( string) {
		string.className = string.className.replace( " selected", "");
	},
	chooseString: function( num) {
		if ( num != 0 ) {
			this.result.value	= this.currentValues[num].id;
			this.obj.value 		= get_text( this.currentValues[num].obj);
			this.delBox();
			this.obj.blur();
			this.initFlag = false;
		}
	},
	mOverStringHandler: function( event) {
		thisObj = event.currentTarget.suggest;
		if ( thisObj.currentValues[thisObj.counter]) {
			thisObj.blurString( thisObj.currentValues[thisObj.counter].obj);
		}
		thisObj.counter = event.currentTarget.num;
		thisObj.selectString( event.currentTarget);
	},
	mOutStringHandler: function( event) {
		event.currentTarget.suggest.blurString( event.currentTarget);
	},
	clickStringHandler: function( event) {
		event.currentTarget.suggest.chooseString( event.currentTarget.num);
	},
	cancelSubmitFunc: function( event) {
// 		:KLUDGE:
		if ( navigator.appName != "Opera") {
			 if ( event.which == 13 ) {
				event.preventDefault();
			 }
		} else {
			return false;
		}
	},
	focusHandler: function( event) {
		event.currentTarget.select();

// 		:KLUDGE:
		if ( navigator.appName != "Opera") {
			Event.add( event.currentTarget.suggest.formElem, "keydown", event.currentTarget.suggest.cancelSubmitFunc);
		} else {
			Event.add( event.currentTarget.suggest.formElem, "submit", event.currentTarget.suggest.cancelSubmitFunc);
		}
	},
	blurHandler: function( event) {
		thisObj = this.suggest;
		if ( !thisObj.stopBlur) {
			window.setTimeout( function() {thisObj.delBox()}, 500);
		}
// 		:KLUDGE:
		if ( navigator.appName != "Opera") {
			Event.remove( thisObj.formElem, "keydown", thisObj.cancelSubmitFunc);
		} else {
			Event.remove( thisObj.formElem, "submit", thisObj.cancelSubmitFunc);
		}
	},
    keyPressHandler: function( event) {							// здесь this -> this.obj
		event.stopPropagation();
		event.preventDefault();
		currentTime = new Date();
		// условия отправки запроса:
		//	- не чаще, чем один раз в minDelay мс.
		//	- если предыдущий запрос уже обработан
		// 	- если нажата клавиша, отличная от служебной
		// устанавливаем, надо ли обработать перемещение по списку или отправку запроса.
		if ( in_obj( event.which, [37,38,39,40,13]) < 0) {
		    if ( this.suggest.obj.value.length >= 3) {
				if ( currentTime = currentTime.getTime() - this.suggest.lastQueryTime > this.suggest.minDelay ) {
				    this.suggest.lastQueryTime = currentTime;
				    this.suggest.sendRequest();
				}
		    } else {
				this.suggest.delBox();
		    }
		} else {
		    // обрабатываем нажатие стрелок и enter
			switch ( event.which ) {
				case 38:
					if ( this.suggest.currentValues[this.suggest.counter]) {
						this.suggest.blurString( this.suggest.currentValues[this.suggest.counter].obj);
					}
					if ( this.suggest.currentValues[(this.suggest.counter - 1 < 0 ? 0 : -- this.suggest.counter)]) {
						this.suggest.selectString( this.suggest.currentValues[this.suggest.counter].obj);
					}
					break;
				case 40:
					if ( this.suggest.currentValues[this.suggest.counter]) {
						this.suggest.blurString( this.suggest.currentValues[this.suggest.counter].obj);
					}
					if ( this.suggest.currentValues[(this.suggest.counter + 1 > this.suggest.currentValues.length ? this.suggest.currentValues.length : ++ this.suggest.counter)]) {
						this.suggest.selectString( this.suggest.currentValues[this.suggest.counter].obj);
					}
					break;
				case 13:
					this.suggest.chooseString( this.suggest.counter);
					event.preventDefault();
					break;
			}

		}
    }
}
