/*
	Sniffer

  Cercherò di ridurre al massimo la parte di sniffing, 
  per puntare su una  rilevazione d'oggetto, quando possibile

*/

ua = navigator.userAgent
Op =(window.opera)?1:0
IE =(ua.indexOf("MSIE")>-1 && !Op)?1:0
IE5=(IE && document.getElementById)?1:0
NN6 =(ua.indexOf("Gecko")>-1 && !Op)?1:0




/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*:::::::::::::::  Libreria per la gestione della pagina  :::::::::::::::*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/


function Pagina(riferimento_frame){
	this.finestra = riferimento_frame || window
	this.recuperaLarghezza = function(){
		return (IE||Op)?this.finestra.document.body.offsetWidth-5:this.finestra.innerWidth-2
		}
	this.recuperaAltezza = function(){
		return (IE||Op)?this.finestra.document.body.offsetHeight-5:this.finestra.innerHeight-4
		}
	this.recuperaXcentrale = function(){
		return this.recuperaLarghezza()/2
		}	
	this.recuperaYcentrale = function(){
		return this.recuperaAltezza()/2
		}
	return this
}



/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*:::::::::::::::::	     Libreria    Base        	:::::::::::::::::*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/





function recuperaElementoDaId(attrID){
  
// con la seguente riga recupero e restituisco un elemento dal suo attributo ID
// se non è recuperabile restituisce  null
return (document.all||window.opera)?document.all[attrID]:document.getElementById?document.getElementById(attrID):null
}


function ElementoDinamico(attrID){
	this.ID = attrID
	this.Elemento = recuperaElementoDaId(attrID)

	// definisco una proprietà dell'Elemento che contenga un riferimento al proprio oggetto ElementoDinamico

	this.Elemento.rif = this
	this.riferimento = this.constructor

	if(this.Elemento){

		// con la proprietà css è possibile recuperare e definire tutti i possibili stili

		this.css = this.Elemento.style

		// inanzitutto setto la proprietà position, in modo da ridurre all'osso
		// il codice HTML da inserire nelle nostre pagine

		// if(this.Elemento.tagName=="DIV" && !this.css.position) this.css.position = "absolute"

		// proprietà indispensabili per le animazioni
		this.azione = 0  		// flag per l'animazione
		this.azioni = [] 		// array delle animazioni
		this.dopoAnimazione = null	// azione da compiere al termine di una generica animazione
		this.animazioniInTempo = true
		this.minimoTempoCPU = 20


		this.Trascinabile = false
		this.Bersaglio = false
		this.BersaglioColpito = false
	}
}



	
// definisco una serie di metodi che recuperano la dimensione e la posizione
// I metodi sono pensati per recuperare i valori anche nel caso non siano 
// esplicitamente definiti
ElementoDinamico.prototype.recuperaLarghezza = function(){return (parseInt(this.css.width) ||  this.offsetWidth || this.Elemento.offsetWidth || 0)}
ElementoDinamico.prototype.recuperaAltezza = function(){return (parseInt(this.css.height) || this.offsetHeight || this.Elemento.offsetHeight || 0)}
ElementoDinamico.prototype.recuperaX = function(){return ((this.css.left) ? parseInt(this.css.left) : (this.offsetLeft || this.Elemento.offsetLeft ||0))}
ElementoDinamico.prototype.recuperaY = function(){return ((this.css.top) ? parseInt(this.css.top) : (this.offsetTop || this.Elemento.offsetTop ||0))}


ElementoDinamico.prototype.recuperaPadre = function(){return (this.Elemento.parentElement?this.Elemento.parentElement:this.Elemento.parentNode?this.Elemento.parentNode:null)}

// Metodi che permettono di ricavare le coordinate assolute (rispetto all'angolo a sinistra in alto del documento)
// anche per element annidati in altri elementi.
// Tutti gli elementi DEVONO possedere gli stile left e top per calcolare correttamente le coordinate assolute

function recuperaXassoluta(){ 
	var Xassoluta = 0 
	var Genealogista=arguments.length>0?arguments[0]:this.Elemento
	while(Genealogista && Genealogista.tagName!="BODY"){
		Xassoluta += ((Genealogista.style.left)?parseInt(Genealogista.style.left):Genealogista.offsetLeft?Genealogista.offsetLeft:0)  
		Genealogista = (Genealogista.parentElement?Genealogista.parentElement:Genealogista.parentNode?Genealogista.parentNode:null)
		}
	return Xassoluta
	}


function recuperaYassoluta(){ 
	var Yassoluta = 0 
	var Genealogista=arguments.length?arguments[0]:this.Elemento
	while(Genealogista && Genealogista.tagName!="BODY"){
		Yassoluta += ((Genealogista.style.top)?parseInt(Genealogista.style.top):Genealogista.offsetTop?Genealogista.offsetTop:0) 
		Genealogista = (Genealogista.parentElement?Genealogista.parentElement:Genealogista.parentNode?Genealogista.parentNode:null)
		}
	return Yassoluta
	}


ElementoDinamico.prototype.recuperaXassoluta = recuperaXassoluta
ElementoDinamico.prototype.recuperaYassoluta = recuperaYassoluta

/*
ElementoDinamico.prototype.recuperaXassoluta = function(){ 
						var Xassoluta = 0 
						var Genealogista=this.Elemento
						while(Genealogista && Genealogista.tagName!="BODY"){
							Xassoluta += ((Genealogista.style.left) ? parseInt(Genealogista.style.left) : 0) //(Genealogista.offsetLeft ||0) 
							Genealogista = (Genealogista.parentElement?Genealogista.parentElement:Genealogista.parentNode?Genealogista.parentNode:null)
							}
						return Xassoluta
						}

ElementoDinamico.prototype.recuperaYassoluta = function(){ 
						var Yassoluta = 0 
						var Genealogista=this.Elemento
						while(Genealogista && Genealogista.tagName!="BODY"){
							Yassoluta += ((Genealogista.style.top) ? parseInt(Genealogista.style.top) : 0 )  //(Genealogista.offsetTop ||0)
							Genealogista = (Genealogista.parentElement?Genealogista.parentElement:Genealogista.parentNode?Genealogista.parentNode:null)
							}
						return Yassoluta
						}

*/



// definisco una serie di metodi che settano la dimensione e la posizione 
// e i colori del nostro ElementoDinamico 

ElementoDinamico.prototype.settaLarghezza = function(stileWidth){this.css.width = parseInt(stileWidth)>=0?parseInt(stileWidth):0}
ElementoDinamico.prototype.settaAltezza = function(stileHeight){this.css.height = parseInt(stileHeight)>=0?parseInt(stileHeight):0}
ElementoDinamico.prototype.settaX = function(coordinataX){this.css.left = parseInt(coordinataX)}
ElementoDinamico.prototype.settaY = function(coordinataY){this.css.top = parseInt(coordinataY)}
ElementoDinamico.prototype.settaPosizione = function(coordinataX,coordinataY){this.settaX(coordinataX);this.settaY(coordinataY)}
ElementoDinamico.prototype.settaDimensione = function(Larghezza,Altezza){this.settaLarghezza(Larghezza);this.settaAltezza(Altezza)}
ElementoDinamico.prototype.settaClip = function(taglioSopra,taglioDx,taglioSotto,taglioSx){this.css.clip = "rect("+taglioSopra+", "+taglioDx+", "+taglioSotto+", "+taglioSx+")"}

