﻿/*TextSuggest = Class.create();*/

TextSuggest = function (anId, nextControlToFocusName, options){

					this.initialize(anId, nextControlToFocusName, options);
			  };

TextSuggest.prototype = {

   initialize: function(anId, nextControlToFocusName, options) {
      this.id          = anId;
      var browser = navigator.userAgent.toLowerCase();
      this.isIE        = $.browser.msie;
      this.isOpera     = $.browser.opera;
      this.textInput   = $('#'+this.id);
      this.suggestions = [];
      this.nextControlToFocus = nextControlToFocusName;
      this.setOptions(options);

      this.injectSuggestBehavior();
   },

   setFocusOnTextControl: function()
   {
   	  if(this.nextControlToFocus)
   	  {

   	  	 $('#'+this.nextControlToFocus).focus();

   	  }
   },

   setOptions: function(options) {
      this.options = {
         suggestDivClassName: 'suggestDiv',
         suggestionClassName: 'suggestion',
         matchClassName     : 'match',
         matchTextWidth     : true,
         selectionColor     : '#3366CC',
         matchAnywhere      : false,
         ignoreCase         : false,
         count              : 10
      }
   },

   injectSuggestBehavior: function() {

      if ( this.isIE )
         this.textInput.autocomplete = "off";

      var keyEventHandler = new TextSuggestKeyHandler(this);
      this.textInput.after('<input type="text" id="'+this.id+'_preventtsubmit'+'" style="display:none"/>');
      this.textInput.after('<input type="hidden" name="'+this.id+'_hidden'+'" id="'+this.id+'_hidden'+'"/>');
      this.createSuggestionsDiv();
   },

   handleTextInput: function() {
	 var previousRequest    = this.lastRequestString;
     this.lastRequestString = this.textInput.val();
     //if (! this.lastRequestString)
     //   this.hideSuggestions();
     //else
    	 if ( this.lastRequestString != previousRequest ) {
    		 this.sendRequestForSuggestions();
     }
   },

   moveSelectionUp: function() {
      if ( this.selectedIndex > 0 ) {
         this.updateSelection(this.selectedIndex - 1);
      }
   },

   moveSelectionDown: function() {
      if ( this.selectedIndex < (this.suggestions.length - 1)  ) {
         this.updateSelection(this.selectedIndex + 1);
      }
   },

   updateSelection: function(n) {
      var span = $('#'+ this.id + "_" + this.selectedIndex );
      if ( span ){
          span.css('background-color','');
      }
      this.selectedIndex = n;
      var span = $('#'+ this.id + "_" + this.selectedIndex );
      if ( span ){
          span.css('background-color',this.options.selectionColor);
      }
   },

   sendRequestForSuggestions: function() {
     this.callAjaxEngine();
   },


   callAjaxEngine: function()
   {
   	if (this.lastRequestString){
		var currentSuggest = this;
	   	var params = "f=get_suggest&word=" + this.lastRequestString + "&id="+this.id;

	   	$.ajax ({'url':'/ajax_functions/train.php',
				 'type': 'post',
	   			 'data': params,
	   			 'success': function(transport) {
			 					currentSuggest.ajaxUpdate(transport);
			 				}
	   			}
	   	);
   	}

   },

   ajaxUpdate: function( ajaxResponse ) {


	   if(ajaxResponse != "-error-")
		{
     	 this.createSuggestions( ajaxResponse );
		}

    	  if ( this.suggestions.length == 0 ) {
    	     this.hideSuggestions();
     	    $('#'+ this.id + "_hidden" ).value = "";
  	    }
  	    else {
   		   this.updateSuggestionsDiv();
  	       this.showSuggestions();
  	       this.updateSelection(-1);
      	}

      	if ( this.pendingRequest ) {
         	this.pendingRequest    = false;
         	this.lastRequestString = this.textInput.value;
         	this.sendRequestForSuggestions();
      	}
   },

   createSuggestions: function(ajaxResponse) {
   	  var retArr = eval('(' + ajaxResponse + ')');
   	  this.suggestions = [];
      for ( var i = 0 ; i < retArr.length ; i++ ) {
    	   this.suggestions[i] =  ({ text: retArr[i][0], value: retArr[i][1] }) ;
      }

   },

   setInputFromSelection: function(isHideSuggestion) {
     var hiddenInput = $('#'+ this.id + "_hidden" );
     var suggestion  = this.suggestions[ this.selectedIndex ];
	 if(suggestion)
	 {
    	 this.textInput.val(suggestion.text);
     	 hiddenInput.val(suggestion.value);
	 }
     if(isHideSuggestion || isHideSuggestion==1)
     {
     	this.hideSuggestions();
     }
   },

   showSuggestions: function() {

     this.suggestionsDiv.show();
     this.positionSuggestionsDiv();

   },

   toDocumentPosition: function(element) {
      return this._toAbsolute(element,false);
   },
   getElementsComputedStyle: function ( htmlElement, cssProperty, mozillaEquivalentCSS) {
      if ( arguments.length == 2 )
         mozillaEquivalentCSS = cssProperty;

      var el = $('#'+htmlElement);
      if ( el.currentStyle )
         return el.currentStyle[cssProperty];
      else
         return document.defaultView.getComputedStyle(el, null).getPropertyValue(mozillaEquivalentCSS);
   },
_toAbsolute: function(element,accountForDocScroll) {
      if ( navigator.userAgent.toLowerCase().indexOf("msie") == -1 )
         return this._toAbsoluteMozilla(element,accountForDocScroll);
      var x = 0;
      var y = 0;
      var parent = element;
      while ( parent ) {

         var borderXOffset = 0;
         var borderYOffset = 0;
         if ( parent != element ) {
            var borderXOffset = parseInt(this.getElementsComputedStyle(parent, "borderLeftWidth" ));
            var borderYOffset = parseInt(this.getElementsComputedStyle(parent, "borderTopWidth" ));
            borderXOffset = isNaN(borderXOffset) ? 0 : borderXOffset;
            borderYOffset = isNaN(borderYOffset) ? 0 : borderYOffset;
         }

         x += parent.offsetLeft + borderXOffset;
         y += parent.offsetTop + borderYOffset;
         parent = parent.offsetParent;
      }

      if ( accountForDocScroll ) {
         x -= this.docScrollLeft();
         y -= this.docScrollTop();
      }

      return { x:x, y:y };
   },

   /**
    *  Mozilla did not report all of the parents up the hierarchy via the
    *  offsetParent property that IE did.  So for the calculation of the
    *  offsets we use the offsetParent property, but for the calculation of
    *  the scrollTop/scrollLeft adjustments we navigate up via the parentNode
    *  property instead so as to get the scroll offsets...
    *
    **/
   _toAbsoluteMozilla: function(element,accountForDocScroll) {
      var x = 0;
      var y = 0;
      var parent = element;
      while ( parent ) {
         x += parent.offsetLeft;
         y += parent.offsetTop;
         parent = parent.offsetParent;
      }

      parent = element;
      while ( parent &&
              parent != document.body &&
              parent != document.documentElement ) {
         if ( parent.scrollLeft  )
            x -= parent.scrollLeft;
         if ( parent.scrollTop )
            y -= parent.scrollTop;
         parent = parent.parentNode;
      }

      if ( accountForDocScroll ) {
         x -= this.docScrollLeft();
         y -= this.docScrollTop();
      }

      return { x:x, y:y };
   },

   positionSuggestionsDiv: function() {
	  var textPos = this.toDocumentPosition(this.textInput.get(0));
      this.suggestionsDiv.css('top:'+(120+textPos.y + this.textInput.get(0).offsetHeight) + "px");
	  this.suggestionsDiv.css('left:'+120+textPos.x + "px");
      if ( this.options.matchTextWidth )
     	  this.suggestionsDiv.css('width:'+(120+this.textInput.get(0).offsetWidth- this.padding()) + "px");

   },

   padding: function() {
     try{
      var lPad =  this.suggestionsDiv.css('padding-left');
      var rPad =  this.suggestionsDiv.css('padding-right');
      var lBorder =  this.suggestionsDiv.css('border-left-width');
      var rBorder =  this.suggestionsDiv.css('border-right-width');
      lPad    = isNaN(lPad)    ? 0 : lPad;
      rPad    = isNaN(rPad)    ? 0 : rPad;
      lBorder = isNaN(lBorder) ? 0 : lBorder;
      rBorder = isNaN(rBorder) ? 0 : rBorder;

      return parseInt(lPad) + parseInt(rPad) + parseInt(lBorder) + parseInt(rBorder);
     }catch (e){
      return 0;
     }
   },

   hideSuggestions: function() {
      this.suggestionsDiv.hide();

   },

   createSuggestionsDiv: function() {

	  this.suggestionsDiv = $('<div id="suggestionDiv"></div>').insertAfter(this.textInput);//'div#modeSearchTrain');//document.createElement("div");
      this.suggestionsDiv.addClass(this.options.suggestDivClassName);
      this.suggestionsDiv.css('position','absolute')
      .css('z-index','101')
      .css('background-color','#FFFFFF')
      .css('width',this.textInput.css('width'));
      this.suggestionsDiv.hide();
   },

   updateSuggestionsDiv: function() {
      this.suggestionsDiv.html('');
      this.createSuggestionSpans();
   },

   createSuggestionSpans: function() {
      var regExpFlags = "";
      if ( this.options.ignoreCase )
         regExpFlags = 'i';
      var startRegExp = "^";
      if ( this.options.matchAnywhere )
         startRegExp = '';

      var regExp  = new RegExp( startRegExp + this.lastRequestString, regExpFlags );

      var suggestionSpans = [];
      for ( var i = 0 ; i < this.suggestions.length ; i++ ){

    	  var class_name  = this.options.suggestionClassName;
    	  var textValues  = this.splitTextValues(this.suggestions[i].text,
                  								(this.lastRequestString+'').length, regExp);
    	  var ms_id       = this.id + "_match_" + i;
          var ms_className= this.options.matchClassName;
          if (textValues!=null){
	          var span = $('<span id="'+this.id + "_" + i +'" class="'+class_name+'"></span>').html(textValues.start+'<span class="'+ms_className+'" id="'+ms_id+'">'+textValues.mid+'</span>'+textValues.end)
	          	.appendTo(this.suggestionsDiv)
	          	.css('display','block').css('width','100%');
	          span.bind('mouseover', this, this.mouseoverHandler);
	          span.bind('click', this, this.itemClickHandler);
          }
      }

      return true;
   },

   mouseoverHandler: function(e) {
      var src = e.srcElement ? e.srcElement : e.target;
      var index = parseInt(src.id.substring(src.id.lastIndexOf('_')+1));
      e.data.updateSelection(index);
   },

   itemClickHandler: function(e) {
	   var src = e.srcElement ? e.srcElement : e.target;
	   var index = parseInt(src.id.substring(src.id.lastIndexOf('_')+1));
	   e.data.updateSelection(index);
	   e.data.hideSuggestions();
	   e.data.setInputFromSelection(index);
	   e.data.textInput.focus();
   },

   splitTextValues: function( text, len, regExp ) {
	  var result = null;
      var startPos  = text.search(regExp);
      if (startPos>=0){

	      var matchText = text.substring( startPos, startPos + len );
	      var startText = startPos == 0 ? "" : text.substring(0, startPos);
	      var endText   = text.substring( startPos + len);
	      result = { start: startText, mid: matchText, end: endText };
      }

      return result;
   },

   getElementContent: function(element) {
      return element.firstChild.data;
   }
}

