/*********************************************
	ajax.js
	******************************************

En aquest fitxer s'hi defineix la funció que realitza les crides AJAX (veure informació més avall)
	cridaAJAX(url,callback_func,loading_func,waiting_time,method)

un wrapper de la mateixa per fer crides per POST més còmodament
	cridaAJAX_POST(url,callback_func,loading_func,waiting_time)
	
dues funcions per usar per defecte quan l'usuari no les indiqui als paràmetres de cridaAJAX
	default_ajax_callback_func()
	default_ajax_loading_func()
	
i una funció d'utilitat per a recuperar valors de formulari i posar-los en una cadena com a parametres URL
	formToStringParams(form_id)

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

/**
	GET(url,callback_func,loading_func,waiting_time)
	POST(url,callback_func,loading_func,waiting_time)
	debug_GET(url,callback_func,loading_func,waiting_time)
	debug_POST(url,callback_func,loading_func,waiting_time)

	url = ubicació del recurs a cridar i parametres. ex: 'getComentaris.php?topic=32'
	
	callback_func =	funció que es cridarà quan la crida estigui llesta i amb resultat
					normalment definirem una funció per fer el què convingui
					sinó s'usarà la crida per defecte
					
	loading_func = 	funció a cridar mentres no es té el resultat de la crida
					per defecte és una funció que no fa res

	waiting_time =	milisegons d'espera abans de cridar la funció de loading. Per defecte 1500. 
					Hi ha casos en què és millor no mostrar informació de loading si la crida és prou ràpida per prevenir efectes pampalluga. Es pot ajustar el temps d'espera amb aquest parametre.
					
*/


function Ajax(){}


//el counter és perquè el navegador interpreti que és una url diferent cada vegada
Ajax.historyCounter = 0;
Ajax.recentHash = "#"; //window.location.hash;

Ajax.debug_POST = function (url,callback_func,loading_func,waiting_time){
	Ajax.call(url,callback_func,loading_func,waiting_time,'POST',true);
}

Ajax.POST = function (url,callback_func,loading_func,waiting_time) {
	Ajax.call(url,callback_func,loading_func,waiting_time,'POST',false);
}

Ajax.debug_GET = function debug_GET(url,callback_func,loading_func,waiting_time){
	Ajax.call(url,callback_func,loading_func,waiting_time,'GET',true);
}

Ajax.GET = function GET(url,callback_func,loading_func,waiting_time){
	Ajax.call(url,callback_func,loading_func,waiting_time,'GET',false);
}

