﻿// ========================================================================================================
// "ExtraScroll" - Classe de scroll dans une balise
//   by Extrafine (contact@extrafine.fr)
// ========================================================================================================
/*
 * Copyright (c) 2011 Extrafine
 * Version: 1.2 (01/03/2011)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */
// ========================================================================================================
// 

function ExtraScroll(pId,pName) 
{	
	// Attribut ###############################################
	this.Id = pId;				// Id de la balise
	this.Name = pName;			// Nom de l'instance de ExtraScroll
	this.Frequence = 50;		// Fréquence des intervals
    this.InScroll = false;		// Mouvement en cours
	this.Scroll = 0;				// Scroll Vertical de la balise
	this.ScrollH = 0;				// Scroll Horizontal de la balise
	this.ScrollGo = 0;				// Scroll Vertical de destination
	this.ScrollGoH = 0;				// Scroll Horizontal de destination
	this.ScrollMin = 0;				// Scroll Vertical Minimun
	this.ScrollMinH = 0;			// Scroll Horizontal Minimun	
	this.ScrollMax = 0;				// Scroll Vertical Maximun
	this.ScrollMaxH = 0;			// Scroll Horizontal Maximun
	this.ScrollInterval = null;			// Identifiant de l'Interval
	this.ScrollIntervalParent = null;	// Identifiant de l'Interval du Scroll Continu
	this.ScrollFondu = true;		// Fondu du Mouvement
	this.ScrollCoef = 10;			// Coefficient du Fondu
    this.ScrollPas = 25;			// Pas du Scroll
	this.ScrollPasHold = false;		// Vérrouillage du Pas sur un multiple
	this.ScrollTagUp = new Array();		// Id des balises informatives Haute
	this.ScrollTagDown = new Array();	// Id des balises informatives Basse
	this.ScrollTagLeft = new Array();	// Id des balises informatives Gauche
	this.ScrollTagRight = new Array();	// Id des balises informatives Droite
	
	// Methode ################################################
	//  this.DoScroll 		// Modification du Scroll Vertical (y)
	//  this.DoScrollH 		// Modification du Scroll Horizontal (x)
	// 	this.ScrollInit 	// Initialisation du Scroll 
	//	this.ScrollMaj 		// Mise à jour du contenu de la balise
	// 	this.ScrollSet 		// Calcul du Scroll Vertical
	// 	this.ScrollSetH		// Calcul du Scroll Horizontal
	// 	this.ScrollTo 		// Changement vers le Scroll Vertical (y)
	// 	this.ScrollToH 		// Changement vers le Scroll Horizontal (x)
	//	this.ScrollBy 		// Changement du Scroll Vertical (y)
	//	this.ScrollByH 		// Changement du Scroll Horizontal (x)
	// 	this.ScrollOn 		// Scroll Continu Vertical de la balise
	// 	this.ScrollOnH 		// Scroll Continu Horizontal de la balise
	// 	this.ScrollOff 		// Arrêt du Scroll Continu de la balise
	// 	this.ScrollWheel 	// Roulette de la souris dans la balise
	// 	this.ScrollBorne 	// Vérification des Borne du Scroll Vertical (y)
	// 	this.ScrollBorneH	// Vérification des Borne du Scroll Horizontal (x)
	//  this.ScrollInfo		// Changement d'état des balises informatives Vertical (y)
	//  this.ScrollInfoH	// Changement d'état des balises informatives Horizontal (x)
	
	
    // Modification du Scroll Vertical (y)
    this.DoScroll = function(y) 
    {
		var $ScrollHold = y;
		if(this.ScrollPasHold) {
			$ScrollHold = Math.round(y / this.ScrollPas) * this.ScrollPas;
			if($ScrollHold > this.ScrollMax)
				$ScrollHold = (Math.round(y / this.ScrollPas) - 1) * this.ScrollPas;
		}
        this.Scroll = $ScrollHold;
        document.getElementById(this.Id).scrollTop = $ScrollHold;
        this.ScrollInfo($ScrollHold);
    }
	
    // Modification du Scroll Horizontal (x)
    this.DoScrollH = function(x) 
    {
        var $ScrollHold = x;
		if(this.ScrollPasHold) {
			$ScrollHold = Math.round(x / this.ScrollPas) * this.ScrollPas;
			if($ScrollHold > this.ScrollMaxH)
				$ScrollHold = (Math.round(y / this.ScrollPas) - 1) * this.ScrollPas;
		}
		this.ScrollH = $ScrollHold;
        document.getElementById(this.Id).scrollLeft = $ScrollHold;
		this.ScrollInfoH($ScrollHold);
    }

    // Initialisation du Scroll
	this.ScrollInit = function() 
    {         
        //document.getElementById(this.Id).style.overflow = 'hidden';
        document.getElementById(this.Id).className = this.Name +" "+ document.getElementById(this.Id).className;
		
        if(document.getElementById(this.Id).addEventListener) {
            document.getElementById(this.Id).addEventListener('DOMMouseScroll', this.ScrollWheel, false);
            document.getElementById(this.Id).addEventListener('mousewheel', this.ScrollWheel, false);
        } else if(document.getElementById(this.Id).attachEvent)
            document.getElementById(this.Id).attachEvent('onmousewheel', this.ScrollWheel);

        this.ScrollMax = document.getElementById(this.Id).scrollHeight - document.getElementById(this.Id).offsetHeight;
		if(this.ScrollMax != 0) 
			this.ScrollMax += 3;
		this.ScrollMaxH = document.getElementById(this.Id).scrollWidth - document.getElementById(this.Id).offsetWidth;
		if(this.ScrollMaxH != 0) 
			this.ScrollMaxH += 3;
    }

    // Mise à jour du contenu de la balise
    this.ScrollMaj = function(pInit)
    {
        this.ScrollMax = document.getElementById(this.Id).scrollHeight - document.getElementById(this.Id).offsetHeight;
		if(this.ScrollMax != 0) 
			this.ScrollMax += 3;
		this.ScrollMaxH = document.getElementById(this.Id).scrollWidth - document.getElementById(this.Id).offsetWidth;
		if(this.ScrollMaxH != 0) 
			this.ScrollMaxH += 3;
		if(pInit) {
			this.Scroll = 0;
			this.ScrollH = 0;
		}		
		this.ScrollInfo(this.ScrollBorne(this.Scroll));
		this.ScrollInfoH(this.ScrollBorneH(this.ScrollH));
    }
    
	// Calcul du Scroll Vertical
    this.ScrollSet = function() 
    {
        var val = 0;            
        var diffVal = ((this.Scroll - this.ScrollGo) / this.ScrollCoef);
        
        if(Math.abs(diffVal) < 1.5) {
            if(Math.abs(diffVal) <= 0.5) {
                if(this.Scroll == this.ScrollGo) {
                    clearInterval(this.ScrollInterval);
                    this.InExtra = false;                    
                    this.InScroll = false;
                    return true;
                } else {
                    diffVal = Math.round(diffVal);
                    if(diffVal == 0) 
                        diffVal = (this.ScrollGo - this.Scroll) > 0 ? -1 : 1;
                }
            } else {
                diffVal = diffVal * 2;
            }
        }
        
        val = (this.Scroll - diffVal);
		val = Math.round(val);
        this.DoScroll(val);
    }
	
	// Calcul du Scroll Horizontal
    this.ScrollSetH = function() 
    {
        var val = 0;            
        var diffVal = ((this.ScrollH - this.ScrollGoH) / this.ScrollCoef);
        
        if(Math.abs(diffVal) < 1.5) {
            if(Math.abs(diffVal) <= 0.5) {
                if(this.ScrollH == this.ScrollGoH) {
                    clearInterval(this.ScrollInterval);
                    this.InExtra = false;                    
                    this.InScroll = false;
                    return true;
                } else {
                    diffVal = Math.round(diffVal);
                    if(diffVal == 0) 
                        diffVal = (this.ScrollGoH - this.ScrollH) > 0 ? -1 : 1;
                }
            } else {
                diffVal = Math.round(diffVal) * 2;
            }
        }
        
        diffVal = Math.round(diffVal);
        val = (this.ScrollH - diffVal);
        this.DoScrollH(val);
    }
	
    // Changement vers le Scroll Vertical (y)
	this.ScrollTo = function(y) 
    {
        this.ScrollGo = y;
        this.ScrollGo = this.ScrollBorne(this.ScrollGo);
        
        if(!this.InScroll) {
            if(this.ScrollFondu) {
                this.InExtra = true;
                this.InScroll = true;
                clearInterval(this.ScrollInterval);
                var myThis = this;
                this.ScrollInterval = setInterval(function(){myThis.ScrollSet()},this.Frequence);
            } else
                this.DoScroll(this.ScrollGo);
        }
    }
    
	// Changement vers le Scroll Horizontal (x)
	this.ScrollToH = function(x) 
    {
        this.ScrollGoH = x;
        this.ScrollGoH = this.ScrollBorneH(this.ScrollGoH);
        
        if(!this.InScroll) {
            if(this.ScrollFondu) {
                this.InExtra = true;
                this.InScroll = true;
                clearInterval(this.ScrollInterval);
                var myThis = this;
                this.ScrollInterval = setInterval(function(){myThis.ScrollSetH()},this.Frequence);
            } else
                this.DoScrollH(this.ScrollGoH);
        }
    }
	
     // Changement du Scroll Vertical (y)
	this.ScrollBy = function(y) 
    {
        this.ScrollMax = document.getElementById(this.Id).scrollHeight - document.getElementById(this.Id).offsetHeight;
		if(this.ScrollMax != 0) 
			this.ScrollMax += 3;
		
		if(!this.InScroll) {
            this.ScrollGo += parseInt(y);
            this.ScrollGo = this.ScrollBorne(this.ScrollGo);
            if(this.ScrollFondu) {
                this.InExtra = true;
                this.InScroll = true;
                clearInterval(this.ScrollInterval);
                var myThis = this;
                this.ScrollInterval = setInterval(function(){myThis.ScrollSet()},this.Frequence);
            } else
                this.DoScroll(this.ScrollGo);
        } else {
            if((this.ScrollGo - this.Scroll) >= ((this.ScrollGo + y) - this.Scroll)) {
                this.ScrollGo += y;
                this.ScrollGo = Math.round(this.ScrollGo);
            } else {
                this.ScrollGo += y;
                this.ScrollGo = Math.round(this.ScrollGo + ((this.ScrollGo - this.Scroll) * 0.15));
            }
            this.ScrollGo = this.ScrollBorne(this.ScrollGo);
        }
    }
	
	// Changement du Scroll Horizontal (x)
	this.ScrollByH = function(x) 
    {
        this.ScrollMaxH = document.getElementById(this.Id).scrollWidth - document.getElementById(this.Id).offsetWidth;
		if(this.ScrollMaxH != 0) 
			this.ScrollMaxH += 3;
		
		if(!this.InScroll) {
            this.ScrollGoH += parseInt(x);
            this.ScrollGoH = this.ScrollBorneH(this.ScrollGoH);
            if(this.ScrollFondu) {
                this.InExtra = true;
                this.InScroll = true;
                clearInterval(this.ScrollInterval);
                var myThis = this;
                this.ScrollInterval = setInterval(function(){myThis.ScrollSetH()},this.Frequence);
            } else
                this.DoScrollH(this.ScrollGoH);
        } else {
            if((this.ScrollGoH - this.ScrollH) >= ((this.ScrollGoH + x) - this.ScrollH)) {
                this.ScrollGoH += x;
                this.ScrollGoH = Math.round(this.ScrollGoH);
            } else {
                this.ScrollGoH += x;
                this.ScrollGoH = Math.round(this.ScrollGoH + ((this.ScrollGoH - this.ScrollH) * 0.15));
            }
            this.ScrollGoH = this.ScrollBorneH(this.ScrollGoH);
        }
    }
	
    // Scroll Continu Vertical de la balise
	this.ScrollOn = function(pSigne) 
    {
        var ePas = pSigne == "+" ? this.ScrollPas : -this.ScrollPas;
		this.ScrollBy(ePas);
        var myThis = this;
        this.ScrollIntervalParent = setInterval(function(){myThis.ScrollBy(ePas)},this.Frequence);
    }
	
	// Scroll Continu Horizontal de la balise
	this.ScrollOnH = function(pSigne) 
    {
        var ePas = pSigne == "+" ? this.ScrollPas : -this.ScrollPas;
		this.ScrollByH(ePas);
        var myThis = this;
        this.ScrollIntervalParent = setInterval(function(){myThis.ScrollByH(ePas)},this.Frequence);
    }
	
    // Arrêt du Scroll Continu de la balise
    this.ScrollOff = function() 
    {
        clearInterval(this.ScrollIntervalParent);
    }	

    // Roulette de la souris dans la balise
    this.ScrollWheel = function(event)
    {
        var delta = 0;
        
        if(!event)
            event = window.event;
                
        if(event.wheelDelta)
            delta = event.wheelDelta / 120;
        else if(event.detail)
            delta = -event.detail / 3;
        
        var cClassName = this.className.search(/ /) == -1 ? this.className : this.className.substr(0,this.className.search(/ /));
        
        delta = -delta;
        delta = eval('delta * '+ cClassName +'.ScrollPas');
        eval(cClassName +'.ScrollBy(delta);')
        
        if(event.preventDefault)
            event.preventDefault();
        event.returnValue = false;
    }

    // Vérification des Borne du Scroll Vertical
    this.ScrollBorne = function(y)
    {
        if(y < this.ScrollMin)
            y = this.ScrollMin;
        if(y > this.ScrollMax)
            y = this.ScrollMax;
            
        return y;
    } 

	// Vérification des Borne du Scroll Horizontal
    this.ScrollBorneH = function(x)
    {
        if(x < this.ScrollMinH)
            x = this.ScrollMinH;
        if(x > this.ScrollMaxH)
            x = this.ScrollMaxH;
            
        return x;
    } 
	
	// Changement d'état des balises informatives Vertical (y)
	this.ScrollInfo = function(y)
	{
		var m = 5;
		for(i=0; i<this.ScrollTagUp.length; i++) {
			if(this.ScrollTagUp[i] != null && document.getElementById(this.ScrollTagUp[i]) != null) {
				if(y >= this.ScrollMin-m && y <= this.ScrollMin+m){
					document.getElementById(this.ScrollTagUp[i]).style.visibility = 'hidden';
					clearInterval(this.ScrollIntervalParent);
				} else
					document.getElementById(this.ScrollTagUp[i]).style.visibility = 'visible';
			}
		}
		for(i=0; i<this.ScrollTagDown.length; i++) {
			if(this.ScrollTagDown[i] != null && document.getElementById(this.ScrollTagDown[i]) != null) {
				if(y >= this.ScrollMax-m && y <= this.ScrollMax+m){
					document.getElementById(this.ScrollTagDown[i]).style.visibility = 'hidden';
					clearInterval(this.ScrollIntervalParent);
				} else
					document.getElementById(this.ScrollTagDown[i]).style.visibility = 'visible';
			}
		}
	}
	
	// Changement d'état des balises informatives Horizontal (x)
	this.ScrollInfoH = function(x)
	{
		var m = 5;
		for(i=0; i<this.ScrollTagLeft.length; i++) {
			if(this.ScrollTagLeft[i] != null && document.getElementById(this.ScrollTagLeft[i]) != null) {
				if(x >= this.ScrollMinH-m && x <= this.ScrollMinH+m){
					document.getElementById(this.ScrollTagLeft[i]).style.visibility = 'hidden';
					clearInterval(this.ScrollIntervalParent);
				} else
					document.getElementById(this.ScrollTagLeft[i]).style.visibility = 'visible';
			}
		}
		for(i=0; i<this.ScrollTagRight.length; i++) {
			if(this.ScrollTagRight[i] != null && document.getElementById(this.ScrollTagRight[i]) != null) {
				if(x >= this.ScrollMaxH-m && x <= this.ScrollMaxH+m){
					document.getElementById(this.ScrollTagRight[i]).style.visibility = 'hidden';
					clearInterval(this.ScrollIntervalParent);
			} else
					document.getElementById(this.ScrollTagRight[i]).style.visibility = 'visible';
			}
		}
	}
}
