/** constructeur à utiliser depuis la page d'appel pour créer l'objet qui fera les transitions de DIV
prend en paramètre
@ contenu : (string) c'est le nom des div contenant les éléments (ex "contenu" si les div sont contenu1,contenu2...)
@ taille : (int) le nombre d'éléments 
@ transition : (string) c'est le type de transition : 
	="diaporama" : passe d'une image à une autre, avec une possibilité de changement de couleur (en changeant startcolor et endcolor)
	="generique" : défilement type générique de film (avec un affichage de 3 DIV de taille fixe simultanément)
	="defilement" : les élements défilent verticalement les uns apres les autres
@ delai : (int) c'est le délai en millisecondes d'attente entre le passe d'un élément à un autre


exemple d'utilisation: 
	mesNews = new MyScroller("news",5,2,1000,"ConteneurNews","mesNews");
	mesNews.setStepDelay(20);
	mesNews.setHauteurContenu(400);
	mesNews.run();
**/


function MyScroller(sContenu, iTaille, sTransition, iDelai, sConteneur, sNomObjet) {
	
	/*attributs*/
	this.contenu = sContenu; // nom du tableau contenant les éléments
	this.nb_elements = parseInt(iTaille); // nombre d'éléments à faire transiter
	this.typetransition = sTransition;  // type de transition entre 2 éléments; pour le moment : "diaporama" ou "defilement"
	this.attente = iDelai;  //temps d'attente entre 2 transitions (en milisecondes)
	
	this.conteneur = sConteneur;
	this.hauteurConteneur = parseInt(document.getElementById(this.conteneur).style.height); // hauteur du conteneur contenant les DIV
	this.nomObjet = sNomObjet ; // nom de l'instance de MyScroller (on en a besoin dans l'appel des setTimeout)
	this.stepdelay = 50;// attente entre 2 états successifs
	this.maxsteps = 40; // nombre d'états entre le début et la fin de la transition; plus le nombre est petit plus le mouvement est saccadé
	// Nota: maxsteps * stepdelay = temps total du changement de couleur (en milisecondes)
	// à ajouter à attente (temps de transition)
	
	// variables spéciales pour la fonction de changement de couleur
	this.startcolor= new Array(255, 0, 0); // start color (red, green, blue)
	this.endcolor = new Array(255, 255, 0); // end color (red, green, blue)
	this.fadelinks = 0;  //should links inside scroller contenu also fade like text? 0 for no, 1 for yes.

	// varaible d'initialisation (privées)
	this.index = 0; /// remise à zéro de l'index
	this.playing = 1;  // variable booleenne indiquant si les news défilent (=1) ou pas (=0). 
	this.fadecounter =0; // compteur de transition
	//var this.step =1;
	
	/*accesseurs*/
	this.setContenu = setContenu;
	this.setAttente = setAttente;
	this.setTypeTransition = setTypeTransition;
	this.setStepDelay = setStepDelay;
	this.setMaxSteps = setMaxSteps;
	this.setNbElements = setNbElements;
	this.setHauteurConteneur = setHauteurConteneur;
	this.setStartColor = setStartColor;
	this.setEndColor = setEndColor;
	this.setFadeLinks = setFadeLinks;
	this.setConteneur = setConteneur;
	
	/*méthodes*/
	this.run = run;
	this.changecontenu = changecontenu;
	this.transition = transition;
	this.linkcolorchange = linkcolorchange;
	this.colorfade = colorfade;
	this.getstepcolor = getstepcolor;
	this.onClickPlay = onClickPlay;
	this.onClickStop = onClickStop;
	this.onClickForward = onClickForward;
	this.onClickRewind = onClickRewind;
	this.nextIndex = nextIndex;
	this.prevIndex = prevIndex;
	this.slideGenerique = slideGenerique;
	this.slideDefilement = slideDefilement;
	
}

