/**
 * @fileoverview
 * AjaxTabs - Bibliothèque d'implémentation d'onglets en Ajax
 * 
 * @version 1.0 - 07/10/2006
 * @copyright (c)2006 Mickaël Marchal
 * @license Distribué sous licence Creative Commons 2.0 fr by-nc-sa
 * @author Mickaël Marchal <mika@lesitedemika.org>
 */



/**
 * Constructeur
 * 
 * @class Classe Onglet : gestion des événements et des données d'un onglet particulier 
 * @constructor
 * @param {String} name Nom qui sera affiché sur l'onglet
 * @param {String} id Identifiant de l'onglet. Doit être unique
 */
function Tab(name, id) {
	/**
	 * @param {String}
	 */
	this.name = name;
	this.id = id;
	this.element = null;
}

Tab.prototype.draw = Tab_draw;
/**
 * Affiche l'onglet à la fin de la zone d'onglets et active la gestion d'événements
 * 
 * @param {HTMLElement} ulContainer Elément de type ul contenant tous les onglets
 * @param {Tab} parent Référence vers l'objet de type Tab contenant cet onglet
 */
function Tab_draw(ulContainer, parent) {
	var new_tab = document.createElement("li");
	new_tab.id = this.id;
	if(parent.tabs[parent.activeTab] == this) {
		new_tab.className = "active";		
	}
	else {
		new_tab.className = "inactive";		
	}
	new_tab.appendChild(document.createTextNode(this.name));	
	ulContainer.appendChild(new_tab);
	new_tab.onclick = function() { parent.change(this); } ;
	this.element = new_tab;
}


/**
 * Evénement activé lorsqu'on onglet est désactivé
 */
Tab.prototype.onLostFocus = function () { };


/**
 * 
 * Evénement activé lorsque l'onglet est fermé
 */
Tab.prototype.onClose = function () { };
/**
 * Evénement activé avant la fermeture de l'onglet
 * @return true pour autoriser la fermeture d'un onglet, false pour l'empêcher
 */
Tab.prototype.onBeforeClose = function () { return true; };
/**
 * Teste si le contenu de l'onglet est déja chargé
 * @return true si l'onglet est déja chargé, false si il nécessite de charger les données
 */
Tab.prototype.isPreloaded = function () { return true; };
/**
 * Charge les données de l'onglet
 */
Tab.prototype.loadContent = function () { };
/**
 * Affiche les données de l'onglet
 */
Tab.prototype.displayContent = function () { };



/**
 * Constructeur
 * @class Classe Liste d'onglets : gestion de la liste d'onglets (ajout, supression, changement d'onglet...) 
 * @constructor
 */
function Tablist() {
	this.tabs = new Array();
	this.activeTab = -1;
	this.tabContainer = null;
	this.subTabContainer = null;
	this.panelContainer = null;
	this.ulContainer = null;
}

/**
 * Attache la liste d'onglets aux éléments HTML dans laquelle elle s'affichera
 * Cette méthode doit être appelée avant la méthode draw()
 * @param {HTMLElement} my_tabContainer Elément div contenant la liste des onglets
 * @param {HTMLElement} my_subTabContainer Elément div contenant la barre sous la liste d'onglets
 * @param {HTMLElement} my_panelContainer Elément div contenant le cntenu de l'onglet affiché
 */
function Tablist_attach(my_tabContainer, my_subTabContainer, my_panelContainer) {
	this.tabContainer = document.getElementById("tabzone");
	this.subTabContainer = document.getElementById(my_subTabContainer);
	this.panelContainer = document.getElementById(my_panelContainer);
}

/**
 * Ajoute un onglet dans la liste, en dernière position
 * Une fois les onglets ajoutés, utiliser la méthode draw() pour les afficher
 * @param {Tab} new_tab onglet à ajouter
 */
function Tablist_append(new_tab) {
	if(new_tab instanceof Tab) {
		this.tabs[this.tabs.length] = new_tab;		
	}
}

/**
 * Ajoute un onglet dans la liste, avant un onglet spécifié
 * Une fois les onglets ajoutés, utiliser la méthode draw() pour les afficher
 * @param {Tab} new_tab onglet à ajouter
 * @param {String} id identifiant de l'onglet suivant le nouvel onglet
 */
function Tablist_insertBefore(new_tab, id) {
	var found = false;
	for(var i = this.tabs.length-1; i >= 0; i--) {
		if(found == false) {
			this.tabs[i+1] = this.tabs[i]; 
		}
		if(this.tabs[i].id == id && found == false) {
			this.tabs[i] = new_tab;
			if(this.activeTab >= i)
				this.activeTab++;
			found = true;
		}
		if(i == 0 && found == false) {
			this.tabs[0] = new_tab;
		}
	}
}

