//Copyright (c) 2004-2008 Anastasis Societa' Cooperativa,Bologna,Italy - www.anastasis.it
//	This copyright notice must stay intact for use.
/**
 * @fileoverview Questo file contiene il core del framework Anastasis.
 */


/**
 * La classe principale del framework.
 * @constructor Il costruttore (senza parametri) della classe Anastasis. 
 * @namespace
 * @property {boolean} is_ie 	true se il browser e' Internet Explorer
 * @property {boolean} is_ie7 	true se il browser e' Internet Explorer 7
 * @property {boolean} is_gecko true se il browser si basa sul motore gecko (Mozilla Firefox)
 * @property {String} base_url la posizione di questo file sul server (ricavata automaticamente)
 * @property {String} domain il dominio del sito della pagina corrente, ricavato automaticamente
 * @property {String} servletContext la servlet del sito della pagina corrente, ricavato automaticamente
 * @property {Object - Anastasis.Ajax} ajax un oggetto Ajax per la comunicazione
 * @property {Object - Anastasis.Utils} utils raccoglie varie funzioni utili
 */
function Anastasis()
{		
	//--------- funzioni "private" usate solo dal costruttore -------------//
	var getBaseUrl=function()
	{
		var ss=document.getElementsByTagName("script");
		for(var index=0; index<ss.length; index++) 
		{
			if(ss[index].src && ss[index].src.match(/Anastasis\.js/i))
			{
				try //Mozilla
				{
					return "/"+ss[index].src.match(/.*:\/\/[\.\w\d-]*\/(.*)Anastasis\.js/i)[1];
				}catch(e) //IE
				{
					try
					{
						var url=ss[index].src.match(/(.*)Anastasis\.js/i)[1];
						//L'url potrebbe essere relativo, dobbiamo farlo assoluto
						if(url && url.match(/^\.\./)) 
						{
							var dove=window.location.toString();
							dove=dove=dove.match(/(.*)\/.*/);
							if(dove &&  dove[1])
								url=dove[1]+"/"+url;
						}
						return url;
					}catch(e){alert("Impossibile inizializzare base_url"); return "";}
				}
			}
		}
	}
	
	var identifyBrowser=function(anastasis)
	{
		var agt = navigator.userAgent.toLowerCase();
	
		// Internet Explorer
		if ( agt.indexOf("msie") != -1 && agt.indexOf("mac") == -1 && agt.indexOf("opera") == -1 )
		{
			var sBrowserVersion = navigator.appVersion.match(/MSIE (.\..)/)[1] ;
			if ( sBrowserVersion >= 5.5 ) anastasis.is_ie=true;
			if ( sBrowserVersion >= 7 ) anastasis.is_ie7=true;
		}
	
		// Gecko - Mozilla Firefox (Opera 9 tries to behave like Gecko at this point).
		if (navigator.product == "Gecko" && navigator.productSub >= 20030210 && !( typeof(opera) == 'object' && opera.postError ) )
			anastasis.is_gecko=true;
	}
	
	//-------------variabili------------------//

	this.is_ie=false;
	this.is_ie7=false;
	this.is_gecko=false;
	identifyBrowser(this);	
	this.base_url=getBaseUrl();	
	if(window.location.href.match(/(https?:\/\/[^\/]+\/).*/)) this.domain=window.location.href.match(/(https?:\/\/[^\/]+\/).*/)[1];
	if(window.location.href.match(/https?:\/\/[^\/]+\/[^\/]+\/.*/)) this.servletContext=window.location.href.match(/https?:\/\/[^\/]+\/([^\/]+)\/.*/)[1];	
	this.systemScripts=new Array();
	this.ajax=new Anastasis.Ajax();
	this.utils=new Anastasis.Utils();
		
	//----------------------------------------//
		
	var me=this;		
	this.syncLoadScript("Dialog",true);				
}


