/****** net.ContentLoader Ajax "helper" object that ******/
/** - create a XMLHttpRequest object in a cross-browser fashion **/
/** - provide a more convenient API for dealing with request parameters **/
/** - route the response back to a component with AjaxUpdate() and handleError() methods **/

/** namespacing object **/
var net = new Object();

net.READY_STATE_UNINITIALIZED = 0;
net.READY_STATE_LOADING = 1;
net.READY_STATE_LOADED = 2;
net.READY_STATE_INTERACTIVE = 3;
net.READY_STATE_COMPLETE=4;

/** object constructor **/
net.ContentLoader = function (component, url, method, requestParams) {
	this.component = component;
	this.url = url;
	this.method = method;
	this.requestParams = requestParams;
};

net.ContentLoader.prototype = {

	/** method handles the creation of XMLHttpRequest in a cross-browser fashion **/
	getTransport: function() {
		var transport;
		if(window.XMLHttpRequest) {
		/** native object **/
			transport = new XMLHttpRequest();
		} else if (window.ActiveXObject) {
		/** Microsoft IE **/
			try {
				transport = new ActiveXObject('Msxml2.XMLHTTP');
			} catch(err) {
				transport = new ActiveXObject('Microsoft.XMLHTTP');
			}
		}
		return transport;
	},
	
	/** method provides a convenient API for dealing with request parameters **/
	sendRequest : function() {
		var requestParams = [];
		for(var i = 0; i < arguments.length;  i++) {
			// alert ("arguments["+i+"] = "+arguments[i]);
			requestParams.push(arguments[i]);
		}
		var oThis = this;
		var request = this.getTransport();
		request.open(this.method, this.url, true);
		request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
		request.onreadystatechange = function() { oThis.handleAjaxResponse(request); };
		// alert ("query string = "+this.queryString(requestParams));
		request.send(this.queryString(requestParams));
	},
	
	queryString : function(args) {
		var requestParams = [];
		for(var i = 0; i < this.requestParams.length; i++) {
			requestParams.push(this.requestParams[i]);
		}
		for(var j = 0; j < args.length; j++) {
			requestParams.push(args[j]);
		}

		var queryString = "";
		if(requestParams && requestParams.length > 0) {
			for(var k = 0; k < requestParams.length; k++) {
				// alert ("requestParams["+k+"] = "+requestParams[k]);
				queryString += requestParams[k] + '&';
			}
			queryString = queryString.substring(0, queryString.length - 1);
		}
		return queryString;
	},
	
	/** method collaborates with a component to handle the response that comes back from Ajax **/
	handleAjaxResponse : function(request) {
		if(request.readyState == net.READY_STATE_COMPLETE) {
			if(this.isSuccess(request)) 
				{ this.component.ajaxUpdate(request); }
			else
				{ this.component.handleError(request); }
		}
	},
	
	isSuccess : function(request) {
		return request.status === 0 || (request.status >= 200 && request.status < 300);
	}
};

/***********************************************************/
/************ InputField con controllo asincrono ************/
/***********************************************************/
function InputField(id, id_msg, url, options) {
	this.id = id;
	this.inputfield = xGetElementById(id);
	this.msg = xGetElementById(id_msg);
	this.options = options;
	this.destField = null;
	this.condition = null;
	this.params = null;
	/**** creazione oggetto XMLHttpRequest cross-browser per richieste asincrone ***/
	this.ajaxHelper = new net.ContentLoader(this, url, "POST", options.requestParameters || []);
	/**** inizializzazione comportamento del componente ****/
	this.initializeBehaviour();
	this.flagChanged = false;
}

