/************************************************************************************
@ Author : Nicolas Castelli
@ Mail : nicolas.castelli2@gmail.com
@ Date of creation : 2008-01-01
@ Filename : prototype.js
@ Use : Javascript dédié au prototypage des classes JS existantes.
Ici, sont prototypés :
- la classe Image
- la classe Element
- la classe String
- la classe Array
************************************************************************************/

/************************************************************************/
/****************************  | STRING |  ******************************/
/************************************************************************/

//Permet de tester si une chaine contient l'un des caractères de la chaîne "strChar"
String.prototype.hasChar = function(strChar) {
			var reg = new RegExp("["+strChar+"]", "g");
			return reg.test(this);
};

//Permet de tester si une chaine contient TOUS les caractères de "strChar"
String.prototype.hasAllChar = function(strChar) {
	    var i=0; var ok=0;
	    for(i; i < strChar.length; i++)
			{
				if(this.hasChar(strChar.charAt(i)))
					ok += 1;
			}
			if (ok == strChar.length)
				return true;
			return false;
};

//Permet de tester si une chaine contient le mot "word".
//Le parametre "caseSbl" indique s'il faut être sensible la casse ou non.
//Par défaut, non, mettre 1 pour oui.
String.prototype.hasWord = function(word, caseSbl) {
	if(caseSbl > 0)
		var reg = new RegExp(word, "g");
	else
		var reg = new RegExp(word, "gi");
	return reg.test(this);
};

//Permet de tester si une chaine contient exactement le mot "word".
//Le parametre "caseSbl" indique s'il faut être sensible la casse ou non.
//Par défaut, non, mettre 1 pour oui.
//Exemple : chaine.hasExactWord("COMMON") doit retourner :
// true pour chaine = COMMON;RARE
// false pour chaine = UNCOMMON;RARE
String.prototype.hasExactWord = function(word, caseSbl) {
	if(caseSbl > 0)
		var reg = new RegExp('\\b' + word + '\\b', 'g');
	else
		var reg = new RegExp('\\b' + word + '\\b', 'gi');
	return reg.test(this);
};

//Permet de tester si une chaine contient l'un des mots de la chaine "words".
//Chaque mot doit être séparé par des ";", sinon, la fonction agira comme s'il s'agissait d'un seul mot !
//Le parametre "caseSbl" indique s'il faut être sensible la casse ou non.
//Par défaut, oui, mettre 1 pour non.
//Le parametre "exactWord" s'utilise si l'on veut que la recherche soit
//Exactement identique au filtre. Par défaut, non, mettre 1 pour oui.
String.prototype.hasWords = function(words, caseSbl, exactWord) {
	var i=0;
	var word = "";
	var result = false;
	//Cas 1 : un seul mot dans la chaine
	if(!words.hasChar(";"))
	{
		//La chaine doit contenir le mot exact
		if(exactWord > 0)
			result = this.hasExactWord(words, caseSbl);
		else
			result = this.hasWord(words, caseSbl);
	}
	//Cas 2 : plusieurs mots dans la chaine séparée par des ;
	else
	{
		var arr = words.split(";");
		for(i=0; i < arr.length; i++)
		{
			word = arr[i];
			if(exactWord > 0 && this.hasExactWord(word, caseSbl))
				result = true;
			else if((!exactWord) && this.hasWord(word, caseSbl))
				result = true;
		}
	}
	return result;
};

//Permet de tester si une chaine contient TOUS les mots de la chaine "words".
//Chaque mot doit être séparé par des ";", sinon, la fonction agira comme s'il s'agissait d'un seul mot !
//Le parametre "caseSbl" indique s'il faut être sensible la casse ou non. Par défaut, oui, mettre 1 pour non.
String.prototype.hasAllWords = function(words, caseSbl) {
	var i=0; var word = ""; var ok = 0;
	//Cas 1 : un seul mot dans la chaine
	if(!words.hasChar(";"))
		return this.hasWord(words, caseSbl);
	//Cas 2 : plusieurs mots dans la chaine séparée par des ;
	else
	{
		var arr = words.split(";");
		for(i=0; i < arr.length; i++)
		{
			word = arr[i];
			if(this.hasWord(word, caseSbl))
				ok += 1;
		}
	}
	if (ok == arr.length)
		return true;
	return false;
}

