﻿/*<SCRIPT type="text/javascript"><!--*/
//#######################################
//####     F U N Z I O N I . J S     ####
//#######################################
//	16/09/2008	ver. 2.15.3.2	- Risolti problemi in [OggettiRif_DlgFind]: ora ho un parametro unico per configurare i comportamenti, chiamato CFG.
//	15/09/2008	ver. 2.15.3.1	- Classe [HtmlPlus_Popup]: risolto baco su calcolo posizione Popup, mancava un "break"; aggiunto controllo sui
//				valori di posizione calcolati: se la coordinata (X o Y) è miniore di 10 allora imposto a 10.
//	12/09/2008	ver. 2.15.3		- Aggiunta funzione [OggettiRif_DlgFind]: apre la maschera standard di ricerca di records OggettiRif; fatte anche
//				numerose migliorie grafiche e di funzionamento su [HtmlPlus_Popup]: aggiunta possibilità di definire la posizione del popup tramite
//				una percentuale, risolto problema dell'ombra per siti più piccoli del browser, aggiunta variabile THIS nel codice dell'IFRAME.
//	03/09/2008	ver. 2.15.2.1	- Classe [HtmlPlus_Popup]: risolto baco su ombra, che non veniva mostrata come tale in caso di animazione "Zoom".
//	25/08/2008	ver. 2.15.2		- Modifica classe [HtmlPlus_Grid]: aggiunte funzioni "SetTrSelect" e "SetTrViewed".
//	07/08/2008	ver. 2.15.1		- Modifica classe [HtmlPlus_Grid]: rinominata funzione "TrEvents_onDblClick" in "TrEvents_OpenRecord".
//	04/08/2008	ver. 2.15.0		- Aggiunta classe [HtmlPlus_Grid]: serve per dare funzionalità Java ad una tabella.
//	31/07/2008	ver. 2.14.3.1	- Corretto baco funzione [SerializeValue]
//	23/07/2008	ver. 2.14.3		- Classe [HtmlPlus_ServerEval]: aggiunta funzione [Parameters], che contiene l'array dei parametri passati; nella
//				classe [DevelopingMode_AddItem] aggiunta condizione: se "window.DevelopingMode" non è TRUE allora la classe non funziona.
//				Procedure [SerializeValue] e [DeserializeValue]: risolto baco su conversione valore EMPTY (stringa vuota).
//	11/07/2008	ver. 2.14.2		- Aggiunta classe [HtmlPlus_ServerEval]: serve ad invocare comandi lato server.
//	27/06/2008	ver. 2.14.1.3	- Modificato procedure [HtmlPlus_BarcodeReader] e [DevelopingMode_AddItem].
//	20/06/2008	ver. 2.14.1.2	- Procedure [SerializeValue] e [DeserializeValue]: risolti diversi bachi che si manifestavano quando un Array o
//				un Dictionary erano senza elementi; ho risolto anche il problema di capire in DeserializeValue se un oggetto è un Dictionary
//				o Array, soluzione però che funziona solo se l'oggetto è stato generato da SerializeValue.
//	19/06/2008	ver. 2.14.1.1	- Soluzione baco [DevelopingMode]: al momento è stata bloccata la procedura [DevelopingModeMenu_AddItem], e
//				presto si dovrà cercare il motivo dell'errore e risolverlo.
//	18/06/2008	ver. 2.14.1		- Aggiunta funzione [DevelopingModeMenu_AddItem] per gestire il menù DevelopingModeMenu, e aggiunto impiego nella
//				classe [HtmlPlus_BarcodeReader].
//	30/05/2008	ver. 2.14.0.3	- Corretti commenti qua e la..
//	20/03/2008	ver. 2.14.0.2	- Classe [HtmlPlus_Popup]: corretto baco: andava in loop poichè ogni volta richiamava l'evento OnLoad.
//	13/02/2008	ver. 2.14.0.1	- Funzione[DeserializeValue] risolto baco: non deserializzava gli Interi ma solo i Float.
//	18/01/2008	ver. 2.14.0		- Modificato Funzione [GetBrowserInfo] in modo che ritorni il tipo sistema operativo utilizzato per il dispositivo, e 
//				aggiunto funzione per vedere che tipo di hardware è utilizzato. Modificata Funzione [SetProperty] se settando opacity si utilizza un 
//				dispositivo non PC opacity non viene settata.
//	08/01/2008	ver. 2.13.0		- Aggiunta Funzione [CNumHTML], ha lo stesso funzionamento di quella esistente in VBScript.
//	27/12/2007	ver. 2.12.1.1	- Classe [HtmlPlus_Popup]: risolto baco per IE6 in caso che il contenuto sia un IFRAME.
//	27/12/2007	ver. 2.12.1		- Funzione [GetBrowserInfo]: aggiunto 'CpuSpeed' che restituisce un numero che indica la velocità del processore.
//	27/12/2007	ver. 2.12.0.2	- Funzione [toNumber]: corretto comportamento nel caso che non c'è alcun numero memorizzato nel testo passato;
//				Classe [HtmlPlus_Popup]: fatta correzione nella funzione di gestione del ridimensionamento del browser, in caso di isModal=true
//				e isOpen=false.
//	21/12/2007	ver. 2.12.0.1	- Procedure [SerializeValue] e [DeserializeValue]: corrette in caso di conversione in Array e Dictionary.
//	20/12/2007	ver. 2.12.0		- Aggiunte funzioni per la gestione dei [COOKIE], aggiunta classe [HtmlPlus_Popup], e aggiunte e corrette altre
//				piccole cose.
//	14/12/2007	ver. 2.11.1		- Aggiunta funzione [IsUndefined]. Funzione [toNumber]: corretto baco che si verificava se il numero passato era
//				già un numero.
//	07/12/2007	ver. 2.11.0		- Aggiunta classe [HtmlPlus_SlideShow] per la gestione degli slide show.
//	05/12/2007	ver. 2.10.0.1	- Corretto baco funzione CStrJS.
//	04/12/2007	ver. 2.10.0		- Aggiunta classe [HtmlPlus_ClipMaker] per la gestione delle animazioni.
//	03/12/2007	ver. 2.9.7		- Modificata funzione [HtmlPlus_Autoscroll], aggiunto la possibilità di far scorrere gli oggetti orizzontalmente.F
//	07/11/2007	ver. 2.9.6		- Aggiunta funzione [CStrJS], che funziona come quella fatta in VBScript. Aggiunta poi [ViewPointerPosition].
//	10/10/2007	ver. 2.9.5		- Aggiunta alla classe [UrlParserClass]: ho aggiunto la funzione [GetPartialUrl] che restituisce una parte percorso
//				secondo le indicazioni (true/false) passate negli argomenti.
//  03/10/2007	ver. 2.9.4.1	- Corretto baco in funzione [HtmlPlus_AnimationOnMouseEvents] e corretto baco nella funzione [ValueType]
//  18/09/2007	ver. 2.9.4		- Inserita nuova funzione [CPropertyJS] da utilizzare per trasformare il nome di una proprietà dal formato CSS
//				al formato JScript. Risolto baco su funzione [SetCssStyle], in pratica nella RegEx per segnalare un carattere "\", JScript ne
//				necessita 2. Es.: per passare "\s*" a RegEx si deve scrivere così "\\s*".
//  14/09/2007	ver. 2.9.3.2	- Modificate Funzioni [CStrUrlParam] e [StringToUrl] risolto dei bachi.
//  13/09/2007	ver. 2.9.3.1	- Modificate Funzione [SetProperty] e HtmlPlus_AnimationOnMouseEvents, risolto dei bachi.
//  06/09/2007	ver. 2.9.3		- Modificate Funzione [GetProperty], in caso che la proprietà sia 'opacity' controlliamo il browser e la settiamo
//				in base allo stesso.
//  31/08/2007	ver. 2.9.2		- Modificate le funzioni[CStrUrlParam] e [StringToUrl]  in quanto esistevano in java procedure apposite
//  27/07/2007	ver. 2.9.1		- Modificata Classe HtmlPlus_AnimationOnMouseEvents, per la gestione di parametri mozilla o Ie (vedi alpha opacity)
//  27/07/2007	ver. 2.9.0		- Aggiunte le funzioni LFill, RFill, HTMLEncode, HTMLDecode, SerializeValue, DeserializeValue. Testare la
//				serializzazione e la deserializzazione degli arary e delle dictionary.
//	23/07/2007	ver. 2.8.6		- Aggiunta funzione [TestiLiberi_OpenWindow].
//	19/06/2007	ver. 2.8.5		- Risolto Baco funzione [toNumber] aggiunto metodo .valueOf all'oggetto Number.
//	15/06/2007	ver. 2.8.4		- Aggiunta funzione [IfNull].
//	25/05/2007	ver. 2.8.3		- Funzione [GetBrowserInfo]: aggiunta Info "ScreenWidth" e "ScreenHeight".
//	23/05/2007	ver. 2.8.2.1	- Classe [HtmlPlus_AutoScroll]: risolto problema di incompatibilità con Firefox.
//	02/04/2007	ver. 2.8.2		- Classe [HtmlPlus_BarcodeReader]: ora l'Azione chiamata può sapere qual'è il KeyChars corrente.
//	30/03/2007	ver. 2.8.1		- Classe [HtmlPlus_BarcodeReader]: su lettura di un barcode, ho fatto in modo di eseguire solo una Azione.
//	28/03/2007	ver. 2.8.0		- Aggiunta classe [HtmlPlus_BarcodeReader] per leggere i codici a barre dal browser (non necessariamente da un
//				Textbox) e [IsTrue] [IsFalse] per riconoscere i valori dichiaratamente impostati su TRUE e su FALSE.
//	19/03/2007	ver. 2.7.0		- Classe [HtmlPlus_AutoScroll]: rifatta nuova versione, con possibilità di indicare un Html di separatore pagina.
//	22/01/2007	ver. 2.6.2		- Aggiunta funzione [GetBrowserInfo], e migliorata la funzione [GetProperty].
//	15/01/2007	ver. 2.6.1.1	- Modifica funzione [SetProperty]: resa compatibile con FireFox.
//	07/12/2006	ver. 2.6.1		- Aggiunte funzioni [Help_OpenWindow] e [CStrUrlParam]
//	06/12/2006	ver. 2.6.0.2	- Modifica funzione [HtmlPlus_TextboxWithLabelInside]: resa compatibile con FireFox.
//	27/11/2006	ver. 2.6.0.1	- Modifica della funzione [SetCssStyle].
//	24/11/2006	ver. 2.6.0		- Diverse modifiche. Tra cui aggiunta di STDEvent, HtmlPlus_PageScroller, GetProperty e SetProperty.
//	21/11/2006	ver. 2.5.2.1	- Modifica alla classe [UrlParserClass]: aggiunto campo objectType.
//	17/11/2006	ver. 2.5.2		- Modifica a [findObj]: aggiunta ricerca per getElementById.
//	06/10/2006	ver. 2.5.1.3	- Risolto baco IMPORTANTE nella funzione [Traduci_Varchar_Write]: non era in grado di salvare correttamente
//				il nuovo testo se questo non era la lingua di indice ZERO e se il valore Indice non era passato come numero ma come testo.
//				Ho anche migliorato in performance le procedure LTrim, RTrim e Trim.
//	11/08/2006	ver. 2.5.1.2	- Risolto piccolo problema alla funzione [SetHtmlControlValue].
//	11/08/2006	ver. 2.5.1.1	- Risolto un problema alla nuova classe [HtmlPlus_TextboxWithLabelInside]: se il form che ospita il textbox ha
//				un pulsante predefinito (che fa il send alla pressione del tasto INVIO) il textbox non riusciva a memorizzare il valore prima
//				dell'invio del form.
//	09/08/2006	ver. 2.5.1		- Sostituito "document.getElementById" con "findObj".
//	09/08/2006	ver. 2.5.0		- Aggiunta classe [HtmlPlus_TextboxWithLabelInside] per mostrare una etichetta nel Textbox quando questo è vuoto.
//	08/08/2006	ver. 2.4.0		- Aggiunte procedure [InArray] e altre per la ricerca di stringhe ed oggetti all'interno di un array;
//				corretto anche difetto alla classe [UrlParserClass]: la funzione GetPath restituiva '/' in situazioni particolari.
//	07/08/2006	ver. 2.3.1		- Migliorie alla classe [UrlParserClass]: aggiunta funxione ExistsProtocol.
//	05/07/2006	ver. 2.3.0		- Aggiunta classe [HtmlPlus_AnimationOnMouseEvents] per animare oggetti html.
//	05/07/2006	ver. 2.2.2		- Risolto piccolo problema alla funzione [SetHtmlControlValue].
//	15/06/2006	ver. 2.2.1		- Spostata procedura per aprire un allegato da Funzioni.ASP a questo file.
//	12/06/2006	ver. 2.2.0		- Aggiunte variabili che indicano il browser in uso; aggiunta classe per la riproduzione di suoni.
//	31/05/2006	ver. 2.1.2		- Migliorati i commenti...
//	03/05/2006	ver. 2.1.1		- Migliorati i commenti...
//	03/05/2006	ver. 2.1.0		- Aggiunta implementazione di funzioni ValueType e modificato SetHtmlControlValue: ora posso settare
//				un SELECT con Multisel passando un Array. Devo però implementare la funzionalità oppostua sulla funzione GetHtmlControlValue.


//Assegnano delle variabili per il riconoscimento del browser in uso.
var IE = (navigator.appVersion.indexOf("MSIE")!=-1 && document.all)? 1:0;
var NS = (navigator.appName=="Netscape" && navigator.plugins["LiveAudio"])? 1:0;
var ver4 = (IE || NS)? 1:0;

function GetBrowserInfo(InfoName) {
	var str1, cont1, cont2;
	switch (InfoName.toLowerCase()) {
		case 'name':			//il comando restituisce questo: IE7="MSIE", Firefox2="Netscape"
			str1 = navigator.appName;
			switch (str1) {
				case 'Microsoft Internet Explorer':
					return 'MSIE';
				case 'Netscape':
					return 'Netscape';
				default:
					return str1;
			}
		case 'version':			//il comando restituisce questo: IE7=4.0, Firefox2=5.0
			str1 = navigator.appVersion;
			switch (GetBrowserInfo('name')) {
				case 'MSIE':
					str1 = str1.substr(str1.indexOf(' MSIE ') + 6);
					return toNumber(str1, 0);
				case 'Netscape':
					return toNumber(str1, 0);
				default:
					return str1;
			}
		case 'screenwidth':		//restituisce la larghezza (in pixel) dell'area utile di lavoro dello schermo (tipicamente 1024)
			switch (GetBrowserInfo('name')) {
				case 'MSIE':
					return window.screen.availWidth;
				case 'Netscape':
					return window.screen.availWidth;
				default:
					return 0;
			}
		case 'screenheight':	//restituisce la larghezza (in pixel) dell'area utile di lavoro dello schermo (tipicamente 1024)
			switch (GetBrowserInfo('name')) {
				case 'MSIE':
					return window.screen.availHeight;
				case 'Netscape':
					return window.screen.availHeight;
				default:
					return 0;
			}
		case 'os':				//indica il sistema operativo. Può essere:  'Windows', 'Linux', 'Mac'
			if (navigator.platform.substr(0,3) == 'Win') {
				return 'Windows';
			} else if (navigator.platform.substr(0,3) == 'Mac') {
				return 'Mac';
			} else if (navigator.platform.substr(0,6) == 'Linux ') {
				return 'Linux';
			} else if (navigator.platform.substr(0,6) == 'CE.Net') {
				return 'WinCE';
			} else if (navigator.platform.substr(0,6) == 'Series') {
				return 'Symbian';
			} else {
				return null;
			}
		case 'hardwaretype':	//indica il tipo di hardware. Può essere:  'pc', 'palm', 'smartphone'
			switch (GetBrowserInfo('os')) {
				case 'Windows':
				case 'Mac':
				case 'Linux':
					return 'pc';
				case 'WinCE':
					return 'palm';
				case 'Symbian':
					return 'smartphone';
				default:
					return null;
			}
		case 'iscookieenabled':	//restituisce TRUE se i cookie sono abilitati
			return IsCookieEnabled();
		case 'cpuspeed':		//restituisce un numero che rappresenta la velocità di calcolo. Prove:  PC P4HT 3.2GHz -> 3.558 ;  Palmare PXA270 624MHz -> 0.25
			if (GetBrowserInfo('IsCookieEnabled')) {
				str1 = GetCookie('CpuSpeed.v1');
				if (str1 === null) {
					SetCookie('CpuSpeed.v1', 1, 365);
					cont2 = new Date();
					for (cont1 = 0; cont1 < 1000000; cont1++) str1 = 1000 / cont1;
					cont1 = new Date();
					str1 = 1000 / (cont1 - cont2);
					SetCookie('CpuSpeed.v1', str1, 365);
				}
			} else {
				//Se i cookie non sono abilitati non mi metto a calcolare la velocità del processore, perchè è una operazione che potrebbe chiedere
				//più di 1 secondo, a seconda del pc, o addirittura di più se l'hardware è un vecchio pc o un palmare (commento del 2007).
				switch (GetBrowserInfo('HardwareType')) {
					case 'pc':
						str1 = 1;
						break;
					default:
						str1 = 0.2;
						break;
				}
			}
			return str1;
		case 'recommendedfps':	//valore FPS consigliato, in base alle prestazioni del pc
			str1 = GetBrowserInfo('CpuSpeed');
			if (str1 < 1) {
				str1 = 10;
			} else if (str1 > 5) {
				str1 = 30;
			} else {
				str1 = 10 + (str1 - 1) / 4 * 20;
			}
			return str1;	//per ora non ho un sistema per intuire il valore da consigliare
		default:
			return null;
	}
}


// ### ViewPointerPosition
// Passando un oggetto come parametro, restituisce le coodrinate del mouse rispetto all'oggetto passato e all'oggetto Window
function ViewPointerPosition(HtmlObject) {
	var obj1 = HtmlObject;
	if (ValueType(obj1) == 'string') obj1 = findObj(obj1);
	addEvent(obj1, 'mousemove', function (ev) {
					var eventObj = new STDEvent(ev);
					window.status = '[ViewPointerPosition] client = ' + eventObj.clientX + ', ' + eventObj.clientY + '; offset = ' + eventObj.offsetX + ', ' + eventObj.offsetY + '; screen = ' + eventObj.screenX + ', ' + eventObj.screenY + ';'  ;
					}
			);
}


//Aggiunge una nuova voce al menù [DevelopingMode]. Se quest'ultimo non esiste allora viene creato dalla funzione stessa. Argomenti:
//	Text :		il testo della voce di menù;
//	Function :	puntatore a funzione o stringa in JavaScript da eseguire su click sulla voce di menù.
function DevelopingModeMenu_AddItem(Text, Function) {
	this.objMenu = findObj('DivDevelopingModeMenu');
	this.objMenu_List;
	this.hideTimer;
	this._initialize = function() {
		var obj1;
		
		if (!this.objMenu) {
			this.objMenu = document.createElement('DIV');
			document.body.appendChild(this.objMenu);
			//alert('1'); return;
			this.objMenu.id = 'DivDevelopingModeMenu';
			this.objMenu.style.cssText = 'cursor:hand; position:absolute; z-index:10000; top:0px;right:0px; width:5px;height:5px; overflow:hidden; background-color:#ffff00; border:1px solid #ff0000; color:black; font-size:8pt; text-align:left;';
			this.objMenu.title = '[DevelopingModeMenu] clicca per aprire';
			addEvent(this.objMenu, 'click', this._DivMenu_Show);
			addEvent(this.objMenu, 'mouseout', this._DivMenu_Hide);
			
			this.objMenu._DivMenu_Hide__timeout = function () {
					this.style.overflow = 'hidden';
					this.style.width = '5px';
				}
			
			obj1 = document.createElement('DIV');
			this.objMenu.appendChild(obj1);
			obj1.innerHTML = '[DevelopingModeMenu]';
			obj1.style.cssText = 'font-weight:bold;';

			this.objMenu_List = document.createElement('UL');
			this.objMenu.appendChild(this.objMenu_List);
			this.objMenu_List.style.cssText = 'margin-top:0px;margin-left:20px;margin-right:0px;margin-bottom:0px;';
		} else {
			//alert('x'); return;
			this.objMenu = findObj('DivDevelopingModeMenu');
			this.objMenu_List = this.objMenu.getElementsByTagName('UL')[0];
		}
	}
	this._addItem = function(Text, Function) {
		var objItem, objItem_A;
		objItem = document.createElement('LI');
		this.objMenu_List.appendChild(objItem);
		
		objItem_A = document.createElement('A');
		objItem.appendChild(objItem_A);
		objItem_A.href = 'java' + 'script:void(0);';
		objItem_A.innerHTML = Text;
		
		switch (typeof(Function)) {
			case 'string':
				//addEvent(objItem_A, 'click', 'function() {' + Function + '}');
				objItem_A.href = 'javas'+'cript:' + Function + ';';
				break;
			case 'function':
				addEvent(objItem_A, 'click', Function);
				break;
		}
		addEvent(objItem, 'mousemove', this._DivMenu_Show);
		addEvent(objItem, 'mouseout', this._DivMenu_Hide);
	}

	this._DivMenu_Show = function () {
		if (this.hideTimer) window.clearTimeout(this.hideTimer);
		this.hideTimer = 0;
		if (objMenu.style.display != 'block') {
			objMenu.style.overflow = 'visible';
			objMenu.style.width = '300px'; 
			objMenu.style.height = 'auto';
		}
	}
	this._DivMenu_Hide = function () {
		if (!this.hideTimer) this.hideTimer = window.setTimeout('findObj(\'DivDevelopingModeMenu\')._DivMenu_Hide__timeout();', 1000);
	}
	this._DivMenu_Hide__timeout = function () {
		objMenu.style.width = '5px';
		objMenu.style.height = '5px';
		objMenu.style.overflow = 'hidden';
		hideTimer = 0;
	}
	if (window.DevelopingMode) {
		this._initialize();
		if (Text && Function) this._addItem(Text, Function);
	}
}


// ###   getPos - Info-Data Flavio Spezi (ver. 2.0 - 03/11/2005)   ###
// Restituisce la coordinata X o Y dell'oggetto HtmlElement.
// Parametri:	HtmlElement :		l'oggetto di cui conoscere le coordinate.
//				TopOrLeft :			la coordinata richiesta; se si passa TOP restituirà la coordinata Y, altrimenti X.
// ATTENZIONE: la procedura non funziona correttamente se l'oggetto passato si trova all'interno di una tabella, la quale
//		ha impostato l'attributo BORDER ad un valore maggiore di zero, non ha una configurazione STYLE che configura lo
//		spessore del bordo e la cella che contiene l'oggetto non ha una configurazione STYLE che configura lo spessore
//		del bordo. Per risolvere questo eventuale problema, impostare l'attributo POSITION dell'oggetto richiesto al
//		valore RELATIVE oppure ABSOLUTE.
function getPos(HtmlElement, TopOrLeft) {
	var fReturn = 0;
	var obj = HtmlElement;
	var topOrLeftValue = ((TopOrLeft.substring(0, 1).toLowerCase()=='t') ? 'Top' : 'Left');
	var styleVal;
	//var str1 = HtmlElement.tagName;		//riattivare per fare i test
	while (obj) {
		styleVal = obj['offset' + topOrLeftValue];
		if (styleVal) {
			styleVal = toNumber(styleVal.toString(), null);
			if (styleVal > 0) {
				fReturn += styleVal;
				//str1 += ' offset=' + styleVal;		//riattivare per fare i test
			}
		}
		//str1 += '\n';			//riattivare per fare i test
		
		obj = obj.offsetParent;
		if (obj) {
			//str1 += obj.tagName;		//riattivare per fare i test
			if (obj.currentStyle) {
				styleVal = obj.currentStyle['border' + topOrLeftValue + 'Width'];
				if (styleVal) {
					styleVal = toNumber(styleVal.toString(), null);
					if (styleVal > 0) {
						fReturn += styleVal;
						//str1 += ' border=' + styleVal;		//riattivare per fare i test
					}
				}

				styleVal = obj.currentStyle['scroll' + topOrLeftValue];
				if (styleVal) {
					styleVal = toNumber(styleVal.toString(), null);
					if (styleVal > 0) {
						fReturn += styleVal;
						//str1 += ' scroll(1)=' + styleVal;		//riattivare per fare i test
					}
				}
			}
		}
	}
	//alert(str1);		//riattivare per fare i test
	return fReturn;
}

// Converte un nome di proprietà di stile css nel formato java.  Es.: "border-color" -> "borderColor".
// Se la proprietà è già scritta in stile Js la funzione restituisce PropertyName.
function CPropertyJS(PropertyName) {
	var fReturn;
	var indice;
	var arrayString;
	
	arrayString = PropertyName.split('-');

	fReturn = arrayString[0];
	for (indice = 1; indice < arrayString.length; indice++) {
		arrayString[indice] = arrayString[indice].substr(0, 1).toUpperCase() + arrayString[indice].substr(1);
		fReturn = fReturn.concat(arrayString[indice]);
	}
	return fReturn;
}

// ###   GetProperty - Info-Data Flavio Spezi (ver. 2.0 - 06/09/20067)
// Restituisce la proprietà richiesta. Se la proprietà non viene trovata, viene restituito il valore NULL.
// La ricerca avviene per stile e per proprietà.
// Testata su Internet Explorer 6 e su Mozilla Firefox 2.0.
function GetProperty(Obj, PropertyName, EmptyIsNotValid) {
	var nome, trovato, filtro;
	var ok, fReturn;
	var nomeProprieta;
	
	ok = false;
	if (Obj) {
		switch (PropertyName){ 
			case 'opacity' :
				// se la proprietà richiesta è opacity
				switch(GetBrowserInfo('name')){
					case 'MSIE' :
						trovato = false;
						for (filtro in Obj.filters) {
							switch (filtro.toLowerCase()) {
								case 'alpha':
								case 'dximagetransform.microsoft.alpha' : 
									trovato = true;
									break;
							}
							if (trovato) {
								fReturn = Obj.filters(filtro).opacity;
								ok = true;
								break;
							}
						}
						break;
					case 'Netscape':
						fReturn = null;
						if (!fReturn) fReturn = GetProperty(Obj, '-moz-opacity', true);
						if (!fReturn) fReturn = GetProperty(Obj, 'OPACITY', true);
						if (fReturn) {
							fReturn = fReturn * 100;
							ok = true;
						}
						break;
					default : 
						fReturn = null;
						if (!fReturn) fReturn = GetProperty(Obj, 'OPACITY', true);
						if (fReturn) {
							fReturn = fReturn * 100;
							ok = true;
						}
						break;
				}
				break;
			default :
				nomeProprieta = CPropertyJS(PropertyName);
				if (!ok && Obj.style) {
					try {
						fReturn = Obj.style[nomeProprieta];
						ok = true;
					} catch (e) {
						ok = false;
					}
					if ((ok) && (!fReturn && fReturn!='') || (fReturn=='' && EmptyIsNotValid)) ok = false;
				}
				if (!ok) {
					try {
						fReturn = Obj[nomeProprieta];
						ok = true;
					} catch (e) {
						ok = false;
					}
					if (ok && !fReturn && fReturn!='') ok = false;
				}
				if (!ok && Obj.style) {
					try {
						for (nome in Obj.style) {
							if (nome.toLowerCase() == nomeProprieta.toLowerCase()) {
								fReturn = Obj.style[nome];
								ok = true;
								break;
							}
						}
					} catch (e) {
						ok = false;
					}
					if ((ok) && (!fReturn && fReturn!='') || (fReturn=='' && EmptyIsNotValid)) ok = false;
				}
				if (!ok) {
					try {
						for (nome in Obj) {
							if (nome.toLowerCase() == nomeProprieta.toLowerCase()) {
								fReturn = Obj[nome];
								ok = true;
								break;
							}
						}
					} catch (e) {
						ok = false;
					}
					if ((ok) && (!fReturn && fReturn!='') || (fReturn=='' && EmptyIsNotValid)) ok = false;
				}
				if (!ok && Obj.currentStyle) {
					try {
						fReturn = Obj.currentStyle[nomeProprieta];
						ok = true;
					} catch (e) {
						ok = false;
					}
					if ((ok) && (!fReturn && fReturn!='') || (fReturn=='' && EmptyIsNotValid)) ok = false;
				}
				if (!ok && Obj.style) {
					try {
						fReturn = Obj.style[nomeProprieta];
						ok = true;
					} catch (e) {
						ok = false;
					}
					if ((ok) && (!fReturn && fReturn!='') || (fReturn=='' && EmptyIsNotValid)) ok = false;
				}
			
			break;
		}
	}
	if (!ok) fReturn = null;
	//alert(Obj.tagName + ': ' + PropertyName + '=' + fReturn + '; ok=' + ok);
	return fReturn;
}


