/*
jx.class.js, version 0.6.1 (2006-05-18)
Copyright: 2006, Maurizio Natali (http://www.spaziografico.it/)
License: http://creativecommons.org/licenses/LGPL/2.1/

0.7
----
2008-01-29 Inserimento dell'opzione Async

0.6.1
-----
Tag alt all'immagine di loading con scritto "Caricamento.."

0.6
---
Inserita opzione XML per richieste JxFunction e JxTarget

0.5
---
Intercettazione di status pagina vuota, che su safari generava un errore

0.4
---
Sintassi try anche per la verifica dello status con eventuale segnalazione di errori
Istanza dell'oggetto XMLHTTP con sintassi condizionale rispetto la versione del browser
	questo evita l'utilizzo del try{} catch{} su IE5

0.3
---
Aggiunta la var JxDebug che definisce se siamo in test l'eliminazione dei try
e la creazione di un div per il debug dei response

0.2 
---
Aggiunta JxExec che può ricevere una stringa con funzioni js da eseguire al termine dell'operazione
Modifica per poter inviare richieste multiple contemporanee
*/
JxConnection		=	0 ;
// Se JxDebug è = a true la sintassi TRY viene tolta e quindi gli errori sono visualizzati
if (typeof(JxDebug)!="undefined") JxDebug = JxDebug;
else JxDebug = false ;
// definisce se viene visualizzata la barra di progressione
if (typeof(JxProgressBarActive)!="undefined") JxProgressBarActive	=	JxProgressBarActive;
else JxProgressBarActive = true ;
// Testo predefinito per il carivamento
if (typeof(JxAlert)!="undefined")  JxAlert = JxAlert;
else JxAlert = "";
// nome di default del div con la barra di progressione
IdDivProgress		=	"divProgress" ;
// nome di default dell'img barra di progressione
IdImgProgress		=	"imgProgress" ;
// nome di default del div di debug
IdDivDebug			=	"divDebug" ;

// FUNZIONE PER VELOCE ISTANZA DI JX CON TARGET "FUNZIONE"
// Invia strQuery a strUrl con strMethod
// Risultato su funzione strFunction(risultato)
function JxFunction	(	
					strMethod, 	// GET | POST
					strUrl,		// URI
					strQuery,	// var1=valore1&va[n]=valore[n]
					strFunction,// stringa nome Funzione
					strExec,	// Funzione da eseguire al termine
					strXML,		// true | false : restituisce XML?
					strASync	// true | false : async | sync
					)
{
	strExec = strExec || "";
	strASync = strASync || "";
	strXML = strXML || false;	
	var oJxFunction				=	new	Jx(strXML);
	oJxFunction._JxMethod		=	strMethod ;
	oJxFunction._JxUrl			=	strUrl ;
	oJxFunction._JxQuery		=	strQuery ;
	oJxFunction._JxFunction		=	strFunction ;
	oJxFunction._JxExec			= 	strExec;
	oJxFunction._JxASync		= 	(strASync) ? true : false;
	oJxFunction._JxFnComplete	=	"";
	oJxFunction.Connect();	
}


// FUNZIONE PER VELOCE ISTANZA DI JX CON TARGET "DIV"
// Invia strQuery a strUrl con strMethod
// Risultato su document.getElementById(strTarget).innerHTML
function JxTarget	(
					strMethod, 	// GET | POST
					strUrl,		// URI
					strQuery,	// var1=valore1&va[n]=valore[n]
					strTarget,	// ID oggetto destinazione
					strExec,	// Funzione da eseguire al termine
					strXML,		// true | false : restituisce XML?
					strASync	// true | false : async | sync
					)
{
	strExec = strExec || "";
	strASync = strASync || "";
	strXML = strXML || false;	
	var oJxTarget			=	new	Jx(strXML);
	oJxTarget._JxMethod		=	strMethod ;
	oJxTarget._JxUrl		=	strUrl ;
	oJxTarget._JxQuery		=	strQuery ;
	oJxTarget._JxTarget		=	strTarget ;
	oJxTarget._JxExec		= 	strExec;
	oJxTarget._JxASync		= 	(strASync) ? true : false;
	oJxTarget._JxFnComplete	=	'';
	oJxTarget.Connect();
}