/*****************************************************************************************************************
Corps des accesseurs
*****************************************************************************************************************/
function setAttente(iAttente){ //temps d'attente entre 2 transitions (en milisecondes)
	this.attente = iAttente;
}

function setTypeTransition(sTypeTransition){ // type de transition entre 2 éléments; pour le moment : "diaporama" ou "defilement"
	this.typetransition = sTypeTransition;
}

// variables communes aux 2 transitions (pour plus tard : à intégrer dans chaque fonciton de transition)
function setStepDelay(iStepDelay){// attente entre 2 états successifs
	this.stepdelay = iStepDelay;
}
function setMaxSteps(iMaxSteps) {// nombre d'états entre le début et la fin de la transition; plus le nombre est petit plus le mouvement est saccadé
	this.maxsteps = iMaxSteps;
}
// "delai" et "attente" (qui sont les vrais valeurs entre chaque transition) sont passés dans chaque fonction 

function setContenu(sContenu) { // nom du tableau contenant les éléments
	this.contenu = sContenu;
}

function setNbElements(iNbElements) { // nombre d'éléments à faire transiter
	this.nb_element = iNbElements;
}

function setHauteurConteneur (iHauteurConteneur) { // hauteur du Conteneur
	if (iHauteurConteneur == "" )
		this.hauteurConteneur = parseInt(document.getElementById(this.conteneur).style.height);
	else 
		this.hauteurConteneur = iHauteurConteneur;
	
}

function setStartColor(aStartColor) { //couleur de départ (transition diapo)
	this.startcolor = aStartColor;
}

function setEndColor(aEndColor) { //couleur de fin (transition diapo)
	this.endcolor = aEndColor;
}

function setFadeLinks (iFadeLinks) {
	this.fadelinks = iFadeLinks;
}

function setConteneur (sConteneur) {
	this.conteneur = sConteneur;
}
function setNomObjet( sNomObjet) {
	this.nomObjet = sNomObjet ;
}

/*****************************************************************************************************************
Corps des méthodes
*****************************************************************************************************************/
/**
	fonction de déclenchement des transitions.
**/
function run() {
	//window.onload=this.changecontenu;
	this.changecontenu();
}



/**
	fonction qui effectue le passage d'un élément à un autre
**/
function changecontenu(){
	if (this.playing == 1) {
		if (this.index>=this.nb_elements) {
			this.index=0;
		}
		switch (this.typetransition) {
		case "diaporama" :
			//on récupère notre contenu est on lui applique la bonne couleur
			document.getElementById(this.conteneur).style.color="rgb("+this.startcolor[0]+", "+this.startcolor[1]+", "+this.startcolor[2]+")";
			
			// on parcourt la liste des contenus, puis on remonte celui en cours (z-index très grand) et on plonge les autres très loin (z-index très bas)
			for (var i =0;i < this.nb_elements ; i++) {
				document.getElementById(this.contenu+i).style.zIndex = ( (i==this.index) ?100:-100);
				document.getElementById(this.contenu+i).style.visibility = ( (i==this.index) ?"visible":"hidden");
			}
			break;

		case "generique" :
			// on récupère notre contenu est on lui applique la bonne couleur
			// document.getElementById(conteneur).style.color="rgb("+startcolor[0]+", "+startcolor[1]+", "+startcolor[2]+")";
			
			/* 
			on parcourt la liste des éléments; 
			pour chaque élément :
				- on remonte celui en cours, son suivant et son précédent (z-index très grand)  et on les rend visbles
				- on cache les autres (z-index très bas) et on les rend invisibles
			*/
			for (i=0;i < this.nb_elements ; i++) {
				document.getElementById(this.contenu+i).style.zIndex = ( (i==this.index||i==this.nextIndex()||i==this.prevIndex()) ?100:-100);
				document.getElementById(this.contenu+i).style.visibility = ( (i==this.index||i==this.nextIndex()||i==this.prevIndex()) ?"visible":"hidden");
			}
			break;

		case "defilement" :
			// on applique le meme type d'affichage que pour le diaporama
			for (i=0;i < this.nb_elements ; i++) {
				document.getElementById(this.contenu+i).style.zIndex = ( (i==this.index) ?100:-100);
				document.getElementById(this.contenu+i).style.visibility = ( (i==this.index) ?"visible":"hidden");
			}
		
			break;

		default:
			break;
		}

		this.transition();
	}
	
}


