// Routines pour scroller 100% javascript, Flash like.
// Net-Createurs www.net-createurs.com - v1.0 : novembre 2009

var sfs_noret=false;				// Bug IE6 + Flash sur la gesiotn onmousemove, qu doit retouner false avec IE6 pour éviter le drag&drop, sauf sur Flash
function sfs_ret(x) { sfs_noret=x }

var sfs_todrag=null					// Objet à déplacer, ou rien si null
var sfs_dragdir=0					// direction du déplacement (dir)
var sfs_draginit=false				// true -> placement de l'objet au premier clic
var sfs_doc=document.compatMode && document.compatMode=="BackCompat" ? document.body : document.documentElement

if(typeof(window.addEventListener)=='undefined') document.onmousedown = function() { sfs_move(event) }		// IE6-7
else window.addEventListener('mousedown',sfs_move,false)													// les autres

if(typeof(window.addEventListener)=='undefined') document.onmouseup = function() { sfs_endmove(event) }
else window.addEventListener('mouseup',sfs_endmove,false)

if(typeof(window.addEventListener)=='undefined') document.onmousemove = function() { sfs_move(event);return sfs_noret }
else window.addEventListener('mousemove',sfs_move,false)

// MAJ du slider suite à une modification dynamique du contenu à scroller (ajax)
// way true -> remontée vers le haut, sinon vers le bas suite à delete d'un objet
// offset -> rien, ou id d'un objet à atteindre
function x_update(slider,speed,way,stepinit,target,target_offset) {
	sfs_presetsliders()
	if(!speed) var speed=0		// vitesse globale, défaut=10
	if(typeof(way)=='undefined') var way=false
	if(!stepinit) var stepinit=x_step_def
	if(typeof(target)=='undefined' || !target) var target=-1		// id d'un élément à atteindre
	if(target!=-1) {
		if(typeof(target_offset)=='undefined') var target_offset=15
		target=document.getElementById(target)
		target=target? target.offsetTop-target_offset : -1
		if(target<0) target=0
	}
	var o,x,c=document.getElementById(sfs_p[slider]['toscroll'])
	offset=c.style.top? parseInt(c.style.top,10) : 0
	if(target==-1) {
		x=document.getElementById(slider)
		o=sfs_p[slider]['yscale']? sfs_p[slider]['ymin']+(-offset/sfs_p[slider]['yscale']) : 0
		if(o<sfs_p[slider]['ymin']) o=sfs_p[slider]['ymin']
		else if(o>sfs_p[slider]['ymax']) o=sfs_p[slider]['ymax']
		x.style.top=Math.floor(o)+'px'
	}
	else way=-offset>target	// Offset est par nature toujours négatif
	if(target!=-1 || o==sfs_p[slider]['ymax'] || !sfs_p[slider]['yscale'] || way) x_scroll(slider,way?0:1,speed,true,stepinit,target)		// recadrage du contenu
}

// Scroll du slider 'slider' vers le bas (cde=1) ou le haut (cde=0) ou arrêt du scroll (cde=2) ou RAZ (cde=3)
var x_scroll_on=new Array()		// mémo des timeout pour les stopper au mouseout
var x_scroll_acc=4				// Facteur d'accélération (0=aucune, 5=moyen, 10=rapide)
var x_scroll_max=10				// Vitesse max (1=maxi, 10=plus lent, etc.)
var x_step_def=2				// step par défaut
function x_scroll(slider,cde,speed,forced,step,target) {
	var id=sfs_p[slider]['toscroll']	// Id du contenu à scroller avec ce curseur
	var x=document.getElementById(id),c=document.getElementById(id+'-container')
	if(typeof(forced)=='undefined') var forced=false
	if(typeof(target)=='undefined') var target=-1		// Offset cible à atteindre
	if(!speed) var speed=x_scroll_max
	if(!step) var step=x_step_def
	if(cde==2) {
		if(x_scroll_on[id]) {
			clearTimeout(x_scroll_on[id])
			x_scroll_on[id]=null
		}
	}
	else if(x && c && (sfs_p[slider]['yscale'] || forced)) {
		var stop=false, xh=x.offsetHeight, ch=c.offsetHeight, offset=x.style.top? parseInt(x.style.top,10) : 0, margin=sfs_p[id]['marginBottom']
		switch (cde) {
		case 0:		// scroll vers le haut 
			if(target==-1) target=0 
			if(offset<-target) offset+=step;
			if(offset>=-target) { offset=-target; stop=true }
			break
		case 1:		// Scroll vers le bas
			if(target==-1) {	// pas de cible à atteindre : on s'arrête en bas de la fenêtre
				if(ch-offset<xh+margin) offset-=step;
				if(ch-offset>xh+margin) { offset=-(xh+margin-ch); if(offset>0) offset=0; stop=true }
			}
			else {				// cible à atteindre, on s'arrête quand elle est en haut, ou que le bas du contenu est atteint
				if(offset>-target) offset-=step;
				if(offset<=-target) { offset=-target; stop=true }
				if(ch-offset>xh+margin) { offset=-(xh+margin-ch); if(offset>0) offset=0; stop=true }
			}
			break
		case 3:		// RAZ
			offset=0
			stop=true
			break
		}
		x.style.top=Math.floor(offset)+'px'

		// Maj du slider associé
		if(slider) {
			x=document.getElementById(slider)
			if(x) x.style.top=(sfs_p[slider]['yscale']? sfs_p[slider]['ymin']+Math.floor(-offset/sfs_p[slider]['yscale']) : sfs_p[slider]['ymin'])+'px'
		}
		if(!stop) {
			// Calcul du step
			step=step*(1+x_scroll_acc/10)
			if(step>Math.abs(ch-xh)/speed) step=Math.abs(ch-xh)/speed
			if(step<1) step=1
			x_scroll_on[id]=setTimeout('x_scroll("'+slider+'",'+cde+','+speed+','+forced+','+step+','+target+')',40)
		}
	}
	return false
}