/*
----------------------------------
Costruttore Jx
----------------------------------
*/
function Jx(isXML)
{
	this._JxXML			=	isXML ; // Segnala se la richiesta è XML o Testo standard
	this._JxMethod		=	"" ; // GET | POST
	this._JxUrl			=	"" ; // Url della richiesta Jx
	this._JxQuery		=	"" ; // var1=valore1&var2=valore2&[..]varN=valoreN
	this._JxTarget		=	"" ; // Se la risposta deve essere inserita in un Div, ne specifica l'ID
	this._JxFunction	=	"" ; // Se la risposta va inviata ad una funzione, questa stringa è il suo nome (la funzione riceve (result)
	this._JxExec		=	"" ; // Se bisogna eseguire delle funzioni al termine, questa stringa le può contenere
	this._JxFnComplete	=	"JxComplete" ; // Funzione predefinita richiamata al termine dell'esecuzione, per ultima
	this._JxAlert		=	JxAlert ; // Eventuale messaggio da scrivere nel Div in attesa che questo venga riempito
	this._JxASync		=	true ; // true = async , false = sync
	this.Connect		=	JxConnect ; // Metodo che inizializza la connessione
}

function JxConnect()
{

	// Integra valori classe per funzioni secondarie
	var JxXML		=	this._JxXML;
	var JxMethod	=	this._JxMethod;
	var JxUrl		=	this._JxUrl;
	var JxQuery		=	this._JxQuery;
	var JxTarget	=	this._JxTarget;
	var JxFunction	=	this._JxFunction;
	var JxExec		=	this._JxExec;
	var JxFnComplete=	this._JxFnComplete ;
	var JxAlert		=	this._JxAlert ;
	var JxASync		=	this._JxASync ;
	var JxProgress	=	JxProgressBar ;
	var JxError		=	JxErrorPage ;
	var JxHttpRequest = false;
	// NOTA: Usare un nuovo oggetto XMLHttpRequest per ogni richiesta.
	// Questo eviterà anche dei problemi quando si fanno richieste multiple e asincrone.	

	// Crea un'istanza dell'oggetto XMLHTTP cross-browser	
	if (window.XMLHttpRequest)
	{ 
		// Mozilla, Safari,...
		JxHttpRequest = new XMLHttpRequest();
		// la linea sottostante causerà errori di JavaScript Console in Firefox 1.5b 
		// come documentato in https://bugzilla.mozilla.org/show bug.cgi?id=311724 
		// se la pagina chiamata da XMLHttpRequest non è XML valido (per esempio se è testo semplice).
		// Se si ottiene Syntax Error oppure Not Well Formed Error su quel browser e non si sta'
		// provando a caricare una pagina XML da una XMLHttpRequest, si deve rimuovere la linea di codice
		// ------------------------------------------------------
		if (JxXML)
		{
			if (JxHttpRequest.overrideMimeType) JxHttpRequest.overrideMimeType('text/xml');
		}
		// ------------------------------------------------------		
	}
	else
	{
		/*@cc_on @*/ 
		/*@if (@_jscript_version >= 5) 
		if (window.ActiveXObject) 
		{ // Internet Explorer
			try {
				JxHttpRequest = new ActiveXObject("Msxml2.XMLHTTP");
			} catch (e) {
				try {
					JxHttpRequest = new ActiveXObject("Microsoft.XMLHTTP");
				} catch (e) {}
			}
		}
		@end @*/ 
	}
	
	if (!JxHttpRequest)
	{
		alert("Errore: impossibile creare un'istanza XMLHTTP");
		return false;
	}
	else
	{
		// Se c'è un div target inserisce il testo di attesa specificato
		if (JxTarget!="") try { document.getElementById(JxTarget).innerHTML = JxAlert; } catch (e) {}
		// lancia la barra di progressione
		try {JxProgress(true);}  catch(e) {}
		// dice all'oggetto di richiesta HTTP quale funzione 
		// JavaScript farà il lavoro di trattare la risposta
		// ----------------------------------------------------------------
		JxHttpRequest.onreadystatechange = function()
		{
			// Funzione che tratta la risposta
			// valori readyState:
			// 0 (non inizializzato)
			// 1 (caricamento)
			// 2 (caricamento completato)
			// 3 (interattivo)	
			// 4 (completo)	
			if (JxHttpRequest.readyState == 4)
			{
				if (JxXML)
					JxResponse = JxHttpRequest.responseXML;
				else
					JxResponse = JxHttpRequest.responseText;
				// Blocca il Load
				try {JxProgress(false);}  catch(e) {}
				// creo un riferimnento alla risposta
				try {JxStatusRequest=JxHttpRequest.status;} catch(e) {alert("Exception : " + e);}
				switch (JxStatusRequest)
				{
					case 200:
						// Per debug visualizza un alert se la risposta inizia con Error: o Debug:
						if (	JxResponse.indexOf('Errore:') > -1 || 
								JxResponse.indexOf('Error:') > -1 || 
								JxResponse.indexOf('Debug:') > -1)
						{
						   alert(JxResponse);
						}
						else
						{	
							if (JxDebug) JxToDebug(JxResponse);
							if (JxFunction!="")
							{
								if (JxDebug)
								{
									eval(JxFunction + "(JxResponse);");
								}
								else
								{
									try {
										eval(JxFunction + "(JxResponse);");
									} catch (e) {
										alert("Errore: non riesco ad eseguire la funzione '" + JxFunction + "'");
									}
								}
							}
							if (JxTarget!="")
							{
								if (JxDebug)
								{
									document.getElementById(JxTarget).innerHTML = JxResponse;
								}
								else
								{
									try {
										document.getElementById(JxTarget).innerHTML = JxResponse;
									} catch (e) {
										alert("Errore: non riesco ad aggiornare il contenuto del div ID='" + JxTarget + "'");
									}
								}
							}							
							if (JxExec!="")
							{
								if (JxDebug)
								{
									// richiama la funzione
									eval(JxExec);
								}
								else
								{
									try {
										eval(JxExec);
									} catch (e) {
										alert("Errore: non riesco ad eseguire '" + JxExec + "'");
									}
								}
							}							
							// carica la funzione JxComplete
							if (JxDebug)
							{
								eval(JxFnComplete + "(JxResponse);");
							}
							else
							{
								try {
									eval(JxFnComplete + "(JxResponse);");
								} catch (e) {}
							}
						}
						break;
						
					case 404:
						// Page-not-found error
						alert("Errore: non trovo il file '" + JxUrl + "'");
						break;
					
					case 500:
						if (JxDebug) JxToDebug(JxResponse);
						else JxError(JxResponse);
						break;
						
					case undefined:
						//alert("Errore: pagina vuota");
						break;
						
					default:
						alert("Errore: non riesco ad analizzare '" + JxUrl + "'\nJxStatusRequest: " +JxStatusRequest);
						//JxError(strResponse);
						break;
				}
			}
		
		} ;

		// ----------------------------------------------------------------
		// il primo parametro è il metodo di richiesta HTTP: 
		// GET, POST, HEAD o altro http://www.w3.org/Protocols/rfc2616/rfc2616-sec9.html
		// Mantenere il metodo in maiuscolo altrimenti alcuni browser
		// (come Firefox) potrebbero non elaborare la richiesta
		//
		// Il secondo parametro è l'URL della pagina che state richiedendo.
		// Per sicurezza, non potete chiamare le pagine su domini di terzi.
		//
		// Il terzo parametro stabilisce se la richiesta è asincrona. 
		// Se true, l'esecuzione della funzione JavaScript continuerà mentre 
		// la risposta del server non è ancora arrivata
		// ----------------------------------------------------------------
		if (JxMethod.toUpperCase()=="POST")
		{
			// Essendo un POST le variabili si inviano successiamente con .send
			// ----------------------------------------------------------------
			JxHttpRequest.open("POST", JxUrl, JxASync);
			// ----------------------------------------------------------------
			// Il parametro del metodo send() può essere costituito dai dati  
			// da inviare al server se la richiesta è POST-ing, così:
			// name=value&anothername=othervalue&so=on
			// ma per inviare i dati bisogna cambiare il MIME type della richiesta 
			// usando la seguente linea:
			// ----------------------------------------------------------------
			JxHttpRequest.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
			// ----------------------------------------------------------------
			JxHttpRequest.send(JxQuery);
			// ----------------------------------------------------------------
		} 
		else if (JxMethod.toUpperCase()=="GET")
		{	
			// Essendo un GET le variabili vanno inserite nella URL con ?var=valore
			// ----------------------------------------------------------------
			JxHttpRequest.open("GET", (JxUrl + "?" + JxQuery), JxASync);
			// ----------------------------------------------------------------
			JxHttpRequest.send('');
			// ----------------------------------------------------------------
		}
		else
		{
			alert("Errore: metodo non corretto per open();");
			return false;
		}
	}



	// funzione che crea la pagina di 
	// errore 500 a tutto schermo:
	function JxErrorPage(strIn)
	{
		var errorWin;
		// Create new window and display error
		try {
				errorWin = window.open('', 'JxErrorWin',''); //width=640,height=480,toolbar=0,location=0,directories=0,status=1,menuBar=0,scrollBars=yes,resizable=1
				errorWin.document.body.innerHTML = strIn;
		}
		// If pop-up gets blocked, inform user
		catch(e) {
				alert(	'Si è verificato un errore, ma non è possibile visualizzare ' +
						'il messaggio di debug, in quanto il browser ha il blocco pop-up attivo.\n' +
						'Abilitare i pop-up per questo sito e ritentare.');
		}
	}


	// Attiva / Disattiva la barra di progressione
	function JxProgressBar(state)
	{
		// verifico se si vuole la barra di progressione
		if (JxProgressBarActive)
		{
			if(!document.getElementById || !document.getElementsByTagName || !document.createElement)
			{
				alert("Errore: il browser non permette la creazione di una barra di progressione");
				return false;
			}
			else
			{	// crea la barra se non è stato fatto prima
				CreateProgressBar();
				// Oggetti Div e Img
				oDivProgress = document.getElementById(IdDivProgress);
				oImgProgress = document.getElementById(IdImgProgress);
				
				// aumenta il n.ro di volte che è stata richiamata la funzione con state=true
				if (state)	JxConnection++;
				// diminiusce il n.ro di volte che è stata richiamata la funzione con state=false
					else	JxConnection--;
				
				// se ci sono connessioni attive la barra viene visualizzata
				if (JxConnection)
				{
					//oID(MASTER_PAGE).style.visibility = "visible";
					oDivProgress.style.display = "block";
					//Progress();
				}	
				// alrimenti viene nascosta
				else
				{
					//oID(MASTER_PAGE).style.visibility = "visible";
					oDivProgress.style.display = "none";
					//Progress(false);
				}
	
			}
		}

	}

}
// Crea l'oggetto Barra di Progressione
function CreateProgressBar()
{
	var img_w=190; var img_h=14;
	var w = window.document.width;
	var h = window.document.height;
	var l = (w/2) - (img_w/2);
	var t = (h/2) - (img_h/2);
	
	// verifica l'esistenza del div
	if (document.getElementById(IdDivProgress)==null)
	{
		// body
		var myBody = document.getElementsByTagName('body')[0];
		//if (typeof(oID(MASTER_PAGE)!=undefined) oID(MASTER_PAGE).style.zIndex=2;
		myBody.style.zIndex=2;										
		// add div
		var oProgress = document.createElement('div');
		oProgress.setAttribute("id",IdDivProgress);
		// style
		oProgress.style.position		= ((isMSIE)?('absolute'):('fixed'));
		oProgress.style.display			= 'none';
		oProgress.style.left			= '0';
		oProgress.style.top				= '0';
		oProgress.style.height			= img_h+'px';
		oProgress.style.width			= img_w+'px';
		oProgress.style.padding			= '20px 20px 20px 20px';
		oProgress.style.borderRight		= '1px solid #666';
		oProgress.style.borderBottom	= '1px solid #666';
		oProgress.style.backgroundColor	= '#fff';	
		// add img
		var oImg = document.createElement('img');
		oImg.setAttribute("id",IdImgProgress);
		oImg.setAttribute("alt","Caricamento...");
		// style
		oImg.src			=	ProgressBarImage.src;
		oImg.style.display	=	'block';
		oImg.width			=	img_w;
		oImg.height			=	img_h;
		// inserisci
		oProgress.appendChild(oImg);
		oProgress.style.zIndex=10;
		myBody.appendChild(oProgress);
		
	}

}