ElementoDinamico.prototype.settaColoreSfondo = function(stileBackgroundColor){this.css.backgroundColor = stileBackgroundColor}
ElementoDinamico.prototype.settaColoreTesto = function(stileColor){this.css.color = stileColor}


// definisco altri metodi per la visibilità e per l'applicazione dei filtri (only IE5.5+) dei livelli

ElementoDinamico.prototype.visibile = function(){this.css.visibility = "visible"}
ElementoDinamico.prototype.invisibile = function(){this.css.visibility = "hidden"}

ElementoDinamico.prototype.settaFiltri = function(stileFiltri){this.css.filter = stileFiltri} //esempio inserimento valore: alpha(opacity=60); 


// funzione universale di settaggio stili

ElementoDinamico.prototype.settaStile = function(stile,valore){this.css[stile] = valore}
ElementoDinamico.prototype.recuperaStile = function(stile){return this.css[stile]}


// definisco un metodo che consenta di modificare un insieme di stili
// nota: non posso usare className, non supportato da Opera

ElementoDinamico.prototype.settaArrayDiStili = function(ArrayDiStili){
				   	var stile
   					for(elementoA in ArrayDiStili) {
						stile = ArrayDiStili[elementoA].split("=")
						this.css[stile[0]] = stile[1]
  						 }
					}







/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*:::::::::::::     Libreria per la Gestione degli Eventi  	:::::::::*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/


/**************************************************************************

		PRINCIPI DEL CODICE UTILIZZATO
			

  Anche per la gestione degli eventi (come per quella delle animazioni)
  mi appogio ad un "motore esterno" ai metodi veri e propri (settaGestoreEvento),
  che mi permette di semplificare la scrittura dei singoli metodi per la gestione
  degli eventi.

  Per far questo però, occorre scegliere per le collezioni che conterrano i riferimenti
  alle funzioni e ai parametri da lanciare, nomi appropriati, in modo da poter sfruttare
  la concatenazione delle stringhe ed unificare così il codice.

  In questo caso, ad esempio, le funzioni da lanciare al click su di un generico ElementoDinamico
  sono contenute nell'array dell'elemento chiamato "onclicks", quelle lanciate al mouseover, sono
  contenute nell'array "onmouseovers".

  Sfruttando questa scelta posso unificare il codice per la definizione di questi array scrivendo:

  this.Elemento["on"+tipo_evento+"s"] = []

  questa sintassi dipende dal valore di "tipo_evento" ed equivale a:

  this.Elemento.onclicks = [] (nel caso tipo_evento="click")
  this.Elemento.onmouseovers = [] (nel caso tipo_evento="mouseover")

  
  A questo punto è facile estendere questo concetto per definire non solo tutti gli array di cui 
  ho bisogno, ma anche per settare l'event Listener vero e proprio del nostro Elemento con il codice:

  this.Elemento["on"+tipo_evento] = function(){	 ...  }

  che equivale a:

  this.Elemento.onclick = function(){  ...  } (nel caso tipo_evento="click")
  this.Elemento.onmouseover = function(){  ...  } (nel caso tipo_evento="mouseover")
  


		PRINCIPI DEL SIGNALS-SLOTS (SEGNALA-INCANALA)

  Questo termine, familiare in molti linguaggi di programmazione, è utilizzato per descrivere il compito del
  vero e proprio event Listener associato ad un evento particolare (es: onclick).
  Questa funzione (che nel nostro caso è una funzione anonima) è infatti l'unica che reagisce direttamente
  all'evento associato e proprio per questo motivo è la funzione che si deve incaricare di distribuire (slot) 
  tale evento (signal) a tutte le nostre richieste.

  La necessità di questa tecnica deriva dal fatto che quando si setta un event Listener via JavaScript, con:

  Elemento.onclick = function(){  ...  }

  qualsiasi altro tentativo di associare un'eventuale altra funzione all'evento, va a sovrascrivere la 
  proprietà onclick cancellando il vecchio riferimento.
  Questo impedisce di poter eseguire due funzioni nello stesso evento settando via JavaScript due 
  funzioni differenti. es:

  Elemento.onclick = functione1 
  Elemento.onclick = functione2  (questa sovrascrive la proprietà onclick cancellando la chiamata alla funzione1) 



		IMPLEMENTAZIONE DEL SIGNALS-SLOTS (SEGNALA-INCANALA)

  Chiarito questo aspetto, il principio del signals-slots è quello di utilizzare l'unico event Listener "reale" 
  per lanciare tutte le funzioni che vogliamo.
  Il codice che ho usato, considerando ad es. l'evento click (tipo_evento = "click") è:

  this.Elemento.onclick = function(){	// è la funzione anonima che si incarica del signals-slots

// onclicks è un'array (precedentemente definito) che contiene i puntatori alle funzioni
// che vogliamo lanciare al click
	 for(i=0; i<this.onclicks.length;i++) {
//devo controllare se il puntatore alla funzione sia presente (può essere stato cancellato)
		if(this.onclicks[i]) {

// ora costruisco una stringa (argomenti) che conterrà tutti gli argomenti passati alle varie funzioni.
// gli argomenti sono contenuti nell'array bi-dimensionale onclickargs (la prima dimensione individua
// le diverse funzioni, la seconda contiene i parametri passati ad ogni funzione)
			var argomenti = ""
			for(j=0;j<this.onclickargs[i].length-1;j++)
				argomenti +="this.onclickargs[i]["+j+"],"

			argomenti += "this.onclickargs[i]["+(this["onclickargs"][i].length-1)+"]"

// Sono "costretto" ad usare eval per poter gestire il numero variabile di parametri passati separati
// dalle virgole nelle varie chiamate. Nel dettaglio sono proprio le virgole che non possono essere definite
// se non utilizzando eval.
			eval("this.onclicks[i]("+argomenti+")" )
		} 
	}
  }

		NOTE

1)La più importante nota da fare è quella sull'uso della keyword "this".
  Se si utilizzano questi metodi non è possibile usare this all'interno delle funzioni
  per riferisi all'oggetto in questione.
  Questo (che a prima vista può sembrare un problema rilevante, soprattutto per chi si
  destreggia un po' col JavaScript) non è un grosso ostacolo, infatti questi metodi sono
  utilizzati per definire eventi su oggetti che si conoscono e i cui riferimenti 
  possono quindi essere passati come parametri.
  E' comunque sempre possibile usare il tradizionale metodo di settare gli event Listener
  via HTML.

2)La seconda nota da fare è quella del passagio dell'oggetto event. Questo è
  utile nella gestione (avanzata) degli eventi.
  Se si desidera utilizzare l'oggetto event nella funzione, il parametro DEVE essere
  definito nella funzione come ULTIMO ARGOMENTO. Fatto questo non occorre passarlo
  come parametro utilizzando i metodi della libreria (infatti viene fatto automaticamente).


		ESEMPI

  1) Per settare come listener una funzione senza parametri è possibile 
     usare le seguenti sintassi:
	
	function avvisa(){alert("CIAO")}

	a) ElementoDinamico.settaListenerSuClick(avvisa)
	b) ElementoDinamico.settaListenerSuClick(function(){alert("CIAO")})

  2) Per settare una funzione con parametri:

	function avvisa(chi,cosa){alert(chi+" dice: "+cosa)}

	a) ElementoDinamico.settaListenerSuClick(avvisa,"standard","CIAO!")
	b) ElementoDinamico.settaListenerSuClick(function(chi,cosa){alert(chi+" dice: "+cosa)},"standard","CIAO!")

  3) Per settare una funzione con parametro l'oggetto del metodo stesso:

	function avvisaX(oggetto){alert(oggetto.recuperaX())}

	a) ElementoDinamico.settaListenerSuClick(avvisaX,ElementoDinamico)
	b) ElementoDinamico.settaListenerSuClick(function(oggetto){alert(oggetto.recuperaX())},ElementoDinamico)
	c) ElementoDinamico.settaListenerSuClick(function(){alert(ElementoDinamico.recuperaX())})

	
  4) Per settare una funzione tra cui un parametro è l'oggetto event:

	function avvisa(chi,cosa,evento){alert(chi+" dice al "+evento.type+": "+cosa)}

	a) ElementoDinamico.settaListenerSuClick(avvisa,"standard","CIAO!")
	b) ElementoDinamico.settaListenerSuClick(function(chi,cosa,evento){alert(chi+" dice al "+evento.type+": "+cosa)},"standard","CIAO!")
	
**************************************************************************/


