/*  Scrollable div prototype.js 1.4.0 extention, version 0.0.2
 *  (c) 2006 OXYS.net - Julien Bidoret, David Charbonnier <contact@oxys.net>
 *
 *  OXScroll is freely distributable under the terms of an MIT-style license.
 *
/*--------------------------------------------------------------------------*/

var OXScroll = Class.create();
OXScroll.prototype = {

	//Configure those values
	wellMouseSpeed: 10,
	buttonOverSpeed: 0, // 0 to disable
	buttonDownSpeed: 8,
	menuLinkMouseEvent: 'down', // down, over, up
	spinner: "<img src='img/spinner.gif' />", // Display while loading data
	displayButtons: true,
	onlyDisableScroll: false,
	baseCssClass: 'OXScroll',

	//Do not modify after this

	pos_y:0,
	slider_mouse_down:false,
	slider_mouse_over:false,

	initialize: function(scroll_div, base_css_name, param_Defilement) {

	  	//Scroll div name
	  	this.scroll_div=scroll_div;
	  	this.baseCssClass = base_css_name;

	  	//Scroll element
	  	this.scroll=$(scroll_div);

	  	if (param_Defilement != null) {
			this.isDefilement = true;
			this.paramDefilement = param_Defilement;
	  	}

	  	if(!this.scroll) {
				alert('Scroll div not found');
		} else {
			//Define styles
	  		this.scroll.style.overflow='hidden';
	  		//Used for links
			this.scroll.object=this;

			//Create new html structure to support scroll
			this.scroll.innerHTML="<div id='"+this.scroll_div+"_container' class='" +  this.baseCssClass + "_container'>"+this.scroll.innerHTML+"</div>";
			this.scroll_container = $(this.scroll_div+"_container");

			html ="<div id='"+this.scroll_div+"_scroller' style='visibility: hidden; display: none;' class='" + this.baseCssClass + "_scroller' onselectstart='return false'>\n";
			html+="	<div id='"+this.scroll_div+"_up_button' class='" + this.baseCssClass + "_up_button'>\n";
			html+="		<a href='#up' onselectstart='return false'>up</a>\n";
			html+="	</div>\n";
			html+="	<div id='"+this.scroll_div+"_slider_container' onselectstart='return false' class='" + this.baseCssClass + "_slider_container'>\n";
			html+="		<div id='"+this.scroll_div+"_slider' onselectstart='return false' class='" + this.baseCssClass + "_slider'>\n";
			html+="			<div id='"+this.scroll_div+"_slider_top' onselectstart='return false' class='" + this.baseCssClass + "_slider_top'>&nbsp;</div>\n";
			html+="			<div id='"+this.scroll_div+"_slider_body' onselectstart='return false' class='" + this.baseCssClass + "_slider_body'>scroll</div>\n";
			html+="			<div id='"+this.scroll_div+"_slider_bottom' onselectstart='return false' class='" + this.baseCssClass + "_slider_bottom'>&nbsp;</div>\n";
			html+="		</div>\n";
			html+="	</div>\n";
			html+="	<div id='"+this.scroll_div+"_down_button' class='" + this.baseCssClass + "_down_button'>\n";
			html+="		<a href='#down' onselectstart='return false'>down</a>\n";
			html+="	</div>\n";
			html+="</div>\n";

			new Insertion.Before(this.scroll_container,html);

			//Register divs as object properties
			this.scroller=$(scroll_div+"_scroller");
			this.up_button=$(scroll_div+"_up_button");
			this.down_button=$(scroll_div+"_down_button");
			this.slider_container=$(scroll_div+"_slider_container");
			this.slider=$(scroll_div+"_slider");
			this.slider_top=$(scroll_div+"_slider_top");
			this.slider_body=$(scroll_div+"_slider_body");
			this.slider_bottom=$(scroll_div+"_slider_bottom");

			this.scroller.style.display='block';

			ScrollContainerOffset=Position.cumulativeOffset(this.scroll_container);

			this.scroller.style.height=(Element.getHeight(this.scroll)+2)+'px';
			this.scroller.style.top=(ScrollContainerOffset[1]-1)+'px';
			this.view_height=Element.getHeight(this.scroll);

			this.scroller.style.display='none';

			//Register events
			Event.observe(document, 'mouseup', this.WindowMouseUp.bindAsEventListener(this), false);
			Event.observe(this.scroll,'mousewheel',this.WheelEvent.bind(this));

			this.slider.onmouseover = this.SliderEvent.bindAsEventListener(this);
			this.slider.onmouseout  = this.SliderEvent.bindAsEventListener(this);
			this.slider.onmousedown = this.SliderEvent.bindAsEventListener(this);
			this.slider.onmouseup   = this.SliderEvent.bindAsEventListener(this);

   			this.up_button.onmouseover = this.ButtonUpEvent.bindAsEventListener(this);
			this.up_button.onmouseout  = this.ButtonUpEvent.bindAsEventListener(this);
			this.up_button.onmousedown = this.ButtonUpEvent.bindAsEventListener(this);
			this.up_button.onmouseup   = this.ButtonUpEvent.bindAsEventListener(this);

   			this.down_button.onmouseover = this.ButtonDownEvent.bindAsEventListener(this);
			this.down_button.onmouseout  = this.ButtonDownEvent.bindAsEventListener(this);
			this.down_button.onmousedown = this.ButtonDownEvent.bindAsEventListener(this);
			this.down_button.onmouseup   = this.ButtonDownEvent.bindAsEventListener(this);

   			this.DragSliderObserver=this.DragSlider.bindAsEventListener(this);

			this.slider_container.onmouseup   = this.ScrollBarEvent.bindAsEventListener(this);
			this.slider_container.onmousedown = this.ScrollBarEvent.bindAsEventListener(this);

			this.scroll.onmouseover = this.ContainerEvent.bindAsEventListener(this);
			this.scroll.onmouseout = this.ContainerEvent.bindAsEventListener(this);

			this.InitLoad();

		}
	},

		InitLoad : function () {
			this.SetScrollHeight();
			this.FixScrollPos(0,false);
			if (this.isDefilement) {
				this.periodicalDefilement = new PeriodicalExecuter(this.StartMovingDefilement.bind(this), this.paramDefilement["pause"]);
			}
		},

		//Defilement
		isDefilement: false,
		periodicalDefilement: null,
		sensDefilement: 'goDown',
		paramDefilement: null,
		isPauseDefilement: false,
		timerMoveDefilement: null,
		pxParcouru: 0,
		pxMouvementReferenceToDo: 0,
		pxMouvementToDo: 0,
		pxTropParcouru: 0,
		sensDefilement: 1,
		DoMovingDefilement: function() {
			rapport = Element.getHeight(this.scroll_container) / Element.getHeight(this.scroll);
			this.pxMouvementReferenceToDo = (this.max_height / rapport);
			this.pxMouvementToDo = this.pxMouvementReferenceToDo - this.pxTropParcouru;
			fq_timer = 0.05;
			pas_px = 1;
			if (this.timerMoveDefilement == null) {
				//premier lancement
				this.timerMoveDefilement = new PeriodicalExecuter(this.DoMovingDefilement.bind(this), fq_timer);
				this.pxParcouru = 0;
			} else {
				if (this.pxParcouru >= this.pxMouvementToDo) {
					//Distance trop parcourue
					this.pxTropParcouru += this.pxParcouru - this.pxMouvementReferenceToDo;
					this.timerMoveDefilement.stop();
					this.timerMoveDefilement = null;
				} else {
					this.pxParcouru += pas_px;
					type_butee = this.FixScrollPos(pas_px * this.sensDefilement, true);
					if (type_butee != '') {
						this.timerMoveDefilement.stop();
						this.timerMoveDefilement = null;
						this.sensDefilement = -this.sensDefilement; //On inverse le sens
						this.periodicalDefilement.stop();
						//On init à nouveau
						this.periodicalDefilement = new PeriodicalExecuter(this.StartMovingDefilement.bind(this), this.paramDefilement["pause"]);
					}
				}
			}
		},
		StartMovingDefilement: function() {
			if (this.periodicalDefilement != null) {
				this.periodicalDefilement.stop();
			}
			if (this.paramDefilement['isPanel'] == 1 && this.isPauseDefilement) {
   				this.FixScrollPos(0, false);
   				this.sensDefilement = 1;
   				this.isPauseDefilement = false;
   			}
			//On lance le défilement
			this.DoMovingDefilement();
			//On l'init à nouveau pour la prochaine fois
			this.periodicalDefilement = new PeriodicalExecuter(this.StartMovingDefilement.bind(this), this.paramDefilement["pause"] + this.paramDefilement["fq"]);
		},

		WheelEvent: function(e) {
			//Pour fixer le pseudo scroll du div
			this.FixScrollPos(Event.wheel(e)*-this.wellMouseSpeed,true);
		},

		ScrollBarEvent: function(evt) {
		   	if(evt.type == 'mousedown') {
		   		if(Event.pointerY(evt)<this.pos_y+this.max_top) {
		   			diff=(Event.pointerY(evt)-(this.pos_y+this.max_top))/2;
		   			if (diff>-10) diff=-10;
		   			this.FixScrollPos(diff,true);
		   		}
		   		if(Event.pointerY(evt)>this.pos_y+this.max_top+this.slider_height+Element.getHeight(this.slider_top)+Element.getHeight(this.slider_bottom)) {
		   			diff=(Event.pointerY(evt)-(this.pos_y+this.max_top+this.slider_height+Element.getHeight(this.slider_top)+Element.getHeight(this.slider_bottom)))/2;
		   			if (diff<10) diff=10;
		   			this.FixScrollPos(diff,true);
		   		}
		   		return false;
		  	}
	   },

	   ContainerEvent: function(evt) {
	   		if(evt.type == 'mouseover' && this.isDefilement) {
	   			if (this.timerMoveDefilement) {
	   				this.timerMoveDefilement.stop();
	   			}
	   			if (this.periodicalDefilement) {
	   				this.periodicalDefilement.stop();
	   			}
	   			this.isPauseDefilement = true;
	   		} else if (evt.type == 'mouseout' && this.isDefilement) {
		   		this.periodicalDefilement = new PeriodicalExecuter(this.StartMovingDefilement.bind(this), this.paramDefilement["pause"]);
	   		}
	   },

		 Slide: function() {
		 	sign=(this.direction=='down')?1:-1;
		 	speed=(this.slider.timer.action=='over')?this.buttonOverSpeed:this.buttonDownSpeed;
		 	this.FixScrollPos(speed*sign,true);
		 },

		 ButtonUpEvent: function(evt) {
		 	this.direction='up';
		 	this.ButtonEvent(evt);
		 },

	   ButtonDownEvent: function(evt) {
		 	this.direction='down';
		 	this.ButtonEvent(evt);
		 },

	   ButtonEvent: function(evt) {
	   	if(evt.type == 'mousedown') {
	   		if(this.slider.timer) {
	   			this.slider.timer.currentlyExecuting=false;
	   			this.slider.timer.action='down';
	   			this.slider.timer.direction=this.direction;
	  		} else {
	  			this.slider.timer = new PeriodicalExecuter(this.Slide.bindAsEventListener(this),0.1);
	  			this.slider.timer.action='down';
	  			this.slider.timer.direction=this.direction;
	  		}
	   		return false; //Disable Select
	  	} else if (evt.type == 'mouseover') {
	  			if(this.slider.timer) {
		  			this.slider.timer.currentlyExecuting=false;
	  				this.slider.timer.action='over';
	  				this.slider.timer.direction=this.direction;
		  		} else {
	  				this.slider.timer = new PeriodicalExecuter(this.Slide.bindAsEventListener(this),0.1);
		  			this.slider.timer.action='over';
		  			this.slider.timer.direction=this.direction;
	  			}
	  	} else if (evt.type == 'mouseout') {
	  		this.slider.timer.currentlyExecuting=true;
	  	} else if (evt.type == 'mouseup') {
	  		if(this.slider.timer&&!this.slider.timer.currentlyExecuting)
	  			this.slider.timer.action='over';
	  	}
	   },


	   SliderEvent: function(evt) {
	   	if(evt.type == 'mousedown') {
	   		this.slider_mouse_down=true;
	   		this.FixSliderClass();
	   		$offsets=Position.cumulativeOffset(this.slider);
	   		this.slider.offset_y_start=Event.pointerY(evt)-$offsets[1];
	   		Event.observe(document, 'mousemove', this.DragSliderObserver, false);
	   		return false; //Disable select
		  } else if(evt.type == 'mouseup') {
		  	this.slider_mouse_down=false;
		  	this.FixSliderClass();
	   		Event.stopObserving(document, 'mousemove', this.DragSliderObserver, false);
	   		return false;
			} else if(evt.type == 'mouseover') {
				this.slider_mouse_over=true;
				this.FixSliderClass();
			} else if(evt.type == 'mouseout') {
				this.slider_mouse_over=false;
				this.FixSliderClass();
			}
	   },
	   FixSliderClass:function() {
	   	if(this.slider_mouse_down) {
		   	this.slider.className= this.baseCssClass + '_slider ' +  this.baseCssClass + '_slider_down';
		  } else if(this.slider_mouse_over) {
			 	this.slider.className=  this.baseCssClass + '_slider ' +  this.baseCssClass + '_slider_over';
		  } else {
			 	this.slider.className=  this.baseCssClass + '_slider';
		  }
	   },

	   DragSlider: function(evt) {
	   	scrollToPos=(Event.pointerY(evt)-this.slider.offset_y_start-this.max_top);
			this.FixScrollPos(scrollToPos,false);
		 },


	FixScrollPos: function (scrollToPos,relative/*,effect*/) {
		if(relative)
			scrollToPos=this.pos_y+scrollToPos;
		scrollToPos=Math.round(scrollToPos);
		type_butee = '';
		if(scrollToPos>this.max_height-this.slider_height) {
			scrollToPos=this.max_height-this.slider_height;
			type_butee = 'bottom';
		}
		if(scrollToPos<0) {
			scrollToPos=0;
			type_butee = 'top';
		}
		position=Math.round((this.content_height/this.max_height)*scrollToPos);
		if(position>this.content_height-this.view_height)
			position=this.content_height-this.view_height
		if(position<0) position=0;
		this.position=position;

		//On ne bouge pas le container si c'est l'effet qui le fait
		this.SetViewportLocation(true);
		this.scroll_container.style.top=-position+'px';
		this.pos_y=scrollToPos;
		this.slider.style.top=this.pos_y+'px';
		return type_butee;
	},

	ScrollViewportLocation: function() {
		this.scroll_container.currentpos-=((this.scroll_container.currentpos-this.position)/4);
		this.scroll_container.style.top=-this.scroll_container.currentpos+'px';
		this.pos_y=Math.round(this.scroll_container.currentpos/(this.content_height/this.max_height));
		this.slider.style.top=this.pos_y+'px';
		if(this.scroll_container.style.top==this.position) this.scroll_container.timer.currentlyExecuting=true;
	},

	SetViewportLocation: function(immediate) {
		if(this.slider.style.visibility!='hidden') {
			if(this.position>this.content_height-this.view_height)
				this.position=this.content_height-this.view_height
			if(immediate) {
				if(this.scroll_container.timer) {
					this.scroll_container.timer.currentlyExecuting=true;
   				}
				this.scroll_container.style.top=-this.position+'px';
				this.scroll_container.currentpos=this.position;
			} else {
				this.scroll_container.position=this.position;
				if(!this.scroll_container.timer||this.scroll_container.timer.currentlyExecuting) {
	  				this.scroll_container.timer = new PeriodicalExecuter(this.ScrollViewportLocation.bind(this),0.01);
	  				this.scroll_container.timer.currentlyExecuting=false;
  				}
			}
		} else {
			this.position=0;
		}
	},

	SetScrollHeight: function() {
		if(this.displayButtons) {
			this.up_button.style.display='block';
			this.down_button.style.display='block';
		} else {
			this.up_button.style.display='none';
			this.down_button.style.display='none';
		}
		this.content_height=Element.getDimensions(this.scroll_container).height;
		if(this.view_height>this.content_height) {
			if(!this.onlyDisableScroll) {
				this.scroller.style.visibility='hidden';
				this.scroller.style.display='none';
			}
			this.slider.style.visibility='hidden';
		} else {

			this.scroller.style.display='block';
			this.slider.style.visibility='visible';
			ScrollContainerOffset=Position.cumulativeOffset(this.scroll_container);

			this.slider_container.style.height=(Element.getHeight(this.scroll)-Element.getHeight(this.up_button)-Element.getHeight(this.down_button))+'px';
			this.max_top    =ScrollContainerOffset[1]+Element.getHeight(this.up_button)+2;
			this.max_bottom =ScrollContainerOffset[1]+Element.getHeight(this.scroll)-Element.getHeight(this.down_button);
			this.max_height =this.max_bottom-this.max_top-Element.getHeight(this.slider_top)-Element.getHeight(this.slider_bottom)+2;


			this.scroll_container.style.width=(Element.getDimensions(this.scroll).width-Element.getDimensions(this.slider).width-3)+'px';
			this.content_height=Element.getDimensions(this.scroll_container).height;

			if(this.content_height>0) {
				this.slider_height=Math.round((this.view_height/this.content_height)*this.max_height);
				if(this.slider_height<1) this.slider_height=1;
				this.slider_body.style.height=this.slider_height+'px';
			}
			this.scroll_container.style.width=(Element.getDimensions(this.scroll).width-Element.getDimensions(this.slider).width-3)+'px';
			this.scroller.style.visibility='visible';
		}
	},
	WindowMouseUp: function (evt) {
		this.slider_mouse_down=false;
	  	this.FixSliderClass();
		Event.stopObserving(document, 'mousemove', this.DragSliderObserver, false);
	}
}