/**
	fonction qui choisit la bonne fonction de transition en fonction du type de transition choisi
**/
function transition() {
	switch (this.typetransition) {
	
	case "diaporama" :
		if (this.fadelinks)
			this.linkcolorchange(1);
		this.colorfade(1);
		break;
	
	case "generique" :
		// initialisation de la position de départ des 3 DIV visibles
		document.getElementById(this.contenu+this.prevIndex()).style.top = 0 * this.hauteurConteneur;
		document.getElementById(this.contenu+this.index).style.top = 1 * this.hauteurConteneur;
		document.getElementById(this.contenu+this.nextIndex()).style.top = 2 * this.hauteurConteneur;
		this.slideGenerique(1);
		break;
		
	case "defilement" :
		// initialisation de la position de départ de la DIV en cours
		document.getElementById(this.contenu+this.index).style.top = this.hauteurConteneur + 20;
		this.slideDefilement(1);
		break;
		
	default : break;
	}
}

/** 
fonction qui change la couleur des hyperliens
**/
function linkcolorchange(step){
	var obj=document.getElementById(this.conteneur).getElementsByTagName("A");
	if (obj.length>0){
		for (i=0; i<obj.length; i++)
		obj[i].style.color=this.getstepcolor(step);
	}
}



/**
	fonction de transition entre les contenus : on gère ici le changement avec fondu de couleur
**/

function colorfade(step) {
	if(step<=this.maxsteps) {
		document.getElementById(this.conteneur).style.color=this.getstepcolor(step);
		if (this.fadelinks)	
			this.linkcolorchange(step);
		step++;
		this.fadecounter=setTimeout(this.nomObjet+".colorfade("+step+")",this.stepdelay);
	} else {
		clearTimeout(this.fadecounter);
		document.getElementById(this.conteneur).style.color="rgb("+this.endcolor[0]+", "+this.endcolor[1]+", "+this.endcolor[2]+")";
		/****** les 2 prochaines lignes sont à incorporer à la fin de chaque fonction de transition que l'on veut ajouter **/
		this.index++;
		setTimeout(this.nomObjet+".changecontenu()", this.attente);
	}   
	
}

/**
	fonction qui récupère la couleur en fonction de l'état dans la transition 
**/
function getstepcolor(step) {
	var diff;
	var newcolor=new Array(3);
	for(var i=0;i<3;i++) {
		diff = (this.startcolor[i]-this.endcolor[i]);
		if(diff > 0) {
			newcolor[i] = this.startcolor[i]-(Math.round((diff/this.maxsteps))*step);
		} else {
			newcolor[i] = this.startcolor[i]+(Math.round((Math.abs(diff)/this.maxsteps))*step);
		}
	}
	return ("rgb(" + newcolor[0] + ", " + newcolor[1] + ", " + newcolor[2] + ")");

}

/**
	fonction qui active le défilement des éléments
**/
function onClickPlay() {
	this.playing = 1;
	clearTimeout(this.fadecounter); //réinitialise le compteur de transition
	this.changecontenu();
}

/**
	fonction qui stoppe le défilement des éléments
**/
function onClickStop() {
	this.playing = 0;
}

/**
	fonction qui passe à l'élément suivant
**/

function onClickForward() {
	this.playing = 1;
	clearTimeout(this.fadecounter); //réinitialise le compteur de transition
	this.index = this.nextIndex();
	this.changecontenu();
}

