/* Copyright (c) 2006 Kelvin Luck (kelvin AT kelvinluck DOT com || http://www.kelvinluck.com)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * 
 * See http://kelvinluck.com/assets/jquery/jScrollPane/
 * $Id: jScrollPane.js 1567 2007-03-23 01:34:29Z kelvin $
 */



jQuery.jScrollPane={active:[]};
jQuery.fn.jScrollPane=function(settings){
	settings=jQuery.extend({
		scrollbarWidth:7,
		scrollbarMargin:5,
		wheelSpeed:18,
		showArrows:false,
		arrowSize:undefined,
		animateTo:false,
		dragMinHeight:1,
		dragMaxHeight:99999
	},settings);
	return this.each(function(){
		var $this=jQuery(this);
		if(jQuery(this).parent().is('.jScrollPaneContainer')){
			var $c=jQuery(this).parent();
			var paneWidth=$c.innerWidth();
			var paneHeight=$c.outerHeight();
			var trackHeight=paneHeight;
			if($c.unmousewheel){
				$c.unmousewheel()
			}
			jQuery('>.jScrollPaneTrack, >.jScrollArrowUp, >.jScrollArrowDown',$c).remove();
			$this.css({'top':0})
		}else{
			this.originalPadding=$this.css('paddingTop')+' '+$this.css('paddingRight')+' '+$this.css('paddingBottom')+' '+$this.css('paddingLeft');
			this.originalSidePaddingTotal=(parseInt($this.css('paddingLeft'))||0)+(parseInt($this.css('paddingRight'))||0);
			var paneWidth=$this.innerWidth();
			var paneHeight=$this.innerHeight();
			var trackHeight=paneHeight;
			$this.wrap(
				jQuery('<div>')
				.attr({'className':'jScrollPaneContainer'})
				.css({'height':paneHeight+'px','width':paneWidth+'px'})
			)
		}
		var p=this.originalSidePaddingTotal;
		$this.css({'height':'auto','width':paneWidth-settings.scrollbarWidth-settings.scrollbarMargin-p+'px','paddingRight':settings.scrollbarMargin+'px'});
		var contentHeight=$this.outerHeight();
		var percentInView=paneHeight/contentHeight;
		if(percentInView<.98){
			var $container=$this.parent();
			$container.append(
				jQuery('<div>')
				.attr({'className':'jScrollPaneTrack'})
				.css({'width':settings.scrollbarWidth+'px'})
				.append(
					jQuery('<div>')
					.attr({'className':'jScrollPaneDrag'})
					.css({'width':settings.scrollbarWidth+'px'})
					.append(
						jQuery('<div>')
						.attr({'className':'jScrollPaneDragTop'})
						.css({'width':settings.scrollbarWidth+'px'})
						,jQuery('<div>')
						.attr({'className':'jScrollPaneDragBottom'})
						.css({'width':settings.scrollbarWidth+'px'})
					)
				)
			);
			var $track=jQuery('>.jScrollPaneTrack',$container);
			var $drag=jQuery('>.jScrollPaneTrack .jScrollPaneDrag',$container);
			if(settings.showArrows){
				var currentArrowButton;
				var currentArrowDirection;
				var currentArrowInterval;
				var currentArrowInc;
				var whileArrowButtonDown=function(){
					if(currentArrowInc>4||currentArrowInc%4==0){
						positionDrag(dragPosition+currentArrowDirection*mouseWheelMultiplier)
					}
					currentArrowInc++
				};
				var onArrowMouseUp=function(event){
					jQuery('body').unbind('mouseup',onArrowMouseUp);
					currentArrowButton.removeClass('jScrollActiveArrowButton');
					clearInterval(currentArrowInterval)
				};
				var onArrowMouseDown=function(){
					jQuery('body').bind('mouseup',onArrowMouseUp);
					currentArrowButton.addClass('jScrollActiveArrowButton');
					currentArrowInc=0;
					whileArrowButtonDown();
					currentArrowInterval=setInterval(whileArrowButtonDown,100)
				};
				$container.append(
					jQuery('<a>')
					.attr({'href':'javascript:;','className':'jScrollArrowUp'})
					.css({'width':settings.scrollbarWidth+'px'})
					.html('Scroll up')
					.bind('mousedown',function(){
						currentArrowButton=$(this);
						currentArrowDirection=-1;
						onArrowMouseDown();
						this.blur();
						return false
					})
					,jQuery('<a>')
					.attr({'href':'javascript:;','className':'jScrollArrowDown'})
					.css({'width':settings.scrollbarWidth+'px'})
					.html('Scroll down')
					.bind('mousedown',function(){
						currentArrowButton=$(this);
						currentArrowDirection=1;
						onArrowMouseDown();
						this.blur();
						return false
					})
				);
				if(settings.arrowSize){
					trackHeight=paneHeight-settings.arrowSize-settings.arrowSize;
					$track.css({'height':trackHeight+'px',top:settings.arrowSize+'px'})
				}else{
					var topArrowHeight=jQuery('>.jScrollArrowUp',$container).height();
					trackHeight=paneHeight-topArrowHeight-jQuery('>.jScrollArrowDown',$container).height();
					$track.css({'height':trackHeight+'px',top:topArrowHeight+'px'})
				}
			}
			var $pane=jQuery(this).css({'position':'absolute','overflow':'visible'});
			var currentOffset;
			var maxY;
			var mouseWheelMultiplier;
			var dragPosition=0;
			var dragMiddle=percentInView*paneHeight/2;
			var getPos=function(event,c){
				var p=c=='X'?'Left':'Top';
				return event['page'+c]||(
					event['client'+c]+(
						document.documentElement['scroll'+p]||document.body['scroll'+p]
					)
				)
				||0
			};
			var ignoreNativeDrag=function(){return false};
			var initDrag=function(){
				ceaseAnimation();
				currentOffset=$drag.offset(false);
				currentOffset.top-=dragPosition;
				maxY=trackHeight-$drag[0].offsetHeight;
				mouseWheelMultiplier=2*settings.wheelSpeed*maxY/contentHeight
			};
			var onStartDrag=function(event){
				initDrag();
				dragMiddle=getPos(event,'Y')-dragPosition-currentOffset.top;
				jQuery('body')
				.bind('mouseup',onStopDrag)
				.bind('mousemove',updateScroll);
				if(jQuery.browser.msie){
					jQuery('body')
					.bind('dragstart',ignoreNativeDrag)
					.bind('selectstart',ignoreNativeDrag)
				}
				return false
			};
			var onStopDrag=function(){
				jQuery('body')
				.unbind('mouseup',onStopDrag)
				.unbind('mousemove',updateScroll);
				dragMiddle=percentInView*paneHeight/2;
				if(jQuery.browser.msie){
					jQuery('body')
					.unbind('dragstart',ignoreNativeDrag)
					.unbind('selectstart',ignoreNativeDrag)
				}
			};
			var positionDrag=function(destY){
				destY=destY<0?0:(destY>maxY?maxY:destY);
				dragPosition=destY;
				$drag.css({'top':destY+'px'});
				var p=destY/maxY;
				$pane.css({'top':((paneHeight-contentHeight)*p)+'px'})
			};
			var updateScroll=function(e){
				positionDrag(getPos(e,'Y')-currentOffset.top-dragMiddle)
			};
			var dragH=Math.max(Math.min(percentInView*paneHeight,settings.dragMaxHeight),settings.dragMinHeight);
			$drag.css({'height':dragH+'px'}).bind('mousedown',onStartDrag);
			var trackScrollInterval;
			var trackScrollInc;
			var trackScrollMousePos;
			var doTrackScroll=function(){
				if(trackScrollInc>8||trackScrollInc%4==0){
					positionDrag((dragPosition-((dragPosition-trackScrollMousePos)/2)))
				}
				trackScrollInc++
			};
			var onStopTrackClick=function(){
				clearInterval(trackScrollInterval);
				jQuery('body')
				.unbind('mouseup',onStopTrackClick)
				.unbind('mousemove',onTrackMouseMove)
			};
			var onTrackMouseMove=function(event){
				trackScrollMousePos=getPos(event,'Y')-currentOffset.top-dragMiddle
			};
			var onTrackClick=function(event){
				initDrag();
				onTrackMouseMove(event);
				trackScrollInc=0;
				jQuery('body')
				.bind('mouseup',onStopTrackClick)
				.bind('mousemove',onTrackMouseMove);
				trackScrollInterval=setInterval(doTrackScroll,100);
				doTrackScroll()
			};
			$track.bind('mousedown',onTrackClick);
			if($container.mousewheel){
				$container.mousewheel(function(event,delta){
					initDrag();
					ceaseAnimation();
					var d=dragPosition;
					positionDrag(dragPosition-delta*mouseWheelMultiplier);
					var dragOccured=d!=dragPosition;
					return!dragOccured
				},false)
			}
			var _animateToPosition;
			var _animateToInterval;
			function animateToPosition(){
				var diff=(_animateToPosition-dragPosition)/3;
				if(diff>1||diff<-1){
					positionDrag(dragPosition+diff)
				}else{
					positionDrag(_animateToPosition);
					ceaseAnimation()
				}
			}
			var ceaseAnimation=function(){
				if(_animateToInterval){
					clearInterval(_animateToInterval);
					delete _animateToPosition
				}
			};
			var scrollTo=function(pos){
				ceaseAnimation();
				var destDragPosition=-pos/(paneHeight-contentHeight)*maxY;
				if(settings.animateTo){
					_animateToPosition=destDragPosition;
					_animateToInterval=setInterval(animateToPosition,100)
				}else{
					positionDrag(destDragPosition)
				}
			};
			$this[0].scrollTo=scrollTo;
			$this[0].scrollBy=function(delta){
				var currentPos=-parseInt($pane.css('top'))||0;
				scrollTo(currentPos+delta)
			};
			initDrag();
			jQuery.jScrollPane.active.push($this[0])
		}else{
			$this.css({'height':paneHeight+'px','width':paneWidth-this.originalSidePaddingTotal+'px','padding':this.originalPadding})
		}
	}
)};
jQuery(window).bind('unload',function(){
	var els=jQuery.jScrollPane.active;
	for(var i=0;i<els.length;i++){
		els[i].scrollTo=els[i].scrollBy=null
	}
});