/******************************************\
  GSSI Customized Scrollbar Widget
  Requires: Base, DOM, Environment, Events
\******************************************/

if (! GSSI) { alert("gssi.scrollbar.js: gssi.base.js not loaded"); };
if (! GSSI.DOM ) { alert("gssi.scrollbar.js: gssi.dom.js not loaded"); };
if (! GSSI.Environment ) { alert("gssi.scrollbar.js: gssi.environment.js not loaded"); };
if (! GSSI.Events ) { alert("gssi.scrollbar.js: gssi.events.js not loaded"); };

GSSI.Scrollbar = GSSI.Class({
	initialize: function( target, verticalbaroptions, horizontalbaroptions ) {
		this.verticalbaroptions = GSSI.Base.Extend( {
			use: true,
			width:16,
			handlesize:16,
			endbuttons:false,
			buttonsize:16,
			cssclass: "verticalscroll",
			zIndex: 5000,
			force:false
		}, verticalbaroptions );
		if (! this.verticalbaroptions.endbuttons) { this.verticalbaroptions.buttonsize = 0; };
		
		if (horizontalbaroptions) {
			this.horizontalbaroptions = GSSI.Base.Extend( {
				use: true,
				width:16,
				handlesize:16,
				endbuttons:false,
				buttonsize:16,
				cssclass: "horizontalscroll",
				zIndex: 5000,
				force:false
			}, horizontalbaroptions );
			if (! this.horizontalbaroptions.endbuttons) { this.horizontalbaroptions.buttonsize = 0; };
		} else {
			this.horizontalbaroptions = {};
		}
		
		this._both = this.verticalbaroptions.use && this.horizontalbaroptions.use;
		var bar = this;
		GSSI.Environment.onDOMReady( function() { bar.build(target); } );
	},
	
	build: function (source) {
		this.element = GSSI.$(source);
		if(! this.element) { return; };
		var sb = this;
		var body = GSSI.DOM.GetBody();
		
		GSSI.Events.WatchMouse();
		GSSI.Events.Add( window, 'resize', function() { sb.refresh(); }, true );


		this.vmousehandler = function(e) { sb.vmouse(e.pageY); };
		this.hmousehandler = function(e) { sb.hmouse(e.pageX); };
		this.releasehandler = function() {
			GSSI.DOM.GetBody().removeEvent( 'mousemove', sb.vmousehandler );
			GSSI.DOM.GetBody().removeEvent( 'mousemove', sb.hmousehandler );
		};
		
		body.addEvent( 'mouseup', sb.releasehandler );

		if( this.verticalbaroptions.use ) {
			this.verticalbar = GSSI.DOM.createElement( 'div', 
				{ 'class': this.verticalbaroptions.cssclass },
				{ position:'absolute', width:(this.verticalbaroptions.width)+'px', fontSize:'1px', lineHeight:'1px', zIndex:this.verticalbaroptions.zIndex } );
			this.verticalbar.sizeTo( this.element, 0, 0, { skipWidth:true } );
			if (( this.element.scrollHeight > this.element.clientHeight ) || (this.verticalbaroptions.force)) {
				this.verticalbar.style.visibility = 'visible';
			} else {
				this.verticalbar.style.visibility = 'hidden';
			}
			body.prependChild(this.verticalbar);

			this.verticalbar.moveTo(this.element, 'top after' );
			if(this.verticalbaroptions.endbuttons) {
				this.verticalbar.upscroll = GSSI.DOM.createElement( 'a', 
					{ 'class': 'upbutton', href:'javascript:void(0);' },
					{
						position:'absolute',
						height:(this.verticalbaroptions.buttonsize)+'px',
						width:(this.verticalbaroptions.width)+'px',
						top:0, left:0
					}
				);
				this.verticalbar.appendChild(this.verticalbar.upscroll);
				this.verticalbar.downscroll = GSSI.DOM.createElement( 'a', 
					{ 'class': 'downbutton', href:'javascript:void(0);' },
					{
						position:'absolute',
						height:(this.verticalbaroptions.buttonsize)+'px',
						width:(this.verticalbaroptions.width)+'px',
						bottom:0, left:0
					}
				);
				this.verticalbar.appendChild(this.verticalbar.downscroll);
				this.verticalbar.upscroll.addEvent( 'mousedown', function() { sb.vpage(true); } );
				this.verticalbar.downscroll.addEvent( 'mousedown', function() { sb.vpage(false); } );
			}
			this.verticalbar.handle = GSSI.DOM.createElement( 'div', 
				{ 'class': 'handle' },
				{
					position:'absolute', zIndex:6000,
					width:(this.verticalbaroptions.width)+'px',
					height:(this.verticalbaroptions.handlesize)+'px',
					left:0, top:this.verticalbaroptions.buttonsize+'px'
				}
			);
			this.verticalbar.appendChild(this.verticalbar.handle);
			this.verticalbar._scrollspace = this.verticalbar.offsetHeight - ( this.verticalbaroptions.buttonsize * 2 ) - this.verticalbaroptions.handlesize;
			this.verticalbar.track = GSSI.DOM.createElement( 'div', 
				{ 'class': 'track' },
				{
					position:'absolute', zIndex:5500,
					width:(this.verticalbaroptions.width)+'px',
					height:(this.verticalbar._scrollspace + this.verticalbaroptions.handlesize)+'px',
					left:0, top:this.verticalbaroptions.buttonsize+'px'
				}
			);
			this.verticalbar.appendChild(this.verticalbar.track);
			this.verticalbar._pagesize = this.verticalbaroptions.handlesize / this.verticalbar._scrollspace;						
			this.verticalbar.selectable(false);
			this.verticalbar.track.addEvent( 'mousedown', function(e) { sb.vmouse(e.pageY); GSSI.DOM.GetBody().addEvent( 'mousemove', sb.vmousehandler ); } );
			this.verticalbar.handle.addEvent( 'mousedown', function(e) { sb.vmouse(e.pageY); GSSI.DOM.GetBody().addEvent( 'mousemove', sb.vmousehandler ); } );
			this.verticalbar.track.addEvent( 'mousewheel', function(e) { sb.vpage( e.wheeldirection == -1 ); } );
			this.element.addEvent( 'mousewheel', function(e) { sb.vpage( e.wheeldirection == -1 ); } );
		}
		
		if( this.horizontalbaroptions.use ) {
			this.horizontalbar = GSSI.DOM.createElement( 'div', 
				{ 'class': this.horizontalbaroptions.cssclass },
				{ position:'absolute', height:(this.horizontalbaroptions.width)+'px', fontSize:'1px', lineHeight:'1px', zIndex:this.horizontalbaroptions.zIndex }  );
			this.horizontalbar.sizeTo( this.element, 0, 0, { skipHeight:true } );
			if (( this.element.scrollWidth > this.element.clientWidth ) || (this.horizontalbaroptions.force)) {
				this.horizontalbar.style.visibility = 'visible';
			} else {
				this.horizontalbar.style.visibility = 'hidden';
			}
			body.prependChild(this.horizontalbar);
			this.horizontalbar.moveTo(this.element, 'below left' );
			if(this.horizontalbaroptions.endbuttons) {
				this.horizontalbar.leftscroll = GSSI.DOM.createElement( 'a', 
					{ 'class': 'leftbutton', href:'javascript:void(0);' },
					{
						position:'absolute',
						height:(this.horizontalbaroptions.width)+'px',
						width:(this.horizontalbaroptions.buttonsize)+'px',
						top:0, left:0
					}
				);
				this.horizontalbar.appendChild(this.horizontalbar.leftscroll);
				this.horizontalbar.rightscroll = GSSI.DOM.createElement( 'a', 
					{ 'class': 'rightbutton', href:'javascript:void(0);' },
					{
						position:'absolute',
						height:(this.horizontalbaroptions.width)+'px',
						width:(this.horizontalbaroptions.buttonsize)+'px',
						top:0, right:0
					}
				);
				this.horizontalbar.appendChild(this.horizontalbar.rightscroll);
				this.horizontalbar.leftscroll.addEvent( 'mousedown', function() { sb.hpage(true); return false; } );
				this.horizontalbar.rightscroll.addEvent( 'mousedown', function() { sb.hpage(false); return false; } );
			}
			this.horizontalbar.handle = GSSI.DOM.createElement( 'div', 
				{ 'class': 'handle' },
				{
					position:'absolute', zIndex:6000,
					height:(this.horizontalbaroptions.width)+'px',
					width:(this.horizontalbaroptions.handlesize)+'px',
					top:0, left:this.horizontalbaroptions.buttonsize+'px'
				}
			);
			this.horizontalbar.appendChild(this.horizontalbar.handle);
			this.horizontalbar._scrollspace = this.horizontalbar.offsetWidth - ( this.horizontalbaroptions.buttonsize * 2 ) - this.horizontalbaroptions.handlesize;
			this.horizontalbar.track = GSSI.DOM.createElement( 'div', 
				{ 'class': 'track' },
				{
					position:'absolute', zIndex:5500,
					height:(this.horizontalbaroptions.width)+'px',
					width:(this.horizontalbar._scrollspace + this.horizontalbaroptions.handlesize)+'px',
					top:0, left:this.horizontalbaroptions.buttonsize+'px'
				}
			);
			this.horizontalbar.appendChild(this.horizontalbar.track);
			this.horizontalbar._pagesize = this.horizontalbaroptions.handlesize / this.horizontalbar._scrollspace;
			this.horizontalbar.selectable(false);
			this.horizontalbar.track.addEvent( 'mousedown', function(e) { sb.hmouse(e.pageX); GSSI.DOM.GetBody().addEvent( 'mousemove', sb.hmousehandler ); } );
			this.horizontalbar.handle.addEvent( 'mousedown', function(e) { sb.hmouse(e.pageX); GSSI.DOM.GetBody().addEvent( 'mousemove', sb.hmousehandler ); } );
		}
		
	},
	
	refresh: function() {
		if( this.verticalbar ) {
			var v = this.vscroll();
			this.verticalbar.sizeTo( this.element, 0, 0, { skipWidth:true } );
			this.verticalbar.moveTo(this.element, 'top after' );
			this.verticalbar._scrollspace = this.verticalbar.offsetHeight - ( this.verticalbaroptions.buttonsize * 2 ) - this.verticalbaroptions.handlesize;
			this.verticalbar._pagesize = this.verticalbaroptions.handlesize / this.verticalbar._scrollspace;
			this.verticalbar.track.style.height = (this.verticalbar._scrollspace + this.verticalbaroptions.handlesize) + 'px';
			if (( this.element.scrollHeight > this.element.clientHeight ) || (this.verticalbaroptions.force)) {
				this.verticalbar.style.visibility = 'visible';
				this.vscroll(v);
			} else {
				this.verticalbar.style.visibility = 'hidden';
				this.vscroll(0);
			}
		}
		
		if( this.horizontalbar ) {
			var h = this.hscroll();
			this.horizontalbar.sizeTo( this.element, 0, 0, { skipHeight:true } );
			this.horizontalbar.moveTo(this.element, 'below left' );
			this.horizontalbar._scrollspace = this.horizontalbar.offsetWidth - ( this.horizontalbaroptions.buttonsize * 2 ) - this.horizontalbaroptions.handlesize;
			this.horizontalbar._pagesize = this.horizontalbaroptions.handlesize / this.horizontalbar._scrollspace;
			this.horizontalbar.track.style.width = (this.horizontalbar._scrollspace + this.horizontalbar.handlesize) + 'px';
			if (( this.element.scrollWidth > this.element.clientWidth ) || (this.horizontalbaroptions.force)) {
				this.horizontalbar.style.visibility = 'visible';
				this.hscroll(h);
			} else {
				this.horizontalbar.style.visibility = 'hidden';
				this.hscroll(0);
			}
		}
	},
	
	vscroll: function( p ) {
		if ( arguments.length < 1 ) {
			var p = (this.verticalbar.handle.offsetTop - this.verticalbaroptions.buttonsize) / this.verticalbar._scrollspace;
		} else {
			if (p<0.0) { p=0.0; };
			if (p>1.0) { p=1.0; };
			this.verticalbar.handle.style.top = (( p * (this.verticalbar._scrollspace) ) + this.verticalbaroptions.buttonsize) + 'px';
			this.element.scrollTop = p * ( this.element.scrollHeight - this.element.clientHeight );
		}
		return p;
	},
	
	hscroll: function( p ) {
		if ( arguments.length < 1 ) {
			var p = (this.horizontalbar.handle.offsetLeft - this.horizontalbaroptions.buttonsize) / this.horizontalbar._scrollspace;
		} else {
			if (p<0.0) { p=0.0; };
			if (p>1.0) { p=1.0; };
			this.horizontalbar.handle.style.left = (( p * this.horizontalbar._scrollspace ) + this.horizontalbaroptions.buttonsize) + 'px';
			this.element.scrollLeft = p * ( this.element.scrollWidth - this.element.clientWidth );
		}
		return p;
	},
	
	vpage: function( up ) {
		this.vscroll( this.vscroll() + (up?(-this.verticalbar._pagesize):this.verticalbar._pagesize)  );
	},
	
	hpage: function( left ) {
		this.hscroll( this.hscroll() + (left?(-this.horizontalbar._pagesize):this.horizontalbar._pagesize)  );
	},
	
	vmouse: function( y ) {
		var p = (y - this.verticalbar.offsetTop - (this.verticalbar.handle.offsetHeight / 2.0) - this.verticalbaroptions.buttonsize) / this.verticalbar._scrollspace;
		this.vscroll(p);
	},

	hmouse: function( x ) {
		var p = (x - this.horizontalbar.offsetLeft - (this.horizontalbar.handle.offsetWidth / 2.0) - this.horizontalbaroptions.buttonsize) / this.horizontalbar._scrollspace;
		this.hscroll(p);
	}

});