ElementoDinamico.prototype.settaGestoreEvento = function(tipo_evento,puntatoreFunzione,args){
			if(!this.Elemento["on"+tipo_evento+"s"]) {
				this.Elemento["on"+tipo_evento+"s"] = []
				this.Elemento["on"+tipo_evento+"args"] = []
				this.Elemento["on"+tipo_evento+"AreaS"] = []
				}

			var indice = this.Elemento["on"+tipo_evento+"s"].length

			this.Elemento["on"+tipo_evento+"s"][indice] = puntatoreFunzione
			this.Elemento["on"+tipo_evento+"args"][indice] = []

			//per l'area sensibile
			this.Elemento["on"+tipo_evento+"AreaS"][indice] = null

			for(sLi=1;sLi<args.length;sLi++) {
				this.Elemento["on"+tipo_evento+"args"][indice][sLi-1] = args[sLi]
				}
/*
			this.Elemento["on"+tipo_evento] = function(e){	
//devo controllare se la funzione è stata cancellata all'interno del ciclo
				for(sLi=0; sLi<this["on"+tipo_evento+"s"].length;sLi++) {
					if(this["on"+tipo_evento+"s"][sLi]) {
						var argomenti = ""
						for(sLj=0;sLj<this["on"+tipo_evento+"args"][sLi].length;sLj++)
							argomenti +="this.on"+tipo_evento+"args[sLi]["+sLj+"],"

						//passo sempre l'evento come ultimo parametro
						argomenti += "e"
						eval("this.on"+tipo_evento+"s[sLi]("+argomenti+")" )
						} 
					}
				}
*/
			this.settaListeners(tipo_evento)
			}


ElementoDinamico.prototype.eliminaGestoreEvento = function(tipo_evento,puntatoreFunzione){
			if(this.Elemento["on"+tipo_evento+"s"]){
				var numeroListener = 0 
				for(eGi=0;eGi<this.Elemento["on"+tipo_evento+"s"].length;eGi++){
					if(this.Elemento["on"+tipo_evento+"s"][eGi] == puntatoreFunzione) {
						this.Elemento["on"+tipo_evento+"s"][eGi] = null
						this.Elemento["on"+tipo_evento+"args"][eGi] = null
						}
					if(this.Elemento["on"+tipo_evento+"s"][eGi]) numeroListener++
					}
				if(numeroListener == 0) this.Elemento["on"+tipo_evento+"s"].length = 0
				}
			
			}

ElementoDinamico.prototype.eliminaTuttiGestoriEvento = function(tipo_evento){
			if(this.Elemento["on"+tipo_evento+"s"]) {
				for(eTGi=0;eTGi<this.Elemento["on"+tipo_evento+"s"].length;eTGi++){
						this.Elemento["on"+tipo_evento+"s"][eTGi] = null
						this.Elemento["on"+tipo_evento+"args"][eTGi] = null	
					}
				this.Elemento["on"+tipo_evento+"s"].length = 0
				}
			}











/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*:::::::::::::         Libreria per le Aree Sensibili      	:::::::::*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/






ElementoDinamico.prototype.settaGestoreEventoAS = function(tipo_evento,areaSensibile,puntatoreFunzione,args){
			if(!this.Elemento["on"+tipo_evento+"s"]) {
				this.Elemento["on"+tipo_evento+"s"] = []
				this.Elemento["on"+tipo_evento+"args"] = []
				this.Elemento["on"+tipo_evento+"AreaS"] = []

				}

			var indice = this.Elemento["on"+tipo_evento+"s"].length

			this.Elemento["on"+tipo_evento+"s"][indice] = puntatoreFunzione
			this.Elemento["on"+tipo_evento+"args"][indice] = []
			this.Elemento["on"+tipo_evento+"AreaS"][indice] = []
			this.Elemento["on"+tipo_evento+"AreaS"][indice] = areaSensibile

			for(sLi=2;sLi<args.length;sLi++) {
				this.Elemento["on"+tipo_evento+"args"][indice][sLi-2] = args[sLi]
				}


/*
			this.Elemento["on"+tipo_evento] = function(e){	
				for(sLi=0; sLi<this["on"+tipo_evento+"s"].length;sLi++) {
					if(this["on"+tipo_evento+"s"][sLi]) {
						if(this.rif.inAreaSensibile(e,tipo_evento,sLi)){
							var argomenti = ""
							for(sLj=0;sLj<this["on"+tipo_evento+"args"][sLi].length;sLj++)
								argomenti +="this.on"+tipo_evento+"args[sLi]["+sLj+"],"

							//passo sempre l'evento come ultimo parametro
							argomenti += "e"
							eval("this.on"+tipo_evento+"s[sLi]("+argomenti+")" )
							}
						} 
					}
				}
*/

			this.settaListeners(tipo_evento)
			}



ElementoDinamico.prototype.inAreaSensibile = function(e,tipo_evento,indice){
			if(!e) e = window.event
			e.X = e.offsetX?e.offsetX:e.layerX
			e.Y = e.offsetY?e.offsetY:e.layerY
			e.generatore = e.srcElement?e.srcElement:e.target
			var arrayAS = []
			arrayAS = this.Elemento["on"+tipo_evento+"AreaS"][indice]

			if(e.generatore != this.Elemento) return false
			return (!arrayAS || (e.X>arrayAS[0] && e.X<arrayAS[1] && e.Y>arrayAS[2] && e.Y<arrayAS[3]))?true:false
			}