Ajax.call = function (url,callback_func,loading_func,waiting_time,method,debug) {

	// Comprovem els paràmetres ajustant valors per defecte
	///////////////////////////////////////////////////////
	if(typeof url == "undefined") return false;
	if(typeof callback_func == "undefined") callback_func = Ajax.default_ajax_callback_func;
	if(typeof loading_func == "undefined") loading_func = Ajax.default_ajax_loading_func;		
	if(typeof waiting_time == "undefined") waiting_time = 1500;
	if(typeof method == "undefined"){
		method = 'GET';
	}else{
		method = method.toUpperCase()
	}
	
	// Extreiem els paràmetres de la crida
	//////////////////////////////////////
	var params="";
	try{
		params=url.split('?')[1];
		url=url.split('?')[0];
		if(typeof params == 'undefined'){
			params="";
		}else{
			params = params.replace("%25","%");
		}
	}catch(e){}		
	
	
	// Per a crides AJAX sense funció de callback personalitzada:
	// Aleshores fan servir la crida per defecte "default_ajax_callback_func",
	// que es basa en l'existència del paràmetre "target" per indicar l'element destí
	/////////////////////////////////////////////////////////////////////////////////
	try{
		if(callback_func == Ajax.default_ajax_callback_func){
			target=params.split('target=')[1].split('&')[0];
		}else{
			target="";
		}
	}catch(e){
		target="";	
	}
	

	// Declarem i instanciem un objecte tipus petició HTTP
	//////////////////////////////////////////////////////
	var httpRequest;
	if (window.XMLHttpRequest) { // Mozilla, Safari, ...
		httpRequest = new XMLHttpRequest();
		if (httpRequest.overrideMimeType) {
			httpRequest.overrideMimeType('text/xml');
		}
	} else if (window.ActiveXObject) { // IE
		try {
			httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
		} catch (e) {
			try {
				httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
			} catch (e) {}
		}
	}
	

	// Solució alternativa (comentada)
	//////////////////////////////////
	/*		 var httpRequest=false;         try {          //Per navegadores diferents a internet explorer          httpRequest = new ActiveXObject("Msxml2.XMLHTTP");         } catch (e) {          try {                   //Per explorer                   httpRequest = new ActiveXObject("Microsoft.XMLHTTP");                   }                   catch (E) {                   httpRequest = false;          }         }         if (!httpRequest && typeof XMLHttpRequest!='undefined') {          httpRequest = new XMLHttpRequest();         }         */
	 
	
	// Comprovem que s'hagi creat l'instància httpRequest
	/////////////////////////////////////////////////////
	if (!httpRequest) {
		alert("Error, no s'ha pogut crear una instància de AJAX");
		return false;
	}
	

	// Posem a punt la funció de loading
	////////////////////////////////////
	var timer_id;
	if(loading_func != Ajax.default_ajax_loading_func){
		timer_id = setTimeout(loading_func,waiting_time);  // Ho fem en aquest punt per tenir el timer_id i poder fer el clearTimeout si la petició finalitza abans del temps d'espera
	}else{
		timer_id = setTimeout('Ajax.default_ajax_loading_func("'+target+'")',waiting_time); 
	}
	
	
	// Definim les funcions a cridar quan hi hagi canvis d'estat de la petició http
	///////////////////////////////////////////////////////////////////////////////
	httpRequest.onreadystatechange = function () { 
										
										/*/ Estats ens els que la crida està en procés
										if (httpRequest.readyState <4) { 
											Abans es crridava la loading_func en aquest punt
										}*/
										
										// Estat en el què la crida està resolta
										if (httpRequest.readyState == 4) { 						
											if (httpRequest.status == 200) { 					// Si s'ha executat correctament
											
												//Aturem el timer de la funció de loading
												eval("clearTimeout(timer_id);");
												if(method!="POST"){
													//Actualitzem la URL del navegador
													Ajax.setHashCall(url,params);
												}
												
												// Cridem la funció de callback indicada
												callback_func(httpRequest.responseXML);			
												
											}else{ 												// Sinó, hi ha hagut alguna mena d'error a la crida
												//alert("AJAX error");							// Fem un alert que en la versió final es comentaria	
											}
										}
									}		

	// Fem la petició 
	/////////////////
	
	
	//POST
	if(method=="POST"){  
		httpRequest.open('POST', url+"?nocache="+Math.random(), true); // *
		httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
		//httpRequest.setRequestHeader("Content-type", "text/plain;charset=ISO-8859-1");
		httpRequest.setRequestHeader("Content-length", params.length);
		httpRequest.setRequestHeader("Connection", "close");
		httpRequest.send(params);
		
	//GET
	}else{ 
		httpRequest.open('GET', url+"?"+params+"&nocache="+Math.random(), true);  // *
		httpRequest.send(null);
	}
	// *Afegim el paràmetre nocache assignant-li un número random perquè la URL sigui diferent cada vegada i no se la quedi en caché
	
	
	if(debug){
		window.open(url+"?"+params+"&nocache="+Math.random(), '_BLANK', 'width=600,height=400,menubar=yes,status=yes');
	}

}

