// Copyright Menu: Libreria dei Forumisti (da Html.it)
// http://forum.html.it/forum/showthread.php?s=&threadid=395626



/*
	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    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 LivelloDinamico(attrID){
	this.livello = recuperaElementoDaId(attrID)

	// definisco una proprietà del livello che contenga un riferimento al proprio oggetto LivelloDinamico

	this.livello.rif = this
	this.riferimento = this.constructor

	if(this.livello){

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

		this.css = this.livello.style


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

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

	
		// 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
		this.recuperaLarghezza = function(){return (parseInt(this.css.width) ||  this.offsetWidth || this.livello.offsetWidth || 0)}
		this.recuperaAltezza = function(){return (parseInt(this.css.height) || this.offsetHeight || this.livello.offsetHeight || 0)}
		this.recuperaX = function(){return ((this.css.left) ? parseInt(this.css.left) : (this.offsetLeft || this.livello.offsetLeft ||0))}
		this.recuperaY = function(){return ((this.css.top) ? parseInt(this.css.top) : (this.offsetTop || this.livello.offsetTop ||0))}


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

		this.settaLarghezza = function(stileWidth){this.css.width = stileWidth}
		this.settaAltezza = function(stileHeight){this.css.height = stileHeight}
		this.settaX = function(coordinataX){this.css.left = coordinataX}
		this.settaY = function(coordinataY){this.css.top = coordinataY}
		this.settaColoreSfondo = function(stileBackgroundColor){this.css.backgroundColor = stileBackgroundColor}
		this.settaColoreTesto = function(stileColor){this.css.color = stileColor}


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

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

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


		// funzione universale di settaggio stili

		this.settaStile = function(stile,valore){this.css[stile] = valore}


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

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

		// 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
	}
}








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

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

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





//LivelloDinamico.prototype.minimoTempoCPU = 20  

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

LivelloDinamico.prototype.gestoreClock = function(indiceGestore){
			var conto = 0
			for(i=0;i<this.azioni.length;i++) conto += (this.azioni[i])?1:0
			if(conto==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 LivelloDinamico. E' utile soprattutto per gestire
// le animazioni gestite da mouse (o da utente in generale)

LivelloDinamico.prototype.terminaAnimazione = function(){
			for(i=0;i<this.azioni.length;i++) {
				clearInterval(this.azioni[i])
				this.azioni[i] = 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.

LivelloDinamico.prototype.azioneFinale = function(){
			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à.

LivelloDinamico.prototype.animazione = function(valoreFinale,passo,indice,grandezza){
			var direzione = (valoreFinale > this[grandezza]) ? 1 : -1
			this[grandezza]+=direzione*passo
			if(direzione*this[grandezza]<valoreFinale) this["setta"+grandezza](this[grandezza])
			else{
				this["setta"+grandezza](valoreFinale)
				clearInterval(this.azioni[indice])
				this.azioni[indice] = null
				}
			}





// Metodi per il movimento e il dimensionamento.
//
// _Nella prima parte sono calcolate le differenza da percorrere nell'animazione
// _Nella seconda parte, se sono abilitate le animazioni in tempi definiti (LivelloDinamico.animazioniInTempo = true),
//  si calcola il giusto passo per ogni animazione memorizzandolo in proprietà dell'oggetto 
//  (chiamate in modo logico in accordo col metodo "animazione"), in modo da poter memorizzare anche valori decimali.
// _Nella terza parte vengono lanciate le animazioni utilizzando la recorsività (setInterval),
//  riempendo progressivamente l'array "azioni".
// _Nell'ultima parte, si introduce il blocco di codice per la gestione del clock

LivelloDinamico.prototype.muoviIn = function(posX,posY,tempoAnimazione_o_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(this.animazioniInTempo){
				var passoX = diffX/(tempoAnimazione_o_passoX/this.minimoTempoCPU)
				var passoY = diffY/(tempoAnimazione_o_passoX/this.minimoTempoCPU)
				var ritardoX = this.minimoTempoCPU
				var ritardoY = this.minimoTempoCPU
			}
			else{
				var passoX = tempoAnimazione_o_passoX || 1
				var passoY = passoY || 1
				var ritardoX = ritardoX || this.minimoTempoCPU
				var ritardoY = ritardoY || this.minimoTempoCPU
			}

			if(diffX) this.azioni.push(setInterval("recuperaElementoDaId('"+this.livello.id+"').rif.animazione("+posX+","+passoX+","+this.azioni.length+",'X')",ritardoX))
			if(diffY) this.azioni.push(setInterval("recuperaElementoDaId('"+this.livello.id+"').rif.animazione("+posY+","+passoY+","+this.azioni.length+",'Y')",ritardoY))

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

LivelloDinamico.prototype.ridimensionaA = function(dimL,dimA,tempoAnimazione_o_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(this.animazioniInTempo){
				var passoL = diffL/(tempoAnimazione_o_passoL/this.minimoTempoCPU)
				var passoA = diffA/(tempoAnimazione_o_passoL/this.minimoTempoCPU)
				var ritardoL = this.minimoTempoCPU
				var ritardoA = this.minimoTempoCPU
			}
			else{
				var passoL = tempoAnimazione_o_passoL || 1
				var passoA = passoA || 1
				var ritardoL = ritardoL || this.minimoTempoCPU
				var ritardoA = ritardoA || this.minimoTempoCPU

			}

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

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

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

LivelloDinamico.prototype.ridimensionaDi = function(dimL,dimA,tempoAnimazione_o_passoL,passoA,ritardoL,ritardoA){
			this.ridimensionaA((this.recuperaLarghezza()+dimL),(this.recuperaAltezza()+dimA),tempoAnimazione_o_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

LivelloDinamico.prototype.settaOpacita = function(stileOpacity){
			if(IE5) this.css.filter="alpha(opacity="+stileOpacity+")"
			else if(NN6) this.css.MozOpacity=(stileOpacity/100)
			}

LivelloDinamico.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
			}
			

LivelloDinamico.prototype.sfumaA = function(opacitaFinale,tempoAnimazione_o_passoOp,ritardoOp){
			this.Opacita = this.recuperaOpacita()
			if(this.Opacita>=0){
				var diffOp = Math.abs(opacitaFinale-this.Opacita)

				if(this.animazioniInTempo){
					var passoOp = diffOp/(tempoAnimazione_o_passoOp/this.minimoTempoCPU)
					var ritardoOp = this.minimoTempoCPU
					}
				else{
					var passoOp = tempoAnimazione_o_passoOp || 1
					var ritardoOp = ritardoOp || this.minimoTempoCPU
					}

				if(diffOp) this.azioni.push(setInterval("recuperaElementoDaId('"+this.livello.id+"').rif.animazione("+opacitaFinale+","+passoOp+","+this.azioni.length+",'Opacita')",ritardoOp))

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

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

