jQuery.jScrollPane = {
active : []
};jQuery.fn.jScrollPane = function(settings){
settings = jQuery.extend({
scrollbarWidth : 12,
scrollbarMargin : 5,
wheelSpeed : 18,
showArrows : false,
arrowSize : 0,
animateTo : false,
dragMinHeight : 1,
dragMaxHeight : 99999,
animateInterval : 100,
animateStep: 3,
maintainPosition: true,
scrollbarOnLeft: false
}, settings);
return this.each(
function(){
var $this = jQuery(this);
if (jQuery(this).parent().is('.jScrollPaneContainer')) {
var currentScrollPosition = settings.maintainPosition ? $this.offset({relativeTo:jQuery(this).parent()[0]}).top : 0;
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 {
var currentScrollPosition = 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);
var paneWidth = $this.innerWidth();
var paneHeight = $this.innerHeight();
var trackHeight = paneHeight;
$this.wrap(
jQuery('<div></div>').attr(
{'className':'jScrollPaneContainer'}
).css({
'height':paneHeight+'px', 
'width':paneWidth+'px'}));
jQuery(document).bind(
'emchange', 
function(e, cur, prev){
$this.jScrollPane(settings);});}
var p = this.originalSidePaddingTotal;
var cssToApply = {
'height':'auto',
'width':paneWidth - settings.scrollbarWidth - settings.scrollbarMargin - p + 'px'}
if(settings.scrollbarOnLeft) {
cssToApply.paddingLeft = settings.scrollbarMargin + settings.scrollbarWidth + 'px';
} else {
cssToApply.paddingRight = settings.scrollbarMargin + 'px';}
$this.css(cssToApply);
var contentHeight = $this.outerHeight();
var percentInView = paneHeight / contentHeight;
if (percentInView < .99) {
var $container = $this.parent();
$container.append(
jQuery('<div></div>').attr({'className':'jScrollPaneTrack'}).css({'width':settings.scrollbarWidth+'px'}).append(
jQuery('<div></div>').attr({'className':'jScrollPaneTrackTop'}).css({'width':settings.scrollbarWidth+'px'}),
jQuery('<div></div>').attr({'className':'jScrollPaneTrackBottom'}).css({'width':settings.scrollbarWidth+'px'}),
jQuery('<div></div>').attr({'className':'jScrollPaneDrag'}).css({'width':settings.scrollbarWidth+'px'}).append(
jQuery('<div></div>').attr({'className':'jScrollPaneDragTop'}).css({'width':settings.scrollbarWidth+'px'}),
jQuery('<div></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('html').unbind('mouseup', onArrowMouseUp);
currentArrowButton.removeClass('jScrollActiveArrowButton');
clearInterval(currentArrowInterval);};
var onArrowMouseDown = function() {
jQuery('html').bind('mouseup', onArrowMouseUp);
currentArrowButton.addClass('jScrollActiveArrowButton');
currentArrowInc = 0;
whileArrowButtonDown();
currentArrowInterval = setInterval(whileArrowButtonDown, 100);};
$container
.append(
jQuery('<a></a>')
.attr({'href':'javascript:;', 'className':'jScrollArrowUp'})
.css({'width':settings.scrollbarWidth+'px'})
.html('Scroll up')
.bind('mousedown', function(){
currentArrowButton = jQuery(this);
currentArrowDirection = -1;
onArrowMouseDown();
this.blur();
return false;}),
jQuery('<a></a>')
.attr({'href':'javascript:;', 'className':'jScrollArrowDown'})
.css({'width':settings.scrollbarWidth+'px'})
.html('Scroll down')
.bind('mousedown', function(){
currentArrowButton = jQuery(this);
currentArrowDirection = 1;
onArrowMouseDown();
this.blur();
return false;}));
var $upArrow = jQuery('>.jScrollArrowUp', $container);
var $downArrow = jQuery('>.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 = 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('html').bind('mouseup', onStopDrag).bind('mousemove', updateScroll);
if (jQuery.browser.msie) {
jQuery('html').bind('dragstart', ignoreNativeDrag).bind('selectstart', ignoreNativeDrag);}
return false;};
var onStopDrag = function(){
jQuery('html').unbind('mouseup', onStopDrag).unbind('mousemove', updateScroll);
dragMiddle = percentInView*paneHeight/2;
if (jQuery.browser.msie) {
jQuery('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(percentInView*(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);
jQuery('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;
jQuery('html').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) / 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 = jQuery(pos, this);
if (!$e.length) return;
pos = $e.offset().top - $this.offset().top;}
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(-currentScrollPosition, true);
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;}});