/**
 * Carica uno script; a caricamento avvenuto esegue l'azione passata onload. 
 * @param {String} 		src 	l'indirizzo dello script (o solo il nome se e' di sistema - cioe' nella stessa cartella di questo js)
 * @param {function}	onload 	una funzione di callback
 * @param {boolean}		system 	specifica se e' uno script di sistema oppure no
 * @memberOf Anastasis
 */
 //Problema: IE non supporta il parametro onload degli script --> bisogna caricare gli script con Ajax!
Anastasis.prototype.loadScript=function(src,onload,system)
{		
	
	//Se il file � gi� stato caricato, ci sar� l'elemento corrispondente --> fine
	for(var i in this.systemScripts)
		if(this.systemScripts[i]==src) return;			
	
	this.systemScripts.push(src);
	
	if(system) src=this.base_url+src+".js";
	
	/*
	var head = document.getElementsByTagName("head")[0];
	var script = document.createElement("script");
	script.type = "text/javascript";
	script.src = src;
	script.onload = onload;
	head.appendChild(script);
	*/
	
	var onReceived=function(text)
	{		
		try{eval(text);} catch(e){alert("Anastasis.loadScript-onReceived\n"+src+"\n"+e+"\n"+text);}
		if (typeof onload == "function") onload();
	}
		
	this.ajax.send(new Object(),src,"GET",false,true,onReceived);
	
}

/**
 * Carica in sequenza una lista di script, dopodiche' chiama una funzione di callback(se passata).
 * @param {Array} 		scripts 	la lista degli scripts da caricare (["script1","script2"])
 * @param {function} 	callback 	la funzione da chiamare alla fine del caricamento di tutti gli script
 * @param {boolean} 	specifica 	se e' gli script sono sistema oppure no (se sono di sistema basta mettere il nome(senza neanche '.js'), altrimenti serve il path completo)
 */
Anastasis.prototype.loadScriptSequence=function(scripts,callback,system)
{
	var me=this;
	if(scripts.length==1)
		this.loadScript(scripts[0],callback,system);
	else
	{
		var next=[];
		for(var index=1; index<scripts.length; index++) 
		{
			next[index-1]=scripts[index];
		}		
		this.loadScript(scripts[0],function(){me.loadScriptSequence(next,callback,system);},system);
	}			
}

/**
 * Carica in maniera sincrona uno script.
 * @param {String} src l'indirizzo dello script (o solo il nome se e' di sistema - cioe' nella stessa cartella di questo js)
 * @param {Boolean} system specifica se e' uno script di sistema oppure no
 */
Anastasis.prototype.syncLoadScript=function(src,system)
{
	if(system) src=this.base_url+src+".js";	
	
	text=this.ajax.send(new Object(),src,"GET",false,false);
	eval(text);
	
}

/**
 * Carica un css e lo applica alla pagina.
 * @param {String} url l'url del css
 */
Anastasis.prototype.loadStyle = function(url) 
{		
	var head=document.getElementsByTagName("head")[0];
	var link = document.createElement("link");
	link.type = "text/css";
	link.rel="stylesheet";
	link.href=url;
	head.appendChild(link);	
}

//-------------------------------------------------//
/**
 * Classe Ajax.
 * Gestisce la comunicazione Ajax.
 * @constructor
 * @class Anastasis.Ajax 
 */
Anastasis.Ajax=function ()
{
	this.iframe=null;
	this.iframeActionQueue=new Array();
	this.iframePostQueue=new Array();
	this.iframeWaitingForReply=false;
}

//------------GLOBAL FUNCTIONS-------------------------------//

/**
 * Implementazione della funzione selectSingleNode per un oggetto XMLElement. 
 * Preso in input l'oggetto xml e l'xpath di un nodo, se c'è lo restituisce, altrimenti restituisce null.
 * @static
 * @param {XMLElement} xmlElement l'oggetto xml all'interno del quale si vuole cercare il nodo
 * @param {String} il path del nodo da cercare
 * @return il nodo cercato
 * @type XMLElement
 */