// Place le curseur à la valeur arrondie la plus proche, selon son échelle de valeur (entrée 'graduations' de ses paramètres, 0 -> pas d'arrondi)
// et mémo de la "valeur" dans un champ de formulaire hidden 'id_value', s'il existe (permet de passer la valeur du curseur dans un formulaire, pour traitement éventuel
function sfs_pos(px,py) {
	var x=document.getElementById(sfs_todrag)
	var p=sfs_p[sfs_todrag],ypos=py+p['yoffset']-p['y0']
	// Calcul de x avec step éventuel, et mémo dans champ hidden éventuel
	if(p['xstep']) { var val=Math.round((px-p['x0']-p['xmin']+p['xoffset'])/p['xstep']), xpos=val*p['xstep']+p['xmin'] }
	else var val=px+p['xoffset']-p['x0'], xpos=val
	var xmem=document.getElementById(sfs_todrag+'_value')	// Champ de formulaire éventuel pour mémo de l'offset
	if(xmem) xmem.value=val
	var z=p['toscroll']? document.getElementById(p['toscroll']) : null	// Contenu éventuel à scroller

	if(sfs_dragdir&2) {if(xpos<p['xmin']) xpos=p['xmin']; else if(xpos>p['xmax']) xpos=p['xmax']; x.style.left=xpos+'px' }
	if((sfs_dragdir&1) && p['yscale']) {
		if(ypos<p['ymin']) ypos=p['ymin']
		else if(ypos>p['ymax']) ypos=p['ymax']
		x.style.top=ypos+'px'
		if(z) z.style.top=-Math.floor((ypos-p['ymin'])*p['yscale'])+'px'
	}
}


// mousedown sur un objet "actif" (pas forcément celui à déplacer) qui lance cette routine via un onmousedown="return sfs_drag()"
// init des paramètres de l'objet à déplacer (celui dont id=what). Le return false final empêche le drag&drop de l'image par le navigateur
// Le mousedown global document arrivera après celui ci
// what=ID de l'objet à bouger, dir=1(vertical) 2(horizontal) 3(les 2), init=move à la position du clic au clic (true) ou pas
// ATTENTION : le step de déplacement de chaque curseur a été calculé lors du preset des sliders (fin de ce fichier)
function sfs_drag(what,dir,init) {
	var x=document.getElementById(what)
	// repere=container de l'ascenceur dont le coin haut/gauche constitue le point de référence pour le calcul des offsets
	repere=sfs_p[what]['container']
	if(x) {
		sfs_todrag=what
		sfs_dragdir=dir
		sfs_draginit=init
		if(!sfs_p[what][init]) {

			// Calcul de l'offset initial de l'objet sur lequel on a cliqué
			var x=document.getElementById(repere), x0=x.offsetLeft, y0=x.offsetTop, x1, y1,	//
				prevpos, thispos='', isfirst
			while(x.parentNode && x.parentNode.tagName!='BODY') {
				x=x.parentNode
				if(x.tagName=='DIV') {
					x1=typeof(x.offsetLeft)=='number' ? x.offsetLeft : 0
					y1=typeof(x.offsetTop)=='number' ? x.offsetTop : 0
					prevpos=thispos
					if(typeof(document.defaultView)=='undefined') {		// IE 6/7. Ne pas tester sur currentStyle car Opera10 le reconnait
																		// bug IE lorsqu'un DIV est le premier élément imbriqué dans un autre
						thispos=x.currentStyle.position
						isfirst=!x.previousSibling
//alert('prevpos='+prevpos+'\nthis pos='+thispos+'\nisfirst='+isfirst + '\nx='+x1+' / y='+y1);
						switch(thispos) {
						case 'relative':
							if(isfirst && prevpos=='relative') { x1=0; y1=0 }
							break
						case 'static':
//							if(isfirst) {
//								if(prevpos=='static') { x1=0; y1=0 }
//								else if(prevpos=='relative') { x1=-x1; y1=-y1 }
//							}
							if(prevpos && prevpos!='absolute') { x1=0; y1=0 }
							break
						}
					}
					else {
						// FF - Safari - Opera - Chrome : pas de pb si le div est le premier
						thispos=document.defaultView.getComputedStyle(x, null).position
//alert('prevpos='+prevpos+'\nthis pos='+thispos + '\nx='+x1+' / y='+y1);

						switch(thispos) {
						case 'static':
							if(prevpos && prevpos!='absolute') { x1=0; y1=0 }
							break
						}
					}
					x0+=x1; y0+=y1
				}
			}

			// mise à jour des offsets
			sfs_p[what]['x0']=x0
			sfs_p[what]['y0']=y0
		}
	}
	return false	// nécessaire pour que certains navigateurs ne fasse pas un drag&drop sur l'image cliquée (FF, safari, google chrome)
					// IE6 : ce return est inutile, il en faut un dans sfs_move() ci dessous
					// Opera 9.64 : inutile dans tous les cas
}


