Blame | Last modification | View Log | RSS feed
/*!* jScrollPane - v2.0.0beta2 - 2010-08-21* http://jscrollpane.kelvinluck.com/** Copyright (c) 2010 Kelvin Luck* Dual licensed under the MIT and GPL licenses.*/// Script: jScrollPane - cross browser customisable scrollbars//// *Version: 2.0.0beta2, Last updated: 2010-08-21*//// Project Home - http://jscrollpane.kelvinluck.com/// GitHub - http://github.com/vitch/jScrollPane// Source - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.js// (Minified) - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.min.js//// About: License//// Copyright (c) 2010 Kelvin Luck// Dual licensed under the MIT or GPL Version 2 licenses.// http://jscrollpane.kelvinluck.com/MIT-LICENSE.txt// http://jscrollpane.kelvinluck.com/GPL-LICENSE.txt//// About: Examples//// All examples and demos are available through the jScrollPane example site at:// http://jscrollpane.kelvinluck.com///// About: Support and Testing//// This plugin is tested on the browsers below and has been found to work reliably on them. If you run// into a problem on one of the supported browsers then please visit the support section on the jScrollPane// website (http://jscrollpane.kelvinluck.com/) for more information on getting support. You are also// welcome to fork the project on GitHub if you can contribute a fix for a given issue.//// jQuery Versions - 1.4.2// Browsers Tested - Firefox 3.6.8, Safari 5, Opera 10.6, Chrome 5.0, IE 6, 7, 8//// About: Release History//// 2.0.0beta2 - (2010-08-21) Bug fixes// 2.0.0beta1 - (2010-08-17) Rewrite to follow modern best practices and enable horizontal scrolling, initially hidden// elements and dynamically sized elements.// 1.x - (2006-12-31 - 2010-07-31) Initial version, hosted at googlecode, deprecated(function($,window,undefined){$.fn.jScrollPane = function(settings){// JScrollPane "class" - public methods are available through $('selector').data('jsp')function JScrollPane(elem, s){var settings, jsp = this, pane, paneWidth, paneHeight, container, contentWidth, contentHeight,percentInViewH, percentInViewV, isScrollableV, isScrollableH, verticalDrag, dragMaxY,verticalDragPosition, horizontalDrag, dragMaxX, horizontalDragPosition,verticalBar, verticalTrack, scrollbarWidth, verticalTrackHeight, verticalDragHeight, arrowUp, arrowDown,horizontalBar, horizontalTrack, horizontalTrackWidth, horizontalDragWidth, arrowLeft, arrowRight,reinitialiseInterval, originalPadding, originalPaddingTotalWidth, previousPaneWidth,wasAtTop = wasAtLeft = true, wasAtBottom = wasAtRight = false;originalPadding = elem.css('paddingTop') + ' ' +elem.css('paddingRight') + ' ' +elem.css('paddingBottom') + ' ' +elem.css('paddingLeft');originalPaddingTotalWidth = (parseInt(elem.css('paddingLeft')) || 0) +(parseInt(elem.css('paddingRight')) || 0);initialise(s);function initialise(s){var clonedElem, tempWrapper, /*firstChild, lastChild, */isMaintainingPositon, lastContentX, lastContentY,hasContainingSpaceChanged;settings = s;if (pane == undefined) {elem.css({'overflow': 'hidden','padding': 0});// TODO: Deal with where width/ height is 0 as it probably means the element is hidden and we should// come back to it later and check once it is unhidden...paneWidth = elem.innerWidth() + originalPaddingTotalWidth;paneHeight = elem.innerHeight();elem.width(paneWidth);pane = $('<div class="jspPane" />').wrap($('<div class="jspContainer" />').css({'width': paneWidth + 'px','height': paneHeight + 'px'}));elem.wrapInner(pane.parent());// Need to get the vars after being added to the document, otherwise they reference weird// disconnected orphan elements...container = elem.find('>.jspContainer');pane = container.find('>.jspPane');pane.css('padding', originalPadding);/*// Move any margins from the first and last children up to the container so they can still// collapse with neighbouring elements as they would before jScrollPanefirstChild = pane.find(':first-child');lastChild = pane.find(':last-child');elem.css({'margin-top': firstChild.css('margin-top'),'margin-bottom': lastChild.css('margin-bottom')});firstChild.css('margin-top', 0);lastChild.css('margin-bottom', 0);*/} else {elem.css('width', null);hasContainingSpaceChanged = elem.outerWidth() + originalPaddingTotalWidth != paneWidth || elem.outerHeight() != paneHeight;if (hasContainingSpaceChanged) {paneWidth = elem.innerWidth() + originalPaddingTotalWidth;paneHeight = elem.innerHeight();container.css({'width': paneWidth + 'px','height': paneHeight + 'px'});}previousPaneWidth = pane.innerWidth();if (!hasContainingSpaceChanged && pane.outerWidth() == contentWidth && pane.outerHeight() == contentHeight) {// Nothing has changed since we last initialisedif (isScrollableH || isScrollableV) { // If we had already set a width then re-set itpane.css('width', previousPaneWidth + 'px');elem.css('width', (previousPaneWidth + originalPaddingTotalWidth) + 'px');}// Then abort...return;}pane.css('width', null);elem.css('width', (paneWidth + originalPaddingTotalWidth) + 'px');container.find('>.jspVerticalBar,>.jspHorizontalBar').remove().end();}// Unfortunately it isn't that easy to find out the width of the element as it will always report the// width as allowed by its container, regardless of overflow settings.// A cunning workaround is to clone the element, set its position to absolute and place it in a narrow// container. Now it will push outwards to its maxium real width...clonedElem = pane.clone().css('position', 'absolute');tempWrapper = $('<div style="width:1px; position: relative;" />').append(clonedElem);$('body').append(tempWrapper);contentWidth = Math.max(pane.outerWidth(), clonedElem.outerWidth());tempWrapper.remove();contentHeight = pane.outerHeight();percentInViewH = contentWidth / paneWidth;percentInViewV = contentHeight / paneHeight;isScrollableV = percentInViewV > 1;isScrollableH = percentInViewH > 1;//console.log(paneWidth, paneHeight, contentWidth, contentHeight, percentInViewH, percentInViewV, isScrollableH, isScrollableV);if (!(isScrollableH || isScrollableV)) {elem.removeClass('jspScrollable');pane.css({'top': 0,'width': container.width() + 'px'});removeMousewheel();removeFocusHandler();unhijackInternalLinks();} else {elem.addClass('jspScrollable');isMaintainingPositon = settings.maintainPosition && (verticalDragPosition || horizontalDragPosition);if (isMaintainingPositon) {lastContentX = contentPositionX();lastContentY = contentPositionY();}initialiseVerticalScroll();initialiseHorizontalScroll();resizeScrollbars();if (isMaintainingPositon) {scrollToX(lastContentX);scrollToY(lastContentY);}initFocusHandler();initMousewheel();observeHash();if (settings.hijackInternalLinks) {hijackInternalLinks();}}if (settings.autoReinitialise && !reinitialiseInterval) {reinitialiseInterval = setInterval(function(){initialise(settings);},settings.autoReinitialiseDelay);} else if (!settings.autoReinitialise && reinitialiseInterval) {clearInterval(reinitialiseInterval)}elem.trigger('jsp-initialised', [isScrollableH || isScrollableV]);}function initialiseVerticalScroll(){if (isScrollableV) {container.append($('<div class="jspVerticalBar" />').append($('<div class="jspCap jspCapTop" />'),$('<div class="jspTrack" />').append($('<div class="jspDrag" />').append($('<div class="jspDragTop" />'),$('<div class="jspDragBottom" />'))),$('<div class="jspCap jspCapBottom" />')));verticalBar = container.find('>.jspVerticalBar');verticalTrack = verticalBar.find('>.jspTrack');verticalDrag = verticalTrack.find('>.jspDrag');if (settings.showArrows) {arrowUp = $('<a class="jspArrow jspArrowUp" />').bind('mousedown.jsp', getArrowScroll(0, -1)).bind('click.jsp', nil);arrowDown = $('<a class="jspArrow jspArrowDown" />').bind('mousedown.jsp', getArrowScroll(0, 1)).bind('click.jsp', nil);if (settings.arrowScrollOnHover) {arrowUp.bind('mouseover.jsp', getArrowScroll(0, -1, arrowUp));arrowDown.bind('mouseover.jsp', getArrowScroll(0, 1, arrowDown));}appendArrows(verticalTrack, settings.verticalArrowPositions, arrowUp, arrowDown);}verticalTrackHeight = paneHeight;container.find('>.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow').each(function(){verticalTrackHeight -= $(this).outerHeight();});verticalDrag.hover(function(){verticalDrag.addClass('jspHover');},function(){verticalDrag.removeClass('jspHover');}).bind('mousedown.jsp',function(e){// Stop IE from allowing text selection$('html').bind('dragstart.jsp selectstart.jsp', function() { return false; });verticalDrag.addClass('jspActive');var startY = e.pageY - verticalDrag.position().top;$('html').bind('mousemove.jsp',function(e){positionDragY(e.pageY - startY, false);}).bind('mouseup.jsp mouseleave.jsp', cancelDrag);return false;});sizeVerticalScrollbar();updateVerticalArrows();}}function sizeVerticalScrollbar(){verticalTrack.height(verticalTrackHeight + 'px');verticalDragPosition = 0;scrollbarWidth = settings.verticalGutter + verticalTrack.outerWidth();// Make the pane thinner to allow for the vertical scrollbarpane.width(paneWidth - scrollbarWidth - originalPaddingTotalWidth+4);// Add margin to the left of the pane if scrollbars are on that side (to position// the scrollbar on the left or right set it's left or right property in CSS)if (verticalBar.position().left == 0) {pane.css('margin-left', scrollbarWidth + 'px');}}function initialiseHorizontalScroll(){if (isScrollableH) {container.append($('<div class="jspHorizontalBar" />').append($('<div class="jspCap jspCapLeft" />'),$('<div class="jspTrack" />').append($('<div class="jspDrag" />').append($('<div class="jspDragLeft" />'),$('<div class="jspDragRight" />'))),$('<div class="jspCap jspCapRight" />')));horizontalBar = container.find('>.jspHorizontalBar');horizontalTrack = horizontalBar.find('>.jspTrack');horizontalDrag = horizontalTrack.find('>.jspDrag');if (settings.showArrows) {arrowLeft = $('<a class="jspArrow jspArrowLeft" />').bind('mousedown.jsp', getArrowScroll(-1, 0)).bind('click.jsp', nil);arrowRight = $('<a class="jspArrow jspArrowRight" />').bind('mousedown.jsp', getArrowScroll(1, 0)).bind('click.jsp', nil);if (settings.arrowScrollOnHover) {arrowLeft.bind('mouseover.jsp', getArrowScroll(-1, 0, arrowLeft));arrowRight.bind('mouseover.jsp', getArrowScroll(1, 0, arrowRight));}appendArrows(horizontalTrack, settings.horizontalArrowPositions, arrowLeft, arrowRight);}horizontalDrag.hover(function(){horizontalDrag.addClass('jspHover');},function(){horizontalDrag.removeClass('jspHover');}).bind('mousedown.jsp',function(e){// Stop IE from allowing text selection$('html').bind('dragstart.jsp selectstart.jsp', function() { return false; });horizontalDrag.addClass('jspActive');var startX = e.pageX - horizontalDrag.position().left;$('html').bind('mousemove.jsp',function(e){positionDragX(e.pageX - startX, false);}).bind('mouseup.jsp mouseleave.jsp', cancelDrag);return false;});horizontalTrackWidth = container.innerWidth();sizeHorizontalScrollbar();updateHorizontalArrows();} else {// no horizontal scroll}}function sizeHorizontalScrollbar(){container.find('>.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow').each(function(){horizontalTrackWidth -= $(this).outerWidth();});horizontalTrack.width(horizontalTrackWidth + 'px');horizontalDragPosition = 0;}function resizeScrollbars(){if (isScrollableH && isScrollableV) {var horizontalTrackHeight = horizontalTrack.outerHeight(),verticalTrackWidth = verticalTrack.outerWidth();verticalTrackHeight -= horizontalTrackHeight;$(horizontalBar).find('>.jspCap:visible,>.jspArrow').each(function(){horizontalTrackWidth += $(this).outerWidth();});horizontalTrackWidth -= verticalTrackWidth;paneHeight -= verticalTrackWidth;paneWidth -= horizontalTrackHeight;horizontalTrack.parent().append($('<div class="jspCorner" />').css('width', horizontalTrackHeight + 'px'));sizeVerticalScrollbar();sizeHorizontalScrollbar();}// reflow contentif (isScrollableH) {pane.width((container.outerWidth() - originalPaddingTotalWidth) + 'px');}contentHeight = pane.outerHeight();percentInViewV = contentHeight / paneHeight;if (isScrollableH) {horizontalDragWidth = 1 / percentInViewH * horizontalTrackWidth;if (horizontalDragWidth > settings.horizontalDragMaxWidth) {horizontalDragWidth = settings.horizontalDragMaxWidth;} else if (horizontalDragWidth < settings.horizontalDragMinWidth) {horizontalDragWidth = settings.horizontalDragMinWidth;}horizontalDrag.width(horizontalDragWidth + 'px');dragMaxX = horizontalTrackWidth - horizontalDragWidth;}if (isScrollableV) {verticalDragHeight = 1 / percentInViewV * verticalTrackHeight;if (verticalDragHeight > settings.verticalDragMaxHeight) {verticalDragHeight = settings.verticalDragMaxHeight;} else if (verticalDragHeight < settings.verticalDragMinHeight) {verticalDragHeight = settings.verticalDragMinHeight;}verticalDrag.height(verticalDragHeight + 'px');dragMaxY = verticalTrackHeight - verticalDragHeight;}}function appendArrows(ele, p, a1, a2){var p1 = "before", p2 = "after", aTemp;// Sniff for mac... Is there a better way to determine whether the arrows would naturally appear// at the top or the bottom of the bar?if (p == "os") {p = /Mac/.test(navigator.platform) ? "after" : "split";}if (p == p1) {p2 = p;} else if (p == p2) {p1 = p;aTemp = a1;a1 = a2;a2 = aTemp;}ele[p1](a1)[p2](a2);}function getArrowScroll(dirX, dirY, ele) {return function(){arrowScroll(dirX, dirY, this, ele);this.blur();return false;}}function arrowScroll(dirX, dirY, arrow, ele){arrow = $(arrow).addClass('jspActive');var eve, doScroll = function(){if (dirX != 0) {positionDragX(horizontalDragPosition + dirX * settings.arrowButtonSpeed, false);}if (dirY != 0) {positionDragY(verticalDragPosition + dirY * settings.arrowButtonSpeed, false);}},scrollInt = setInterval(doScroll, settings.arrowRepeatFreq);doScroll();eve = ele == undefined ? 'mouseup.jsp' : 'mouseout.jsp';ele = ele || $('html');ele.bind(eve,function(){arrow.removeClass('jspActive');clearInterval(scrollInt);ele.unbind(eve);});}function cancelDrag(){$('html').unbind('dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp');verticalDrag && verticalDrag.removeClass('jspActive');horizontalDrag && horizontalDrag.removeClass('jspActive');}function positionDragY(destY, animate){if (!isScrollableV) {return;}if (destY < 0) {destY = 0;} else if (destY > dragMaxY) {destY = dragMaxY;}// can't just check if(animate) because false is a valid value that could be passed in...if (animate == undefined) {animate = settings.animateScroll;}if (animate) {jsp.animate(verticalDrag, 'top', destY, _positionDragY);} else {verticalDrag.css('top', destY);_positionDragY(destY);}}function _positionDragY(destY){if (destY == undefined) {destY = verticalDrag.position().top;}container.scrollTop(0);verticalDragPosition = destY;var isAtTop = verticalDragPosition == 0,isAtBottom = verticalDragPosition == dragMaxY,percentScrolled = destY/ dragMaxY,destTop = -percentScrolled * (contentHeight - paneHeight);if (wasAtTop != isAtTop || wasAtBottom != isAtBottom) {wasAtTop = isAtTop;wasAtBottom = isAtBottom;elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);}updateVerticalArrows(isAtTop, isAtBottom);pane.css('top', destTop);elem.trigger('jsp-scroll-y', [-destTop, isAtTop, isAtBottom]);}function positionDragX(destX, animate){if (!isScrollableH) {return;}if (destX < 0) {destX = 0;} else if (destX > dragMaxX) {destX = dragMaxX;}if (animate == undefined) {animate = settings.animateScroll;}if (animate) {jsp.animate(horizontalDrag, 'left', destX, _positionDragX);} else {horizontalDrag.css('left', destX);_positionDragX(destX);}}function _positionDragX(destX){if (destX == undefined) {destX = horizontalDrag.position().left;}container.scrollTop(0);horizontalDragPosition = destX;var isAtLeft = horizontalDragPosition == 0,isAtRight = horizontalDragPosition == dragMaxY,percentScrolled = destX / dragMaxX,destLeft = -percentScrolled * (contentWidth - paneWidth);if (wasAtLeft != isAtLeft || wasAtRight != isAtRight) {wasAtLeft = isAtLeft;wasAtRight = isAtRight;elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);}updateHorizontalArrows(isAtLeft, isAtRight);pane.css('left', destLeft);elem.trigger('jsp-scroll-x', [-destLeft, isAtLeft, isAtRight]);}function updateVerticalArrows(isAtTop, isAtBottom){if (settings.showArrows) {arrowUp[isAtTop ? 'addClass' : 'removeClass']('jspDisabled');arrowDown[isAtBottom ? 'addClass' : 'removeClass']('jspDisabled');}}function updateHorizontalArrows(isAtLeft, isAtRight){if (settings.showArrows) {arrowLeft[isAtLeft ? 'addClass' : 'removeClass']('jspDisabled');arrowRight[isAtRight ? 'addClass' : 'removeClass']('jspDisabled');}}function scrollToY(destY, animate){var percentScrolled = destY / (contentHeight - paneHeight);positionDragY(percentScrolled * dragMaxY, animate);}function scrollToX(destX, animate){var percentScrolled = destX / (contentWidth - paneWidth);positionDragX(percentScrolled * dragMaxX, animate);}function scrollToElement(ele, stickToTop, animate){var e, eleHeight, eleTop = 0, viewportTop, maxVisibleEleTop, destY;// Legal hash values aren't necessarily legal jQuery selectors so we need to catch any// errors from the lookup...try {e = $(ele);} catch (err) {return;}eleHeight = e.outerHeight();container.scrollTop(0);// loop through parents adding the offset top of any elements that are relatively positioned between// the focused element and the jspPane so we can get the true distance from the top// of the focused element to the top of the scrollpane...while (!e.is('.jspPane')) {eleTop += e.position().top;e = e.offsetParent();if (/^body|html$/i.test(e[0].nodeName)) {// we ended up too high in the document structure. Quit!return;}}viewportTop = contentPositionY();maxVisibleEleTop = viewportTop + paneHeight;if (eleTop < viewportTop || stickToTop) { // element is above viewportdestY = eleTop - settings.verticalGutter;} else if (eleTop + eleHeight > maxVisibleEleTop) { // element is below viewportdestY = eleTop - paneHeight + eleHeight + settings.verticalGutter;}if (destY) {scrollToY(destY, animate);}// TODO: Implement automatic horizontal scrolling?}function contentPositionX(){return -pane.position().left;}function contentPositionY(){return -pane.position().top;}function initMousewheel(){container.unbind('mousewheel.jsp').bind('mousewheel.jsp',function (event, delta, deltaX, deltaY) {var dX = horizontalDragPosition, dY = verticalDragPosition;positionDragX(horizontalDragPosition + deltaX * settings.mouseWheelSpeed, false)positionDragY(verticalDragPosition - deltaY * settings.mouseWheelSpeed, false);// return true if there was no movement so rest of screen can scrollreturn dX == horizontalDragPosition && dY == verticalDragPosition;});}function removeMousewheel(){container.unbind('mousewheel.jsp');}function nil(){return false;}function initFocusHandler(){pane.unbind('focusin.jsp').bind('focusin.jsp',function(e){scrollToElement(e.target, false);});}function removeFocusHandler(){pane.unbind('focusin.jsp');}function observeHash(){if (location.hash && location.hash.length > 1) {var e, retryInt;try {e = $(location.hash);} catch (err) {return;}if (e.length && pane.find(e)) {// nasty workaround but it appears to take a little while before the hash has done its thing// to the rendered page so we just wait until the container's scrollTop has been messed up.if (container.scrollTop() == 0) {retryInt = setInterval(function(){if (container.scrollTop() > 0) {scrollToElement(location.hash, true);$(document).scrollTop(container.position().top);clearInterval(retryInt);}},50)} else {scrollToElement(location.hash, true);$(document).scrollTop(container.position().top);}}}}function unhijackInternalLinks(){$('a.jspHijack').unbind('click.jsp-hijack').removeClass('jspHijack');}function hijackInternalLinks(){unhijackInternalLinks();$('a[href^=#]').addClass('jspHijack').bind('click.jsp-hijack',function(){var uriParts = this.href.split('#'), hash;if (uriParts.length > 1) {hash = uriParts[1];if (hash.length > 0 && pane.find('#' + hash).length > 0) {scrollToElement('#' + hash, true);// Need to return false otherwise things mess up... Would be nice to maybe also scroll// the window to the top of the scrollpane?return false;}}})}// Public API$.extend(jsp,{// Reinitialises the scroll pane (if it's internal dimensions have changed since the last time it// was initialised). The settings object which is passed in will override any settings from the// previous time it was initialised - if you don't pass any settings then the ones from the previous// initialisation will be used.reinitialise: function(s){s = $.extend({}, s, settings);initialise(s);},// Scrolls the specified element (a jQuery object, DOM node or jQuery selector string) into view so// that it can be seen within the viewport. If stickToTop is true then the element will appear at// the top of the viewport, if it is false then the viewport will scroll as little as possible to// show the element. You can also specify if you want animation to occur. If you don't provide this// argument then the animateScroll value from the settings object is used instead.scrollToElement: function(ele, stickToTop, animate){scrollToElement(ele, stickToTop, animate);},// Scrolls the pane so that the specified co-ordinates within the content are at the top left// of the viewport. animate is optional and if not passed then the value of animateScroll from// the settings object this jScrollPane was initialised with is used.scrollTo: function(destX, destY, animate){scrollToX(destX, animate);scrollToY(destY, animate);},// Scrolls the pane so that the specified co-ordinate within the content is at the left of the// viewport. animate is optional and if not passed then the value of animateScroll from the settings// object this jScrollPane was initialised with is used.scrollToX: function(destX, animate){scrollToX(destX, animate);},// Scrolls the pane so that the specified co-ordinate within the content is at the top of the// viewport. animate is optional and if not passed then the value of animateScroll from the settings// object this jScrollPane was initialised with is used.scrollToY: function(destY, animate){scrollToY(destY, animate);},// Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then// the value of animateScroll from the settings object this jScrollPane was initialised with is used.scrollBy: function(deltaX, deltaY, animate){jsp.scrollByX(deltaX, animate);jsp.scrollByY(deltaY, animate);},// Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then// the value of animateScroll from the settings object this jScrollPane was initialised with is used.scrollByX: function(deltaX, animate){var destX = contentPositionX() + deltaX,percentScrolled = destX / (contentWidth - paneWidth);positionDragX(percentScrolled * dragMaxX, animate);},// Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then// the value of animateScroll from the settings object this jScrollPane was initialised with is used.scrollByY: function(deltaY, animate){var destY = contentPositionY() + deltaY,percentScrolled = destY / (contentHeight - paneHeight);positionDragY(percentScrolled * dragMaxY, animate);},// This method is called when jScrollPane is trying to animate to a new position. You can override// it if you want to provide advanced animation functionality. It is passed the following arguments:// * ele - the element whose position is being animated// * prop - the property that is being animated// * value - the value it's being animated to// * stepCallback - a function that you must execute each time you update the value of the property// You can use the default implementation (below) as a starting point for your own implementation.animate: function(ele, prop, value, stepCallback){var params = {};params[prop] = value;ele.animate(params,{'duration' : settings.animateDuration,'ease' : settings.animateEase,'queue' : false,'step' : stepCallback});},// Returns the current x position of the viewport with regards to the content pane.getContentPositionX: function(){return contentPositionX();},// Returns the current y position of the viewport with regards to the content pane.getContentPositionY: function(){return contentPositionY();},// Returns whether or not this scrollpane has a horizontal scrollbar.getIsScrollableH: function(){return isScrollableH;},// Returns whether or not this scrollpane has a vertical scrollbar.getIsScrollableV: function(){return isScrollableV;},// Gets a reference to the content pane. It is important that you use this method if you want to// edit the content of your jScrollPane as if you access the element directly then you may have some// problems (as your original element has had additional elements for the scrollbars etc added into// it).getContentPane: function(){return pane;},// Scrolls this jScrollPane down as far as it can currently scroll. If animate isn't passed then the// animateScroll value from settings is used instead.scrollToBottom: function(animate){positionDragY(dragMaxY, animate);},// Hijacks the links on the page which link to content inside the scrollpane. If you have changed// the content of your page (e.g. via AJAX) and want to make sure any new anchor links to the// contents of your scroll pane will work then call this function.hijackInternalLinks: function(){hijackInternalLinks();}});}// Pluginifying code...settings = $.extend({}, $.fn.jScrollPane.defaults, settings);var ret;this.each(function(){var elem = $(this), jspApi = elem.data('jsp');if (jspApi) {jspApi.reinitialise(settings);} else {jspApi = new JScrollPane(elem, settings);elem.data('jsp', jspApi);}ret = ret ? ret.add(elem) : elem;})return ret;};$.fn.jScrollPane.defaults = {'showArrows' : false,'maintainPosition' : true,'autoReinitialise' : false,'autoReinitialiseDelay' : 500,'verticalDragMinHeight' : 0,'verticalDragMaxHeight' : 99999,'horizontalDragMinWidth' : 0,'horizontalDragMaxWidth' : 99999,'animateScroll' : false,'animateDuration' : 300,'animateEase' : 'linear','hijackInternalLinks' : false,'verticalGutter' : 4,'horizontalGutter' : 4,'mouseWheelSpeed' : 10,'arrowButtonSpeed' : 10,'arrowRepeatFreq' : 100,'arrowScrollOnHover' : false,'verticalArrowPositions' : 'split','horizontalArrowPositions' : 'split'};})(jQuery,this);