Anastasis.Ajax.selectSingleNode=function(xmlElement,node)
{	
	node=node.split(/\//);		
	var currentElement=xmlElement;
	for(var i=0;i<node.length;i++)
	{
		if(!currentElement) break;
		var child=currentElement.firstChild;	
		if(!child) 	currentElement=null;
		while(child)
		{						
			if(child.tagName && child.tagName==node[i])
			{
				currentElement=child;
				break;
			}
			else 
			{ 
				currentElement=null;
			}
			child=child.nextSibling;
		}	
	}		
	return currentElement;
	
}

/**
 * Preso un xmlElement, ne restituisce il testo (o null se non è una "foglia")
 * @static
 * @param {XMLElement} xmlElement l'oggetto xml da cui si vuole estrarre il testo
 * @return il testo
 * @type String 
 */
Anastasis.Ajax.getText=function(xmlElement)
{
	if(xmlElement.textContent)			//Mozilla
		return xmlElement.textContent;
	if(xmlElement.text) 				//IE
		return xmlElement.text;		
	else if(xmlElement.firstChild && xmlElement.firstChild.nodeType==4)
	{
		if(xmlElement.firstChild.textContent)			//Mozilla
			return xmlElement.firstChild.textContent;
		if(xmlElement.firstChild.text) 
			return xmlElement.firstChild.text;		//IE
	}
	else if(xmlElement.firstChild && xmlElement.firstChild.nodeType==8)	//Problema di Mozilla che vede CDATA come commenti
	{
		if(xmlElement.firstChild.textContent)			//Mozilla
			return xmlElement.firstChild.textContent.replace(/^\[CDATA\[/,'').replace(/\]\]$/,'');		
	}
	return null;
}




//---------------------------METODI-PUBBLICI---------------------------//
/**
* Invio sincrono o asincrono di dati via XMLHttp; i primi due parametri sono obbligatori, gli altri opzionali.<br />
* Se e' sincrono, restituisce l'output della pagina receiver sotto forma di testo
* @param {Object} 	param 		param[id]=contenuto, dove id e' l'id che avra' nella queryString
* @param {String} 	receiver 	l'indirizzo a cui mandarlo
* @param {String} 	method 		se non specificato e' POST
* @param {boolean} 	xmldoc 		se true ritona un Document Xml, altrimenti una semplice stringa
* @param {boolean} 	async 		asincrono? se false non ritorna nulla!
* @param {function} callback 	se il metodo e' asincrono, la funzione che gestisce l'arrivo della risposta (opzionale)
* @return se la chiamata è sincrona, restituisce il messaggio di risposta, altrimenti lo passa alla funzione di callback. Se xmldoc e' true, restituisce un XMLElement, altrimenti una stringa
* @type XMLElement|String
*/
Anastasis.Ajax.prototype.send=function (param,receiver,method,xmldoc,async,callback)
{
  if(method!="GET" && method!="POST") method="POST";
  try
  {             
    var xmlHttp=this.getSender();

	//Apre la "connessione"
    xmlHttp.open(method,receiver,async);    //(method, url, async)
    if(method=="POST")
    	xmlHttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=ISO-8859-1");
    else
    	xmlHttp.setRequestHeader("Content-Type","text/plain; charset=ISO-8859-1");
    
    
    //Compone la richiesta da inviare
    var qs="";
    var tmp;
    var primo=false;
    for(var par in param)
    {
      if(!primo) primo=true; else qs+="&";    
      tmp=encodeURIComponent(param[par]); //Encode con tutti i % 
      tmp=tmp.replace(/&/g,"%26");   //Sostituisce gli &, perrhc� encodeURI non lo fa      
      qs+=par+"="+tmp; //Attenzione alla sostituzione degli &!!!
    }        
    
    if(async)
    {
    	var ajax=this;
    	if(xmldoc)
	    	xmlHttp.onreadystatechange=function()
	    		{	    			
	    			if(xmlHttp.readyState==4 && callback)
	    				callback(xmlHttp.responseXML);
	    		}
	    else
	    	xmlHttp.onreadystatechange=function()
	    		{
	    			if(xmlHttp.readyState==4 && callback)
	    				callback(xmlHttp.responseText);
	    		}
    }
    
    xmlHttp.send(qs);
    
    if(!async)
    {
	    var response;
	    if(xmldoc)
	    	{
	    		var contentType=xmlHttp.getResponseHeader("Content-Type");
	    		//contentType=contentType.toLowerCase();
	    		if(!(contentType && (contentType.match(/application\/xml/) || contentType.match(/text\/xml/))))
	    			{
	    				this.errore("send","Si richiedeva una risposta XML ma il Content-Type dichiarato non corrisponde.\nContent-type: "+contentType+"\nText: "+xmlHttp.responseText);
	    				//prova comunque a parserizzarla...
	    				response=Anastasis.Utils.parseXML(xmlHttp.responseText);
	    			}
	    		else
		    		response = xmlHttp.responseXML;
	    	}
	    else
	    	response = xmlHttp.responseText;
	    return response;
    }   
    
  }catch(err){this.errore("send",err);}
}

/**
 * Funzione che invia un form in background.
 * Quando riceve la risposta, la passa alla funzione di callback che gli viene passata.<br />
 * NB: l'oggetto passato alla funzione di callback, nel caso che la risposta sia xml,
 * 		e'un oggetto XMLElement gia' parserizzato. In tutti gli altri casi e' una semplice stringa.
 * 
 * @param {String} 		id_form 	l'id del form da inviare
 * @param {function} 	callback 	la funzione di callback chiamata passandole la risposta come primo parametro
 * @return nulla, passa la risposta alla funzione di callback
 */

Anastasis.Ajax.prototype.sendForm=function(id_form,callback)
{
	var form=document.getElementById(id_form);
	this.createIFrame();
	form.target=this.iframe.name;	
	this.iframeActionQueue.push(function(rep){callback(rep);});
	this.doSendForm(form);
}


//---------------------------METODI-PRIVATI---------------------------//

/**
 * Crea un nuov oggetto xmlHTTP (va rifatto ogni volta)
 * @private
 */
Anastasis.Ajax.prototype.getSender=function ()
{
	var xmlHttp=null;
	
	if(window.XMLHttpRequest)//IE 7, Firefox
		try
		{
			xmlHttp=new XMLHttpRequest();                            
		}catch(e){this.errore("resetSender",e);}	
	else //IE 6
	{
		try { xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");}         //IE nuovi
	    catch (e) 
	    { try { xmlHttp = new ActiveXObject("Microsoft.XMLHTTP"); }    //IE vecchi
	      catch (E){this.errore("resetSender",e+"\n"+E);}                        
	    }
	}
	
	return xmlHttp;
}

/**
 * @private
 */
Anastasis.Ajax.prototype.errore=function(metodo,err)
{
	alert("[Ajax."+metodo+"]\n"+err);
}

/**
 * @private
 */
Anastasis.Ajax.prototype.createIFrame=function()
{		
		if(this.iframe){ return; }
		
		var iframe = null;
		
		var ifrstr = '<iframe name="anastasis_ajax_iframe" src="'+anastasis.base_url+'blank_src.html" onload="parent.anastasis.ajax.onloadedIFrame();">';
		var div=document.createElement("div");
		div.innerHTML=ifrstr;
		iframe = div.firstChild;		
				
		this.iframe = iframe;

		iframe.style.position = "absolute";
		iframe.style.left = iframe.style.top = "-1000px";
		iframe.style.height = iframe.style.width = "0px";
		
		document.body.appendChild(iframe);
}

/**
 * @private
 */
Anastasis.Ajax.prototype.doSendForm=function(form)
{
	if(this.iframeWaitingForReply)
		this.iframePostQueue.push(form);
	else
	{
		this.iframeWaitingForReply=true;
		form.submit();
	}
}

/**
 * @private
 */
Anastasis.Ajax.prototype.onloadedIFrame=function()
{
	var rep="";
		
	if(anastasis.is_ie && this.iframe.contentWindow.document.XMLDocument)			//E' un doc XML e siamo in IE
		rep=this.iframe.contentWindow.document.XMLDocument;
	else if(anastasis.is_gecko && this.iframe.contentWindow.document.firstChild && this.iframe.contentWindow.document.firstChild.nodeType==1)	//E' un doc XML e siamo in Mozilla
	{
			rep=this.iframe.contentWindow.document.firstChild;			
	}
	else
	try
	{
			rep=this.iframe.contentWindow.document.body.innerHTML;
	}	catch(e){}
					
	
	if(rep.match && rep.match("BLANK_ANASTASIS_IFRAME")) return;	//primo caricamento dell'iframe (anche se non avviene sempre)				
	
	try
	{
		var callback=this.iframeActionQueue.shift();
		callback(rep);
	}
	catch(e){this.errore("onloadedIframe",e.toString());}
		
	
	//Ora vediamo se c'erano altri form in attesa di essere inviati e li inviamo
	this.iframeWaitingForReply=false;
	var next=this.iframePostQueue.shift();
	if(next)
		this.doSendForm(next);	
}

//------------CLASS XMESSAGE--------------------------//
/**
 * Costruttore degli XMessaggi: non va mai usato, si costruiscono con la funzione buildXMessage
 * @class 	Wrapper per XMessage in X-serena. La sintassi di un XMessage e':<br /><code> &lt;serena&gt;&lt;service&gt;&lt;_system_message&gt;...&lt;/_system_message&gt;&lt;/service&gt;&lt;/serena&gt;</code><br /> All'interno ci deve stare almeno il tag &lt;type&gt; e, se il type e' "error", anche il tag &lt;error&gt;
 * @property {XMLElement} message la root del messaggio
 * @property {String} type il tipo del messaggio (contentuto anche in /type)
 * @property {String} error l'eventuale messaggio di errore, se il type e' "error"
 */
 //Per chi sta leggendo la documentazione da qua e non dall'html: <serena><service><_system_message>...</_system_message></service></serena>
Anastasis.XMessage=function()
{
	this.message=null;
	this.type="";
	this.error="";	
}

	//----------GLOBAL FUNCTIONS-----------------------//

/**
 * Funzione statica che ritorna in XMessaggio a partire ad un element XML.
 * @param {XMLElement} un elemento xml scritto in x-serena rispettando la sintassi di un xmessage. 
 */
Anastasis.XMessage.buildXMessage=function(xmldoc)
{
	msg=new Anastasis.XMessage();

/*	
	alert("QUA");
	var aa=Anastasis.Ajax.selectSingleNode(xmldoc,"serena");
	alert("Node type: "+aa.nodeType);
	alert("TAGNAME: "+aa.tagName);
	return;
*/
	if(xmldoc.tagName!="serena")
	{
		if(xmldoc.tagName && xmldoc.tagName.toLowerCase()=="html")
		{
			msg.type="error";
			msg.error="Il content-type della risposta ricevuta e' HTML anizhe' XML\nOppure il content-type e' corretto ma il contenuto e' HTML.";
			return msg;
		}
		xmldoc=Anastasis.Ajax.selectSingleNode(xmldoc,"serena");
		if(!xmldoc)
		{
			msg.type="error";
			msg.error="XML ricevuto non inizia con tag serena";
			return msg;
		}
	}
	if(!Anastasis.Ajax.selectSingleNode(xmldoc,"service"))
	{
		msg.type="error";
		msg.error="XML ricevuto non contiene serena/service";
		return msg;
	}
	
	msg.message=Anastasis.Ajax.selectSingleNode(xmldoc,"service/_system_message");
	if(!msg.message)
	{
		msg.type="error";
		msg.error="XML ricevuto non contiene service/_system_message";
		return msg;
	}		
	
	msg.type=Anastasis.Ajax.selectSingleNode(msg.message,"type");
	if(msg.type) msg.type=Anastasis.Ajax.getText(msg.type);		
	
	if(msg.type=="error" && Anastasis.Ajax.selectSingleNode(msg.message,"error"))
		msg.error=Anastasis.Ajax.getText(Anastasis.Ajax.selectSingleNode(msg.message,"error"));
		
	return msg;
}

	//-----------PUBLIC FUNCTIONS----------------------//

/**
 * Restituisce il testo contenuto nell'elemento richiesto
 * @param {String} element il nome del nodo di cui si vuole il contenuto
 * @return il testo contenuto nell'elemento richiesto
 * @type String
 */
Anastasis.XMessage.prototype.getContentOf=function(element)
{
	var el=Anastasis.Ajax.selectSingleNode(this.message,element);	
	if(el) return Anastasis.Ajax.getText(el);
	else return null;
}

/**
 * True se il messaggio è un messaggio di errore. In questo caso sara' disponibile il campo <code>error</code>.
 * @return true se il messaggio è un messaggio di errore
 * @type boolean
 */
Anastasis.XMessage.prototype.isErrorMessage=function()
{
	return (this.type=="error");
}

/**
 * True se il messaggio è un messaggio di di tipo "ok".
 * @return true se il messaggio è un messaggio di ok
 * @type boolean
 */
Anastasis.XMessage.prototype.isOkMessage=function()
{
	return (this.type=="ok");
}


//------------CLASS UTILS-------------------------//

/**
 * @class Una serie di strumenti utili.
 */
Anastasis.Utils=function(){};

	//----------GLOBAL FUNCTIONS-----------------------//
//Queste funzioni possono essere chiamate ovunque, basta aver caricato questo js.
/**
 * Trim di stringhe
 * @param {String} stringa la stringa
 * @return la stringa senza spazi prima e dopo
 * @type {String}
 */
Anastasis.Utils.trim = function(stringa) 
{	
	stringa = stringa.replace(/^\s+/, '');
	return stringa.replace(/\s+$/, '');
};

/**
 * Da una stringa restituisce un oggetto DOM XML.
 * @param {String} xml una stringa con un xml ben formato
 * @return un elemento xml ottenuto parserizzando la stringa
 * @type XMLElement
 * @throws una stringa con il messaggio di errore
 */
Anastasis.Utils.parseXML=function(xml)
{
	var xmldoc;
	try
	{
	  	if(window.DOMParser)  //Mozilla
		{
			var parser=new DOMParser();
			xmldoc=parser.parseFromString(xml,"text/xml");  
		}
		else  //IE 
	  	{
			xmldoc=new ActiveXObject("Microsoft.XMLDOM");		//new ActiveXObject("Msxml2.DOMDocument.3.0");
		  	xmldoc.async="false";
		  	xmldoc.loadXML(xml);
	  	}
	}catch(e) { throw "parseXML - Errore nel parsing dell'xml.\n"+e; }
	
  if(!(xmldoc.documentElement))
  {
  	if (xml) throw "parseXML - Errore nel parsing dell'xml.\n"+xml;
  	else throw "parseXml - Tentativo di parseXML() su variabile null";
  	return null;
  }
  
  return xmldoc;
}

/**
 * Crea un cookie descritto dai parametri passati.
 * @param {String} name il nome del cookie
 * @param {String} value il valore del cookie
 * @param {String} days il numero di giorni di validita' del cookie 
 */
Anastasis.Utils.creaCookie=function(name,value,days) 
{
  if (days) 
  {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  }
  else expires = "";
  document.cookie = name+"="+value+expires+"; path=/";
}

/**
 * Legge un cookie e ne riporta il valore.
 * @param {String} name il nome del cookie
 * @return il valore del cookie oppure null
 * @type String 
 */
Anastasis.Utils.leggiCookie=function(name) 
{
  var nameEQ = name + "=";
  var ca = document.cookie.split(';');
  for(var i=0;i < ca.length;i++) {
    var c = ca[i];
    while (c.charAt(0)==' ') c = c.substring(1,c.length);
    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
  }
  return null;
}

/**
 * Esegue l'encoding html di un testo, sostituendo solo i quattro simboli piu' ostici: &amp; &lt; &gt; &quot;
 */
Anastasis.Utils.htmlEncode = function(str) 
{
	str = str.replace(/&/ig, "&amp;");
	str = str.replace(/</ig, "&lt;");
	str = str.replace(/>/ig, "&gt;");
	str = str.replace(/\x22/ig, "&quot;");
	return str;
};

	//-----------PUBLIC FUNCTIONS----------------------//
// Questi metodi sottindendono l'allocazione di un oggetto Utils e anche di uno Anastasis

/**
 * @private
 */
Anastasis.Utils.prototype.errore=function(metodo,err)
{
	alert("[Utils."+metodo+"]\n"+err);
}

/**
 * Ferma la propagazione dell'evento ev.
 * @param {Object - event} ev l'evento da stoppare
 */
Anastasis.Utils.prototype.stopEvent = function(ev) 
{
	if(anastasis.is_ie) {
		ev.cancelBubble = true;
		ev.returnValue = false;
	} else {
		ev.preventDefault();
		ev.stopPropagation();
	}
};

/**
 * Registra la funziona passata come handler per l'evento evname sull'elemento el.<br />
 * Se questa funzione è chiamata piu' volte per lo stesso evento sullo stesso oggetto,
 * le funzioni passate sono eseguite nell'ordite in cui sono state registrate.<br />
 * @param {HTMLElement} el l'elemento
 * @param {String} evname il nome dell'evento(senza il prefisso "on"
 * @param {function} func la funzione handler
 */ 
 // Registers the function as handler for the event evname on the element el.<br />
 // If this function is called more than one time for the same element and the same event, 
 // the function are executed one after the other in the registering order.
Anastasis.Utils.prototype.addEvent = function(el, evname, func) 
{
	if(!el.document && !el.nodeType) el=document.getElementById(el);
	if (anastasis.is_ie) 
	{
		el.attachEvent("on" + evname, func);
	} 
	else 
	{
		el.addEventListener(evname, func, false);
	}
};

/**
 * Rimuove una specifica funzione dall'handler dell'evento ev sull'elemento el.<br />
 * La funzione non puo' essere anonima.
 * @param {HTMLElement} el l'elemento
 * @param {String} evname il nome dell'evento(senza il prefisso "on"
 * @param {function} func la funzione da rimuovere, che deve essere esattamente quella aggiunta
 */
 //Removes a specific function as handler for the event evname on the element el
Anastasis.Utils.prototype.removeEvent = function(el, evname, func) 
{
	if(!el.document && !el.nodeType) el=document.getElementById(el);
	if (anastasis.is_ie) 
	{
		el.detachEvent("on" + evname, func);
	} 
	else 
	{
		el.removeEventListener(evname, func, false);
	}
};

/**
 * Rimuove una classe da un elemento. Se non c'e' non succede nulla.
 * @param {HTMLElement} el l'elemento html
 * @param {String} className la classe da eliminare 
 */
 //Removes the class className from the element el
Anastasis.Utils.prototype.removeClass = function(el, className) 
{
	if (!(el && el.className && el.className.match(className))) 
	{
		return;
	}
	var cls = el.className.split(" ");
	var ar = new Array();
	for (var i = cls.length; i > 0;) 
	{
		if (cls[--i] != className) 
		{
			ar[ar.length] = cls[i];
		}
	}
	el.className = ar.join(" ");
};

/**
 * @param {Object} event l'evento che generato dalla pressione di un tasto
 * @param {integer} charCode il codice del tasto da monitorare
 * @param {boolean} propagation se l'esecuzione deve continuare dopo l'esecuzione dell'azione
 * @param {Function} action l'azione da eseguirsi nel caso in cui l'evento sia generato da charCode
 */
Anastasis.Utils.prototype.checkKeyPressed = function(event,charCode,propagation,action)
{
	var keynum;

	if(window.event) // IE
  	{
  		keynum = event.keyCode;
  	}
	else if(event.which) // Netscape/Firefox/Opera
	{
		keynum = event.which;
  	}
	
	if (keynum==charCode)
	{
		if (action) action();
		return propagation;
	}
} 

/**
 * Aggiunge una classe ad un elemento html.
 * @param {HTMLElement} el l'elemento html
 * @param {String} className la classe da aggiugere (aggiunge uno spazio e la accoda alle preesistenti)
 */
 //Adds the class className to the element el
Anastasis.Utils.prototype.addClass = function(el, className) 
{
	this.removeClass(el, className);
	el.className += " " + className;
};

/**
 * Ritorna l'HTMLElement che ha generato l'evento. Serve perche' il mdo di richiederlo cambia in ie e firefox.
 */
Anastasis.Utils.prototype.getEventSource=function(event)
{
	if(anastasis.is_ie)
		return event.srcElement;
	else 
		return event.target;		
}

//--------------------------------------------------------------------//

/**
 * Internationalization class.
 * It must be initialized with an object with the following syntax:
 * object_name=
 * {
 * 	"text" : "translation",
 * 	"text" : "translation"
 * }
 * @param strings Object; the strings and their tranlsations
 * @class 
 * @constructor
 */
Anastasis.I18N=function(strings)
{
	this.strings=strings;	
}

Anastasis.I18N.prototype.translate=function(string)
{
	string=string.replace(/^\s*/,'');
	string=string.replace(/\s*$/,'');	
	var punteggiatura="";	
	if(string.match(/[:\s*.]$/)) 
	{
		match=string.match(/(.*)([:\s*.])$/);
		string=match[1];
		punteggiatura=match[2];
	}

	if(this.strings && this.strings[string])
		return this.strings[string]+punteggiatura;
	else
		return string+punteggiatura;
}

Anastasis.I18N.prototype.add=function(term,translation)
{
	this.strings[term]=translation;
}

Anastasis.Utils.translatePage=function(i18n)
{
	if(!i18n) return;
	
	tags_to_translate=["div","span","p","option","td","button","legend","label"];
	//-----------------------------------------------------------------------------------------------------//
	function toBeTranslated(tag)
	{
		for(var i in tags_to_translate)
		{
			if(tag==tags_to_translate[i]) return true;
		}
		return false;
	}
	
	function recTranslate(root)
	{
		if(!root) return;
		if(root.nodeType==1 || root.nodeType==11)
	  	{  
	    	var i;  
	    	var root_tag = (root.nodeType == 1) ? root.tagName.toLowerCase() : '';
	    	if(toBeTranslated(root_tag))
	      		if (root.firstChild && root.firstChild.data) 
	        	{                      	         		 
	  				root.firstChild.data = i18n.translate(root.firstChild.data);
				 }
			if(root.title) root.title=i18n.translate(root.title);
	    	for (i=root.firstChild; i; i = i.nextSibling) recTranslate(i);		
	  	}	  
	}	
	
	document.title = i18n.translate(document.title);
	recTranslate(document.body);			
}

 //-----------------MANTENUTO PER RETROCOMPATIBILITA' -------------------------//
	 
Anastasis.Utils.print=function(cosa)	
{
	anastasis.syncLoadScript("serena/SerenaUtils",true);
	Anastasis.SerenaUtils.print(cosa);	
}

//-----------------------------------------------------------------------------//

window.anastasis=new Anastasis();
