/* ============================== Méthodes communes ==============================
 *
 * Sont présentes ici les méthodes communes aux Webaps Iphone Cityvox et Iphone Cinefil
 * Toutes les méthodes présentes ici doivent être commentées !!!
 * 
*/

/* ================================== UTILS =================================== */

// Pour gagner de la place $ devient un alias de document.getElementById
function $(id) {
	var tmp = document.getElementById(id);
	if(tmp && isSet(tmp)) return tmp;
	return false;
}

// Fonction qui permet de tester si une variable est définie ou non
function isSet( variable ) {
	return( typeof( variable ) != 'undefined' );
}

/* ======================== Permet le travail en local  ======================= */

function isLocal(domain) {
	var localConf = ['172.17.3.82', '192.168.7.173', '192.168.7.148'];
	if (localConf.indexOf(domain)==-1) { return false; }
	else { return true; }
}

/* ============================== Méthodes sur les tableau associatifs ============================== */

// Suppression d'une clef dans un tableau associatif
function delKey(clef) {
	if (arguments.length == 1) { // context
		if (context[clef]) {
			delete context[clef];
		}
	} else { // Autre tableau
		var table = arguments[1];
		if (table[clef]) {
			delete table[clef];
		}
	}
}

// Suppression de plusieurs clef dans un tableau associatif
function delKeys(tabClef) {
	if (arguments.length == 1) { // context
		for (var i=0; i<tabClef.length; i++) {
			delKey(tabClef[i]);
		}
	} else { // Autre tableau
		var table = arguments[1];
		for (var j=0; j<tabClef.length; j++) {
			delKey(tabClef[j], table);
		}
	}
}

// Correction du bug de gestion des tableaux associatifs pour safari et google chrome
function validkey(key) {
	if (key!='indexOf' && key.charAt(0)!=' ' && key.indexOf('}')==-1) { return true; }
	return false;
}

// Renvoi true si l'objet est un array
function isArray(obj) {
	return obj.constructor == Array;
}

/* ============================== Méthodes Ajax ============================== */

// Création d'un Objet XMLHttp
function newXmlHttp() {
	var Xobject;
	if(window.XMLHttpRequest) { // Iphone + Safari + Firefox 
		try {
			Xobject = new XMLHttpRequest(); 
		} catch(e) {
			Xobject = false;
		}
	} else if(window.ActiveXObject) { // Internet Explorer 
		try {
			Xobject = new ActiveXObject("Microsoft.XMLHTTP"); 
		} catch(f) {
			Xobject = false;
		}
	} else { // XMLHttpRequest non supporté par le navigateur 
		Xobject = false;
	}
	return Xobject;
}

/* ============================== Méthodes Ajax ============================== */

/* ===== freeAjaxPipe =====
 * Libération d'un pipe Ajax : Arrète toutes les  opérations en cours dans le pipe spécifié
 * @param: pipe (int) - Le numéro du pipe Ajax à libérer
 */
function freeAjaxPipe(pipe){
	if (ajax_in_progress[pipe]) {
		ajax_in_progress[pipe] = false;
		clearTimeout(timerAntiblocage[pipe]);
		xhr_object[pipe].abort();
	}
	if (ajax_loaded[pipe]) { ajax_loaded[pipe] = false;}
}

/* ===== freeSecondaryAjaxPipes =====
 * Arrète toutes les opérations en cours dans les pipes secondaires (de 1 à 3)
 * Les pipes secondaire sont généralement utilisés pour le chargement de la pub
 */
function freeSecondaryAjaxPipes() {
	for (var i=1; i < ajax_in_progress.length; i++) {
		freeAjaxPipe(i);
	}
}

/* ===== useMainAjaxPipe =====
 * On demande l'autorisation pour utiliser le pipe Ajax principal
 * @param: freeSecondaryPipes (BOOL) - True si l'on souhaite également libérer les pipes secondaires
 * @param: redirect (BOOL) - true si l'on souhaite simplement utiliser le pipe principal pour faire une redirection
 * @param: preload (BOOL) - true s'il faut afficher le loader, false sinon
 * @return : (BOOL) true si le pipe est disponible, sinon false
 */
