/**
* 20.05.08@FC	1.0.1	Aggiunto vmeter di frequenza per i termini
* 17.03.08@FC	1.0.0	First release.
*/

/* scriptaculous Ajax.Autocompleter extension

new w3gAutocompleter("searchPattern", "searchHelper", "LuceneAjaxAutocompleter.do", { size:15, minChars: 2})

other params:
paramNameQuery: "term"
paramNameSize: "size"
updateElement: addItemToList
indicator: 'searchIndicator'
*/
var w3gAutocompleter = Class.create();
Object.extend(w3gAutocompleter.prototype,Ajax.Autocompleter.prototype);
Object.extend(w3gAutocompleter.prototype,{
	getFilterQuery: function(){		
		if(!this.options.filters)
			return false;
		var query = '';
		for(var i=0; i< this.options.filters.length; i++){
			var key = this.options.filters[i];			
			var obj = $(key);			
			if(obj!='undefined'){
				if(obj.tagName.toUpperCase()=='SELECT'){
					if(obj.selectedIndex>=0){
//						var value = obj.options[obj.selectedIndex].value;
						query+='&'+key+'='+obj.options[obj.selectedIndex].value;
					}					
				} else if(obj.tagName.toUpperCase()=='INPUT'){
					var value;
					var sType = obj.type.toUpperCase();
					if (sType=='TEXT' || sType=='HIDDEN')	
						value = obj.value;
					else if (sType=='CHECKBOX')
						value = obj.checked ? 'true' : 'false';
					else if (sType=='RADIO') {
						var cnt = -1;
					    for (var i=obj.length-1; i > -1; i--) {
					        if (obj[i].checked) {cnt = i; i = -1;}
					    }
					    value = (cnt > -1) ? obj[cnt].value : "";
					}
					query+='&'+key+'='+value;						
				} else if(obj.tagName.toUpperCase()=='TEXTAREA'){
					query+='&'+key+'='+ (obj.value == null ? '' : obj.alue);
				}
			}
		}
		return query;
	},
	getUpdatedChoices: function() {
	    entry = encodeURIComponent(this.options.paramNameQuery) + '=' + 
	    encodeURIComponent(this.getToken())+ '&' +
	    encodeURIComponent(this.options.paramNameSize) + '=' + 
	    encodeURIComponent(this.options.size)	;
	    
	 		this.options.parameters = this.options.callback ? this.options.callback(this.element, entry) : entry;
	    if(this.options.defaultParams) 
	    	this.options.parameters += '&' + this.options.defaultParams;
	   	var appendQuery=this.getFilterQuery();
	   	if (appendQuery != '') {
	   		this.options.parameters += appendQuery;
	   	}	   	   	
	   	
	 	new Ajax.Request(this.url, this.options);
	},
	baseInitialize: function(element, update, options) {
	    this.element     = $(element); 
	    this.update      = $(update);//OnTopElement.extend($(update));
	    this.hasFocus    = false; 
	    this.scrolling	 = false;
	    this.updateFocus = false;
	    this.changed     = false; 
	    this.active      = false; 
	    this.index       = 0;     
	    this.entryCount  = 0;
	    this.originalLeft ;
		this.scrollTimer;		
	    if(this.setOptions)
	      this.setOptions(options);
	    else
	      this.options = options || {};
	
		//2010.02.03@FC-SO
		this.options.parseFunction = this.options.parseFunction|| this.parsetTermFreq;
		//2010.01.12@FC-SO
		this.options.filters = this.options.filters || false;
		this.options.termFreq   = this.options.termFreq || false;
	    this.options.paramNameQuery  = this.options.paramNameQuery || 'term';
	    this.options.paramNameSize  = this.options.paramNameSize|| 'size';
	    this.options.tokens       = this.options.tokens || [' '];
	    this.options.frequency    = this.options.frequency || 0.2;
	    this.options.minChars     = this.options.minChars || 1;
	    this.options.size					= this.options.size || 10;
	    this.options.onShow       = this.options.onShow || 
	      function(element, update){ 	      	
	      	if(!this.originalLeft)
	      		this.originalLeft = Position.cumulativeOffset(element)[0];	      		
	        if(!update.style.position || update.style.position=='absolute') {
	          update.style.position = 'absolute';		
	          //fix for IE text field cursor offset bug...          
	          var realLeft = Position.realOffset(element)[0];	          
	          Position.clone(element, update, {
	            setHeight: false, 
	            offsetTop: element.offsetHeight,
	            offsetLeft: realLeft           
	          });
	        }
	        Effect.Appear(update,{duration:0.15});
	      };
	    this.options.onHide = this.options.onHide || 
	      function(element, update){ new Effect.Fade(update,{duration:0.15}) };
	
	    if(typeof(this.options.tokens) == 'string') 
	      this.options.tokens = new Array(this.options.tokens);
	
	    this.observer = null;
	    
	    this.element.setAttribute('autocomplete','off');
	
	    Element.hide(this.update);
	    
	    Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this)); 	    
	    Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this));

	    Event.observe(this.update, "focus", this.updateOnFocus.bindAsEventListener(this));
	    Event.observe(this.update, "blur", this.updateOnBlur.bindAsEventListener(this));	   

   		
	    Event.observe(this.update, "scroll", this.onScroll.bindAsEventListener(this));
	    
	    Event.observe(window, "resize", this.onResize.bindAsEventListener(this));

	   // Event.observe(this.update, "mouseup", this.onMouseup.bindAsEventListener(this));
	    
  	}
  	,
  	onScroll:function(event){    		
  		if(this.scrolling!=false)
  			clearTimeout(this.scrollTimer);  
  		this.scrolling=true;
  		this.scrollTimer = setTimeout(this.relaseBlur.bind(this), 100);
  		this.element.focus();  		
  	},
  	relaseBlur: function (event){
  		this.scrolling=false;
  	},
  	onBlur:function(event){  		
  	    // needed for IE scrollbar click interference    	      
  	    if(this.scrolling==false)
    		setTimeout(this.conditionalHide.bind(this), 180);    
    	Event.stop(event);    	
  	},
  	conditionalHide: function(event){	
  		// only if list div dont have current focus close all..   	
  		if(this.scrolling == false){
  			// needed to make click events working 
  			setTimeout(this.hide.bind(this), 250);
  			this.hasFocus = false;
    		this.active = false;  
    		this.updateFocus = false;
  		}
  	},
  	updateOnFocus: function(event) {
  		 this.updateFocus = true;
  	},
  	updateOnBlur: function(event) {
  		 this.updateFocus = false;  		 
  	},
   	onClick: function(event) { 
    	var element = Event.findElement(event, 'LI');
    	if(element){
	    	this.index = element.autocompleteIndex;
	    	this.selectEntry();
	    	this.hide();
    	}
   	},
	getToken: function() {
	 function trim (toTrim){
	 	if(!toTrim)return toTrim;
		while (toTrim.substring(0,1) == ' ')
			toTrim = toTrim.substring(1, toTrim.length);
		while (toTrim.substring(toTrim.length-1, toTrim.length) == ' ')
			toTrim = toTrim.substring(0,toTrim.length-1);
		return toTrim;
	}	
    var tokenPos = this.findLastToken();
    if (tokenPos != -1)
      var ret = trim(this.element.value.substr(tokenPos + 1))
    else
      var ret = this.element.value;

    return /\n/.test(ret) ? '' : ret;
  },
  cursorToEnd: function () {
    if(this.element != null) {
    	if(this.element.createTextRange) {
            var range = this.element.createTextRange();
            range.move('character', this.element.value.length);
            range.select();
        }else if(this.element.selectionStart) {
                this.element.focus();
                this.element.setSelectionRange(this.element.value.length, this.element.value.length);
        }else
            this.element.focus();
    }
  },
  updateElement: function(selectedElement) {
    if (this.options.updateElement) {
      this.options.updateElement(selectedElement);
      return;
    }
    var value = '';
    var overwrite = selectedElement.getAttribute('entry');
    if(overwrite){
    	value = overwrite;
    }else if (this.options.select) {
      var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
      if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select);
    } else
      value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal');
    
    var lastTokenPos = this.findLastToken();
    if (lastTokenPos != -1) {
      var newValue = this.element.value.substr(0, lastTokenPos + 1);
      var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
      if (whitespace)
        newValue += whitespace[0];
      this.element.value = newValue + value;
    } else {
      this.element.value = value;
    }
    this.element.focus();
    this.cursorToEnd();
    if (this.options.afterUpdateElement)
      this.options.afterUpdateElement(this.element, selectedElement);
  },
  resetVerticalScroll: function(){
  	this.update.scrollTop = 0;
  },
  onKeyPress: function(event) {
    if(this.active){
      this.resetVerticalScroll();
      switch(event.keyCode) {
       case Event.KEY_TAB:
       case Event.KEY_RETURN:
         this.selectEntry();
         Event.stop(event);
       case Event.KEY_ESC:
         this.hide();
         this.active = false;
         Event.stop(event);
         return;
       case Event.KEY_LEFT:
       case Event.KEY_RIGHT:
         return;
       case Event.KEY_UP:
         this.markPrevious();
         this.render();
         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
         return;
       case Event.KEY_DOWN:
         this.markNext();
         this.render();
         if(navigator.appVersion.indexOf('AppleWebKit')>0) Event.stop(event);
         return;
      }
     }else if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || 
         (navigator.appVersion.indexOf('AppleWebKit') > 0 && event.keyCode == 0)) return;

    this.changed = true;
    this.hasFocus = true;

    if(this.observer) clearTimeout(this.observer);
      this.observer = 
        setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000);
  },
  parsetTermFreq:function(entry){
    entry = $(entry);
  	var term = entry.innerHTML;
  	var freq = ''; 	  	  	
  	term.sub(new RegExp('([0-9]+/[0-9]+)$'), function(match){  		
  		term = term.replace(match[1],'').strip();
  		freq = match[1];
	});
	
	entry.setAttribute('entry',term);
	entry.update("");
		
	entry.setStyle({'padding-right':'0px'});
	var container = $(document.createElement('DIV'));
	container.setStyle({width:'100%',padding:'0px',margin:'0px',clear:'both','background-color':'transparent',height:'16px'});
	

	var entrycontainer = $(document.createElement('DIV'));
	entrycontainer.setStyle({float:'left','background-color':'transparent'});
	entrycontainer.update(term);
	
	container.appendChild(entrycontainer);
	
	var vcontainer = $(document.createElement('DIV'));
	vcontainer.setStyle({float:'right',width:'36px',height:'16px','padding-top':'2px','background-color':'#fff'});
	var vmask = $(document.createElement('DIV'));
	vmask.addClassName('searchHelper-vmask');	
	
	var vmeter = $(document.createElement('DIV'));		
	
	vmeter.addClassName('searchHelper-vmeter');
	
	vcontainer.appendChild(vmeter);
	vcontainer.appendChild(vmask);
	var adjustVMeter= function(vmask,vmeter,freq){
		var maskwidth = parseInt(vmask.getStyle('width'));	
		if(isNaN(maskwidth) || maskwidth<1)return false;
		var split= freq.split('/');				
		var tot = parseInt(split[1]) * .5;	
		var f = Math.min(parseInt(split[0]) , tot);
		var mywidth = Math.max( maskwidth /100 * Math.min(f,100) ,4);	
		vmeter.setStyle({width:mywidth+'px'});	
		return true;
	}
	if(!adjustVMeter(vmask,vmeter,freq))
		setTimeout(adjustVMeter.bind(this,vmask,vmeter,freq),150);	
	container.appendChild(vcontainer);
	entry.appendChild(container);	
  },
  updateChoices: function(choices) {
    if(!this.changed && this.hasFocus) {
      this.update.innerHTML = choices;
      Element.cleanWhitespace(this.update);
      Element.cleanWhitespace(this.update.down());

      if(this.update.firstChild && this.update.down().childNodes) {
        this.entryCount = 
          this.update.down().childNodes.length;
          var mess='';
        for (var i = 0; i < this.entryCount; i++) {
          var entry = this.getEntry(i);
          if(this.options.termFreq){          	
          	this.options.parseFunction(entry);
          }     
          entry.autocompleteIndex = i;
          this.addObservers(entry);
        }
      } else { 
        this.entryCount = 0;
      }

      this.stopIndicator();
      this.index = 0;
      
      if(this.entryCount==1 && this.options.autoSelect) {
        this.selectEntry();
        this.hide();        
      } else {      	
        this.render();
        setTimeout(this.update.hideOverlappedSelect.bind(this.update), 150);
      }
    }
  }, 
  onResize: function(event){
  	if(Element.getStyle(this.update, 'display')!='none'){
  		//this.hide();
  	}
  },
  hide: function() {
    this.stopIndicator();    
    if(Element.getStyle(this.update, 'display')!='none'){
    	this.options.onHide(this.element, this.update);    	
    }
    if(this.iefix) Element.hide(this.iefix);    
  }
  
});
Object.extend(w3gAutocompleter,{
	Version: function(){
		var release ='1';
		var major='0';
		var minor='0';		
		this.release=release;this.major=major;this.minor=minor;	
		function fullVersion(){	return release+'.'+major+'.'+minor; }
		return fullVersion();
},
 CheckDependency: function() {
    if((typeof Prototype=='undefined') || (typeof Ajax.Autocompleter=='undefined'))
    	throw "w3gAutocompleter require Prototype and Scriptaculous";
}
});
	
	    		
w3gAutocompleter.CheckDependency();


