/**
 * imports nécessaires
 * 
 *	<script language="JavaScript" src="xbDom.js"></script>
 *
 */
// on crée une image tampon (attention : un seul diapo par page)
// (permet de contourner un bug safari)
var tempImg = new Image();
tempImg.onload = tempoImgLoaded;
tempImg.myLoaded = false;

/**
 * Objet l'affichage et le déroulement d'un diaporama
 * @param a_name      identifiant du diaporama (unique sur la page)
 * @param a_images    tableau des images à afficher
 * @param a_format    paramétrage de l'affichage (si null, pas de construction par défaut)
 * @param a_init	  true si affichage de la première diapo
 */
function DiapoComponent(a_name, a_images, a_format, a_init) {
	this.name = a_name;
	this.images = a_images;
	
	this.init = ((a_init == null) || (a_init == 'undefined')) ? true : a_init;

	this.isDefil = false;
	this.index = -1;
	
	this.initFormat = function(a_format) {
		if (a_format) {
			this.format = a_format;
		} else {
			// construction d'un format par défaut
			this.format = new Object();
			this.format.table = new Object();
			this.format.image = new Object();
			this.format.desc = new Object();
		}
	}

	// on lance la construction directement dans le constructeur, si un format est défini
	this.initFormat(a_format);
	// on définit les options de fading
	this.withFade = this.format.fade;

	// on relit l'image temporaire à ce diaporama (attention : un seul diapo par page)
	tempImg.diapo = this;

	if (a_format) {
		this.build();
	}
}
	
/**
 * Met à jour le diaporama, en changeant les images à afficher
 * @param a_images    tableau des images à afficher
 * @param a_rep		  répertoire contenant les images
 */
DiapoComponent.prototype.update = function(a_images, a_rep) {
	this.images = a_images;
	this.format._imgs = a_rep;
	
	this.stop();
	
	// on initialise les images
	// on regarde s'il faut démarrer le diaporama automatiquement
	this.isDefil = this.getParam(this.format, "startOnLoad", false);
	if (this.isDefil) {
		// on essaie de garder le bouton start enfonce
		this.pushCommand("start", "true");
	}
	this.displayImage(0);
}
	
/**
 * Renvoie le paramètre a_paramName de l'objet a_obj.
 * S'il n'est pas défini, renvoie a_default.
 * @param a_obj		    objet contenant les paramètres
 * @param a_paramName   nom du paramètre demandé
 * @param a_default		valeur par défaut
 */
DiapoComponent.prototype.getParam = function(a_obj, a_paramName, a_default) {
	if (a_obj && a_obj[a_paramName]) {
		return a_obj[a_paramName];
	} else {
		return a_default;
	}
}
	
/**
 * Renvoie l'éventuelle css.
 * @param a_obj		    objet contenant la css
 * @param a_paramName   nom du paramètre demandé
 */
DiapoComponent.prototype.getCss = function(a_obj, a_paramName) {
	var l_css = this.getParam(a_obj, a_paramName);
	if (l_css) {
		return ' class="' + l_css + '"';
	} else {
		return '';
	}
}

/**
 * Insère à l'endroit d'appel le code complet du composant
 */
