/* 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 33 2008-12-10 22:55:28Z kelvin.luck $
 */

/**
 * Replace the vertical scroll bars on any matched elements with a fancy
 * styleable (via CSS) version. With JS disabled the elements will
 * gracefully degrade to the browsers own implementation of overflow:auto.
 * If the mousewheel plugin has been included on the page then the scrollable areas will also
 * respond to the mouse wheel.
 *
 * @example jQuery(".scroll-pane").jScrollPane();
 *
 * @name jScrollPane
 * @type jQuery
 * @param Object	settings	hash with options, described below.
 *								scrollbarWidth	-	The width of the generated scrollbar in pixels
 *								scrollbarMargin	-	The amount of space to leave on the side of the scrollbar in pixels
 *								wheelSpeed		-	The speed the pane will scroll in response to the mouse wheel in pixels
 *								showArrows		-	Whether to display arrows for the user to scroll with
 *								arrowSize		-	The height of the arrow buttons if showArrows=true
 *								animateTo		-	Whether to animate when calling scrollTo and scrollBy
 *								dragMinHeight	-	The minimum height to allow the drag bar to be
 *								dragMaxHeight	-	The maximum height to allow the drag bar to be
 *								animateInterval	-	The interval in milliseconds to update an animating scrollPane (default 100)
 *								animateStep		-	The amount to divide the remaining scroll distance by when animating (default 3)
 *								maintainPosition-	Whether you want the contents of the scroll pane to maintain it's position when you re-initialise it - so it doesn't scroll as you add more content (default true)
 *								scrollbarOnLeft	-	Display the scrollbar on the left side?  (needs stylesheet changes, see examples.html)
 *								reinitialiseOnImageLoad - Whether the jScrollPane should automatically re-initialise itself when any contained images are loaded
 * @return jQuery
 * @cat Plugins/jScrollPane
 * @author Kelvin Luck (kelvin AT kelvinluck DOT com || http://www.kelvinluck.com)
 */