TextSuggestKeyHandler = function (textSuggest){
							this.initialize(textSuggest);
						};


TextSuggestKeyHandler.prototype = {

   initialize: function( textSuggest ) {
      this.textSuggest = textSuggest;
      this.input       = this.textSuggest.textInput;
      this.addKeyHandling();
   },

   addKeyHandling: function() {
//     this.input.bind('change', this, this.keydownHandler);
	   this.input.bind('keyup', this, this.keyupHandler);//this.keyupHandler.bindAsEventListener(this);
	   this.input.bind('keydown', this, this.keydownHandler);
   	   this.input.bind('blur',this, this.onblurHandler);
   },

   keydownHandler: function(e) {
      var upArrow   = 38;
      var downArrow = 40;
      var tabKey 	= 9;
      var enterKey 	= 13;

      if ( e.keyCode == upArrow ) {
         e.data.textSuggest.moveSelectionUp();
         //setTimeout('',200);
         e.data.moveCaretToEnd();
         e.data.textSuggest.setInputFromSelection(0);
      }
      else if ( e.keyCode == downArrow ){
         e.data.textSuggest.moveSelectionDown();
         e.data.textSuggest.setInputFromSelection(0);
      }
      else if (e.keyCode == tabKey)
      {
      	 e.data.textSuggest.hideSuggestions();
      }
      else if(e.keyCode == enterKey)
      {
      	 e.data.textSuggest.hideSuggestions();
      	 e.data.textSuggest.setFocusOnTextControl();
      }
   },

   keyupHandler: function(e) {
     if ( e.data.input.val().length == 0 && !e.data.isOpera )
    	 e.data.textSuggest.hideSuggestions();

     if ( !e.data.handledSpecialKeys(e) ){
    	 //setTimeout('',200);
    	 e.data.textSuggest.handleTextInput();
     }
   },

   handledSpecialKeys: function(e) {
      var enterKey  = 13;
      var upArrow   = 38;
      var downArrow = 40;

      if ( e.keyCode == upArrow || e.keyCode == downArrow ) {
         return true;
      }
      else if ( e.keyCode == enterKey ) {
         this.textSuggest.setInputFromSelection(1);
         return true;
      }

      return false;
   },

   moveCaretToEnd: function() {
      var pos = this.input.val().length;
      if (this.input.get(0).setSelectionRange) {
    	  this.input.get(0).setSelectionRange(pos,pos);
      }
      else if(this.input.get(0).createTextRange){
         var m = this.input.get(0).createTextRange();
         m.moveStart('character',pos);
         m.collapse();
         m.select();
      }
   },

   onblurHandler: function(e) {
       var visible = e.data.textSuggest.suggestionsDiv.css('display')=='';
	   if (visible){
	       e.data.textSuggest.setInputFromSelection(!visible);
		   e.data.textSuggest.hideSuggestions();
	   }
   }

};