// Mousedown ou Mousemove global document -> déplacement correspondant de sfs_todrag
// Le mousedown est utile quand le curseur doit se déplacer au clic ailleurs que sur lui même
function sfs_move(e) {
	if(sfs_todrag && sfs_dragdir) {
		var ev=document.all ? window.event: e
		var px=ev.clientX+sfs_doc.scrollLeft, py=ev.clientY+sfs_doc.scrollTop
		sfs_pos(px,py)
	}
	return false	// IE6 uniquement : interdit le drag&drop. Pour les autres bavigateurs : cf. sfs_drag() ci dessus
}


// Mouseup global document -> fin de déplacement
function sfs_endmove(e) {
	if(sfs_todrag) {
		sfs_todrag=null
	}
}


// ---------------------------
// Initialisation (preset) des curseurs décrits dans sfs_p[]
// Cette fonction doit être exécutée car elle initialise leurs éventuelles 'graduations' et échelle
// le slider est remis à 0 (en haut)
function sfs_presetsliders() {
	if(typeof(sfs_p)!='undefined') for(var i in sfs_p) {
		var x=document.getElementById(i+'_value'),val=x? x.value : ''		// Preset du slider i
		var p=sfs_p[i], alpha=100
		sfs_p[i]['xstep']=p['graduations']? (p['xmax']-p['xmin'])/(p['graduations']-1) : 0
		if(val!='') document.getElementById(i).style.left=Math.round((sfs_p[i]['xstep']*val)+p['xmin'])+'px'
		if(sfs_p[i]['toscroll']) {		// Calcul de l'échelle de scroll. sfs_p[i]['marginBottom']=marge à ajouter en bas du contenu à scroller
			var x=document.getElementById(sfs_p[i]['toscroll']),c=document.getElementById(sfs_p[i]['toscroll']+'-container')
			var offset=x.offsetHeight-c.offsetHeight+sfs_p[sfs_p[i]['toscroll']]['marginBottom']
			sfs_p[i]['yscale']=offset/(sfs_p[i]['ymax']-sfs_p[i]['ymin'])	// nb de pixel à déplacer sur la fenêtre pour 1 pixel sur le curseur
			if(sfs_p[i]['yscale']<=0) {
				sfs_p[i]['yscale']=0	// le contenu est moins long que le conteneur
				alpha=sfs_p[i]['alphaoff']
			}
			if(!document.all) {
				var s=document.getElementById(p['container'])
				if(s) s.style.opacity=alpha/100
			}
			else {
				// IE6 : modif alpha du DIV global entraine la disparition de ses éléments internes (même si alpha=100)
				// on traite donc ses composants individuellement
//				var slider_comp=new Array(i,sfs_p[i]['container']+'-path',sfs_p[i]['container']+'-top',sfs_p[i]['container']+'-bottom')
				var slider_comp=new Array(sfs_p[i]['container']+'-path',sfs_p[i]['container']+'-top',sfs_p[i]['container']+'-bottom')
				for (var j in slider_comp) {
					var s=document.getElementById(slider_comp[j])
					if(s) s.style.filter='progid:DXImageTransform.Microsoft.alpha(opacity='+alpha+')'
				}
			}
		}
	}
}

