//======================================================================// Libreria di base del framework Q. Per utilizzare correttamente il framework, \u00E8 necessario invocare la funzione// QInitializeDocument nell'evento onload delle pagine html.//// Nome della libreria: QJS Basic//// Versione corrente:// - 4.0			Prima versione ufficialmente rilasciata.//// Versioni precedenti:// - Nessuna//// Prerequisiti:// - Alcune funzioni richiedo la presenza di elementi di design aggiuntivi (ad es. la funzione QWEBPrompt). Si rimanda// alla descrizione delle singole funzioni.//// Indice delle funzioni:// QDisplayInverter// QDisplayElements// QException// QFieldCheckValue// QFieldGetValue// QGetElementsByAttribute// QGetURLParameter// QGetURLParameters// QIEGetVersion// QInitializeDocument// QIsArray// QIsZero// QLogout// QMouseInitialize// QNodeGetByAttribute// QReplace// QReqFields// QSelectSetOptions// QSelectGetSelected// QStyleGetAttribute// QTrim// QWEBAddressBook// QWEBCalendar// QWEBPrompt//// Indice delle classi:// QArray// QEnum// QString// QNode//// Funzioni deprecate:// QCheckRequestedFields// QGetFieldValue//// Avvertenza:// si esortano gli utilizzatori a non effettuare modifiche non autorizzate su questa libreria. Tali modifiche verrebbero// perse in caso di aggiornamento ed inoltre potrebbero causare malfunzionamenti nelle funzioni che ne fanno uso.//// Propriet\u00E0:	Quattroemme S.p.A.// Autore:		Francesco Diamanti//======================================================================//======================================================================// Variabili globali//======================================================================var QForm									//Contiene il document.forms[0], se prima invocata la funzione QInitializeDocumentvar QCurPath									//Contiene il filepath del database, se prima invocata la funzione QInitializeDocument var QIsIE										//Se true il browser \u00E8 IE, se prima invocata la funzione QInitializeDocument var QMouseX = 0							//Coordinata X del mouse, se prima invocata la funzione QMouseInitializevar QMouseY = 0								//Coordinata Y del mouse, se prima invocata la funzione QMouseInitializevar QSEP1 = "|1"							//Separatore convenzionale di stringhevar QSEP2 = "|2"							//Separatore convenzionale di stringhevar QSEP3 = "|3"							//Separatore convenzionale di stringhe//Variabili globali read-onlyvar QMouseListenerAdded = false			//Se true \u00E8 stato aggiunto //======================================================================// Funzioni//======================================================================function QFieldCheckValue(pField, pValue) {	//Verifica che il campo il cui nome indicato nel parametro pField contenga il valore pValue	try {		var Field = (typeof(pField) == "string")? QForm.elements[pField] : pField		var Checked = false				if (Field) {			//Campi testo e numerici			if (Field.type == "text" || Field.type == "hidden" || Field.type == "textarea" || Field.type == "password") {				if (Field.value == pValue) return(true)			}			//Campi a scelta (singola o multipla)			else if (Field.type == "select-one" || Field.type == "select-multiple") {				if (Field.options.length == 0) {					if (pValue == "") return(true)				}				else {					for (var i = 0; i < Field.options.length; i++) {						if (Field.options[i].selected) {							if (Field.options[i].text == pValue) return(true)							Checked = true						}					}				}				if (Checked == false && pValue == "") return(true)			}			//Controllo CheckBox e RadioButton			else {				for (var i = 0; i < QForm.elements.length; i++) {					Field = QForm.elements[i];					if (Field.name == Field.name && (Field.type == "checkbox" || Field.type == "radio")) {						if (Field.checked) {							if (Field.value == pValue) return(true)							Checked = true;						}					}				}				if (Checked == false && pValue == "") return(true)			}		}		return(false)	}	catch(e) {QException(e, "QFieldCheckValue")}}//======================================================================function QDisplayInverter(elementName, pPartialMatch) {	//Inverte la propriet\u00E0 display degli elementi di una pagina HTML.	//Parametri:	//- ElementName		Il nome dell'elemento del quale invertire la visibilit\u00E0. E' possibile indicare pi\u00F9 nomi	//						separandoli con il carattere ";"	//- pPartialMatch		Booleano. Se true verranno considerati gli elementi il cui nome inizia con il parametro ElementName	try  {		var array = new Array()		var SEP = ";"		var element		var partialMatch = (pPartialMatch == undefined)? false:pPartialMatch		var start = ""				if (elementName != "") {			//Esplode la stringa dei nomi elementi da nascodere/visualizzare in un array			array = elementName.split(SEP)			//Cicla sull'array dei nomi degli elementi			for (var i = 0; i < array.length; i++) {				if (partialMatch) {					//Se richiesto partialmatch cerca tutti gli elementi del form che iniziano con il nome corrente					for (var n = 0; n < QForm.elements.length; n++) {				 		if (QForm.elements[n].name != "") {					 		start = QForm.elements[n].name.substr(0, array[i].length)					 		if (start.toUpperCase() == array[i].toUpperCase()) {								if (element.style.display != "none") QForm.elements[n].style.display = "none"								else QForm.elements[n].style.display = "block"							}				 		}					}				}				else {					//Se non richiesto partialmatch punta all'elemento del form con il nome dato					element = document.getElementById(QTrim(array[i]))					if (element) {						if (element.style.display != "none") element.style.display = "none"						else element.style.display = "block"					}				}			}		}	}	catch(e) {QException(e, "QDisplayInverter")}}//======================================================================function QDisplayElements(show, hide) {	//In un form mostra gli elementi i cui nomi contenuti nel parametro show e nasconde	//quelli il cui nome nel parametro hide. I nomi devono essere separati da ";"	try {		var array		var SEP = ";"		var element				if (show != "") {			array = show.split(SEP)			for (var i = 0; i < array.length; i++) {				element = document.getElementById(QTrim(array[i]))				if (element) element.style.display = "block"			}		}							if (hide != "") {			array = hide.split(SEP)			for (var i = 0; i < array.length; i++) {				element = document.getElementById(QTrim(array[i]))				if (element) element.style.display = "none"			}		}	}	catch(e) {QException(e, "QDisplayElements")}}//======================================================================function QException(error, functionName){	//Questa funzione deve essere richiamata all'interno del blocco catch{}	alert("ATTENTION!!! The following JavaScript error occurred: \n\n" +	"On function: " + functionName + "\n" +	"Error message: " + error.message + "\n\n" +	"Please, communicate this error to the system administrators.")}//======================================================================function QFieldGetValue(pInput, p1, p2) {	//Restituisce il valore di un elemento input senza che il programmatore debba conoscerne il tipo.	//Per elementi input di tipo checkbox o select multiple restituisce un array, altrimenti una stringa.	//Se il campo non \u00E8 stato trovato restituisce null.	//Parametri	//- pInput		Elemento input o suo nome o suo id.	//- p1			Oggetto document sul quale si trova il campo (facoltativo)	//- p2			Solo per elementi select se true restituisce l'alias, ovvero la propriet\u00E0 value, altrimenti il testo	//				ovvero la propriet\u00E0 text. Assume per defualt false (facoltativo)	//	//esempi di chiamata della funzione	//				x = GetFieldValue("Nome del campo")	//				x = GetFieldValue(OggettoCampo)	//				x = GetFieldValue(OggettoCampo, document)	//				x = GetFieldValue(OggettoCampo, true)	//				x = GetFieldValue(OggettoCampo, document, true)	try {		var alias = false		var doc = QForm		var input		var inputArray		var array		var value = ""				//GESTIONE PARAMETRI		//Interpretazione p1		if (p1 != null) {			switch (typeof(p1)) {				case "object":					doc = p1.forms[0]					break				case "string":					sep = p1					break				case "boolean":					alias = p1					break			}			//Interpretazione p2			if (p2 != null && typeof(p2) == "boolean") alias = p2		}		//Interpretazione del parametro pInput		switch (typeof(pInput)) {			case "string":				inputArray = document.getElementsByName(pInput)				if (inputArray.length == 0) input = document.getElementById(pInput)				else input = inputArray[0]				break			case "object":				input = pInput				break		}		//Estrazione del valore del campo		if (input) {			switch (input.type) {				case "text":						value = input.value					break				case "hidden":						value = input.value					break				case "textarea":						value = input.value					break							case "select-one":					value = QSelectGetSelected(input, alias)					break				case "select-multiple":					value = QSelectGetSelected(input, alias)					break				case "radio":					for (var i = 0; i < inputArray.length; i++) {						if (inputArray[i].checked) {							value = inputArray[i].value							break						}					}					break				case "checkbox":					value = new Array()					for (var i = 0; i < inputArray.length; i++) {						if (inputArray[i].checked) {							value[value.length] = inputArray[i].value						}					}					break			}		}		return value	}	catch(e) {QException(e, "QFieldGetValue")}}//======================================================================function QFieldSetValue(pField, value, form) {	//Restituisce il valore di un campo senza che il programmatore debba conoscerne il tipo.	//Parametri:		try {		var field = (typeof(pField) == "string")? document.getElementById(pField) : pField				//Impostazione del valore		if (field) {			switch (field.type) {			case "text":				field.value = value				break			case "hidden":				field.value = value				break			case "textarea":				field.value = value				break						case "select-one":				//Verifica se esista la propriet\u00E0 value e la restituisce, altrimenti la propriet\u00E0 text				if (field.options.length > 0) {					//Se \u00E8 stato richiesto l'alias restituisce la propriet\u00E0 value della option. Se non esiste la propriet\u00E0 text					//Altrimenti restituisce la propriet\u00E0 text					if (alias && field.options[field.selectedIndex].value) value = field.options[field.selectedIndex].value					else value = field.options[field.selectedIndex].text				}				break			case "select-multiple":				for (var i = 0; i < field.options.length; i++) {			          if (field.options[i].selected) {			          	//Aggiunge il separatore per comporre la stringa di ritorno						if (value != "") value += sep						//Se \u00E8 stato richiesto l'alias restituisce la propriet\u00E0 value della option. Se non esiste la propriet\u00E0 text						//Altrimenti restituisce la propriet\u00E0 text						if (alias && field.options[i].value) value += field.options[i].value						else value += field.options[i].text					}				}				break			default:				if(field.length == undefined) {					//In questo caso si tratta di un checkbox o di un radiobutto con una sola ricorrenza					if (field.checked)						//Se \u00E8 stato richiesto l'alias restituisce la propriet\u00E0 value. Se questa non c'\u00E8 restituisce la propriet\u00E0 text.						//Altrimenti restituisce la propriet\u00E0 text						if (alias && field.value) value = field.value						else value = field.text					}					else {						elenco = QForm.elements[field[0].name]						for (var i = 0; i < elenco.length; i++) {						field = elenco[i]										if (field.checked) {							if (field.type == "checkbox") {								//Gestione checkbox								if (value != "") value += sep								value += field.value							}							else if (field.type == "radio") {								//Gestione radiobutton								value = field.value								break							}						}					} 				}			}				}							}	catch(e) {QException(e, "QFieldSetValue")}}//======================================================================function QGetElementsByAttribute(attributeName, attributeValue, tagName) {	//Restituisce un array di elementi del documento aventi l'attributo attributeName valorizzato a attributeValue.	//E' anche possibile restringere la ricerca ad un tag specifico (parametro tagName) o ad un valore parziale.	//Se non ne trova restituisce un array di lunghezza 0.	//La ricerca \u00E8 case insensitive.	//Parametri:	// attributeName		Nome dell'attributo. Obbligatorio.	// attributeValue		Valore dell'attributo. Per ricerche parziali utilizzare l'asterisco (es. "val*"). Obbligatorio.	// tagName			Nome del tag al quale restringere la ricerca. Facoltativo solo per IE4+.	try {		var back = new Array()		var count = -1		var elements = (tagName == undefined || tagName == "")? document.all : document.getElementsByTagName(tagName)			var partialMatch = attributeValue.substring(attributeValue.length - 1) == "*"		var value = (partialMatch)? attributeValue.substring(0, attributeValue.length - 1) : attributeValue		value = value.toUpperCase()		for (index in elements) {			if (elements[index].attributes) {				if (elements[index].attributes[attributeName]) {					var curValue = elements[index].attributes[attributeName].value.toUpperCase()					if (partialMatch) {						if (curValue.substring(0, value.length) == value) {							count++							back[count] = elements[index]						}						}					else {						if (curValue == value) {							count++							back[count] = elements[index]						}					}				}			}		}		return back	}	catch(e) {QException(e, "QGetElementsByAttribute")}	}//======================================================================function QGetURLParameter(pParam, pURL) {	//Restituisce un parametro contenuto nell'url. E' anche possibile indicare un URL diverso da quello corrente.	try {		var param = "&" + pParam + "="		var URL = (pURL == undefined || pURL == "")? window.location.href : pURL		var start = URL.indexOf(param)		var back = ""				if (start != -1) {			start += param.length			var stop = URL.indexOf("&", start)			if (stop == -1) stop = URL.length			back = URL.substring(start, stop)			back = QReplace(back, "%20", " ")		}				return back	}	catch(e) {QException(e, "QGetURLParameter")}}//======================================================================function QGetURLParameters(pURL) {	//Restituisce la stringa dei parametri dell'url. E' anche possibile indicare un URL diverso da quello corrente.	try {		var URL = (pURL == undefined || pURL == "")? window.location.href : pURL		var start = window.location.href.lastIndexOf(window.location.pathname) + window.location.pathname.length		var back = ""		start = window.location.href.indexOf("&", start)		if (start != -1) back = window.location.href.substring(start)		return back	}	catch(e) {QException(e, "QGetURLParameters")}}//======================================================================function QIEGetVersion() {	//Restituisce la versione del browser IE in un array di versione e sottoversioni.	//Se il browser non \u00E8 IE, restitusce un array di un solo elemento stringa vuota	try {		version = new Array("")		if (QIsIE) {			if(navigator.userAgent.indexOf("MSIE") > -1) {				var strVersion = navigator.userAgent.substring(navigator.userAgent.indexOf("MSIE") + 5)				strVersion = strVersion.substring(0, strVersion.indexOf(";"))				version = strVersion.split(".")			}		}		return version	}	catch(e) {QException(e, "QIEGetVersion")}}//======================================================================function QInitializeDocument() {	//Inizializza l'utilizzo del framework Q per un documento HTML	try {		//Variabile globale QForm, ovvero il form 0.		QForm = document.forms[0]				//Variabile globale QCurPath, ovvero il percorso del documento HTML corrente.		//Viene estratto dall'url della locazione corrente in tre tentativi.		// 1. la parte sinistra rispetto al primo slash alla sinistra della sottostringa ".nsf"		// 2. la parte sinistra rispetto al primo slash alla sinistra della sottostringa "?"		// 3. la parte sinistra rispetto al primo slash a partire da destra		var pos = self.location.href.indexOf(".nsf")		if (pos == -1) {			pos = self.location.href.indexOf("?")			if (pos == -1) pos = self.location.href.lastIndexOf("/")			else pos = self.location.href.lastIndexOf("/", pos)			if (pos == -1) QCurPath = self.location.href			else QCurPath = self.location.href.substring(0, pos)		}		else QCurPath = self.location.href.substring(0, pos + 4)		//Variabile globale QIsIE, ovvero il browser \u00E8 internet eexplorer o no?		QIsIE = (navigator.appName == "Microsoft Internet Explorer")? true : false	}	catch(e) {QException(e, "QInitializeDocument")}}//======================================================================function QIsArray(obj) {	//Restituisce true se obj \u00E8 un array	try {		if (obj && obj.constructor == Array) return true		else return false	}	catch(e) {QException(e, "QIsArray")}}//======================================================================function QIsZero(number) {	//Restituisce true se la stringa \u00E8 un numero uguale a zero (es 000, 0, 0,0 o 0.0)	try {		var car = ""			if (number.length == 0) return false		else {			for (var i = 1; i <= number.length; i++) {				car = number.substring(i - 1, i)				if (car != "0" && car != "." && car != ",") return false			}		}			return true	}	catch(e) {QException(e, "QIsZero")}}//======================================================================function QLogout() {	try {		var Path = top.location.href.substring(0, top.location.href.indexOf(".nsf") + 4)		document.cookie="DomAuthSessId=; expires=Saturday, 30-Sep-1969 08:00:00 GMT ; path=/";		document.cookie="LtpaToken=; expires=Saturday, 30-Sep-1969 08:00:00 GMT ; domain=.zonatlc.mi.ps ;path=/";		top.location.href = Path + "?opendatabase&ts=" + Math.random();	}	catch(e) {QException(e, "QLogout")}}//======================================================================function QMouseInitialize() {	//Aggiorna le variabili QMouseX e QMouseY aggiungendo al documento un listener per l'evento onmousemove.	//Anche richiamando la funzione pi\u00F9 volte, verr\u00E0 aggiunto un solo listener.	try {		if (QMouseListenerAdded == false) {			if (QIsIE) document.attachEvent("onmousemove", QMouseRefresh)			else document.addEventListener("mousemove", QMouseRefresh, false)			QMouseListenerAdded = true		}	}	catch(e) {QException(e, "QMouseInitialize")}}function QMouseRefresh(event) {	//Ad uso della funzione QMouseInitialize per l'aggiornamento delle coordinate del mouse.	try {		if (QIsIE) {			QMouseX = event.clientX + document.body.scrollLeft			QMouseY = event.clientY + document.body.scrollTop		}		else {			QMouseX = event.pageX			QMouseY = event.pageY		}	}	catch(e) {QException(e, "QMouseRefresh")}}//======================================================================function QNodeGetByAttribute(pMainNode, attributeName, attributeValue, nodeName) {	//Restituisce un array di nodi contenuti nel nodo mainNode aventi l'attributo attName valorizzato a addValue.	//E' anche possibile restringere la ricerca ai nodi di tipo nodeName.	//Se non ne trova restituisce un array di lunghezza 0.	//La ricerca \u00E8 case insensitive	//- pMainNode					Nodo o id del nodo di partenza. Obbligatorio.	//- attributeName				Nome dell'attributo. Obbligatorio.	//- attributeValue					Valore dell'attributo. Per ricerche parziali utilizzare l'asterisco (es. "val*"). Obbligatorio.	//- nodeName					Nome del nodo al quale restringere la ricerca. Facoltativo.	try {		var mainNode = (typeof(pMainNode) == "string")? document.getElementById(pMainNode) : pMainNode		var array = new Array()				if (mainNode) {			var childArray			var goOn			var node			var nodeValue			var partialMatch = attributeValue.substring(attributeValue.length - 1) == "*"			var value = (partialMatch)? attributeValue.substring(0, attributeValue.length - 1) : attributeValue			value = value.toUpperCase()						node = mainNode.firstChild			while (node) {				//Verifica il valore dell'attributo				if (node.attributes) {					if (node.attributes[attributeName]) {						//Verifica se il nodo sia del tipo indicato (quando indicato).						goOn = true						if (nodeName && node.nodeName != nodeName) goon = goOn						if (goOn) {							//Verifica il valore dell'attributo							nodeValue = node.attributes[attributeName].value.toUpperCase()							if (partialMatch) {								if (nodeValue.substring(0, value.length) == value) array[array.length] = node							}							else if (nodeValue == value) array[array.length] = node						}					}				}				//Ripete l'operazione per i nodi interni				childArray = QNodeGetByAttribute(node, attributeName, attributeValue, nodeName)				if (childArray.length > 0) array = array.concat(childArray)				//Passa al nodo successivo				node = node.nextSibling			}		}		return array	}	catch(e) {QException(e, "QNodeGetByAttribute")}}//======================================================================function QReplace(oldString, oldSub, newSub) {	try {		var appo		var newString = ""		for (var i = 0; i < oldString.length; i++) {			appo = oldString.substring(i, i + oldSub.length)			if (appo == oldSub) {				newString = newString + newSub				i = i + oldSub.length - 1			}			else newString = newString + oldString.substring(i, i + 1)		}		return newString	}	catch(e) {QException(e, "QReplace")}}//======================================================================function QReqFields(pFields) {	//Controlla se i campi i cui nomi ed eventuali descrizioni sono contenuti nel parametro pFields siano stati valorizzati.	//Non entra nel merito del contenuto.	//Parametri:	//pFields		Elenco dei nomi campo e descrizione avente il seguente formato:	//				"NomeCampo1 [,Label campo 1]; NomeCampo2 [,Label campo 2];...."	try {		var Campi = pFields.split(";")		var Campo		var Msg = ""		var AFuoco = ""		var ACapo = "\n"		for (var i in Campi) {			Campo = Campi[i].split(",")			Campo[0] = QTrim(Campo[0])						if (Campo[0] != "") {				if (Campo[1]) Campo[1] = QTrim(Campo[1])				else Campo[1] = Campo[0]				if (QFieldCheckValue(Campo[0], ""))	{					Msg = Msg + ACapo + "- " + Campo[1]					if (AFuoco == "") AFuoco = Campo[0]				}			}		}		if (Msg != "") {			alert("I seguenti campi sono obbligatori:" + ACapo + Msg)			//Puntamento del fuoco			var elementType = QForm.elements[AFuoco].type			if (elementType != "hidden") {				if (elementType == undefined) QForm.elements[AFuoco][0].focus()				else QForm.elements[AFuoco].focus()			}			return (false)		}		else return(true)	}	catch(e) {QException(e, "QReqFields")}}//======================================================================function QSelectSetOptions(pField, options, curOptions, admitEmpty) {	//Imposta le options per un tag Select.	//Parametri:	//- pField				Campo select o il suo nome	//- options			Array o stringa separata da QSEP1 delle options. Gestisce gli alias separati da "|" dal valore della option	//- curOptions		Array o stringa separata da QSEP1 delle options correntemente selezionate (facoltativo). Nel caso in cui	//						la option contenga un alias, ovvero la propriet\u00E0 value diversa da text, curOptions deve contenere	//						gli alias.	//						Se gestiti nel param Options devono essere alias	//- admitEmpty		Boleano, indica se la prima option sia vuota (facoltativo)	try {		//Interpretazione del parametro pField		var field = (typeof(pField) == "string")? QForm.elements[pField] : pField		var iO = -1		var array		var value		var alias		var optionsArray = (QIsArray(options))? options : options.split(QSEP1)				//Inizializza l'elenco delle options		field.options.length = 0		//Se richiesta inserisce una option vuota		if (admitEmpty) {			iO++			field.options[iO] = new Option("")		}		for (var i = 0; i < optionsArray.length; i++) {			array = optionsArray[i].split("|")			value = QTrim(array[0])			alias = (array.length > 1)? QTrim(array[1]) : ""			//Aggiunge una nuova options			iO++			if (alias == "") field.options[iO] = new Option(value)			else field.options[iO] = new Option(value, alias)						//Se tra quelle indicate come option correnti, la seleziona			if (curOptions != undefined) {				if (field.options[iO].value) value = field.options[iO].value				else value = field.options[iO].text							var curOptionsArray = (QIsArray(curOptions))? curOptions : curOptions.split(QSEP1)				for (var n = 0; n < curOptionsArray.length; n++) {					if (QTrim(curOptionsArray[n]) == value) {						field.options[iO].selected = true						break					}				}			}		}	}	catch(e) {QExceptions(e, "QSelectSetOptions")}}//======================================================================function QSelectGetSelected(pSelect, alias) {	//Restituisce la o le options selezionate in un elemento select. Se la select \u00E8 a scelta singola, restituisce	//una stringa. Se la select \u00E8 a scelta multipla restituisce sempre un array. Se nessun elemento \u00E8 stato	//selezionato, od anche se l'elemento non \u00E8 una select, restituisce null.	//Parametri:	//- pSelect			Elemento select o il suo nome. Pu\u00F2 anche essere il suo id.	//- alias				Se true, restituisce l'alias, altrimenti il testo della option. Se l'alias non esiste restituisce	//						comunque il testo della option.	try {		var select		var selected			//Identifica la select		switch (typeof(pSelect)) {			case "string":				select = document.getElementsByName(pSelect)				if (select == null) select = document.getElementById(pSelect)				else select = select[0]				break			case "object":				select = pSelect				break		}			if (select) {			//Verifica il tipo di select			switch (select.type) {				case "select-one":					if (select.options.length > 0) {						//Verifica se esista la propriet\u00E0 value e la restituisce, altrimenti la propriet\u00E0 text						if (alias && select.options[select.selectedIndex].value) selected = select.options[select.selectedIndex].value						else selected = select.options[select.selectedIndex].text					}					break				case "select-multiple":					selected = new Array()					for (var i = 0; i < select.options.length; i++) {				          if (select.options[i].selected) {							//Verifica se esista la propriet\u00E0 value e la restituisce, altrimenti la propriet\u00E0 text							if (alias && select.options[i].value) selected[selected.length] = select.options[i].value							else selected[selected.length] = select.options[i].text						}					}			}		}		return selected	}	catch(e) {QExceptions(e, "QSelectGetSelected")}}//======================================================================function QStyleGetAttribute(pNode, attName, asNumber) {	//Restituisce il valore dell'attributo di stile richiesto per il nodo indicato.	//Parametri:	//- pNode				Node o suo id	//- attName			Nome dell'attributo ricercato	//- asNumber			Se false restituisce il valore in formato stringa.	//						Se true restituisce un array dove il primo elemento \u00E8 il valore numerico dell'attributo ed il secondo	//						\u00E8 l'unit\u00E0 di misura. Gestisce le um px, %, pt, em. NOTA: utilizzare solo dove ha senso. Per attributi	//						non interpretabili come valori numerici (es. text-align:center o padding: 6px 10px 4px 3px) restituisce 0.	try {		var node = (typeof(pNode) == "string")? document.getElementById(pNode) : pNode		var value = ""		if (node.currentStyle) value = node.currentStyle[attName]		else if (window.getComputedStyle) value = document.defaultView.getComputedStyle(node, null).getPropertyValue(attName)		if (asNumber) {			//Se richiesto e dove sensato, restituisce il valore in forma di numero.			var listValue = [0, ""]			if (value != null && value != "") {				var umList = new Array("px", "%", "pt", "em")				for (index in umList) {					var pos = value.indexOf(umList[index])					if (pos != -1) {						//Estrae l'unit\u00E0 di misura						var um = value.substring(pos)						//Verifica che non ci siano altri caratteri oltre all'unit\u00E0 di misura (es. "1px 3px 4px 2px")						if (um != umList[index]) break						else {							//Verifica che la parte estratta sia un numerico							var number = parseInt(value.substring(0, pos))							if (number != "NaN") listValue = [number, um]							break						}					}				}			}			return listValue		}		else return value	}	catch(e) {QException(e, "QStyleGetAttribute")}}//======================================================================function QTrim(pString, pFullTrim) {	//Rimuove gli spazi di testa, di coda e, se indicato nel parametro pFullTrim anche quelli doppi	try {		var backString = pString		var fullTrim = (pFullTrim == "" || pFullTrim == undefined)? false:pFullTrim		var times = 0		//Elimina gli spazi a sinistra		for (var i = 0; i < backString.length; i++) {			if (backString.charAt(i) != " ") {				backString = backString.substring(i)				break			}		}		//Elimina gli spazi a destra		for (var i = backString.length - 1; i >= 0; i--) {			if (backString.charAt(i) != " ") {				backString = backString.substring(0, i + 1)				break			}		}		//Se richiesto elimina gli spazi doppi		if (fullTrim) {			for (var i = 0; i < backString.length; i++) {				if (backString.charAt(i) == " ") {					times++					if (times > 1) {						i--						backString = backString.substring(0, i) + backString.substring(i + 1)					}				}				else times = 0			}		}		return backString	}	catch(e) {QException(e, "QTrim")}}//======================================================================function QWEBCalendar(targetField) {	//Attiva il calendario per la scelta di una data	//Parametri:	//targetField			Campo di destinazione o suo id.	//Nota: \u00E8 necessario che sia installato il form QWEBCalendar.	try {		//Interpretazione del parametro pField		var target =  (typeof(targetField) == "string")? QForm.elements[targetField]:targetField			if (target != null) {			if (target.type != "hidden") {				FieldDate = target.name				x = window.event.screenX				y = window.event.screenY				window.open(QCurPath + '/QWEBCalendar?ReadForm' , 'Calendario' , 'width=180, height=200, left=' + x + ', top=' + (y + 25) + ', noresize')			}		}	}	catch(e) {QException(e, "QWEBCalendar")}}//======================================================================function QWEBAddressBook(multi, target, format, type, nameSep, nodeId) {	//Apre la finestra di selezione dei nominativi dalla rubrica del server	//Parametri:	//- multi			=	Boleano. Se true indica che si devono poter selezionare pi\u00F9 nominativi	//- target			=	Stringa. Nome del campo dove verranno inseriti i nominativi o nome della funzione opener da 	//						richiamare al termine ed alla quale verr\u00E0 passato un array contenete i nominativi selezionati.	//- format			=	Stringa. Formato del nome restituito, ovvero "A" = abbreviato, "C"= canonico,"CN" = comune.	//- type			=	Stringa multivalore separati da ";". Tipo di scelte proposte, ovvero "P" = persone, "G" = gruppi,	//						"S" = server, "D" = database	//- nameSep		=	Carattere separatore dei nomi se abilitata la modalit\u00E0 a scelta multipla.	//- nodeId			=	Stringa. Indicare l'id di un eventuale nodo HTML nel quale scrivere l'elenco dei nominativi. Pu\u00F2 essere	//						utile se il campo target \u00E8 di tipo calcolato.	//	// Nota: \u00E8 necessario che siano stati installati i seguenti elementi di desgin:	//1. Script library QJS AJAX	//2. Script library QLS Basic	//3. Agente QWEBAddressBook	//4. Form QWEBAddressBook	//5. E' fortemente consigliabile creare il foglio di stile QWEBAddressBookStyle.	try {		var width = 0		var options = ""		var URL = QCurPath + "/QWEBAddressBook?OpenForm"				//Determina le opzioni da inviare alla finestra di selezione dei nominativi		//Selezione multipla		if (multi) {			width = 680			options += "&Multi=S"		}		else width = 430		//Target		if  (document.forms[0].elements[target]) options += "&TargetField=" + target		else options += "&TargetFunction=" + target		//Formato		if (format != undefined) options += "&Format=" + format		//Tipo		if (type != undefined) options += "&Type=" + type		//Separatore		if (nameSep != undefined) options += "&NameSep=" + nameSep		//ID del nodo nel quale scrivere l'elenco dei nomi		if (nodeId != undefined) options += "&NodeId=" + nodeId				URL += options		 		window.open(URL, "", "toolbar=no, location=no, scrollbars=no, width=" + width + ", height=520")	}	catch(e) {QException(e, "QWEBAddressBook")}}//======================================================================function QWebPrompt(newWindow, windowType, msg, options) {	//Apre la finestra QWEBPrompt.	//Parametri:	//- newWindow						Se true apre la prompt in una nuova finestra.	//- windowType						Assume "Ok", "OkCancelEdit", "OkCancelArea", "OkCancelEditList", "OkCancelList",	//										"OkCancelListMult", "YesNo", "YesNoCancel"	//- msg								Messaggio da inserire prima dei campi della prompt.	//- options							Per le opzioni si veda la descrizione contenuta nel form QWEBPrompt	//	// Nota: \u00E8 necessario che siano stati installati i seguenti elementi di desgin:	//1. Form QWEBPrompt	//2. E' fortemente consigliabile creare il foglio di stile QWEBPromptStyle.	try {			var parameters		var URL		var height		//Impostazione dell'altezza della finestra		if (windowType == "OkCancelListMult") height = "400"		else height = "300"			//Impostazione dei parametri		if (newWindow) parameters = "&NuovaFinestra=S"		else parameters = "&NuovaFinestra=N"		windowType = "&Tipo=" + windowType		msg = "&Msg=" + msg		options = "&Opz=" + options				parameters = parameters + windowType + msg + options + "&"		URL = QCurPath + "/QWebPrompt?OpenForm" + parameters			if (newWindow) window.open(URL, "", "toolbar=no, location=no, scrollbars=no, width=600, height=" + height)		else self.location.href = URL	}	catch(e) {QException(e, "QWebPrompt")}}//======================================================================// Funzioni deprecate mantenute per retrocompatibilit\u00E0//======================================================================function QCheckRequestedFields(pFields) {return QReqFields(pFields)}function QGetFieldValue(pField, p1, p2, p3) {return QFieldGetValue(pField, p1, p2, p3)}//======================================================================// CLASSI//======================================================================// Class Array//======================================================================function QArray(pArray, pSep) {	var sep = pSep	var that = this	//Inizializzazione	initialize()		//------------------------------------------------------------------------------------------------------------------------	// Propriet\u00E0 pubbliche	//------------------------------------------------------------------------------------------------------------------------	this.array												//L'oggetto array			//------------------------------------------------------------------------------------------------------------------------	// Metodi pubblici	//------------------------------------------------------------------------------------------------------------------------	this.addElement = M_addElement					//Aggiunge un elemento all'array	this.indexOf = M_indexOf							//Restitiosce l'indice della String. Se non \u00E8 trovata restituisce -1.	this.hasElement = M_hasElement					//Restituisce true se l'elemento indicato \u00E8 presente nell'array.	this.join = M_join										//Concatena l'array in una stringa e la restituisce.	this.removeElement = M_removeElement			//Rimuove un elemento e, eventualmente, tutte le sue ridondanze.	this.removeFirst = M_removeFirst					//Rimuove il primo elemento	this.removeLast = M_removeLast					//Rimuove l'ultimo elemento	//------------------------------------------------------------------------------------------------------------------------	// Definizione dei metodi pubblici	//------------------------------------------------------------------------------------------------------------------------	function M_addElement(element) {		try {			this.array[this.array.length] = element		}		catch(e) {QException(e, "QArray.addElement")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_indexOf(pElement, caseSensitive) {		//Restitiosce l'indice della String. Se non \u00E8 trovata restituisce -1.		//E' anche possibile indicare se la ricerca debba essere case sensitive o meno.		try {			var element			var curElement			var index = -1			if (typeof(pElement) == "object") element = pElement			else element = (caseSensitive)? pElement : pElement.toUpperCase()			for (var i = 0; i < this.array.length; i++) {				if (typeof(this.array[i]) == "object") curElement = this.array[i]				else if (caseSensitive) curElement = this.array[i]				else curElement = this.array[i].toUpperCase()				if (curElement == element) {					index = i					break				}			}			return index		}		catch(e) {QException(e, "QArray.indexOf")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_hasElement(element, caseSensitive) {		//Restituisce true se l'elemento element \u00E8 presente nell'array.		try {			if (this.indexOf(element, caseSensitive) == -1) return false			else return true		}		catch(e) {QException(e, "QArray.hasElement")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_join(sep) {		//Concatena l'array in una stringa e la restituisce.		try {			return this.array.join(sep)		}		catch(e) {QException(e, "QArray.join")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_removeElement(pElement, redondaceToo, caseSensitive) {		//Rimuove un elemento e, eventualmente, tutte le sue ridondanze.		//E' anche possibile indicare se la ricerca debba essere case sensitive o meno.		try {			var element			var newArray = new Array()			var curElement			var isRedondance = false						if (typeof(pElement) == "object") element = pElement			else element = (caseSensitive)? pElement : pElement.toUpperCase()						for (var i = 0; i < this.array.length; i++) {							if (typeof(this.array[i]) == "object") curElement = this.array[i]				else if (caseSensitive) curElement = this.array[i]				else curElement = this.array[i].toUpperCase()				if(curElement != element || isRedondance) newArray[newArray.length] = this.array[i]				else if (!redondaceToo) isRedondance = true			}			this.array = newArray		}		catch(e) {QException(e, "QArray.removeElement")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_removeFirst() {		//Rimuove il primo elemento e lo restituisce. Accorcia l'array		try {			return this.array.shift()		}		catch(e) {QException(e, "QArray.removeFirst")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_removeLast() {		//Rimuove l'ultimo elemento e lo restituisce. Accorcia l'array		try {			return this.array.pop()		}		catch(e) {QException(e, "QArray.removeLast")}	}		//------------------------------------------------------------------------------------------------------------------------	// Metodi privati	//------------------------------------------------------------------------------------------------------------------------	function initialize() {		try {			if (QIsArray(pArray)) that.array = pArray			else if (typeof(pArray) == "string") {				if (sep == undefined) that.array = new Array(pArray)				else that.array = pArray.split(sep)			}				else that.array = new Array()		}		catch(e) {QException(e, "QArray.initialize")}	}}//======================================================================// Class Enum//======================================================================function QEnum(pPrefix, pLength, pStartFrom) {	//Enumeratore		var filler = "0000000000"		//Propriet\u00E0 pubbliche	this.count = (pStartFrom == undefined)? 0 : pStartFrom	this.length = (pLength == undefined)? 2 : (pLength > filler.length)? filler.length : pLength	this.prefix = (pPrefix == undefined)? "" : pPrefix	//------------------------------------------------------------------------------------------------------------------------	// Metodi pubblici	//------------------------------------------------------------------------------------------------------------------------	this.getNew = M_getNew	//------------------------------------------------------------------------------------------------------------------------	// Definizione dei metodi pubblici	//------------------------------------------------------------------------------------------------------------------------	function M_getNew() {		//Restituisce un nuovo numeratore		var text = filler + this.count		var start = filler.length - this.length + 1		this.count++		return this.prefix + text.substring(start, text.length)	}}//======================================================================// Class QString//======================================================================function QString(pString) {		//Propriet\u00E0 pubbliche	this.string = (typeof(pString) == "string")? pString:""	this.length = (typeof(pString) == "string")? this.string.length:0		//------------------------------------------------------------------------------------------------------------------------	//Metodi pubblici	//------------------------------------------------------------------------------------------------------------------------	this.append = M_append	this.endsWith = M_endsWith	this.left = M_left	this.leftBack = M_leftBack	this.replaceInner = M_replaceInner	this.right = M_right	this.rightBack = M_rightBack	this.startsWith = M_startsWith	this.substring = M_substring	this.trim = M_trim		//------------------------------------------------------------------------------------------------------------------------	//Definizione dei metodi pubblici	//------------------------------------------------------------------------------------------------------------------------	function M_append(pString) {		//Appende una stringa alla stringa oggetto		try {			return this.string += pString		}		catch(e) {QException(e, "QString.append")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_endsWith(pString) {		//Restituisce true se la stringa oggetto finisce con pString		try {			if (pString && this.string.substr(this.length - pString.length).toUpperCase() == pString.toUpperCase()) return true			else return false		}		catch(e) {QException(e, "QString.endsWith")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_left(pString) {		//Restituisce la parte sinistra della stringa oggetto rispetto alla stringa pString		try {			var end = this.string.toUpperCase().indexOf(pString.toUpperCase())			if (end < 0) return ""			else return this.string.substring(0, end)		}		catch(e) {QException(e, "QString.left")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_leftBack(pString) {		//Restituisce la parte sinistra della stringa oggetto rispetto alla stringa pString partendo da destra		try {			var end = this.string.toUpperCase().lastIndexOf(pString.toUpperCase())			if (end < 0) return ""			else return this.string.substring(0, end)		}		catch(e) {QException(e, "QString.leftBack")}	}			//------------------------------------------------------------------------------------------------------------------------	function M_replaceInner(substring, startString, endString, limitToo) {		//Sostituisce una sottostringa individuata da una string di inizio ed una di fine.		//Paremetri:		//- substring			nuova stringa che sostituir\u00E0 quella che si trova tra la startString e endString		//- startString			stringa che delimita l'inizio della sottostringa da rimpiazzare		//- endString			stringa che delimita la fine della sottostringa da rimpiazzare		//- limitToo			se true la sostituzione comprender\u00E0 anche la stringa di inzio e di fine		try {			var limit1 = this.string.indexOf(startString)			if (limit1 != -1) {				var limit2 = this.string.indexOf(endString, limit1 + startString.length)				if (limit2 != -1) {					if (limitToo) limit2 += endString.length					else limit1 += startString.length					this.string = this.string.substring(0, limit1) + substring + this.string.substring(limit2)				}			}			return this.string		}		catch(e) {QException(e, "QString.replaceInner")}	}	//------------------------------------------------------------------------------------------------------------------------	function M_right(pString) {		//Restituisce la parte destra della stringa oggetto rispetto alla stringa pString		try {			var start = this.string.toUpperCase().lastIndexOf(pString.toUpperCase())			if (start < 0) return ""			else {				start += pString.length				return this.string.substring(start)			}		}		catch(e) {QException(e, "QString.right")}	}	//------------------------------------------------------------------------------------------------------------------------	function M_rightBack(pString) {		//Restituisce la parte destra della stringa oggetto rispetto alla stringa pString partendo da sinistra		try {			var start = this.string.toUpperCase().indexOf(pString.toUpperCase())			if (start < 0) return ""			else {				start += pString.length				return this.string.substring(start)			}		}		catch(e) {QException(e, "QString.rightBack")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_startsWith(pString) {		//Restituisce true se la stringa oggetto inizia con pString		try {			if (pString && this.string.substr(0, pString.length).toUpperCase() == pString.toUpperCase()) return true			else return false		}		catch(e) {QException(e, "QString.startsWith")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_substring(pStartFrom, pStartString, pEndString, pMultiple) {		//Restituisce una sottostringa della stringa oggetto		try {			var ret = (pMultiple)? new Array() : ""			var startFrom = (typeof(pStartFrom) == "number")? pStartFrom:0 			var start = this.string.toUpperCase().indexOf(pStartString.toUpperCase(), startFrom) + pStartString.length 			var end = 0 			var count = -1			if (start > -1) {	 			//Differenzia l'elaborazione per ritorno singoli o multipli 				if (pMultiple) { 					while (start <= this.string.length) { 						end = this.string.toUpperCase().indexOf(pEndString.toUpperCase(), start) 						if (end == -1) break						count++ 						ret[count] = this.string.substring(start, end) 						start = end + pEndString.length + pStartString.length 					} 				} 				else {	 				end = this.string.toUpperCase().indexOf(pEndString.toUpperCase(), start)			 		if (end > -1) ret = this.string.substring(start, end) 				} 			} 			return ret		}		catch(e) {QException(e, "QString.substring")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_trim(pFullTrim) {		//Restituisce la stringa oggetto eliminado gli spazi di inizio e cosa e, se indicato nel parametro pFullTrim		//anche quelli doppi all'interno della stringa.		try {			return QTrim(this.string, pFullTrim)		}		catch(e) {QException(e, "QString.startsWith")}	}}//======================================================================// QNode//======================================================================function QNode(pNode) {	var effectiveLeft = 0							//Coordinata left dell'effective parent.	var effectiveTop = 0							//Coordinata top dell'effective parent.	//------------------------------------------------------------------------------------------------------------------------	// Propriet\u00E0 pubbliche	//------------------------------------------------------------------------------------------------------------------------		this.node										//Oggetto nodo		//Coordinate del nodo rispetto al primo parent node non static. Vengono impostate dal metodo updateCoordinates.	this.left = 0									//Cooridinata X del limite sinistro	this.right = 0									//Cooridinata X del limite destro	this.top = 0									//Coordinata Y del limite superiore	this.bottom = 0								//Coordinata Y del limite inferiore		//Coordinate del nodo sullo schermo. Vengono impostate dal metodo updateOffsetCoordinates.	this.offsetLeft = 0							//Cooridinata X del limite sinistro	this.offsetRight = 0							//Cooridinata X del limite destro	this.offsetTop = 0							//Coordinata Y del limite superiore	this.offsetBottom = 0						//Coordinata Y del limite inferiore	//------------------------------------------------------------------------------------------------------------------------	// Metodi pubblici	//------------------------------------------------------------------------------------------------------------------------	this.getEffectiveParent = M_getEffectiveParent	this.isMouseOver = M_isMouseOver	this.moveTo = M_moveTo	this.moveToNode = M_moveToNode	this.setNode = M_setNode	this.setStyle = M_setStyle	this.startMoving = M_startMoving	this.updateCoordinates = M_updateCoordinates	//Inizializzazione	this.setNode(pNode)		//------------------------------------------------------------------------------------------------------------------------	// Definizione dei metodi pubblici	//------------------------------------------------------------------------------------------------------------------------	function M_getEffectiveParent() {		//Restituisce il parent node effettivo rispetto al posizionemnto del nodo corrente. Ovvero:		//- per nodi position static e relative il parent node.		//- per nodi position absolute il primo parent node con position non static. Al massimo ritorna al document.body		//- per nodi position fixed restituisce undefied		try {			var parent			switch (this.node.style.position.toLowerCase()) {				case "absolute":					parent = this.node.parentNode					while (parent) {						if (parent.nodeName == "BODY") break						if (parent.style.position == "relative" || parent.style.position == "absolute") break						parent = parent.parentNode					}					break				case "fixed":					parent = undefined					break				default:					parent = this.node.parentNode			}			return parent		}		catch(e) {QException(e, "QNode.getEffectiveParent")}	}			//------------------------------------------------------------------------------------------------------------------------		function M_isMouseOver() {		//Indica se il mouse si trova all'esterno del nodo. ATTENZIONE: deve essere stata inizializzata la gestione del mouse.		try {			if (this.node) {				//Aggiorna le coordinate offset.				this.updateCoordinates(true)				if (QMouseX >= this.offsetLeft && QMouseX <= this.offsetRight && QMouseY >= this.offsetTop && QMouseY <= this.offsetBottom) return true				else return false			}			else return false		}		catch(e) {QException(e, "QNode.isMouseOver")}	}	//------------------------------------------------------------------------------------------------------------------------	function M_moveTo(x, y) {		//Muove il nodo alle coordinate indicate. Tiene conto delle relazioni di style.position dei nodi.		//Parametri:		//- x				Coordinata X. Se null o comunque non numerica mantiene la coordinata corrente.		//- y				Coordinata Y. Se null o comunque non numerica mantiene la coordinata corrente.		//NOTA: prima di invocare il metodo moveTo, \u00E8 necessario invocare almeno una volta il metodo startMoving.		//Inoltre il nodo deve avere position absolute.		try {			if (this.node) {				if (typeof(x) == "number") this.node.style.left = x - effectiveLeft + "px"				if (typeof(y) == "number") this.node.style.top = y - effectiveTop + "px"			}		}		catch(e) {QException(e, "QNode.moveTo")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_moveToNode(pReference, pReferenceEdge, pThisEdge, pMarginX, pMarginY) {		//Posizione il nodo in relazione ad un nodo di riferimento. Il nodo corrente deve essere visibile ed avere		//pozione absolute. Parametri:		//- pReference				Nodo di riferimento o suo id		//- pReferenceEdge			Angolo del parent node al quale attaccare il nodo corrente. Assume i valori:		//								"top-left", "top-right", "bottom-right", "bottom-left" (default)		//- pThisEdge					Come per pParentCorner, ma per il nodo corrente.		//- pMarginX					Margine orizzontale. Assume valori positivi e negativi.		//- pMarginY					Margine verticale. Assume valori positivi e negativi.		//NOTA: il nodo deve avere position absolute.		try {			if (this.node) {				var reference = new QNode(pReference)				reference.updateCoordinates(true)				var referenceEdge = (pReferenceEdge)? pReferenceEdge : "bottom-left"				var thisEdge = (pThisEdge)? pThisEdge : "top-left"				var marginX = (pMarginX)? pMarginX : 0				var marginY = (pMarginY)? pMarginY : 0				var x				var y				//Calcola la coordinata X				if (referenceEdge == "top-left" || referenceEdge == "bottom-left") {					if (thisEdge == "top-left" || thisEdge == "bottom-left") x = reference.offsetLeft					else x = reference.offsetLeft - this.node.offsetWidth				}				else {					if (thisEdge == "top-left" || thisEdge == "bottom-left") x = reference.offsetRight					else x = reference.offsetRight - this.node.offsetWidth				}				//Calcola la coordinata Y				if (referenceEdge == "top-left" || referenceEdge == "top-right") {					if (thisEdge == "top-left" || thisEdge == "top-right") y = reference.offsetTop					else y = reference.offsetTop - this.node.offsetHeight				}				else {					if (thisEdge == "top-left" || thisEdge == "top-right") y = reference.offsetBottom					else y = reference.offsetBottom - this.node.offsetHeight				}				//Effettua il movimento del nodo correggendo le coordinate degli ventuali margini.				this.startMoving()				this.moveTo(x + marginX, y + marginY)			}		}		catch(e) {QException(e, "QNode.moveToNode")}	}	//------------------------------------------------------------------------------------------------------------------------		function M_startMoving() {		//Assolve alle funzioni preliminari per il movimento del nodo e va sempre utilizzato prima del metodo moveTo.		//Omettere l'invocazione di questo metodo pu\u00F2 indurre il metodo moveTo a generare risultati insoddisfacenti.		try {			if (this.node) {				var qParent = new QNode(this.getEffectiveParent())				if (qParent) {					qParent.updateCoordinates(true)					effectiveLeft = qParent.offsetLeft					effectiveTop = qParent.offsetTop				}						}		}		catch(e) {QException(e, "QNode.startMoving")}	}	//------------------------------------------------------------------------------------------------------------------------		function M_setNode(nodeX) {		//Imposta il nodo. E' possibile indicare un nodo o il suo id. Se quest'ultimo \u00E8 in bianco il nodo sar\u00E0 undefined.		try {			if (typeof(nodeX) == "string") {				if (nodeX != "") this.node = document.getElementById(nodeX)				else this.node = undefined			}			else this.node = nodeX		}		catch(e) {QException(e, "QNode.setNode")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_setStyle(name, value) {		//Indica se il mouse si trova all'esterno del nodo.		try {			if (this.node) {				switch (name.toLowerCase()) {					case "display":						this.node.style.display = value						break					case "float":						this.node.style.cssFloat = value						break					case "height":						this.node.style.height = value						break					case "width":						this.node.style.width = value						break				}			}		}		catch(e) {QException(e, "QNode.setStyle")}	}		//------------------------------------------------------------------------------------------------------------------------	function M_updateCoordinates(offsetToo) {		//Aggiorna le coordinate del nodo relative ell'effective parent node e, se richiesto, quelle relative		//all'offsetParent assoluto, ovvero il nodo document.body.		//NOTA!!!		//SEMBRA FUNZIONARE, MA E' INAFFIDABILE		try {			if (this.node) {				//Calcola le coordinate relative.				this.left = this.node.offsetLeft				this.right = this.node.offsetLeft + this.node.offsetWidth				this.top = this.node.offsetTop				this.bottom = this.node.offsetTop + this.node.offsetHeight				//Calcola le coordinate assolute.				if (offsetToo) {					this.offsetLeft = this.node.offsetLeft					this.offsetTop = this.node.offsetTop					var parent = this.node.offsetParent					while (parent) {						this.offsetLeft += parent.offsetLeft						this.offsetTop += parent.offsetTop						//Correzione dei bordi						if (parent.clientLeft && parent.offsetLeft != 0 && parent.offsetTop != 0) {							this.offsetLeft += parent.clientLeft							this.offsetTop += parent.clientTop						}						//Offset parent successivo						parent = parent.offsetParent					}					this.offsetRight = this.offsetLeft + this.node.offsetWidth					this.offsetBottom = this.offsetTop + this.node.offsetHeight				}			}		}		catch(e) {QException(e, "QNode.updateCoordinates")}	}}