/*

 ________________________________________________________________________________________
|					OBJET AJAX					 |
------------------------------------------------------------------------------------------

					Fabrice de Caluwe
					fabrice@le-castor.com
					mai 2007


Quelques consignes 
------------------

Sur le serveur , deux paramètres doivent être pris en compte

1- le cache sur le serveur => renvoyer des entêtes pour gérer le cache
2-le serveur reçoit les paramètres en UTF-8

exemple de traitement des variables suite à un post ou un get

$ma variable=utf8_decode($_REQUEST['ma_variable']);


exemple de sortie en php

	header("Content-type: text/html;charset=UTF-8");
	header("Cache-control: no-cache, max-age=0");
	echo utf8_encode($chaine);


limitation d'utilisation
------------------------

On ne peut pas utiliser la méthode multipart/form-data pour uploader des fichiers
semble-t-il que la méthode post doit pointer vers une page capable d'exploiter les informations.
Si un post mointe vers un fichier html, cela renvoit une erreur mais s'il pointe vers une page php.


exemple de mise en place sur une page web
------------------------------------------


<html>
<head>
<SCRIPT LANGUAGE="javascript" type="text/Javascript" src="../include/ajax.js"></script>
<SCRIPT LANGUAGE="javascript" >


function response(myvar){
document.getElementById("output").innerHTML='reponse du serveur: '+myvar;	
}

function send_form(){

var Query = new Ajax_send();

Query.http_method='POST';
Query.http_header='application/x-www-form-urlencoded';
Query.target_url='../include/test.php';
Query.query_string='essai=allo&salut='+document.myform.salut.value;
Query.anchor='myanchor';
Query.on_error='';
Query.if_no_ajax='';
Query.msg_error=1;
Query.msg_error_content = 'Ajax a rencontré une erreur';
Query.on_error='';
Query.if_no_ajax='';
msg_error=1;
Query.debug=1;
Query.synchro=0;
Query.delay=0;
Query.threading=1;
Query.cache=0;
Query.split_response='';
Query.max_time=3;
Query.on_response='response(myvar)';
Query.start();
}
</script>
</head>
<body>
<div id="output">allo</div>
<form name="myform" id="myform">
<input type="text" name="salut" value="bonjour, ca marche">
<a href="javascript:send_form()">executer ajax</a>
</form>
</body>


*/