function useMainAjaxPipe(freeSecondaryPipes, redirect, preload) {
	
	if (action_in_progress) { // Il y a déjà une action en cours : est-ce qu'on peut l'arreter ?
		if (ajax_in_progress[0]) { // Oui on peut l'arreter
			freeAjaxPipe(0); // Arret de toutes les opérations dans le pipe principal
			if(redirect) { action_in_progress = false; } // Dans le cas d'une redirection on met action_in_progress à false
		} else { return false; } // Non on ne peut plus l'arreter (transition en cours)
	} else if (!redirect) { // S'il n'y a pas de redirection on met action_in_progress à true
		action_in_progress = true;
	}
	if (freeSecondaryPipes) {
		freeSecondaryAjaxPipes(); // On libère les pipes secondaires (Arret du chargement de la pub)
	}
	if (preload) {
		startSpinning(); // Démarage du spinner de Preload Classique
	} else {
		stopSpinning(); // Arret du Preload Classique s'il est en cours
	}
	return true;
}

/* ===== getPhp =====
 * Appel d'une page PHP en AJAX : 
 * Appel l'url d'une page php donnée et récupére le contenu renvoyé par cette page
 * @param: url - url to call
 * @param: onSuccess - Script to execute on Sucess
 * @param: onFail  - Script to execute on Fail
 * @param: params - list of params
 * @param: pipe - 0=main pipe for loading pages, pipe 1 & 2 & 3 are used for loading ads
 */
function getPhp(url, onSuccess, onFail, params, pipe) {
	ajax_in_progress[pipe] = true;
	ajax_loaded[pipe] = false;
	xhr_object[pipe] = newXmlHttp();
	if (xhr_object[pipe]) {
		xhr_object[pipe].open("GET", url, true);
		timerAntiblocage[pipe] = setTimeout(function () { // Si délai d'attente dépassé
			xhr_object[pipe].abort(); 
			if (ajax_in_progress[pipe]) { // Pour éviter d'éxécuter 2x onFail
				ajax_in_progress[pipe] = false;
				eval(onFail);
			}
		},check_delay);
		
		xhr_object[pipe].onreadystatechange = function () { 
			//console.log('pipe : '+pipe+' - readyState : '+xhr_object[pipe].readyState+' - status : '+xhr_object[pipe].status); //Pour Firebug
			if(xhr_object[pipe].readyState == 4 && ajax_in_progress[pipe]) {
				ajax_in_progress[pipe] = false;
				clearTimeout(timerAntiblocage[pipe]); // On peux supprimer le timeout
				if (xhr_object[pipe].status == 200 && xhr_object[pipe].responseText != '') {
					ajax_loaded[pipe] = true;
					eval(onSuccess);
				} else { // si réponse négative
					eval(onFail); 
					return;
				}
			}
		};
		xhr_object[pipe].send(null);
	} else {
		alert("Votre navigateur ne supporte pas les objets XMLHTTPRequest..."); 
		return; 
	}
}

/* ===== getRedirectionUrl =====
 * Vérifie que le pipe principal est Libre, et exécute un getPhp sur ce pipe
 * @param: pipe (int) - Le numéro du pipe Ajax à libérer
 */
function getRedirectionUrl(url, onSuccess, onFail) {
	// On demande l'utilisation du pipe Ajax Principal
	if(!useMainAjaxPipe(false, true, true)) { return; } // Impossible d'utiliser le pipe principal
	var params = [];
	getPhp(url, onSuccess, onFail, params, 0);
}

/* ============================== Méthodes D'accès aux Pages ============================== */

function getPage(url, params) {
	var onSuccess = 'getPageSuccess(xhr_object[0].responseText, params)';
	var onFail = 'getPageFail(params)';
	var pipe = 0; // Default pipe for Pages
	getPhp(url, onSuccess, onFail, params, pipe);
}