InputField.prototype = {
	initializeBehaviour : function() {
		var oThis = this;
		this.inputfield.onchange = function() {oThis.fieldChanged();};
		this.inputfield.onblur = function() {oThis.fieldBlur();};
	},
	
	fieldChanged : function() {
		this.flagChanged = true;
		var fieldValue = this.inputfield.value;
		var p = '';
		if (null !== this.params){
			for (k=0; k<this.params.length; k++){
				p += '&'+this.params[k]+'='+xGetElementById(this.params[k]).value;
			}			
		}

		if (null !== this.condition){    		
		    if (xGetElementById(this.condition[0]).value === this.condition[1]){
				this.ajaxHelper.sendRequest(this.id+'='+fieldValue+p);
			}
		}
		else {		   
			this.ajaxHelper.sendRequest(this.id+'='+fieldValue+p);
		}
	},

	fieldBlur : function() {
		if (!this.flagChanged){
			var fieldValue = this.inputfield.value;
			var p = '';
			if (null !== this.params){
				for (k=0; k<this.params.length; k++){
					p += '&'+this.params[k]+'='+xGetElementById(this.params[k]).value;
				}				
			}

			if (null !== this.condition){			    
			    if (xGetElementById(this.condition[0]).value === this.condition[1]){
					this.ajaxHelper.sendRequest(this.id+'='+fieldValue+p);
				}
			}
			else {			    
				this.ajaxHelper.sendRequest(this.id+'='+fieldValue+p);
			}
		}
		this.flagChanged = false;
	},
	
	ajaxUpdate : function(request) {
		this.responseManager(request.responseXML.documentElement);
	},
	
	focus : function (){
		this.inputfield.focus();
	},

	setDestField : function (id_dest){
		this.destField = xGetElementById(id_dest);
	},
	
	setCondition : function (field_id, field_value){
		this.condition = [field_id, field_value];
	},
	
	addParam : function (field_id){	    
		if (null === this.params){
			this.params = []; 
		}		
		this.params[this.params.length] = field_id;		
	},
	
	disableOnBlurEvent: function (){
		this.inputfield.onblur = function() {};
	},
	
	responseManager : function(ajaxResponse) {
		myResponseManager(this, ajaxResponse);
	},

   getElementContent: function(element,tagName) {
      var childElement = element.getElementsByTagName(tagName)[0];
      if (null === childElement || childElement === undefined){
      	return null;
      }
      else {
      	return childElement.text !== undefined ? childElement.text : childElement.textContent;
      }
   },

   getChildContent: function(element) {
      var childElement = element;
      return childElement.text !== undefined ? childElement.text : childElement.textContent;
   },

	handleError : function(request) {
		this.msg.innerHTML = 'Si &egrave; verificato un errore di comunicazione con il server. Contattare l\'amministratore di sistema';
	}
	
};

/****************************************************************/
/************ InputFieldGroup con controllo asincrono ***********/
/****************************************************************/
function InputFieldGroup(groupName, arrayOfId, id_msg, url, options) {
	this.id = groupName;
	this.inputfields = [];
	if(arrayOfId) {
		for(var i = 0; i < arrayOfId.length; i++) {
			this.inputfields[i] = xGetElementById(arrayOfId[i]);
		}
	}
	this.msg = xGetElementById(id_msg);
	this.options = options;
	this.destField = null;
	this.lastChanged = null;
	/**** lista dei campi del gruppo che possono avere contentuto nullo ***/
	this.canBeEmptyList = '';
	/**** creazione oggetto XMLHttpRequest cross-browser per richieste asincrone ***/
	this.ajaxHelper = new net.ContentLoader(this, url, "POST", options.requestParameters || []);
	/**** inizializzazione comportamento del componente ****/
	this.initializeBehaviour();
}