ElementoDinamico.prototype.recuperaAreaSensibile = function(){
			return [this.recuperaX(),this.recuperaX()+this.recuperaLarghezza(),this.recuperaY(),this.recuperaY()+this.recuperaAltezza()]
			}

ElementoDinamico.prototype.settaListenerSuClick_areaSensibile = function(areaSensibile,puntatoreFunzione){
			var __aS__ = areaSensibile.constructor==Array?areaSensibile:areaSensibile.recuperaAreaSensibile() 			
			this.settaGestoreEventoAS("click",__aS__,puntatoreFunzione,arguments)
			}


ElementoDinamico.prototype.settaListeners = function(tipo_evento){

			this.Elemento["on"+tipo_evento] = function(e){	
				for(sLi=0; sLi<this["on"+tipo_evento+"s"].length;sLi++) {
					if(this["on"+tipo_evento+"s"][sLi]) {
						if(!this["on"+tipo_evento+"AreaS"][sLi] || this.rif.inAreaSensibile(e,tipo_evento,sLi)){
							var argomenti = ""
							for(sLj=0;sLj<this["on"+tipo_evento+"args"][sLi].length;sLj++)
								argomenti +="this.on"+tipo_evento+"args[sLi]["+sLj+"],"

							//passo sempre l'evento come ultimo parametro
							argomenti += "e"
							eval("this.on"+tipo_evento+"s[sLi]("+argomenti+")" )
							}
						} 
					}
				}


/*
			this.Elemento["on"+tipo_evento] = function(e){	
				for(sLi=0; sLi<this["on"+tipo_evento+"s"].length;sLi++) {
					if(this["on"+tipo_evento+"s"][sLi]) {
						var argomenti = ""
						for(sLj=0;sLj<this["on"+tipo_evento+"args"][sLi].length;sLj++)
							argomenti +="this.on"+tipo_evento+"args[sLi]["+sLj+"],"

						//passo sempre l'evento come ultimo parametro
						argomenti += "e"
						eval("this.on"+tipo_evento+"s[sLi]("+argomenti+")" )
						} 
					}
				}
*/
			}
















ElementoDinamico.prototype.settaListenerSuClick = function(puntatoreFunzione){
			this.settaGestoreEvento("click",puntatoreFunzione,arguments)
			}

ElementoDinamico.prototype.settaListenerSuMouseOver = function(puntatoreFunzione){
			this.settaGestoreEvento("mouseover",puntatoreFunzione,arguments)
			}

ElementoDinamico.prototype.settaListenerSuMouseOut = function(puntatoreFunzione){
			this.settaGestoreEvento("mouseout",puntatoreFunzione,arguments)
			}

ElementoDinamico.prototype.eliminaListenerSuClick = function(puntatoreFunzione){
			this.eliminaGestoreEvento("click",puntatoreFunzione)	
			}

ElementoDinamico.prototype.eliminaListenerSuMouseOver = function(puntatoreFunzione){
			this.eliminaGestoreEvento("mouseover",puntatoreFunzione)	
			}

ElementoDinamico.prototype.eliminaListenerSuMouseOut = function(puntatoreFunzione){
			this.eliminaGestoreEvento("mouseout",puntatoreFunzione)	
			}

ElementoDinamico.prototype.eliminaTuttiListenerSuClick = function(){
			this.eliminaTuttiGestoriEvento("click")
			}

ElementoDinamico.prototype.eliminaTuttiListenerSuMouseOver = function(){
			this.eliminaTuttiGestoriEvento("mouseover")
			}

ElementoDinamico.prototype.eliminaTuttiListenerSuMouseOut = function(){
			this.eliminaTuttiGestoriEvento("mouseout")
			}




ElementoDinamico.prototype.settaListenerSuMouseDown = function(puntatoreFunzione){
			this.settaGestoreEvento("mousedown",puntatoreFunzione,arguments)
			}

ElementoDinamico.prototype.eliminaListenerSuMouseDown = function(puntatoreFunzione){
			this.eliminaGestoreEvento("mousedown",puntatoreFunzione)	
			}

ElementoDinamico.prototype.eliminaTuttiListenerSuMouseDown = function(){
			this.eliminaTuttiGestoriEvento("mousedown")
			}

ElementoDinamico.prototype.settaListenerSuMouseUp = function(puntatoreFunzione){
			this.settaGestoreEvento("mouseup",puntatoreFunzione,arguments)
			}

ElementoDinamico.prototype.eliminaListenerSuMouseUp = function(puntatoreFunzione){
			this.eliminaGestoreEvento("mouseup",puntatoreFunzione)	
			}

ElementoDinamico.prototype.eliminaTuttiListenerSuMouseUp = function(){
			this.eliminaTuttiGestoriEvento("mouseup")
			}

ElementoDinamico.prototype.settaListenerSuMouseMove = function(puntatoreFunzione){
			this.settaGestoreEvento("mousemove",puntatoreFunzione,arguments)
			}

ElementoDinamico.prototype.eliminaListenerSuMouseMove = function(puntatoreFunzione){
			this.eliminaGestoreEvento("mousemove",puntatoreFunzione)	
			}

ElementoDinamico.prototype.eliminaTuttiListenerSuMouseMove = function(){
			this.eliminaTuttiGestoriEvento("mousemove")
			}





/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*:::::::::::::::::	Libreria per le Animazioni	:::::::::::::::::*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/






// Il metodo gestoreClock, ha lo scopo di interrompere
// qualsiasi temporizzazione alla fine delle animazioni,
// anche se queste sono lanciate in tempi diversi

ElementoDinamico.prototype.gestoreClock = function(indiceGestore){
			var contogCi = 0

			for(gCi=0;gCi<this.azioni.length;gCi++) contogCi += (this.azioni[gCi])?1:0
			if(contogCi==1){
				clearInterval(this.azioni[indiceGestore])
				this.azioni[indiceGestore] = null
				this.azione = 0
				if(this.dopoAnimazione) this.azioneFinale()
				}
			}


// Il metodo terminaAnimazione serve per terminare ogni animazione
// attiva sul ElementoDinamico. E' utile soprattutto per gestire
// le animazioni gestite da mouse (o da utente in generale)

ElementoDinamico.prototype.terminaAnimazione = function(){
			for(tAi=0;tAi<this.azioni.length;tAi++) {
				clearInterval(this.azioni[tAi])
				this.azioni[tAi] = null
				}
			this.azione = 0
			this.dopoAnimazione = null
			}


// Il metodo azioneFinale serve per eseguire un'azione
// al termine dell'animazione definita.
// Terminare l'animazione prima della sua conclusione inibisce 
// l'esecuzione dell'azione finale.

ElementoDinamico.prototype.azioneFinale = function(){
			if(typeof(this.dopoAnimazione) == "string")
				eval(this.dopoAnimazione)
			else this.dopoAnimazione() 

			//eval(this.dopoAnimazione)

			this.dopoAnimazione = null
			}
			

// Il metodo animazione è il vero e proprio motore per ogni animazione.
// Ciò che contraddistingue un tipo d'animazione dall'altra è l'ultimo
// parametro "grandezza", una stringa che contiene il nome della grandezza
// da modificare.
// Può essere usato per ogni tipo di animazione, definendo opportunamente
// i nomi delle funzioni e delle proprietà.