function getPageFail(params) {
	if (!params.listPreload) { stopSpinning(); }
	action_in_progress = false;
	alert("Delai d\'attente depasse");
}

/* ================= Récupération et affichage de la publicité ================== */

// Demande d'affichage de publicité
function getPub(url, id, pipe) {
	var tmp = [];
	if (!ajax_loaded[pipe] && !ajax_in_progress[0] && !ajax_in_progress[pipe]) { // Vérification que le pipe n'est pas occupé
		var params = [];
		getPhp(url, 'getPubSuccess(xhr_object['+pipe+'].responseText, \''+id+'\', \''+pipe+'\');', 'getPubFail( \''+pipe+'\');', params, pipe);
	}
}
// Décompte d'une page vue + demande d'affichage de la publicité
function getPubAndEstat(url, id, pipe, marqueur, master, niveau1, niveau2, niveau3, niveau4) {
	//alert("getPubAndEstat marqueur : "+marqueur+" - "+master+" - "+niveau1+" - "+niveau2+" - "+niveau3+" - "+niveau4);
	// Script de stat
	var script ='<!-- eStat -->'+
				'<SCRIPT LANGUAGE="JavaScript">'+
				'<!--'+
				'var _PJS=0;'+
				'//-->'+
				'</script>'+
				'<SCRIPT LANGUAGE="JavaScript" SRC="http://prof.estat.com/js/ml.js"></script>'+
				'<SCRIPT LANGUAGE="JavaScript">'+
				'<!--'+
				'if(_PJS) _estatl("'+marqueur+'","'+master+'","'+niveau1+'","'+niveau2+'","'+niveau3+'","'+niveau4+'");'+
				'//-->'+
				'</script>'+
				'<noscript>'+
				'<IMG SRC="http://prof.estat.com/m/web/'+marqueur+'?g='+master+'&c='+niveau1+'&p='+niveau2+'&l3='+niveau3+'&l4='+niveau4+'" BORDER="0" WIDTH="1" HEIGHT="1" />'
				'</noscript>'+
				'<!-- /eStat -->';
	// Ajout du script dans la div
	addToDiv(id, script, false);
	// On execute le javascript de la div :
	executeDivJavascript(id, context.browser == 'firefox', false);
	
	// On fait appel à la méthode classique pour récupérer la publicité
	getPub(url, id, pipe);
}

// Succès du chargement de la pub
function getPubSuccess(result, id, pipe) {
	addToDiv(id, result, false);
	//resizeContainerHeight();
}

// Echec du chargement de la pub
function getPubFail(pipe) {}

/* ============================== Webcontext ============================== */

// Fonction qui permet de mettre à jour le webContext à partir d'un tableau
function updateContex(context, tab) {
	if (tab) {
		for (var key in tab) {
			if (validkey(key) && tab[key]!==context[key]) {
				context[key] = tab[key];
			}
		}
	}
}

// Fonction qui permet de mettre à jour le webContext à partir d'un cookie
function updateContextFromCookie(context, cookie) {
	if (cookie) {
		updateContex(context, cookie);
		context.cookie = cookie;
	}
}

/* ============================== Gestion du Preloader de la page : Spinner ============================== */

var spinLevel = 1;
var timerSpin;

// Fait boucler le spinner
function spin() {
	if (!spin_in_progress) { return; }
	$('preload').style.display = "block";
	spinLevel = (spinLevel === 12) ? 1 : spinLevel;
	var pixel = 48 * spinLevel;
	$('spinner').style.backgroundPosition = "-"+ pixel +"px";
	spinLevel++;
	timerSpin = setTimeout(spin, 50);
}

// Démare le spinner
function startSpinning() {
	if (!spin_in_progress) {
		spin_in_progress = true;
		spin();
	}
}

// Arrete le spinner
function stopSpinning() {
	if (spin_in_progress) {
		$('preload').style.display = "none";
		clearTimeout(timerSpin);
		spinLevel = 1;
		spin_in_progress = false;
	}
}

/* ============================== Gestion du scroll de la page ============================== */