/*
JxToDebug, se JxDebug è true, invia del testo al div nascosto
per effettuare il debug delle risposte Jx
*/
function JxToDebug(result)
{
	if (JxDebug)
	{
		CreateJxDebug() ;
		var oDebug = document.getElementById(IdDivDebug);
		var oList = document.createElement('div');
		oDebug.appendChild(oList);	
		oList.innerHTML = '<div align="left"><strong>['+ current_time() +']</strong>\t\t'+ stripslashes(result) +'<hr /><div>';
	}	
}
// Crea il div contenente le istruzioni di debug
function CreateJxDebug()
{
	if (document.getElementById(IdDivDebug)==null)
	{
		var myBody = document.getElementsByTagName('body')[0];		
		// add div
		var oDebug = document.createElement('div');
		oDebug.setAttribute("id",IdDivDebug);
		// style		
		oDebug.style.display		= 'block';
		oDebug.style.padding		= '10px';
		oDebug.style.backgroundColor= '#ffd0dc';	
		oDebug.style.color			= '#000';
		oDebug.style.fontFamily		= 'Courier';
		oDebug.style.fontSize		= '10px';
		myBody.appendChild(oDebug);
	}
}
// Attaccata al click sul mostra nascondi del div di debug
// serve per nasconderlo o visualizzarlo
function SwapJxDebug()
{
	var oDebug = document.getElementById(IdDivDebug);
	if (oDebug)
	{
		if (oDebug.style.display=='none')
		{
			oDebug.style.display		= 'block';
		}
		else
		{
			oDebug.style.display		= 'none';	
		}
	}
}