ElementoDinamico.prototype.animazione = function(valoreFinale,passo,indiceAzione,grandezza){
			var direzione = (valoreFinale > this[grandezza]) ? 1 : -1
			this[grandezza]+=direzione*passo

			if(direzione*this[grandezza]<Math.abs(valoreFinale)) this["setta"+grandezza](this[grandezza])
			else{
				clearInterval(this.azioni[indiceAzione])
				this.azioni[indiceAzione] = null
				this["setta"+grandezza](valoreFinale)
				}
			}




/*:::::::::::::::::	Metodi per le animazioni 	:::::::::::::::::*/

// Questi sono classici metodi per le animazioni, 
// in cui è possibile settare direttamente i passi delle varie animazioni e
// i ritardi tra un'animazione e l'altra

ElementoDinamico.prototype.muoviIn = function(posX,posY,passoX,passoY,ritardoX,ritardoY){
			this.X = this.recuperaX()
			this.Y = this.recuperaY()
			var diffX = Math.abs(posX-this.X)
			var diffY = Math.abs(posY-this.Y)


			if(diffX) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+posX+","+(passoX || 1)+","+this.azioni.length+",'X')",(ritardoX || this.minimoTempoCPU) )
			if(diffY) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+posY+","+(passoY || 1)+","+this.azioni.length+",'Y')",(ritardoY || this.minimoTempoCPU) )
			
			//if(diffX) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+posX+","+(passoX || 1)+","+this.azioni.length+",'X')",(ritardoX || this.minimoTempoCPU) ))
			//if(diffY) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+posY+","+(passoY || 1)+","+this.azioni.length+",'Y')",(ritardoY || this.minimoTempoCPU) ))

			// gestione dei clock (potrebbe essere accellerata)
			if(!this.azione) {
				this.azione = 1
				this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",this.minimoTempoCPU)
//				this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",1000))
				}
			}


ElementoDinamico.prototype.ridimensionaA = function(dimL,dimA,passoL,passoA,ritardoL,ritardoA){
			this.Larghezza = this.recuperaLarghezza()
			this.Altezza = this.recuperaAltezza()
			var diffL = Math.abs(dimL-this.Larghezza)
			var diffA = Math.abs(dimA-this.Altezza)

			if(diffL) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+dimL+","+(passoL || 1)+","+this.azioni.length+",'Larghezza')",(ritardoL || this.minimoTempoCPU) )
			if(diffA) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+dimA+","+(passoA || 1)+","+this.azioni.length+",'Altezza')",(ritardoA || this.minimoTempoCPU) )

//			if(diffL) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+dimL+","+(passoL || 1)+","+this.azioni.length+",'Larghezza')",(ritardoL || this.minimoTempoCPU) ))
//			if(diffA) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+dimA+","+(passoA || 1)+","+this.azioni.length+",'Altezza')",(ritardoA || this.minimoTempoCPU) ))

			// gestione dei clock
			if(!this.azione) {
				this.azione = 1
				this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",this.minimoTempoCPU)
//				this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",1000))
				}
			}

ElementoDinamico.prototype.muoviDi = function(posX,posY,passoX,passoY,ritardoX,ritardoY){
			this.muoviIn((this.recuperaX()+posX),(this.recuperaY()+posY),passoX,passoY,ritardoX,ritardoY)
			}

ElementoDinamico.prototype.ridimensionaDi = function(dimL,dimA,passoL,passoA,ritardoL,ritardoA){
			this.ridimensionaA((this.recuperaLarghezza()+dimL),(this.recuperaAltezza()+dimA),passoL,passoA,ritardoL,ritardoA)
			}




// Metodi per la gestione dell'opacità.
//
// Sono strutturate nella stessa maniera dei metodi precedenti,
// facendo però attenzione al crossbrowser, necessario in questo caso
conto = 0
ElementoDinamico.prototype.settaOpacita = function(stileOpacity){
			if(IE5) this.css.filter="alpha(opacity="+stileOpacity+")"
			else if(NN6) { //escamotage per aggirare un bug di Mozilla
				if(stileOpacity==100){
					this.css.MozOpacity=0.5
					this.css.MozOpacity=0.99
					this.css.MozOpacity=1
					}
				else this.css.MozOpacity=(stileOpacity/100)
				}
			}

ElementoDinamico.prototype.recuperaOpacita = function(){
			var ind,opacitaAttuale
			if(IE5) opacitaAttuale = (ind=this.css.filter.indexOf("alpha(opacity=")>-1) ? parseInt(this.css.filter.substr(ind+13)) : 100
			else if(NN6) opacitaAttuale = (this.css.MozOpacity) ? this.css.MozOpacity*100 : 100
			else opacitaAttuale = null
			return opacitaAttuale
			}
			

ElementoDinamico.prototype.sfumaA = function(opacitaFinale,passoOp,ritardoOp){
			this.Opacita = this.recuperaOpacita()
			if(this.Opacita>=0){
				var diffOp = Math.abs(opacitaFinale-this.Opacita)
				if(diffOp) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+opacitaFinale+","+(passoOp || 1)+","+this.azioni.length+",'Opacita')",(ritardoOp || this.minimoTempoCPU) )
			//	if(diffOp) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+opacitaFinale+","+(passoOp || 1)+","+this.azioni.length+",'Opacita')",(ritardoOp || this.minimoTempoCPU) ))
 
				// gestione dei clock
				if(!this.azione) {
					this.azione = 1
					this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",1000)
				//	this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",1000))
					}
				}
			}

ElementoDinamico.prototype.sfumaDi = function(opacitaFinale,passoOp,ritardoOp){
			this.sfumaA((this.recuperaOpacita()+opacitaFinale),passoOp,ritardoOp)
			}






/*:::::::::::::::::	Metodi per le animazioni coordinate	:::::::::::::::::*/

// Questi metodi eseguono le animazioni in un tempo determinato (passato come parametro)
// All'interno dei vari metodi, vengono calcolati i passi delle varie animazioni.
// L'utilizzo di questi metodi consente coordinare le varie animazioni, eseguendole 
// tutte in uno specificato lasso di tempo (tempoAnimazione).
// Tutti i metodi hanno gli stessi nomi dei corrispettivi definti in precedenza con il prefisso "T".


ElementoDinamico.prototype.TmuoviIn = function(posX,posY,tempoAnimazione){
			this.X = this.recuperaX()
			this.Y = this.recuperaY()
			var diffX = Math.abs(posX-this.X)
			var diffY = Math.abs(posY-this.Y)

			var passoX = diffX/(tempoAnimazione/this.minimoTempoCPU)
			var passoY = diffY/(tempoAnimazione/this.minimoTempoCPU)
			
			if(diffX) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+posX+","+passoX+","+this.azioni.length+",'X')",this.minimoTempoCPU)
			if(diffY) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+posY+","+passoY+","+this.azioni.length+",'Y')",this.minimoTempoCPU)