// Funció que serveix a la crida AJAX per actualitzar la URL
////////////////////////////////////////////////////////////
Ajax.setHashCall = function (url,params){

	try{
	
		//De la URL agafem el nom de l'arxiu sense extensió per saber el nom de la crida i li afegim els parametres després d'un punt
		var nom_crida=url.split('/'); //new RegExp(/\//));
		nom_crida = nom_crida[nom_crida.length-1];
		nom_crida = nom_crida.split('.');
		nom_crida = nom_crida[0];
		var nova_crida = nom_crida+"."+params;
		
		//Ens guardem els hash actual per saber les crides que hi ha emmagatzemades a la URL actualment
		hash_act=window.location.hash;
		
		var swaped=false;  //variable per advertir si la crida ja era existent i per tant l'hem sobreescrit i no cal afegir-la
		var crides = hash_act.split('&&');  //Cada crida en el hash està separada per '&&', extreiem les crides
		delete crides[0]; //Borrem la primera crida que és innexistent, ja que el hash comença '#&&crida1.param1=valor1&&crida2.param1=valor1&param2=valor2
		
		for(i in crides){ // Per cada crida mirem si el nom de la crida coincideix i si és així la reemplacem, amb els nou paràmetres que hi pugui haver
			var crida = crides[i];
			if(crida.match(nom_crida+".")!=null){
				crides[i]=nova_crida;
				swaped=true;
			}
		}
		
		if(!swaped){  //Si no s'ha reemplaçat la crida, no existia la hi inserim
			crides[crides.length]=nova_crida;
		}

		crides = "#"+crides.join('&&');  //tornem a ajuntar les crides i les posem a punt.
		
		var canvi_url = Ajax.recentHash!=crides;  //detectem si hi ha canvis a les crides
		var auto_hist_check = window.history.length;  //per detectar si el navegador fa canvis a l'historic al canviar les crides
		
		Ajax.recentHash = "";   //Canviem la crida de manera que la funció de pollHash (veure més avall) no detecti el canvi
		window.location.hash = crides;
		Ajax.recentHash = crides;
		
		var auto_hist = auto_hist_check!=window.history.length;  //comprovem si el navegador canvi l'historic al canviar la crida
		
		if(canvi_url && !auto_hist){  //si el navegador no ho fa sol i la crida ha canviat utilitzem l'artimanya de l'iframe amagat cridant hist_mng de manera que llavors si crearà l'històric
			try{
					//el counter és perquè el navegador interpreti que és una url diferent cada vegada
					Ajax.history_iframe.src="ajax_hist_mng.html?counter="+Ajax.historyCounter+crides;
					Ajax.historyCounter++;
			}catch(e){
				//alert(e);
			}
		}
		
	}catch(e){
		//alert(e);
	}	
}




/*********************
 Intents per no haver de fer el PollHash
****************************
var Event = {
	add: function(obj,type,fn) {
		if (obj.attachEvent) {
			obj['e'+type+fn] = fn;
			obj[type+fn] = function() { obj['e'+type+fn](window.event); }
			obj.attachEvent('on'+type,obj[type+fn]);
		} else
		obj.addEventListener(type,fn,false);
	},
	remove: function(obj,type,fn) {
		if (obj.detachEvent) {
			obj.detachEvent('on'+type,obj[type+fn]);
			obj[type+fn] = null;
		} else
		obj.removeEventListener(type,fn,false);
	}
}

Event.add(window.location.hash.value,'onchange',function(){ alert('canvi'); });
window.location.hash.onchange=function (){ alert('canvi'); };

*/



//  Funció que serveix per anar revisant si hi ha hagut canvis en el hash 
//  És util per quan fem paste de una url de la mateixa pagina amb diferents crides (el navegador no torna a cridar la pàgina però nosaltres si que hem de llanár les crides AJAX que l'actualitzin
//	També és util per la navegació  històrica a traves de l'iframe quan el navegador no ho fa automàticament.
///////////////////////////////////////////////////////
Ajax.pollHash = function () {
  
	//Si el hash no ha canviat ho estés buit "" (quan estem fent l'actualització a la funció setHashCall)
	 if (window.location.hash==Ajax.recentHash || Ajax.recentHash=="") {
	   return; 
	 }
	 Ajax.recentHash = window.location.hash;
	 Ajax.executeHashCalls();
}



