﻿/*******************************************
	j_arbo.js
	
	Arborescence dynamique
	
	Utilisation standard :

		<ul class="j_racine">
			<li class="j_moins"><span class="j_cliquer">Cliquer pour replier</span>
				<ul class="j_branche">
					<li class="j_plus"><span class="j_cliquer">Cliquer pour déplier</span>
						<ul class="j_branche">
							...
						</ul>
					</li>
				</ul>
			</li>
			...
		</ul>
*******************************************/


function j_arbo(options) {
	
	// Configuration :
	var param = $.extend({

		// Sélecteurs et classes utilisées par l'application :
		selConteneur : ".j_racine",
		selCliquable : ".j_cliquer",
		classPlus : "j_plus",
		classMoins : "j_moins",
		
		// Divers :
		ancreArbo : "#arbo",
		idDefaut1 : "j_idauto",
		idDefaut2 : "ul",
		
		// Classes générées et utilisées par la feuille de style :
		classDynamique : "dynamique",
		classHover : "actif",
		
		// Boutons :
		classBoutons : "j_avec_boutons",
		bnDeplier : {cl:"j_deplier",libDefaut:"Tout déplier",clLib :"j_lib_deplier"},
		bnReplier : {cl:"j_replier",libDefaut:"Tout replier",clLib :"j_lib_replier"},
		bnConteneur : "<p class='j_boutons_arbo'></p>",

		// Option de style nécessitant de trouver le dernier fils de chaque liste :
		classSpecial : "j_pointille",
		classLast : "last",
		
		// Pour ne "mémoriser" que la dernière branche dépliée, mettre à true :
		queDerniereBranche : false,
		
		// Prise en charge d'ie 6 :		
		classIe6 : "j_ie6"
		
	},options);

	// Ajout de la classe dynamique en début de script pour ne pas laisser l'arborescence dépliée :
	var $lesArborescences = $(param.selConteneur).addClass(param.classDynamique) ;
	
	// Initialisation :
	if ($lesArborescences.length>0) {

		// Attribution d'un id par défaut aux uls qui n'en ont pas :
		$lesArborescences.each( function(rangArbo) {
			$(this).find("li."+param.classPlus+">ul:not([id]),li."+param.classMoins+">ul:not([id])").each(function(rangUl){
				$(this).attr("id",param.idDefaut1+rangArbo+param.idDefaut2+rangUl)
			}) ;		
		
		}) ;

		// On retrouve les branches dépliées d'après les ancres dans l'url :
		var aAncres =  new Array();
		var montrer =  $.j_urlGetVar("montrerbranches",{ancre : param.ancreArbo}) ;
		if (montrer) {
			var separateur=new RegExp("/+", "g");
			aAncres=montrer.split(separateur);
			for (var i=0; i<aAncres.length; i++) {
				$("ul#"+aAncres[i]).parent("li."+param.classPlus).removeClass(param.classPlus).addClass(param.classMoins);
			}
		}
	
		// Avant de quitter la page, on mémorise les branches dépliées dans l'url :
		$.j_quittePage(function(){
			if(aAncres.length>0) {
				if(param.queDerniereBranche) {
					aAncres =  $("ul#"+aAncres[aAncres.length-1]).parents(param.selConteneur + " ul").andSelf().map(function(){
						  return $(this).attr("id");
						}).get() ;
				} 
				else {
					aAncres = $lesArborescences.find("li."+param.classMoins+">ul").map(function(){
						  if( $.trim($(this).attr("id")) !="") return $(this).attr("id");
					}).get() ;	
				}
				$.j_urlPushVar("montrerbranches",aAncres.join("/"),{ancre : param.ancreArbo}) ;
			}
			return true  ;
		}) ;
	
	}

	// Fonction principale :
	$lesArborescences.each(function() {
	
		var $this = $(this) ;
		
		// Action plier/déplier et mémorisation des branches dépliées :
		$this.find(param.selCliquable)
			.click(function(){
				var $parentLi = $(this).parent("li") ;
				var ulAncre = $(this).next("ul").attr("id") ;
				ajoutRetrait(aAncres,ulAncre);
				$parentLi.toggleClass(param.classPlus).toggleClass(param.classMoins);
			})
			.hover(	 function(){$(this).parent().addClass(param.classHover) ;},function(){$(this).parent().removeClass(param.classHover) ;});
			
		// Bouton pour tout plier ou tout replier :
		if ($this.hasClass(param.classBoutons)) {
			var $deplier = $("<button></button>").click(function(){$(this).closest("div").find("li."+param.classPlus).attr("class",param.classMoins);});
			var $replier = $("<button></button>").click(function(){$(this).closest("div").find("li."+param.classMoins).attr("class",param.classPlus);});
			$deplier.addClass(param.bnDeplier.cl).html(($("*").index($("input."+param.bnDeplier.clLib))==-1)? param.bnDeplier.libDefaut : $("input."+param.bnDeplier.clLib).eq(0).val());
			$replier.addClass(param.bnReplier.cl).html(($("*").index($("input."+param.bnReplier.clLib))==-1)? param.bnReplier.libDefaut : $("input."+param.bnReplier.clLib).eq(0).val());
			var $boutons = $(param.bnConteneur);
			$boutons.prepend($deplier).prepend($replier) ;
			$this.wrap("<div></div>").before($boutons);
		};
		
		// Classe spéciales pour les derniers éléments des listes :
		if ($this.hasClass(param.classSpecial)){$this.find("li:last-child").addClass(param.classLast)}
		
		// leBrowserEstIE6 :
		if ((window.XMLHttpRequest == undefined) && (ActiveXObject != undefined)) {$this.addClass(param.classIe6)}
		
		/**
		* Fonctions utiles :
		**/
		// Fonction qui ajoute une valeur dans un vecteur si elle ne s'y trouve pas
		// et retire cette valeur si elle s'y trouve :
		ajoutRetrait = function (array,val) {
			if (val==""){
				return false ;
			} 
			for(var i = 0, l = array.length; i < l; i++) {
				if(array[i] == val) {
					array.splice(i,1) ;
					return true ;
				}
			}
			array.push(val)  ;
			return true ;
		}
				
	});
	
}