//			if(diffX) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+posX+","+passoX+","+this.azioni.length+",'X')",this.minimoTempoCPU))
//			if(diffY) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+posY+","+passoY+","+this.azioni.length+",'Y')",this.minimoTempoCPU))

			// gestione dei clock
			if(!this.azione) {
				this.azione = 1
				this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",this.minimoTempoCPU)
//				this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",1000))
				}
			}


ElementoDinamico.prototype.TridimensionaA = function(dimL,dimA,tempoAnimazione){
			this.Larghezza = this.recuperaLarghezza()
			this.Altezza = this.recuperaAltezza()
			var diffL = Math.abs(dimL-this.Larghezza)
			var diffA = Math.abs(dimA-this.Altezza)

			var passoL = diffL/(tempoAnimazione/this.minimoTempoCPU)
			var passoA = diffA/(tempoAnimazione/this.minimoTempoCPU)
			
			if(diffL) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+dimL+","+passoL+","+this.azioni.length+",'Larghezza')",this.minimoTempoCPU)
			if(diffA) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+dimA+","+passoA+","+this.azioni.length+",'Altezza')",this.minimoTempoCPU)
//			if(diffL) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+dimL+","+passoL+","+this.azioni.length+",'Larghezza')",this.minimoTempoCPU))
//			if(diffA) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+dimA+","+passoA+","+this.azioni.length+",'Altezza')",this.minimoTempoCPU))

			// gestione dei clock
			if(!this.azione) {
				this.azione = 1
				this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",this.minimoTempoCPU)
//				this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",1000))
				}
			}

ElementoDinamico.prototype.TmuoviDi = function(posX,posY,tempoAnimazione){
			this.TmuoviIn((this.recuperaX()+posX),(this.recuperaY()+posY),tempoAnimazione)
			}

ElementoDinamico.prototype.TridimensionaDi = function(dimL,dimA,tempoAnimazione){
			this.TridimensionaA((this.recuperaLarghezza()+dimL),(this.recuperaAltezza()+dimA),tempoAnimazione)
			}

ElementoDinamico.prototype.TsfumaA = function(opacitaFinale,tempoAnimazione){
			this.Opacita = this.recuperaOpacita()
			if(this.Opacita>=0){
				var diffOp = Math.abs(opacitaFinale-this.Opacita)
				var passoOp = diffOp/(tempoAnimazione/this.minimoTempoCPU)
				
				if(diffOp) this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+opacitaFinale+","+passoOp+","+this.azioni.length+",'Opacita')",this.minimoTempoCPU)
//				if(diffOp) this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.animazione("+opacitaFinale+","+passoOp+","+this.azioni.length+",'Opacita')",this.minimoTempoCPU))

				// gestione dei clock
				if(!this.azione) {
					this.azione = 1
					this.azioni[this.azioni.length] = setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",this.minimoTempoCPU)
//					this.azioni.push(setInterval("recuperaElementoDaId('"+this.Elemento.id+"').rif.gestoreClock("+this.azioni.length+")",1000))
					}
				}
			}

ElementoDinamico.prototype.TsfumaDi = function(opacitaFinale,tempoAnimazione){
			this.TsfumaA((this.recuperaOpacita()+opacitaFinale),tempoAnimazione)
			}





/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*:::::::::::::::::     Libreria per il Drag & Drop         :::::::::::::*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/


/**************************************************************************

		PRINCIPIO DEL CODICE UTILIZZATO
			
  Il principio su cui si basa la libreria per il Drag & Drop è
  semplicissimo: si può trascinare solo un elemento alla volta!!

  Questo ci consente di utilizzare l'oggetto drag_and_drop, la cui 
  visibilità è globale, per eseguire tutti i nostri drag'n'drop.
  In pratica drag_and_drop conterrà di volta in volta il riferimento
  all'ElementoDinamico impegnato nel trascinamento.

  La libreria fornisce 2 metodi:

  ElementoDinamico.rendiTrascinabile([coordinata,ElementoDnd,minX,maxX,minY,maxY,ElementoRiferimento])

	Il metodo consente di rendere un ElementoDinamico trascinabile per le 
	operazioni di Drag & Drop.

	parametri:
	  _ coordinata : ("X","Y",null) permette di scegliere un solo asse di trascinamento
	  _ ElementoDnd: (ElementoDinamico) elemento attivo del Drag&Drop
	  _ minX,maxX,minY,maxY :(int,null) permettono di definire 
			una regione per il Drag&Drop
	  _ ElementoRiferimento: ElementoDinamico che contiene l'elemento reso Trascinabile




  ElementoDinamico.rendiNonTrascinabile()

	Il metodo elimina la "trascinabilità" di un ElementoDinamico, impedendone
	il Drag & Drop.


		IMPLEMENTAZIONE
  
  Il D.&D. deve gestire 3 eventi: MouseDown,MouseMove,MouseUp. I.p:

  MouseDown : è "catturato", ovviamente, dall'elemento che si vuole trascinare.
		La funzione lanciata (____DragAndDropSUMouseDown____) ha visibilità
		anch'essa globale, e si preoccupa di:
		1) settare i vari parametri di offset del puntatore del mouse
		2) definire l'event handler document.onmousemove 
		3) definire, se non ne è gia stato definito uno in precedenza,
		   l'event handler document.onmouseup

  MouseMove : è gestito dall'oggetto document (per garantire la possibilità di
		spostamento ovunque) ed è lanciato il metodo Trascina, che si
		preoccupa di eseguire gli spostamenti dell'oggetto in trascinamento
		nelle zone concesse.

  MouseUp : è gestito dall'oggetto document e lancia la funzione globale 
		____DragAndDropSUMouseUp____ che si occupa di annullare il
		document.onmousemove e di ripristinare le condizioni "di riposo"
		dell'oggetto trascinato.


		NOTE

  E' presente la flag globale ____NonGestireZIndex____  per la gestione
  degli z-index al rilascio degli elementi trascinati.
  Se la variabile viene lasciata a false (per default) gli elementi 
  rilasciati saranno automaticamente riportati ad uno z-index pari a 1.
  Se settata a true, non modifica la z-index (che nel trascinamento è 10)
  lasciando il compito allo "scripter".

  La libreria non è ancora apposto per il fatto che consente il drag&drop
  solo di elementi al livello del document e non di elementi annidati,
  per i quali occorre sistemare le coordinate di riferimento
  
**************************************************************************/



