

//-------------------- mTextSuggest.js

TextSuggest = Class.create();

TextSuggest.prototype = {

   initialize: function(anIdPrefix, url, options) {
   	this.groupIdPrefix = anIdPrefix;
      this.id          = anIdPrefix + options.suggestSuffix;
      var browser = navigator.userAgent.toLowerCase();
      this.isIE        = browser.indexOf("msie") != -1;
      this.isOpera     = browser.indexOf("opera")!= -1;
      this.textInput   = $(this.id);
      this.suggestions = [];
      this.setOptions(options);
      this.initAjax(url);

      this.injectSuggestBehavior();
   },

   initAjax: function(url) {
      ajaxEngine.registerRequest( this.id + '_request', url );
      ajaxEngine.registerAjaxObject( this.id + '_updater', this );
   },

   setOptions: function(options) {
      this.options = {
         suggestDivClassName: 'suggestDiv',
         suggestionClassName: 'suggestion',
         matchClassName     : 'match',
         matchTextWidth     : true,
         selectionClassName : 'selection',
         matchAnywhere      : false,
         ignoreCase         : false,
         count              : 10,
         singleUse			 : false,
         standAlone			 : false,
         title					 : '',
         suggestSuffix			:	'suggestSuffix',
         value1Suffix				: '',
         value2Suffix				: '',
         value3Suffix				: '',
         callback				 : function(options) {}
      }
      Object.extend(this.options, options || {});
   },

   injectSuggestBehavior: function() {

      if ( this.isIE )
         this.textInput.autocomplete = "off";

      var keyEventHandler = new TextSuggestKeyHandler(this);
      /*new Insertion.After( this.textInput,
                           '<input type="text" id="'+this.id+'_preventtsubmit'+'" style="display:none"/>' );
      new Insertion.After( this.textInput,
                           '<input type="hidden" name="'+this.id+'_hidden'+'" id="'+this.id+'_hidden'+'"/>' );
       */

      this.createSuggestionsDiv();
   },
   
   handleTextInput: function() {
   	 
     var previousRequest    = this.lastRequestString;
     this.lastRequestString = this.textInput.value;
    
     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.className = this.options.suggestionClassName;
      }
      this.selectedIndex = n;
      var span = $( this.id + "_" + this.selectedIndex );
      if ( span ){
         span.className = this.options.selectionClassName;
      }
   },

   sendRequestForSuggestions: function() {
		 var now = new Date();
		 if ( this.handlingRequest && ((now - this.pendingTime) < 5000)) {     	
     		this.pendingRequest = true;
        return;
     }    

     this.handlingRequest = true;
     this.pendingTime = new Date();
     this.textInput.ajaxInProgress = 'TextSuggest';
     this.callRicoAjaxEngine();
   },

   callRicoAjaxEngine: function() {
      var callParms = [];
      callParms.push( this.id + '_request');
      callParms.push( 'id='             + this.id);
      callParms.push( 'count='          + this.options.count);
      callParms.push( 'query='          + this.lastRequestString);
      callParms.push( 'match_anywhere=' + this.options.matchAnywhere);
      callParms.push( 'ignore_case='    + this.options.ignoreCase);

      var additionalParms = this.options.requestParameters || [];
      for( var i=0 ; i < additionalParms.length ; i++ )
         callParms.push(additionalParms[i]);

      ajaxEngine.sendRequest.apply( ajaxEngine, callParms );
   },

   ajaxUpdate: function( ajaxResponse ) {

      this.createSuggestions( ajaxResponse );

      if ( this.suggestions.length == 0 ) {

         this.hideSuggestions();
         $( this.groupIdPrefix + this.options.value1Suffix ).value = "";
         $( this.groupIdPrefix + this.options.value2Suffix ).value = "";
         $( this.groupIdPrefix + this.options.value3Suffix ).value = "";
      }
      else {

         this.updateSuggestionsDiv();
         this.showSuggestions();
         this.updateSelection(0);
      }

      this.handlingRequest = false;

      if ( this.pendingRequest ) {
         this.pendingRequest    = false;
         this.lastRequestString = this.textInput.value;
         this.sendRequestForSuggestions();
      }
   },

   createSuggestions: function(ajaxResponse) {
      this.suggestions = [];
      var entries = ajaxResponse.getElementsByTagName('entry');

      for ( var i = 0 ; i < entries.length ; i++ ) {
         var strText  = this.getElementContent(entries[i].getElementsByTagName('text')[0]);
         var strValue1 = this.getElementContent(entries[i].getElementsByTagName('value1')[0]);
         var strValue2 = this.getElementContent(entries[i].getElementsByTagName('value2')[0]);
         var strValue3 = this.getElementContent(entries[i].getElementsByTagName('value3')[0]);
 
         this.suggestions.push( { text: strText, value1: strValue1, value2: strValue2, value3: strValue3 } );        
      }
   },
   
   setInputFromSelection: function() {

     value1Input = $( this.groupIdPrefix + this.options.value1Suffix );
     value2Input = $( this.groupIdPrefix + this.options.value2Suffix );
     value3Input = $( this.groupIdPrefix + this.options.value3Suffix );
     var suggestion  = this.suggestions[ this.selectedIndex ];
     
     if (value1Input != null) { value1Input.value = suggestion.value1; }
     if (value2Input != null) { value2Input.value = suggestion.value2; }
     if (value3Input != null) { value3Input.value = suggestion.value3; }
   
     this.hideSuggestions();  
     this.options.callback(this.options);  
   },

   showSuggestions: function() {
      var divStyle = this.suggestionsDiv.style;
  
      if ( divStyle.display == '' ) {
          if (this.options.standAlone) {
	       	this.suggestionsWin.updateWidth();
	      	this.suggestionsWin.updateHeight();
	       }
	       return;
      }
  
      this.positionSuggestionsDiv();
      divStyle.display = '';
   },

   positionSuggestionsDiv: function() {

      var textPos = Position.positionedOffset(this.textInput); 
      var divStyle = this.suggestionsDiv.style;
    
      divStyle.top  = (textPos[1] + this.textInput.offsetHeight) + "px"; 
      divStyle.left = textPos[0] + "px";
      
      if (this.options.standAlone) {
      	divStyle.display = '';
      } else {
      	divStyle.display = 'none';
      	divStyle.position = 'absolute';
      }
     
      if ( this.options.matchTextWidth )
         divStyle.width = (this.textInput.offsetWidth - this.padding()) + "px";  
      
      if (this.options.standAlone) {
	      this.suggestionsWin = new Window({className: "ccs-blue", title: this.options.title, maximizable: false, minimizable: false, resizable: false, draggable: true, minHeight: 0, hideEffect:Element.hide, showEffect:Element.show, destroyOnClose: true})
	   	  this.suggestionsWin.setZIndex(3333);   
	      this.suggestionsWin.setContent(this.suggestionsDiv, false, true);
	      this.suggestionsWin.setLocation(textPos[1] + this.textInput.offsetHeight, textPos[0]);  
	      this.suggestionsWin.show(false);
	      this.suggestionsWin.updateWidth();
	      this.suggestionsWin.updateHeight();
             
         myObserver = {
			   
			    onStartMove: function(eventName, win) {  // includes click-down on window border
					 win.smee = true; // signals that the suggestions window should not be closed
			    },
			    
			    onEndMove: function(eventName, win) {    // includes click-up on window border
			
					win.smee = false; 
			    	win.textSuggest.textInput.focus();
			    	win.textSuggest.moveCaretToEnd();
			      
			    },
			   
			    onDestroy: function(eventName, win) {	 
      			win.textSuggest.setInputFromSelection();
      			win.textSuggest.suggestionsDiv.style.display = 'none';
			    	win.textSuggest = null;
			      Windows.removeObserver(this);	     
			    }
			 }
			 Windows.addObserver(myObserver);
			 
			 this.suggestionsWin.textSuggest = this;
			
      } 
     
   },
   
   padding: function() {
  
     try{
     
      var lPad    = parseInt(this.suggestionsDiv.getStyle("padding-left")); // styleFunc( this.suggestionsDiv, "paddingLeft",      "padding-left" );
      var rPad    = parseInt(this.suggestionsDiv.getStyle("padding-right")); // styleFunc( this.suggestionsDiv, "paddingRight",     "padding-right" );
      var lBorder = parseInt(this.suggestionsDiv.getStyle("border-left-width")); // styleFunc( this.suggestionsDiv, "borderLeftWidth",  "border-left-width" );
      var rBorder = parseInt(this.suggestionsDiv.getStyle("border-right-width")); // styleFunc( this.suggestionsDiv, "borderRightWidth", "border-right-width" );

		lPad    = isNaN(lPad)    ? 0 : lPad;
      rPad    = isNaN(rPad)    ? 0 : rPad;
      lBorder = isNaN(lBorder) ? 0 : lBorder;
      rBorder = isNaN(rBorder) ? 0 : rBorder;    

      return lPad + rPad + lBorder + rBorder; 
      
     }catch (e){
      return 0;
     }

   },

   hideSuggestions: function() {
   
   	if (this.options.standAlone && this.suggestionsWin) {
  			Windows.closeAll();	
   		this.suggestionsWin = null;
   	}
   	
      this.suggestionsDiv.style.display = 'none';
     
      if ( $( this.id ).value == "" ||  $( this.id ).value == "null" ) {
	      if (this.options.value1Suffix.length > 0) { $( this.groupIdPrefix + this.options.value1Suffix ).value = ""; }
	      if (this.options.value2Suffix.length > 0) { $( this.groupIdPrefix + this.options.value2Suffix ).value = ""; }
	      if (this.options.value3Suffix.length > 0) { $( this.groupIdPrefix + this.options.value3Suffix ).value = ""; }
	    }
	    
	    this.textInput.ajaxInProgress = null;
	    
   },

   createSuggestionsDiv: function() {
      
      this.suggestionsDiv = document.createElement("div");
      this.suggestionsDiv.className = this.options.suggestDivClassName;

      var divStyle = this.suggestionsDiv.style;
      divStyle.display  = 'none';

      this.textInput.parentNode.appendChild(this.suggestionsDiv);
      
   },

   updateSuggestionsDiv: function() {
      this.suggestionsDiv.innerHTML = "";
      var suggestLines = this.createSuggestionSpans();
      for ( var i = 0 ; i < suggestLines.length ; i++ )
         this.suggestionsDiv.appendChild(suggestLines[i]);
         
      if (this.options.standAlone && this.suggestionsWin) {
         this.suggestionsWin.updateHeight();
         this.suggestionsWin.updateWidth();
      }
   },

   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++ )
         suggestionSpans.push( this.createSuggestionSpan( i, regExp ) )

      return suggestionSpans;
   },

   createSuggestionSpan: function( n, regExp ) {
      var suggestion = this.suggestions[n];

      var suggestionSpan = document.createElement("span");
      suggestionSpan.className = this.options.suggestionClassName;
      suggestionSpan.style.width   = '100%';
      suggestionSpan.style.display = 'block';
      suggestionSpan.id            = this.id + "_" + n;
      suggestionSpan.onmouseover   = this.mouseoverHandler.bindAsEventListener(this);
      suggestionSpan.onclick       = this.itemClickHandler.bindAsEventListener(this);

      var textValues = this.splitTextValues( suggestion.text,
                                             this.lastRequestString.length,
                                             regExp );

      var textMatchSpan = document.createElement("span");
      textMatchSpan.id            = this.id + "_match_" + n;
      
      if (suggestion.value1 != null)
      	textMatchSpan.className     = this.options.matchClassName;
      	
      textMatchSpan.onmouseover   = this.mouseoverHandler.bindAsEventListener(this);
      textMatchSpan.onclick       = this.itemClickHandler.bindAsEventListener(this);

      textMatchSpan.appendChild( document.createTextNode(textValues.mid) );

      suggestionSpan.appendChild( document.createTextNode( textValues.start ) );
      suggestionSpan.appendChild( textMatchSpan );
      suggestionSpan.appendChild( document.createTextNode( textValues.end ) );

      return suggestionSpan;
   },

   mouseoverHandler: function(e) {
      var src = e.srcElement ? e.srcElement : e.target;
      var index = parseInt(src.id.substring(src.id.lastIndexOf('_')+1));
      this.updateSelection(index);
   },

   itemClickHandler: function(e) {
      this.mouseoverHandler(e);
      this.hideSuggestions();
      this.textInput.focus();
   },

   splitTextValues: function( text, len, regExp ) {
      var startPos  = text.search(regExp);
      var matchText = text.substring( startPos, startPos + len );
      var startText = startPos == 0 ? "" : text.substring(0, startPos);
      var endText   = text.substring( startPos + len );
      return { start: startText, mid: matchText, end: endText };
   },

   getElementContent: function(element) {
   		
   		if (element.firstChild) {
   			return element.firstChild.data;
    	} else {
 	  		return null;		
    	}
   },
   
   moveCaretToEnd: function() {
  
      var pos = this.textInput.value.length;
      if (this.textInput.setSelectionRange) {
         this.textInput.setSelectionRange(pos,pos);
      }
      else if(this.textInput.createTextRange){
         var m = this.textInput.createTextRange();
         m.moveStart('character',pos);
         m.collapse();
         m.select();
      }
   }
}