DiapoComponent.prototype.build = function() {
	// on définit les identifiants des boutons présents
	var l_boutons = (this.format.commands) 
						? this.format.commands
						: [{"id":"prev"}, {"id":"stop"}, {"id":"start"}, {"id":"next"}];
	var l_s = "";

	// table
	l_s += '<table align="' + this.getParam(this.format.table, 'align', 'center')
			+ '" width="' + this.getParam(this.format.table, 'width', '100%')
			+ '" height="' + this.getParam(this.format.table, 'height', '100%')
			+ '" border="' + this.getParam(this.format.table, 'border', '0')
			+ '" cellspacing="' + this.getParam(this.format.table, 'cellspacing', '5')
			+ '" cellpadding="' + this.getParam(this.format.table, 'cellpadding', '3')
			+ '"';
	l_s	+= this.getCss(this.format.table, 'css');
	l_s += '>';
	
	// image
	l_s += '<tr>';
	l_s += '<td height="100%"'
			+ ' align="'  + this.getParam(this.format.image, 'align', 'center') + '"'
			+ ' valign="' + this.getParam(this.format.image, 'valign', 'middle');
	l_s += '"';
	l_s	+= this.getCss(this.format.image, 'css');
	l_s += '>';
	l_s += '<img id="img_' + this.name + '"';
	if (this.getParam(this.format.image, 'defil', (l_boutons.length > 0)) == true) {
		l_s += ' onclick="' + this.name + '.switchDefil();"';
	}
	if (window.imgLoaded) {
		l_s += ' onload="imgLoaded(' + this.name + ')";'
	}
	l_s += ' src="../_imgs/transp.gif"/>';
	l_s += '</td>';
	l_s += '</tr>';
	
	// boutons (encapsulés dans une table)
	this.commands = [];
	if (l_boutons.length > 0) {
		l_s += '<tr>';
		l_s += '<td';
		l_s	+= this.getCss(this.format.tableCommands, 'cssTD');
		l_s += '>';
		// table
		l_s += '<table align="' + this.getParam(this.format.tableCommands, 'align', 'center') 
				+ '" width="' + this.getParam(this.format.tableCommands, 'width', '100%')
				+ '" border="' + this.getParam(this.format.tableCommands, 'border', '0')
				+ '" cellspacing="' + this.getParam(this.format.tableCommands, 'cellspacing', '5')
				+ '" cellpadding="' + this.getParam(this.format.tableCommands, 'cellpadding', '3')
				+ '"';
		l_s	+= this.getCss(this.format.table, 'css');
		l_s += '>';
		
		l_s += '<tr>';
		var l_command;
		var l_params;
		for (i = 0; i < l_boutons.length; i++) {
			l_command = l_boutons[i].id;
			l_params = l_boutons[i].params;
			// on conserve les paramètres directement accessibles par le nom de la commande
			this.commands[l_command] = l_params;
			
			l_s += '<td';
			if (l_params && l_params.widthTD) {
				l_s += ' width="' + l_params.widthTD + '"';
			}
			if (l_params && l_params.align) {
				l_s += ' align="' + l_params.align + '"';
			}
			if (l_params && l_params.cssTD) {
				l_s += ' class="' + l_params.cssTD + '"';
			}
			l_s += '>';
			// div
			l_s += '<div id="' + l_command + '_' + this.name + '" onclick="';
			if (l_params && l_params.cssOff) {
				l_s += 'this.className = \'' + l_params.cssOff + '\';';
			}
			if (l_params && l_params.command) {
				l_s += l_params.command;
			} else {
				l_s += this.name + '.' + l_command + '();';
			}
			l_s += '"';
			if (l_params && l_params.cssOff) {
				l_s += ' class="' + l_params.cssOff + '"';
				l_s += ' onmouseup="this.className = \'' + l_params.cssOff + '\';"';
			}
			if (l_params && l_params.cssClic) {
				l_s += ' onmousedown="this.className = \'' + l_params.cssClic + '\';"';
			}
			if (l_params && l_params.width) {
				l_s += ' style="width:' + l_params.width + '"';
			}
			l_s += '>';
			l_s += (l_params && l_params.codeOff) ? l_params.codeOff : l_command;
			l_s += '</div>';
			l_s += '</td>';
		}
		l_s += '</tr>';
		l_s += '</table>';

		l_s += '</td>';
		l_s += '</tr>';
	}
	l_s += '</table>';
	
	// on affiche
	document.write(l_s);
	
	// on initialise les images
	this.initImages();
}

/**
 * Ajoute les images définit dans le tableau à la combo.
 */
DiapoComponent.prototype.initImages = function() {
	this.image = xbGetElementById("img_" + this.name);
	this.image.diapo = this;

	// on affiche la premiere
	if (this.init == true) {
		// on regarde s'il faut démarrer le diaporama automatiquement
		this.isDefil = this.getParam(this.format, "startOnLoad", false);
		this.displayImage(0);
	}
}