ElementoDinamico.prototype.Trascina = function(e,coordinata,minX,maxX,minY,maxY){
			if(drag_and_drop.Trascinabile){
				if(!e) e = window.event
				var MinX = (minX||0) + drag_and_drop.RifX
				var MaxX = (maxX||0) + drag_and_drop.RifX
				var MinY = (minY||0) + drag_and_drop.RifY
				var MaxY = (maxY||0) + drag_and_drop.RifY
				var posizione_Mouse_X = e.clientX-drag_and_drop.DownX+(window.opera?0:document.body.scrollLeft)
				var posizione_Drag_X = coordinata=="X"||!coordinata?minX!=null&&posizione_Mouse_X<=MinX?minX:maxX!=null&&posizione_Mouse_X>=MaxX?maxX:posizione_Mouse_X-drag_and_drop.RifX:drag_and_drop.recuperaX()
				var posizione_Mouse_Y = e.clientY-drag_and_drop.DownY+(window.opera?0:document.body.scrollTop)
				var posizione_Drag_Y = coordinata=="Y"||!coordinata?minY!=null&&posizione_Mouse_Y<=MinY?minY:maxY!=null&&posizione_Mouse_Y>=MaxY?maxY:posizione_Mouse_Y-drag_and_drop.RifY:drag_and_drop.recuperaY()

				if(!isNaN(posizione_Drag_X)&&!isNaN(posizione_Drag_Y)) drag_and_drop.settaPosizione(posizione_Drag_X,posizione_Drag_Y)

				if(drag_and_drop.azioniSulTrascinamento)
					for(AsT=0;AsT<drag_and_drop.azioniSulTrascinamento.length;AsT++)
						if(drag_and_drop.azioniSulTrascinamento[AsT]) {
							if(typeof(drag_and_drop.azioniSulTrascinamento[AsT]) == "string")
								eval(drag_and_drop.azioniSulTrascinamento[AsT])
							else drag_and_drop.azioniSulTrascinamento[AsT]() 
							}
//drag_and_drop.azioniSulTrascinamento[AsT]()
				}
			}


____DragAndDropSUMouseDown____ = function(El,coordinata,minX,maxX,minY,maxY,ElementoRiferimento,offsetDaRiferimentoX,offsetDaRiferimentoY,e){
			drag_and_drop = El
			if(!e) e=window.event 
			drag_and_drop.inTrascinamento = true
			drag_and_drop.DownX = (e.offsetX?e.offsetX:e.layerX) + drag_and_drop.offset_drag_n_drop_X 
			drag_and_drop.DownY = (e.offsetY?e.offsetY:e.layerY) + drag_and_drop.offset_drag_n_drop_Y
			drag_and_drop.RifX = (ElementoRiferimento?ElementoRiferimento.recuperaX()+(offsetDaRiferimentoX||0):0)
			drag_and_drop.RifY = (ElementoRiferimento?ElementoRiferimento.recuperaY()+(offsetDaRiferimentoY||0):0)
			drag_and_drop.settaStile("zIndex",10)

			document.onmousemove = function(e){drag_and_drop.Trascina(e,coordinata,minX,maxX,minY,maxY);return false}
			if(!document.onmouseup) document.onmouseup = ____DragAndDropSUMouseUp____
			}


____DragAndDropSUMouseUp____ = function(){
			document.onmousemove = null
			if(window.drag_and_drop) {
				if(!____NonGestireZIndex____) drag_and_drop.settaStile("zIndex",1)
				drag_and_drop.inTrascinamento = false

				if(drag_and_drop.azioniSulRilascio)
					for(AsR=0;AsR<drag_and_drop.azioniSulRilascio.length;AsR++)
						if(drag_and_drop.azioniSulRilascio[AsR]) {
							if(typeof(drag_and_drop.azioniSulRilascio[AsR]) == "string")
								eval(drag_and_drop.azioniSulRilascio[AsR])
							else drag_and_drop.azioniSulRilascio[AsR]() 
							}

					//	if(drag_and_drop.azioniSulRilascio[AsR]) drag_and_drop.azioniSulRilascio[AsR]() 
				}
			}




ElementoDinamico.prototype.rendiTrascinabile = function(coordinata,ElementoDnD,minX,maxX,minY,maxY,ElementoRiferimento,offsetDaRiferimentoX,offsetDaRiferimentoY){
			if(!this.Trascinabile){
				this.Trascinabile = true

				this.ElementoTrascinante = ElementoDnD?ElementoDnD:this
				this.offset_drag_n_drop_X = ElementoDnD?this.ElementoTrascinante.recuperaX():0
				this.offset_drag_n_drop_Y = ElementoDnD?this.ElementoTrascinante.recuperaY():0

				this.ElementoTrascinante.settaListenerSuMouseDown(____DragAndDropSUMouseDown____,this,coordinata,minX,maxX,minY,maxY,ElementoRiferimento,offsetDaRiferimentoX,offsetDaRiferimentoY)
				}
			}


ElementoDinamico.prototype.rendiNonTrascinabile = function(){
			if(this.Trascinabile){
				this.Trascinabile = false
				this.ElementoTrascinante.eliminaListenerSuMouseDown(____DragAndDropSUMouseDown____)
				}
			}


ElementoDinamico.prototype.azioneSulRilascio = function(funzioneDaEseguire){
			if(!this.azioniSulRilascio) this.azioniSulRilascio = []
			this.azioniSulRilascio[this.azioniSulRilascio.length] = funzioneDaEseguire
//			this.azioniSulRilascio.push(funzioneDaEseguire)
			}

ElementoDinamico.prototype.azioneSulTrascinamento = function(funzioneDaEseguire){
			if(!this.azioniSulTrascinamento) this.azioniSulTrascinamento = []
			this.azioniSulTrascinamento[this.azioniSulTrascinamento.length] = funzioneDaEseguire
//			this.azioniSulTrascinamento.push(funzioneDaEseguire)
			}

____NonGestireZIndex____ = false






/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*:::::::::::::::::     Libreria per i Drop Targets        :::::::::::::*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/


/**************************************************************************

		PRINCIPIO DEL CODICE UTILIZZATO
			
  Anche in questo caso ci appoggiamo a riferimenti di visibilità globale
  per i vari drop Targets (bersagli per il Drag&Drop).
  Utilizzo il vettore (globale) ____DragAndDropBersagli____ per contenere 
  tutta la lista dei drop Targets, vettore che andrò a scandire all'evento
  onmouseup per controllare se un elemento trascinato sia stato rilasciato
  sopra l'area di un drop Target.

  Il codice si basa su una riscrittura dell'event handler document.onmouseup
  nel caso un qualche elemento dinamico sia reso Bersaglio del Drag&Drop.

  La libreria fornisce 2 metodi:

  ElementoDinamico.rendiBersaglio(azioneDAEseguire)

	il metodo rende l'ElementoDinamico un bersaglio per il drag&drop.

	_parametri:
	  azioneDAEseguire : (string,riferimento a funzione) é l'azione da eseguire
				nel caso un elemento trascinato sia rilasciato
				sopra al bersaglio.
				Può essere passata una stringa che verrà valutata
				con la funzione eval o un riferimento ad una funzione,
				(in questo caso non è possibile passare dei parametri,
				ma la prefisco, per velocità, all'uso di eval).

  ElementoDinamico.rendiNonBersaglio()

	Il metodo elimina la capacita dell'ElementoDinamico di reagire
	al rilascio su di esso di un elemento trascinato.

**************************************************************************/

____DragAndDropBersagli____ = []


ElementoDinamico.prototype.rendiBersaglio = function(azioneDAEseguire){
			if(!this.Bersaglio){
					this.____indiceBersaglio____ = ____DragAndDropBersagli____.length
					____DragAndDropBersagli____[this.____indiceBersaglio____] = this

					____DragAndDropBersagli____[this.____indiceBersaglio____].act = azioneDAEseguire
					this.Bersaglio = true
					if(document.onmouseup!=____BersagliDragAndDropSUMouseUp____) document.onmouseup = ____BersagliDragAndDropSUMouseUp____
				}
			}