//Supprime le mot "word" de la chaîne dont les mots sont séparés par des ";"
//Si la chaine ne contient pas le mot, la fonction retourne FALSE
String.prototype.deleteWord = function(word) {
	var newStr = false;
	if(this.hasExactWord(word, 0))
	{
		newStr = this.replace(word, "");
		//La suppression d'un mot peut entraîner 3 cas dans la nouvelle chaine :
		//1) A;B;C;D ==> ;B;C;D
		//2) A;B;C;D ==> A;;C;D
		//3) A;B;C;D ==> A;B;C;
		//Il faut donc corriger cela pour mettre la chaine au norme
		if(newStr.charAt(0) == ";")
			newStr = newStr.substr(1, newStr.length - 1);
		else if(newStr.charAt(newStr.length-1) == ";")
			newStr = newStr.substr(0, newStr.length - 1);
		else
			newStr = newStr.replace(/;;/gi, ";");
	}
	return newStr;
}

//Convertir les caractères spéciaux en HTML
String.prototype.convertToHTML = function() {
	var convert = this.replace(">=", "&gt;=");
	convert = convert.replace(">", "&gt;");
	convert = convert.replace("<", "&lt;");
	convert = convert.replace("<=", "&lt;=");
	return convert;
}

//Supprimer tous les espaces blancs d'une chaine
String.prototype.trim = function() {
	return this.replace(/^\s+|\s+$/g,"");
}

//Supprimer tous les espaces blancs d'une chaine en début de chaine
String.prototype.ltrim = function() {
	return this.replace(/^\s+/,"");
}

//Supprimer tous les espaces blancs d'une chaine en fin de chaine
String.prototype.rtrim = function() {
	return this.replace(/\s+$/,"");
}

/************************************************************************/
/****************************  | ARRAY |  *******************************/
/************************************************************************/
// * Classe  : MyArray
// * Utilité : Pour ajouter des fonctions spécifiques de tri à un tableau
MyArray = function() {
	var myArr = new Array();

	this.hasElement = function(elmt) {
		for(var i=0; i < this.length; i++)
		{
			var el = this[i];
			if(el == elmt) { return true; }
		}
		return false;
	}

	this.sortArray = function(sortCol) {
		this.sort(
			function by_name(a, b) {
				if (a[sortCol] < b[sortCol] ) { return -1; }
				if (a[sortCol] > b[sortCol] ) { return 1; }
			return 0;
		}
		);
	}

	this.invertArray = function() {
		var newArr = new Array();
		//On recopie en inversant
		for(var i=0; i< this.length; i++)
		{
			newArr[i] = this[this.length-1-i];
		}
		//On ecrase le tableau de base
		for(var i=0; i<newArr.length; i++)
		{
			this[i] = newArr[i];
		}
	}

	this.push = function() { return Array.prototype.push.apply(this,arguments); }
	this.sort = function() { return Array.prototype.sort.apply(this,arguments); }


}//Fin de classe MyArray

/*******************
LE PROBLEME DU PROTOTYPAGE DE TABLEAU EST QU'IL RAJOUTE AUTANT D'ELEMENTS QUE DE FONCTIONS
A TOUS LES TABLEAUX, FAUSSANT AINSI TOUTES LES LECTURES DE TABLEAUX !!!
//Vérifier si un tableau à une dimension contient l'élément "elmt" passé en paramètre
Array.prototype.hasElement = function(elmt) {
	for(var i=0; i < this.length; i++)
	{
		var el = this[i];
		if(el == elmt)
			return true;
	}
	return false;
}

//Pour trier un tableau à plusieurs dimensions en précision sur quelle dimension on veut trier
Array.prototype.sortArray = function(sortCol) {
	this.sort(
		function by_name(a, b) {
			if (a[sortCol] < b[sortCol] ) { return -1; }
			if (a[sortCol] > b[sortCol] ) { return 1; }
			return 0;
		}
	);
}

//Pour inverser un tableau : le premier élément devient le dernier
//et vice-versa
Array.prototype.invertArray = function() {
	var newArr = new Array();
	//On recopie en inversant
	for(var i=0; i<this.length; i++)
	{
		newArr[i] = this[this.length-1-i];
	}
	//On ecrase le tableau de base
	for(var i=0; i<newArr.length; i++)
	{
		this[i] = newArr[i];
	}
}
****************************/