/**
 * Affiche l'image correspondant à l'index fourni.
 * @param a_index index (0 based)
 */
DiapoComponent.prototype.displayImage = function(a_index) {
	var l_newSrc = ((this.format._imgs) ? this.format._imgs : '.') + '/' 
						+ this.images[a_index];
	// on teste le besoin de fadeOut
	if (this.withFade && tempImg.src && (tempImg.src != l_newSrc)) {
		// fait disparaitre l'image affichée
		this.fadeOut();
	}
	// on conserve l'index courant
	this.index = a_index;

	// lance le chargement de l'image suivante
	tempImg.myLoaded = false;
	tempImg.src = l_newSrc;
}

/**
 * Affiche l'image "suivante"
 */
DiapoComponent.prototype.showImage = function() {
	// affiche l'image correspondant a l'index
	if (this.withFade) {
		if (this.timerId) {
			// on ne fait rien : a priori, fadeOut en cours
			return;
		} else if (tempImg.myLoaded == false) {
			// on ne fait rien : l'image suivante n'est pas encore chargée
			return;
		} else {
			setOpacity(this.image, 0);
			this.image.src = tempImg.src;
			this.fadeIn();
		}
	} else {
		this.image.src = tempImg.src;
	}	

	// appelle la méthode de callback si elle existe
	if (this.imgSelected) {
		this.imgSelected(this.getSelected());
	}
	if (this.isDefil) {
		// on continue
		this.defilId = window.setTimeout(this.name + ".next(true)", this.getParam(this.format, "delay", 2000));
	}
}


/**
 * Affiche l'image venant d'être sélectionnée dans la combo.
 */
DiapoComponent.prototype.imageSelected = function() {
	// affiche l'image selectionnee
	this.displayImage(this.imgDesc.selectedIndex);
}

/**
 * Renvoie l'index de l'image sélectionnée.
 * @return l'index sélectionné
 */
DiapoComponent.prototype.getSelected = function() {
	if (this.imgDesc) {
		this.index = this.imgDesc.selectedIndex;
	}
	return this.index;
}

/**
 * Sélectionne et affiche l'image correspondant à l'index fourni.
 * @param a_newIndex   index de l'image à afficher
 */
DiapoComponent.prototype.setSelected = function(a_newIndex) {
	if (this.imgDesc) {
		this.imgDesc.selectedIndex = a_newIndex;
	}
	// affiche l'image associee
	this.displayImage(a_newIndex);
}

/**
 * Sélectionne et affiche l'image correspondant au nom de de la source fournie.
 * @param a_imgSrc   nom de la source de l'image à afficher
 */
DiapoComponent.prototype.setSelectedSrc = function(a_imgSrc) {
	// on parcours la liste de sources pour trouver l'index correspondant
	for (i = 0; i < this.images.length; i++) {
		if (this.images[i] == a_imgSrc) {
			this.setSelected(i);
			break;
		}
	}
}

/**
 * Affiche l'image suivante, en bouclant.
 */
DiapoComponent.prototype.next = function(a_defil) {
	if (this.isDefil != (a_defil | false)) {
		// défilement en cours -> on ne fait rien
		return;
	}
	// recupere l'index courant
	var l_index = this.getSelected();
	// incremente
	l_index++;
	// verifie que l'index ne sort pas des bornes
	l_index %= this.images.length;
	// selectionne l'index
	this.setSelected(l_index);
}

/**
 * Affiche l'image précédante, en bouclant.
 */
DiapoComponent.prototype.prev = function(a_defil) {
	if (this.isDefil != (a_defil | false)) {
		// défilement en cours -> on ne fait rien
		return;
	}
	// recupere l'index courant
	var l_index = this.getSelected();
	// decremente
	l_index--;
	// verifie que l'index ne sort pas des bornes
	if (l_index < 0) {
		l_index = this.images.length - 1;
	}
	// selectionne l'index
	this.setSelected(l_index);
}

/**
 * Lance le déroulement automatique du diaporama, 
 * à partir de l'image courante.
 */