ElementoDinamico.prototype.rendiNonBersaglio = function(){
			if(this.Bersaglio){
					____DragAndDropBersagli____[this.____indiceBersaglio____].act = null
					____DragAndDropBersagli____[this.____indiceBersaglio____] = null
					this.Bersaglio = false
					
					var contoBersagli = 0
					for(DnD=0;DnD<____DragAndDropBersagli____.length;DnD++)
						if(____DragAndDropBersagli____[DnD]) contoBersagli++
					if(contoBersagli == 0) document.onmouseup = ____DragAndDropSUMouseUp____
					}
			}	

____BersagliDragAndDropSUMouseUp____ = function(){
			document.onmousemove = null
			if(window.drag_and_drop && window.drag_and_drop.inTrascinamento) {
				if(!____NonGestireZIndex____) drag_and_drop.settaStile("zIndex",1)
				drag_and_drop.inTrascinamento = false

				if(drag_and_drop.azioniSulRilascio)
					for(AsR=0;AsR<drag_and_drop.azioniSulRilascio.length;AsR++)
						if(drag_and_drop.azioniSulRilascio[AsR]) {
							//drag_and_drop.azioniSulRilascio[AsR]() 
							if(typeof(drag_and_drop.azioniSulRilascio[AsR]) == "string")
								eval(drag_and_drop.azioniSulRilascio[AsR])
							else drag_and_drop.azioniSulRilascio[AsR]() 
							}
				var DnDsx = drag_and_drop.recuperaX()
				var DnDdx = DnDsx + drag_and_drop.recuperaLarghezza()
				var DnDSu = drag_and_drop.recuperaY()
				var DnDGu = DnDSu + drag_and_drop.recuperaAltezza()

				for(DnD=0;DnD<____DragAndDropBersagli____.length;DnD++){
					if(____DragAndDropBersagli____[DnD]){
						var Brssx = ____DragAndDropBersagli____[DnD].recuperaXassoluta() 
						var Brsdx = Brssx + ____DragAndDropBersagli____[DnD].recuperaLarghezza()
						var BrsSu = ____DragAndDropBersagli____[DnD].recuperaYassoluta() 
						var BrsGu = BrsSu + ____DragAndDropBersagli____[DnD].recuperaAltezza()

						if( !(DnDsx > Brsdx || DnDdx < Brssx) && !(DnDSu > BrsGu || DnDGu < BrsSu) ){
							if(typeof(____DragAndDropBersagli____[DnD].act) == "string")
								eval(____DragAndDropBersagli____[DnD].act)
							else ____DragAndDropBersagli____[DnD].act()
							}
						}
					}
				}
			}


/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*:::::::::::::::::     Libreria per le Aree Sensibili      :::::::::::::*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/




// Questo metodo restituisce TRUE se l'elemento passato come parametro è contenuto in termini di DOM
// nell'ElementoDinamico, cioè se ne è un nodo figlio; FALSE altrimenti

ElementoDinamico.prototype.contenutoDOM = function(elementoHTML){
			while(elementoHTML && elementoHTML!= this.Elemento && elementoHTML.tagName!="BODY") 
				elementoHTML = elementoHTML.parentElement?elementoHTML.parentElement:elementoHTML.parentNode?elementoHTML.parentNode:this.Elemento
			return (elementoHTML == this.Elemento)
			}




// Questo metodo restituisce TRUE se l'elemento passato come parametro è contenuto (geometricamente)
// nell'ElementoDinamico, FALSE altrimenti.
// Al riguardo, occorre notare che c'è distinzione nel controllo, tra elementi contenuti a livello di DOM
// e gli altri: per i primi i controlli spaziali hanno come riferimento lo spigolo in alto a sinistra 
// dell'ElementoDinamico che li contiene, mentre per gli altri il riferimento è 
// lo spigolo in alto a sinistra del documento.
// NOTA: si sottointende che per ogni elemento si sia definito il posizionamento assoluto.

ElementoDinamico.prototype.contenuto = function(elementoHTML){
			if(this.contenutoDOM(elementoHTML)){
				var elementoHTMLX = parseInt(elementoHTML.style.left || elementoHTML.offsetLeft || 0)
				var elementoHTMLW = parseInt(elementoHTML.style.width || elementoHTML.offsetWidth || 0)
				var elementoHTMLY = parseInt(elementoHTML.style.top || elementoHTML.offsetTop || 0)
				var elementoHTMLH = parseInt(elementoHTML.style.height || elementoHTML.offsetHeight || 0)

				return ( (elementoHTML == this.Elemento) || 
					(elementoHTMLX >= 0 && elementoHTMLY>= 0 &&
					elementoHTMLX + elementoHTMLW <= this.recuperaLarghezza() &&
					elementoHTMLY + elementoHTMLH <= this.recuperaAltezza())
					)
				}
			else {
				var elementoHTMLX = recuperaXassoluta(elementoHTML)
				var elementoHTMLW = parseInt(elementoHTML.style.width || elementoHTML.offsetWidth || 0)
				var elementoHTMLY = recuperaYassoluta(elementoHTML)
				var elementoHTMLH = parseInt(elementoHTML.style.height || elementoHTML.offsetHeight || 0)
				return 	(elementoHTMLX >= this.recuperaXassoluta() && 
					elementoHTMLY>= this.recuperaYassoluta() &&
					elementoHTMLX + elementoHTMLW <= this.recuperaXassoluta() + this.recuperaLarghezza() &&
					elementoHTMLY + elementoHTMLH <= this.recuperaYassoluta() + this.recuperaAltezza())
				}
			}




/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/

/*:::::::::::::   Libreria per la Gestione dell'Oggetto Event   :::::::::*/

/*:::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::*/



function E(e){
	if(!e) e = window.event;
	e.cX = e.clientX;
	e.cY = e.clientY;
	e.tipo = e.type;

	e.X = (e.offsetX?e.offsetX:e.layerX || 0)
	e.Y = (e.offsetY?e.offsetY:e.layerY || 0)

	e.generatoIn = function(){
				var E_ogg = this.srcElement?this.srcElement:this.target?this.target:null;
				if(E_ogg && E_ogg.nodeType && E_ogg.nodeType==3) E_ogg = E_ogg.parentNode;
				return E_ogg;}
	e.provenienteDa = function(){
				var E_ogg = (e.relatedTarget && e.target) ? ((e.type=="mouseover") ? e.relatedTarget :e.target) : e.fromElement ? e.fromElement : null;
				if(E_ogg && E_ogg.nodeType && E_ogg.nodeType==3) E_ogg = E_ogg.parentNode;
				return E_ogg;}
	e.direttoA = function(){
				var E_ogg = (e.relatedTarget && e.target) ? ((e.type=="mouseout") ? e.relatedTarget :e.target) : e.toElement ? e.toElement : null;
				//var E_ogg = this.toElement?this.toElement:this.target?this.target:null;
				if(E_ogg && E_ogg.nodeType && E_ogg.nodeType==3) E_ogg = E_ogg.parentNode;
				return E_ogg}
	return e;
}

