﻿/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Custom Scroller Object   V0.2
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
//  Développé par: Robert Limoges
//  
//  Fonction:
//      Crée des barres de défilement, avec ou sans trackbar,flèches etc. 
//      Fonctionne dans IE6+, FF1.5+ et safari 1.3+.
//
//  Dépendences:
//      EventManager.js
//
//  Méthodes:
//      init():
//          Doit être utilisé après avoir définit l'objet et ses propriétés. Initialise l'objet est render le scroll.
//
//      scrollUp():
//          Peut être appeller de l'externe pour initialiser le défilement vers le haut (ou la gauche).
//
//      scrollDown():
//          Peut être appeller de l'externe pour initialiser le défilement vers le bas (ou la droite).
//
//      refresh():
//          Doit être appellé dans le cas ou le contenu change de dimension pour updater les dimensions du scroll.
//
//  Propriétés:
//      Requises:
//          scrollContent: L'ID de l'élement(div) de contenu qui sera scrollé.
//
//      Optionelles:
//		    direction:  La direction du scroll. 0 = verticale, 1 = horizontale
//		    scrollOver: A true, le défilement s'active en rollover sur les flèches
//		    scrollSpeed: La vitesse de défilement
//		    scrollerFixedWidth, scrollerFixedHeight: Si spécifié, le scroller restera de taille fixe plutot que s'ajuster au contenu.
//		    scrollUpImg: L'image de la fleche vers le haut, ou gauche si la direction est horizontale.
//		    scrollUpImgOv: L'image de la fleche vers le haut, ou gauche si la direction est horizontale, en rollover.
//		    disabledUpImg: Si spécifié, l'image de la fleche du haut, ou gauche quand on est completement en haut ou a gauche du contenu.
//          scrollDownImg: L'image de la fleche vers le bas, ou droite si la direction est horizontale.
//		    scrollBtnHeight: La hauteur des images des boutons fleches (haut, bas, droite, gauche).
//		    scrollBtnWidth: La largeur des images des boutons fleches (haut, bas, droite, gauche).
//          scrollStep: Si définie, le défilement se fait par étape de (x)
//          trackHideOnDisabled: A true, le scrolltrack disparrait quand il n'est pas nécessaire.
//
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
	// Constructor
	/////////////////////////////////////////////////////////////////////////////////////
	function scrollerObj(me) {
		this.me = me;
		this.direction = 0; // 0 = vertical, 1 = horizontal
		this.scrollOver = false;
		this.scrollSpeed = 3;
		this.trackHideOnDisabled = null;
		this.scrollStep = null;
		
		this.scrollContent = null;
		this.scrollContentHeight = null;
		this.scrollTrack = null;
		this.scrollTrackInner = null;
		this.scroller = null;
		this.scrollTrackHeight = null;
		this.scrollTrackWidth = null;
		
		this.scrollMax = null;
		this.scrollContentMax = null;
		
		this.scrollerSize = null;
		this.scrollerPosition = null;
		
		this.scrollerInitialPos = 0;
		this.scrollerFixedWidth = null;
		this.scrollerFixedHeight = null;
		
		this.scrollerImg = null;
        this.scrollerBGImg = null;
        this.scrollerBGDisImg = null;

		this.scrollUpBtn = null;
		this.scrollDownBtn = null;

		this.scrollUpImg = null;
		this.scrollUpImgOv = null;
		this.disabledUpImg = null;
        this.scrollUpState = 1;

		this.scrollDownImg = null;
		this.scrollDownImgOv = null;
		this.disabledDownImg = null;
        this.scrollDownState = 1;
		
		this.scrollBtnHeight = 0;
		this.scrollBtnWidth = 0;

        this.checkDisabledNeeded = 0;
        
		this.draggingScroll = false;
		this.scrolling = false;
		this.scrollStopInitiated = false;
		this.disabled = true;
	}
	
    /////////////////////////////////////////////////////////////////////////////////////
	// Methods
	/////////////////////////////////////////////////////////////////////////////////////
	scrollerObj.prototype.init = function() {
		// Initialize object and create the scroller HTML elements
		this.scrollContent = document.getElementById(this.scrollContent);
	    this.scrollContentHeight = parseInt(this.scrollContent.style.height.removePX());
	    this.scrollContentWidth = parseInt(this.scrollContent.style.width.removePX());
        floater = "";
        if(this.scrollerImg) {
            this.scrollTrack = this.me.undotted() + "Track";
            this.scroller = this.me.undotted() + "Scroller";
    		this.scrollTrack = document.getElementById(this.scrollTrack);
    		if(this.direction == 0) {
                this.scrollTrackHeight = parseInt(this.scrollTrack.style.height.removePX(),0) - (this.scrollBtnHeight *2);
                this.scrollTrackWidth = (this.scrollerFixedWidth) ? this.scrollerFixedWidth : this.scrollBtnWidth;
		        offsetD = "offsetTop"
            } else {
                
                this.scrollTrackHeight = (this.scrollerFixedHeight) ? this.scrollerFixedHeight : this.scrollBtnHeight;
		        this.scrollTrackWidth = parseInt(this.scrollTrack.style.width.removePX(),0) - (this.scrollBtnWidth *2);
		        floater = "float:left;";
		        offsetD = "offsetLeft"
            }
		} else {
    		this.scrollTrackHeight = this.scrollContent.style.height.removePX(); 
            this.scrollTrackWidth = this.scrollContent.style.width.removePX();
	        this.scrollTrackUp = this.me + "TrackUp";
	        this.scrollTrackDown = this.me + "TrackDown";
		    this.scrollTrackUp = document.getElementById(this.scrollTrackUp);
		    this.scrollTrackDown = document.getElementById(this.scrollTrackDown);
		}
        
		// Render the scrollbar
		// Up/Left arrow
		if(this.scrollUpImg) {
            html  = "<img width='" + this.scrollBtnWidth + "'";
            html += " height='" + this.scrollBtnHeight + "'";
            html += " onmousedown='" + this.me + ".scrollUp();'";
            if(this.scrollUpImgOv || this.scrollOver) {
                html += " onmouseover='" + this.me + ".rollOver(0);'";
                html += " onmouseout='" + this.me + ".rollOut(0);'";
            }
            html += " ondragstart='return false;' onselectstart='return false;' onDrag='return false;'";
            html += " style='cursor: pointer; " + floater + "' "
            html += " id='" + this.me + "UpBtn'";
            html += " src='" + this.scrollUpImg + "' alt='' border='0' />";
        } else {
            html="";
        }
        
        // Track & scroller
        if(this.scrollerImg) {
            bw = (this.scrollerFixedWidth) ? this.scrollerFixedWidth : this.scrollBtnWidth;
            bh = (this.scrollerFixedHeight) ? this.scrollerFixedHeight : this.scrollBtnHeight;
            html += "<div id='" + this.me.undotted() + "TrackInner' style='height:" + this.scrollTrackHeight + "px; width:" + this.scrollTrackWidth + "px; position:relative; cursor: pointer; background-image:url(" + this.scrollerBGImg + "); " + floater + "' onmousedown='" + this.me + ".scrollToMouse(this." + offsetD + ")'>";
            html += "<div id='" + this.me.undotted() + "Scroller' onmousedown='" + this.me + ".beginDrag()' style='position:absolute;'>";
            html += "<img src='" + this.scrollerImg + "' alt='' border='0' width=" + bw + " height=" + bh + " id='" + this.me.undotted() + "ScrollerImg' ";
            html += "ondragstart='return false;' onselectstart='return false;' onDrag='return false;' onmousedown='return false;' "
            html += "style='cursor: pointer';' /><br />";
            html += "</div></div>";
        } else {
            this.scrollTrackUp.innerHTML = html;
            html="";
        }
                
        // Down/Right arrow
        if(this.scrollDownImg ) {
            html +="<img width=" + this.scrollBtnWidth + " height=" + this.scrollBtnHeight + " ondblclick='" + this.me + ".scrollDown();' onmousedown='" + this.me + ".scrollDown(); return false;' onmouseup='" + this.me + ".stopScroll();' src='" + this.scrollDownImg + "' alt='' border='0' style='cursor: pointer; " + floater + "' ";
            html+= "id='" + this.me.undotted() + "DownBtn' ";
            if(this.scrollDownImgOv || this.scrollOver) {
                html +="onmouseover='" + this.me + ".rollOver(1);' ";
                html +="onmouseout='" + this.me + ".rollOut(1);' ";
            }            
            html +="ondragstart='return false;' onselectstart='return false;' onDrag='return false;' /><br />";
        }
        
        // Scroller
	    if(this.scrollerImg) {
		    this.scrollTrack.innerHTML = html;
	        this.scroller = document.getElementById(this.scroller);
	        this.scrollTrackInner = document.getElementById(this.me.undotted() + "TrackInner");
		    this.scrollerImg = document.getElementById(this.me.undotted() + "ScrollerImg");
		    this.scroller.onselectstart = function() { return false; }
        } else {
            this.scrollTrackDown.innerHTML = html;
        }
        if(this.scrollUpImg) this.scrollUpBtn = document.getElementById(this.me.undotted() + "UpBtn");
        if(this.scrollDownImg) this.scrollDownBtn = document.getElementById(this.me.undotted() + "DownBtn");

        // Add mouseUps (EventManager)
        mouseUpArr.push(this.me + ".stopScroll();");
        this.checkDisabledNeeded = (this.disabledUpImg || this.disabledDownImg || this.scrollerBGDisImg) ? true : false;
        this.refresh();
	};

	scrollerObj.prototype.rollOver = function(which) {
	    if(this.scrollUpImgOv || this.scrollDownImgOv){
	        if(which) {
    	        if(this.scrollDownState) this.scrollDownBtn.src = this.scrollDownImgOv;
            } else {
                if(this.scrollUpState) this.scrollUpBtn.src = this.scrollUpImgOv;
            }
        }    	    
        if(this.scrollOver){ 
            (which) ? this.scrollDown() : this.scrollUp(); 
        }
	};

	scrollerObj.prototype.rollOut = function(which) {
        if(which) {
            if(this.scrollDownState) this.scrollDownBtn.src = this.scrollDownImg;
        } else {
            if(this.scrollUpState) this.scrollUpBtn.src = this.scrollUpImg;
        }
        this.stopScroll();
	};
	
	scrollerObj.prototype.scrollUp = function() {
		// Inititate Scroll down or right
		if((!this.scrollStopInitiated || !this.scrollStep) && (!this.scrolling)){
		    this.scrolling = true;
		    this.scrollIt(-1);
        }
	};

	scrollerObj.prototype.scrollDown = function() {
		// Inititate Scroll up or left
		if((!this.scrollStopInitiated || !this.scrollStep) && (!this.scrolling)){
		    this.scrolling = true;
		    this.scrollIt(1);
		}
	};
	
	scrollerObj.prototype.scrollIt = function(sdirection) {
		// Scroll the content
		if(this.scrolling) {
			speed = this.scrollSpeed * sdirection;
			if(this.direction) {
			    if((speed > 0 && this.scrollContent.scrollLeft + this.scrollContentWidth < this.scrollContent.scrollWidth) || (speed < 0 && this.scrollContent.scrollLeft > 0)){
                    this.scrollContent.scrollLeft += speed;
                }
            } else {
			    if((speed > 0 && this.scrollContent.scrollTop + this.scrollContentHeight < this.scrollContent.scrollHeight) || (speed < 0 && this.scrollContent.scrollTop > 0)) {
                    this.scrollContent.scrollTop += speed;
                }
            }
            this.quickRefresh();
            if(this.scrollStopInitiated) this.stopScroll();
            setTimeout(this.me + ".scrollIt(" + sdirection + ")", 1);
		}
	};
	
	scrollerObj.prototype.stopScroll = function() {
	    // Stop scrolling
	    if(this.scrolling || this.draggingScroll ) {
	        if(!this.scrollStep){
        	    this.draggingScroll = false;
        	    this.scrolling = false;
            } else {
                this.scrollStopInitiated = true;
                t = (this.direction) ? this.scrollContent.scrollLeft / this.scrollStep : this.scrollContent.scrollTop / this.scrollStep;
                if(t == Math.round(t)) {
        	        this.draggingScroll = false;
                    this.scrolling = false;
                    this.scrollStopInitiated = false;
                }
            }
        }
    }
	
	scrollerObj.prototype.beginDrag = function() {
		// Start dragging the scroller
		this.scrollerInitialPos = (this.direction) ? mouseX - this.scroller.style.left.removePX() : mouseY - this.scroller.style.top.removePX();
		this.draggingScroll = true;
		this.dragMe();
	};
	
	scrollerObj.prototype.dragMe = function() {
	    // Drag the scroller
        (this.direction) ? this.refreshScrollerPosition(mouseX - this.scrollerInitialPos) : this.refreshScrollerPosition(mouseY - this.scrollerInitialPos);
        this.checkDisabled(); 
		if(this.draggingScroll) setTimeout(this.me + ".dragMe()", 1);
	};

    scrollerObj.prototype.refreshScrollerSize = function() {
        if(this.direction) {
            this.scrollerSize = (this.scrollerFixedWidth) ? this.scrollerFixedWidth : (this.scrollContentWidth / this.scrollContent.scrollWidth) * this.scrollTrackWidth;
            if(this.scrollContentWidth > this.scrollContent.scrollWidth) {this.scrollerSize = 2; }
            if(this.scrollerSize < 2) this.scrollerSize = 2;
            this.scrollerSize = Math.round(this.scrollerSize);
            this.scrollerImg.style.width = this.scrollerSize + "px";
        } else {
            this.scrollerSize = (this.scrollerFixedHeight) ? this.scrollerFixedHeight : (this.scrollContentHeight / this.scrollContent.scrollHeight) * this.scrollTrackHeight;
            if(this.scrollContentHeight > this.scrollContent.scrollHeight) {this.scrollerSize = 2; }
            if(this.scrollerSize < 2) this.scrollerSize = 2;
            this.scrollerSize = Math.round(this.scrollerSize);
            this.scrollerImg.style.height = this.scrollerSize + "px";
        }
    };
    
    scrollerObj.prototype.refreshScrollMax = function() {
        this.scrollContentMax = (this.direction) ? this.scrollContent.scrollWidth - this.scrollContent.style.width.removePX() : this.scrollContent.scrollHeight - this.scrollContent.style.height.removePX();
        if(this.scrollContentMax < 0) { this.scrollContentMax = 0; }
        this.scrollMax = (this.direction) ? this.scrollTrackWidth : this.scrollTrackHeight;
        this.scrollMax -= this.scrollerSize;
        this.scrollMax = Math.round(this.scrollMax);
    };

    scrollerObj.prototype.getScrollerPosition = function() {
        if(this.scrollContentMax > 0) {
            return (this.direction) ? (this.scrollContent.scrollLeft / this.scrollContentMax) * this.scrollMax : (this.scrollContent.scrollTop / this.scrollContentMax) * this.scrollMax;
        } else { return 0; }
    }
    
    scrollerObj.prototype.getScrollContentPosition = function() {
        return (this.scrollerPosition / this.scrollMax) * this.scrollContentMax;
    }

    scrollerObj.prototype.refreshScrollerPosition = function(position) {
        this.scrollerPosition = (position) ? position : this.getScrollerPosition();
        if(this.scrollerPosition < 0) this.scrollerPosition = 0;
        if(this.scrollerPosition > this.scrollMax) this.scrollerPosition = this.scrollMax;
        if(this.scrollStep && (this.draggingScroll || !this.scrolling)) {
            scrollFactor = this.scrollMax / (this.scrollContentMax / this.scrollStep);
            if(this.scrollerPosition > 0) {
                this.scrollerPosition = Math.round((this.scrollerPosition / scrollFactor)) * scrollFactor;
            }
        }
        if(this.direction){
            this.scroller.style.left = this.scrollerPosition + "px";
            this.scrollContent.scrollLeft = this.getScrollContentPosition();
        } else {
            this.scroller.style.top = this.scrollerPosition + "px";
            this.scrollContent.scrollTop = this.getScrollContentPosition();
        }
    };

	scrollerObj.prototype.refreshScroller = function(position) {
	    // Refresh scroller position / size
	    if(this.scroller){
	        if(!this.scrollerFixedHeight || this.scrollerSize < 1) this.refreshScrollerSize();
	        this.refreshScrollMax();
            this.refreshScrollerPosition(position);
        }
	}

	scrollerObj.prototype.scrollToMouse = function(p) {
	    // Scroll tracker to mouse position (<p>)
	    if(!this.draggingScroll) {
	        this.draggingScroll = true;
		    (this.direction) ? this.refreshScroller(mouseX - p) : this.refreshScroller(mouseY - p);
        }
	};

	scrollerObj.prototype.btnState = function(which, state) {
	    // Enable/disable the buttons
        if(which) {
        	this.scrollDownBtn.src = (state) ? this.scrollDownImg : this.disabledDownImg;
            this.scrollDownState = (state) ? 1 : null;
            this.scrollDownBtn.style.cursor = (state) ? "pointer" : "none";
        } else {
            this.scrollUpBtn.src = (state) ? this.scrollUpImg : this.disabledUpImg;
	        this.scrollUpState = (state) ? 1 : null;
	        this.scrollUpBtn.style.cursor = (state) ? "pointer" : "none";
        }
	}

	scrollerObj.prototype.checkDisabled = function() {
    	// Check wether to disable arrows
        if(this.checkDisabledNeeded) {
            this.scrollerPosition = this.getScrollerPosition();
            if(this.scrollerPosition == 0 && this.scrollUpState) this.btnState(0,0);
            if(this.scrollerPosition != 0 && !this.scrollUpState) this.btnState(0,1);
            if((this.scrollerPosition < this.scrollMax) && !this.scrollDownState) this.btnState(1,1);
            if(this.direction) {
                if((this.scrollerPosition >= this.scrollMax || this.scrollContent.scrollWidth < this.scrollContent.style.width.removePX()) && this.scrollDownState) this.btnState(1,0);
            } else {
                if((this.scrollerPosition >= this.scrollMax || this.scrollContent.scrollHeight < this.scrollContent.style.height.removePX()) && this.scrollDownState) this.btnState(1,0);
            }
		}	
	}

	scrollerObj.prototype.stateToggle = function(on) {
	    // Toggles scroller & track on / off
        this.scroller.style.display = (on) ? "block" : "none";
        this.disabled = on;
        if(this.scrollerBGDisImg) this.scrollTrackInner.style.backgroundImage = (on) ? "url('" + this.scrollerBGImg + "')" : "url('" + this.scrollerBGDisImg + "')";
        if(this.trackHideOnDisabled) this.scrollTrack.style.display = (on) ? "block" : "none";
	}


    scrollerObj.prototype.refreshStates = function(quick) {
		if(this.scrollerImg) {
	        if(this.direction) {
		        if (this.scrollContentWidth < this.scrollContent.scrollWidth && this.scroller.style.display != "block") this.stateToggle(true);
		        if (this.scrollContentWidth >= this.scrollContent.scrollWidth && this.scroller.style.display != "none") this.stateToggle(false);
            } else {
		        if(this.scrollContentHeight < this.scrollContent.scrollHeight && !this.disabled) this.stateToggle(true);
		        if(this.scrollContentHeight >= this.scrollContent.scrollHeight && this.disabled) this.stateToggle(false);
            }
            (quick) ? this.refreshScrollerPosition() : this.refreshScroller();
		}
    }

	scrollerObj.prototype.quickRefresh = function() {
    	this.refreshStates(1)
	    this.checkDisabled();
    }

	scrollerObj.prototype.refresh = function() {
        this.scrollContentHeight = parseInt(this.scrollContent.style.height.removePX());
	    this.scrollContentWidth = parseInt(this.scrollContent.style.width.removePX());
    	this.scrollTrackHeight = this.scrollContent.style.height.removePX(); 
        this.scrollTrackWidth = this.scrollContent.style.width.removePX();

	    this.refreshScrollMax();
    	this.refreshStates(0);
	    this.checkDisabled();
	};

    // Prototype duplicate from SidleePrototypes.js
    // Duplicated here to avoid having to include SidleePrototypes.js just for this one functionality
	String.prototype.removePX = function() {
		return this.substr(0, this.lastIndexOf('px'));
	};
	
    String.prototype.undotted = function() {
        
		r = this.replace('.','');
		r = r.replace('[','');
		r = r.replace(']','');

		return r;
		
	};