/************************************************************************/
/****************************  | IMAGE |  *******************************/
/************************************************************************/
//Classe pour prototyper l'objet Image
MyImage = function() {
	//**** VARIABLES PRIVÉES
	var myImg = new Image();
	//**** VARIABLES PUBLIQUES

	//**** FONCTIONS PRIVÉES

	//**** FONCTIONS PUBLIQUES
	this.preload = function(imgSrc) { myImg.src = imgSrc; }

} //Fin de classe MyImage


/************************************************************************/
/****************************  |ELEMENT|  *******************************/
/************************************************************************/
//Classe pour prototyper l'objet Element
MyElement = function(idElt) {
	//**** VARIABLES PRIVÉES
	var myElt = $(idElt);
	//**** VARIABLES PUBLIQUES

	//**** FONCTIONS PRIVÉES

	//**** FONCTIONS PUBLIQUES
	//Change la classe d'un element
	this.modifyClass = function(cssClass) {
		myElt.className = cssClass;
	}

	//Obtient le status "On/Off" d'un element, si celui possède une classe de type "xxx_0n/xxx_Off".
	//Sinon, retourne FALSE.
	this.getIsOn = function() {
		var status = false;
		if(myElt.className.hasChar("_") && myElt.className.split("_")[1] == "On")
			status = true;
		return status;
	}

	//Obtient la racine de la classe d'un element "switchable", si celui possède une
	//classe de type "xxx_0n/xxx_Off". Sinon, retourne une chaine vide.
	this.getRoot = function() {
		var root = "";
		if(myElt.className.hasChar("_"))
			root = myElt.className.split("_")[0];
		return root;
	}

	//"Allume" l'élément
	this.switchOn = function(noUCImage) {
		this.modifyClass(this.getRoot() + "_On");
		if(myElt.src && noUCImage != 1)
			myElt.src = myElt.src.replace("_uc.gif", ".gif");
	}


	//"Eteint" l'element
	this.switchOff = function(noUCImage) {
		this.modifyClass(this.getRoot() + "_Off");
		//si c'est une image, on la remplace par l'image "désactivée"
		//sauf si cela n'est pas demandée
		if(myElt.src && noUCImage != 1)
			myElt.src = myElt.src.replace(".gif", "_uc.gif");
	}


	//Change la classe d'un élément de "On" à "Off" et vice-versa.Uniquement si celui
	//possède une classe de type "xxx_0n/xxx_Off".
	this.switchOnOff = function(noUCImage) {
		if(this.getIsOn())
			this.switchOff(noUCImage);
		else
			this.switchOn(noUCImage);
	}


	//Certains élements du filtre se comportent comme des radios boutons :
	//on ne peut avoir qu'un seul de ces elements actifs pour un groupe donné.
	//Par exemple, le mode spécial de sélection de couleur : colorless, hybrid, gold.
	//group => tableau contenant les ID des élements du groupe
	//noUCImage => mettre à 1 si il n'y a pas de version d'image "décochée"
	//alwaysOne => mettre à 1 si le groupe d'élements à toujours au moins un element actif
	this.switchRBOnOff = function(group, noUCImage, alwaysOne) {
		var i = 0;
		if(group)
		{
			//On active l'élément cliqué

			if(alwaysOne)
				this.switchOn(noUCImage);
			else
				this.switchOnOff(noUCImage);
			//Et on désactive tous les autres elements de son groupe
			for(i=0; i < group.length; i++)
			{
				var idElt = group[i];
				if(idElt != myElt.id)
				{
					var eltTmp = new MyElement(idElt);
					//Si l'élément est actif, on le désactive
					if(eltTmp.getIsOn())
						eltTmp.switchOff(noUCImage);
				}
			}
		}
		else
		{
			//On active l'élément cliqué

			if(alwaysOne)
				this.switchOn(noUCImage);
			else
				this.switchOnOff(noUCImage);
		}
	}


} //Fin de classe MyElement


