
	// foamScroll v00
	// Ailantd & Additive Works 
	// www.ailantd.com & www.additiveworks.com

	// Usage is automatic
	// You can use initScrollbox() function to reinitialize after changes in html document.
	//------------------------------------------------------------

	// CFoamScroll()
	//------------------------------------------------------------
	function CFoamScroll( oMyDiv )
	{
		// Default css style values if no Scrollbox css linked on page

		//FILTER
		if ( oMyDiv.getAttribute("data-filter") )
			this.filter = parseFloat( oMyDiv.getAttribute("data-filter") ) ;	
		else
			this.filter = 0.2 ;
		
		//JUMP	
		if ( oMyDiv.getAttribute("data-percentjump") )
		{	
			var data = oMyDiv.getAttribute("data-percentjump") ;
			var jumpdata = data.substring( data.length-1 , data.length ) ;
			if( jumpdata == '%' )
			{
				this.jumpdata = 1 ;
				this.jumpvalue = parseInt( data.substring( 0 , data.length-1 ) ) ;
			}
			else
			{
				// Puede haber pérdidas de resolucion en este caso. Preferiblemente no usar px.
				this.jumpdata = 0 ;
				this.jumpvalue = parseInt( data.substring( 0 , data.length-2 ) ) ;
			}
		}
		else
		{
			this.jumpdata = 1 ;
			this.jumpvalue = 25 ;
		}
		
		// DIV PROPERTIES
		//
		this.div = oMyDiv ;							// base div
		this.Mask ;									// mask
		this.Content ;								// content

		this.Barr ;									// barr
		this.Handle ;								// handle

		this.PressUp ;								// div up by press
		this.PressDown ;							// div down by press

		this.ClickUp ;								// div up by click
		this.ClickDown ;							// div down by clik
		
		// For handle Drag
		//
		this.draging = false ;						// Gestion del drag
		
		this.timer ;
		this.bReady = false ;						// Fucking IExplorer trick
		var that = this ;							// Useful Callback Trick
		
		//------------------------------------------
		// METHODS
		//------------------------------------------

		// CREATE
		// Create new Items for the Scrollbox
		//-------------------------------------------------	
		this.Create = function()
		{
			// CLEAR DIV
			// TODO: BEST CLEARING METHOD
			var sInner = this.div.innerHTML ; 
			this.div.style.overflow = "visible" ;
			this.div.style.display = "block" ;
			this.div.innerHTML = "" ;			
			
			// MASK
			this.Mask = document.createElement( "div" ) ;
			this.Mask.className = "FoamScroll-Mask" ;
			this.Mask.style.position = "absolute" ;
			this.Mask.style.top = "0px" ;
			this.Mask.style.left = "0px" ;
			this.Mask.style.width = "100%" ;
			this.Mask.style.height = "100%" ;
			this.Mask.style.overflow = "hidden" ;
			this.div.appendChild( this.Mask ) ;
			
			// CONTENT
			this.Content = document.createElement( "div" ) ;
			this.Content.className = "FoamScroll-Content" ;
			this.Content.style.position = "absolute" ;
			this.Content.style.top = "0px" ;
			this.Content.style.left = "0px" ;
			this.Content.style.width = "100%" ;
			//this.Content.style.height = "895px" ;
			this.Content.innerHTML = sInner ;
			this.Mask.appendChild( this.Content ) ;

			// BARR
			this.Barr = document.createElement( "div" ) ;
			this.Barr.className = "FoamScroll-Barr" ;
			
			this.Barr.style.overflow = "hidden" ;
			this.Barr.style.height = "100%" ;
			this.div.appendChild( this.Barr ) ;		

			// BARR HANDLE
			this.Handle = document.createElement( "div" ) ;
			this.Handle.className = "FoamScroll-Handle" ;
			this.Barr.appendChild( this.Handle ) ;
			

			// UP / DOWN PRESS
			//---------------------
			this.PressUp = document.createElement( "div" ) ;
			this.PressUp.className = "FoamScroll-UpPress" ;
			this.div.appendChild( this.PressUp ) ;
			
			this.PressDown = document.createElement( "div" ) ;
			this.PressDown.className = "FoamScroll-DownPress" ;
			this.div.appendChild( this.PressDown ) ;
			
			
			// UP / DOWN CLICK
			this.ClickUp = document.createElement( "div" ) ;
			this.ClickUp.className = "FoamScroll-UpClick" ;
			this.div.appendChild( this.ClickUp ) ;
			
			this.ClickDown = document.createElement( "div" ) ;
			this.ClickDown.className = "FoamScroll-DownClick" ;
			this.div.appendChild( this.ClickDown ) ;
			
			
			// EVENTS
			//
			
			// UP / DOWN PRESS
			//---------------------			
			this.PressUp.onmousedown = this.OnStartPressUp ;
			this.PressDown.onmousedown = this.OnStartPressDown ;

			// UP / DOWN CLICK
			//---------------------			
			this.ClickUp.onclick = this.OnClickUp ;
			this.ClickDown.onclick = this.OnClickDown ;

			// BARR
			//---------------------			
			//this.Barr.onclick = this.OnClickBarr ;

			// HANDLE
			//---------------------			
			this.Handle.onmousedown = this.StartHandleDrag ;
			
			// MOUSE WHEEL	
			//---------------------			
			// IE/Opera/Chrome
			this.div.onmousewheel = that.ScrollWheel ;
			if ( this.div.addEventListener )
			{
				// DOMMouseScroll is for mozilla.
				this.div.addEventListener( 'DOMMouseScroll' , that.ScrollWheel , false ) ;
			}
			
			//document.body.onmouseup = this.BodyMouseUp ;
			window.onresize = this.Reset ;
			
			this.bReady = true ;
			
			// RECONFIGURE
			this.Reset();
			
		}


		// RESET
		// Reset Scrollbox elements
		//-------------------------------------------------	
		this.Reset = function( e )
		{
			if( !that.bReady )
				return ;

			// SETTING PARMETERS
			that.bPressUp = false ;
			that.bPressDown = false  ; 
			that.bFiltering = false ;

			// HANDLE HEIGHT
			var nContentH = that.Content.offsetHeight ;
			if ( nContentH == 0 )
				nContentH = 1 ;

			var HandleHeight = that.div.offsetHeight * that.Barr.offsetHeight / nContentH ;
			
			// OCULTAR LA BARRA SI NO ES NECESARIA
			if( HandleHeight >= that.Barr.offsetHeight )
				that.Barr.style.display = "none";
			else
				that.Barr.style.display = "block";
				
			that.Handle.style.height = HandleHeight + "px" ;
			
			// HANDLE TOP
			that.Handle.style.top = -( that.Content.offsetTop * that.Barr.offsetHeight / nContentH ) + "px" ;
			that.HandleDisplace( 0 ) ;
			
			that.scaleFactor = that.Content.offsetHeight / that.Barr.offsetHeight ;
			
			if( !e ) that.Content.T = that.Content.nextContentT = that.Content.offsetTop ;

			// CALCULATING JUMP
			if( that.jumpdata )
			{
				that.jump = that.jumpvalue * that.Handle.offsetHeight  / 100 ;
			}else{
				that.jump = that.jumpvalue / that.scaleFactor ;
				//alert( that.jump ) ;
			}			
		}


		// BODY MOUSE UP
		// Ends all scrolls
		//-------------------------------------------------	
		this.BodyMouseUp = function(e)
		{
		}				


		// CLEAR TIMER
		// 
		//-------------------------------------------------	
		this.CheckTimer = function()
		{
			//alert( this.bPressUp +" - "+ this.bPressDown +" - "+ this.bFiltering );
			if( !this.bPressUp && !this.bPressDown && !this.bFiltering )
			{
				clearInterval( that.timer ) ;
				if( that.oldOnmouseup )
				{
					window.onmouseup = that.oldOnmouseup ;
					that.oldOnmouseup = null ;
				}
				this.timer = null ;			
			}else{
				if( !this.timer )
					this.timer = setInterval( function(){ that.OnTimer() ; } , 12 ) ;				
			}
		}

		this.OnTimer = function()
		{
			if( this.bPressUp )
				this.HandleDisplace( -1 ) ;
			
			if( this.bPressDown )
				this.HandleDisplace( 1 ) ;
			
			if( this.bFiltering )
				this.ContentDisplace() ;
		}

		// ON START PRESS UP / DOWM
		// 
		//-------------------------------------------------	
		this.ScrollWheel = function( e )
		{
			var delta = 0 ;
			// For IE
			if ( !e ){ e = window.event ; }

			// IE / Opera / CHROME (que me devuelve dos llamdas O___O )
			if ( e.wheelDelta )
			{ 
				delta = e.wheelDelta ;
			}
			else if ( e.detail )
			{ 
				// Mozilla case. In Mozilla, sign of delta is different than in IE. Also, delta is multiple of 3.
				delta = -e.detail ;
			}
			
			if( delta > 0 )
			{
				that.HandleDisplace( -that.jump ) ;
			}
			else
			{
				that.HandleDisplace( that.jump ) ;
			}		

			if ( e.preventDefault ) e.preventDefault() ;
			e.returnValue = false ;			
		}

		// ON START PRESS UP / DOWM
		// 
		//-------------------------------------------------	
		this.OnStartPressUp = function( e )
		{
			that.Reset(); // TEMPORAL
			
			that.bPressUp = true ;
			that.oldOnmouseup = window.onmouseup ;
			window.onmouseup = function()
			{ 
				that.bPressUp = false ; 
			} ;
			that.CheckTimer() ;
		}
		
		this.OnStartPressDown = function( e )
		{
			that.Reset(); // TEMPORAL
			
			that.bPressDown = true ;
			that.oldOnmouseup = window.onmouseup ;
			window.onmouseup = function()
			{ 
				that.bPressDown = false ; 
			} ;
			that.CheckTimer() ;
		}


		// ON CLICK UP / DOWM
		// 
		//-------------------------------------------------	
		this.OnClickUp = function( e )
		{
			that.Reset(); // TEMPORAL
			
			//that.HandleDisplace( -that.Handle.offsetHeight * 0.4 ) ;
			that.HandleDisplace( -that.jump ) ;
		}
		
		this.OnClickDown = function( e )
		{
			that.Reset(); // TEMPORAL
			
			//that.HandleDisplace( that.Handle.offsetHeight * 0.4 ) ;
			that.HandleDisplace( that.jump ) ;
		}
				
		// HANDLE DISPLACE
		// Handle Displace. nDisplace es un delta de desplazamiento
		//-------------------------------------------------	
		this.HandleDisplace = function( nDisplace )
		{
			var bOK = true ; // NO ESTAMOS EN UN TOPE, SE PRODUCE MOVIMIENTO
			var nHandleH = this.Handle.offsetHeight ;
			var nHandleT = this.Handle.offsetTop ;
			var nBarrH = this.Barr.offsetHeight ;

			this.PressUp.style.visibility = "visible" ;			// div up by press
			this.ClickUp.style.visibility = "visible" ;			// div up by click	
			this.PressDown.style.visibility = "visible" ;		// div down by press
			this.ClickDown.style.visibility = "visible" ;		// div down by clik
											
			var newHandleT = Math.round( nHandleT + nDisplace ) ;
			if( newHandleT<=0 )
			{
				newHandleT = 0 ;
				bOK = false ; // ESTAMOS EN UN TOPE, NO SE PRODUCE MOVIMIENTO
				// OCULTAR BOTONES SUPERIORES
				this.PressUp.style.visibility = "hidden" ;		// div up by press
				this.ClickUp.style.visibility = "hidden" ;		// div up by click			
			}
				
			if( newHandleT + nHandleH >= nBarrH )
			{
				newHandleT = nBarrH - nHandleH ;
				bOK = false ; // ESTAMOS EN UN TOPE, NO SE PRODUCE MOVIMIENTO
				// OCULTAR BOTONES INFERIORES
				this.PressDown.style.visibility = "hidden" ;	// div down by press
				this.ClickDown.style.visibility = "hidden" ;	// div down by clik
			}

			this.Handle.style.top =  newHandleT + "px" ;
			
			var nextContentT = - Math.round( this.Handle.offsetTop * this.scaleFactor ) ;
			if( nextContentT > 0 ) nextContentT = 0 ;			
			
			//alert( nextContentT ) ;
			this.Content.nextContentT = nextContentT ;
			
			that.bFiltering = true ;
			that.CheckTimer() ;
			
			return bOK ;
		}
		

		// UPDATE CONTENT TOP
		// Reconfigure Scrollbox elements
		//-------------------------------------------------	
		this.ContentDisplace = function()
		{
			if( this.Content.nextContentT == Math.round( this.Content.T ) )
			{
				that.bFiltering = false ;
				that.CheckTimer() ;
				return ;
			}
			
			this.Content.T = this.InterpolateAB( this.Content.T , this.Content.nextContentT , this.filter ) ;
			this.Content.style.top = Math.floor( this.Content.T ) + "px" ;	
		}

		// INTERPOLATE AB
		// Retunrs interpolated value between two nuumbers
		//-------------------------------------------------	
		this.InterpolateAB = function( fA , fB , fPonderado )
		{
			if ( fA == fB ) return fA ;
			
			var increment ;
			if( fA > fB )
			{
				fA *= 1000 ;
				fB *= 1000 ;
				increment = ( fA - fB ) * fPonderado ;
				if( increment < 1 ) increment = 1 ;
				//return( Math.floor( ( fA - increment ) * 0.01 ) ) ;
				return( ( fA - increment ) * 0.001  ) ;
				
			}else{
				
				fA *= 1000 ;
				fB *= 1000 ;
				increment = ( fB - fA ) * fPonderado ;
				if( increment < 1 ) increment = 1 ;
				//return ( Math.ceil( ( fA + increment ) * 0.01 ) ) ;
				return ( ( fA + increment ) * 0.001 ) ;
			}
		}


		// ON CLICK BARR
		// 
		//-------------------------------------------------	
		this.OnClickBarr = function( e )
		{
			if ( !e ) e = window.event ;
				that.draging = true ;
				
			var midHandle = Math.round( that.Handle.offsetTop + that.Handle.offsetHeight * 0.5 ) ;
			if( e.layerY < midHandle )
				that.HandleDisplace( -( midHandle - e.layerY ) ) ;
			else
				that.HandleDisplace( e.layerY - midHandle ) ;				
		}
		
		// START HANDLE DRAG
		// Handle Drag Activation
		//-------------------------------------------------	
		this.StartHandleDrag = function( e )
		{
			that.Reset(); // TEMPORAL
			
			if ( !e ) e = window.event ;
				that.draging = true ;
			
			that.y = e.clientY ;
			var oldOnmousemove = document.onmousemove ;
			document.onmousemove = function( e )
			{
				if ( !e ) e = window.event ;
				if ( that.draging )
				{
					if( that.HandleDisplace( e.clientY - that.y  ) )
						that.y = e.clientY ;
						
					return false ;
				}			
			} ;

			that.oldOnmouseup = window.onmouseup ;
			window.onmouseup = function()
			{ 
				that.draging = false ;
				document.onmousemove = oldOnmousemove ;
				
			} ;			
			
			return false ;
		}

		// STOP DRAG
		// Handler Drag deactivation
		//-------------------------------------------------	
		this.StopDrag = function StopDrag()
		{
			that.drag = false ;
			that.HoverOff() ;
			document.onmousemove = null ;
		}			

		// AFTER LOAD AND DEFINE CREATE IT
		this.Create() ;
	}