InputFieldGroup.prototype = {

	initializeBehaviour : function() {
		var oThis = this;
		if(this.inputfields) {
			for(var i = 0; i < this.inputfields.length; i++) {
				this.inputfields[i].onchange = function(event) {oThis.fieldChanged(event);};
			}
		}
	},
	
	/**** il campo 'id' può avere contenuto nullo ***/
	canBeEmpty : function(id){
		this.canBeEmptyList += (id+',');
	},
	

	fieldChanged : function() {
		var event = document.createEvent("HTMLEvents");
		event.initEvent("change",true,true);
		this.fieldChanged(event);
	},

	fieldChanged : function(event) {
		
		if(this.inputfields) {
			var checkNow = true;
			for(var i = 0; i < this.inputfields.length; i++) {
				if ((this.canBeEmptyList.indexOf(this.inputfields[i].id) < 0) 
								&& (this.inputfields[i].value === '')){
						checkNow = false;
						break;
					}
			}
			
			// TODO: VERIFICARE QUAL'é IL MODO CORRETTO DI ACCODARE I PARAMETRI !!! 
			if (checkNow){
				var requestParams = this.id+"=";
				for(var i = 0; i < this.inputfields.length; i++) {
					requestParams += "&"+this.inputfields[i].id+"="+this.inputfields[i].value;
				}			

				// ricavo l'id del campo del gruppo da cui proviene questo evento: 
				if (event && event.target){
					this.lastChanged = event.target.id;
				}
				else{ // se "event.target" non è definito (browser) prendo il primo della lista
					this.lastChanged = this.inputfields[0].id;
				}
				
				requestParams += "&_changed="+this.lastChanged;
				this.ajaxHelper.sendRequest(requestParams);
			}	
		}
	},
	
	ajaxUpdate : function(request) {
		this.responseManager(request.responseXML.documentElement);
	},
	
	setDestField : function (id_dest){
		this.destField = xGetElementById(id_dest);
	},
	
	responseManager : function(ajaxResponse) {
		myResponseManager(this, ajaxResponse);
	},

   getElementContent: function(element,tagName) {
      var childElement = element.getElementsByTagName(tagName)[0];
      if (null === childElement || childElement === undefined){
      	return null;
      }
      else {
      	return childElement.text !== undefined ? childElement.text : childElement.textContent;
      }
   },

   getChildContent: function(element) {
      var childElement = element;
      return childElement.text !== undefined ? childElement.text : childElement.textContent;
   },

	handleError : function(request) {
		this.msg.innerHTML = 'Si &egrave; verificato un errore di comunicazione con il server. Contattare l\'amministratore di sistema';
	}
	
};


/******************************************************/
/***************** OGGETTO TEXT SUGGEST ***************/
/******************************************************/
TextSuggest = Class.create();

TextSuggest.prototype = {

	initialize: function(anId, url, options) {
		this.id          = anId;
		this.textInput   = $(this.id);

		var browser = navigator.userAgent.toLowerCase();
		this.isIE        = browser.indexOf("msie") != -1;
		this.isOpera     = browser.indexOf("opera")!= -1;

		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 = Object.extend({
			suggestDivClassName: 'suggestDiv',
			suggestionClassName: 'suggestion',
			matchClassName     : 'match',
			matchTextWidth     : true,
			selectionColor     : '#DDDDDD',
			matchAnywhere      : false,
			ignoreCase         : false,
			count              : 10
	      }, options || {});
	},

	injectSuggestBehavior: function() {
		if ( this.isIE )
			{this.textInput.autocomplete = "off";}
		var keyEventHandler = new TextSuggestKeyHandler(this);
		var insAfter = new Insertion.After( this.textInput, '<input type="text" id="'+this.id+'_preventtsubmit'+'" style="display:none"/>' );
		var insAfter1 = 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.style.backgroundColor = "";
		}
		this.selectedIndex = n;
		span = $( this.id + "_" + this.selectedIndex );
		if ( span ){
			span.style.backgroundColor = this.options.selectionColor;
		}
	},

	sendRequestForSuggestions: function() {
		if ( this.handlingRequest ) {
			this.pendingRequest = true;
			return;
		}
		this.handlingRequest = true;
		this.callRicoAjaxEngine();
	},

	callRicoAjaxEngine: function() {
		var callParms = [];
		callParms.push( this.id + '_request');
		callParms.push( 'id='             + this.id);
		callParms.push( 'count='          + this.options.count);
		callParms.push( 'strQuery='       + 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.id + "_hidden" ).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 strValue = this.getElementContent(entries[i].getElementsByTagName('value')[0]);
			this.suggestions.push( { text: strText, value: strValue } );
		}
	},

	setInputFromSelection: function() {
		var hiddenInput = $( this.id + "_hidden" );
		var suggestion  = this.suggestions[ this.selectedIndex ];
		
		this.textInput.value = suggestion.text;
		hiddenInput.value    = suggestion.value;
		this.hideSuggestions();
		/*** modifica aggiunta in data 30/01/2007 ***/
		if(this['transferHiddenValue'] !== undefined)
			{this.transferHiddenValue(suggestion.value);}
	},

	showSuggestions: function() {
		var divStyle = this.suggestionsDiv.style;
		if ( divStyle.display === '' )
			{return;}
		this.positionSuggestionsDiv();
		divStyle.display = '';
	},

	positionSuggestionsDiv: function() {
		var textPos = RicoUtil.toDocumentPosition(this.textInput);
		var divStyle = this.suggestionsDiv.style;
		divStyle.top  = (textPos.y + this.textInput.offsetHeight) + "px";
		divStyle.left = textPos.x + "px";
		
		if ( this.options.matchTextWidth )
			{divStyle.width = (this.textInput.offsetWidth- this.padding()) + "px";}
	},

	padding: function() {
		try{
			var styleFunc = RicoUtil.getElementsComputedStyle;
			var lPad    = styleFunc( this.suggestionsDiv, "paddingLeft",      "padding-left" );
			var rPad    = styleFunc( this.suggestionsDiv, "paddingRight",     "padding-right" );
			var lBorder = styleFunc( this.suggestionsDiv, "borderLeftWidth",  "border-left-width" );
			var rBorder = 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 parseInt(lPad) + parseInt(rPad) + parseInt(lBorder) + parseInt(rBorder);
		}catch (e){
			return 0;
		}
	},

	hideSuggestions: function() {
		this.suggestionsDiv.style.display = 'none';
	},

	createSuggestionsDiv: function() {
		this.suggestionsDiv = document.createElement("div");
		this.suggestionsDiv.className = this.options.suggestDivClassName;
		
		var divStyle = this.suggestionsDiv.style;
		divStyle.position = 'absolute';
		divStyle.zIndex   = 101;
		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]);}
	},

	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;
		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) {
		return element.firstChild.data;
	}
	
};