// ###   SetProperty - Info-Data Flavio Spezi (ver. 2.0 -27/08/2007)
// Setta la proprietà richiesta. Restituisce TRUE se è stato sovrascritto un valore di STILE o di TAG.
// Testata su Internet Explorer 6 e su Mozilla Firefox 2.0.
function SetProperty(Obj, PropertyName, PropertyValue) {
	var filtro, trovato;
	var ok, fReturn;
	var nomeProprieta;
	
	ok = false;
	if (Obj) {
		switch (PropertyName) {
			case 'opacity':
				// il valore "opacity" deve essere da 0 a 100 ossia da trasparente a completamente opaco
				switch (GetBrowserInfo('name')) {
					case 'MSIE':
						switch 	(GetBrowserInfo('hardwaretype')) {
							case 'pc':
								trovato = false;
								for (filtro in Obj.filters) {
									switch (filtro.toLowerCase()) {
										case 'alpha':
										case 'dximagetransform.microsoft.alpha':
											trovato = true;
											break;
									}
									if (trovato) break;
								}
								if (trovato) {
									Obj.filters(filtro).Opacity = parseInt(PropertyValue);
								} else {
									Obj.style.filter += ' progid:DXImageTransform.Microsoft.Alpha(Opacity=' + parseInt(PropertyValue) + ')';
								}
								ok = true;
								break;
							default:
								ok = true;
								break;
						}
						break;
					case 'Netscape':
						//Si deve usare "-moz-opacity" oppure "opacity" ?...
						//Utilizziamo "opacity" per le nuove versioni di Firefox.. 1.5(Versione Ipotizzata)
						//Si utilizzava "-moz-opacity" per le vecchie versioni di MOzilla
						Obj.style.opacity = parseInt(PropertyValue) / 100;
						ok = true;
						break;
					default:
						Obj.style.opacity = parseInt(PropertyValue) / 100;
						ok = true;
				}
				break;
			default:
				if (!ok) {
					nomeProprieta = CPropertyJS(PropertyName);
					eval('Obj.' + nomeProprieta + ' = PropertyValue;');
					if (Obj.style) eval('Obj.style.' + nomeProprieta + ' = PropertyValue;');
					//if (Obj.style) Obj.style(PropertyName) = PropertyValue;
					ok = true;
				}
		}
	}
	//alert(Obj.tagName + ': ' + PropertyName + '=' + fReturn + '; ok=' + ok);
	return ok;
}



/* ==== COOKIE ==== */
// NOTE: un Cookie creato dal browser è leggibile ma non modificabile dal server, e viceversa. Se entrambi scrivono un Cookie con medesimo nome
// succede che ci troveremo entrambi i Cookie. Quando si leggeranno i valori, il server leggerà il primo che incontra. Mentre il browser, non
// fornendo procedure per leggere i singoli valori, posso ottenere ciò che voglio.
// Per non trovarmi a dover scegliere quale valore leggere (se quello scritto dal client o dal server) nego la possibilità di scrittura di un
// cookie se questo è già stato scritto dal suo antagonista.
function GetCookie(Name) {
	var re = new RegExp('([;][ ])?([^=]+)=([^;]*)', 'g');
	var reMatch;
	while ((reMatch = re.exec(document.cookie)) != null) {
		if (CStrByAscii(reMatch[2]) == Name) return DeserializeValue(CStrByAscii(reMatch[3].substr(1)));
	}
	return null;
}
function GetCookieOwner(Name) {
	//Restituisce "S", "C" o NULL in caso che il Cookie sia di proprietà del SERVER, CLIENT o se non esiste.
	//Restituisce "n" se il Cookie non è stato creato dalle procedure [SetCookie].
	//Attensione: per sapere se un Cookie è di proprietà di uno o l'altro, si deve leggere il primo catarrete, che puo essere "S" o "C". Quindi
	//questo meccanismo non garantisce in maniera assoluta se un Cookie è di una certa proprietà o se è stato creato con altre procedure e
	//casualmente il suo contenuto inizia con una di quelle lettere.
	var re = new RegExp('([;][ ])?([^=]+)=([^;]*)', 'g');
	var reMatch;
	while ((reMatch = re.exec(document.cookie)) != null) {
		if (CStrByAscii(reMatch[2]) == Name) {
			return (('SC'.indexOf(reMatch[3].charAt(0)) > -1) ? reMatch[3].charAt(0) : 'n');
		}
	}
	return null;
}
function SetCookie(Name, Value, Expire) {
	//ATTENZIONE: questa funzione è autorizzata a scrivere Cookie solo se esso non è stato già creato dal server.
	switch (IfNull(GetCookieOwner(Name), 'C')) {
		case 'C':	//Cookie creato dal client o non esistente, autorizzazione concessa.
			var scadenza;
			switch (ValueType(Expire)) {
				case 'number':		//numero di giorni a partire da oggi
					scadenza = new Date(); scadenza.setTime(scadenza.getTime() + 24 * 3600 * 1000 * Expire);
					break;
				case 'Date':		//data esatta
					scadenza = Expire;
					break;
				default:			//fra 3 mesi
					scadenza = new Date(); scadenza.setMonth(scadenza.getMonth() + 3);
					break;
			}
			document.cookie = CStrAscii(Name) + "=C" + CStrAscii(SerializeValue(Value)) + "; expires=" + scadenza.toGMTString();
			return true;
		default:	//Cookie creato dal server o provenienza sconosciuta, autorizzazione negata.
			return false;
	}
}
function DelCookie(Name) {
	SetCookie(Name, '', 1);
}
function IsCookieEnabled() {
	SetCookie('testCookie', 'test');
	return (GetCookie('testCookie') == 'test');
}



// ##	STD Event - Info-Data Flavio Spezi (ver. 1.0 - 24/11/2006)
// Interfaccia per oggetto Event. Istanziando questo oggetto, il primo argomento di un handler di evento, la classe restituisce le
// proprietà in stile IE. (info prese su http://www.javascriptkit.com/domref/domevent.shtml#e2)
// "STD" sta per "Standard".
function STDEvent(EventObjectByArgument) {
	this._ie = ((window.event) ? true : false);
	this.eventObj = ((this._ie) ? window.event : EventObjectByArgument);
	this.altKey; this.ctrlKey; this.shiftKey; this.button;
	this.clientX; this.clientY; this.fromElement; this.toElement;
	this.keyCode; this.offsetX; this.offsetY; this.srcElement; this.type;
	
	this._initialize = function () {
		this.altKey = this.eventObj.altKey;
		this.ctrlKey = this.eventObj.ctrlKey;
		this.shiftKey = this.eventObj.shiftKey;
		if (this._ie) {
			this.button = this.eventObj.button;
		} else {
			switch (this.eventObj.button) {
				case 0: this.button = 1; break;
				case 2: this.button = 2; break;
				case 1: this.button = 4; break;
				default: this.button = 0;
			}
		}
		this.clientX = this.eventObj.clientX;
		this.clientY = this.eventObj.clientY;
		this.fromElement = this._scegliGiusto(this.eventObj.fromElement, this.eventObj.relatedElement);
		this.toElement = this._scegliGiusto(this.eventObj.toElement, this.eventObj.relatedElement);
		this.keyCode = this._scegliGiusto(this.eventObj.keyCode, this.eventObj.charCode);
		this.offsetX = this._scegliGiusto(this.eventObj.offsetX, this.eventObj.layerX);
		this.offsetY = this._scegliGiusto(this.eventObj.offsetY, this.eventObj.layerY);
		//this.srcElement = this._scegliGiusto(this.eventObj.srcElement, this.eventObj.target);		pare che non sia [target] ma [currentTarget]
		this.srcElement = this._scegliGiusto(this.eventObj.srcElement, this.eventObj.currentTarget);
		this.type = this.eventObj.type;
	}
	this._scegliGiusto = function (perIE, perAltri) {
		if (this._ie) {
			return perIE;
		} else {
			return perAltri;
		}
	}
	/*
	this.altKey = function () { return this.eventObj.altKey; }
	this.ctrlKey = function () { return this.eventObj.ctrlKey; }
	this.shiftKey = function () { return this.eventObj.shiftKey; }
	this.button = function () {
		if (this._ie) {
			return this.eventObj.button;
		} else {
			switch (this.eventObj.button) {
				case 0: return 1; break;
				case 2: return 2; break;
				case 1: return 4; break;
				default: return 0;
			}
		}
	}
	
	//Proprietà
	this.clientX = function () { return this.eventObj.clientX; }
	this.clientY = function () { return this.eventObj.clientY; }
	this.fromElement = function () { return this._scegliGiusto(this.eventObj.fromElement, this.eventObj.relatedElement); }
	this.toElement = function () { return this._scegliGiusto(this.eventObj.toElement, this.eventObj.relatedElement); }
	this.keyCode = function () { return this._scegliGiusto(this.eventObj.keyCode, this.eventObj.charCode); }
	this.offsetX = function () { return this._scegliGiusto(this.eventObj.offsetX, this.eventObj.layerX); }
	this.offsetY = function () { return this._scegliGiusto(this.eventObj.offsetY, this.eventObj.layerY); }
	this.srcElement = function () { return this._scegliGiusto(this.eventObj.srcElement, this.eventObj.target); }
	this.type = function () { return this.eventObj.type; }
	*/
	//Metodi
	this.cancelBubble = function(Valore) {
		if (this._ie) {
			this.eventObj.cancelBubble = ((Valore)? true : false);
		} else {
			this.eventObj.stopPropagation((Valore)? true : false);
		}
	}
	this.returnValue = function(Valore) {
		if (this._ie) {
			this.eventObj.returnValue = ((Valore)? true : false);
		} else {
			this.eventObj.preventDefault((Valore)? false : true);
		}
	}
	
	this._initialize();
	return this;
}