(function($) {

$.jScrollPane = {
	active : []
};
$.fn.jScrollPane = function(settings)
{
	settings = $.extend({}, $.fn.jScrollPane.defaults, settings);

	var rf = function() { return false; };
	
	return this.each(
		function()
		{
			var $this = $(this);
			// Switch the element's overflow to hidden to ensure we get the size of the element without the scrollbars [http://plugins.jquery.com/node/1208]
			$this.css('overflow', 'hidden');
			var paneEle = this;
			
			if ($(this).parent().is('.jScrollPaneContainer')) {
				var currentScrollPositionY = settings.maintainPosition ? $this.position().top : 0;
				var currentScrollPositionX = settings.maintainPosition ? $this.position().left : 0;
				var $c = $(this).parent();
				var paneWidth = $this.width();
				var paneHeight = $this.height();
				var trackHeight = paneHeight;
				var trackWidth = paneWidth;
				$c.css(
						{
							'height':paneHeight+'px', 
							'width':paneWidth+'px'
						}
					)
				$('>.jScrollPaneTrack, >.jScrollArrowUp, >.jScrollArrowDown, >.jScrollArrowLeft >.jScrollArrowRight', $c).remove();
				$this.css({'top':0});
				$this.css({'left':0});
			} else {
				var currentScrollPositionY = 0;
				var currentScrollPositionX = 0;
				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);
				this.originalTopPaddingTotal = (parseInt($this.css('paddingTop')) || 0) + (parseInt($this.css('paddingBottom')) || 0);
				var paneWidth = $this.width();
				var paneHeight = $this.height();
				var trackHeight = paneHeight;
				var trackWidth = paneWidth;
				$this.wrap(
					$('<div></div>').attr(
						{'className':'jScrollPaneContainer'}
					).css(
						{
							'height':paneHeight+'px', 
							'width':paneWidth+'px'
						}
					)
				);
				// deal with text size changes (if the jquery.em plugin is included)
				// and re-initialise the scrollPane so the track maintains the
				// correct size
				$(document).bind(
					'emchange', 
					function(e, cur, prev)
					{
						$this.jScrollPane(settings);
					}
				);
				
			}
			
			/*if (settings.reinitialiseOnImageLoad) {
				// code inspired by jquery.onImagesLoad: http://plugins.jquery.com/project/onImagesLoad
				// except we re-initialise the scroll pane when each image loads so that the scroll pane is always up to size...
				// TODO: Do I even need to store it in $.data? Is a local variable here the same since I don't pass the reinitialiseOnImageLoad when I re-initialise?
				var $imagesToLoad = $.data(paneEle, 'jScrollPaneImagesToLoad') || $('img', $this);
				var loadedImages = [];
				
				if ($imagesToLoad.length) {
					$imagesToLoad.each(function(i, val)	{
						$(this).bind('load', function() {
							if($.inArray(i, loadedImages) == -1){ //don't double count images
								loadedImages.push(val); //keep a record of images we've seen
								$imagesToLoad = $.grep($imagesToLoad, function(n, i) {
									return n != val;
								});
								$.data(paneEle, 'jScrollPaneImagesToLoad', $imagesToLoad);
								settings.reinitialiseOnImageLoad = false;
								$this.jScrollPane(settings); // re-initialise
							}
						}).each(function(i, val) {
							if(this.complete || this.complete===undefined) { 
								//needed for potential cached images
								this.src = this.src; 
							} 
						});
					});
				};
			}*/

			var pX = this.originalSidePaddingTotal;
			var pY = this.originalTopPaddingTotal;
			
			
			
			var cssToApply = {
				'height': 'auto',
				'width' : 'auto'
				//'height': paneHeight - settings.scrollbarWidth - settings.scrollbarMargin - pY + 'px',
				//'width':paneWidth - settings.scrollbarWidth - settings.scrollbarMargin - pX + 'px'
			}
			$this.css(cssToApply);
			var contentHeight = settings.contentHeight != -1 ? settings.contentHeight : $this.outerHeight();
			var contentWidth = settings.contentWidth != -1 ? settings.contentWidth : $this.outerWidth();
			var percentInViewY = paneHeight / contentHeight;
			var percentInViewX = paneWidth / contentWidth;
			
			var cssToApply2 = {
				'height': paneHeight - settings.scrollbarWidth - settings.scrollbarMargin - pY + 'px',
				'width':paneWidth - settings.scrollbarWidth - settings.scrollbarMargin - pX + 'px'
			}
			
			cssToApply2.paddingBottom = settings.scrollbarMargin + settings.scrollbarWidth + 'px';
			
			if(settings.scrollbarOnLeft) {
				cssToApply2.paddingLeft = settings.scrollbarMargin + settings.scrollbarWidth + 'px';
			} else {
				cssToApply2.paddingRight = settings.scrollbarMargin + settings.scrollbarWidth + 'px';
			}

			$this.css(cssToApply2);

			

			if (percentInViewY < .99) {
				var $container = $this.parent();
				$container.append(
					$('<div></div>').attr({'className':'jScrollPaneTrack'}).css({'width':settings.scrollbarWidth+'px'}).append(
						$('<div></div>').attr({'className':'jScrollPaneDrag'}).css({'width':settings.scrollbarWidth+'px'}).append(
							$('<div></div>').attr({'className':'jScrollPaneDragTop'}).css({'width':settings.scrollbarWidth+'px'}),
							$('<div></div>').attr({'className':'jScrollPaneDragBottom'}).css({'width':settings.scrollbarWidth+'px'})
						)
					)
				);
				
				var $track = $('>.jScrollPaneTrack', $container);
				var $drag = $('>.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)
					{
						$('html').unbind('mouseup', onArrowMouseUp);
						currentArrowButton.removeClass('jScrollActiveArrowButton');
						clearInterval(currentArrowInterval);
					};
					var onArrowMouseDown = function() {
						$('html').bind('mouseup', onArrowMouseUp);
						currentArrowButton.addClass('jScrollActiveArrowButton');
						currentArrowInc = 0;
						whileArrowButtonDown();
						currentArrowInterval = setInterval(whileArrowButtonDown, 100);
					};
					$container
						.append(
							$('<a></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;
								})
								.bind('click', rf),
							$('<a></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;
								})
								.bind('click', rf)
						);
					var $upArrow = $('>.jScrollArrowUp', $container);
					var $downArrow = $('>.jScrollArrowDown', $container);
					if (settings.arrowSize) {
						trackHeight = paneHeight - settings.arrowSize - settings.arrowSize;
						$track
							.css({'height': trackHeight+'px', top:settings.arrowSize+'px'})
					} else {
						var topArrowHeight = $upArrow.height();
						settings.arrowSize = topArrowHeight;
						trackHeight = paneHeight - topArrowHeight - $downArrow.height();
						$track
							.css({'height': trackHeight+'px', top:topArrowHeight+'px'})
					}
				}*/
				
				var $pane = $(this).css({'position':'absolute', 'overflow':'visible'});
				
				var currentOffset;
				var maxY;
				var mouseWheelMultiplier;
				// store this in a seperate variable so we can keep track more accurately than just updating the css property..
				var dragPosition = 0;
				var dragMiddle = percentInViewY*paneHeight/2;
				
				// pos function borrowed from tooltip plugin and adapted...
				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;
					$('html').bind('mouseup', onStopDrag).bind('mousemove', updateScroll);
					if ($.browser.msie) {
						$('html').bind('dragstart', ignoreNativeDrag).bind('selectstart', ignoreNativeDrag);
					}
					return false;
				};
				var onStopDrag = function()
				{
					$('html').unbind('mouseup', onStopDrag).unbind('mousemove', updateScroll);
					dragMiddle = percentInViewY*paneHeight/2;
					if ($.browser.msie) {
						$('html').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'});
					$this.trigger('scroll');
					if (settings.showArrows) {
						$upArrow[destY == 0 ? 'addClass' : 'removeClass']('disabled');
						$downArrow[destY == maxY ? 'addClass' : 'removeClass']('disabled');
					}
				};
				var updateScroll = function(e)
				{
					positionDrag(getPos(e, 'Y') - currentOffset.top - dragMiddle);
				};
				
				var dragH = Math.max(Math.min(percentInViewY*(paneHeight-settings.arrowSize*2), 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);
					$('html').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;
					$('html').bind('mouseup', onStopTrackClick).bind('mousemove', onTrackMouseMove);
					trackScrollInterval = setInterval(doTrackScroll, 100);
					doTrackScroll();
				};
				
				$track.bind('mousedown', onTrackClick);
				
				$container.bind(
					'mousewheel',
					function (event, delta) {
						initDrag();
						ceaseAnimation();
						var d = dragPosition;
						positionDrag(dragPosition - delta * mouseWheelMultiplier);
						var dragOccured = d != dragPosition;
						return !dragOccured;
					}
				);

				var _animateToPosition;
				var _animateToInterval;
				function animateToPosition()
				{
					var diff = (_animateToPosition - dragPosition) / settings.animateStep;
					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, preventAni)
				{
					if (typeof pos == "string") {
						$e = $(pos, $this);
						if (!$e.length) return;
						pos = $e.offset().top - $this.offset().top;
					}
					$container.scrollTop(0);
					ceaseAnimation();
					var destDragPosition = -pos/(paneHeight-contentHeight) * maxY;
					if (preventAni || !settings.animateTo) {
						positionDrag(destDragPosition);
					} else {
						_animateToPosition = destDragPosition;
						_animateToInterval = setInterval(animateToPosition, settings.animateInterval);
					}
				};
				$this[0].scrollTo = scrollTo;
				
				$this[0].scrollBy = function(delta)
				{
					var currentPos = -parseInt($pane.css('top')) || 0;
					scrollTo(currentPos + delta);
				};
				
				initDrag();
				
				scrollTo(-currentScrollPositionY, true);
			
				// Deal with it when the user tabs to a link or form element within this scrollpane
				$('*', this).bind(
					'focus',
					function(event)
					{
						var $e = $(this);
						
						// loop through parents adding the offset top of any elements that are relatively positioned between
						// the focused element and the jScrollPaneContainer so we can get the true distance from the top
						// of the focused element to the top of the scrollpane...
						var eleTop = 0;
						
						while ($e[0] != $this[0]) {
							eleTop += $e.position().top;
							$e = $e.offsetParent();
						}
						
						var viewportTop = -parseInt($pane.css('top')) || 0;
						var maxVisibleEleTop = viewportTop + paneHeight;
						var eleInView = eleTop > viewportTop && eleTop < maxVisibleEleTop;
						if (!eleInView) {
							var destPos = eleTop - settings.scrollbarMargin;
							if (eleTop > viewportTop) { // element is below viewport - scroll so it is at bottom.
								destPos += $(this).height() + 15 + settings.scrollbarMargin - paneHeight;
							}
							scrollTo(destPos);
						}
					}
				)
				
				
				if (location.hash) {
					scrollTo(location.hash);
				}
				
				// use event delegation to listen for all clicks on links and hijack them if they are links to
				// anchors within our content...
				$(document).bind(
					'click',
					function(e)
					{
						$target = $(e.target);
						if ($target.is('a')) {
							var h = $target.attr('href');
							if (h.substr(0, 1) == '#') {
								scrollTo(h);
							}
						}
					}
				);
				
				$.jScrollPane.active.push($this[0]);
				
			} else {
				$this.css(
					{
						'height':paneHeight+'px',
						'width':paneWidth-this.originalSidePaddingTotal+'px',
						'padding':this.originalPadding
					}
				);
				// remove from active list?
				$this.parent().unbind('mousewheel');
			}
			
			
			if (percentInViewX < 0.99) {
				var $Hcontainer = $this.parent();

				$Hcontainer.append(
					$('<div></div>').attr({'className':'jScrollPaneTrackBottom'}).css({'height':settings.scrollbarHeight+'px'}).append(
						$('<div></div>').attr({'className':'jScrollPaneDragHor'}).css({'height':settings.scrollbarHeight+'px'}).append(
							$('<div></div>').attr({'className':'jScrollPaneDragLeft'}).css({'height':settings.scrollbarHeight+'px'}),
							$('<div></div>').attr({'className':'jScrollPaneDragRight'}).css({'height':settings.scrollbarHeight+'px'})
						)
					)
				);
				
				var $Htrack = $('>.jScrollPaneTrackBottom', $Hcontainer);
			
				//Attach the intervals to the track
				/*for(inter in _jscr_intervals) { 
					
					if(settings.showArrows == true) { 
						scrollOffset = settings.arrowSize;
					} else { 
						scrollOffset = 0;
					}

					intervalTrackPos = _jscr_intervals[inter] / contentWidth * $Htrack.width() - (scrollOffset);
					trackIntervals[inter] = intervalTrackPos;
					
					if(trackIntervals[inter - 1] != undefined) {
						halfIntervals[inter-1] = (trackIntervals[inter] + trackIntervals[inter-1]) / 2;
					}
				
					if(inter != 0) { 
						interObj = jQuery('<div>|</div>').attr({'className':'jScrollIntervalTrack'}).css({'left':intervalTrackPos + 'px'})
						$Htrack.append(interObj);
					}
				}*/

				var $Hdrag = $('>.jScrollPaneTrackBottom .jScrollPaneDragHor', $Hcontainer);
				
				/*
				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);
						arrowUp = true;
						moveIntervals();
					};
					var onArrowMouseDown = function() {
						jQuery('body').bind('mouseup', onArrowMouseUp);
						currentArrowButton.addClass('jScrollActiveArrowButton');
						currentArrowInc = 0;
						whileArrowButtonDown();
						currentArrowInterval = setInterval(whileArrowButtonDown, 100);
					};
					$Hcontainer
						.append(
							jQuery('<a></a>')
								.attr({'href':'javascript:;', 'className':'jScrollArrowLeft'})
								.css({'width':settings.arrowSize+'px'})
								.html('Scroll Left')
								.bind('mousedown', function()
								{
									currentArrowButton = jQuery(this);
									currentArrowDirection = -1;
									onArrowMouseDown();
									this.blur();
									return false;
								}),
							jQuery('<a></a>')
								.attr({'href':'javascript:;', 'className':'jScrollArrowRight'})
								.css({'width':settings.arrowSize+'px'})
								.html('Scroll Right')
								.bind('mousedown', function()
								{
									currentArrowButton = jQuery(this);
									currentArrowDirection = 1;
									onArrowMouseDown();
									this.blur();
									return false;
								})
						);
					if (settings.arrowSize) {
						trackWidth = paneWidth - settings.arrowSize - settings.arrowSize;
						$Htrack
							.css({'width': trackWidth+'px', left:settings.arrowSize+'px'})
					} else {
						var leftArrowWidth = jQuery('>.jScrollArrowLeft', $Hcontainer).width();
						settings.arrowSize = leftArrowWidth;
						trackWidth = paneWidth - leftArrowWidth - jQuery('>.jScrollArrowRight', $Hcontainer).width();
						$Htrack
							.css({'width': trackWidth +'px', left: leftArrowWidth+'px'})
					}
				}*/
				
				var $Hpane = $(this).css({'position':'absolute', 'overflow':'visible'});
				
				var HcurrentOffset;
				var HmaxX;
				var HmouseWheelMultiplier;
				
				// store this in a seperate variable so we can keep track more accurately than just updating the css property..
				var HdragPosition = 0;
				var HdragMiddle = percentInViewX*paneWidth/2;
				
				// pos function borrowed from tooltip plugin and adapted...
				var HgetPos = function (event, c) {
					var p = c == 'X' ? 'Left' : 'Bottom';
					return event['page' + c] || (event['client' + c] + (document.documentElement['scroll' + p] || document.body['scroll' + p])) || 0;
				};
				
				var HignoreNativeDrag = function() {	return false; };
				var HcurrentInterval = 0;
				var Hdirection = 1;
				var HarrowUp = false;
				var HintervalMove = false;
				//_jscr_trackInt[currentId] = -1;;
						
				var HinitDrag = function()
				{
					HceaseAnimation();
					HcurrentOffset = $Hdrag.offset(false);
					HcurrentOffset.left -= HdragPosition;
					HmaxX = trackWidth - $Hdrag[0].offsetWidth;
					HmouseWheelMultiplier = 2 * settings.wheelSpeed * HmaxX / contentWidth;
				};
				
				var HonStartDrag = function(event)
				{
					HinitDrag();
					HdragMiddle = HgetPos(event, 'X') - HdragPosition - HcurrentOffset.left;
					$('body').bind('mouseup', HonStopDrag).bind('mousemove', HupdateScroll);
					if ($.browser.msie) {
						$('body').bind('dragstart', HignoreNativeDrag).bind('selectstart', HignoreNativeDrag);
					}
					return false;
				};
				var HonStopDrag = function()
				{
					$('body').unbind('mouseup', HonStopDrag).unbind('mousemove', HupdateScroll);
					HdragMiddle = percentInViewX*paneWidth/2;
					//moveIntervals();
					
					if ($.browser.msie) {
						$('body').unbind('dragstart', HignoreNativeDrag).unbind('selectstart', HignoreNativeDrag);
					}
				};
				var HpositionDrag = function(destX)
				{
					//Figure out if we need to adjust because of intervals.
					//evaluateIntervals(HdragPosition, destX);
					destX = destX < 0 ? 0 : (destX > HmaxX ? HmaxX : destX);
					HdragPosition = destX;

					$Hdrag.css({'left':destX +'px'});
					var p = destX / HmaxX;
					//_jscr_originalPos[currentId] = (paneWidth-contentWidth) * p * -1;
					$Hpane.css({'left':((paneWidth-contentWidth)*p) + 'px'});
					$this.trigger('scroll');
				};
				
				var HupdateScroll = function(e)
				{
					HpositionDrag(HgetPos(e, 'X') - HcurrentOffset.left - HdragMiddle);
				};
				
				/*var evaluateIntervals = function(position, destX) { 
	
					if((HintervalMove == false) && (mouseWheelMove != true)) { 
							_jscr_trackInt[currentId] = -1;
							halfInter = -1;
							
							smallInter = -1;
							bigInter = -1;
							
							endDragPos = destX + $Hdrag.width();
							fullTrackWidth = $('.jScrollPaneTrackBottom').width();

							for(inter in trackIntervals) { 
								if((endDragPos >= fullTrackWidth) && (endDragPos >= trackIntervals[inter])) {
									_jscr_trackInt[currentId] = inter;
								} else if(destX >= trackIntervals[inter]) {
									smallInter = inter;
								}	else { 
									bigInter = inter;
									break;
								}
								
							}

							if(_jscr_trackInt[currentId] == -1) {
								smallDistance = destX - trackIntervals[smallInter];
								largeDistance = trackIntervals[bigInter] - destX;
								
								if(smallDistance <= largeDistance) {
									_jscr_trackInt[currentId] = smallInter;
								} else { 
									_jscr_trackInt[currentId] = bigInter;
								}
							}
					} else { 
						HintervalMove = false;
					}
	
				}*/
				
				/*var moveIntervals = function() { 
					if(_jscr_trackInt[currentId] != -1) { 
						//Catching arrow clicks
						if(HarrowUp == true) { 
							if((Hdirection == -1) && (_jscr_trackInt[currentId] != 0)) { 
								_jscr_trackInt[currentId] = HcurrentInterval - 1;
							} else if((Hdirection == 1) && (_jscr_trackInt[currentId] != (_jscr_intervals.length -1))) {
								_jscr_trackInt[currentId] = parseInt(HcurrentInterval) + 1;
							}
							HarrowUp = false;
						} 
						
						HintervalMove = true;
						HpositionDrag(trackIntervals[_jscr_trackInt[currentId]]);
						HcurrentInterval = _jscr_trackInt[currentId];
					}
				}*/
				
				var HarrowSize = 0;
				
				if(settings.showArrows == true) {
					HarrowSize = settings.arrowSize;
				} 
				
				var HdragH = Math.max(Math.min(percentInViewX*(paneWidth-HarrowSize*2), settings.dragMaxWidth), settings.dragMinWidth);
				
				$Hdrag.css(
					{'width':HdragH+'px'}
				).bind('mousedown', HonStartDrag);
				
				var HtrackScrollInterval;
				var HtrackScrollInc;
				var HtrackScrollMousePos;
				var HdoTrackScroll = function()
				{
					if (HtrackScrollInc > 8 || HtrackScrollInc%4==0) {
						HpositionDrag((HdragPosition - ((HdragPosition - HtrackScrollMousePos) / 2)));
					}
					HtrackScrollInc ++;
				};
				var HonStopTrackClick = function()
				{
					clearInterval(HtrackScrollInterval);
					//moveIntervals();
					$('body').unbind('mouseup', HonStopTrackClick).unbind('mousemove', HonTrackMouseMove);
				};
				var HonTrackMouseMove = function(event)
				{
					HtrackScrollMousePos = HgetPos(event, 'X') - HcurrentOffset.left - HdragMiddle;
				};
				var HonTrackClick = function(event)
				{
					HinitDrag();
					HonTrackMouseMove(event);
					HtrackScrollInc = 0;
					$('body').bind('mouseup', HonStopTrackClick).bind('mousemove', HonTrackMouseMove);
					HtrackScrollInterval = setInterval(HdoTrackScroll, 100);
					HdoTrackScroll();
				};
				
				$Htrack.bind('mousedown', HonTrackClick);
				
				// if the mousewheel plugin has been included then also react to the mousewheel
//				if ($Hcontainer.mousewheel) {

//					$Hcontainer.mousewheel (
//						function (event, delta) {
//							var movePos = -1;
//							
//							if($.browser.opera) {
//								delta = event.wheelDelta / 120;	
//							}

//							//The following handles intervals with the mouse wheel
//							/*if(trackIntervals.length > 1) {
//								mouseWheelMove = true;
//										
//								//increase or decrease the interval we are currently on, depending
//								//on the Hdirection of the mouse wheel
//								if(delta < 0) {
//									_jscr_trackInt[currentId] = parseInt(_jscr_trackInt[currentId]) + 1;

//									if((_jscr_trackInt[currentId]) >= trackIntervals.length - 1) {
//										_jscr_trackInt[currentId] = trackIntervals.length - 1;
//									}
//									
//									//If the next interval is beyond the dragWidth then recalculate.
//									if((parseInt($Hdrag.width())+ parseInt(trackIntervals[_jscr_trackInt[currentId]])) > parseInt($('.jScrollPaneTrackBottom').width())) {
//										movePos = parseInt($('.jScrollPaneTrackBottom').width()) - $Hdrag.width();
//									}
//									
//								} else { 
//									_jscr_trackInt[currentId] = parseInt(_jscr_trackInt[currentId]) - 1;
//									if(_jscr_trackInt[currentId] < 0) {
//										_jscr_trackInt[currentId] = 0;
//									}
//								}
//							}*/

//							HinitDrag();
//							HceaseAnimation();
//							var d = HdragPosition;
//							
//							//when intervals are in use, mouseWheelMove is set to true
//							/*if(mouseWheelMove == true) {
//								if(movePos == -1) {
//									HpositionDrag(trackIntervals[_jscr_trackInt[currentId]]);
//								} else {
//									HpositionDrag(movePos);
//								}
//							} */
//							
//							/*if (mouseWheelMove == true) {
//								HpositionDrag(movePos);
//							}
//							else {
//								HpositionDrag(HdragPosition - delta * HmouseWheelMultiplier);
//							}*/
//							
//							//moveIntervals();
//							var dragOccured = d != HdragPosition;
//							//mouseWheelMove = false;
//							return !dragOccured;
//						},
//						false
//					);					
//				}
				var H_animateToPosition;
				var H_animateToInterval;
				function HanimateToPosition()
				{

					var diff = (H_animateToPosition - HdragPosition) / settings.animateStep;
					
					if ((diff > 1 || diff < -1) && ((HdragPosition + diff + $Hdrag.width()) < (paneWidth))) {
						HpositionDrag(HdragPosition + diff);
					} else {
						HpositionDrag(H_animateToPosition);
						HceaseAnimation();
					}
				}
				var HceaseAnimation = function()
				{
					if (H_animateToInterval) {
						clearInterval(H_animateToInterval);
						delete H_animateToPosition;
					}
				};
				var HscrollTo = function(pos, preventAni)
				{
					if (typeof pos == "string") {
						$e = jQuery(pos, this);

						if (!$e.length) return;
						pos = $e.position().left;
					}

					HceaseAnimation();
					var destHdragPosition = -pos/(paneWidth-contentWidth) * HmaxX;
					if (!preventAni || settings.animateTo) {
						H_animateToPosition = destHdragPosition;
						H_animateToInterval = setInterval(HanimateToPosition, settings.animateInterval);
		
					} else {
						HpositionDrag(destHdragPosition);
					}	
				};
				$this[0].scrollTo = HscrollTo;
				
				$this[0].scrollBy = function(delta)
				{
					var currentPos = -parseInt($Hpane.css('left')) || 0;
					HscrollTo(currentPos + delta);
				};
				
				HinitDrag();
				
				HscrollTo(-currentScrollPositionX, true);
				
				$.jScrollPane.active.push($this[0]);

			} else {
				var HscrollTo = function(pos, preventAni) {}
				$this[0].scrollTo = HscrollTo;
				
				$this.css(
					{
						'height':paneHeight-this.originalSidePaddingTotal+'px',
						//'width': paneWidth+'px',
						//TODO: temp solution
						'padding-top':0+'px',
						'padding-bottom' : 0 + 'px'
					}
				);
				// remove from active list?
			}
			
		}
	)
};

$.fn.jScrollPane.defaults = {
	scrollbarWidth : 10,
	scrollbarHeight : 10,
	scrollbarMargin : 5,
	wheelSpeed : 18,
	showArrows : false,
	arrowSize : 0,
	animateTo : false,
	dragMinHeight : 1,
	dragMaxHeight : 99999,
	dragMinWidth : 1,
	dragMaxWidth : 99999,
	animateInterval : 100,
	animateStep: 3,
	maintainPosition: true,
	scrollbarOnLeft: false,
	reinitialiseOnImageLoad: false,
	contentHeight : -1,
	contentWidth : -1
};

// clean up the scrollTo expandos
$(window)
	.bind('unload', function() {
		var els = $.jScrollPane.active; 
		for (var i=0; i<els.length; i++) {
			els[i].scrollTo = els[i].scrollBy = null;
		}
		
	}
);

})(jQuery);