TextSuggestKeyHandler = Class.create();

TextSuggestKeyHandler.prototype = {

   initialize: function( textSuggest ) {
      this.textSuggest = textSuggest;
      this.input       = this.textSuggest.textInput;
      this.addKeyHandling();
   },

   addKeyHandling: function() {
      this.input.onkeyup    = this.keyupHandler.bindAsEventListener(this);
      this.input.onkeydown  = this.keydownHandler.bindAsEventListener(this);
      this.input.onblur     = this.onblurHandler.bindAsEventListener(this);
      
      if ( this.isOpera )
         this.input.onkeypress = this.keyupHandler.bindAsEventListener(this);
   },
   
   removeKeyHandling: function() {
      this.input.onkeyup    = null;
      this.input.onkeydown  = null;
      this.input.onblur     = null;
      if ( this.isOpera )
         this.input.onkeypress = null;
   },

   keydownHandler: function(e) {
      var upArrow   = 38;
      var downArrow = 40;

      if ( e.keyCode == upArrow ) {
         this.textSuggest.moveSelectionUp();
         setTimeout( this.textSuggest.moveCaretToEnd.bind(this.textSuggest, 1) );
      }
      else if ( e.keyCode == downArrow ){
         this.textSuggest.moveSelectionDown();
      }
   },

   keyupHandler: function(e) {
      if ( this.input.length == 0 && !this.isOpera )
         this.textSuggest.hideSuggestions();

     if ( !this.handledSpecialKeys(e) )
        this.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();
         
         if (this.textSuggest.options.singleUse) {     
      		this.removeKeyHandling();
      		this.input = null;    
	    		delete this.textSuggest;
	   	}
         
         return true;
      }

      return false;
   },

   onblurHandler: function(e) {
   
   	/* this.textSuggest.options.callback(this.textSuggest.options); */

		if (this.textSuggest.suggestionsWin && this.textSuggest.suggestionsWin.smee == null) {
			this.textSuggest.suggestionsWin.smee = false; // start our request
			setTimeout( this.onblurHandler.bind(this), 500 ); // give the window a chance to respond
	
		} else if ((this.textSuggest.suggestionsWin != null) && (this.textSuggest.suggestionsWin.smee)) {
			// do nothing, keep the suggestions open, but reset our test
			delete this.textSuggest.suggestionsWin.smee;
		} else {
	   	
	      if ( this.textSuggest.suggestionsDiv.style.display == '' ) {
	         this.textSuggest.setInputFromSelection();
	      } else {
	      	 this.textSuggest.options.callback(this.textSuggest.options);
	      }
	      this.textSuggest.hideSuggestions();
	     
	           
	      if (this.textSuggest.options.singleUse) {     
	      	this.removeKeyHandling();
	      	this.input = null;    
		    	delete this.textSuggest;
		   }
	   }
  
   }
   
};

