//Copyright (C) 2003-2012 AJLSM, Anaphore
//Voir le fichier LICENCE
//$Id: MifTreeCustom.js 21416 2012-01-24 14:34:55Z mdia $

/**
 * @fileOverview Surcharges relatives a Mif. Cela comprend une surcharge de l'elment Mif.Tree.Node et la définition d'une classe MifTreeCustom qui etend la classe Mif.Tree existante 
 * @author Julien Huet
 * @author Johan Cwiklinski
 */

var DEBUG_MODE = false;

/**
 * @class Gestion de noeud HTML utilisé lors de la création de l'arbre MifTreeCustom
 * @author Julien Huet
 * @author Johan Cwiklinski
 */
Mif.Tree.Node = Class.refactor(Mif.Tree.Node,/** @lends Mif.Tree.Node.prototype */{

	/**
	* <strong>Constructor</strong><br/> Surcharge de Mif.Tree.Node pour qu'on ajoute automatiquement l'id du noeud dans l'index de l'arbre
	* La surcharge propose une methode permettant de retourner un tableau contenant tous les identifiants des noeuds parents
	* @param {Object} structure
	* @param {Object} options
	*/
	initialize: function(structure, options){
		this.previous(structure, options);
		if ( this.data ) {
			this.tree.treeNodesHash[this.data.id] = this;
		}
		var id=this.id;
		if(id!=null) Mif.ids[id]=this;
		this.tree.fireEvent('nodeCreate', [this]);
		this._property=['id', 'name', 'cls', 'openIcon', 'closeIcon', 'openIconUrl', 'closeIconUrl', 'hidden'];
	},

	/**
	* Fonction permettant de retourner un tableau contenant tous les identifiants des noeuds parents depuis un noeud
	* @return {Array} tab_out Tableau contenant les identifiants des noeuds parend. L'indice 0 correspond au noeud au premier parent du noeud
	*/
	getAncestor: function(){
		var tab_out = new Array();
		var n = this.getParent();
		var id = '';
		while ((n)) {
			if ( (n.data) ) {
				tab_out[tab_out.length] = n.data.id;
			}
			n = n.getParent();
		}
		return tab_out;
	},

	/**
	* Fonction permettant de savoir si lun fils possède un element à charger (s'il possède une balise ul vide)
	* Si oui cela signifie qu'il possède des fils et donc qu'on peut effectuer un appel Ajax pour récuperer ces fils
	* @returns {Boolean} Retourne true ou false si le noeud contient des enfants A charger
	*/
	hasChildrenToLoad: function(){
		var el = this.data.el;
		var tmp = $type(el);
		if ( $type(el) == 'element' ) {
			if ( el && el.getChildren().length == 0 ) {
				return true;
			} else {
				return false;
			}
		} else {
			return false;
		}
	},

	/**
	* Permet de savoir si le noeud courant possède déja des fils
	* @returns {Boolean} Retourne true ou false si les enfants du noeud sont chargé ou non
	*/
	hasChildrenLoaded: function(){
		if ( this.data && ($type(this.data.el) == 'element') ) {
			return this.data.el.get('html').length > 0;
		} else {
			return false;
		}
	},

	/**
	* Permet de recuperer l'element el des données du noeud 
	* @returns {Element} Retour le data element contenu dans le noeud
	*/
	getDataElement: function(){
		return this.data.el;
	},

	/**
	* Permet de fixer l'element el des données du noeud
	* @param {Object} elt
	*/
	setDataElement: function(elt){
		this.data.el = elt;
	},

	/**Permet de recuperer le lien du noeud */
	getDataHref: function(){
		return this.data.href;
	},

	/** Fonction permettant d'afficher l'icone de chargement du noeud */
	setLoadIcon: function(){
		if ( this.isRendered() ) {
			var g = this.getDOM('gadjet');
			g.removeClass('mif-tree-gadjet-plus');
			g.addClass('mif-tree-loader-open-icon');	
		}
	},

	/** Fonction permettant d'enlever l'icone de chargement du noeud */
	removeLoadIcon: function(){
		if ( this.isRendered() ) {
			var g = this.getDOM('gadjet');
			g.removeClass('mif-tree-loader-open-icon');
		}
	},

	/** Savoir si le noeud courant est affiché a l'ecran*/
	isRendered: function(){
		if ( $(this.tree.DOMidPrefix+this.UID) ) {
			return true;
		} else {
			return false;
		}
	}
});