Ajax.init = function (){
	Ajax.pollHash()
	setInterval('Ajax.pollHash()',500);
	
	Ajax.history_iframe = document.createElement('iframe');
	Ajax.history_iframe.style.visibility='hidden';
	Ajax.history_iframe.style.display='none';
	document.getElementsByTagName('body')[0].appendChild(Ajax.history_iframe);
	
	Ajax.history_iframe.src = 'ajax_hist_mng.html#init';
}


// Funció que agafa la URL per extreure'n les crides AJAX que cal fer
//////////////////////////////////////////////////////////////////////
Ajax.executeHashCalls = function (){

	

	var to_dos = window.location.hash.split("&&");
	
	//window.location.hash="#";

	for(i in to_dos){
	
		try{
			var to_do = to_dos[i].split(".",2);
			var is_hashcall = eval("typeof("+to_do[0]+"_hashcall)!='undefined'");

			//Si s'ha definit una funció hashcall (que rep l'string de parametres)
			if(is_hashcall==1){
				if(to_do.length>1){
					eval(to_do[0]+"_hashcall('"+to_do[1]+"')");
				}else{
					eval(to_do[0]+"_hashcall()");
				}
				
			//Sinó es mira de cridar a la funció original, posant cada parametre en el mateix ordre.
			}else{
				var crida = to_do[0]+="(";
				var parametres = to_do[1].split("&");
				
				for(j in parametres){
					parametre = parametres[j];
					var valor_parametre = "";
					try{
						valor_parametre = (parametre.split("="))[1];
						if(typeof(valor_parametre)=='string'){
							valor_parametre = "'"+valor_parametre+"'";
						}
					}catch(e){}
					crida += ( j>0 ? (","+valor_parametre) : valor_parametre );
				}
				
				crida += ")";
			
				eval(crida);
			}
			
		}catch(e){ 
		//	alert(e); 
		}

	}
}


Ajax.default_ajax_callback_func = function (xmlDoc){

	try{
	
		var	target=xmlDoc.getElementsByTagName("target")[0].firstChild.data;
		var html=xmlDoc.getElementsByTagName("html");
	
		document.getElementById(target).innerHTML="";
		for (i=0;i<html.length;i++) {
			document.getElementById(target).innerHTML+=html[i].firstChild.data;
		}
		
	}catch(e){
		alert("AJAX default callback error: potser no s'ha especificat target o html en l'XML");	
	}
}


Ajax.default_ajax_loading_func = function (target){

	try{
		document.getElementById(target).innerHTML="Loading...";
	}catch(e){
		//alert("Loading...");
	}
}






//Funció que converteix els valors dels camps d'un formulari en una cadena per enviar-ho així a la crida AJAX
Ajax.formToStringParams = function (form_id){

	var form = document.getElementById(form_id);
	var params="";
	var form_elements=form.elements;

	for(var i = 0; i < form_elements.length; i++){

		var element=form_elements[i];
		var tipus=element.type;

		if(tipus=='hidden'){
			if(element.value.length>0){
				params+=element.name+"="+element.value+"&";
			}
		}else if(tipus=='text'){
			if(element.value.length>0){
				params+=element.name+"="+element.value+"&";
			}
		}else if(tipus=='password'){
			if(element.value.length>0){
				params+=element.name+"="+element.value+"&";
			}
		}else if(tipus=='textarea'){
			if(element.value.length>0){
				params+=element.name+"="+element.value+"&";
			}
		}else if(tipus=='checkbox'){
			if(element.checked){
				params+=element.name+"="+element.value+"&";
			}
		}else if(tipus=='radio'){
			if(element.checked){
				params+=element.name+"="+element.value+"&";
			}
		}else if(tipus=='select-one'){
			for(var j = 0; j < element.options.length; j++) {
				if(element.options[j].selected == true) {
					params+=element.name+"="+element.options[j].value+"&";
				}
			}
		}else if(tipus=='select-multiple'){
			for(var j = 0; j < element.options.length; j++) {
				if(element.options[j].selected == true) {
					params+=element.name+"="+element.options[j].value+"&";
				}
			}
		}
	
	}
	
	return params;
}
	

