function $() {
  var elements = new Array();

  for (var i = 0; i < arguments.length; i++) {
    var element = arguments[i];
    if (typeof element == 'string')
      element = document.getElementById(element);

    if (arguments.length == 1)
      return element;

    elements.push(element);
  }

  return elements;
}

var $A = function(iterable) {
  if (!iterable) return [];
  if (iterable.toArray) {
    return iterable.toArray();
  } else {
    var results = [];
    for (var i = 0; i < iterable.length; i++)
      results.push(iterable[i]);
    return results;
  }
}

Function.prototype.bind = function() {
  var __method = this, args = $A(arguments), object = args.shift();
  return function() {
    return __method.apply(object, args.concat($A(arguments)));
  }
}

if(typeof(XMLHttpRequest) == "undefined")
{
	var XMLHttpRequest = function()
	{
		return new ActiveXObject("Microsoft.XMLHTTP");
	}
}

function CSuggestion(fieldName)
{
	this.objField 		= $(fieldName);
	this.lastRequest 	= '';
	this.timer			= false;
	this.hideTimeOut	= 500;
	this.searchUrl		= '';
	this.searchKey		= '';
	this.searchTarget	= '';
	this.selectedIndex	= -1;
}

//autocomplete="off"

CSuggestion.prototype = {

	init: function( obj )
	{
		this.searchUrl				= obj.searchUrl?obj.searchUrl:'';
		this.searchKey				= obj.searchKey?obj.searchKey:'';
		this.searchTarget			= obj.searchTarget?obj.searchTarget:'';
		this.requestUrl				= obj.requestUrl?obj.requestUrl:'';
		this.objField.onkeyup 		= this.getStrings.bind(this);
		this.objField.onmouseover 	= this.hideTimerReset.bind(this);
		this.objField.onmouseout	= this.hideTimerSet.bind(this);
	},

	resetSelectedIndex: function()
	{
		this.selectedIndex = -1;
	},

	getStrings: function( evt )
	{
		evt = evt ? evt : window.event;
		var srcEl = (evt.target) ? evt.target : evt.srcElement;
		if ( srcEl && srcEl.value != this.lastRequest )
		{
			if ( evt.keyCode != 38 && evt.keyCode != 40 && evt.keyCode != 9 )
			{
				this.request(this.requestUrl+srcEl.value);
				this.lastRequest = srcEl.value;
				this.resetSelectedIndex();
			}
		}
	},

	request: function ( url )
	{
		try{
			var req = new XMLHttpRequest();
		} catch(e) {
			return;
		}

		req.onreadystatechange = function()
		{
			if (req.readyState == 4)
			{
				if (req.status == 200)
				{
					try
					{
						var objContainer = this.createContainer();
						var xml = req.responseXML;
						var words = xml.getElementsByTagName('words');
						if  ( words && words[0] )
						{
							objContainer.innerHTML = '';
							var word_arr = words[0].getElementsByTagName('word');
							if ( word_arr && word_arr.length )
							{
								for (var i = 0; i < word_arr.length; i++ )
								{
									{
										var word 		= document.createElement('A');
										word.onfocus	= function ( evt )
										{
											var evt = (evt) ? evt : ((window.event) ? event : null);
											var target = (evt.target) ? evt.target : evt.srcElement;
											this.objField.value = target.firstChild.nodeValue;
											this.objField.focus();
										}.bind(this);

										word.onmouseover = function ( evt )
										{
											var evt = (evt) ? evt : ((window.event) ? event : null);
											var target = (evt.target) ? evt.target : evt.srcElement;
											if ( this.selectedIndex != -1 )
											{
												var els = $('suggestions').getElementsByTagName('A');
												for ( var i = 0; i < els.length; i++ )
													els[i].className = 'out';
											}
											this.selectedIndex = target.rel;
											target.className = 'over';
										}.bind(this);

										word.onmouseout = function ( evt )
										{
											var els = $('suggestions').getElementsByTagName('A');
											for ( var i = 0; i < els.length; i++ )
												els[i].className = 'out';
										}.bind(this);

										word.setAttribute('tag', word_arr[i].getAttribute('id'));
										word.onclick = function ( evt )
										{
											var evt = (evt) ? evt : ((window.event) ? event : null);
											var target = (evt.target) ? evt.target : evt.srcElement;
											
											location.href = target.getAttribute('href');
											this.updateStatistic( target.getAttribute( 'tag' ) );
											return false;
										}.bind(this);

										word.setAttribute('rel',i);
										word.setAttribute('href', word_arr[i].getAttribute('url'));
										word.setAttribute('target', this.searchTarget);
										
										word.innerHTML 	= word_arr[i].firstChild.nodeValue;
										
										objContainer.appendChild(word);
									}
								}
								objContainer.style.display = '';
							}
							else
							{
								objContainer.style.display = 'none';
							}
						}
					}
					catch (e){}
				}
			}
		}.bind(this);
		
    //this line below doesn't work		
		req.open('GET', url, true);
		
		req.setRequestHeader ('x-requested-with', 'XMLHttpRequest');//
		req.send('');
	},

	hideSuggestions: function()
	{
		if ( $('suggestions') )
		{
			$('suggestions').style.display = 'none';
			this.lastRequest = '';
			this.resetSelectedIndex();
		}
	},

	hideTimerSet: function()
	{
		this.timer = setTimeout(this.hideSuggestions.bind(this), this.hideTimeOut);
	},

	hideTimerReset: function()
	{
		if (this.timer) clearTimeout(this.timer);
	},

	createContainer: function ()
	{
		if ( $('suggestions') ) return $('suggestions');
		var body = document.getElementsByTagName('body');
		if ( body && body[0] )
		{
			var container 				= document.createElement('DIV');
			container.id				= 'suggestions';
			container.style.display 	= 'none';
			container.style.position 	= 'absolute';
			container.onmouseover 		= this.hideTimerReset.bind(this);
			container.onmouseout		= this.hideTimerSet.bind(this);
			body[0].appendChild(container);
			this.containerPosition(container);
		}
		return container;
	},

	setSuggestFocus: function ( action )
	{
		if ( $('suggestions') )
		{
			var els = $('suggestions').getElementsByTagName('A');
			if ( els )
			{
				for ( var i = 0; i < els.length; i++ )
					els[i].className = 'out';

				if ( action == 'down' )
					this.selectedIndex++;
				else
					this.selectedIndex--;

				switch( this.selectedIndex )
				{
					case -1:
					case -2:
						this.selectedIndex = els.length-1;
					break;

					case els.length:
					this.selectedIndex = 0;
					break;
				}

				els[this.selectedIndex].className = 'over';
				if ( $('suggestions') && $('suggestions').style.display == '' )
					els[this.selectedIndex].focus();
				return;
			}
		}
	},

	
	
	updateStatistic: function ( term_id ){
		try{
			var req = new XMLHttpRequest();
		} catch(e) {
			return;
		}
		req.open('GET', this.searchUrl+"?mode=set_statistic&tid=" + term_id, false);
		req.send('');
		
	},
	
	gotoDefinition: function ()
	{
		if ( $('suggestions') )
		{
 			var els = $('suggestions').getElementsByTagName('A');
 			if ( els && this.selectedIndex>=0 && els[this.selectedIndex] )
			{
				var t = els[this.selectedIndex].getAttribute('tag');
				if( t > 0 )
					this.updateStatistic( t );
				location.href = els[this.selectedIndex].href;
				return true;
			}
		}
		return false;
	},
	
	handleArrowKeys: function ( evt )
	{
		var evt = (evt) ? evt : ((window.event) ? event : null);
	    if (evt) {
	        switch (evt.keyCode) {
	            case 38: //up
					this.setSuggestFocus('up');
					break;

	            case 40: //down
					this.setSuggestFocus('down');
					break;
	         }
	    }
	},

	formSubmit: function()
	{
		if ( !this.gotoDefinition() )
		{
			return true;
		}
		return false;
	},
	
	containerPosition: function ( container )
	{
		container.style.left 	= (this.getLeftPos(this.objField.offsetParent))+'px';
		container.style.top		= (this.getTopPos(this.objField.offsetParent)+25)+'px';
	},

	getLeftPos: function (obj)
	{
		var res = 0;
		while (obj)
		{
			res += obj.offsetLeft;
			obj = obj.offsetParent;
		}
		return res;
	},

	getTopPos: function (obj)
	{
		var res = 0;
		while (obj)
		{
			res += obj.offsetTop;
			obj = obj.offsetParent;
		}
		return res;
	}

}