/**
 * Ferme l'onglet spécifié
 * Gère automatiquement la sélection d'un nouvel onglet si on ferme l'onglet sélectionné
 * @param {Tab} tab Onglet à fermer
 */
function Tablist_close(tab) {
	
	if(tab) {
		if(tab.onBeforeClose()) {
			//seulement si le tab est déja dessiné
			if(tab.element) {
				//retire l'élément de la tablist
				this.ulContainer.removeChild(tab.element);
			}
				
			//retire le tab de la tablist
			var found = false;
			for(var i = 0; i < this.tabs.length; i++) {
				//si on est sur le lien à supprimer
				if(found == false && this.tabs[i] == tab)
				{
					found = true;
				
					//gestion du tab actif
					
					//si on ne ferme pas le tab actif
					if(this.activeTab > i)
						this.activeTab--;
			
					//si on ferme le tab actif..			
					else if(this.activeTab == i) {
						
						//...et que c'était le dernier tab restant : on désactive la tablist
						if (this.tabs.length == 1) {
							tab.onLostFocus();
							this.activeTab = -1;
						}						
						
						//...et que c'était le dernier : on active le tab précédent
						else if(i == this.tabs.length - 1) {
							this.change(this.tabs[i-1].element);
						}
						
						//...et que ce n'était pas le dernier : on active le tab suivant
						else {
							//le tab a fermer perd le focus
							tab.onLostFocus();
							//on load et/ou affiche le tab suivant
							if(! this.tabs[this.activeTab+1].isPreloaded()) {
								this.tabs[this.activeTab+1].loadContent();
							}
							else {
								this.tabs[this.activeTab+1].displayContent();
							}					
						}						
					}
					//ici tous les problèmes de tab actif sont réglés
					
					//déclenchement de l'événement close
					tab.onClose();
				}
				//si le tab a déja été trouvé, on décale le reste des tabs de la liste
				if(found == true) {
					this.tabs[i] = this.tabs[i+1];
				}
			}
			//a la fin, si on a trouvé le tab, on efface le dernier de la liste (qui se trouve en double)
			if(found == true) {
				delete this.tabs[i];
				this.tabs.length --;
			}
		}
	}
}

/**
 * Affiche la liste des onglets
 * Recrée la liste des onglets dans le tabContainer. A utiliser après chaque modification de la liste d'onglets.
 */
function Tablist_draw() {
	deleteChildren(this.tabContainer);
	this.ulContainer = document.createElement("ul");
	this.tabContainer.appendChild(this.ulContainer);

	for(var i = 0; i < this.tabs.length; i++) {
		this.tabs[i].draw(this.ulContainer, this);
	}
}

/**
 * Change l'onglet acrif dans la liste d'onglets
 * Gère automtaiquement le chargement et l'affichage des données nécessaires
 * @param {HTMLElement} targetElement Elément LI représentant l'onglet devant être activé
 */
function Tablist_change(targetElement) {
	var targetTab = this.getTabByElement(targetElement);
	if(targetTab != this.tabs[this.activeTab]) {
		//si il y a un élément précédent, on le désactive
		if(this.activeTab != -1) {
			var lastTab = this.tabs[this.activeTab];
			lastTab.onLostFocus();
			lastTab.element.className = "inactive";
		}
		//active l'élément cliqué

		targetElement.className = "active";
		for(var i = 0; i < this.tabs.length; i++) {
			if (targetTab == this.tabs[i]) {
				this.activeTab = i;
				if(! targetTab.isPreloaded()) {
					targetTab.loadContent();
				}
				else {
					targetTab.displayContent();
				}			
			}
		}
		
	}
}

/**
 * Renvoie l'onglet ayant pour HTMLElement l'élément spécifié
 * @param {HTMLElement} element
 * @return Onglet correspondant
 * @type Tab
 */
function Tablist_getTabByElement(element) {
	for (var i = 0; i < this.tabs.length; i++) {
		if(this.tabs[i].element == element) {
			return this.tabs[i];
		}
	}
	return false;	
}

/**
 * Renvoie l'onglet ayant pour identifiant l'identifiant spécifié
 * @param {String} id
 * @return Onglet correspondant
 * @type Tab
 */
function Tablist_getTabById(id) {
	for (var i = 0; i < this.tabs.length; i++) {
		if(this.tabs[i].id == id) {
			return this.tabs[i];
		}
	}
	return false;	
}

Tablist.prototype.attach = Tablist_attach;
Tablist.prototype.append = Tablist_append;
Tablist.prototype.insertBefore = Tablist_insertBefore;
Tablist.prototype.close = Tablist_close;
Tablist.prototype.draw = Tablist_draw;
Tablist.prototype.change = Tablist_change;
Tablist.prototype.getTabByElement = Tablist_getTabByElement;
Tablist.prototype.getTabById = Tablist_getTabById;