/*
La funzione itera la collezione attraverso gli elements della form, 
usando il type di ogni elemento per calcolare come recuperare il suo valore. 
Per ogni elemento denominato distintamente, aggiunge il nome ed il valore 
in una variabile della querystring strSubmit. 
Poi passa quella stringa all'oggetto XMLHttpRequest per il POST.
*/
function JxQueryForm(strForm)
{
	var submitContent = '' ;
	var formElem ;
	var lastElemName = '' ;
	
	// Cerca la form indicata a partire dal nome
	for (f = 0; f < document.forms.length; f++)
	{
		if (document.forms[f].name==strForm || document.forms[f].id==strForm)
		{
			myForm = document.forms[f];
			//alert("Trovata form("+myForm.name+")");
			break;
		}
	}
	// Se la trova ok altrimenti va avanti
	try {
		myForm.elements.length ;
	} catch(e) {
		alert("Errore: non riesco ad identificare il form '" + strForm + "'");
		return false ;
	}
  
	for (i = 0; i < myForm.elements.length; i++)
	{
		formElem = myForm.elements[i];
		switch (formElem.type)
		{
		  // Elementi per i quali è possibile leggere il value
		  case 'text':
		  case 'hidden':
		  case 'password':
		  case 'textarea':
		  case 'select-one':
			submitContent += formElem.name + '=' + formElem.value + '&'
			break;
			
		  // Radio buttons
		  case 'radio':
			if (formElem.checked) {
			  submitContent += formElem.name + '=' + formElem.value + '&'
			}
			break;
			
		  // Checkboxes
		  case 'checkbox':
			if (formElem.checked) {
			  // Continuing multiple, same-name checkboxes
			  if (formElem.name == lastElemName) {
				// Strip of end ampersand if there is one
				if (submitContent.lastIndexOf('&') == submitContent.length-1) {
				  submitContent = submitContent.substr(0, submitContent.length - 1);
				}
				// Append value as comma-delimited string
				submitContent += ',' + formElem.value;
			  }
			  else {
				submitContent += formElem.name + '=' + formElem.value;
			  }
			  submitContent += '&';
			  lastElemName = formElem.name;
			}
			break;
			
		}
	}
	// Remove trailing separator
	submitContent = submitContent.substr(0, submitContent.length - 1);
	return encodeURI(submitContent);
}


// Attacca l'evento Onload al Body
// -------------------------------
if (window.addEventListener)		window.addEventListener("load", do_onload, false);
else if (window.attachEvent)		window.attachEvent("onload", do_onload);
else if (document.getElementById)	window.onload=do_onload;
// -------------------------------
function do_onload()
{
	CreateProgressBar();
	if(typeof(JxInit)=='function') JxInit();
}
// -------------------------------