var Ajax_send = function() {


/*______________________________________________________________________________________________
 					propriétés
________________________________________________________________________________________________*/ 

		//émission


		
		this.http_method = 'get'; //method http
		this.http_header = "application/x-www-form-urlencoded"; //en cas de post, header http à utiliser		
		this.target_url = ''; //url à ouvrir
		this.query_string ='';
		this.anchor=''; //permet de passer une ancre #ancre dans l'url. Attention ne pas mettre le caractère dièse
		
		this.synchro = 0;  	//determine si on est en asynchrone ou en synchrone
		this.threading = 1; //empêche ou permet plusieurs requêtes simultanées
		this.delay = 1 ;  //indique le délai en seconde avant d'accepter une nouvelle requête
		this.cache = 0; //active ou désactive le cache

		 
		//reception
		this.max_time = 0; //envoi une requête d'annulation de la demande au serveur après un délai en seconde d'inaction de la requête
		this.split_response = ''; //si cette propriete contient ce symbole, la chaine réponse ajax sera splité vers un tableau d'après ce symbole 
		this.on_response =''; //indiquer la fonction a évaluer quand on obtient la réponse on_response(myvar)
		this.on_error = ''; //indiquer la fonction a évaluer en cas d'erreur on_error(msg)
		this.if_no_ajax = ''; //indiquer la fonction a évaluer si ajax n'est pas disponible

		//la methode [nom_objet].request_cancel permet d'annuler la requête depuis l'extérieur

		//message


		this.msg_error = 1;
		this.msg_error_content = 'AJAX ERROR';
		this.debug = 0;
		


		var my_object=this;
		var doc = document;
				
		var Ajax = '';
		var bloc=0;
		

		



/*______________________________________________________________________________________________
 						annulation de la demande abort
________________________________________________________________________________________________*/ 


		this.request_cancel = function(){
	
			try{
				call_debug('abort ajax request sending');			
				Ajax.abort;
			}
			catch(erreur){
					
			my_object.show_error('error aborting ajax. error is '+erreur);
				
			}
			
		
		}






/*______________________________________________________________________________________________
 						debug
________________________________________________________________________________________________*/ 


		function call_debug(state){
	
	
		if(my_object.debug){
		var param='toolbar=no,location=no,directories=no,status=no,menubar=no,scrollbars=yes,resizable=yes,width=600,height=600';

		
		ext_window=open('','debug',param);
		ext_window.document.write('--'+state+'<br>');
		}
	
		}

		
/*______________________________________________________________________________________________
 					gestion des erreurs
________________________________________________________________________________________________*/ 
		
		
		this.show_error = function(where,my_error) {
		
			var msg = my_object.msg_error_content + '\n\n' + where + '\n' + my_error;
			call_debug('ERROR: '+msg);
			if(my_object.msg_error){alert(msg);}
			
			if(my_object.on_error){
				try{
				eval(my_object.on_error);
				}
				catch(erreur){
				
				my_object.show_error('on_error method: ',erreur);	
				}
			}			
		}
		



/*______________________________________________________________________________________________
 					ouverture de l'instance
________________________________________________________________________________________________*/ 
		
		
		function get_Ajax() {
		
		var instance = null;
		
			if(window.XMLHttpRequest){
			
					try {
			
					instance = new XMLHttpRequest();
					call_debug('try XMLHttp native component');
					
			
					}
					catch(e){
																					
					}
				
			}//end if
		
			else if (window.ActiveXObject){			
		
					try {
			
					instance = new ActiveXObject("Msxml2.XMLHTTP");
					call_debug('try Msxml2 component');
			
					}
					catch(e){
					
						try {
							
							instance = new ActiveXObject("Microsoft.XMLHTTP");		
							call_debug('XMLHTTP component');
						}
						catch(erreur){
							if(my_object.if_no_ajax){
								try{
								eval(my_object.if_no_ajax);
								}
								catch(erreur){
									
								my_object.show_error('if_no_ajax method: ',erreur);
									
								}
							
							}
							my_object.show_error('New Ajax instance has crashed ',erreur);					
						
						}							
					
						
					}//end catch					
		
			}//end else if


		call_debug('get_Ajax instance= '+instance);
		
		
		
		return instance;
		
		} //end function



		
/*______________________________________________________________________________________________
 						reception
________________________________________________________________________________________________*/ 
		
		
		function Ajax_received (){


			var state=Ajax.readyState;
			var state_content='nothing';
			call_debug('Trying to receive...');
			
			switch(state){

				//opera ne connait que les étapes 0 3 et 4
				
				case 0 : state_content='non initialized';break;
				case 1 : state_content='loading';break;
				case 2 : state_content='load'; break;
				case 3 : state_content='waiting for response';break;
				case 4 : state_content=my_object.target_url+'=> response send (http status: '+Ajax.status+')';break;
	
			}

			call_debug(state_content);
			
			if( state == 4 ){
				
				if(Ajax.status == 200){
					call_debug('Response=>success http status 200');
					
					if(my_object.delay==0){
						
						bloc=0;
						call_debug('bloc mode=0');	
					}


					if(my_object.split_response){
						
					var myvar = Ajax.responseText.split(my_object.split_response);	
					call_debug('split response with '+my_object.split_response);
					
					}
					else{
		
					var myvar = Ajax.responseText
					call_debug('no split response');
					}
					try{
					
						eval(my_object.on_response);
					}
					catch(erreur){
						my_object.show_error('on_response method: ',erreur);
					
					}

				}
				else{
				
				my_object.show_error('Ajax received','error with http response status: '+Ajax.status+' (wait for 200) be careful: for post method, html file may cause 405 error');
				
				}
			}
			
			
			
		}//end function		



/*______________________________________________________________________________________________
 				fonction d'encodage des params des urls
________________________________________________________________________________________________*/ 

			function encode_param(param){
				
				var chaine='';
				var paire='';
				var valeur='';
				var inc=0;
				
				try{
					paire=param.split("&");
				}
				catch(e){
				
				
				}
				
				while(inc<paire.length){
				
					if(inc>0){chaine=chaine+'&';}
					
					try{
						valeur = paire[inc].split("=");	
						chaine=chaine+valeur[0]+'=';
						
						if(valeur[1] !=''){														
							chaine=chaine+encodeURIComponent(valeur[1]);
							}
							
						
					}
					catch(e){
						
					}
														
					inc++;	
					}
				
				
				call_debug('encode param => original param: '+param+' transformation:'+chaine);
				
				return chaine;	
				}



		
/*______________________________________________________________________________________________
 						execution
________________________________________________________________________________________________*/ 
		
		
		this.start = function () {
			
			
		var new_query_string='';
		
		

			
			if(!bloc) {
				

				Ajax=get_Ajax();
				
				if(my_object.threading==0){
					bloc=1;
					call_debug('set bloc mode no delay');
				}


			
				if(my_object.synchro){my_synchro=false;}else{my_synchro=true;}




				//traitement sur la méthode get concernant l'encodage, le cache, la query string
				
				if(my_object.query_string !=''){
					var new_query_string=encode_param(my_object.query_string);
				}

				var get_url=my_object.target_url+'?';
				
				
				
				if(this.cache==0){
				
					get_url = get_url + 'nocache=' + (new Date()).getTime(); 
					
					}


								
				get_url = get_url + '&' + new_query_string;
				

				if(my_object.anchor != ''){

					get_url = get_url + '#'+my_object.anchor; 
					}
										





				try {
				
				var my_method=my_object.http_method.toUpperCase();
				
					if(my_method=='POST'){
				
					var url=my_object.target_url;
					
					}
					else{
					var url=get_url;
				
					}
					
					Ajax.open(my_method,url,my_synchro);
					call_debug('try to open component value'+Ajax+' '+ my_method +' '+url+' asynchrone= '+my_synchro);
				
				
				}			
				catch(erreur){
				
					my_object.show_error('unable to open Ajax component ' + my_method+' '+url);	
			
				}
			


			
				Ajax.onreadystatechange = Ajax_received;
				
				
			
				if(my_method='POST'){
				
					try{
						Ajax.setRequestHeader("Content-type",my_object.http_header);
					}
					catch(erreur){
					
						my_object.show_error('unable to set request header for http post method: '+my_object.http_header+' Error is ' + erreur);	
					}
				
								
					Ajax.send(new_query_string); 
					
					call_debug('http method post content: '+my_object.http_header+' post var: '+new_query_string);
				}
				else {

					call_debug('http method get');
					Ajax.send(null);						
				}				
				

				if(my_object.max_time){
				
			
				if(my_object.max_time){
					var max_time=my_object.max_time*1000;
					setTimeout(my_object.request_cancel,max_time);
				}
			}


			}//end bloc
			else{
			
			call_debug('permission refused : Ajax is in bloc mode ');
			
			}

			if(my_object.delay>0){
				
				
				bloc=1;
				var seconde=my_object.delay * 1000;
				
				setTimeout("bloc=0",seconde);
				call_debug('set bloc mode delay:'+seconde);
				
			}//end if_delay
					



		}//end methode start
	





}//end Ajax send		