/******************************************************************/
/***************** OGGETTO GESTORE EVENTI TEXTFIELD ***************/
/******************************************************************/
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);}
	},

	keydownHandler: function(e) {
		var upArrow   = 38;
		var downArrow = 40;
		
		if ( e.keyCode == upArrow ) {
			this.textSuggest.moveSelectionUp();
			setTimeout( this.moveCaretToEnd.bind(this), 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();
			return true;
		}
		return false;
	},

	moveCaretToEnd: function() {
		var pos = this.input.value.length;
		if (this.input.setSelectionRange) {
			this.input.setSelectionRange(pos,pos);
		}
		else if(this.input.createTextRange){
			var m = this.input.createTextRange();
			m.moveStart('character',pos);
			m.collapse();
			m.select();
		}
	},

	onblurHandler: function(e) {
		if ( this.textSuggest.suggestionsDiv.style.display === '' )
			{this.textSuggest.setInputFromSelection();}
		this.textSuggest.hideSuggestions();
	}
	
};



/***********************************************************/
/************ Button con controllo asincrono ************/
/***********************************************************/
function AjaxButton(id, formId, url, options) {
	this.id = id;
	this.theButton = xGetElementById(id);
	this.theForm = xGetElementById(formId);
	this.options = options;
	this.msgField = null;
	/**** creazione oggetto XMLHttpRequest cross-browser per richieste asincrone ***/
	this.ajaxHelper = new net.ContentLoader(this, url, "POST", options.requestParameters || []);
	/**** inizializzazione comportamento del componente ****/
	this.initializeBehaviour();
}

AjaxButton.prototype = {
	initializeBehaviour : function() {
		var oThis = this;
		this.theButton.onclick = function() {oThis.clicked();};
	},
	
	clicked : function() {
		/**** Serializzazione degli input contenuti nella form ****/
		this.ajaxHelper.sendRequest(Form.serialize(this.theForm));
	},
		
	setMsgField : function (id_msgField){
		this.msgField = xGetElementById(id_msgField);
	},
	
	ajaxUpdate : function(request) {
		this.responseManager(request.responseXML.documentElement);
	},
	
	responseManager : function(ajaxResponse) {
		myResponseManager(this, ajaxResponse);
	},

   getElementContent: function(element,tagName) {
      var childElement = element.getElementsByTagName(tagName)[0];
      if (null === childElement || childElement === undefined){
      	return null;
      }
      else {
      	return childElement.text !== undefined ? childElement.text : childElement.textContent;
      }
   },

   getChildContent: function(element) {
      var childElement = element;
      return childElement.text !== undefined ? childElement.text : childElement.textContent;
   },

	handleError : function(request) {
		var errorStr = 'Si &egrave; verificato un errore di comunicazione con il server.\nContattare l\'amministratore di sistema (verificare i diritti di accesso alla risorsa)';
		if (null !== this.msgField){
			this.msgField.innerHTML = errorStr;
		}
		else{
			alert (errorStr);
		}
	}
	
};