// Fonction qui retourne le niveau de scroll de la page
function getScrollXY() {
	var scrOfX = 0, scrOfY = 0;
	if( typeof( window.pageYOffset ) == 'number' ) {
		//Netscape compliant
		scrOfY = window.pageYOffset;
		scrOfX = window.pageXOffset;
	} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
		//DOM compliant
		scrOfY = document.body.scrollTop;
		scrOfX = document.body.scrollLeft;
	} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
		//IE6 standards compliant mode
		scrOfY = document.documentElement.scrollTop;
		scrOfX = document.documentElement.scrollLeft;
	}
	return [ scrOfX, scrOfY ];
}

// Fonction qui cache la barre d'url iphone
function hide_address_bar() {
	window.scrollTo(0, 0);
}

// Fonction qui exécute un saut de scroll sur la page
function executeJump(height) {
	if (height && height !== 'none' && height !== 'hide') {
		var newOffset;
		if (window.pageYOffset > height) {
				var i=1;
				while (window.pageYOffset > height) {
					newOffset = Math.max(Math.round(window.pageYOffset - window.pageYOffset / 3), i);
					if(newOffset<height) {
						newOffset = height;
					}
					window.scrollTo(0,newOffset);
					i++;
				} 
		} else if (window.pageYOffset< height){
				var oldPageOffset=-1;
				var i=1;
				while (window.pageYOffset < height) {
					if (oldPageOffset === window.pageYOffset) { // On ne peux pas scroller plus bas que le bas de la page
						window.scrollTo(0,height);
						break;
					}
					newOffset = Math.max(Math.round(window.pageYOffset + window.pageYOffset / 3), i);
					if(newOffset>height) {
						newOffset = height;
					}
					oldPageOffset = window.pageYOffset;
					window.scrollTo(0,newOffset);
					i++;
				} 
		}
	} else if (height === 'hide'){ // On cache la barre d'url
		hide_address_bar();
	}
}

/* ===================== Méthodes DOM génériques sur les div ================== */

// Création d'un nouveau div
function createDiv(id, html, parent) {
	var newdiv = document.createElement('div');
	newdiv.setAttribute('id', id);
	if (html) {
       newdiv.innerHTML = html;
	} else {
       newdiv.innerHTML = "nothing";
	}
	$(parent).appendChild(newdiv);
}

// Suppression d'un div
function removeDiv(id, parent) {
	$(parent).removeChild($(id));
}

// Affiche un div
function showDiv(id) {
	$(id).style.opacity = 1;
}

// Masque un Div
function hideDiv(id) {
	$(id).style.opacity = 0;
}

// Supprime le contenu d'un div
function clearDiv(id) {
	$(id).innerHTML = '';
}

// Récupère la hauteur d'un div
function getDivHeight(id) {
	return $(id).offsetHeight;
}

// Remplace le contenu d'un div
function setToDiv(id, html) {
	clearDiv(id);
	$(id).innerHTML = html;
}

// Ajoute du contenu à la fin d'un div
function addToDiv(id, html, scroll) {
	//TODO : regarder la méthode scrollHeight
	$(id).innerHTML += html;
	if (scroll) { $(id).scrollTop = $(id).scrollHeight; }
}

function addClassName(element, className) {
	if (element) {
		if (!hasClassName(element, className)) element.className += (element.className ? ' ' : '') + className;
			return element;
	}
	return null;
}

function hasClassName (element, className){
	if (element) {
		var elementClassName = element.className;
		return (elementClassName.length > 0 && (elementClassName == className || new RegExp("(^|\\s)" + className + "(\\s|$)").test(elementClassName)));
	}
}