// Setta uno stile o un elenco di stili (formattati così come sarebbero formattati nell'attributo STYLE di un TAG)
// ad un oggetto HTML.
// FORSE OBSOLETA...perchè ora esiste "ObjHtml.style.cssText "
function SetCssStyle(HtmlObject, CssStyle) {
	var cssStyleSenzaStringhe;
	var cont1, cont2;
	var str1, str2;
	
	str1 = new String(CssStyle);
	str1 = str1.replace(/\\\\/g, '##');		//Sostituisco la doppia barra con doppio #
	//Sostituisco le stringhe con dei #, uno per carattere di stringa.
	cont1 = str1.search(/['"]/g);
	while (cont1 > -1) {
		str2 = str1.substr(cont1, 1);
		//Cerco la chiusura di stringa, escludendo quelle situazioni in cui il sepStringa è preceduro da uno Escape (\)
		for (cont2 = cont1+1; cont2 < str1.length; cont2++) {
			if (str1.substr(cont2, 1) == str2 && str1.substr(cont2-1, 1) != '\\') break;
		}
		str1 = str1.substr(0, cont1) + StringRepeater('#', cont2 - cont1 + 1) + str1.substr(cont2 + 1);
		cont1 = str1.search(/['"]/g);
	}
	cssStyleSenzaStringhe = str1;
	
	//Cerco le definizioni di stile e le applico all'oggetto.
	var re = new RegExp('([@:a-z][a-z\\-]+)\\s*:\\s*([^;]+)', 'gi');
	var reMatch;
	while ((reMatch = re.exec(cssStyleSenzaStringhe)) != null) {
		//reMatch è un array che contiene informazioni sul match corrente.
		str1 = reMatch[1];	//reMatch[1] restituisce il nomeAttributo, che è sicuramente lo stesso valore che trovo come sottostringa di CssStyle a parità di posizione.
		str2 = RTrim(CssStyle.substr(reMatch.lastIndex - reMatch[2].length, reMatch[2].length));
		SetProperty(HtmlObject, str1, str2);
		//HtmlObject.setAttribute(str1, str2);
		//eval('HtmlObject.style.' + str1 + ' = "' + str2 + '";');
	}
}


// ###   toNumber - Info-Data Flavio Spezi (ver. 2.0 - 03/11/2005)   ###
// Restituisce il numero dalla forma string alla forma numerica
// Parametri:	NumericString :		il numero da restituire.
//				ReturnIfInvalid :	se il numero indicato è errato, verrà restituito questo valore.
//				AnyError :			se TRUE, la procedura restituirà ReturnIfInvalid per qualsiasie errore;
//									se FALSE (default) restituisce la parte numerica valida.
function toNumber(NumericString, ReturnIfInvalid, AnyError) {
	// Costanti di programmazione
	var numeriValidi = '0123456789', segniValidi = '+-', sepDecimaliValidi = '.,';
	// Variabili di programmazione
	var strNumero, strCifra;
	var segno = '+', intero = '', decimale = '';
	var trovatoSegno = false, trovatoDecimale = false, err = 0;
	var i, fReturn;

	if (typeof(NumericString) == 'number') {
		fReturn = NumericString;
	} else if (!NumericString || NumericString == '') {
		fReturn = ReturnIfInvalid;
	} else {
		strNumero = '';
		try {
			strNumero = NumericString.toString();
		} catch(e) {
		}
		strCifra = strNumero.charAt(0);
		if (segniValidi.indexOf(strCifra) > -1) {
			segno = strCifra;
			trovatoSegno = true;
		}
		for (i = ((trovatoSegno)? 1 : 0); i < strNumero.length; i++) {
			strCifra = strNumero.charAt(i);
			if (numeriValidi.indexOf(strCifra) > -1) {
				if (!trovatoDecimale) {
					intero += strCifra;
				} else {
					decimale += strCifra;
				}
			} else if ((!trovatoDecimale) && (sepDecimaliValidi.indexOf(strCifra) > -1)) {
				trovatoDecimale = true;
			} else {
				err = 1;	//troppi separatori o carattere non riconosciuto
				break;
			}
		}
		if ((intero != '' || decimale != '') && (err == 0 || !AnyError)) {
			if (intero == '') intero = '0';
			if (decimale == '') decimale = '0';
			fReturn = (new Number(segno + intero + '.' + decimale)).valueOf();
		} else {
			fReturn = ReturnIfInvalid;
		}
	}
	return fReturn;
}

function IfNull(Value, ValueIfNull) {
	if (Value === null || Value === void(0)) {
		return ValueIfNull;
	} else {
		return Value;
	}
}

function CNum(NumericString) {
	return toNumber(NumericString, null, true);
}

function CNumHTML(Value, Decimali){
	var fReturn;
	fReturn = CNum(Value);
	if (fReturn === null || fReturn === void(0)) {
		fReturn = Value;
	} else {
		fReturn = Value.toFixed(Decimali);
	}
	return fReturn;
}

function CNumHtml(Value, Decimali){
	return CNumHTML(Value, Decimali);
}

function CStrJS(Value) {
	return escape(Value).replace(/%/g, '\\x');
}
function CStrHTML(Value) {
	return CStrHtml(Value);
}
function CStrHtml(Value) {
	var fReturn;
	if (Value === null || Value === void(0)) {
		fReturn = Value;
	} else {
		fReturn = HTMLEncode(Value);
		if (fReturn) fReturn = fReturn.replace(/\x20\x20/g, '&nbsp;');
	}
	return fReturn;
}
function CStrUrlParam(Testo) {
      //Converte l'argomento [Testo] in una stringa adatta per essere passata come "valore di parametro" di un percorso URL.
      //Per esempio, la stringa "Cip & ciop" viene convertita in: "Cip%20%26%20ciop".
      var fReturn = Testo;
      fReturn = encodeURIComponent(Testo);
      /*
      fReturn = fReturn.replace(/\x26/g, '%26');                       //"&"
      fReturn = fReturn.replace(/\x23/g, '%23');                       //"="
      fReturn = fReturn.replace(/\x25/g, '%25');                       //"%"
      fReturn = fReturn.replace(/\+/g, '%2B');							//"+"
      fReturn = fReturn.replace(/\x23/g, '%23');                       //"#"
      fReturn = fReturn.replace(/\x0D/g, '%0D');                       //vbCr
      fReturn = fReturn.replace(/\x0A/g, '%0A');                       //vbLf
      */
      return fReturn;
}
function CStrAscii(Value) {
	//NOTA: La funzione [escape] converte tutti i caratteri speciali nel rispettivo valore in forma "%hh", ad eccezione di questi: "@*/+".
	//		Questa è la lista dei caratteri riconosciuti come speciali: " ~!@#$%^&*(){}[]=:/,;?+'""\"
	var fReturn = escape(Value);
	fReturn = fReturn.replace(/\x40/g, '%40');	//Conversione "@"
	fReturn = fReturn.replace(/\x2A/g, '%2A');	//Conversione "*"
	fReturn = fReturn.replace(/\x2F/g, '%2F');	//Conversione "/"
	fReturn = fReturn.replace(/\x2B/g, '%2B');	//Conversione "+"
	fReturn = fReturn.replace(/\x2D/g, '%2D');	//Conversione "-"
	fReturn = fReturn.replace(/\x2E/g, '%2E');	//Conversione "."
	//fReturn = fReturn.replace(/\x2D/g, '%2D');	//Conversione "-"
	//fReturn = fReturn.replace(/%20/g, '+');		//Ripristino " " in "+"
	return fReturn;
}
function CStrByAscii(Value) {
	var fReturn = unescape(Value);
	fReturn = fReturn.replace(/\x2B/g, ' ');	//Conversione "+" in " "
	return fReturn;
}

function StringToUrl(Testo) {      //## OBSOLETA ##

      //Converte l'argomento [Testo] in una stringa adatta per essere usata come "argomenti" di un percorso URL.
      //Per esempio, la stringa "param1=Cip & ciop&param2=x = y - z" viene convertito in: "param1=Cip%20&%20ciop&param2=x%20=%20y%20-%20z".
      //ATTENZIONE: se i valori di parametro contengono caratteri come "&" questi non vengono convertiti. Quindi è preferibile NON UTILIZZARE
      //QUESTA PROCEDURA.
      var fReturn = Testo;
      fReturn = encodeURI(Testo);
      /*
      fReturn = fReturn.replace(/\x25/g, '%25');                        //"%"
      fReturn = fReturn.replace(/\x26/g, '%26');                        //"&"
      fReturn = fReturn.replace(/\+/g,   '%2B');						//"+"
      fReturn = fReturn.replace(/\x23/g, '%23');                        //"#"
      fReturn = fReturn.replace(/\x0D/g, '%0D');                        //vbCr
      fReturn = fReturn.replace(/\x0A/g, '%0A');                        //vbLf
      */
      fReturn = fReturn.replace(/\[Dialog_SepParam\]/g, '&');    //ripristino "&"
      return fReturn;
}

function LTrim(Stringa) {
	var str1 = Stringa.toString();
	var cont1 = 0, limite = str1.length;
	while(str1.charAt(cont1) == ' ') {cont1++; if (cont1==limite) break;}
	return str1.substr(cont1);
}
function RTrim(Stringa) {
	var str1 = Stringa.toString();
	var cont1 = str1.length - 1, limite = -1;
	while(str1.charAt(cont1) == ' ') {cont1--; if (cont1==limite) break;}
	return str1.substr(0, cont1 + 1);
}
function Trim(Stringa) {
	var str1 = Stringa.toString();
	var cont1 = 0, cont2 = str1.length - 1;
	while(str1.charAt(cont1) == ' ') {cont1++; if (cont1==cont2) break;}
	while(str1.charAt(cont2) == ' ') {cont2--; if (cont2<=cont1) break;}
	return str1.substr(cont1, cont2 - cont1 + 1);
}

function LFill(Testo, Carattere, Lunghezza) {
	//Aggiunge [Carattere] a sinistra di [Testo] fino ad arrivare a [Lunghezza].
	//Se la lunghezza di [Testo] è maggiore di [Lunghezza], allora restituisce [Testo] senza variazioni.
	var fReturn, k, cont1;
	
	fReturn = '';
	k = Testo.length;
	if (k > Lunghezza) {
		fReturn = Testo;
	}else{
		cont1 = 0;
		while (cont1 < Lunghezza - k){
			fReturn += Carattere;
			cont1 += 1;
		}
		fReturn += Testo;
	}
	return fReturn;
}
function RFill(Testo, Carattere, Lunghezza) {
	//Aggiunge [Carattere] a destra di [Testo] fino ad arrivare a [Lunghezza].
	//Se la lunghezza di [Testo] è maggiore di [Lunghezza], allora restituisce [Testo] senza variazioni.
	var fReturn, k, cont1;
	
	fReturn = '';
	k = Testo.length;
	if (k > Lunghezza) {
		fReturn = Testo;
	}else{
		cont1 = 0;
		fReturn += Testo;		
		while (cont1 < Lunghezza - k){
			fReturn += Carattere;
			cont1 += 1;
		}
	}
	return fReturn;
}

function StringRepeater(strInput, intCount) {
	var arrTmp = new Array(intCount + 1);
	return arrTmp.join(strInput);
}


function IsTrue(Value) {
	var str1;
	if (ValueType(Value) == 'undefined') str1 = ''; else str1 = Value.toString().toLowerCase();
	switch (str1) {
		case 't': case 'true':
		case 'v': case 'vero':
		case 'y': case 'yes':
		case 's': case 'si': case 'sì':
		case 'on':
		case '1': case '-1':
			return true;
		default:
			return false;
	}
}
function IsFalse(Value) {
	var str1;
	if (ValueType(Value) == 'undefined') str1 = ''; else str1 = Value.toString().toLowerCase();
	switch (str1) {
		case 'f': case 'false': case 'falso':
		case 'n': case 'no':
		case 'off':
		case '0':
			return true;
		default:
			return false;
	}
}
function IsUndefined(Value) {
	return (Value === void(0));
}


//###############################################################################
//####		Elenco di procedure per la gestione di valori all'interno di un array.
function InArray(ArrayObject, Value) {
	//Cerca il valore nell'array, e restituisce la rispettiva KEY. Se non viene trovato restituisce NULL.
	var str1, fReturn;
	fReturn = null;
	if (ValueType(ArrayObject) == 'Array') {
		if (typeof(Value) == 'object') {
			for (str1 in ArrayObject) {
				if (ArrayObject[str1] === Value) {
					fReturn = str1;
					break;
				}
			}
		} else {
			for (str1 in ArrayObject) {
				if (ArrayObject[str1] == Value) {
					fReturn = str1;
					break;
				}
			}
		}
	}
	return fReturn;
}
/*
function InArrayRev(ArrayObject, Value) {
	//Cerca il valore nell'array, e restituisce la rispettiva KEY. Se non viene trovato restituisce NULL.
	//La ricerca avviene in ordine inverso.
}
function InKeyArray(ArrayObject, KeyValue) {
	//Cerca la KEY nell'array, e restituisce la rispettiva posizione. Se non viene trovato restituisce NULL.
}
*/
function TextInArray(ArrayObject, String) {
	//Cerca il valore di tipo string nell'array (no case sensitive), 
	var str1, fReturn;
	fReturn = null;
	if (ValueType(ArrayObject) == 'Array') {
		for (str1 in ArrayObject) {
			if (String.localeCompare(ArrayObject[str1].toString()) == 0) {
				fReturn = str1;
				break;
			}
		}
	}
	return fReturn;
	
}

function ValueType(Value) {
	//Restituisce il tipo di valore o oggetto
	var fReturn;
	if (Value === void(0)) {
		fReturn = 'undefined';
	} else if (Value === null) {
		fReturn = 'null';
	} else if (Value === '') {
		fReturn = 'empty';
	} else {
		fReturn = typeof(Value);	//Può essere: string, number, boolean, object, function
		if (fReturn == 'object') {
			//Cerco di vedere se Value è uno di questi specifici oggetti. Notare che questi hanno la prima lettera maiuscola. Quindi si
			//può sfruttare questa informazione per sapere se il tipo restituito 'OBJECT' è un tipo generico oppure esattamente 'Object'.
			if (Value instanceof Array) {
				fReturn = 'Array';
			} else if (Value instanceof Date) {
				fReturn = 'Date';
			} else {	//if (Value instanceof Object) {
				fReturn = 'Object';
			}
		} else if (fReturn == 'function') {
			fReturn = 'Function';
		}
	}
	return fReturn;
}

function HTMLEncode(Value){
	// Converte la stringa passata nel formato HTML
	var k, cont1;		//cont1 mi serve per iterare sulla stringa
	var cont2;			//mi serve per memmorizzare il carattere di partenza pgni volta che trovo un carattere da codificare
	var chars, ascChars;
	var trovato;
	var fReturn;
	
	if (Value === void(0) || Value === null) {
		fReturn = null;
	} else {
		fReturn = '';
		k = Value.length;
		cont1 = 0;
		cont2 = 0;
		trovato = false;
		
		while (cont1 < k) {
			ascChars = Value.charCodeAt(cont1);
			if (ascChars >= 128) {
				chars = '&#' + ascChars + ';';
				trovato = true;
			} else {
				switch (Value.charAt(cont1)) {
					case '"':	chars = '&quot;';	trovato = true; break;
					case '&':	chars = '&amp;';	trovato = true; break;
					case '<':	chars = '&lt;';		trovato = true; break;
					case '>':	chars = '&gt;';		trovato = true; break;
				}
			}
			if (trovato) {
				fReturn += Value.substr(cont2, cont1 - cont2) + chars;
				cont2 = cont1 + 1;
				trovato = false;
			}
			cont1 += 1;
		}	
		if (!trovato) fReturn += Value.substr(cont2);
	}
	return fReturn;
}

function HTMLDecode(TestoHtml){
	// converte caratteri codificati da Html a Unicode
	var re, indice, reMatch, str1;
	var nuovoVal;
	var fReturn;
	
	indice = 0;
	fReturn = '';
	nuovoVal = -1;
	re = new RegExp('&(#x[0-9a-fA-F]+|#[0-9]+|[a-zA-Z]{1,9}[0-9]{0,3});', 'g');
	reMatch = re.exec(TestoHtml);
	while (reMatch != null){
		str1 = reMatch[1];
		if (str1.substr(0,2) == '#x') {
			nuovoVal = parseInt(str1.substr(2), 16);
		} else if (str1.substr(0,1) == '#') {
			nuovoVal = str1.substr(1);
		} else {
			switch (str1){
				case 'quot'  : nuovoVal = 34; break;
				case 'amp'  : nuovoVal = 38; break;
				case 'lt'  : nuovoVal = 60; break;
				case 'gt'  : nuovoVal = 62; break;
				case 'nbsp'  : nuovoVal = 160; break;
				case 'iexcl'  : nuovoVal = 161; break;
				case 'cent'  : nuovoVal = 162; break;
				case 'pound'  : nuovoVal = 163; break;
				case 'curren'  : nuovoVal = 164; break;
				case 'yen'  : nuovoVal = 165; break;
				case 'brvbar'  : nuovoVal = 166; break;
				case 'sect'  : nuovoVal = 167; break;
				case 'uml'  : nuovoVal = 168; break;
				case 'copy'  : nuovoVal = 169; break;
				case 'ordf'  : nuovoVal = 170; break;
				case 'laquo'  : nuovoVal = 171; break;
				case 'not'  : nuovoVal = 172; break;
				case 'shy'  : nuovoVal = 173; break;
				case 'reg'  : nuovoVal = 174; break;
				case 'macr'  : nuovoVal = 175; break;
				case 'deg'  : nuovoVal = 176; break;
				case 'plusmn'  : nuovoVal = 177; break;
				case 'sup2'  : nuovoVal = 178; break;
				case 'sup3'  : nuovoVal = 179; break;
				case 'acute'  : nuovoVal = 180; break;
				case 'micro'  : nuovoVal = 181; break;
				case 'para'  : nuovoVal = 182; break;
				case 'middot'  : nuovoVal = 183; break;
				case 'cedil'  : nuovoVal = 184; break;
				case 'sup1'  : nuovoVal = 185; break;
				case 'ordm'  : nuovoVal = 186; break;
				case 'raquo'  : nuovoVal = 187; break;
				case 'frac14'  : nuovoVal = 188; break;
				case 'frac12'  : nuovoVal = 189; break;
				case 'frac34'  : nuovoVal = 190; break;
				case 'iquest'  : nuovoVal = 191; break;
				case 'Agrave'  : nuovoVal = 192; break;
				case 'Aacute'  : nuovoVal = 193; break;
				case 'Acirc'  : nuovoVal = 194; break;
				case 'Atilde'  : nuovoVal = 195; break;
				case 'Auml'  : nuovoVal = 196; break;
				case 'Aring'  : nuovoVal = 197; break;
				case 'AElig'  : nuovoVal = 198; break;
				case 'Ccedil'  : nuovoVal = 199; break;
				case 'Egrave'  : nuovoVal = 200; break;
				case 'Eacute'  : nuovoVal = 201; break;
				case 'Ecirc'  : nuovoVal = 202; break;
				case 'Euml'  : nuovoVal = 203; break;
				case 'Igrave'  : nuovoVal = 204; break;
				case 'Iacute'  : nuovoVal = 205; break;
				case 'Icirc'  : nuovoVal = 206; break;
				case 'Iuml'  : nuovoVal = 207; break;
				case 'ETH'  : nuovoVal = 208; break;
				case 'Ntilde'  : nuovoVal = 209; break;
				case 'Ograve'  : nuovoVal = 210; break;
				case 'Oacute'  : nuovoVal = 211; break;
				case 'Ocirc'  : nuovoVal = 212; break;
				case 'Otilde'  : nuovoVal = 213; break;
				case 'Ouml'  : nuovoVal = 214; break;
				case 'times'  : nuovoVal = 215; break;
				case 'Oslash'  : nuovoVal = 216; break;
				case 'Ugrave'  : nuovoVal = 217; break;
				case 'Uacute'  : nuovoVal = 218; break;
				case 'Ucirc'  : nuovoVal = 219; break;
				case 'Uuml'  : nuovoVal = 220; break;
				case 'Yacute'  : nuovoVal = 221; break;
				case 'THORN'  : nuovoVal = 222; break;
				case 'szlig'  : nuovoVal = 223; break;
				case 'agrave'  : nuovoVal = 224; break;
				case 'aacute'  : nuovoVal = 225; break;
				case 'acirc'  : nuovoVal = 226; break;
				case 'atilde'  : nuovoVal = 227; break;
				case 'auml'  : nuovoVal = 228; break;
				case 'aring'  : nuovoVal = 229; break;
				case 'aelig'  : nuovoVal = 230; break;
				case 'ccedil'  : nuovoVal = 231; break;
				case 'egrave'  : nuovoVal = 232; break;
				case 'eacute'  : nuovoVal = 233; break;
				case 'ecirc'  : nuovoVal = 234; break;
				case 'euml'  : nuovoVal = 235; break;
				case 'igrave'  : nuovoVal = 236; break;
				case 'iacute'  : nuovoVal = 237; break;
				case 'icirc'  : nuovoVal = 238; break;
				case 'iuml'  : nuovoVal = 239; break;
				case 'eth'  : nuovoVal = 240; break;
				case 'ntilde'  : nuovoVal = 241; break;
				case 'ograve'  : nuovoVal = 242; break;
				case 'oacute'  : nuovoVal = 243; break;
				case 'ocirc'  : nuovoVal = 244; break;
				case 'otilde'  : nuovoVal = 245; break;
				case 'ouml'  : nuovoVal = 246; break;
				case 'divide'  : nuovoVal = 247; break;
				case 'oslash'  : nuovoVal = 248; break;
				case 'ugrave'  : nuovoVal = 249; break;
				case 'uacute'  : nuovoVal = 250; break;
				case 'ucirc'  : nuovoVal = 251; break;
				case 'uuml'  : nuovoVal = 252; break;
				case 'yacute'  : nuovoVal = 253; break;
				case 'thorn'  : nuovoVal = 254; break;
				case 'yuml'  : nuovoVal = 255; break;
				case 'OElig'  : nuovoVal = 338; break;
				case 'oelig'  : nuovoVal = 339; break;
				case 'Scaron'  : nuovoVal = 352; break;
				case 'scaron'  : nuovoVal = 353; break;
				case 'Yuml'  : nuovoVal = 376; break;
				case 'fnof'  : nuovoVal = 402; break;
				case 'circ'  : nuovoVal = 710; break;
				case 'tilde'  : nuovoVal = 732; break;
				case 'Alpha'  : nuovoVal = 913; break;
				case 'Beta'  : nuovoVal = 914; break;
				case 'Gamma'  : nuovoVal = 915; break;
				case 'Delta'  : nuovoVal = 916; break;
				case 'Epsilon'  : nuovoVal = 917; break;
				case 'Zeta'  : nuovoVal = 918; break;
				case 'Eta'  : nuovoVal = 919; break;
				case 'Theta'  : nuovoVal = 920; break;
				case 'Iota'  : nuovoVal = 921; break;
				case 'Kappa'  : nuovoVal = 922; break;
				case 'Lambda'  : nuovoVal = 923; break;
				case 'Mu'  : nuovoVal = 924; break;
				case 'Nu'  : nuovoVal = 925; break;
				case 'Xi'  : nuovoVal = 926; break;
				case 'Omicron'  : nuovoVal = 927; break;
				case 'Pi'  : nuovoVal = 928; break;
				case 'Rho'  : nuovoVal = 929; break;
				case 'Sigma'  : nuovoVal = 931; break;
				case 'Tau'  : nuovoVal = 932; break;
				case 'Upsilon'  : nuovoVal = 933; break;
				case 'Phi'  : nuovoVal = 934; break;
				case 'Chi'  : nuovoVal = 935; break;
				case 'Psi'  : nuovoVal = 936; break;
				case 'Omega'  : nuovoVal = 937; break;
				case 'alpha'  : nuovoVal = 945; break;
				case 'beta'  : nuovoVal = 946; break;
				case 'gamma'  : nuovoVal = 947; break;
				case 'delta'  : nuovoVal = 948; break;
				case 'epsilon'  : nuovoVal = 949; break;
				case 'zeta'  : nuovoVal = 950; break;
				case 'eta'  : nuovoVal = 951; break;
				case 'theta'  : nuovoVal = 952; break;
				case 'iota'  : nuovoVal = 953; break;
				case 'kappa'  : nuovoVal = 954; break;
				case 'lambda'  : nuovoVal = 955; break;
				case 'mu'  : nuovoVal = 956; break;
				case 'nu'  : nuovoVal = 957; break;
				case 'xi'  : nuovoVal = 958; break;
				case 'omicron'  : nuovoVal = 959; break;
				case 'pi'  : nuovoVal = 960; break;
				case 'rho'  : nuovoVal = 961; break;
				case 'sigmaf'  : nuovoVal = 962; break;
				case 'sigma'  : nuovoVal = 963; break;
				case 'tau'  : nuovoVal = 964; break;
				case 'upsilon'  : nuovoVal = 965; break;
				case 'phi'  : nuovoVal = 966; break;
				case 'chi'  : nuovoVal = 967; break;
				case 'psi'  : nuovoVal = 968; break;
				case 'omega'  : nuovoVal = 969; break;								
				case 'thetasym'  : nuovoVal = 977; break;
				case 'upsih'  : nuovoVal = 978; break;
				case 'piv'  : nuovoVal = 982; break;
				case 'ensp'  : nuovoVal = 8194; break;
				case 'emsp'  : nuovoVal = 8195; break;
				case 'thinsp'  : nuovoVal = 8201; break;
				case 'zwnj'  : nuovoVal = 8204; break;
				case 'zwj'  : nuovoVal = 8205; break;
				case 'lrm'  : nuovoVal = 8206; break;
				case 'rlm'  : nuovoVal = 8207; break;
				case 'ndash'  : nuovoVal = 8211; break;
				case 'mdash'  : nuovoVal = 8212; break;
				case 'lsquo'  : nuovoVal = 8216; break;
				case 'rsquo'  : nuovoVal = 8217; break;
				case 'sbquo'  : nuovoVal = 8218; break;
				case 'ldquo'  : nuovoVal = 8220; break;
				case 'rdquo'  : nuovoVal = 8221; break;
				case 'bdquo'  : nuovoVal = 8222; break;
				case 'dagger'  : nuovoVal = 8224; break;
				case 'Dagger'  : nuovoVal = 8225; break;
				case 'bull'  : nuovoVal = 8226; break;
				case 'hellip'  : nuovoVal = 8230; break;
				case 'permil'  : nuovoVal = 8240; break;
				case 'prime'  : nuovoVal = 8242; break;
				case 'Prime'  : nuovoVal = 8243; break;
				case 'lsaquo'  : nuovoVal = 8249; break;
				case 'rsaquo'  : nuovoVal = 8250; break;
				case 'oline'  : nuovoVal = 8254; break;
				case 'frasl'  : nuovoVal = 8260; break;
				case 'euro'  : nuovoVal = 8364; break;
				case 'image'  : nuovoVal = 8465; break;
				case 'weierp'  : nuovoVal = 8472; break;
				case 'real'  : nuovoVal = 8476; break;
				case 'trade'  : nuovoVal = 8482; break;
				case 'alefsym'  : nuovoVal = 8501; break;
				case 'larr'  : nuovoVal = 8592; break;
				case 'uarr'  : nuovoVal = 8593; break;
				case 'rarr'  : nuovoVal = 8594; break;
				case 'darr'  : nuovoVal = 8595; break;
				case 'harr'  : nuovoVal = 8596; break;
				case 'crarr'  : nuovoVal = 8629; break;
				case 'lArr'  : nuovoVal = 8656; break;
				case 'uArr'  : nuovoVal = 8657; break;
				case 'rArr'  : nuovoVal = 8658; break;
				case 'dArr'  : nuovoVal = 8659; break;
				case 'hArr'  : nuovoVal = 8660; break;
				case 'forall'  : nuovoVal = 8704; break;
				case 'part'  : nuovoVal = 8706; break;
				case 'exist'  : nuovoVal = 8707; break;
				case 'empty'  : nuovoVal = 8709; break;
				case 'nabla'  : nuovoVal = 8711; break;
				case 'isin'  : nuovoVal = 8712; break;
				case 'notin'  : nuovoVal = 8713; break;
				case 'ni'  : nuovoVal = 8715; break;
				case 'prod'  : nuovoVal = 8719; break;
				case 'sum'  : nuovoVal = 8721; break;
				case 'minus'  : nuovoVal = 8722; break;
				case 'lowast'  : nuovoVal = 8727; break;
				case 'radic'  : nuovoVal = 8730; break;
				case 'prop'  : nuovoVal = 8733; break;
				case 'infin'  : nuovoVal = 8734; break;
				case 'ang'  : nuovoVal = 8736; break;
				case 'and'  : nuovoVal = 8743; break;
				case 'or'  : nuovoVal = 8744; break;
				case 'cap'  : nuovoVal = 8745; break;
				case 'cup'  : nuovoVal = 8746; break;
				case 'int'  : nuovoVal = 8747; break;
				case 'there4'  : nuovoVal = 8756; break;
				case 'sim'  : nuovoVal = 8764; break;
				case 'cong'  : nuovoVal = 8773; break;
				case 'asymp'  : nuovoVal = 8776; break;
				case 'ne'  : nuovoVal = 8800; break;
				case 'equiv'  : nuovoVal = 8801; break;
				case 'le'  : nuovoVal = 8804; break;
				case 'ge'  : nuovoVal = 8805; break;
				case 'sub'  : nuovoVal = 8834; break;
				case 'sup'  : nuovoVal = 8835; break;
				case 'nsub'  : nuovoVal = 8836; break;
				case 'sube'  : nuovoVal = 8838; break;
				case 'supe'  : nuovoVal = 8839; break;
				case 'oplus'  : nuovoVal = 8853; break;
				case 'otimes'  : nuovoVal = 8855; break;
				case 'perp'  : nuovoVal = 8869; break;
				case 'sdot'  : nuovoVal = 8901; break;
				case 'lceil'  : nuovoVal = 8968; break;
				case 'rceil'  : nuovoVal = 8969; break;
				case 'lfloor'  : nuovoVal = 8970; break;
				case 'rfloor'  : nuovoVal = 8971; break;
				case 'lang'  : nuovoVal = 9001; break;
				case 'rang'  : nuovoVal = 9002; break;
				case 'loz'  : nuovoVal = 9674; break;
				case 'spades'  : nuovoVal = 9824; break;
				case 'clubs'  : nuovoVal = 9827; break;
				case 'hearts'  : nuovoVal = 9829; break;
				case 'diams'  : nuovoVal = 9830; break;
				default :	nuovoVal = -1;
			}
			
		}
		if (nuovoVal > -1){ 
			fReturn += TestoHtml.substr(indice, reMatch.index-indice) + String.fromCharCode(nuovoVal);
			indice = reMatch.lastIndex;
		}
		reMatch = re.exec(TestoHtml);
	}
	fReturn += TestoHtml.substr(indice);
	return fReturn
}


function SerializeValue(Valore){
// Serializza il valore passato.
	var cont1, cont2, cont3, str1, str2, k, y;
	var fReturn;
	
	switch (ValueType(Valore)){
		case 'null' : 
			fReturn = '#NULL';
			break;
		case 'empty' : 
			fReturn = '#EMPTY';
			break;
		case 'undefined' : 
			fReturn = '#NOTHING';
			break;
		case 'Object' : 
			fReturn = '#OBJECT';
			break;
		case 'Array' : 
			fReturn = '';
			str1 = '';
			if (window.SerializeValue__ArrayColl) {
				//Verifico se l'array è stato creato da DeserializeValue, per sapere se è un Array o Dictionary
				for (cont1 in window.SerializeValue__ArrayColl) {
					if (cont1 === Valore) {
						str1 = window.SerializeValue__ArrayColl[cont1];
						break;
					}
				}
				//Attenzione: questa istruzione non funziona, è stata sostituita col codice qui sopra.
				//str1 = window.SerializeValue__ArrayColl[Valore];
			}
			if (!str1) {
				// Controllo se l'array ottenuto si tratta di un Array o di una Dictionary
				// in caso si tratti d un array si procede normalmente..
				// in caso si trattasse di una dictionary provvederemo a serializzare sia chiave che valore..
				cont2 = 0;
				str1 = 'Array';
				for (cont1 in Valore) {
					if (ValueType(Valore[cont1]) != 'Function') {
						if (cont1.toString() != cont2.toString()) {
							str1 = 'Dictionary';
							//alert('SerializeValue :' +  '\n   cont1 = ' + cont1 + '\n   cont2 = ' + cont2 + '\n   typeof= ' + ValueType(Valore[cont1]));
							break;
						}
						cont2 += 1;
					}
				}
			}
			switch (str1) {
				case 'Array':		// Stiamo serializzando un Array
					fReturn = '{';
					for (cont1=0; cont1<Valore.length; cont1++) {
						if (fReturn != '{') fReturn += ',';
						str1 = SerializeValue(Valore[cont1]);
						k = str1.length;
						fReturn += k + ':' + str1; 
					}
					fReturn = fReturn + '}';
					break;
				case 'Dictionary':	// Stiamo Serializzando un Dictionary
					fReturn = '[';
					for (cont1 in Valore) {
						if (typeof(Valore[cont1]) != 'function') {
							if (fReturn != '[') fReturn += ',';
							str1 = SerializeValue(cont1);
							str2 = SerializeValue(Valore[cont1]);
							y = str1.length;
							k = str2.length;
							fReturn += y + ':' + str1 + ',' + k + ':' + str2;
						}
					}
					fReturn = fReturn + ']';
					break;
			}
			break;
		case 'number':
			fReturn = 'F' + Valore.toString();
			break;
		case 'Date':
			fReturn = 'D' + Valore.getFullYear() + LFill((Valore.getMonth()+1).toString(), '0',2) + LFill(Valore.getDate().toString(), '0',2) + LFill(Valore.getHours().toString(),'0', 2)+ LFill(Valore.getMinutes().toString(),'0', 2) + LFill(Valore.getSeconds().toString(),'0', 2);
			break;
		case 'boolean':
			if ( IsTrue(Valore) == true) {
				fReturn = 'B' + '1'; 
			} else {
				fReturn = 'B' + '0';
			}
			break;
		case 'string':
			fReturn = 'S' + HTMLEncode(Valore);
			break;
		default:
			fReturn = '#tipo [' + ValueType(Valore) + '] non supportato.';
	}
	return fReturn;
}
function DeserializeValue(ValoreSerializzato) {
	//deserializza il valore passato
	var cont1, cont2, cont3, str1, str2, lunghezza, tipo, valore, fReturn;
	tipo = ValoreSerializzato.charAt(0);
	valore = ValoreSerializzato.substr(1);
	switch (tipo) {
		case '#':
			switch (valore) {
				case 'NULL':
					fReturn = null;
					break;
				case 'NOTHING':
					fReturn = void(0);
					break;
				case 'OBJECT':
					fReturn = null;
					break;
				case 'EMPTY':
					fReturn = '';
					break;
				default:
					fReturn = null;
					break;
			}
			break;
		case 'D':
			fReturn = new Date();
			fReturn.setFullYear(toNumber(valore.substr(0,4)));
			fReturn.setMonth(toNumber(valore.substr(4,2))-1);
			fReturn.setDate(toNumber(valore.substr(6,2)));
			fReturn.setHours(toNumber(valore.substr(8,2)));
			fReturn.setMinutes(toNumber(valore.substr(10,2)));
			fReturn.setSeconds(toNumber(valore.substr(12,2)));
			break;
		case 'S':
			fReturn = HTMLDecode(valore);
			break;
		case 'F':
		case 'I':
			fReturn = toNumber(valore,0, false);
			break;
		case 'B':
			fReturn = IsTrue(valore);
			break;
		case '{':
			fReturn = new Array();
			if (!window.SerializeValue__ArrayColl) window.SerializeValue__ArrayColl = new Array();
			window.SerializeValue__ArrayColl[fReturn] = 'Array';
			cont1 = 0;
			cont3 = 0;
			do {
				cont1 += 1;
				cont2 = cont1 + 1 + ValoreSerializzato.substr(cont1 + 1).search(/:/);
				lunghezza = toNumber(ValoreSerializzato.substr(cont1, cont2 - cont1));
				str1 = ValoreSerializzato.substr(cont2 + 1, lunghezza);
				fReturn[cont3] = DeserializeValue(str1);
				cont1 = cont2 + lunghezza + 1;
				cont3 += 1;
			} while (ValoreSerializzato.charAt(cont1) == ',');
			break;
		case '[':
			fReturn = new Array();
			if (!window.SerializeValue__ArrayColl) window.SerializeValue__ArrayColl = new Array();
			window.SerializeValue__ArrayColl[fReturn] = 'Dictionary';
			if (valore != ']') {
				cont1 = 0;
				do {
					cont1 += 1;
					cont2 = cont1 + 1 + ValoreSerializzato.substr(cont1 + 1).search(/:/);
					lunghezza = toNumber(ValoreSerializzato.substr(cont1, cont2 - cont1));
					str1 = ValoreSerializzato.substr(cont2 + 1, lunghezza);
					cont1 = cont2 + lunghezza + 1;
					cont1 += 1;
					cont2 = cont1 + 1 + ValoreSerializzato.substr(cont1 + 1).search(/:/);
					lunghezza = toNumber(ValoreSerializzato.substr(cont1, cont2 - cont1));
					str2 = ValoreSerializzato.substr(cont2 + 1, lunghezza);
					fReturn[DeserializeValue(str1)] = DeserializeValue(str2);
					cont1 = cont2 + lunghezza + 1;
				} while (ValoreSerializzato.charAt(cont1) == ',');
			}
			break;
		default: fReturn = null;
	}
	return fReturn;
}	

//####   GetHtmlControlValue   -   SetHtmlControlValue   ####
//####   Info-Data - Flavio Spezi - ver. 1.0	(17/11/2005)
//Leggono e scrivono il valore degli oggetti INPUT, TEXTAREA e SELECT. Parametri:
//		ControlObject:	è il riferimento all'oggetto oppure l'ID dell'oggetto. Se si tratta di INPUT type=radio,
//						il parametro può essere il riferimento ad uno degli oggetti INPUT type=radio del gruppo oppure il nome del
//						gruppo seguito dal nome del frame (es. FrmPrinc.OptSesso_M, 'OptSesso_F', 'FrmPrinc.OptSesso').
function GetHtmlControlValue(ControlObject, Checkbox_TrueFalse) {
	var obj, tipoCtrl, objForm;
	var tipoRadio_Nome, listaCtrl;
	var cont1;
	var fReturn = null;
	obj = ControlObject;
	if (typeof(obj) == 'string') {
		if (obj.indexOf('.') > -1) obj = obj.substr(obj.indexOf('.')+1);
		obj = findObj(obj);
		if (typeof(obj) != 'object' || !obj.tagName) obj = ControlObject;
	}
	switch (typeof(obj)) {
		case 'object':
			tipoCtrl = obj.tagName;
			if (tipoCtrl == 'INPUT') tipoCtrl += ' ' + obj.type.toLowerCase();
			break;
		case 'string':
			tipoCtrl = 'INPUT radio';
			break;
	}
	if (tipoCtrl != 'INPUT radio' && typeof(obj) != 'object') tipoCtrl = 'non valido';
	switch (tipoCtrl) {
		case 'INPUT checkbox':
			fReturn = ((obj.checked) ? obj.value : null);
			break;
		case 'INPUT hidden':
			fReturn = obj.value;
			break;
		case 'INPUT password':
			fReturn = obj.value;
			break;
		case 'INPUT radio':
			if (typeof(obj) == 'string') {
				objForm = findObj(obj.substr(0, obj.indexOf('.')));
				tipoRadio_Nome = obj.substr(obj.indexOf('.')+1).toLowerCase();
			} else {
				objForm = obj.form;
				tipoRadio_Nome = obj.name.toLowerCase();
			}
			listaCtrl = objForm.tags('INPUT');
			if (listaCtrl) {
				for (cont1 = 0; cont1 < listaCtrl.length; cont1++) {
					if (listaCtrl[cont1].type.toLowerCase() == 'radio'
							&& listaCtrl[cont1].name.toLowerCase() == tipoRadio_Nome
							&& listaCtrl[cont1].checked) {
						fReturn = listaCtrl[cont1].value;
						break;
					}
				}
			}
			break;
		case 'INPUT text':
			fReturn = obj.value;
			break;
		case 'SELECT':
			fReturn = obj.value;
			break;
		case 'TEXTAREA':
			fReturn = obj.value;
			break;
	}
	return fReturn;
}
//Stesso principio della procedura [GetHtmlControlValue]. Restituisce TRUE se l'operazione va a buon fine.
function SetHtmlControlValue(ControlObject, NewValue) {
	var obj, tipoCtrl, objForm;
	var tipoRadio_Nome, listaCtrl;
	var cont1, cont2;
	var fReturn = false;
	obj = ControlObject;
	if (typeof(obj) == 'string') {
		if (obj.indexOf('.') > -1) obj = obj.substr(obj.indexOf('.')+1);
		obj = findObj(obj);
		if (typeof(obj) != 'object' || !obj.tagName) obj = ControlObject;
	}
	switch (typeof(obj)) {
		case 'object':
			tipoCtrl = obj.tagName;
			if (tipoCtrl == 'INPUT') tipoCtrl += ' ' + obj.type.toLowerCase();
			break;
		case 'string':
			tipoCtrl = 'INPUT radio';
			break;
	}
	if (tipoCtrl != 'INPUT radio' && typeof(obj) != 'object') tipoCtrl = 'non valido';
	switch (tipoCtrl) {
		case 'INPUT checkbox':
			obj.checked = ((NewValue) ? true : false);
			fReturn = true;
			break;
		case 'INPUT hidden':
			obj.value = NewValue;
			fReturn = true;
			break;
		case 'INPUT password':
			obj.value = NewValue;
			fReturn = true;
			break;
		case 'INPUT radio':
			switch (typeof(obj)) {
				case 'string':
					objForm = findObj(obj.substr(0, obj.indexOf('.')));
					tipoRadio_Nome = obj.substr(obj.indexOf('.')+1).toLowerCase();
					break;
				case 'object':
					objForm = obj.form;
					tipoRadio_Nome = obj.name.toLowerCase();
					break;
			}
			listaCtrl = objForm.tags('INPUT');
			if (listaCtrl) {
				for (cont1 = 0; cont1 < listaCtrl.length; cont1++) {
					if (listaCtrl[cont1].type.toLowerCase() == 'radio'
							&& listaCtrl[cont1].name.toLowerCase() == tipoRadio_Nome
							&& listaCtrl[cont1].value == NewValue) {
						listaCtrl[cont1].checked = true;
						fReturn = true;
						break;
					}
				}
			}
			break;
		case 'INPUT text':
			obj.value = NewValue;
			fReturn = true;
			break;
		case 'SELECT':
			if (ValueType(NewValue) == 'Array') {
				obj.value = NewValue;
				if (obj.value == NewValue) {
					fReturn = true;
				} else {
					fReturn = 0;
					for (cont1=0; cont1<obj.options.length; cont1++) {
						for (cont2=0; cont2<NewValue.length; cont2++) {
							if (obj.options(cont1).value == NewValue[cont2]) {
								obj.options(cont1).selected = true;
								fReturn ++;
							}
						}
					}
					fReturn = (fReturn == NewValue.length);
				}
			} else {
				obj.value = NewValue;
				if (obj.value == NewValue) {
					fReturn = true;
				} else {
					fReturn = false;
					for (cont1=0; cont1<obj.options.length; cont1++) {
						if (obj.options(cont1).text == NewValue[cont2]) {
							obj.options(cont1).selected = true;
							fReturn = true;
							break;
						}
					}
				}
			}
			break;
		case 'TEXTAREA':
			obj.value = NewValue;
			fReturn = true;
			break;
		default:
			alert('Funzioni.js\n  function SetHtmlControlValue()\n    TipoCtrl non gestito: ' + tipoCtrl + '\n    Parametro ControlObject: ' + ControlObject);
	}
	return fReturn;
}


// ####  Funzioni di STANDARDIZZAZIONE BROWSERS  ##########

// Associa una funzione all'evento di un oggetto
function addEvent(obj, evType, fn) {
	if (obj.addEventListener) {
		obj.addEventListener(evType, fn, false);
		return true;
	} else if (obj.attachEvent) {
		var r = obj.attachEvent('on' + evType, fn);
		return r;
	} else {
		return false;
	}
}
function fireEvent(obj, evType) {
	var esisteEvento;
	if (obj.fireEvent) {
		obj.fireEvent('on' + evType);
	} else {
		eval('esisteEvento = obj.on' + evType + ';');
		if (esisteEvento) eval('esisteEvento = obj.on' + evType + '();');
	}
}
function findObj(idObject, document_Optional) {
	var p, i, x;
	if (!document_Optional) document_Optional = document;
	if ((p = idObject.toString().indexOf('?')) > 0 && parent.frames.length) {
		document_Optional = parent.frames[idObject.substring(p + 1)].document;
		idObject = idObject.substring(0, p);
	}
	if (!(x = document_Optional[idObject]) && document_Optional.all) x = document_Optional.all[idObject];
	if (!x && document_Optional.forms) for (i=0; i < document_Optional.forms.length; i++) x = document_Optional.forms[i][idObject];
	if (!x && document_Optional.layers) for (i=0; i < document_Optional.layers.length; i++) x = findObj(idObject, document_Optional.layers[i].document);
	if (!x && document_Optional.getElementById) x = document_Optional.getElementById(idObject);
	return x;
}


// ####  [Traduci_Varchar_Read] ,  [Traduci_Varchar_Write] ,  [Traduci_Text_Read] ,  [Traduci_Text_Write]  ####
// ####  Info-Data Flavio Spezi (ver. 2.0 - 04/11/2005)  ###
// Procedure per la lettura e la scrittura in lingua.
// Parametri:
// 	MultilanguageSource   :	Può essere il [testo intero] in tutte le lingue oppure l'oggetto da cui prendere il valore:
// 							se il parametro è di tipo [Object], verrà prelevato il valore dell'attributo Value;
// 							se il parametro è una stringa essa verrà usata come [testo intero];
// 							per le funzioni Xxx_Write, nel caso in cui il parametro passato è un [Object], il risultato
// 							dell'elaborazione verrà salvato all'interno dell'oggetto; e in ogni caso verrà restituito come
// 							stringa dalla funzione.
// 	LanguageCode		  : il codice della lingua (es: IT, EN).
// 	LanguageIndex		  : l'indice di posizione della lingua (a partire da zero).
// 	LanguageSource		  : per le funzioni Xxx_Write, settare questo parametro col valore del testo nella lingua indicata;
// 							se il parametro è di tipo [Object], verrà prelevato il valore dell'attributo Value;
// 							se il parametro è una stringa essa verrà usata come [testo della lingua].
// 	CharsPerLanguage	  : caratteri messi a disposizione per ogni lingua. A differenza del programma analogo lato server,
//							qui non posso consentire l'uso del valore -1 (in automatico leggendo lungezza campo nel db) per
//							ovvi motivi.
function Traduci_Varchar_Read(MultilanguageSource, CharsPerLanguage, LanguageIndex) {
	var numCaratteri = toNumber(CharsPerLanguage, null, true);
	var indiceLingua = toNumber(LanguageIndex, null, true);
	var sorgenteIsObj = typeof(MultilanguageSource) == 'object';
	var sorgenteTesto = ((sorgenteIsObj) ? MultilanguageSource.value : MultilanguageSource);
	var fReturn = RTrim(sorgenteTesto.substr(numCaratteri * indiceLingua, numCaratteri));
	return fReturn;
}
function Traduci_Varchar_Write(MultilanguageSource, CharsPerLanguage, LanguageIndex, LanguageSource) {
	var numCaratteri = toNumber(CharsPerLanguage, null, true);
	var indiceLingua = toNumber(LanguageIndex, null, true);
	var sorgenteIsObj = typeof(MultilanguageSource) == 'object';
	var sorgenteTesto = ((sorgenteIsObj) ? MultilanguageSource.value : MultilanguageSource);
	var sorgenteLanIsObj = typeof(LanguageSource) == 'object';
	var sorgenteLanTesto = ((sorgenteLanIsObj) ? LanguageSource.value : LanguageSource);
	var fReturn;
	
	while (sorgenteTesto.length < numCaratteri * indiceLingua) sorgenteTesto += ' ';
	while (sorgenteLanTesto.length < numCaratteri) sorgenteLanTesto += ' ';
	fReturn = sorgenteTesto.substr(0, numCaratteri * indiceLingua) +
			sorgenteLanTesto + 
			sorgenteTesto.substr(numCaratteri * (indiceLingua + 1));
	if (sorgenteIsObj) MultilanguageSource.value = RTrim(fReturn);
	return fReturn;
}
function Traduci_Text_Read(MultilanguageSource, LanguageCode) {
	//#	Costanti utili che sono dichiarante in FUNZIONI.ASP : #
	//	Traduci_ChrLingua, Traduci_ChrFormatoTesto, Traduci_Lingue_DefaultIndex, Traduci_Lingue_DefaultCode, Traduci_FormatoTestoDefault
	var sorgenteIsObj = typeof(MultilanguageSource) == 'object';
	var sorgenteTesto = ((sorgenteIsObj) ? MultilanguageSource.value : MultilanguageSource);
	var posizIni, posizFine;
	var formatoTesto;
	var fReturn;
	//Leggo e rimuovo la definizione del FormatoTesto dalla stringa.
	formatoTesto = Traduci_GetFormatoTesto(sorgenteTesto);
	if (!formatoTesto) {
		formatoTesto = Traduci_FormatoTestoDefault;
	} else {
		sorgenteTesto = Traduci_RemoveFormatoTesto(sorgenteTesto);
	}
	
	//Se NON trovo nemmeno un [Traduci_ChrLingua], significa che il testo non ha alcuna formattazione di lingua,
	//quindi imposterò tutto il testo alla lingua default [Traduci_Lingue_DefaultCode].                
	if (sorgenteTesto.substr(0, Traduci_ChrLingua.length) != Traduci_ChrLingua) sorgenteTesto = Traduci_ChrLingua + Traduci_Lingue_DefaultCode + sorgenteTesto;
	
    posizIni = sorgenteTesto.indexOf(Traduci_ChrLingua + LanguageCode);
    if (posizIni == -1) {
		fReturn = '';
	} else {
		posizIni += Traduci_ChrLingua.length + LanguageCode.length;
		posizFine = sorgenteTesto.indexOf(Traduci_ChrLingua, posizIni);
		if (posizFine == -1) posizFine = sorgenteTesto.length;
		fReturn = sorgenteTesto.substr(posizIni, posizFine - posizIni);
	}
	return fReturn;
}
function Traduci_Text_Write(MultilanguageSource, LanguageCode, LanguageSource) {
	//#	Costanti utili che sono dichiarante in FUNZIONI.ASP : #
	//	Traduci_ChrLingua, Traduci_ChrFormatoTesto, Traduci_Lingue_DefaultIndex, Traduci_Lingue_DefaultCode, Traduci_FormatoTestoDefault
	var sorgenteIsObj = typeof(MultilanguageSource) == 'object';
	var sorgenteTesto = ((sorgenteIsObj) ? MultilanguageSource.value : MultilanguageSource);
	var sorgenteLanIsObj = typeof(LanguageSource) == 'object';
	var sorgenteLanTesto = ((sorgenteLanIsObj) ? LanguageSource.value : LanguageSource);
	var posizIni, posizFine;
	var formatoTesto;
	var fReturn;
	//Leggo e rimuovo la definizione del FormatoTesto dalla stringa.
	formatoTesto = Traduci_GetFormatoTesto(sorgenteTesto);
	if (!formatoTesto) {
		formatoTesto = Traduci_FormatoTestoDefault;
	} else {
		sorgenteTesto = Traduci_RemoveFormatoTesto(sorgenteTesto);
	}
	
	//Se NON trovo nemmeno un [Traduci_ChrLingua], significa che il testo non ha alcuna formattazione di lingua,
	//quindi imposterò tutto il testo alla lingua default [Traduci_Lingue_DefaultCode].                
	if (sorgenteTesto.substr(0, Traduci_ChrLingua.length) != Traduci_ChrLingua) sorgenteTesto = Traduci_ChrLingua + Traduci_Lingue_DefaultCode + sorgenteTesto;
	
	posizIni = sorgenteTesto.indexOf(Traduci_ChrLingua + LanguageCode);
	if (posizIni == -1) {
		fReturn = sorgenteTesto + Traduci_ChrLingua + LanguageCode + sorgenteLanTesto;
	} else {
		posizIni += Traduci_ChrLingua.length + LanguageCode.length;
		posizFine = sorgenteTesto.indexOf(Traduci_ChrLingua, posizIni);
		if (posizFine == -1) posizFine = sorgenteTesto.length;
		fReturn = sorgenteTesto.substr(0, posizIni) +
				sorgenteLanTesto +
				sorgenteTesto.substr(posizFine);
	}
	fReturn = Traduci_SetFormatoTesto(fReturn, formatoTesto);
	if (sorgenteIsObj) MultilanguageSource.value = fReturn;
	return fReturn;
}
function Traduci_GetFormatoTesto(textString) {
	//  Restituisce il FormatoTesto memorizzato nella stringa di testo passata come parametro.
	//  Se la stringa di testo non possiede un FormatoTesto definito, la funzione restituisce NULL.
	var fReturn = null;
    if (textString.substr(textString.length-2, 1) == Traduci_ChrFormatoTesto) {
		fReturn = textString.substr(textString.length-1, 1);
    }
    return fReturn;
}
function Traduci_SetFormatoTesto(textString, newTextFormat) {
	//  Restituisce il Testo con il FormatoTesto modificato.
	//  Se la stringa di testo non possiede un FormatoTesto definito, questo verrà aggiunto.
	var fReturn;
	fReturn = Traduci_RemoveFormatoTesto(textString) + Traduci_ChrFormatoTesto + newTextFormat.toString().substr(0, 1);
    return fReturn;
}
function Traduci_RemoveFormatoTesto(textString, newTextFormat) {
	//  Restituisce il Testo senza il FormatoTesto.
	//  Se la stringa di testo non possiede un FormatoTesto definito, la funzione restituisce il Testo intero del parametro.
	var fReturn;
    if (textString.substr(textString.length-2, 1) == Traduci_ChrFormatoTesto) {
		fReturn = textString.substr(0, textString.length - 2);
    } else {
		fReturn = textString;
    }
    return fReturn;
}



//######################################################################################
//####	Funzioni per la gestione dei DOMINI del sito (come nel file Funzioni.asp)	####
//######################################################################################
var Domini_Nomi_ArrayCacheValue;
function Domini_Nomi_ArrayCacheValue_Fill() {
	if (!Domini_Nomi_ArrayCacheValue) Domini_Nomi_ArrayCacheValue = Domini_Nomi_List.split(';');
}
function Domini_Nomi_Count() {
	Domini_Nomi_ArrayCacheValue_Fill();
	return Domini_Nomi_ArrayCacheValue.length;
}
function Domini_Nomi_Index(NomeDominio) {
	var str1, cont1;
	Domini_Nomi_ArrayCacheValue_Fill();
	str1 = NomeDominio.toString().toLowerCase();
	for (cont1=0; cont1<Domini_Nomi_ArrayCacheValue.length; cont1++) {
		if (str1 == Domini_Nomi_ArrayCacheValue[cont1]) return cont1;
	}
    return -1;
}
function Domini_Nomi_Name(IndiceDominio) {
	Domini_Nomi_ArrayCacheValue_Fill();
	return Domini_Nomi_ArrayCacheValue[IndiceDominio];
}
function Domini_Nomi_CurrentIndex() {
	return Domini_Nomi_Index(Domini_Nomi_CurrentName);
}
function Domini_Nomi_CurrentName() {
	var fReturn = window.location.hostname;
	if (window.location.port != DefaultProtocolIpPort(window.location.protocol)) fReturn += ':' + window.location.port;
	return fReturn;
}
function DefaultProtocolIpPort(Protocol) {
	switch (Protocol.toLowerCase()) {
		case 'http':		return 80;
		case 'https':		return 443;
		case 'ftp':			return 21;
		case 'smtp':		return 25;
		case 'pop3':		return 110;
		case 'imap':		return 143;
		case 'nntp':		return 119;
		case 'snmp':		return 161;
		case 'irc':			return 194;
		case 'sqlserver':	return 1433;
		case 'mysql':		return 3306;
		case 'pptp':		return 1723;			//Point to Point Tunneling Protocol
		case 'telnet':		return 23;
		case 'rdp':			return 3389;			//Remote Desktop Protocol
		case 'vnc':			return 5900;
		default:			return -1;
	}
}


//#################################
//####  Funzioni di HTML PLUS  ####
//#################################


//Procedure per aggiungere funzionalità ad oggetti Html

function HtmlPlus_SlideShow(IdObject, BackGroundColor, ObjContainer, ImagesPath, ZoomType, PermanenceTime, TransactionTime, TransactionStyle, TransactionType, Fps){
	// Questa funzione serve per meccanizzare gli SlideSHow in modo da non dover ogni volta ricominciare daccapo.
	// gestisce 3 tipi di transazioni : trasparenza, transazione verticale, trasazione orizzontale. Sarà possibile aggiungerne altre.
	// ci sono però dei bug da risolvere che riguardano l'utilizzo non standard dei browser riguardo ad alcuni attributi di stile
	//	degli oggetti html come left, top, zIndex che sono da verificare bene.
	this.id = IdObject;								// Id dell'oggetto HtmlPlus
	this.objectType = 'HtmlPlus_SlideShow';			// Tipo di oggetto
	this.objectContainer = ObjContainer;			// Oggetto che contiene le immagini da visualizzare in slideshow
	this.imagesCollection = null;					// Array di path di immagini da visualizzare
	this.zoomType = ZoomType;						// Può essere 'Fixed', 'Min' 'Max'
	this.permanenceTime = PermanenceTime;			// Durata della visualizzazione dell'immagine [in secondi]
	this.transactionTime = TransactionTime;			// Durata dello scambio [in secondi]
	this.transactionStyle = TransactionStyle;		// Style di transazione['opacity', 'left-right', 'right-left', 'top-bottom', 'bottom-top']
	this.transactionType = TransactionType;			// Tipo di transazione['sin', 'cos', 'square', 'triangle']
	this.fps = Fps;									// Fotogrammi per secondo della transazione.
	this.repeat = true;								// se [False] alla fine del ciclo si ferma. se [True] ricomincia da capo
	this.startMethod = 'image';						// Puo essere ['image', 'transaction', '<url-img>']
	this.transactionMaker = null;
	this.backgroundColor = BackGroundColor;
	
	if (!window.HtmlPlus_SlideShowColl) window.HtmlPlus_SlideShowColl = new Array();
	window.HtmlPlus_SlideShowColl[this.id] = this;
	
	this._initialize = function(){
		var cont1;
		
		switch (this.zoomType.toLowerCase()){
			case 'fixed':
			case 'min':
			case 'max':
				this.zoomType = this.zoomType.toLowerCase();
				break;
			default:
				this.zoomType = 'fixed';
				break;
		}
		
		if(this.permanenceTime < this.transactionTime) this.permanenceTime = this.transactionTime;
		
		switch (this.transactionStyle.toLowerCase()){
			case 'opacity':
			case 'right-left':
			case 'left-right':
			case 'top-bottom':
			case 'bottom-top':
			case 'test':
				this.transactionStyle = this.transactionStyle.toLowerCase();
				break;
			default:
				this.transactionStyle = 'opacity';
				break;
		}
		if (ValueType(ImagesPath) == 'Array') {
			switch (ValueType(ImagesPath[0])) {
				case 'Object':
					// Gli elementi [Oggetto] devono avere gli attributi "alt", "src" e "onClick".
					this.imagesCollection = ImagesPath;
					break;
				case 'string':
					this.imagesCollection = new Array();
					for (cont1=0; cont1 < ImagesPath.length; cont1++) {
						this.imagesCollection[cont1] = new Object();
						this.imagesCollection[cont1].src = ImagesPath[cont1];
						this.imagesCollection[cont1].alt = '';
						this.imagesCollection[cont1].onClick = '';
					}
					break;
			}
		}
		if (ValueType(ImagesPath) != 'Array') this.imagesCollection = new Array();
		
		if (!this.fps) this.fps = GetBrowserInfo('RecommendedFps');
		
		if (typeof(this.objectContainer)=='string'){
			this.objectContainer = findObj(this.objectContainer);
			this.objectContainer.style.overflow = 'hidden';
		}
		
		this.objectContainer_width = this.objectContainer.style.width;
		this.objectContainer_height = this.objectContainer.style.height;
		
		this._div1 = null;
		this._div2 = null;
		this._img1 = null;
		this._img2 = null;
		this._imgLoad = null;
		this._currentPosition = 0;
		this._status = 'stop';
		this._tmr = null;
		this._buildObjects();
	}
	
	this._runStep1 = function(){
		// Carica l'immagine successiva e attende il tempo di permanenza dell'immagine ed innesca poi la transazione
		if (this.GetNextPosition() == null){
			this._status = 'stop';
		} else {
			
			if (this._tmr) clearTimeout(this._tmr);
			this._tmr = setTimeout('HtmlPlus_SlideShowColl[\'' + CStrJS(this.id) +  '\']._runStep2();',  (this.permanenceTime - this.transactionTime) * 1000);
			this._preloadImg(this.imagesCollection[this.GetNextPosition()].src);
		}
	}
	
	this._runStep2 = function(){
		//imposta l'immagine caricata come immagine che dovrà effettuare la transazione e fa partire il CLipMaker
		var str1;
		str1 = 'var obj1 = HtmlPlus_SlideShowColl[\'' + CStrJS(this.id) +  '\'];';
		str1 += 'obj1._img2.src = obj1._imgLoad.src;';
		str1 += 'obj1.transactionMaker.Play();';
		str1 += 'obj1.OnTransactionBegin(obj1, obj1._currentPosition, obj1.GetNextPosition());';
		str1 += 'obj1._img1.alt=\'\';';
		str1 += 'obj1._img1.onClick=\'\';';
		this._loadImg(this.imagesCollection[this.GetNextPosition()].src, str1);
	
	}
	
	this.GetPreviousPosition = function(){
		if (this.imagesCollection.length <= 1) {
			return null;
		} else if ((this._currentPosition == 0) && (!this.repeat)) {
			return null;
		} else if ((this._currentPosition == 0) && (this.repeat)) {
			return this.imagesCollection.length - 1;
		} else {
			return this._currentPosition - 1;
		}
	}
	
	this.GetNextPosition = function(){
		if (this.imagesCollection.length <= 1) {
			return null;
		} else if ((this._currentPosition == this.imagesCollection.length - 1) && (!this.repeat)) {
			return null;
		} else if ((this._currentPosition == this.imagesCollection.length - 1) && (this.repeat)) {
			return 0;
		} else {
			return this._currentPosition + 1;
		}
	}
	
	this._preloadImg = function(src) {
		if (this._imgLoad.src != src) {
			this._imgLoad_isLoaded = false; 
			this._imgLoad.src = src;
			this.OnPreloadBegin(this, src);
		}
	}
	
	this._loadImg = function(src, strFunction){
		var lanciaTimer = true;
		if (this._imgLoad.src == src){
			if (this._imgLoad_isLoaded) {
				eval(strFunction);
				lanciaTimer = false;
			}
		} else {
			this._preloadImg(src);
		}
		if (lanciaTimer) {
			if (this._tmr) window.clearTimeout(this._tmr);
			this._tmr = setTimeout('HtmlPlus_SlideShowColl[\'' + CStrJS(this.id) +  '\']._loadImg(\'' + CStrJS(src) + '\', \'' + CStrJS(strFunction) + '\');', 100);
		}
	}
	
	this.Play = function(){
		var str1;
		switch (this._status){
			case 'play':
				break;
			case 'pause':
				this._runStep1();
				this._changeStatus('play');
				break;	
			case 'stop':
				this._changeStatus('play');
				switch (this.startMethod){
					case 'image':
						this._currentPosition = 0;
						str1 = 'var obj1 = HtmlPlus_SlideShowColl[\'' + CStrJS(this.id) +  '\'];';
						str1 += 'obj1._img1.src = obj1._imgLoad.src;';
						str1 += 'obj1._img1.alt = \'' + CStrJS(this.imagesCollection[0].alt) + '\';';
						str1 += 'obj1._img1.onClick = \'' + CStrJS(this.imagesCollection[0].onClick) + '\';';
						str1 += 'obj1._imgRedim(obj1._img1);';
						str1 += 'obj1._runStep1();';
						str1 += 'obj1._div1.style.visibility=\'visible\';';
						this._loadImg(this.imagesCollection[0].src, str1);
						break;
					case 'transaction': 
						this._currentPosition = -1;
						this._runStep2();
						break;
					default:
						this._currentPosition = -1;
						str1 = 'var obj1 = HtmlPlus_SlideShowColl[\'' + CStrJS(this.id) +  '\'];';
						str1 += 'obj1._img1.src = this._imgLoad.src;';
						str1 += 'obj1._imgRedim(this._img1);';
						str1 += 'obj1._runStep2();';
						this._loadImg(this.startMethod, str1);
						break;
				}
				break;
		}
	}
	
	this.Pause = function(){
		switch (this._status){
			case 'play':
				if (this._tmr) window.clearTimeout(this._tmr);
				this._changeStatus('pause');
				break;
			case 'pause':
				break;
			case 'stop':
				break;
		}
	}
	
	this.Stop = function(){
		switch (this._status){
			case 'play':
				if (this._tmr) window.clearTimeout(this._tmr);
				this._changeStatus('stop');
				break;
			case 'pause':
				if (this._tmr) window.clearTimeout(this._tmr);
				this._changeStatus('pause');
				break;	
			case 'stop':
				break;
		}
	}
	
	this.GetCurrentPosition = function(){
		return this._currentPosition;
	}
	
	this.SetCurrentPosition = function(value){
		switch(this._status){
			case 'pause':
				this.Pause();
				break;
			case 'play':
				this.Pause();
				this._currentPosition = value;
				break;
			case 'stop':
				break;
		}
		return this._currentPosition;
	}
	
	this.Status = function(){
		return this._status;
	}
	
	this._buildObjects = function(){
		if (this.objectContainer.innerHTML == '' ){
			
			// Creo gli oggetti per 
			this._div1 = document.createElement('div');
			this._div2Base = document.createElement('div');
			this._div2 = document.createElement('div');
			this._img1 = document.createElement('img');
			this._img2 = document.createElement('img');
			this._div1.appendChild(this._img1);
			this._div2.appendChild(this._img2);
			this._div2Base.appendChild(this._div2);
			this.objectContainer.appendChild(this._div1);
			this.objectContainer.appendChild(this._div2Base);
			
			// Creo ed inizializzo l'immagine che mi serve per ridimensionare le immagini da mostrare
			this._imgLoad = document.createElement('img');
			this._imgLoad._HtmlPlus_SlideShowObj = this;
			this._imgLoad.style.visibility = 'hidden';
			addEvent(this._imgLoad, 'load', this._imgLoad_onLoad);
			
			if (false) {
				this.objectContainer.appendChild(this._imgLoad);
			} else {
				this._div3 = document.createElement('div');
				this.objectContainer.appendChild(this._div3);
				this._div3.appendChild(this._imgLoad);
			}
			
			// Inizializzo i div assegnandogli le giuste proprieta
			this._div1.style.position = 'relative';
			this._div1.style.width = this.objectContainer_width;
			this._div1.style.height = this.objectContainer_height;
			this._div1.style.overflow = 'hidden';
			this._div1.style.visibility = 'hidden';
			this._div1.style.zIndex = 10;
			this._div1.style.backgroundColor = this.backgroundColor;
			
			this._div2.style.position = 'relative';
			this._div2.style.width = this.objectContainer_width;
			this._div2.style.height = this.objectContainer_height;
			this._div2.style.overflow = 'hidden';
			this._div2.style.visibility = 'visible';
			this._div2.style.zIndex = 30;
			this._div2.style.backgroundColor = this.backgroundColor;
			
			this._div2Base.style.position = 'relative';
			this._div2Base.style.width = this.objectContainer_width;
			this._div2Base.style.height = this.objectContainer_height;
			this._div2Base.style.overflow = 'hidden';
			this._div2Base.style.left = '0px';
			this._div2Base.style.top = - toNumber(this.objectContainer_height) + 'px';
			this._div2Base.style.display = 'none';
			this._div2Base.style.zIndex = 20;
			this._div2Base.style.backgroundColor = 'transparent';
			
			this._img1.style.position = 'relative';
			this._img2.style.position = 'relative';
			this._img1.style.alt = '';
			this._img2.style.alt = '';
			
			if (this.zoomType == 'fixed'){
				this._img1.style.width = this.objectContainer_width;
				this._img1.style.height = this.objectContainer_height;
				this._img2.style.width = this.objectContainer_width;
				this._img2.style.height = this.objectContainer_height;
				this._img1.style.left = '0px';
				this._img1.style.top = '0px';
				this._img2.style.left = '0px';
				this._img2.style.top = '0px';
			}
			
			this.transactionMaker = new HtmlPlus_ClipMaker(CStrJS(this.id) + '_transaction', this.transactionTime, this.fps);
			switch (this.transactionStyle) {
				case 'opacity':
					this.transactionMaker.AppendMotion(this._div2, 'opacity', '', 0, 100, 0, 100);
					this.transactionMaker.AppendMotion(this._div1, 'opacity', '', 0, 100, 100, 0);
					break;
				case 'right-left':
					this.transactionMaker.AppendMotion(this._div1, 'left', 'px', 0, 100, 0, -toNumber(this.objectContainer_width));
					this.transactionMaker.AppendMotion(this._div2, 'left', 'px', 0, 100, toNumber(this.objectContainer_width), 0);
					break;
				case 'left-right':
					this.transactionMaker.AppendMotion(this._div1, 'left', 'px', 0, 100, 0, toNumber(this.objectContainer_width));
					this.transactionMaker.AppendMotion(this._div2, 'left', 'px', 0, 100, -toNumber(this.objectContainer_width), 0);	
					break;
				case 'top-bottom':
					this.transactionMaker.AppendMotion(this._div1, 'top', 'px', 0, 100, 0, toNumber(this.objectContainer_height));
					this.transactionMaker.AppendMotion(this._div2, 'top', 'px', 0, 100, -toNumber(this.objectContainer_height), 0);
					break;
				case 'bottom-top':
					this.transactionMaker.AppendMotion(this._div1, 'top', 'px', 0, 100, 0, -toNumber(this.objectContainer_height));
					this.transactionMaker.AppendMotion(this._div2, 'top', 'px', 0, 100, toNumber(this.objectContainer_height), 0);
					break;
				case 'test':
					this.transactionMaker.AppendMotion(this._div1, 'top', 'px', 0, 100, 0, -toNumber(this.objectContainer_height));
					this.transactionMaker.AppendMotion(this._div2, 'top', 'px', 0, 100, toNumber(this.objectContainer_height), 0);
					break;
			}
			this.transactionMaker.AppendEvent(1, 'var obj1 = HtmlPlus_SlideShowColl[\'' + CStrJS(this.id) +  '\']; var ok = obj1.transactionMaker._status==\'play\';  obj1._div2Base.style.display = ((ok) ? \'block\' : \'none\'); if(ok) obj1._imgRedim(obj1._img2);');
			this.transactionMaker.AppendEvent(100, 'HtmlPlus_SlideShowColl[\'' + CStrJS(this.id) +  '\']._transactionMaker_Restore();');	
		}
	} 
	
	this._transactionMaker_Restore = function(){
		//ripristino l'immagine1
		this._img1.src = this._img2.src;
		this._img1.alt = this.imagesCollection[this.GetNextPosition()].alt;
		this._img1.onClick = this.imagesCollection[this.GetNextPosition()].onClick;
		switch (this.zoomType){
			case 'fixed':
				break;
			default:
				this._img1.style.width = this._img2.style.width;
				this._img1.style.height = this._img2.style.height;
				this._img1.style.top = this._img2.style.top;
				this._img1.style.left = this._img2.style.left;
		}
		
		//ripristino il div1 e div2 e nascondo il div2
		this.transactionMaker.Stop();
		//faccio partire il caricamento della nuova immagine
		cont1 = this._currentPosition;
		if (this.GetNextPosition() >= 0) {
			this._currentPosition = this.GetNextPosition();	
		}else{
			this._changeStatus('stop');
		}
		this.OnTransactionEnd(this, cont1,  this.GetCurrentPosition());
		if (this._status == 'play') this._runStep1();
	}

	
	this._imgRedim = function (img){
		var divW, divH, imgW, imgH;
		
		divW = toNumber(GetProperty(this.objectContainer, 'width', true));
		divH = toNumber(GetProperty(this.objectContainer, 'height', true));
		imgW = toNumber(GetProperty(this._imgLoad, 'width', true));
		imgH = toNumber(GetProperty(this._imgLoad, 'height', true));
		
		switch (this.zoomType){
			case 'fixed':
				break;
			case 'min':
				if (( divW / divH ) > (imgW / imgH)) {
					// Calcolo le dimensioni
					img.style.width = divW + 'px';
					img.style.height = (imgH * divW / imgW) + 'px';
					// Centrol'immagine
					img.style.top = Math.round(-(parseInt(img.style.height, 0) - divH)/2 )+ 'px';
					img.style.left = '0px';
				}else{
					// Calcolo le dimensioni
					img.style.height = divH + 'px';
					img.style.width = (imgW * divH / imgH) + 'px';
					// Centro l'immagine
					img.style.top = '0px';
					img.style.left = Math.round(-(parseInt(img.style.width, 0) - divW)/2) + 'px';
				}
				break;
			case 'max':
				if (( divW / divH ) < (imgW / imgH)){
					// Calcolo le dimensioni dell'immagine
					img.style.width = divW + 'px';
					img.style.height = (imgH * divW / imgW) + 'px' ;
					// Centro l'immagine
					img.style.left = '0px';
					img.style.top = Math.round((divH -(parseInt(img.style.height, 0)))/ 2) + 'px';
				}else{
					// Calcolo le dimensioni dell'immagine
					img.style.height = divH + 'px';
					img.style.width = (imgW * divH / imgH) + 'px' ;
					// Centro l'immagine	
					img.style.left = Math.round((divW -(parseInt(img.style.width, 0)))/ 2) + 'px';
					img.style.top = '0px';
				}
				break;
		}
	}
	
	this._imgLoad_onLoad = function (ev){
		var eventObj = new STDEvent(ev);
		if (eventObj.srcElement._HtmlPlus_SlideShowObj) {
			eventObj.srcElement._HtmlPlus_SlideShowObj._imgLoad_isLoaded = true;
			//this.OnPreloadEnd(this, eventObj.srcElement.src);
		}
	}
	
	this._changeStatus = function (nuovoValore) {
		if (this._status != nuovoValore) {
			var str1 = this._status;
			this._status = nuovoValore;
			this.OnStatusChanged(this, str1, nuovoValore);
		}
	}
	
	this.OnStatusChanged = function (SlideShow, OldStatusValue, NewStatusValue) {return void(0)};
	this.OnPreloadBegin = function (SlideShow, Src) {return void(0)};
	this.OnPreloadEnd = function (SlideShow, Src) {return void(0)};
	this.OnTransactionBegin = function (SlideShow, OldImageIndex, NewImageIndex) {return void(0)};
	this.OnTransactionEnd = function (SlideShow, OldImageIndex, NewImageIndex) {return void(0)};
	
	this._initialize();
	return this;
}


function HtmlPlus_VerticalFill(HtmlObject, NoDynamic) {
	//Dimensiona l'oggetto passato al fine di riempire lo spazio a disposizione senza far comparire le barre di scorrimento.
	//Mettendo NoDynamic a TRUE, il ridimensionamento viene impostato al valore secondo la dimensione attuale del browser, e su
	//ridimensionamento l'oggetto non viene ridimensionato.
	//ATTENZIONE: l'oggetto è consigliabile che sia posizionato in alto a sinistra rispetto al suo contenitore.
	var posY = getPos(HtmlObject, 'top');
	var Body = window.document.body;
	var offsetY = 0;
	HtmlObject.height = Body.clientHeight - posY - offsetY;
	if (Body.scrollHeight > Body.clientHeight) {	//Se c'è la scrollBar allora...
		HtmlObject.height -= Body.scrollHeight - Body.clientHeight;
	}
	offsetY = Body.clientHeight - posY - HtmlObject.height;
	if (!NoDynamic) {
		HtmlObject.setExpression('height', 'window.document.body.clientHeight - getPos(findObj("' + ((HtmlObject.id) ? HtmlObject.id : HtmlObject.name) + '"), "top") - ' + offsetY);
	}
}
function HtmlPlus_OrizzontalFill(HtmlObject, NoDynamic) {
	var posX = getPos(HtmlObject, 'left');
	var Body = window.document.body;
	var offsetX = 0;
	HtmlObject.width = Body.clientWidth - posX - offsetX;
	if (Body.scrollWidth > Body.clientWidth) {	//Se c'è la scrollBar allora...
		HtmlObject.width -= Body.scrollWidth - Body.clientWidth;
	}
	offsetX = Body.clientWidth - posX - HtmlObject.width;
	if (!NoDynamic) {
		HtmlObject.setExpression('width', 'window.document.body.clientWidth - getPos(findObj("' + ((HtmlObject.id) ? HtmlObject.id : HtmlObject.name) + '"), "left") - ' + offsetX);
	}
}
function HtmlPlus_AutoScroll_AddPlusToObject(HtmlObject, ObjectHeight, PixelPerSec, NoAutoStart) {
	new HtmlPlus_AutoScroll('AutoScroll_' + HtmlObject.id, HtmlObject, ObjectHeight, PixelPerSec, NoAutoStart, null);
}
function HtmlPlus_AutoScroll(IdObject, ScrollerHtmlObject, ClientHeight, PixelPerSecond, NoAutoStart, HtmlPageSeparator, IsOrizzontal) {
	this.id = IdObject;
	this.objectType = 'HtmlPlus_AutoScroll';
	this.scrollerHtmlObject = ScrollerHtmlObject;	//Riferimento all'oggetto che effettuerà lo scrolling del suo contenuto;
	this.clientHeight = ClientHeight;				//Valore in Pixel o rif. a oggetto Html da cui determinare l'altezza di ScrollerHtmlObject;
	this.pixelPerSec = 30;							//Velocità di scorrimento;
	this.htmlPageSeparator = HtmlPageSeparator;		//Codice HTML che verrà usato come separatore fra pagine; se non definito il separatore sarà una
													//pagina bianca alta quanto [scrollerHtmlObject.clientHeight];
	this.isOrizzontal = IsOrizzontal;				//Se nullo o true la pagina simuove verticalmente altrimenti orizzontalmente
	this.autoStart = false;							//Se TRUE, lo scroll partirà quando verrà eseguito l'evento WINDOW.ONLOAD;
	this.fps = 0;									//Fotogrammi per secondo (qualità animazione);
	this.enabled = false;							//Tipicamente TRUE o FALSE, indica se l'animazione è attivata o disattivata;
	this._isPlay = false;							//Se TRUE, significa che l'animazione è accesa;
	this._tmp = null;								//Riferimento all'istanza "setInterval" che esegue l'animazione;

	if (!window.HtmlPlus_AutoScrollColl) {
		window.HtmlPlus_AutoScrollColl = new Array();
		addEvent(window, 'load', function() {
						var obj;
						for (obj in window.HtmlPlus_AutoScrollColl) {
							window.HtmlPlus_AutoScrollColl[obj].WINDOW_OnLoadHandler();
							break;
						}
					}
				 );
	}
	window.HtmlPlus_AutoScrollColl[this.id] = this;
	
	this._initialize = function() {
		var defaultPixelPerSec = 20;
		var defaultFps = GetBrowserInfo('RecommendedFps');
		
		this.scrollerHtmlObject.AutoScrollObject = this;
		if (!this.pixelPerSec) this.pixelPerSec = defaultPixelPerSec;
		this.autoStart = ((NoAutoStart) ? false : true);
		this.fps = defaultFps;
		this.enabled = 'toInitialize';

		if ( ! this.isOrizzontal ) {
			switch (typeof(this.clientHeight)) {
				case 'object':
					if (GetBrowserInfo("Name") == 'MSIE') {
						this.scrollerHtmlObject.style.setExpression('height', function() {this.clientHeight.currentStyle('clientHeight');});
					} else {
						this.scrollerHtmlObject.style.height = GetProperty(this.clientHeight, 'clientHeight') + 'px';
					}
					break;
				case 'string':
					if (this.clientHeight.length > 10) {
						this.scrollerHtmlObject.style.height = this.clientHeight + 'px';
						break;
					}
				default:
					this.scrollerHtmlObject.style.height = toNumber(this.clientHeight, 0) + 'px';
					break;
				}
			} 
			else 
			{
				switch (typeof(this.clientHeight)) {
					case 'object':
						if (GetBrowserInfo("Name") == 'MSIE') {
							this.scrollerHtmlObject.style.setExpression('width', function() {this.clientHeight.currentStyle('clientWidth');});
						} else {
							this.scrollerHtmlObject.style.width = GetProperty(this.clientHeight, 'clientWidth') + 'px';
						}
						break;
					case 'string':
						if (this.clientHeight.length > 10) {
							this.scrollerHtmlObject.style.width = this.clientHeight + 'px';
							break;
						}
					default:
						this.scrollerHtmlObject.style.width = toNumber(this.clientHeight, 0) + 'px';
						break;
					}		
			}

		addEvent(this.scrollerHtmlObject, 'mouseover', function(ev) {
						var eventObj = new STDEvent(ev);
						var obj = eventObj.srcElement;
						while (obj.tagName != 'BODY') {
							if (obj.AutoScrollObject) {
								obj.AutoScrollObject.OnMouseOverHandler();
								break;
							} else {
								obj = obj.parentNode;
							}
						}
					}
				);
		addEvent(this.scrollerHtmlObject, 'mouseout', function(ev){
						var eventObj = new STDEvent(ev);
						var obj = eventObj.srcElement;
						while (obj.tagName != 'BODY') {
							if (obj.AutoScrollObject) {
								obj.AutoScrollObject.OnMouseOutHandler();
								break;
							} else {
								obj = obj.parentNode;
							}
						}
					}
				);
	}
	
	this.WINDOW_OnLoadHandler = function() {
		var obj;
		for (obj in window.HtmlPlus_AutoScrollColl) {
			if (window.HtmlPlus_AutoScrollColl[obj].autoStart) window.HtmlPlus_AutoScrollColl[obj].Start();
		}
	}
	this.OnMouseOverHandler = function() {
		this.Stop();
	}
	this.OnMouseOutHandler = function() {
		this.Start();
	}
	
	this.Start = function() {
		if (this.enabled == 'toInitialize') {
				//Inizializzo l'oggetto
			if (! this.isOrizzontal){
				if (this.scrollerHtmlObject.scrollHeight > this.scrollerHtmlObject.clientHeight) {
					if (this.htmlPageSeparator) {
						// Inserisco il SeparatoreDiPagina all'inizio del contenuto dello Scroller, poi duplico tutto il contenuto.
						var str1 = this.htmlPageSeparator + this.scrollerHtmlObject.innerHTML;
						this.scrollerHtmlObject.innerHTML = str1 + str1;
						this.scrollerHtmlObject.style.paddingTop = '0px';
						this.scrollerHtmlObject.style.paddingBottom = '0px';
					} else {
						// Aggiungo dello spazio vuoto in testa ed in coda al contenuto
						this.scrollerHtmlObject.style.paddingTop = this.scrollerHtmlObject.clientHeight + 'px';
						this.scrollerHtmlObject.style.paddingBottom = this.scrollerHtmlObject.clientHeight + 'px';
					}
					this.enabled = true;
				}
				this._tmr = '';
			}else{
				if (this.scrollerHtmlObject.scrollWidth > this.scrollerHtmlObject.clientWidth) {
					if (this.htmlPageSeparator) {
						// Inserisco il SeparatoreDiPagina all'inizio del contenuto dello Scroller, poi duplico tutto il contenuto.
						var str1 = '<table cellpadding="0" height="100%" cellspacing="0" border="0"><tr>';
						str1 = str1 + '<td align="left" valign="middle">' + this.htmlPageSeparator + '</td>' ;
						str1 = str1 + '<td>' + this.scrollerHtmlObject.innerHTML + '</td>';
						str1 = str1 + '<td align="left" valign="middle">' + this.htmlPageSeparator + '</td>';
						str1 = str1 + '<td>' + this.scrollerHtmlObject.innerHTML + '</td>';
						str1 = str1 + '</tr></table>';
						this.scrollerHtmlObject.innerHTML = str1;
						this.scrollerHtmlObject.style.paddingLeft = '0px';
						this.scrollerHtmlObject.style.paddingRight = '0px';
					} else {
						// Aggiungo dello spazio vuoto in testa ed in coda al contenuto
						this.scrollerHtmlObject.style.paddingLeft = this.scrollerHtmlObject.clientWidth + 'px';
						this.scrollerHtmlObject.style.paddingRight = this.scrollerHtmlObject.clientWidth + 'px';
					}
					this.enabled = true;
				}
				this._tmr = '';
			}
		}
		if (!this.isPlay && this.enabled) {
			this._tmr = setInterval('var obj = window.HtmlPlus_AutoScrollColl["' + this.id + '"]; obj._runStep();', 1000 / this.fps);
			this.isPlay = true;
		}
	}


	this.Stop = function() {
		if (this.isPlay) {
			this.isPlay = false;
			window.clearInterval(this._tmr);
			this._tmr = '';
		}
	}
		
	this._runStep = function() {
		var i;
		if (this.isPlay) {
			if ( ! this.isOrizzontal) {
				if (this.scrollerHtmlObject.scrollHeight <= this.scrollerHtmlObject.clientHeight) {
					this.Stop();
				} else {
					i = this.scrollerHtmlObject.scrollTop + Math.ceil(this.pixelPerSec / this.fps);
					if (this.htmlPageSeparator) {
						if ((i >= this.scrollerHtmlObject.scrollHeight / 2) || (i < 0)) {
							if (this.pixelPerSec > 0) {
								i = 0;
							} else {
								i = this.scrollerHtmlObject.scrollHeight / 2;
							}
						}
					} else {
						if ((i > this.scrollerHtmlObject.scrollHeight - this.scrollerHtmlObject.clientHeight) || (i < 0)) {
							if (this.pixelPerSec > 0) {
								i = 0;
							} else {
								i = this.scrollerHtmlObject.scrollHeight;
							}
						}
					}
					this.scrollerHtmlObject.scrollTop = i;
				}
			}else{
				if (this.scrollerHtmlObject.scrollWidth <= this.scrollerHtmlObject.clientWidth) {
					this.Stop();
				} else {
					i = this.scrollerHtmlObject.scrollLeft + Math.ceil(this.pixelPerSec / this.fps);
					if (this.htmlPageSeparator) {
						if ((i >= this.scrollerHtmlObject.scrollWidth / 2) || (i < 0)) {
							if (this.pixelPerSec > 0) {
								i = 0;
							} else {
								i = this.scrollerHtmlObject.scrollWidth / 2;
							}
						}
					} else {
						if ((i > this.scrollerHtmlObject.scrollWidth - this.scrollerHtmlObject.clientWidth) || (i < 0)) {
							if (this.pixelPerSec > 0) {
								i = 0;
							} else {
								i = this.scrollerHtmlObject.scrollWidth;
							}
						}
					}
					this.scrollerHtmlObject.scrollLeft = i;
				}
			}
		}
	}
	
	this._initialize();
	return this;
}



function HtmlPlus_ClipMaker(IdObject, TransactionTime, fps) {
	this.id = IdObject;
	this.objectType = 'HtmlPlus_ClipMaker';
	this.transactionTime = TransactionTime;		//Durata della transazione (in secondi).
	this.fps = fps;								//Fotogrammi per secondo della transazione.
	
		
	if (!window.HtmlPlus_ClipMakerColl) window.HtmlPlus_ClipMakerColl = new Array();
	window.HtmlPlus_ClipMakerColl[this.id] = this;
	
	this._initialize = function () {
		this._time = 0;
		this._speed = 1;
		this._status = 'stop';
		this._tmr = null;
		this._startTime = null;
		this._showFrame_running = false;
		if (!this.fps) this.fps = GetBrowserInfo('RecommendedFps');
	}
	this.Motions = function () {
		return this._motions;
	}
	this.AppendMotion = function (AnimatedHtmlObject, AttributeName, AttributeUM_Format, StartTime, StopTime, StartValue, StopValue, TransactionType) {
		/*
		Aggiunge un oggetto Movimento all'array [Motions]. Parametri:
			AnimatedHtmlObject		Qggetto da animare.
			AttributeName			Attributo da modificare.
			AttributeUM_Format		L'unità di misura del valore che verrà impostato all'attributo; se la stringa contiene il carattere "#" allora
									la stringa verrà usata in modalità Format, sostituendo il carattere segnaposto "#" col valore numerico da settare;
									Es.:    AttributeUM_Format = 'alpha(opacity=#)'    l'attributo verra settato con:   'alpha(opacity=12)'.
			StartTime				Tempo in cui deve iniziare l'animazione (da 0 a 100, corrispondenti all'inizio e alla fine del clip).
			StopTime				Tempo in cui deve finire l'animazione (come per StartTime).
			StartValue				Valore di partenza dell'attributo.
			StopValue				Valore finale dell'attributo.
			TransactionType			Il tipo di transazione; può essere: 'square', 'triangle', 'sin', 'cos'.
		*/
		var obj1 = new Object();
		obj1.htmlObject = AnimatedHtmlObject;
		obj1.attributeName = AttributeName;
		obj1.attributeFormat = AttributeUM_Format;
		obj1.startTime = StartTime;
		obj1.stopTime = StopTime;
		obj1.startValue = StartValue;
		obj1.stopValue = StopValue;
		obj1.transactionType = TransactionType;
		obj1.enabled = true;
		
		if (typeof(obj1.htmlObject) != 'object') obj1.htmlObject = findObj(obj1.htmlObject);
		if (obj1.attributeFormat.indexOf('#') == -1) obj1.attributeFormat = '#' + obj1.attributeFormat;
		switch (obj1.transactionType) {
			case 'square': case 'triangle': case 'sin': case 'cos': break;
			default: obj1.transactionType = 'triangle';
		}
		
		if (!this._motions) this._motions = new Array();
		this._motions[this._motions.length] = obj1;
	}
	this.Events = function () {
		return this._events;
	}
	this.AppendEvent = function (Time, Action) {
		/*
		Aggiunge un oggetto Evento all'array [Events]. Parametri:
			Time					Il momento in cui deve eseguirsi l'evento (da 0 a 100, corrispondenti all'inizio e alla fine del clip).
			Action					L'azione che deve essere eseguita; può essere una stringa JavaScript oppure un puntatore a funzione.
		*/
		var obj1 = new Object();
		obj1.time = Time;
		obj1.action = Action;
		
		if (!this._events) this._events = new Array();
		this._events[this._events.length] = obj1;
	}
	this.Play = function () {
		if (this._status != 'play') {
			var ora = new Date().getTime();
			if (this._tmr) window.clearInterval(this._tmr);
			if (this._status == 'stop') {
				this._time = ((this._speed > 0) ? 0 : 100);
			}
			this._startTime = ora - (this.transactionTime / this._speed) * 1000 * this._time / 100;
			this._status = 'play';
			this._tmr = setInterval('var obj = window.HtmlPlus_ClipMakerColl["' + this.id + '"]; obj._showFrame();', 1000 / this.fps);
			return true;
		} else {
			return false;
		}
	}
	this.Pause = function () {
		if (this._status == 'play') {
			if (this._tmr) window.clearInterval(this._tmr);
			this._status = 'pause';
			this._forceShowFrame(this._calculateCurrTime());
			return true;
		} else {
			return false;
		}
	}
	this.Stop = function () {
		if (this._tmr) window.clearInterval(this._tmr);
		this._startTime = null;
		this._status = 'stop';
		this._forceShowFrame((this._speed > 0)? 0 : 100);
		return true;
	}
	this.GetTime = function () {
		//Percentuale di esecuzione. 0: inizio del clip; 100: fine del clip.
		//Se Speed è negativo, 100 corrisponderà sempre alla fine del filmato, che però, se il clip è in Play, decrementerà fino a 0.
		return this._time;
	}
	this.SetTime = function (TimeValue) {
		//Sposta il punto di esecuzione. Valore da 0 a 100.
		if (TimeValue >= 0 && TimeValue <= 100) {
			if (this._status == 'play') {
				this.Pause();
				this._forceShowFrame(TimeValue);
				this.Play();
			} else {
				this._forceShowFrame(TimeValue);
			}
		}
	}
	this.GetSpeed = function () {
		//Velocità di esecuzione. 1: velocità normale; 0.5: velocità dimezzata; 2: velocità doppia; -1: reverse; ecc..
		return this._speed;
	}
	this.SetSpeed = function (SpeedValue) {
		//Velocità di esecuzione. Valore minore o maggiore da 0.
		if (SpeedValue > 0 || SpeedValue < 0) this._speed = SpeedValue;
	}
	this.Status = function () {
		//Può essere: 'play', 'pause', 'stop'.
		return this._status;
	}
	
	this._calculateCurrTime = function () {
		//Calcolo il TIME corrente in base a quanto tempo è trascorso dall'inizio dell'animazione
		var fReturn;
		fReturn = (new Date().getTime() - this._startTime) / 1000 / (this.transactionTime / this._speed) * 100;
		if (fReturn < 0) {
			fReturn = 0;
		} else if (fReturn > 100) {
			fReturn = 100;
		}
		return fReturn;
	}
	this._forceShowFrame = function (newTime) {
		var risp;
		risp = this._showFrame(newTime);
		if (!risp) setTimeout('window.HtmlPlus_ClipMakerColl[\'' + this.id + '\']._forceShowFrame(' + newTime + ');', 100);
	}
	this._showFrame = function (newTime) {
		//Elabora un fotogramma. Il parametro [newTime] (opzionale) serve per indicare il TIME che si deve elaborare. Dopo l'elaborazione
		//la funzione setterà il valore TIME alla classe.
		var listaMotions = new Array();
		var listaEvents = new Array();
		var precTime, currTime;
		var cont1, cont2, str1, obj1, obj2;
		
		if (!this._showFrame_running) {
			this._showFrame_running = true;
			
			//Determino i TIME
			precTime = this._time;
			if (newTime >= 0 || newTime < 0) {
				currTime = newTime;
				if (currTime < 0) {
					currTime = 0;
				} else if (currTime > 100) {
					currTime = 100;
				}
			} else {
				currTime = this._calculateCurrTime();
			}
			
			if (currTime != precTime) {
				//Determino gli oggetti-attributi da modificare
				for (cont1 in this._motions) {
					obj1 = this._motions[cont1];
					//Verifico se l'oggetto Motion esegue un movimento all'interno dell'intervallo  [precTime - currTime]
					if (precTime <= currTime && obj1.startTime <= currTime && obj1.stopTime > precTime
							|| precTime > currTime && obj1.startTime < precTime && obj1.stopTime >= currTime) {
						//L'oggetto Motion è da prendere in considerazione.
						//Verifico se l'oggetto-attributo è già presente in [listaMotions]:
						str1 = obj1.htmlObject.uniqueID + '.' + obj1.attributeName;
						if (listaMotions[str1]) {
							//è presente, quindi valuto se l'oggetto Motion presente nell'array ha un valore [expire] maggiore di quello corrente;
							//se così fosse allora sostituisco il Motion dell'array con quello corrente.
							obj2 = listaMotions[str1];
							cont2 = this._showFrame_calcolaExpire(currTime, precTime, obj1);
							if (cont2 < obj2.expire) {
								//Il valore [expire] del Motion corrente è minore; sostituisco il Motion dell'array con quello corrente.
								obj2.motion = obj1;
								obj2.expire = cont2;
							}
						} else {
							//non è presente, quindi creo un nuovo item.
							obj2 = new Object();
							obj2.motion = obj1;
							obj2.value = null;
							//setto [expire]: indica il tempo da cui è scaduto il movimento
							obj2.expire = this._showFrame_calcolaExpire(currTime, precTime, obj1);
						}
						listaMotions[str1] = obj2;
					}
				}
				//Determino gli eventi da invocare
				for (cont1 in this._events) {
					obj1 = this._events[cont1];
					//Verifico se l'oggetto Evento si verifica all'interno dell'intervallo  [precTime - currTime]
					if (precTime <= currTime && precTime < obj1.time && currTime >= obj1.time
							|| precTime > currTime && currTime <= obj1.time && precTime > obj1.time) {
						//L'oggetto Evento si verifica all'interno di questo intervallo temporale.
						listaEvents[listaEvents.length] = obj1;
					}
				}
				//Calcolo i valori per ogni animazione
				for (cont1 in listaMotions) {
					obj1 = listaMotions[cont1];
					if (currTime >= precTime && obj1.motion.stopTime <= currTime) {
						str1 = obj1.motion.stopValue;
					} else if (currTime < precTime && obj1.motion.startTime >= currTime) {
						str1 = obj1.motion.startValue;
					} else {
						//Calcolo il "fattore percentuale" della Motion corrente. Il valore che si ottiene và da 0 a 1.
						cont2 = (currTime - obj1.motion.startTime) / (obj1.motion.stopTime - obj1.motion.startTime);
						switch (obj1.motion.transactionType) {
							case 'square':		//si sposta con un unico fotogramma, che è quello centrale rispetto al tempo di transizione indicato.
								str1 = obj1.motion.startValue + ((obj1.motion.stopValue - obj1.motion.startValue) * Math.round(cont2));
								break;
							case 'sin':			//da riposo a MouseOver: parte veloce e si ferma lentamente
								str1 = obj1.motion.startValue + ((obj1.motion.stopValue - obj1.motion.startValue) * Math.sin(cont2 * Math.PI / 2));
								break;
							case 'cos':			//da riposo a MouseOver: parte lento e si ferma di scatto
								str1 = obj1.motion.stopValue - ((obj1.motion.stopValue - obj1.motion.startValue) * Math.cos(cont2 * Math.PI / 2));
								break;
							case 'triangle':	//movimento a velocità costante
							default:
								str1 = obj1.motion.startValue + ((obj1.motion.stopValue - obj1.motion.startValue) * cont2);
						}
					}
					obj1.value = obj1.motion.attributeFormat.replace('#', str1);
				}
				//Eseguo le animazioni
				for (cont1 in listaMotions) {
					obj1 = listaMotions[cont1];
					SetProperty(obj1.motion.htmlObject, obj1.motion.attributeName, obj1.value);
				}
				//Controllo [currTime] e valuto se sono arrivato alla fine del clip
				if (this._status == 'play') {
					if (this._speed > 0 && currTime == 100 || this._speed < 0 && currTime == 0) {
						this.Pause();
					}
				}
				this._time = currTime;
				//Eseguo gli eventi
				for (cont1 in listaEvents) {
					obj1 = listaEvents[cont1];
					switch (typeof(obj1.action)) {
						case 'function':
							obj1.action(this, currTime);
							break;
						case 'string':
							str1 = obj1.action;
							str1 = str1.replace(/\[THIS.ID]/g, this.id);
							str1 = str1.replace(/\[THIS]/g, 'window.HtmlPlus_ClipMakerColl[\'' + this.id + '\']');
							str1 = str1.replace(/\[CURRENT_TIME]/g, currTime);
							str1 = str1.replace(/\[CURRENT_STATUS]/g, this._status);
							eval(str1);
							break;
					}
				}
			}
			//window.status = 'Status = ' + this.Status() + '   Speed = ' + this.GetSpeed() + '    Time = ' + this.GetTime();
			this._showFrame_running = false;
			return true;
		} else {
			return false;
		}
	}
	this._showFrame_calcolaExpire = function (CurrTime, PrecTime, ObjMotion) {
		if (PrecTime <= CurrTime) {
			return ((ObjMotion.stopTime >= CurrTime) ? ObjMotion.stopTime - CurrTime : 0);
		} else {
			return ((ObjMotion.startTime <= CurrTime) ? CurrTime - ObjMotion.startTime : 0);
		}
	}
	
	this._initialize();
	return this;
}

function HtmlPlus_AnimationOnMouseEvents(IdObject, ControllerHtmlObject, AnimatedHtmlObject, AttributeName, AttributeUM_Format, ValueInMouseOut, ValueInMouseOver, TransactionType, TransactionTime, fps) {
	//Ogni oggetto [HtmlPlus_AnimationOnMouseEvents] può gestire una sola animazione, ma la classe è pensata per far si che si possano
	//agganciare più animazioni sugli stessi oggetti, animando attributi diversi, col medesimo oggetto ControllerHtmlObject.
	this.id = IdObject;
	this.objectType = 'HtmlPlus_AnimationOnMouseEvents';
	this.controllerHtmlObjectColl = ControllerHtmlObject;	//Riferimento all'oggetto che capterà gli eventi OnMouseOver e OnMouseOut (può essere un array di oggetti).
	this.animatedHtmlObject = AnimatedHtmlObject;			//Riferimento all'oggetto che deve essere animato.
	this.attributeName = AttributeName;			//Il nome dell'attributo che sarà modificato (es. 'left', 'top', 'width', 'height').
	this.attributeFormat = AttributeUM_Format;	//L'unità di misura del valore che verrà impostato all'attributo; se la stringa contiene il carattere "#" allora
												//la stringa verrà usata in modalità Format, sostituendo il carattere segnaposto "#" col valore numerico da settare;
												//Es.:    AttributeUM_Format = 'alpha(opacity=#)'    l'attributo verra settato con:   'alpha(opacity=12)'.
	this.valueInMouseOut = ValueInMouseOut;		//Il valore che deve avere l'attributo in posizione di riposo.
	this.valueInMouseOver = ValueInMouseOver;	//Il valore che deve avere l'attributo quando si verifica OnMouseOver su HtmlObject.
	this.transactionType = TransactionType;		//Il tipo di transazione; può essere: 'square', 'triangle', 'sin', 'cos'.
	this.transactionTime = TransactionTime;		//Durata della transazione (in secondi).
	this.fps = fps;								//Fotogrammi per secondo della transazione.
	this.enabled = true;						//Se impostato a FALSE, gli eventi OnMouseOver e OnMouseOut non produrranno alcun effetto.
	// -- eventi --
	this.OnAnimationEnd = null;					//Puntatore a funzione o comando JS da eseguire quando l'animazione è finita (vedere [_animateHtmlObject])
	
	
	if (!window.HtmlPlus_AnimationOnMouseEventsColl) window.HtmlPlus_AnimationOnMouseEventsColl = new Array();
	window.HtmlPlus_AnimationOnMouseEventsColl[this.id] = this;
	
	this._initialize = function () {
		var i;
		this._direzione = 0;
		this._currAction = '';
		this._tmr = null;
		this._startTime = null;
		this._perc = 0;
		if (!this.fps) this.fps = GetBrowserInfo('RecommendedFps');
		switch (ValueType(this.controllerHtmlObjectColl)) {
			case 'Object':
				i = this.controllerHtmlObjectColl;
				this.controllerHtmlObjectColl = [i];
				break;
			case 'Array':
				for (i in this.controllerHtmlObjectColl) {
					if (typeof(this.controllerHtmlObjectColl[i]) == 'string') this.controllerHtmlObjectColl[i] = findObj(this.controllerHtmlObjectColl[i]);
				}
				break;
			case 'string':
				this.controllerHtmlObjectColl = [findObj(this.controllerHtmlObjectColl)];
				break;
			default:
				this.controllerHtmlObjectColl = null;
		}
		if (typeof(this.animatedHtmlObject) != 'object') this.animatedHtmlObject = findObj(this.animatedHtmlObject);
		if (this.controllerHtmlObjectColl) {
			for (i in this.controllerHtmlObjectColl) {
				this._initializeControllerHtmlObject(this.controllerHtmlObjectColl[i]);
			}
		}
		if (this.attributeFormat.indexOf('#') == -1) this.attributeFormat = '#' + this.attributeFormat;
	}
	
	this._initializeControllerHtmlObject = function (ControllerHtmlObject) {
		var i;
		if (!ControllerHtmlObject.HtmlPlus_AnimationOnMouseEventsColl) {
			ControllerHtmlObject.HtmlPlus_AnimationOnMouseEventsColl = new Array();
			addEvent(ControllerHtmlObject, 'mouseover', function (ev) {
						var eventObj = new STDEvent(ev);
						for (i in eventObj.srcElement.HtmlPlus_AnimationOnMouseEventsColl) {
							eventObj.srcElement.HtmlPlus_AnimationOnMouseEventsColl[i].OnMouseOverHandler();
							break;
						}
					}
				);
			addEvent(ControllerHtmlObject, 'mouseout', function (ev) {
						var eventObj = new STDEvent(ev);
						for (i in eventObj.srcElement.HtmlPlus_AnimationOnMouseEventsColl) {
							eventObj.srcElement.HtmlPlus_AnimationOnMouseEventsColl[i].OnMouseOutHandler();
							break;
						}
					}
				);
		}
		if (!ControllerHtmlObject.HtmlPlus_AnimationOnMouseEventsColl[this.id]) {
			ControllerHtmlObject.HtmlPlus_AnimationOnMouseEventsColl[this.id] = this;
			if (ControllerHtmlObject.all) {
				for (i=0; i<ControllerHtmlObject.all.length; i++) this._initializeControllerHtmlObject(ControllerHtmlObject.all[i]);
			} else if (ControllerHtmlObject.childNodes) {
				for (i=0; i<ControllerHtmlObject.childNodes.length; i++) this._initializeControllerHtmlObject(ControllerHtmlObject.childNodes[i]);
			}
		}
	}
	this._setStatusVariables = function (NewAction, NewTransactionTime) {
		var ora = new Date().getTime();
		if (this._tmr) window.clearInterval(this._tmr);
		switch (this._currAction) {
			case '':
				this._startTime = ora;
				break;
			case 'ini':
				this._startTime = ora;
				break;
			case 'moved':
				if (NewAction == 'stop') {
					this._perc = 100 - (ora - this._startTime) / 1000 / NewTransactionTime * 100;
					this._startTime = ora - NewTransactionTime * 1000 * this._perc / 100;
				}
				break;
			case 'stop':
				if (NewAction == 'moved') {
					this._perc = 100 - (ora - this._startTime) / 1000 / NewTransactionTime * 100;
					this._startTime = ora - NewTransactionTime * 1000 * this._perc / 100;
				}
				break;
		}
		this._currAction = NewAction;
	}
	
	this.InitializeWithAnimation = function (InitializeValue, TransactionTime) {
		this._direzione = 1;
		SetProperty(this.animatedHtmlObject, this.attributeName, this.attributeFormat.replace('#',InitializeValue));
		this._setStatusVariables('ini', TransactionTime);
		this._tmr = setInterval('var obj = window.HtmlPlus_AnimationOnMouseEventsColl["' + this.id + '"]; obj._animateHtmlObject(' + InitializeValue + ', obj.valueInMouseOut, ' + TransactionTime + ');', 1000 / this.fps);
	}
	this.OnMouseOverHandler = function () {
		this.OnFiredEvent(true);
	}
	this.OnMouseOutHandler = function () {
		this.OnFiredEvent(false);
	}
	this.OnFiredEvent = function (IsBeginAnimation) {
		var i, j, obj, anim;
		for (i in this.controllerHtmlObjectColl) {
			obj = this.controllerHtmlObjectColl[i];
			for (j in obj.HtmlPlus_AnimationOnMouseEventsColl) {
				anim = obj.HtmlPlus_AnimationOnMouseEventsColl[j];
				if (anim._currAction != 'ini' && anim.enabled) {
					anim._direzione = ((IsBeginAnimation) ? 1 : -1);
					anim._setStatusVariables(((IsBeginAnimation) ? 'moved' : 'stop'), anim.transactionTime);
					anim._tmr = setInterval('var obj = window.HtmlPlus_AnimationOnMouseEventsColl["' + j + '"]; obj._animateHtmlObject(obj.valueInMouseOut, obj.valueInMouseOver, obj.transactionTime);', 1000 / this.fps);
				}
			}
		}
	}
	this._animateHtmlObject = function (StartValue, EndValue, TranslationTime) {
		var nuovoVal;
		var str1;
		var precAction;
		if (this._currAction != '') {
			//Incremento il valore [_PERC] di un tot per ogni esecuzione di questa funzione
			//this._perc = this._perc + 100 / (this.fps * TranslationTime);
			
			//Imposto il valore [_PERC] in base a quanto tempo è trascorso dall'inizio dell'animazione
			this._perc = (new Date().getTime() - this._startTime) / 1000 / TranslationTime * 100;
			if (this._direzione == -1) this._perc = 100 - this._perc;
			
			if (this._perc < 0) {
				this._perc = 0;
			} else if (this._perc > 100) {
				this._perc = 100;
			}
			switch (this._perc) {
				case 0:
					nuovoVal = StartValue;
					break;
				case 100:
					nuovoVal = EndValue;
					break;
				default:
					switch (this.transactionType) {
						case 'square':		//si sposta con un unico fotogramma, che è quello centrale rispetto al tempo di transizione indicato.
							nuovoVal = StartValue + ((EndValue - StartValue) * Math.round(this._perc / 100));
							break;
						case 'sin':			//da riposo a MouseOver: parte veloce e si ferma lentamente
							nuovoVal = StartValue + ((EndValue - StartValue) * Math.sin(this._perc * Math.PI / 200));
							break;
						case 'cos':			//da riposo a MouseOver: parte lento e si ferma di scatto
							nuovoVal = EndValue - ((EndValue - StartValue) * Math.cos(this._perc * Math.PI / 200));
							break;
						case 'triangle':	//movimento a velocità costante
						default:
							nuovoVal = StartValue + ((EndValue - StartValue) * (this._perc / 100));
					}

					break;
			}
			str1 = this.attributeFormat.replace('#', nuovoVal);
			SetProperty(this.animatedHtmlObject, this.attributeName, str1);
			if (this._perc==0 && this._currAction=='stop' || this._perc==100 && this._currAction!='stop') {
				//Fine animazione.
				
				//Reset delle variabili per la gestione dell'animazione
				precAction = this._currAction;
				if (this._currAction == 'ini') this._perc = 0;
				this._currAction = '';
				window.clearInterval(this._tmr);
				
				//Invoco l'evento [OnAnimationEnd], se gestito.
				if (this.OnAnimationEnd) {
					switch (typeof(this.OnAnimationEnd)) {
						case 'function':
							this.OnAnimationEnd(this, precAction);
							break;
						case 'string':
							str1 = this.OnAnimationEnd;
							str1 = str1.replace(/\[THIS.ID]/g, this.id);
							str1 = str1.replace(/\[THIS]/g, 'window.HtmlPlus_AnimationOnMouseEventsColl[\'' + this.id + '\']');
							str1 = str1.replace(/\[CURRENT_ACTION]/g, precAction);
							eval(str1);
							break;
					}
				}
			}
		}
	}
	
	this._initialize();
	return this;
}


function HtmlPlus_PageScroller(idObject, AnimatedHtmlObject, IsVerticalScroll, PageWidth, CurrentPage, TransactionType, TransactionTime, fps) {
	this.id = idObject;
	this.objectType = 'HtmlPlus_PageScroller';
	this.animatedHtmlObject = AnimatedHtmlObject;			//Riferimento all'oggetto che deve essere animato
	this.isVerticalScroll = IsVerticalScroll;	//Se TRUE, indica che lo scroll deve avvenire verticalmente, altrimenti sarà orizzontalmente.
	this.pageWidth = PageWidth;					//Dimensione della pagina (larghezza o altezza in base all'orientamento dello scroll)
	this.currentPage = CurrentPage;				//La pagina corrente, a base ZERO.
	this.transactionType = TransactionType;		//Il tipo di transazione; può essere: 'square', 'triangle', 'sin', 'cos'
	this.transactionTime = TransactionTime;		//Durata della transazione fra una pagnia ed un'altra adiacente (in secondi)
	this.fps = fps;								//Fotogrammi per secondo della transazione
	this.enabled = true;						//Se impostato a FALSE, i metodi GoTo####Page non produrranno alcun effetto

	if (!window.HtmlPlus_PageScrollerColl) window.HtmlPlus_PageScrollerColl = new Array();
	window.HtmlPlus_PageScrollerColl[this.id] = this;
	
	this._initialize = function () {
		var dimCorpo, obj1;
		this._attributeName = ((this.isVerticalScroll) ? 'scrollTop' : 'scrollLeft');
		//Creo e setto variabili pubbliche
		this.bodyWidth = ((this.isVerticalScroll) ? this.animatedHtmlObject.scrollHeight : this.animatedHtmlObject.scrollWidth);
		this.pages = Math.ceil(this.bodyWidth / this.pageWidth);
		//Se l'ultima pagina non è completamente piena, allora aggiungo un DIV per riempirla con spazio vuoto.
		dimCorpo = this.pageWidth * this.pages;
		if (dimCorpo != this.bodyWidth) {
			obj1 = this.animatedHtmlObject.childNodes[0];
			SetProperty(obj1, ((this.isVerticalScroll) ? 'height' : 'width'), dimCorpo.toString() + 'px');
		}
		if (!this.fps) this.fps = GetBrowserInfo('RecommendedFps');
		//Creo e setto variabili private
		this._attributeName = ((this.isVerticalScroll) ? 'scrollTop' : 'scrollLeft');
		this._currAction = '';
		this._tmr = null;
		this._startTime = null;
		this._perc = 0;
		//Mi posiziono nella PAGINA CORRENTE indicata nella creazione dell'oggetto
		SetProperty(this.animatedHtmlObject, this._attributeName, this.pageWidth * this.currentPage);
	}
	this._setStatusVariables = function (NewAction, NewTransactionTime) {
		var ora = new Date().getTime();
		if (this._tmr) window.clearInterval(this._tmr);
		switch (this._currAction) {
			case '':		//Nessuna azione in corso.
				this._perc = 0;
				this._startTime = ora;
				break;
			case 'ini':		//Azione in corso, inizializzazione.
				this._perc = 0;
				this._startTime = ora;
				this.currentPage = this._getTemporaryCurrentPage();
				break;
			case 'move':	//Azione in corso, spostamento in nuova pagina.
				this._perc = 0;
				this._startTime = ora;
				this.currentPage = this._getTemporaryCurrentPage();
				break;
		}
		this._currAction = NewAction;
	}
	this._getTemporaryCurrentPage = function () {
		var currPx;
		currPx = toNumber(GetProperty(this.animatedHtmlObject, this._attributeName), 0);
		return currPx / this.pageWidth;
	}
	this._getTransactionTotalTime = function (Pixels, TransactionTime) {
		var pagine = Pixels / this.pageWidth;
		switch (this.transactionType) {
			case 'square':		//si sposta con un unico fotogramma, che è quello centrale rispetto al tempo di transizione indicato.
				return TransactionTime;
				break;
			case 'sin':			//parte veloce e si ferma lentamente, l'ultima pagina è a velocità variabile
				if (pagine <= 1) {
					return TransactionTime * pagine;
				} else {
					return TransactionTime + (pagine - 1) * TransactionTime * Math.sin(100 / (TransactionTime * this.fps) * Math.PI / 200);
				}
				break;
			case 'cos':			//parte lento e si ferma di scatto, la prima pagina è a velocità variabile
				if (pagine <= 1) {
					return TransactionTime * pagine;
				} else {
					return TransactionTime + (pagine - 1) * TransactionTime * Math.cos(100 / (TransactionTime * this.fps) * Math.PI / 200);
				}
				break;
			case 'triangle':	//movimento a velocità costante
			default:
				return TransactionTime * pagine;
		}
	}
	this._scrollPage = function (StartPixel, EndPixel, TransactionTime) {
		var nuovoVal, tempoTot, tempoTrascorso, cont1;
		if (this._currAction != '') {
			//Imposto il valore [_PERC] in base a quanto tempo è trascorso dall'inizio dell'animazione
			tempoTot = this._getTransactionTotalTime(Math.abs(StartPixel - EndPixel), TransactionTime);
			tempoTrascorso = (new Date().getTime() - this._startTime) / 1000;
			this._perc = tempoTrascorso / tempoTot * 100;
			if(this._perc<0) this._perc=0; else if(this._perc>100) this._perc=100;
			
			switch (this._perc) {
				case 0:
					nuovoVal = StartPixel;
					break;
				case 100:
					nuovoVal = EndPixel;
					break;
				default:
					switch (this.transactionType) {
						case 'square':		//si sposta con un unico fotogramma, che è quello centrale rispetto al tempo di transizione indicato.
							nuovoVal = StartPixel + ((EndPixel - StartPixel) * Math.round(this._perc / 100));
							break;
						case 'sin':			//parte veloce e si ferma lentamente, l'ultima pagina è a velocità variabile
											//...in realtà non son riuscito a farlo, mi ci voleva troppo.
							nuovoVal = StartPixel + ((EndPixel - StartPixel) * Math.sin(this._perc * Math.PI / 200));
							break;
						case 'cos':			//parte lento e si ferma di scatto, la prima pagina è a velocità variabile
							nuovoVal = EndPixel - ((EndPixel - StartPixel) * Math.cos(this._perc * Math.PI / 200));
							break;
						case 'triangle':	//movimento a velocità costante
						default:
							nuovoVal = StartPixel + ((EndPixel - StartPixel) * (this._perc / 100));
					}
					nuovoVal = Math.round(nuovoVal);
					break;
			}
			
			SetProperty(this.animatedHtmlObject, this._attributeName, nuovoVal);
			if (this._perc == 100) {
				window.clearInterval(this._tmr);
				this._currAction = '';
				cont1 = this.currentPage;
				this.currentPage = nuovoVal / this.pageWidth;
				this.OnAfterPageChanged(this, cont1, this.currentPage);
			}
		}
	}
	
	this.GoToPage = function (PageNumber) {
		var nuovaPag = PageNumber;
		var startPx, endPx;
		if (nuovaPag < 0) nuovaPag = 0;
		if (nuovaPag >= this.pages) nuovaPag = this.pages - 1;
		if (this.enabled && (this._currentAction=='' && nuovaPag!=this.currentPage || this._currentAction!='' && nuovaPag!=this._getTemporaryCurrentPage())) {
			this.OnBeforePageChanging(this, this.currentPage, nuovaPag);
			this._setStatusVariables('move', this.transactionTime);
			startPx = toNumber(GetProperty(this.animatedHtmlObject, this._attributeName), 0);
			endPx = this.pageWidth * nuovaPag;
			this._tmr = setInterval('var obj = window.HtmlPlus_PageScrollerColl["' + this.id + '"]; obj._scrollPage(' + startPx.toString() + ', ' + endPx.toString() + ', obj.transactionTime);', 1000 / this.fps);
		}
	}
	this.GoToFirstPage = function () { this.GoToPage(1); }
	this.GoToPreviousPage = function () { this.GoToPage(this.currentPage - 1); }
	this.GoToNextPage = function () { this.GoToPage(this.currentPage + 1); }
	this.GoToLastPage = function () { this.GoToPage(this.pages); }
	
	/* Definizione eventi */
	this.OnAfterPageChanged = function (PageScroller, OldPage, CurrentPage) {return void(0);}
	this.OnBeforePageChanging = function (PageScroller, CurrentPage, NewPage) {return void(0);}
	
	this._initialize();
	return this;
}


function HtmlPlus_TextboxWithLabelInside(IdObject, TextboxObject, ValueObject, LabelString, NullValue, TextboxModeCssStyle, LabelModeCssStyle) {
	this.id = IdObject;
	this.objectType = 'HtmlPlus_TextboxWithLabelInside';
	this.textboxObject = TextboxObject;		//L'oggetto TextBox che mostra la LABEL e dove vengono immessi i dati
	this.valueObject = ValueObject;			//L'oggetto "<input type=hidden" su cui viene memorizzato il valore vero
	this.label = LabelString;				//Il testo da mostrare quando il valore non è indicato
	this.nullValue = NullValue;				//Il valore da salvare quando non vi è un valore inserito
	this.textboxModeCssStyle = TextboxModeCssStyle;		//Lo stile del Textbox quando la modalità è 'textbox' (contiene un valore o ha focus)
	this.labelModeCssStyle = LabelModeCssStyle;			//Lo stile del Textbox quando la modalità è 'label' (non contiene un valore e non ha focus)
	this.currentMode = '';		//Può essere 'label' o 'textbox'. Indica cosa viene mostrato nel textbox e con quale stile.
	this.enabled = true;
	
	if (!window.HtmlPlus_TextboxWithLabelInsideColl) window.HtmlPlus_TextboxWithLabelInsideColl = new Array();
	window.HtmlPlus_TextboxWithLabelInsideColl[this.id] = this;
	
	this._initialize = function () {
		if (!this.textboxObject.TextboxWithLabelInsideObject) {
			this.textboxObject.TextboxWithLabelInsideObject = this;
			addEvent(this.textboxObject, 'focus', function (ev) {
						var eventObj = new STDEvent(ev);
						eventObj.srcElement.TextboxWithLabelInsideObject.OnFocusInHandler();
					}
				);
			addEvent(this.textboxObject, 'blur', function (ev) {
						var eventObj = new STDEvent(ev);
						eventObj.srcElement.TextboxWithLabelInsideObject.OnFocusOutHandler();
					}
				);
			addEvent(this.textboxObject, 'keydown', function (ev) {
						var eventObj = new STDEvent(ev);
						eventObj.srcElement.TextboxWithLabelInsideObject.OnKeyDownHandler(eventObj);
					}
				);
			this.currentMode = '';
			this.SetValue(this.GetValue());
		}
	}
	this.OnFocusInHandler = function () {
		var str1 = this.GetValue();
		if (str1 == '') {
			this.currentMode = 'textbox';
			SetCssStyle(this.textboxObject, this.textboxModeCssStyle);
		}
		this.SetValue(str1);
	}
	this.OnFocusOutHandler = function () {
		var str1 = this.GetValue(true);
		if (str1 == '') {
			this.currentMode = 'label';
			SetCssStyle(this.textboxObject, this.labelModeCssStyle);
		}
		this.SetValue(str1);
	}
	this.OnKeyDownHandler = function (eventObject) {
		if (eventObject.keyCode == 13) {
			this.SetValue(this.GetValue(true));
		}
	}
	this.GetValue = function (GetTextboxValue) {
		//La funzione restituisce il valore REALE del TextBox. Se il valore non è definito, restituisce <stringa-vuota>.
		var str1;
		if (GetTextboxValue) {
			str1 = this.textboxObject.value;
			str1 = ((str1 == this.label || str1 == this.nullValue) ? '' : str1);
		} else {
			str1 = this.valueObject.value;
			str1 = ((str1 == this.nullValue) ? '' : str1);
		}
		return str1;
	}
	this.SetValue = function (NewValue) {
		var str1 = NewValue.toString();
		if (str1 == '') {
			switch (this.currentMode) {
				case 'label':
					this.textboxObject.value = this.label;
					break;
				case 'textbox':
					this.textboxObject.value = '';
					break;
				default:
					this.textboxObject.value = this.label;
					SetCssStyle(this.textboxObject, this.labelModeCssStyle);
					this.currentMode = 'label';
			}
		} else {
			this.textboxObject.value = str1;
			switch (this.currentMode) {
				case 'textbox':
					break;
				default:
					SetCssStyle(this.textboxObject, this.textboxModeCssStyle);
					this.currentMode = 'textbox';
			}
		}
		this.valueObject.value = ((str1 == '') ? this.nullValue : str1);
	}
	
	this._initialize();
	return this;
}

function HtmlPlus_BarcodeReader(IdObject, KeyChars, Action, MinLen, MaxLen, BarcodeConf_PreChar, BarcodeConf_PostChar) {
	this.id = IdObject;
	this.objectType = 'HtmlPlus_BarcodeReader';
	this.keyChars = KeyChars;				//Stringa CHIAVE. Il barcode letto verrà preso in esame solo se inizia con questa
											//stringa (può essere NULL).
	this.action = Action;					//Azione da eseguire quando viene letto un codice a barre; può essere String o Function.
	this.minLen = MinLen;					//(opz) Lunghezza minima del barcode.
	this.maxLen = MaxLen;					//(opz) Lunghezza massima del barcode.
	this.bcCfg_Pre = BarcodeConf_PreChar;	//(opz) Carattere di preambolo. Verrà ritenuto "barcode" solo le battiture a tastiera
											//che iniziano con questo carattere.
	this.bcCfg_Post = BarcodeConf_PostChar;	//(opz) Carattere di postambolo. Verrà ritenuto "barcode" solo le battiture a tastiera
											//che finiscono con questo carattere.
											//ATTENZIONE: i caratteri preambolo e postambolo devono essere gli stessi per tutti gli
											//oggetti [HtmlPlus_BarcodeReader].
	this.timeout = 500;						//Tempo massimo (in millisec) fra ogni pressione di tasto affinchè si possa ritenere
											//che si sta leggendo un "barcode" valido; dopodichè la lettura viene annullata.
	this.runOneAction = true;				//Se TRUE, quando si è letto un Barcode, verrà eseguita l'Azione appartenente al primo
											//oggetto [HtmlPlus_BarcodeReader] compatibile col Barcode letto, in ordine di lunghezza
											//di KeyChars, dal più lungo al più corto.
	
	this._initialize = function () {
		var primoBarcode = false;
		if (!window.HtmlPlus_BarcodeReaderColl) {
			window.HtmlPlus_BarcodeReaderColl = new Array();
			window.HtmlPlus_BarcodeReader__runtime_curKeybStrm = '';
			window.HtmlPlus_BarcodeReader__runtime_tmr = 0;
			primoBarcode = true;
		}
		window.HtmlPlus_BarcodeReaderColl[this.id] = this;
		if (primoBarcode) {
			addEvent(window.document, 'keypress', function(ev) {
						var i, obj;
						for (i in window.HtmlPlus_BarcodeReaderColl) {
							obj = window.HtmlPlus_BarcodeReaderColl[i];
							break;
						}
						obj.DOCUMENT_OnKeyPressHandler(ev);
					}
				);
			if (window.DevelopingMode) DevelopingModeMenu_AddItem('BarcodeReader - Test', 'window.HtmlPlus_BarcodeReaderColl[\'' + CStrJS(this.id) + '\'].DOCUMENT_RunBarcode(window.prompt("[HtmlPlus_BarcodeReader - Test] :  inserisci il codice barcode di cui simulare la lettura:", ""));');
		}
		if (!this.keyChars) this.keyChars = '';
		if (!this.minLen) this.minLen = 1;
		if (!this.bcCfg_Pre) this.bcCfg_Pre = '\x02';
		if (!this.bcCfg_Post) this.bcCfg_Post = '\x04';
	}
	
	this.DOCUMENT_OnKeyPressHandler = function (ev) {
		var eventObj = new STDEvent(ev);
		var i, obj, chrLetto, barcodeLetto;
		var inLettura = false;
		chrLetto = String.fromCharCode(eventObj.keyCode);
		//alert('Ciao, ' + eventObj.keyCode);
		if (window.HtmlPlus_BarcodeReader__runtime_curKeybStrm == '') {
			//Non sono in stato LETTURA.
			if (chrLetto == this.bcCfg_Pre) {
				//Inizio LETTURA.
				window.HtmlPlus_BarcodeReader__runtime_curKeybStrm = this.bcCfg_Pre;
				this.resetTimer();
				inLettura = true;
			}
		} else {
			//Sono già in stato LETTURA, quindi aspetto il carattere di POSTAMBOLO.
			inLettura = true;
			if (window.HtmlPlus_BarcodeReader__runtime_curKeybStrm == this.bcCfg_Pre) window.HtmlPlus_BarcodeReader__runtime_curKeybStrm = '';
			if (chrLetto != this.bcCfg_Post) {
				window.HtmlPlus_BarcodeReader__runtime_curKeybStrm += chrLetto;
			} else {
				//Sono alla fine della lettura.
				this.DOCUMENT_RunBarcode(window.HtmlPlus_BarcodeReader__runtime_curKeybStrm);
			}
		}
		if (inLettura) {
			eventObj.cancelBubble(true);
			eventObj.returnValue(null);
		}
	}
	this.DOCUMENT_RunBarcode = function (BarcodeString) {
		var i, obj;
		if (this.runOneAction) {
			//Cerco l'oggetto [HtmlPlus_BarcodeReader] che ha il parametro KeyChars più lungo
			var maxLenKeyChars = 0;
			var ok;
			for (i in window.HtmlPlus_BarcodeReaderColl) {
				obj = window.HtmlPlus_BarcodeReaderColl[i];
				if (obj.keyChars) {
					if (maxLenKeyChars < obj.keyChars.length) maxLenKeyChars = obj.keyChars.length;
				}
			}
			//Ora sfoglio tutti gli oggetti [HtmlPlus_BarcodeReader] in ordine di lunghezza KeyChars, dal più lungo al più corto
			ok = false;
			for (maxLenKeyChars=maxLenKeyChars; maxLenKeyChars >= 0; maxLenKeyChars--) {
				for (i in window.HtmlPlus_BarcodeReaderColl) {
					obj = window.HtmlPlus_BarcodeReaderColl[i];
					if (maxLenKeyChars == obj.keyChars.length) {
						ok = obj.RunAction(BarcodeString);
						if (ok) break;
					}
				}
				if (ok) break;
			}
		} else {
			for (i in window.HtmlPlus_BarcodeReaderColl) {
				obj = window.HtmlPlus_BarcodeReaderColl[i];
				obj.RunAction(BarcodeString);
			}
		}
	}
	
	this.CheckBarcodeCompatibility = function (BarcodeString) {
		var fReturn = true;
		fReturn = true;
		if (fReturn && this.keyChars) fReturn = ((BarcodeString.substr(0, this.keyChars.length) == this.keyChars) ? true : false);
		if (fReturn && this.minLen) fReturn = ((BarcodeString.length >= this.minLen) ? true : false);
		if (fReturn && this.maxLen) fReturn = ((BarcodeString.length <= this.maxLen) ? true : false);
		return fReturn;
	}
	this.RunAction = function (BarcodeString, CheckBarcodeCompatibility) {
		//Attenzione: se il parametro [CheckBarcodeCompatibility] è omesso, si intenderà TRUE.
		//Restituisce True se l'azione è stata eseguita.
		var ok, str1;
		if (IsFalse(CheckBarcodeCompatibility)) {
			ok = true;
		} else {
			ok = this.CheckBarcodeCompatibility(BarcodeString);
		}
		if (ok) {
			switch (typeof(this.action)) {
				case 'string':
					str1 = this.action;
					str1 = str1.replace(/\[BARCODE]/g, BarcodeString);
					str1 = str1.replace(/\[KEYCHARS]/g, this.keyChars);
					eval(str1);
					break;
				case 'function':
					this.action(BarcodeString, this);
					break;
				default:
					alert('ERRORE in HtmlPlus_BarcodeReader: il parametro ACTION deve essere una function o una string contenente un comando JavaScript.');
					ok = false;
			}
		}
		return ok;
	}
	this.resetTimer = function () {
		if (window.HtmlPlus_BarcodeReader__runtime_tmr) window.clearTimeout(window.HtmlPlus_BarcodeReader__runtime_tmr);
		window.HtmlPlus_BarcodeReader__runtime_tmr = setTimeout('window.HtmlPlus_BarcodeReader__runtime_curKeybStrm = ""; window.HtmlPlus_BarcodeReader__runtime_tmr = 0;', this.timeout);
	}
	
	this._initialize();
	return this;
}




function HtmlPlus_ServerEval(IdObject, Server, Code) {
	this.id = IdObject;
	this.objectType = 'HtmlPlus_ServerEval';
	this.server = Server;				// Può essere ASP oppure ASPX per indicare che deve invocare le pagine standard, oppure un percorso intero per indicare che deve invocare una pagina precisa.
	this.code = Code;					// Il codice da eseguire
	
	if (!window.HtmlPlus_ServerEvalColl) window.HtmlPlus_ServerEvalColl = new Array();
	window.HtmlPlus_ServerEvalColl[this.id] = this;
	
	this._initialize = function(){
		switch (this.server.toLowerCase()) {
			case 'asp':
				this.server = 'asp';
				break;
			case 'aspx':
				this.server = 'aspx';
				break;
			default:
				if (this.server.substr(0, 4) != 'http') this.server = R + this.server;
		}
		
		this._container = null;
		this._container_iFrame = null;
		
		this._parameters = null;
		this._isResponseAvailable = false;
		this._isResponseAbort = null;
		this._returnValue = null;
		this._isRun = false;
		this._generaFrame_onLoad_Eseguito = false;
		
	}
	
	this._generaFrame = function(srParameters) {
		var strJS;
		
		// Inizializzazione del DIV contenitore
		this._container = document.createElement('DIV');
		this._container.id = this.id;
		this._container.style.position = 'absolute';
		this._container.style.overflow = 'hidden';
		this._container.style.zIndex = 10020;
		this._container.style.left = '-110px';	this._container.style.top = '0px';
		this._container.style.width = '500px';	this._container.style.height = '100px';
		this._container.ObjServerEval = this;
		this._container.style.display = 'none';
		document.body.appendChild(this._container);
		
		// Creazione [contenuto] del DIV
		this._container_iFrame = document.createElement('IFRAME');
		this._container.appendChild(this._container_iFrame);
		switch (this.server) {
			case 'asp':
				this._container_iFrame.src = R + '_Include/AspResponder.asp?cli=Brw';
				break;
			case 'aspx':
				this._container_iFrame.src = R + '_Include/AspxResponder.aspx?cli=Brw';
				break;
			default:
				this._container_iFrame.src = this.server;
		}
		
		this._generaFrame_onLoad_Eseguito = false;
		strJS = 'addEvent(this._container_iFrame, \'load\', function(ev) {' + 
						'var eventObj = new STDEvent(ev);' +
						'eval(\'' + CStrJS('window.HtmlPlus_ServerEvalColl[\'' + CStrJS(this.id) + '\']._generaFrame_onLoad(\'' + CStrJS(srParameters) + '\');') + '\');' + 
					'}' +
				');';
		eval(strJS);
	}
	
	this._generaFrame_onLoad = function(srParameters) {
		strJS = 'window.HtmlPlus_ServerEvalColl[\'' + CStrJS(this.id) + '\']._container_iFrame.contentWindow.Interface_HtmlPlus_ServerEval_OnSubmit = function (ReturnSerializedValue, IsAbort) {' +
					'window.HtmlPlus_ServerEvalColl[\'' + CStrJS(this.id) + '\'].End(DeserializeValue(ReturnSerializedValue), IsAbort);' +
				'}';
		eval(strJS);
		if (!this._generaFrame_onLoad_Eseguito) {
			this._container_iFrame.contentWindow.Interface_HtmlPlus_ServerEval_OnLoad(this.code, srParameters);
			this._generaFrame_onLoad_Eseguito = true;
		}
		this.OnRun(this);
	}
	
	this.Run = function(Parameters) {
		//Lancia il comando server. Argomenti:
		//	Parameters :		array in stile "Dictionary" con la lista degli parametri da passare al server.
		if (this.IsRun()) {
			return false;
		} else {
			this._parameters = Parameters;
			this._isResponseAvailable = false;
			this._isResponseAbort = null;
			this._returnValue = null;
			this._isRun = true;
			
			//Generazione oggetti HTML e passaggio argomento [Parameters]
			if (!this._container) {
				this._generaFrame(SerializeValue(Parameters));
			} else {
				this._container_iFrame.contentWindow.Interface_HtmlPlus_ServerEval_OnLoad(this.code, SerializeValue(Parameters));
				this.OnRun(this);
			}
			
			return true;
		}
	}
	this.Break = function() {
		//Termina il comando server e setta l'esito in ABORT.
		if (this.IsRun()) {
			this._isRun = false;
			this._isResponseAvailable = true;
			this._isResponseAbort = true;
			this._returnValue = null;
			
			this.OnEnd(this, this._returnValue, this._isResponseAbort);
			return true;
		} else {
			return false;
		}
	}
	this.End = function(ReturnValue, IsAbort) {
		//Chiude il comando server, ed imposta sia il [Valore] da restituire sia lo stato [IsAbort].
		if (this.IsRun()) {
			this._isRun = false;
			this._isResponseAvailable = true;
			this._isResponseAbort = ((IsAbort) ? true : false);
			this._returnValue = ReturnValue;
			
			this.OnEnd(this, this._returnValue, this._isResponseAbort);
			return true;
		} else {
			return false;
		}
	}
	this.Parameters = function() {
		return this._parameters;
	}

	this.IsRun = function() {
		return this._isRun;
	}
	this.IsResponseAvailable = function() {
		return this._isResponseAvailable;
	}
	this.IsResponseAbort = function() {
		return ((this._isResponseAvailable) ? this._isResponseAbort : null);
	}
	this.ReturnValue = function() {
		return ((this._isResponseAvailable) ? this._returnValue : null);
	}
	
	/* Definizione eventi */
	this.OnRun = function (ServerEval) {return void(0);}							//Invocata quando il metodo Run viene lanciato
	this.OnEnd = function (ServerEval, ReturnValue, IsAbort) {return void(0);}		//Invocata quando il Popup viene chiuso
	
	this._initialize();
	return this;
}



function HtmlPlus_Popup(IdObject, Title, Src, PopupWidth, PopupHeight, ContentWidth, ContentHeight, CssPrefix) {
	this.id = IdObject;
	this.objectType = 'HtmlPlus_Popup';
	this.cssPrefix = CssPrefix;			// Prefisso che serve per l'utilizzazione delle classi Css da utilizzare
	this.lblTitle = Title;				// E' il titolo della finestra
	this.lblClose = 'X';				// E' il testo del pulsante di chiusura
	this.src = Src;						// Può essere un percorso, o un testo HTML
	this.popupWidth = PopupWidth;		// Larghezza del contenitore
	this.popupHeight = PopupHeight;		// Larghezza del contenitore
	this.contentWidth = ContentWidth;	// Larghezza del contenitore
	this.contentHeight = ContentHeight;	// Altezza del contenitore
	this.container = null;				// contenitore Popup
	this.container_content = null;		// contenuto del Popup
	this.isModal = false;				// è TRUE se il Popup viene aperto in modalità Modale
	this.popupShadowWidth = 8;			// dimensione dell'ombra (sfasamento rispetto alla posizione del Popup)
	this.popupShadowValue = 25;			// opacità  del Div che disegna l'ombra
	
	/*	####    DETTAGLI SULL'ARGOMENTO [Src] :    ####
		L'argomento può essere un percorso URL o un testo HTML. La classe [HtmlPlus_Popup] interpreta l'argomento come HTML se vi trova il
		carattere "<", altrimenti sarà interpretato come percorso URL.
		Se viene interpetato come percorso URL la classe genererà un IFRAME nel popup, con l'argomento SRC dell'IFRAME settato con l'Src indicato.
		La pagina che viene aperta può ospitare 3 variabili JavaScript:
			window.Interface_HtmlPlus_Popup_OnLoad :
				(function) viene invocata dalla classe [HtmlPlus_Popup] alla fine del caricamento e generazione del popup. Gli argomenti sono:
					SendSerializedArgument :	è l'argomento SendArgument passato alla funzione HtmlPlus_Popup.Open, serializzato.
			window.Interface_HtmlPlus_Popup_OnSubmit
				(function) dev'essere invicata dalla pagina dell'IFRAME per chiudere il Popup. Gli argomenti sono:
					ReturnSerializedValue :		dev'essere riempito con l'argomento che si vuole restituire, serializzato;
					IsAbort :					dev'esssere settato a TRUE se è stato invocato un "Annulla", altrimenti FALSE.
			window.Interface_HtmlPlus_Popup_This
				(object) punta all'istanza HtmlPlus_Popup corrente. E' utile per invocare metodi come [SetTitle], per cambiare il titolo del popup,
				ma è anche utilizzabile per invocare il metodo [Close] al posto di [Interface_HtmlPlus_Popup_OnSubmit].
	*/
	
	if (!window.HtmlPlus_PopupColl) window.HtmlPlus_PopupColl = new Array();
	window.HtmlPlus_PopupColl[this.id] = this;
	
	this._initialize = function(){
		this._divContenuto2 = null;
		this._divOmbra = null;
		this._divModal = null;
		this._modal_resizeTmr = null;
		this._popupTmr = null;
		this._clipAppearance = null;
		
		this._isResponseAvailable = false;
		this._isResponseAbort = null;
		this._returnValue = null;
		this._isOpen = false;
		this._generaPopup_iFrame_onLoad_EseguitoPrimo = false;
		this._generaPopup_iFrame_onLoad_EseguitoInOpen = false;
		
		this.popupWidth = toNumber(this.popupWidth, null, false);
		this.popupHeight = toNumber(this.popupHeight, null, false);
		this.contentWidth = toNumber(this.contentWidth, null, false);
		this.contentHeight = toNumber(this.contentHeight, null, false);
		if (!this.cssPrefix) this.cssPrefix = 'Def';
	}
	
	this._generaPopup = function(SendArgument) {
		var strJS;
		
		// Inizializzazione del DIV contenitore del Popup
		this.container = document.createElement('DIV');
		this.container.id = this.id;
		this.container.style.position = 'absolute';
		this.container.style.overflow = 'hidden';
		this.container.style.zIndex = 10010;
		if (this.popupWidth) this.container.style.width = this.popupWidth.toString() + 'px';
		if (this.popupHeight) this.container.style.height = this.popupHeight.toString() + 'px';
		this.container.className = this.cssPrefix + '_Popup_Container';
		this.container.ObjPopup = this;
		this.container.style.display = 'none';
		document.body.appendChild(this.container);
		
		this._divOmbra = document.createElement('DIV');
		this._divOmbra.style.position = 'absolute';
		this._divOmbra.style.zIndex = 10009;
		if (this.popupWidth) this._divOmbra.style.width = this.popupWidth.toString() + 'px';
		if (this.popupHeight) this._divOmbra.style.height = this.popupHeight.toString() + 'px';
		this._divOmbra.className = this.cssPrefix + '_Popup_Container_Shadow';
		this._divOmbra.style.display = 'none';
		document.body.appendChild(this._divOmbra);
		SetProperty(this._divOmbra, 'opacity', this.popupShadowValue);
		
		this._divModal = document.createElement('DIV');
		this._divModal.style.position = 'absolute';
		this._divModal.style.left = '0px';
		this._divModal.style.top = '0px';
		this._divModal.style.zIndex = 10005;
		//alert(window.document.body.offsetWidth);
		//this._divModal.style.height = window.dialogHeight;
		this._divModal.className = this.cssPrefix + '_Popup_Container_BgModal';
		this._divModal.style.display = 'none';
		document.body.appendChild(this._divModal);
		SetProperty(this._divModal, 'opacity', 25);
		strJS = 'addEvent(window, \'resize\', function(ev) {' + 
						'var eventObj = new STDEvent(ev); var obj1;' +
						'eval(\'' + CStrJS('obj1 = window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\'];') + '\');' + 
						'obj1._generaPopup_divModal_window_onResize();' +
					'}' +
				');';
		eval(strJS);
		
		
		this.container.innerHTML = '' +
				'<div class="' + this.cssPrefix + '_Popup_Container2">' +
					'<div class="' + this.cssPrefix + '_Popup_TitleBar">' +
						'<table class="' + this.cssPrefix + '_Popup_TitleBar_Table" cellpadding=0 cellspacing=0 border=0 width="100%">' +
							'<tr>' +
								'<td class="' + this.cssPrefix + '_Popup_TitleBar_Title" id="' + this.container.id + '_TdTitle">' + CStrHTML(this.lblTitle) + '</td>' +
								'<td class="' + this.cssPrefix + '_Popup_TitleBar_CmdAbort">' +
									'<a href="javascript:void(0);" onclick="window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\'].Close(null, true);" title="Close">' +
										CStrHTML(this.lblClose) +
									'</a>' +
								'</td>' +
							'</tr>' +
						'</table>' +
					'</div>' +
					'<div class="' + this.cssPrefix + '_Popup_Content" id="' + HTMLEncode(this.id) + '_Popup_Content"></div>' +
				'</div>';
		
		this.container_content = document.createElement((this.src.substr(0, 1) == '<') ? 'DIV' : 'IFRAME');
		this._divContenuto2 = findObj(this.id + '_Popup_Content');
		this._divContenuto2.appendChild(this.container_content);
		// Creazione [contenuto] del popup
		switch (this.container_content.tagName) {
			case 'DIV':
				this.container_content.innerHTML = this.src;
				this._generaPopup_iFrame_onLoad(SerializeValue(SendArgument));
				break;
			case 'IFRAME':
				this.container_content.src = this.src;
				SetProperty(this.container_content, 'frameborder', '0');
				SetProperty(this.container_content, 'marginwidth', '0');
				SetProperty(this.container_content, 'marginheight', '0');
				SetProperty(this.container_content, 'scrolling', 'no');
				
				this._generaPopup_iFrame_onLoad_EseguitoPrimo = false;
				strJS = 'addEvent(this.container_content, \'load\', function(ev) {' + 
								'var eventObj = new STDEvent(ev);' +
								'eval(\'' + CStrJS('window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\']._generaPopup_iFrame_onLoad(\'' + SerializeValue(SendArgument) + '\');') + '\');' + 
							'}' +
						');';
				eval(strJS);
				break;
		}
		if (this.contentWidth) this.container_content.style.width = this.contentWidth.toString() + 'px';
		if (this.contentHeight) this.container_content.style.height = this.contentHeight.toString() + 'px';
		this.container_content.style.overflow = 'hidden';
	}
	this._posizionaPopup = function(Left, Top) {
		this.container.style.left = Left.toString() + 'px';
		this.container.style.top = Top.toString() + 'px';
		this._divOmbra.style.left = (Left + this.popupShadowWidth).toString() + 'px';
		this._divOmbra.style.top = (Top + this.popupShadowWidth).toString() + 'px';
	}
	
	this._generaPopup_iFrame_onLoad = function(SendSerializedArgument) {
		if (this.container_content.tagName == 'IFRAME') {
			this.container_content.contentWindow.Interface_HtmlPlus_Popup_This = this;
			eval('window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\'].container_content.contentWindow.Interface_HtmlPlus_Popup_OnSubmit = function (ReturnSerializedValue, IsAbort) {' +
						'window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\'].Close(DeserializeValue(ReturnSerializedValue), IsAbort);' +
					'}');
			if (!this._generaPopup_iFrame_onLoad_EseguitoInOpen) this.OnLoad(this);
			if (!this._generaPopup_iFrame_onLoad_EseguitoPrimo) {
				this.container_content.contentWindow.Interface_HtmlPlus_Popup_OnLoad(SendSerializedArgument);
				this._generaPopup_iFrame_onLoad_EseguitoPrimo = true;
			}
		} else {
			if (!this._generaPopup_iFrame_onLoad_EseguitoInOpen) this.OnLoad(this);
		}
		if (!this._generaPopup_iFrame_onLoad_EseguitoInOpen) this.OnOpen(this);
		this._generaPopup_iFrame_onLoad_EseguitoInOpen = true;
	}
	this._generaPopup_divModal_ridimensiona = function() {
		this._divModal.style.width = Math.max(window.document.body.scrollWidth, window.document.body.clientWidth);
		this._divModal.style.height = Math.max(window.document.body.scrollHeight, window.document.body.clientHeight);
	}
	this._generaPopup_divModal_window_onResize = function(ev) {
		if (this.isModal && this.IsOpen()) {
			if (this._divModal.style.display != 'none') this._divModal.style.display = 'none';
			if (this._modal_resizeTmr) clearTimeout(this._modal_resizeTmr);
			this._modal_resizeTmr = setTimeout('window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\']._generaPopup_divModal_window_onResize_timer();', 300);
		}
	}
	this._generaPopup_divModal_window_onResize_timer = function() {
		if (this.isModal && this._divModal.style.display == 'none') {
			this._generaPopup_divModal_ridimensiona();
			this._divModal.style.display = 'block';
		}
	}
	
	this.Open = function(SendArgument, Left, Top, IsModal, Timer, AppearanceType, AppearanceTime) {
		//Argomenti:
		//	SendArgument :		l'argomento che si vuole passare all'IFRAME del popup, attraverso la procedura "Interface_HtmlPlus_Popup_OnLoad".
		//	Left, Top :			la posizione del Popup
		//	IsModal :			se True, la finestra sarà bloccata finchè non si chiude il Popup
		//	AppearanceType :	modalità con cui il popup apparirà; può essere: 0=none(default); 1=zoom; 2=fromLeft; 3=fromTop; <objClip>=verrà usato tale oggetto per gestire l'apparizione del Popup.
		//	AppearanceTime :	durata, in secondi, di apparizione del popup (se modalità è diverso da 0); default = 0.6 sec.
		var appearanceType, appearanceTime;
		var posX, posY;
		if (this.IsOpen()) {
			return false;
		} else {
			//Setting valori
			this._isResponseAvailable = false;
			this._isResponseAbort = null;
			this._returnValue = null;
			this._isOpen = true;
			this.isModal = ((IsModal) ? true : false);
			if (this._popupTmr) clearTimeout(this._popupTmr);
			posX = Left;
			switch (ValueType(posX)) {
				case 'string':
					//Il valore [posX] è espresso in PERCENTUALE. Ciò significa che posizionerò il popup in base alla dimensione della finestra.
					if (posX.charAt(posX.length - 1) != '%') posX = '50%';
					posX = (Math.min(window.document.body.scrollWidth, window.document.body.clientWidth) - this.popupWidth) * posX.substr(0, posX.length - 1) / 100 + window.document.body.scrollLeft;
					break;
				case 'number':
					if (posX > 0) {		//Posizionamento da sinistra
						posX = posX + window.document.body.scrollLeft;
					} else {			//Posizionamento da destra
						posX = Math.min(window.document.body.scrollWidth, window.document.body.clientWidth) - this.popupWidth + posX + window.document.body.scrollLeft;
					}
					break;
				default:
					posX = 10;
			}
			if (posX < 10) posX = 10;
			posY = Top;
			switch (ValueType(posY)) {
				case 'string':
					//Il valore [posY] è espresso in PERCENTUALE. Ciò significa che posizionerò il popup in base alla dimensione della finestra.
					if (posY.charAt(posY.length - 1) != '%') posY = '50%';
					posY = (Math.min(window.document.body.scrollHeight, window.document.body.clientHeight) - this.popupHeight) * posY.substr(0, posY.length - 1) / 100 + window.document.body.scrollTop;
					break;
				case 'number':
					if (posY > 0) {		//Posizionamento dall'alto
						posY = posY + window.document.body.scrollTop;
					} else {			//Posizionamento dal basso
						posY = Math.min(window.document.body.scrollHeight, window.document.body.clientHeight) - this.popupHeight + posY + window.document.body.scrollTop;
					}
					break;
				default:
					posY = 10;
			}
			if (posY < 10) posY = 10;
			
			//Generazione oggetti HTML e passaggio argomento [SendArgument]
			this._generaPopup_iFrame_onLoad_EseguitoInOpen = false;
			if (!this.container) {
				this._generaPopup(SendArgument);
				this._posizionaPopup(posX, posY);
			} else {
				if (!IsUndefined(SendArgument) && this.container_content.tagName == 'IFRAME') {
					this.container_content.contentWindow.Interface_HtmlPlus_Popup_OnLoad(SerializeValue(SendArgument));
				}
				this._posizionaPopup(posX, posY);
				this.OnOpen(this);
			}
			if (this.isModal) {
				this._generaPopup_divModal_ridimensiona();
				this._divModal.style.display = 'block';
			}
			
			//Gestione della modalità di APPARENZA del POPUP.
			if (AppearanceType.objectType == 'HtmlPlus_ClipMaker') {
				this._clipAppearance = AppearanceType;
			} else {
				appearanceTime = ((AppearanceTime) ? AppearanceTime : 0.6);
				switch (AppearanceType) {
					case 1: case 2: case 3:
						this._clipAppearance = new HtmlPlus_ClipMaker('Popup_' + this.id + '_appearance', appearanceTime);
						appearanceType = AppearanceType;
						break;
					default:
						this._clipAppearance = null;
						appearanceType = 0;
				}
				switch (appearanceType) {
					case 0:
						break;
					case 1:
						this._clipAppearance.AppendMotion(this.container, 'opacity', '', 0, 100, 0, 100, 'sin');
						this._clipAppearance.AppendMotion(this._divOmbra, 'opacity', '', 0, 100, 0, this.popupShadowValue, 'sin');
						this._clipAppearance.AppendMotion(this._divOmbra, 'opacity', '', 0, 100, 0, 100, 'sin');
						this._clipAppearance.AppendMotion(this._divOmbra, 'zoom', '', 0, 100, 0.6, 1, 'sin');
						break;
					case 2:
						this._clipAppearance.AppendMotion(this.container, 'left', 'px', 0, 100, -this.popupWidth - this.popupShadowWidth, posX, 'sin');
						this._clipAppearance.AppendMotion(this._divOmbra, 'left', 'px', 0, 100, -this.popupWidth, posX + this.popupShadowWidth, 'sin');
						break;
					case 3:
						this._clipAppearance.AppendMotion(this.container, 'top', 'px', 0, 100, -this.popupHeight - this.popupShadowWidth, posY, 'sin');
						this._clipAppearance.AppendMotion(this._divOmbra, 'top', 'px', 0, 100, -this.popupHeight, posY + this.popupShadowWidth, 'sin');
						break;
					default:
						
				}
			}
			if (this._clipAppearance) {
				this._clipAppearance.AppendEvent(1, '' +
						'var obj1 = window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\'];' +
						'obj1.container.style.display = \'block\';' +
						'obj1._divOmbra.style.display = \'block\';' +
						'');
				if (Timer > 0) this._clipAppearance.AppendEvent(100, 'window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\']._popupTmr = setTimeout(\'' + CStrJS('window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\'].Close(null, true);') + '\', ' + (Timer * 1000) + ');');
				this._clipAppearance.Play();
			} else {
				this.container.style.display = 'block';
				this._divOmbra.style.display = 'block';
				if (Timer > 0) this._popupTmr = setTimeout('window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\'].Close(null, true);', Timer * 1000);
			}
			return true;
		}
	}
	this.Close = function(ReturnValue, IsAbort) {
		//Chiude il Popup, ed imposta sia il [Valore] da restituire sia lo stato [IsAbort].
		if (this.IsOpen()) {
			this.container.style.display = 'none';
			this._divOmbra.style.display = 'none';
			this._divModal.style.display = 'none';
			if (this._popupTmr) clearTimeout(this._popupTmr);
			//document.body.removeChild(this.container);
			this._isOpen = false;
			this._isResponseAvailable = true;
			this._isResponseAbort = IsAbort;
			this._returnValue = ReturnValue;
			
			this.OnClose(this, ReturnValue, IsAbort);
			return true;
		} else {
			return false;
		}
	}
	this.SetTitle = function(htmlValue) {
		findObj(this.container.id + '_TdTitle').innerHTML = htmlValue;
	}

	this.IsOpen = function() {
		return this._isOpen;
	}
	this.IsResponseAvailable = function() {
		return this._isResponseAvailable;
	}
	this.IsResponseAbort = function() {
		return ((this._isResponseAvailable) ? this._isResponseAbort : null);
	}
	this.ReturnValue = function() {
		return ((this._isResponseAvailable) ? this._returnValue : null);
	}
	
	/* Definizione eventi */
	this.OnLoad = function (Popup) {return void(0);}							//Invocata quando il Popup è stato generato o riaperto
	this.OnOpen = function (Popup) {return void(0);}							//Invocata quando il metodo Open viene eseguito con successo
	this.OnClose = function (Popup, ReturnValue, IsAbort) {return void(0);}		//Invocata quando il Popup viene chiuso
	
	this._initialize();
	return this;
}



function HtmlPlus_Grid(ID, AllowSelect1, AllowSelect2, AllowSelect3) {
	this.id = ID;
	this.objectType = 'HtmlPlus_Grid';
	this.jsOpenRecord = null;
	this.jsEditRecord = null;
	//this.allowOpenRecord = ((OpenRecord_JSFunction) ? true : false);
	this.allowSelect = new Array();
	
	if (!window.HtmlPlus_GridColl) window.HtmlPlus_GridColl = new Array();
	window.HtmlPlus_GridColl[this.id] = this;
	
	this._initialize = function(){
		var cont1, cont2;
		this._maxSelectVal = 3;
		this.allowSelect[1] = ((AllowSelect1) ? true : false);
		this.allowSelect[2] = ((AllowSelect2) ? true : false);
		this.allowSelect[3] = ((AllowSelect3) ? true : false);
		
		this._allowSelectList = new Array();
		cont2 = 0;
		this._allowSelectList[cont2] = 0;
		for (cont1=1; cont1<=this._maxSelectVal; cont1++) {
			if (this.allowSelect[cont1]) {cont2++; this._allowSelectList[cont2] = cont1;}
		}
	}
	this.TrEvents_OpenRecord = function(TrObj) {
		var trInfo, fatto = false;
		if (TrObj.tagName == 'TR') {
			trInfo = this._getRecordInfo(TrObj.id);
		} else if (ValueType(TrObj) == 'Array') {
			trInfo = TrObj;
		}
		if (this.jsOpenRecord && trInfo) {
			if (ValueType(this.jsOpenRecord) == 'string') {
				eval(this.jsOpenRecord + '(window.HtmlPlus_GridColl[\'' + CStrJS(this.id) + '\'], \'' + CStrJS(trInfo['type']) + '\', \'' + CStrJS(trInfo['id']) + '\');');
			} else {
				this.jsOpenRecord(this, trInfo['type'], trInfo['id']);
			}
			fatto = true;
		} else if (this.jsEditRecord) {
			fatto = this.TrEvents_EditRecord(TrObj, ((trInfo['id']=='new')? 'gotonew' : 'goto'));
		}
		if (fatto) {
			this.SetTrViewed(TrObj, true, true);
		}
		return fatto;
	}
	this.TrEvents_EditRecord = function(TrObj, CommandName) {
		var trInfo = null;
		if (TrObj.tagName == 'TR') {
			trInfo = this._getRecordInfo(TrObj.id);
		} else if (ValueType(TrObj) == 'Array') {
			trInfo = TrObj;
		}
		if (this.jsEditRecord && trInfo) {
			if (ValueType(this.jsEditRecord) == 'string') {
				eval(this.jsEditRecord + '(window.HtmlPlus_GridColl[\'' + CStrJS(this.id) + '\'], \'' + CStrJS(trInfo['type']) + '\', \'' + CStrJS(trInfo['id']) + '\', \'' + CStrJS(CommandName) + '\');');
			} else {
				this.jsEditRecord(this, trInfo['type'], trInfo['id'], CommandName);
			}
			return true;
		} else {
			return false;
		}
	}
	this.TrEvents_OnMouseOver = function(TrObj) {
		var primoTr = this._getFirstObj(TrObj.id);
		var str1, valSelect;
		valSelect = primoTr.HtmlPlus_Grid__selected;
		if (!valSelect) valSelect = 0;
		str1 = this._getClassName(valSelect, (primoTr.HtmlPlus_Grid__viewed==1));
		switch (valSelect) {
			case 0:
				this._setClass(primoTr, str1, true, true, false);
				break;
			default:
				this._setClass(primoTr, str1, true, true, false);
				break;
		}
	}
	this.TrEvents_OnMouseOut = function(TrObj) {
		var primoTr = this._getFirstObj(TrObj.id);
		var str1, valSelect;
		valSelect = primoTr.HtmlPlus_Grid__selected;
		if (!valSelect) valSelect = 0;
		str1 = this._getClassName(valSelect, (primoTr.HtmlPlus_Grid__viewed==1));
		switch (valSelect) {
			case 0:
				this._setClass(primoTr, str1, false, false, false);
				break;
			default:
				this._setClass(primoTr, str1, false, false, false);
				break;
		}
	}
	this.TrEvents_OnMouseDown = function(TrObj) {
		var valSelect;
		switch (window.event.button) {
			case 1:
				break;
			case 2:
				var primoTr = this._getFirstObj(TrObj.id);
				valSelect = primoTr.HtmlPlus_Grid__selected;
				if (!valSelect) valSelect = 0;
				valSelect += 1;
				if (this._allowSelectList.length <= valSelect) valSelect = 0;
				this.SetTrSelect(TrObj, valSelect, true);
				break;
		}
	}
	this.SetTrViewed = function(TrObj, Value, optIsOver) {
		var primoTr;
		primoTr = this._getFirstObj(TrObj.id);
		primoTr.HtmlPlus_Grid__viewed = ((Value) ? 1 : 0);
		this._setClass(primoTr, this._getClassName(0, true), ((optIsOver)?true:false), ((Value)?true:false), ((Value)?false:true));
		
	}
	this.SetTrSelect = function(TrObj, Value, optIsOver) {
		var cont1, str1, valSelect;
		var primoTr = this._getFirstObj(TrObj.id);
		valSelect = Value;
		if (valSelect >= 0 && valSelect < this._allowSelectList.length) {
			for (cont1=0; cont1<this._allowSelectList.length; cont1++) {
				str1 = this._getClassName(cont1, (primoTr.HtmlPlus_Grid__viewed==1));
				if (cont1==0) {
					this._setClass(primoTr, str1, (valSelect==cont1 && optIsOver), false, false);
				} else {
					this._setClass(primoTr, str1, (valSelect==cont1 && optIsOver), (valSelect==cont1), (valSelect!=cont1));
				}
			}
			primoTr.HtmlPlus_Grid__selected = valSelect;
		}
	}
	this._getFirstObj = function(ID) {
		return document.getElementById(ID);
	}
	this._getRecordInfo = function(ID) {
		var fReturn, vett1;
		vett1 = ID.split('.');
		fReturn = new Object();
		if (vett1.length == 4) {
			fReturn['col'] = vett1[1];
			fReturn['type'] = vett1[2];
			fReturn['id'] = vett1[3];
		} else {
			fReturn['col'] = null;
			fReturn['type'] = null;
			fReturn['id'] = null;
		}
		return fReturn;
	}
	this._getClassName = function(SelectValue, IsViewed) {
		if (SelectValue == 0) {
			if (IsViewed) {
				return 'Viewed';
			} else {
				return 'Link';
			}
		} else {
			return 'Sel' + SelectValue.toString();
		}
	}
	this._setClass = function(TrObj, ClassName, IsHover, Add, Remove) {
		var trInfo = this._getRecordInfo(TrObj.id);
		var esisteX, vett1, cont1, nuovoClass, trovato;
		if (trInfo) {
			esisteX = (trInfo['col'] == 'X');
			if (esisteX) {
				if (Remove) {
					nuovoClass = '';
				} else {
					nuovoClass = ClassName + ((IsHover) ? '_Hover' : '');
				}
				vett1 = TrObj.className.split(' ');
				trovato = false;
				for (cont1 in vett1) {
					if (vett1[cont1] == ClassName || vett1[cont1] == ClassName + '_Hover') {
						vett1[cont1] = nuovoClass;
						trovato = true;
					}
				}
				if (!trovato && Add) vett1[vett1.length] = nuovoClass;
				TrObj.className = vett1.join(' ').replace('  ', ' ');
			} else {
				//Non esiste la colonna tipo X ma le colonne tipo A e B.
			}
		}
	}
	
	this._initialize();
	return this;
}


function OggettiRif_DlgFind(OggettoRifCode, SqlFilter, CFG) {
	var fReturn, parametri;
	var idObj = 'ObjRifPopUp' + ';' + OggettoRifCode + ';' + SqlFilter ;
	var TxtSearchValue = '';
	
	parametri = '?ObjRifCode=' + OggettoRifCode;
	parametri += '&SqlFilter=' + ((SqlFilter)? CStrUrlParam(SqlFilter) : '');
	if (window.HtmlPlus_PopupColl) {
		if (window.HtmlPlus_PopupColl[idObj]) fReturn = HtmlPlus_PopupColl[idObj];
	}
	if (!fReturn) {
		fReturn = new HtmlPlus_Popup(idObj, 'Ricerca [Oggetto rif.]', R + 'WebAdmin/DevTools_OggettiRif_DlgFind.asp' + parametri, 420, 318, 420, 300, '');
	}
	if (CFG['fncOnClose']) {
		if (CFG['fncOnOpen']) eval('fReturn.OnOpen = function() {' + CFG['fncOnOpen'] + '(DeserializeValue(\'' + CStrJS(SerializeValue(CFG)) + '\'));}');
		fReturn.OnClose = CFG['fncOnClose'];
		fReturn.Open(TxtSearchValue, '50%', '30%', true, 0, 0, 0);
	}
	return fReturn;
}


//###################################
//####  Funzioni di MACRO MEDIA  ####
//###################################

function MM_displayStatusMsg(msgStr)  { //v3.0
	status=msgStr; document.MM_returnValue = true;
}

function MM_findObj(n, d) { //v3.0
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document); return x;
}
function MM_swapImage() { //v3.0
  var i,j=0,x,a=MM_swapImage.arguments; document.MM_sr=new Array; for(i=0;i<(a.length-2);i+=3)
   if ((x=MM_findObj(a[i]))!=null){document.MM_sr[j++]=x; if(!x.oSrc) x.oSrc=x.src; x.src=a[i+2];}
}
function MM_swapImgRestore() { //v3.0
  var i,x,a=document.MM_sr; for(i=0;a&&i<a.length&&(x=a[i])&&x.oSrc;i++) x.src=x.oSrc;
}

function MM_preloadImages() { //v3.0
 var d=document; if(d.images){ if(!d.MM_p) d.MM_p=new Array();
   var i,j=d.MM_p.length,a=MM_preloadImages.arguments; for(i=0; i<a.length; i++)
   if (a[i].indexOf("#")!=0){ d.MM_p[j]=new Image; d.MM_p[j++].src=a[i];}}
}


function MM_reloadPage(init) {  //reloads the window if Nav4 resized
  if (init==true) with (navigator) {if ((appName=="Netscape")&&(parseInt(appVersion)==4)) {
    document.MM_pgW=innerWidth; document.MM_pgH=innerHeight; onresize=MM_reloadPage; }}
  else if (innerWidth!=document.MM_pgW || innerHeight!=document.MM_pgH) location.reload();
}
MM_reloadPage(true);



//##################################
//####	SoundPlayerClass		####
//##################################

function SoundPlayerClass(idObject) {
	this.id = idObject;
	this.objectType = 'SoundPlayer';
	this.PlayList = new Array();
	this.ObjCon = null;
	
	this.preLoad = function () {
		var i, objHtml, str1;
		if (!ver4) return;
		if (NS) {
			objHtml = new Layer(0,window);
		} else {
			document.body.insertAdjacentHTML('BeforeEnd', '<DIV ID="SoundPlayer_Div' + this.id + '" STYLE="position:absolute;"></DIV>');
			objHtml = findObj('SoundPlayer_Div' + this.id);
		}
		str1 = '';
		for (i in this.PlayList) {
			str1 += '<EMBED SRC="' + this.PlayList[i] + '" AUTOSTART="FALSE" HIDDEN="TRUE"></EMBED>';
		}
		if (IE) {
			objHtml.innerHTML = str1;
		} else {
			objHtml.document.open();
			objHtml.document.write(str1);
			objHtml.document.close();
		}
		if (IE) {
			this.ObjCon = document.createElement('<bgsound id="SoundPlayer_Tag' + this.id + '" volume="0" balance="0"></bgsound>');
			findObj('body').appendChild(this.ObjCon);
		} else {
			this.ObjCon = objHtml;
		}
		this.ObjCon.makeAction = function (index, play, fileName, vol, leftRight) {
			//vol:			è il volume da applicare. Deve essere fra 0 (silenzio) a +100 (volume max).
			//leftRight:	è il bilanciamento. Da -100 (canale L) a +100 (canale R).
			if (IE) {
				//if (vol) this.volume = 10000 * (vol / 100 - 1);		//Conversione lineare
				if (vol==0) {
					this.volume = -10000;
				} else {
					if (vol) this.volume = Math.log(vol / 100) * 2167;
				}
				if (leftRight==0) {
					this.balance = 0;
				} else {
					/*if (leftRight) {
						if (leftRight > 0) {
							this.balance = -Math.log(leftRight / 100) * 216;//* 2167;
						} else {
							this.balance = Math.log(-leftRight / 100) * 216; //* 2167;
						}
					}*/
					if (leftRight) this.balance = 10000 * (leftRight / 100);
				}
				this.src = play? fileName : '';
			} else {
				if (vol) eval('this.document.embeds[index].volume = ' + vol);	//Volume va da 0 a 100
				eval('this.document.embeds[index].' + (play? 'play()':'stop()'));
			}
		}
	}
	this.Play = function (index, volume, balance) {
		if (!this.ObjCon) this.preLoad();
		if (this.ObjCon) this.ObjCon.makeAction(index, true, this.PlayList[index], volume, balance);
	}
	this.Stop = function (index) {
		if (!this.ObjCon) this.preLoad();
		if (this.ObjCon) this.ObjCon.makeAction(index, false);
	}
}



//##################################
//####	UrlParserClass			####
//##################################

function UrlParserClass(UrlString) {
	this.objectType = 'UrlParserClass';
	this.Url = Trim(UrlString.toString());
	this.z_existsProtocol = null;
	this.z_protocol = null;
	this.z_domain = null;
	this.z_fullRequest = null;
	this.z_fullPath = null;
	this.z_path = null;
	this.z_fileName = null;
	this.z_parametersString = null;
	this.z_parameters = null;
	
	this.ExistsProtocol = function() {
		if (this.z_existsProtocol === null) this.z_existsProtocol = this.RecalcExistsProtocol();
		return this.z_existsProtocol;
	}
	this.GetPartialUrl = function(WithProtocol, WithDomain, WithPath, WithFileName, WithParametersString) {
		//ATTENZIONE: al momento funziona solo per protocolli HTTP e HTTPS
		var fReturn = '';
		switch (this.GetProtocol()) {
			case 'http':
			case 'https':
				if (WithProtocol) {
					fReturn += this.GetProtocol();
					if (WithDomain || WithPath || WithFileName) fReturn += '://';
				}
				if (WithDomain) {
					fReturn += this.GetDomain();
					if (WithPath || WithFileName) fReturn += '/';
				}
				if (WithPath) {
					fReturn += this.GetPath();
					if (WithFileName || WithParametersString) fReturn += '/';
				}
				if (WithFileName) fReturn += this.GetFileName();
				if (WithParametersString) {
					if (WithProtocol || WithDomain || WithPath || WithFileName) fReturn += '?';
					fReturn += this.GetParametersString();
				}
				break;
			case 'ftp':
				break;
			case 'javascript':
				break;
			case 'mailto':
				break;
		}
		return fReturn;
	}
	this.GetProtocol = function() {
		if (!this.z_protocol) this.z_protocol = this.RecalcProtocol();
		return this.z_protocol;
	}
	this.GetDomain = function() {
		if (!this.z_domain) this.z_domain = this.RecalcDomain();
		return this.z_domain;
	}
	this.GetFullRequest = function() {
		if (!this.z_fullRequest) this.z_fullRequest = this.RecalcFullRequest();
		return this.z_fullRequest;
	}
	this.GetFullPath = function() {
		if (!this.z_fullPath) this.z_fullPath = this.RecalcFullPath();
		return this.z_fullPath;
	}
	this.GetPath = function() {
		if (!this.z_path) this.z_path = this.RecalcPath();
		return this.z_path;
	}
	this.GetFileName = function() {
		if (!this.z_fileName) this.z_fileName = this.RecalcFileName();
		return this.z_fileName;
	}
	this.GetParametersString = function() {
		if (!this.z_parametersString) this.z_parametersString = this.RecalcParametersString();
		return this.z_parametersString;
	}
	this.GetParameters = function() {
		if (!this.z_parameters) this.z_parameters = this.RecalcParameters();
		return this.z_parameters;
	}
	this.GetParameter = function(Name, oIgnoreCase) {
		//Restituisce il valore del parametro richiesto. <null> se il parametro non è presente nell'array. Argomenti:
		//	Name :			(stringa) il nome del parametro da cercare;
		//	oIgnoreCase :	(boolean, opzionale, def.=False) se TRUE la ricerca avverrà in modalità IgnoreCase.
		var str1, str2, fReturn;
		if (!this.z_parameters) this.z_parameters = this.RecalcParameters();
		fReturn = null;
		if (oIgnoreCase) {
			str2 = Name.toLowerCase();
			for (str1 in this.z_parameters) {
				if (str1.toLowerCase() == str2) { fReturn = this.z_parameters[str1]; break; }
			}
		} else {
			for (str1 in this.z_parameters) {
				if (str1 == str2) { fReturn = this.z_parameters[str1]; break; }
			}
		}
		return fReturn;
	}
	
	this.RecalcExistsProtocol = function() {
		//Restituisce il protocollo (default: il protocollo usato nella pagina corrente)
		var cont1 = this.Url.indexOf(':');
		return ((cont1 == -1 || cont1 > 12) ? false : true);
	}
	this.RecalcProtocol = function() {
		//Restituisce il protocollo (default: il protocollo usato nella pagina corrente)
		if (this.ExistsProtocol()) {
			return this.Url.substr(0, this.Url.indexOf(':')).toLowerCase();
		} else {
			return window.location.protocol;
		}
	}
	this.RecalcDomain = function() {
		//Restituisce la parte [dominio], comprensivo di porta ip se diversa dalla porta di default del protocollo
		var cont1, cont2, fReturn;
		switch (this.GetProtocol()) {
			case 'http':
			case 'https':
			case 'ftp':
				fReturn = this.Url.substr(this.Url.indexOf(':')+1);
				if (fReturn.substr(0, 2) == '//') {
					fReturn = fReturn.substr(2);
					cont1 = fReturn.search(/[\/?#]/g);
					if (cont1 != -1) fReturn = fReturn.substr(0, cont1);
					//Verifico la presenza ed il valore della porta. Se è il valore di default lo tolgo dal valore da restituire
					cont1 = fReturn.indexOf(':');
					if (cont1 != -1) {
						cont2 = fReturn.substr(cont1 + 1);
						if (cont2 == DefaultProtocolIpPort(this.GetProtocol())) fReturn = fReturn.substr(0, cont1);
					}
				} else {
					fReturn = Domini_Nomi_CurrentName();
				}
				return fReturn;
				break;
			case 'javascript':
				//Non gestito. Usare le altre funzioni GetXxxx
				break;
			case 'mailto':
				//Restituisce il dominio del primo indirizzo valido
				fReturn = this.GetFullPath();
				if (fReturn) return fReturn.substr(fReturn.indexOf('@') + 1);
				break;
		}
		return null;
	}
	this.RecalcFullRequest = function() {
		//Restituisce la richiesta intera, senza dominio, porta ip e protocollo.
		var str1, str2, cont1, cont2, re, arr;
		var fReturn = this.Url.substr(this.Url.indexOf(':')+1);
		switch (this.GetProtocol()) {
			case 'http':
			case 'https':
			case 'ftp':
				if (fReturn.substr(0, 2) == '//') {
					fReturn = fReturn.substr(2);
					cont1 = fReturn.search(/[\/?#]/g);
					if (cont1 != -1) {
						if (fReturn.substr(cont1, 1) == '/') cont1 ++;
						return fReturn.substr(cont1);
					} else {
						fReturn = '';
					}
					return decodeURI(fReturn);
				} else {
					//Attenzione: il percorso deve essere assoluto
				}
				break;
			case 'javascript':
				//Restituisce l'intera invocazione alla procedura. (mi aspetto di trovare [NomeObj.]NomeFunzione([parametri]);)
				//Attenzione: la classe considera solo la prima chiamata a funzione trovata.
				fReturn = LTrim(fReturn);
				str1 = new String(fReturn);
				str1 = str1.replace(/\\\\/g, '##');		//Sostituisco la doppia barra con doppio #
				//Sostituisco le stringhe con dei #, uno per carattere di stringa.
				cont1 = str1.search(/['"]/g);
				while (cont1 > -1) {
					str2 = str1.substr(cont1, 1);
					//Cerco la chiusura di stringa, escludendo quelle situazioni in cui il sepStringa è preceduro da uno Escape (\)
					for (cont2 = cont1+1; cont2 < str1.length; cont2++) {
						if (str1.substr(cont2, 1) == str2 && str1.substr(cont2-1, 1) != '\\') break;
					}
					str1 = str1.substr(0, cont1) + StringRepeater('#', cont2 - cont1 + 1) + str1.substr(cont2 + 1);
					cont1 = str1.search(/['"]/g);
				}
				//Ora cerco la fine chiamata funzione, cercando la prima ParentesiChiusa seguita da PuntoVirgola o FineStringa
				cont1 = str1.search(/\)\s*($|;)/g);
				if (cont1 > -1) {
					return fReturn.substr(0, cont1 + 1) + ';';
				}
				break;
			case 'mailto':
				//Restituisce il primo indirizzo valido
				re = new RegExp('[^\\s,;]+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)');
				arr = re.exec(fReturn);
				if (arr.length) return arr[0];
				break;
		}
		return null;
	}
	this.RecalcFullPath = function() {
		//Restituisce il nome del file completo di percorso (senza eventuali parametri del protocollo).
		//Attenzione: per protocollo http, http, ftp il percorso deve essere assoluto.
		var str1, str2, cont1, cont2, re, arr;
		var fReturn = this.Url.substr(this.Url.indexOf(':')+1);
		switch (this.GetProtocol()) {
			case 'http':
			case 'https':
			case 'ftp':
				fReturn = this.GetFullRequest();
				if (fReturn) {
					re = new RegExp('^[^?#]*');
					arr = re.exec(fReturn);
					if (arr && arr.length) fReturn = arr[0];
				}
				return fReturn;
				break;
			case 'javascript':
				//Restituisce l'intera invocazione alla procedura, senza i parametri e le relative parentesi tonde.
				//Es: "javascript:nomeObj.nomeFunzione(param1, param2);"    restituisce   "nomeObj.nomeFunzione"
				fReturn = this.GetFullRequest();
				if (fReturn) {
					str1 = new String(fReturn);
					str1 = str1.replace(/\\\\/g, '##');		//Sostituisco la doppia barra con doppio #
					//Sostituisco le stringhe con dei #, uno per carattere di stringa.
					cont1 = str1.search(/['"]/g);
					while (cont1 > -1) {
						str2 = str1.substr(cont1, 1);
						//Cerco la chiusura di stringa, escludendo quelle situazioni in cui il sepStringa è preceduro da uno Escape (\)
						for (cont2 = cont1+1; cont2 < str1.length; cont2++) {
							if (str1.substr(cont2, 1) == str2 && str1.substr(cont2-1, 1) != '\\') break;
						}
						str1 = str1.substr(0, cont1) + StringRepeater('#', cont2 - cont1 + 1) + str1.substr(cont2 + 1);
						cont1 = str1.search(/['"]/g);
					}
					//Ora tolgo l'ultima coppia di parentesi tonde, conteggiando quante se ne aprono e quante se ne chiudono.
					cont2 = 0;		//num parentesi aperte
					for (cont1=str1.length-2; cont1>0; cont1--) {
						switch (str1.substr(cont1, 1)) {
							case '(': cont2--; break;
							case ')': cont2++; break;
						}
						if (cont2==0) return fReturn.substr(0, cont1);
					}
				}
				break;
			case 'mailto':
				return this.GetFullRequest();
				break;
		}
		return null;
	}
	this.RecalcPath = function() {
		//Restituisce il percorso.
		//Attenzione: se l'ultima parte restituita da GetFullPath comprende un punto, questa sarà intesa come file.
		var cont1, cont2, fReturn;
		switch (this.GetProtocol()) {
			case 'http':
			case 'https':
			case 'ftp':
				fReturn = this.GetFullPath();
				if (fReturn) {
					cont1 = fReturn.lastIndexOf('/');
					cont2 = fReturn.lastIndexOf('.');
					if (cont1 == -1 && cont2 > -1) {
						fReturn = '';
					} else if (cont1 > -1 && (cont1 < cont2 || cont2 == -1)) {
						fReturn = fReturn.substr(0, cont1);
					}
				}
				return fReturn;
				break;
			case 'javascript':
				//Restituisce il nome dell'oggetto per cui è stata invocata la funzione.
				//Es: "javascript:nomeObj.nomeFunzione(param1, param2);"    restituisce   "nomeObj"
				fReturn = this.GetFullPath();
				if (fReturn) {
					cont1 = fReturn.lastIndexOf('.');
					if (cont1 == -1) {
						fReturn = '';
					} else {
						fReturn = fReturn.substr(0, cont1);
					}
					return fReturn;
				}
				break;
			case 'mailto':
				//Non gestito. Usare GetFullPath, GetDomain, GetFileName.
				break;
		}
		return null;
	}
	this.RecalcFileName = function() {
		//Restituisce il nome del file.
		//Attenzione: se l'ultima parte restituita da GetFullPath comprende un punto, questa sarà intesa come file.
		var cont1, fReturn;
		switch (this.GetProtocol()) {
			case 'http':
			case 'https':
			case 'ftp':
				fReturn = this.GetFullPath();
				if (fReturn) {
					fReturn = fReturn.substr(this.GetPath().length);
					if (fReturn.substr(0, 1) == '/') fReturn = fReturn.substr(1);
				}
				return fReturn;
				break;
			case 'javascript':
				//Restituisce il nome della procedura chiamata. Privo di eventuale riferimento ad oggetto.
				//Es: "javascript:nomeObj.nomeFunzione(param1, param2);"    restituisce   "nomeFunzione"
				fReturn = this.GetFullPath();
				if (fReturn) {
					cont1 = fReturn.lastIndexOf('.');
					if (cont1 > -1) fReturn = fReturn.substr(cont1 + 1);
					return fReturn;
				}
				break;
			case 'mailto':
				fReturn = this.GetFullPath();
				if (fReturn) return fReturn.substr(0, fReturn.indexOf('@'));
				break;
		}
		return null;
	}
	this.RecalcParametersString = function() {
		//Restituisce i parametri del percorso URL, sottoforma di stringa.
		var cont1, str1, fReturn;
		switch (this.GetProtocol()) {
			case 'http':
			case 'https':
				//Se il primo parametro è un bookmark, lascerò il carattere # come primo carattere della stringa.
				fReturn = this.GetFullRequest();
				if (fReturn) {
					cont1 = fReturn.search(/[?#]/g);
					if (cont1 == -1) {
						fReturn = '';
					} else {
						if (fReturn.substr(cont1, 1) == '?') cont1 ++;
						fReturn = fReturn.substr(cont1);
					}
				}
				return fReturn;
				break;
			case 'ftp':
				//Potrei restituire un vettore con Username e Password... lo svilupperò se ne avrò bisogno.
				break;
			case 'javascript':
				//Restituisce l'elenco dei parametri, senza le parentesi.
				//Es: "javascript:nomeObj.nomeFunzione(param1, param2);"    restituisce   "param1, param2"
				fReturn = this.GetFullRequest();
				if (fReturn) {
					str1 = this.GetFullPath();
					cont1 = fReturn.indexOf(str1) + str1.length;
					fReturn = fReturn.substr(cont1 + 1, fReturn.length - cont1 - 3);
					return fReturn;
				}
				break;
			case 'mailto':
				//Non gestito. Usare GetFullPath, GetDomain, GetFileName.
				break;
		}
		return null;
	}
	this.RecalcParameters = function() {
		//Restituisce i parametri del percorso URL, sottoforma di Array
		var cont1, cont2, cont3, cont4, str1, strOrg, vett1, vett2, fReturn;
		switch (this.GetProtocol()) {
			case 'http':
			case 'https':
				fReturn = this.GetParametersString();
				if (fReturn) {
					strOrg = new String(fReturn);
					cont1 = strOrg.lastIndexOf('#');
					if (cont1 > -1) {
						str1 = strOrg.substr(cont1 + 1);
						strOrg = strOrg.substr(0, cont1);
					} else {
						str1 = '';
					}
					fReturn = new Array();
					if (strOrg) {
						vett1 = strOrg.split(/(&amp;|&)/g);			//ATTENZIONE: QUESTO METODO PER SEPARARE I PARAMETRI non mi piace, perchè non mi permette di elaborare adeguatamente il testo URL. Preferirei usare un metodo di JScript per codificare il testo, ma non lo trovo.
						for (cont1=0; cont1<vett1.length; cont1++) {
							if (vett1[cont1]) {
								vett2 = vett1[cont1].split('=', 2);
								if (vett2.length == 2) {
									fReturn[vett2[0].toString()] = vett2[1];
								} else {
									fReturn[vett2[0].toString()] = '';
								}
							}
						}
					}
					//Aggiungo l'eventuale Bookmark come se fosse un parametro
					if (str1) fReturn['#'] = str1;
				}
				return fReturn;
				break;
			case 'ftp':
				//Potrei restituire un vettore con Username e Password... lo svilupperò se ne avrò bisogno.
				break;
			case 'javascript':
				//Restituisce il nome della procedura chiamata. Privo di eventuale riferimento ad oggetto.
				//Es: "javascript:nomeObj.nomeFunzione(param1, param2);"    restituisce   Array[0] = "param1"; Array[1] = "param2"
				fReturn = this.GetParametersString();
				if (fReturn) {
					strOrg = new String(fReturn + ',');
					fReturn = new Array();
					
					str1 = new String(strOrg);
					str1 = str1.replace(/\\\\/g, '##');		//Sostituisco la doppia barra con doppio #
					//Sostituisco le stringhe con dei #, uno per carattere di stringa.
					cont1 = str1.search(/['"]/g);
					while (cont1 > -1) {
						str2 = str1.substr(cont1, 1);
						//Cerco la chiusura di stringa, escludendo quelle situazioni in cui il sepStringa è preceduro da uno Escape (\)
						for (cont2 = cont1+1; cont2 < str1.length; cont2++) {
							if (str1.substr(cont2, 1) == str2 && str1.substr(cont2-1, 1) != '\\') break;
						}
						str1 = str1.substr(0, cont1) + StringRepeater('#', cont2 - cont1 + 1) + str1.substr(cont2 + 1);
						cont1 = str1.search(/['"]/g);
					}
					//Scandaglio la stringa alla ricerca delle VIRGOLE, quindi carico fReturn.
					cont2 = 0;		//Num parametro corrente
					cont3 = 0;		//Num parentesi
					cont4 = -1;		//Posiz prec Virgola
					for (cont1=0; cont1<str1.length; cont1++) {
						switch (str1.substr(cont1, 1)) {
							case '(': cont3++; break;
							case ')': cont3--; break;
							case ',':
								if (cont3 == 0) {
									fReturn[cont2] = Trim(strOrg.substr(cont4+1, cont1-cont4-1));
									cont2++;
									cont4 = cont1;
								}
								break;
						}
					}
				} else if (fReturn == '') {
					fReturn = new Array();
				}
				return fReturn;
				break;
			case 'mailto':
				//Non gestito. Usare GetFullPath, GetDomain, GetFileName.
				break;
		}
		return null;
	}
}


//##########################################
//####	Funzioni per apertura PAGINE	####
//##########################################

function Images_OpenWindow(id, descr) {
	window.open(R + 'Images/Image_Visualizza.asp?ID=' + id + '&NoTemplate=yes&Description=' + descr, '_blank', 'width=400,height=300,toolbar=0,menubar=0,location=0,scrollbars=0,status=1,resizable=1');
}
function Help_OpenWindow(path) {
	window.open(R + '_HtmlTag/Help.asp?path=' + CStrUrlParam(path), '_blank', 'width=500,height=400,toolbar=0,menubar=0,location=0,scrollbars=1,status=1,resizable=1');
}
function TestiLiberi_OpenWindow(code) {
	window.open(R + 'Testo/Popup.asp?Code=' + code, 'Testo_Popup', 'width=600,height=500,toolbar=0,menubar=0,location=0,scrollbars=1,status=1,resizable=1');
}



//--></SCRIPT>