DiapoComponent.prototype.start = function() {
	if (this.isDefil) {
		// on ne fait rien
	} else {
		// on essaie de garder le bouton start enfonce
		this.pushCommand("start", "true");
		// on passe en mode défil
		this.isDefil = true;
		// on change
		this.next(true);
	}
}

/**
 * Arrête le déroulement.
 */
DiapoComponent.prototype.stop = function() {
	if (this.isDefil) {
		window.clearInterval(this.defilId);
		this.isDefil = false;
		// on "releve" le bouton start
		this.pushCommand("start");
	}
}

/**
 * Lance ou arrête le défilement en fonction de l'état courant.
 */
DiapoComponent.prototype.switchDefil = function() {
	if (this.isDefil) {
		// on arrête
		this.stop();
	} else {
		// on lance
		this.start();
	}
}

/**
 * Enfonce le bouton correspondant à la commande fournie si a_true est définit,
 * le relève sinon.
 * @param  a_command  nom de la commande
 * @param  a_true  si définit, enfonce le bouton
 */
DiapoComponent.prototype.pushCommand = function(a_command, a_true) {
	var l_params = this.commands[a_command];
	if (l_params) {
		// il y a bien une commande correspondante
		// on recupere le div correspondant a la commande
		var l_div = xbGetElementById(a_command + "_" + this.name);
		if (l_div) {
			// on change la css
			if (a_true) {
				if (l_params.cssOn) {
					l_div.className = l_params.cssOn;
				}
				if (l_params.codeOn) {
					xbSetInnerHTML(l_div, l_params.codeOn);
				}
			} else {
				if (l_params.cssOff) {
					l_div.className = l_params.cssOff;
				}
				if (l_params.codeOff) {
					xbSetInnerHTML(l_div, l_params.codeOff);
				}
			}
		}
	}
}

DiapoComponent.prototype.fadeOut = function() {
	// on estompe l'image courante
	fade("img_" + this.name, 90, false, this.format.fade.delta_opacity, this.format.fade.tempo);
}

DiapoComponent.prototype.fadeIn = function() {
	// on estompe l'image courante
	fade("img_" + this.name, 0, true, this.format.fade.delta_opacity, this.format.fade.tempo);
}

/**
 * 
 */
function fade(a_objId, a_opacity, a_plus, a_deltaOpacity, a_tempo) {
	if (document.getElementById) {
		var l_img = document.getElementById(a_objId);
		// plus de timer
		l_img.diapo.timerId = null;
		var l_temporisation;
		if (a_plus) {
			a_opacity += a_deltaOpacity;
			l_temporisation = a_tempo;
		} else {
			a_opacity -= a_deltaOpacity;
			l_temporisation = a_tempo;
		}
		if (!a_plus && (a_opacity < a_deltaOpacity)) {
			// on arrête, et on affiche la suivante
			l_img.diapo.showImage();
			return;
		}
		if ((a_opacity >= 0) && (a_opacity <= 100)) {
			setOpacity(l_img, a_opacity);
			// on rappelle la méthode, en récupérant l'id du process
			l_img.diapo.timerId =
				window.setTimeout("fade('" + a_objId + "'," + a_opacity + "," + a_plus + "," + a_deltaOpacity + "," + a_tempo + ")", l_temporisation);
		}
	}
}

function setOpacity(a_obj, a_opacity) {
	// on conserve l'opacité comme attribut direct de l'objet
	a_obj.opacityValue = a_opacity;
	
	a_opacity = (a_opacity == 100) ? 99.999 : a_opacity;
	// IE/Win
	a_obj.style.filter = "alpha(opacity:" + a_opacity + ")";
	// Safari < 1.2, Konqueror
	a_obj.style.KHTMLOpacity = a_opacity / 100;
	// Older Mozilla and Firefox
	a_obj.style.MozOpacity = a_opacity / 100;
	// Safari 1.2, newer Firefox and Mozilla, CSS3
	a_obj.style.opacity = a_opacity / 100;
}

/**
 * La première image est chargée -> on l'affiche, puis on désactive le principe.
 */
function tempoImgLoaded() {
	tempImg.myLoaded = true;
	tempImg.diapo.showImage();
}