/**
	fonction qui passe à l'élément précedent
**/
function onClickRewind() {
	this.playing = 1;
	clearTimeout(this.fadecounter); //réinitialise le compteur de transition
	this.index = this.prevIndex();
	this.changecontenu();
}

/**
	fonction qui retourne le N° de l'élément suivant
**/

function nextIndex(){
	return (this.index==(this.nb_elements - 1))? 0: (this.index+1);
}

/**
	fonction qui retourne le N° de l'élément précédent	
**/
function prevIndex(){
	return (this.index==0)? (this.nb_elements - 1): (this.index-1);
}



/**
	fonction de slide vertical spécial generique 
**/
function slideGenerique(step){
// tant que l'on n'a pas fini la transition
	if(step<=this.maxsteps) { 
		// on remonte les 3 DIV 
		document.getElementById(this.contenu+this.index).style.top = parseInt(document.getElementById(this.contenu+this.index).style.top) - (this.hauteurConteneur/(2*this.maxsteps));
		document.getElementById(this.contenu+this.nextIndex()).style.top = parseInt(document.getElementById(this.contenu+this.index).style.top) + this.hauteurConteneur/2 - (this.hauteurConteneur/(2*this.maxsteps));
		document.getElementById(this.contenu+this.prevIndex()).style.top = parseInt(document.getElementById(this.contenu+this.index).style.top) - this.hauteurConteneur/2 - (this.hauteurConteneur/(2*this.maxsteps));
		step++;
		this.fadecounter=setTimeout(this.nomObjet+".slideGenerique("+step+")",this.stepdelay);
	} else {
		// on a fini la transition, on passe à l'élément suivant
		clearTimeout(this.fadecounter);
		/** les 2 prochaines lignes sont à incorporer à la fin de chaque fonction de transition que l'on veut ajouter **/
		this.index++;
		setTimeout(this.nomObjet+".changecontenu()", this.attente);
	}  
}

/** 
fonction de défilement vertical bas vers haut
prend en paramètre 
@ step le numéro de l'état de départ de la transition ( = 1)
@ phase (falcutatif) le numéro de la phase du défilement ( 1 => l'élément rentre dans le conteneur ; 2=> l'élément en sort)
**/
function slideDefilement(step,phase) {
	if (this.playing == 1) {
		switch (phase) {
			case 1 :
				// première phase de l'appel : on fait monter l'élément jusqu'au centre du conteneur 
				if(step<=this.maxsteps) { 
					// on remonte l'élément 
					//alert (this.contenu+this.index+" "+this.hauteurConteneur+" "+this.maxsteps);
					document.getElementById(this.contenu+this.index).style.top = parseInt(document.getElementById(this.contenu+this.index).style.top) - (1*(this.hauteurConteneur/this.maxsteps));
					//alert (this.contenu+this.index+" "+this.hauteurConteneur+" "+this.maxsteps);
					step++;
					this.fadecounter= setTimeout(this.nomObjet+".slideDefilement("+step+",1);", this.stepdelay);
					//alert ("apres le timeout");
				} else {
					clearTimeout(this.fadecounter);
					// on laisse l'élément immobile pendant la durée d' "attente"
					setTimeout(this.nomObjet+".slideDefilement(1,2)", this.attente);
				}
				break;
			case 2 :
				// deuxieme phase de l'appel : on fait monter l'élément hors du conteneur 
				if(step<=this.maxsteps) { 
					// on remonte l'élément 
					document.getElementById(this.contenu+this.index).style.top = parseInt(document.getElementById(this.contenu+this.index).style.top) - (1*(this.hauteurConteneur/this.maxsteps));
					step++;
					this.fadecounter=setTimeout(this.nomObjet+".slideDefilement("+step+",2)", this.stepdelay);
				} else {
					clearTimeout(this.fadecounter);
					// une fois hors de l'écran, on passe à l'élément suivant.
					this.index++;
					this.changecontenu();
				}
				break;
			default: 
					this.slideDefilement(1,1);
				break;
		}
	}
}