function removeClassName (element, className) {
    if (element) {
        element.className = element.className.replace(new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ');
        element.className = element.className.replace(/^\s+|\s+$/g, ""); // strip whitespace
        return element;
    }
    return null;
}

// Execute le contenu javascript d'une div
function executeDivJavascript(id, firefox, force) {
	if (!firefox || force) { // Si on n'est pas sur Firefox il faut exécuter le script de la page manuellement
		var x = $(id).getElementsByTagName("script");
		var delayed = [];
		var j=0;
		// Scripts qui doivent êtres exécutés en premier
		for (var i=0;i<x.length;i++) {
			var text = x[i].text;
			if (isSet(text) && text != '' && text.indexOf(';')!=-1) {
				text = text.replace('<!--','');
				text = text.replace('-->','');
				if (text.indexOf('delayexecution;')!=-1) { // On le reporte à la fin
					delayed[j]=text;
					j++;
				} else { eval(text); }
			}
		}
		// Scripts qui doivent êtres exécutés en derniers
		for (var i=0; i<j; i++) {
			if (isSet(delayed[i])) {
				eval(delayed[i]);
			}
		}
	}
}

/* ============================== Méthodes Dom spécifiques sur les pages ============================== */

// Affichage la page
function showPage(page) {
	showDiv ('page_'+page);
}

// Supprime la page
function removePage(page) {
	removeDiv('page_'+page, 'pages_container');
}

// Masque la page
function hidePage(page) {
	hideDiv('page_'+page);
}

// Supprime le contenu de la page
function clearPage(page, delClass) {
	clearDiv('page_'+page);
	if (delClass) {
		$('page_'+page).style.display='none';
		$('page_'+page).className = '';
	}
}

// Retourne la hauteur d'une page
function getPageHeight(page) {
	return getDivHeight('page_'+page);
}

// Ajoute du contenu à une page
function addToPage(page, html, scroll, js, fond) {
	addToDiv('page_'+page, html, scroll);
	if (fond) { $('page_'+page).className = fond; }
	if (js) { setTimeout(function () { executeDivJavascript('page_'+activePageId, true, true); }, 300); }
}

// Resize le container en fonction de la hauteur de la page
// TODO : supprimer les apples à cette méthode puisque celle-ci ne fait plus rien
// Atention à ce que les 2 webap fonctionnent bien après suppression (cinefil + cityvox)
function resizeContainerHeight() {
	var divHeight = getPageHeight(activePageId);
	var newHeight;
	if(arguments.length>0) {
		newHeight = divHeight+arguments[0];
	} else {
		newHeight = Math.max(divHeight, screen_height);
	}
	//$('pages_container').style.minHeight = newHeight+'px';
}

/* ============================== Gestion des calques Dropdown ============================== */

// Change le dropdown visible
function show(id) {
	var smenu = $('smenu'+id);
	if (id<100) {
		for (var i = 1; i<=10; i++) {
			if ($('smenu'+i) && i!= id) {
				$('smenu'+i).style.display='none';
				$('menu'+i).className = 'closed';
			}
		}
	} else {
		for (var i = 100; i<=110; i++) {
			if ($('smenu'+i)&& i!= id) {
				$('smenu'+i).style.display='none';
				$('menu'+i).className = 'closed';
			}
		}
	}
	if (smenu) {
		var menu = $('menu'+id);
		if (menu.className == 'opened') {
			smenu.style.display='none';
			menu.className = 'closed';
		} else {
			smenu.style.display = 'block';
			menu.className = 'opened';
		}
	}
	resizeContainerHeight();
}


/* ============================== Gestion du chargement des images ============================== */

// Applique l'image chargée à la source
function imagesLoaded(id, image) {  
	$(id).src = image;
}

// Preload d'une image
function preloadO(image, id) {
	var objImage = new Image();
	objImage.onLoad=imagesLoaded(id, image);
    objImage.src=image;
}

// Preload de plusieurs images
function preloadImages(images, prefixe, offset) {
	var tmp = prefixe;
	var tb = false;
	if (isArray(prefixe)) { tb = true; }
	for(var j=offset;j<(offset+images.length);j++) {
		if(images[j]) {
			if (tb) { var tmp = prefixe[j]; }
			if (images[j]!=$(tmp+j).src) {
				preloadO(images[j], tmp+j);
			}
		}
	}
}

/* ============================== Gestion des sessions utilisateurs ============================== */

// Création d'un nouvel ID utilisateur aléatoire
function createRandomId(length)
{
  var chars = "1234567890";
  var pass = "";
  for(var x=0;x<length;x++)
  {
    i = Math.floor(Math.random() * 10);
    pass += chars.charAt(i);
  }
  return pass;
}

// Récupération des variables associatives stockées dans un cookie : renvoi un tableau
function getCookie(name) {
	var cookie = LireCookie(name);
	if (cookie) {
		var tab = cookie.split(';');
		var result = [];
		for (var i=0; i<tab.length; i=i+2) {
			result[tab[i].toLowerCase()] = tab[i+1];
		}
		return result;
	}
	return false;
}

// Fonction de création d'un cookie : passe un tableau avec les variables associatives à stocker
function createCookie(name, tab, domaine) {
	var dateExpire = new Date;
	var value = '';
	for (var key in tab) {
		if (validkey(key) && tab[key]!=='NULL') {
			value += key+";"+tab[key]+";";
		}
	}
	if (value!='') { // pas d'écriture de cookie vide
		value = value.slice(0,-1); // Suppression du dernier ;
		dateExpire.setFullYear(dateExpire.getFullYear()+1);
		EcrireCookie(name, value, dateExpire, '/', domaine);
	}
}

// Fonction de mise à jour d'un cookie associatif
function updateCookie(name, values, context) {
	var domain = context.cookieDomain;
	var cookie = context.cookie;
	if (cookie) { // Le cookie existe
		for (var key in cookie) {
			if (validkey(key) && !values[key]) {
				values[key] = cookie[key];
			}
		}
	}
	createCookie(name, values, domain);
}

/* ============================== Gestion des Champs de recherche ============================== */

function filterVille(element, libvil, posvil) {
	var value = stringAccentToNoAccent(element.value.toUpperCase()); // Keyword
	var size = value.length; // Nombre de caractères du keyword
	var nbvilles = libvil.length; // Nombre de villes dans le tableau
	var max = 12; // Nombre max de villes à afficher
	var tabResult = []; // Liste de villes correspondantes
	if (size>0) {
		var j=0;
		for (var i=0; i<nbvilles; i++) {
			if(j>max) {break;}
			if(stringAccentToNoAccent(libvil[i]).substring(0,size).toUpperCase() == value) {
				tabResult[j] = posvil[i];
				j++;
			}
		}
		var nbResult = tabResult.length;
		if (nbResult>0) {
			var k=0;
			for(var i=0; i<nbvilles; i++) {
				var test = false;
				for(var j=0; j<nbResult; j++) {
					if(i==tabResult[j]) { test = true; } // La ville fait partie des résultats
				}
				if (test) {
					if (k%2==0) {
						var nomClass = 'pair';
					} else {
						var nomClass = 'impair';
					}
					$('p'+i).className = nomClass;
					k++;
				} else { // On cache 
					$('p'+i).className = 'hidden';
				}
			}
		} else {
			for(var i=0; i<nbvilles; i++) {
				$('p'+i).className = 'hidden';
			}
		}
	} else { // On affiche les n plus grandes villes
		for(var i=0; i<nbvilles; i++) {
			if(i<max) { // Ville majeure
				$('p'+posvil[i]).className = 'pair';
			} else {
				$('p'+posvil[i]).className = 'hidden';
			}
		}
		var k=0;
		for(var i=0; i<nbvilles; i++) {
			if($('p'+i).className=='pair') {
				if (k%2!=0) {
					$('p'+i).className = 'impair';
				}
				k++;
			}
		}
	}
}

/* ============================== Activate star ============================== */

function activateStar(idStar){
	var limit = idStar.substr(-1,1);
	var nameStr = idStar.substr(0,idStar.length-1); 
	for(i=1;i<=5;i++){
		if(i<=limit){
			$(nameStr+i).className = 'etlActive';
		}else{
			$(nameStr+i).className = 'etlInactive';
		}	
	}
	$(idStar).value = limit;
	switch(nameStr){
		case 'accstar':
			$('accstarIn').value = limit;
			break;
		case 'decor':
			$('decorIn').value = limit;
			break;
		case 'qualite':
			$('qualiteIn').value = limit;
			break;		
	}
}


// Efface le contenu d'un imput quand il est sélectionné.
function effaceInput(textAEffacer, idInput){
	var inputValue = $(idInput).value;
	if(inputValue.indexOf(textAEffacer) !=-1){
		$(idInput).value = '';
	}
}

/* ======================== Méthodes pour travailler avec strings  ======================= */

// Fonction qui permet de récupérer une variable de type string dans l'url
function getStringFromRequest(name){
	name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
	var regexS = "[\\?&]"+name+"=([^&#]*)";
	var regex = new RegExp(regexS);
	var results = regex.exec(window.location.href);
	if(results == null){
		return false;
	} else {
		return results[1];
	}
}


// Remplace toutes les occurences d'une chaine
function stringReplaceAll(str, search, repl) {
	while (str.indexOf(search) != -1){
		str = str.replace(search, repl);
	}
	return str;
}

// Remplace les caractères accentués
function stringAccentToNoAccent(str) {
	var norm = ['À','Á','Â','Ã','Ä','Å','Æ','Ç','È','É','Ê','Ë',
		'Ì','Í','Î','Ï', 'Ð','Ñ','Ò','Ó','Ô','Õ','Ö','Ø','Ù','Ú','Û','Ü','Ý',
		'Þ','ß', 'à','á','â','ã','ä','å','æ','ç','è','é','ê','ë','ì','í','î',
		'ï','ð','ñ', 'ò','ó','ô','õ','ö','ø','ù','ú','û','ü','ý','ý','þ','ÿ'];
	var spec = ['A','A','A','A','A','A','A','C','E','E','E','E',
		'I','I','I','I', 'D','N','O','O','O','0','O','O','U','U','U','U','Y',
		'b','s', 'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i',
		'i','d','n', 'o','o','o','o','o','o','u','u','u','u','y','y','b','y'];
	for (var i = 0; i < spec.length; i++){
		str = stringReplaceAll(str, norm[i], spec[i]);
	}
	return str;
}

function extractCodeResteFromReste(reste) {
	var tmpArray = reste.split("_");
	return tmpArray[1];
}

/* ============================== Méthodes de débug ============================== */

// Détermine le navigateur web utilisé par le client en fonction du user agent
function getBrowser() {
	var userAgent = navigator.userAgent;
	if (userAgent.match(/iPhone/i) || userAgent.match(/iPod/i)) { // Je suis sur un Iphone
		return 'iphone';
	} else if (/Firefox[\/\s](\d+\.\d+)/.test(userAgent)) { // Je suis sur firefox
		return 'firefox';
	} else if (/Safari[\/\s](\d+\.\d+)/.test(userAgent)) { // Je suis sur Safari
		return 'safari';
	} else { // Autre
		return 'other'; 
	} 
}

/* ============================== Méthodes de débug ============================== */

// Affichage d'un tableau
function printarray(theObj) {
	var deb = '';
	if (arguments.length>1) {
		deb = arguments[1];
	}
	var result = '';
	result += "\n"+deb+"---";
	for(var key in theObj) {
   		if(validkey(key)) {
			if(theObj[key].constructor == Array || theObj[key].constructor == Object) {
				result += "\n"+deb+"["+key+"] =>"+typeof(theObj);
				result += printarray(theObj[key], deb+'\t');
			} else {
				result += "\n"+deb+"["+key+"] =>"+theObj[key];
			}
		}
	}
	result += "\n"+deb+"---";
	return result;
}

/* ======================== Méthodes non utilisés mais conservés pour référence ======================= */

// Gestion du changement d'orientation de la page
function updateOrientation() {
    switch(window.orientation) { 
    case 0: 
        orient = "portrait"; 
        break; 
    case -90: 
        orient = "landscape"; 
        break; 
    case 90: 
        orient = "landscape"; 
        break; 
    case 180: 
        orient = "portrait"; 
        break; 
    } 
    document.body.setAttribute("orient", orient); 
} 