/**
 * @class Surchage Mif.Tree pour prendre en compte les listes HTML et ajout de fonction de recherche
 * Ajout également de fonction permettant un noeud dans un arbre à partir de son ID
 * @augments Mif.Tree
 * @author Julien Huet
 * @author Johan Cwiklinski
 */
var MifTreeCustom = new Class(/** @lends MifTreeCustom.prototype */{
	Extends: Mif.Tree,
	
	/**
	* Initialisation de l'arbre
	* @param {Object} options
	* @param {String} urlStart Debut de l'url appelé pour construire les noeuds fils  en ajax
	* @param {String} urlEnd  Fin de l'url appelé pour construire les noeuds fils  en ajax
	* @param {Object} treeManager Objet permettant d'utiliser un manager externe pour interagir avec les noeuds
	* @param {Element} containerToScroll Container parent ou grand parent à l'arbre. C'est sur ce container que s'effecturra le scroll si l'arbre depasse la taille de la fenêtre.
	*/
	initialize: function(options, urlStart, urlEnd, treeManager, containerToScroll){
		this.parent(options);
		this.urlStart = urlStart;
		this.urlEnd = urlEnd;
		this.containerToScroll = containerToScroll;
		this.treeManager = treeManager;
		//declaration du tableau d'indexation pour faciliter la recherche des noeuds
		this.treeNodesHash = {};
		this.container.setStyle('overflow','hidden');
		this.container.setStyle('overflow-x','hidden');
		this.container.getElement('div').setStyle('overflow','hidden');
		this.container.getElement('div').setStyle('overflow-x','hidden');
		this.container.getElement('div').setStyle('height','auto');

		this.nodeSpecialStyle = {};
		if(DEBUG_MODE){
			this.enableLog().log('[MifTreeCustom] Arbre initialisé');
		}
	},

	/**
	* Implémentation de la fonction $chk qui est dépréciée dans mootools 1.3
	* @param obj :  obj à vérifier
	*/
	chk_impl: function(obj){
		return !!(obj || obj === 0);
	},

	/**
	* function permettant de récupérere le noeud à la position spécifier
	* @param pos : la position. On comence à la position 1
	*/
	getChildAt: function(pos){
		if((this.forest) && (this.root) && (this.root.getChildren().length > pos) && (pos > 0)) {
			if(pos == 1) return this.root.getFirst();
			else if(pos == 2) return this.root.getFirst().getNext();
			else {
				return this.getChildAt(pos-1).getNext();
			}
		}
		else return null;
	},

	/**
	* On surchage la methode toggleClick de Mif.Tree car, dans la version orignal de la fonction,
	* la detection de noeud lors d'evenement n'est pas correcte. Elle prennait en compte tous les noeuds, peut imprort son arbre
	* Pour corriger cela il suffit simplement de verifier si le noeud qu'on selectionne appartient bien à l'arbre courant
	* Sinon on fait rien
	* @param {Event} event
	*/
	toggleClick: function(event){
		if( this.mouse.target != 'gadjet' ) {
			return;
		}
		if ( this.mouse.node.tree == this ) { //condition ajoutée pour verifier qu'on va bien agir dans le bon arbre
			this.mouse.node.toggle();
			if ( !this.mouse.node.hasChildrenLoaded() ) {
				if ( this.mouse.node.hasChildrenToLoad() ) {
					this.mouse.node.setLoadIcon();
				}
			}
		}
	},

	/**
	* Fonction permettant de prendre en compte les balises ul et li
	* @param {Mif.Tree.Node} node
	* @returns {Json}
	*/
	loadOptions: function(node){
		if ((node != undefined) && (node.data!=undefined)) {
			var json = [];			
			json = this.buildJsonStructure(node, true);
			return json;
		}
	},

	/**
	*  Fonction utilisée pour la prise en compte des listes HTML
	* Cette fonction permet de génerer du JSON en fonction du HTML présent dans les balises.
	* Ce JSON est ensuite retourné et utilisé pour génerer l'arbre
	* @param {Mif.Tree.Node} node
	* @param {Boolean} animateLoading
	* @private
	* @returns {Json} retourne le json utilisé pour la création du noeud
	*/
	buildJsonStructure: function(node, animateLoading){
		if ((node != undefined) && (node.data!=undefined)) {
			var json = [];
			node.setLoadIcon();

			if(DEBUG_MODE){
				this.enableLog().log('[MifTreeCustom] Construction du noeud `' + node.data.id + '`');
			}

			// recuperation de l'element UL
			var el = node.getDataElement();
			if ( $type(el)!='element' ) {
				return json;
			}

			// si l'element UL est vide c'est qu'il faut le charger en ajax
			if ( el.getChildren().length == 0 ) {
				return this.getNewChildByAjax(node, animateLoading);
			}

			//parcours de tous les fils de l'element UL
			el.getChildren().each(function(chd, index){
				var child = new HtmlNode(chd);
				var loadable = false;
				var name = '';
				var elt = child;
				var href = '#';
				var hasAnOtherList = child.hasHtmlChild(); // le cas où on a une balise li simple (cad sans
				// si la balise contint des ul cela signifie qu'elle contient d'autre liste
				if ( hasAnOtherList ) {
					elt = child.getHtmlChild();
					child.eraseHtmlChild();
					loadable = true;
				}

				href = child.getNodeLinkUrl();
				var _type = child.getNodeType();

				name = node.tree.setHtmlNode(child);
				if(node.hasCheckbox){
					name = '<span class="myCheckBox"></span>'+name;
				}

				var childId = child.getId();
				json.push({
					property: {
						name: name,
						loadable: loadable,
						uid: childId,
						level: node.level+1
					},
					type: _type,
					data: {
						el: elt,
						id: childId,
						href: href
					}
				});
			}.bind(this));

			node.removeLoadIcon();
			if ( DEBUG_MODE ) {
				this.enableLog().log('[MifTreeCustom] Noeud `' + node.data.id + '` construit');
			}
			return {
				json: json
			};
		}
	},

	/**
	* Fonction permettant de retourner le code HTML qui sera affiché pour les noeud du treeView
	* @private
	*/
	setHtmlNode: function(child){
		return child.getHtml();
	},

	/**
	* @private
	* @param (Mif.tree.node) node Noeud dont on souhaite récupérer le fils 
	* @returns {Json} Retourne le json utilisé lors de la création du noeud
	*/
	getNewChildByAjax: function(node, animateLoading){
		var url = this.getChildrenUrl(node);
		var json = [];
		if ( DEBUG_MODE ) {
			this.enableLog().log('[MifTreeCustom] Appel ajax pour le noeud `'+node.data.id +'`');
		}
		if(url){
			var req = new Request.HTML({
				url: url,
				method: 'get',
				onSuccess: function(responseTree, responseElements, responseHTML, responseJavaScript){ 
					// on filtre le tableau pour qu'il ne prenne que les elements de type Element
					if(DEBUG_MODE){
						node.tree.enableLog().log('[MifTreeCustom] Reception de l\'appel ajax pour le noeud noeud `' + node.data.id + '`');
					}
					var allElement = $A(responseTree).filter(function(item, index){
						if($type(item)=='element'){
							return $type(item)=='element';
						}
					});
					node.setDataElement(allElement[0].getFirst());
					node.getDataElement().set('id','');
					node.load();
					node.fireEvent('nodeLoad',[this]);
					node.removeLoadIcon();
				},
				onFailure: function(xhr){
					alert('Erreur lors du chargement des fils '+xhr); //TODO: i18n
				},
				onException: function(headerName, value){
					alert('Erreur lors du chargement des fils '+headerName); //TODO: i18n
				}
				
			});
			req.send();
		}
		return {
			json: json
		};
	},

	/**
	* Pour recuperer facilement la taille de l'arbre 
	* @private
	*/
	getTreeOffsetHeight: function(){
		return this.container.getElement('div').getSize().y;
	},

	/** Fonction importante car elle qui définit l'URL utilisee lors de l'appel ajax pour récuperer les fils d'un noeud
	* @param {Mif.Tree.Node} node Noeud parent dont on souhaite avoir les enfants
	* @private
	*/
	getChildrenUrl: function(node){
		if ( node.data.id ) {
			return this.urlStart+node.data.id+this.urlEnd;
		} else {
			return null;
		}
	},

	/**
	* Fonction permetant d'initialiser simplement un arbre depuis une liste HTML.(UL/LI). Cette liste doit être contenu dans un 'element' du DOM, Par exemple un DIV
	* @param (Collection) responseTree Reponse ajax contenant l'arbre HTML
	* @private
	**/
	initTree: function(responseTree){
		var allElement= new Array();
		//debugger;
		// on peut avoir en entrée soit une collection issue d'un appel ajax
		// soit directement un div contenant la liste.
		// Si c'est une collection on la trie car il peut y avoir des eléments non souhaité issue de l'appel ajax.
		// Sinon on prend directement le div	
		if ( $type(responseTree) == 'collection' ) {
			// on filtre le tableau pour qu'il ne prenne que les elements de type Element
			allElement = $A(responseTree).filter(function(item, index){
				if ( $type(item)=='element' ) {
					return $type(item)=='element';
				}
			});
		} else {
			// dans le cas ou a directement le div en entrée
			if ( responseTree.get('tag') == 'div' ) {
				allElement[0] = responseTree;
			}
		}
		//on verifie si l'arbre est valide
		if ( allElement.length == 0 ) {
			alert('structure html invalide'); //TODO: i18n
			return false;
		} else { // on regarde s'il possede au moins un element li
			if ( !allElement[0].getFirst().getElement('li') ) {
				return false;
			}
		}

		// creation d'un nouveau noeud permettant l'initialisation de l'arbre
		var newNode=new Mif.Tree.Node(
			{
				parentNode: null,
				tree: this
			},
			{
				property: {
					name: '<a href="http://ajlsm.com">AJLSM</a>',
					loadable: true,
					level: 0
				},
				data: {
					el: allElement[0].getFirst(),
					id: 'root'
				}
			}
		);
		return this.buildJsonStructure(newNode,false);
	},

	/**Permet de scroller l'arbre pour centrer l'affichage sur le noeud passé en parametre
	* @param (Mif.Tree.Node) node Noeud sur lequel on souhaite faire le focus
	*/
	focusOnNode: function(node){
		if ( this.containerToScroll && node ) {
			try{
				if ( DEBUG_MODE ) {
					this.enableLog().log('[MifTreeCustom] focus sur le noeud ' + node.data.id);
				}
				var elt = node.getDOM('name');
				this.containerToScroll.scrollTo(elt);
				this.onFocusNodeComplete(node);
			}catch(e){}
		}
	},

	/**
	* Fonction appellée après que le focus soit fait sur un noeud
	* @param (Mif.Tree.Node) node Noeud sur lequel on fait le focus
	*/
	onFocusNodeComplete: function(node){},

	/**Fonction permettant de selectionner un noeud à l'aide de son identifiant
	* @param (String) id Identifiant du noeud a selectionner 
	* @param (Array) ancestor Tableau contenant les identifiants des ancetres du noeud
	*/
	selectNodeByID: function(id, ancestor){
		if ( DEBUG_MODE ) {
			this.enableLog().log('selection du noeud ayant pour ID '+id);
		}
		this.applyFunctionOnNode(id,function(selectedNode){
			selectedNode.tree.expandTo(selectedNode);
			if ( DEBUG_MODE ) {
				selectedNode.tree.enableLog().log('   expand TO OK');
			}
			if(selectedNode.isRendered()){
				selectedNode.tree.select(selectedNode);
				if ( DEBUG_MODE ) {
					selectedNode.tree.enableLog().log('   selection node OK');
				}
				selectedNode.tree.focusOnNode(selectedNode);
			}
		},ancestor);
	},

	/**
	* fonction permettant de recuprer le noeud depuis son identifiant.
	* @param {string} id ID du noeud que l'on recherche
	* @param (function) fn function to apply
	* @param {array} ancestor (facultatif)Tableau contenant les id des ancestres du noeud
	*/
	applyFunctionOnNode: function(id,fn,ancestor){
		//on regarde tout d'abord si le noeud existe deja dans le tableau d'indexation
		var nodeOut = this.treeNodesHash[id];
		// si le noeud n'existe pas dans la table c'est peut-etre qu'il n'est pas encore affiché
		// alors il faut rechercher dans l'arbre et charger les noeuds les uns après les autres.
		if ( !nodeOut ) {
			if ( ancestor && (ancestor.length > 0) ) {
				//optimisation : on regarde si un des ancetre est connu par l'index. Si oui on commence directement la recherche depuis ce noeud
				var startingNode = this.root;
				for (var i = 0; i < ancestor.length; i++) {
					//on regarde si un ID d'un des ancetre existe. Si oui alors on prend ce noeud comme noeud de depart
					// ON COUPE le tableau ancestor afin d'y laisser que les ancetres utiles.
					var ancestorNode = this.treeNodesHash[ancestor[i]];
					if ( ancestorNode ) {
						startingNode = ancestorNode;
						if ( DEBUG_MODE ) {
							this.enableLog().log('startingNode.data.id '+startingNode.data.id);
						}
						startingNode.load();
						ancestor = ancestor.slice(0,i);
						break;
					}
				};

				if (startingNode.hasChildren()) {// cas synchrone
					nodeOut = this.applyFunctionOnNodeRecursiveSmart(
						startingNode.children,
						id,
						ancestor,
						fn
					);
				} else if(startingNode.hasChildrenToLoad()){ // cas asynchrone pour le chargement des fils par appel ajax
					//var tree = this;
					startingNode.addEvent('load',function(node){
						nodeOut = startingNode.tree.applyFunctionOnNodeRecursiveSmart(
							startingNode.children,
							id,
							ancestor,
							fn
						);
					});
					startingNode.load();
				}
			} else {
				if(this.forest) {
					$A(this.root.children).each(function(startingNode){
						if ( startingNode.hasChildren() ) {// cas synchrone
							nodeOut = this.applyFunctionOnNodeRecursive(
								startingNode.children,
								id,
								fn
							);
						} else if ( (startingNode.hasChildrenLoaded()) ) {// cas asynchrone pour le chargement des fils par appel ajax
							//var tree = this;
							startingNode.addEvent('load', function(node){
								nodeOut = startingNode.tree.applyFunctionOnNodeRecursive(
									this.children,
									id,
									fn
								);
							});
							startingNode.load();
						}
					});
				}else{
					nodeOut = this.applyFunctionOnNodeRecursive(this.root.children, id, fn);
				}
			}
		} else {
			fn(nodeOut);
		}
        	return nodeOut;
	},
	
	/**
	* Fonction interne permettant de rechercher intelligement un noeud depuis son ID et depuis le tableau d'identifiant de ces ancetres
	* @param {Array} children tableau de noeud enfant
	* @param {Object} idtofind id que l'on cherche
	* @param {Object} ancestor tableau des ancetres
	* @param {function} fn function to apply
	*/
	applyFunctionOnNodeRecursiveSmart: function(children, idtofind, ancestor, fn){
		var lastAncestor = ancestor.getLast();
		for (var i = 0, l = children.length; i < l; i++) {
			var currentChild = children[i];
			// on trouve le noeud que l'on cherche on lui applique la fonction voulu
			if ( idtofind == currentChild.data.id ) {
					fn(currentChild);
					return currentChild;
			} else {
				if (lastAncestor == currentChild.data.id) {
					currentChild.tree.expandTo(currentChild);
					//on essaie de charger le noeud
					// dans le premier cas, lorsque c'est un chargement asynchrone on reagit à l'evenement load du noeud
					if (currentChild.hasChildrenToLoad()) {
						currentChild.addEvent('load',function(node){
							ancestor.erase(lastAncestor);
							child = currentChild.tree.applyFunctionOnNodeRecursiveSmart(
								currentChild.children,
								idtofind,
								ancestor,
								fn
							);
							if ( child != null ) {
								return child;
							}
						});
						currentChild.load();
						break;
						// cas du chargement synchrone on appel directement la fonction (car l'evenement load est deja realisé)
					} else {
						currentChild.load();
						if(currentChild.hasChildren()){
							ancestor.erase(lastAncestor);
							child = currentChild.tree.applyFunctionOnNodeRecursiveSmart(
								currentChild.children,
								idtofind,
								ancestor,
								fn
							);
							if ( child != null )  {
								return child;
							}
							break;
						}
					}
				}
			}
		}
		return null;
	},

	/**
	* Fonction permettant de deplier tous les noeuds d'un arbre 
	*/
	expandAll: function(nbLevelMax){
		if ( this.forest ) {
			if ( this.root ) {
				if ( !this.chk_impl(nbLevelMax)|| nbLevelMax != 0 ) {
					this.root.getChildren().each(function(node){
						node.recursive(function(){
							if ( this.isRendered() ) {
								this.toggle();
							}
						});
						node.addEvent('nodeLoad', this.expandNode.bind(this,[node,nbLevelMax]));
					}.bind(this));
				}
			}
		}
	},

	/**
	* Fonction permettant de deplier tous les fils d'un noeud
	* @param {MifTreeNode} node
	*/
	expandNode: function(node,nbLevelMax){
		if ( (!this.chk_impl(nbLevelMax))|| (nbLevelMax ==-1) ||((node.level+1) < nbLevelMax) ) {
			node.getChildren().each(function(child){
				child.addEvent('nodeLoad', this.expandNode.bind(this,[child,nbLevelMax]));
				child.recursive(function(){
					if ( this.isRendered() ) {
						this.toggle();
					}
				});
			}.bind(this));
		}
	},

	// Returns null if id has not been found, otherwise the node element with the given id
	/**
	* Fonction interne permettant de rechercher  un noeud depuis son ID. Elle est appellée lorsque l'on ne connait pas les ancetres d'un noeud
	* @param {Object} id Identifiant du noeud que l'on souhaite trouver
	* @param {Object} Noeud parent dans lequel on cherche le noeud que l'on désire
	* @param {Object} id Identifiant du noeud que l'on souhaite trouver
	* @param {function} fn function to apply
	*/
	applyFunctionOnNodeRecursive: function(children, idtofind, fn){
		for ( var i = 0, l = children.length; i < l; i++ ) {
			if ( idtofind == children[i].data.id ) {
				fn(children[i]);
				return children[i];
			} else {
				//on essaie de charger le noeud
				if(children[i].hasChildrenLoaded()){
					var tmp = children[i];		
					tmp.addEvent('load', function(node){
						var tmp2 = tmp;
						var tmp3 = this;
						var tmp4 = children[i];	
						child = this.tree.applyFunctionOnNodeRecursive(this.children, idtofind, fn);
						if ( child != null ) {
							return child;
						}
					});
					children[i].load();
				}
			}
		}
		return null;
	},

	/**
	* Surcharge de la methode getTarget de Mif.Tree. 
	* La surcharge permet de selectionner un noeud que lorsque l'on survole ce noeud en question.
	* On ne se base plus sur la hauteur des éléements pour selectionner le noeud
	*/
	getTarget: function(event){
		var target=event.target, node;
		while(!/mif-tree/.test(target.className)){
			target=target.parentNode;
		}
		var test=target.className.match(/mif-tree-(gadjet)|mif-tree-(icon)|mif-tree-(name)|mif-tree-(checkbox)|mif-tree-(node)/);
		if ( !test ) {
			node = false;
			return {
				node: node,
				target: 'node'
			};
		}
		for ( var i = 6 ;i > 0 ; i-- ) {
			if ( test[i] ) {
				var type=test[i];
				break;
			}
		}
		return {
			node: Mif.Tree.Nodes[target.getAttribute('uid')],
			target: type
		};
	},

	/**
	* Surcharge de la methode select pour qu'on declenche tout de même l'evenement select si on clique sur un noeud déjà selectionné
	*/
	select: function(node, preventFocus) {
		if ( !preventFocus && (Browser.Engine.gecko||Browser.Engine.webkit) ) {
			this.wrapper.focus();
		}
		var current=this.selected;
		if ( current == node ) {
			node.select(true);
			this.fireEvent('select', [node]);
			return this;
		}
		return this.parent(node, preventFocus);
	}
});

/**
* Redefinition de la proprieté Hover de MifTree.
* Ajout d'un contrôle sur le noeud pour savoir s'il est déjà chargé dans le DOM. Dans le cas où il n'est pas chargé on ne fait rien sinon on applique la fonction par défaut
* Attention en cas de mise il faut impérativement vérifier les modifications apportées à ce bou de code.
*/
Mif.Tree.Hover={
	over: function(node, target){
		if ( node.isRendered() ) { // Ajout pleade
			/** Code original */
			var wrapper=node.getDOM('wrapper');
			wrapper.addClass((node.hoverClass||'mif-tree-hover')+'-'+target);
			if(node.state.selected) wrapper.addClass((node.hoverClass||'mif-tree-hover')+'-selected-'+target);
			/** Fin Code original */
		}
	},

	out: function(node, target){
		if ( node.isRendered() ) { // Ajout pleade
			/** Code original */
			var wrapper=node.getDOM('wrapper');
			wrapper.removeClass((node.hoverClass||'mif-tree-hover')+'-'+target).removeClass((node.hoverClass||'mif-tree-hover')+'-selected-'+target);
			/** Fin Code original */
		}
	}
};

