﻿/*<SCRIPT type="text/javascript"><!--*/
//#######################################
//####     F U N Z I O N I . J S     ####
//#######################################
//	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;
	}
	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';
			}
		}
	}
	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 = '#NULL';
			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 SerializeValue, per sapere se è un Array o Dictionary
				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 (cont1.toString() != cont2.toString()) {
						str1 = 'Dictionary';
						break;
					}
					cont2 +=1;
				}
			}
			switch (str1) {
				case 'Array':		// Stiamo serializzando un Array
					fReturn = '{';
					for (cont1 in Valore){
						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 (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 [' + str2 + '] sconosciuto.';
	}
	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;
				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_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 una stringa 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)
	
	
	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_Eseguito = 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', 25);
		
		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;
		this._divModal.style.width = window.document.body.scrollWidth;
		this._divModal.style.height = window.document.body.scrollHeight;
		//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) + '\'];') + '\');' + 
						'if (obj1.isModal && obj1.IsOpen()) {' +
							'if (obj1._divModal.style.display != \'none\') obj1._divModal.style.display = \'none\';' +
							'if (obj1._modal_resizeTmr) clearTimeout(obj1._modal_resizeTmr);' +
							'obj1._modal_resizeTmr = setTimeout(\'' + 
								CStrJS('' +
									'var obj1 = window.HtmlPlus_PopupColl[\'' + CStrJS(this.id) + '\'];' +
									'if (obj1.isModal && obj1._divModal.style.display == \'none\') {' +
										'obj1._divModal.style.width = window.document.body.scrollWidth;' +
										'obj1._divModal.style.height = window.document.body.scrollHeight;' +
										'obj1._divModal.style.display = \'block\';' +
									'}') +
								'\', 300);' +
						'}' +
					'}' +
				');';
		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">' + 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_Eseguito = 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') {
			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);' +
					'}');
			this.OnLoad(this);
			if (!this._generaPopup_iFrame_onLoad_Eseguito) {
				this.container_content.contentWindow.Interface_HtmlPlus_Popup_OnLoad(SendSerializedArgument);
				this._generaPopup_iFrame_onLoad_Eseguito = true;
			}
		} else {
			this.OnLoad(this);
		}
		this.OnOpen(this);
	}
	
	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;
		if (this.IsOpen()) {
			return false;
		} else {
			this._isResponseAvailable = false;
			this._isResponseAbort = null;
			this._returnValue = null;
			this._isOpen = true;
			this.isModal = ((IsModal) ? true : false);
			if (this._popupTmr) clearTimeout(this._popupTmr);
			
			//Generazione oggetti HTML e passaggio argomento [SendArgument]
			if (!this.container) {
				this._generaPopup(SendArgument);
				this._posizionaPopup(Left, Top);
			} else {
				if (!IsUndefined(SendArgument) && this.container_content.tagName == 'IFRAME') {
					this.container_content.contentWindow.Interface_HtmlPlus_Popup_OnLoad(SerializeValue(SendArgument));
				}
				this._posizionaPopup(Left, Top);
				this.OnOpen(this);
			}
			if (this.isModal) 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.container, 'zoom', '', 0, 100, 0.6, 1, '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, Left, 'sin');
						this._clipAppearance.AppendMotion(this._divOmbra, 'left', 'px', 0, 100, -this.popupWidth, Left + this.popupShadowWidth, 'sin');
						break;
					case 3:
						this._clipAppearance.AppendMotion(this.container, 'top', 'px', 0, 100, -this.popupHeight - this.popupShadowWidth, Top, 'sin');
						this._clipAppearance.AppendMotion(this._divOmbra, 'top', 'px', 0, 100, -this.popupHeight, Top + 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.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.OnOpen = function (Popup) {return void(0);}							//Invocata quando il metodo Open viene eseguito con successo
	this.OnLoad = function (Popup) {return void(0);}							//Invocata quando il Popup è stato generato
	this.OnClose = function (Popup, ReturnValue, IsAbort) {return void(0);}		//Invocata quando il Popup viene chiuso
	
	this._initialize();
	return this;
}




//###################################
//####  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>
