PageRenderTime 64ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/ajax/libs/jScrollPane/2.0.0beta9/script/jquery.jscrollpane.js

https://gitlab.com/Mirros/cdnjs
JavaScript | 1376 lines | 1081 code | 129 blank | 166 comment | 171 complexity | 77db6d33e61c0eb9b9342dfc4ce62522 MD5 | raw file
  1. /*!
  2. * jScrollPane - v2.0.0beta9 - 2011-01-31
  3. * http://jscrollpane.kelvinluck.com/
  4. *
  5. * Copyright (c) 2010 Kelvin Luck
  6. * Dual licensed under the MIT and GPL licenses.
  7. */
  8. // Script: jScrollPane - cross browser customisable scrollbars
  9. //
  10. // *Version: 2.0.0beta9, Last updated: 2011-01-31*
  11. //
  12. // Project Home - http://jscrollpane.kelvinluck.com/
  13. // GitHub - http://github.com/vitch/jScrollPane
  14. // Source - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.js
  15. // (Minified) - http://github.com/vitch/jScrollPane/raw/master/script/jquery.jscrollpane.min.js
  16. //
  17. // About: License
  18. //
  19. // Copyright (c) 2010 Kelvin Luck
  20. // Dual licensed under the MIT or GPL Version 2 licenses.
  21. // http://jscrollpane.kelvinluck.com/MIT-LICENSE.txt
  22. // http://jscrollpane.kelvinluck.com/GPL-LICENSE.txt
  23. //
  24. // About: Examples
  25. //
  26. // All examples and demos are available through the jScrollPane example site at:
  27. // http://jscrollpane.kelvinluck.com/
  28. //
  29. // About: Support and Testing
  30. //
  31. // This plugin is tested on the browsers below and has been found to work reliably on them. If you run
  32. // into a problem on one of the supported browsers then please visit the support section on the jScrollPane
  33. // website (http://jscrollpane.kelvinluck.com/) for more information on getting support. You are also
  34. // welcome to fork the project on GitHub if you can contribute a fix for a given issue.
  35. //
  36. // jQuery Versions - tested in 1.4.2+ - reported to work in 1.3.x
  37. // Browsers Tested - Firefox 3.6.8, Safari 5, Opera 10.6, Chrome 5.0, IE 6, 7, 8
  38. //
  39. // About: Release History
  40. //
  41. // 2.0.0beta9 - (2011-01-31) new API methods, bug fixes and correct keyboard support for FF/OSX
  42. // 2.0.0beta8 - (2011-01-29) touchscreen support, improved keyboard support
  43. // 2.0.0beta7 - (2011-01-23) scroll speed consistent (thanks Aivo Paas)
  44. // 2.0.0beta6 - (2010-12-07) scrollToElement horizontal support
  45. // 2.0.0beta5 - (2010-10-18) jQuery 1.4.3 support, various bug fixes
  46. // 2.0.0beta4 - (2010-09-17) clickOnTrack support, bug fixes
  47. // 2.0.0beta3 - (2010-08-27) Horizontal mousewheel, mwheelIntent, keyboard support, bug fixes
  48. // 2.0.0beta2 - (2010-08-21) Bug fixes
  49. // 2.0.0beta1 - (2010-08-17) Rewrite to follow modern best practices and enable horizontal scrolling, initially hidden
  50. // elements and dynamically sized elements.
  51. // 1.x - (2006-12-31 - 2010-07-31) Initial version, hosted at googlecode, deprecated
  52. (function($,window,undefined){
  53. $.fn.jScrollPane = function(settings)
  54. {
  55. // JScrollPane "class" - public methods are available through $('selector').data('jsp')
  56. function JScrollPane(elem, s)
  57. {
  58. var settings, jsp = this, pane, paneWidth, paneHeight, container, contentWidth, contentHeight,
  59. percentInViewH, percentInViewV, isScrollableV, isScrollableH, verticalDrag, dragMaxY,
  60. verticalDragPosition, horizontalDrag, dragMaxX, horizontalDragPosition,
  61. verticalBar, verticalTrack, scrollbarWidth, verticalTrackHeight, verticalDragHeight, arrowUp, arrowDown,
  62. horizontalBar, horizontalTrack, horizontalTrackWidth, horizontalDragWidth, arrowLeft, arrowRight,
  63. reinitialiseInterval, originalPadding, originalPaddingTotalWidth, previousContentWidth,
  64. wasAtTop = true, wasAtLeft = true, wasAtBottom = false, wasAtRight = false,
  65. originalElement = elem.clone().empty(),
  66. mwEvent = $.fn.mwheelIntent ? 'mwheelIntent.jsp' : 'mousewheel.jsp';
  67. originalPadding = elem.css('paddingTop') + ' ' +
  68. elem.css('paddingRight') + ' ' +
  69. elem.css('paddingBottom') + ' ' +
  70. elem.css('paddingLeft');
  71. originalPaddingTotalWidth = (parseInt(elem.css('paddingLeft'), 10) || 0) +
  72. (parseInt(elem.css('paddingRight'), 10) || 0);
  73. function initialise(s)
  74. {
  75. var clonedElem, tempWrapper, /*firstChild, lastChild, */isMaintainingPositon, lastContentX, lastContentY,
  76. hasContainingSpaceChanged, originalScrollTop, originalScrollLeft;
  77. settings = s;
  78. if (pane === undefined) {
  79. originalScrollTop = elem.scrollTop();
  80. originalScrollLeft = elem.scrollLeft();
  81. elem.css(
  82. {
  83. overflow: 'hidden',
  84. padding: 0
  85. }
  86. );
  87. // TODO: Deal with where width/ height is 0 as it probably means the element is hidden and we should
  88. // come back to it later and check once it is unhidden...
  89. paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
  90. paneHeight = elem.innerHeight();
  91. elem.width(paneWidth);
  92. pane = $('<div class="jspPane" />').css('padding', originalPadding).append(elem.children());
  93. container = $('<div class="jspContainer" />')
  94. .css({
  95. 'width': paneWidth + 'px',
  96. 'height': paneHeight + 'px'
  97. }
  98. ).append(pane).appendTo(elem);
  99. /*
  100. // Move any margins from the first and last children up to the container so they can still
  101. // collapse with neighbouring elements as they would before jScrollPane
  102. firstChild = pane.find(':first-child');
  103. lastChild = pane.find(':last-child');
  104. elem.css(
  105. {
  106. 'margin-top': firstChild.css('margin-top'),
  107. 'margin-bottom': lastChild.css('margin-bottom')
  108. }
  109. );
  110. firstChild.css('margin-top', 0);
  111. lastChild.css('margin-bottom', 0);
  112. */
  113. } else {
  114. elem.css('width', '');
  115. hasContainingSpaceChanged = elem.innerWidth() + originalPaddingTotalWidth != paneWidth || elem.outerHeight() != paneHeight;
  116. if (hasContainingSpaceChanged) {
  117. paneWidth = elem.innerWidth() + originalPaddingTotalWidth;
  118. paneHeight = elem.innerHeight();
  119. container.css({
  120. width: paneWidth + 'px',
  121. height: paneHeight + 'px'
  122. });
  123. }
  124. // If nothing changed since last check...
  125. if (!hasContainingSpaceChanged && previousContentWidth == contentWidth && pane.outerHeight() == contentHeight) {
  126. elem.width(paneWidth);
  127. return;
  128. }
  129. previousContentWidth = contentWidth;
  130. pane.css('width', '');
  131. elem.width(paneWidth);
  132. container.find('>.jspVerticalBar,>.jspHorizontalBar').remove().end();
  133. }
  134. // Unfortunately it isn't that easy to find out the width of the element as it will always report the
  135. // width as allowed by its container, regardless of overflow settings.
  136. // A cunning workaround is to clone the element, set its position to absolute and place it in a narrow
  137. // container. Now it will push outwards to its maxium real width...
  138. clonedElem = pane.clone().css('position', 'absolute');
  139. tempWrapper = $('<div style="width:1px; position: relative;" />').append(clonedElem);
  140. $('body').append(tempWrapper);
  141. contentWidth = Math.max(pane.outerWidth(), clonedElem.outerWidth());
  142. tempWrapper.remove();
  143. contentHeight = pane.outerHeight();
  144. percentInViewH = contentWidth / paneWidth;
  145. percentInViewV = contentHeight / paneHeight;
  146. isScrollableV = percentInViewV > 1;
  147. isScrollableH = percentInViewH > 1;
  148. //console.log(paneWidth, paneHeight, contentWidth, contentHeight, percentInViewH, percentInViewV, isScrollableH, isScrollableV);
  149. if (!(isScrollableH || isScrollableV)) {
  150. elem.removeClass('jspScrollable');
  151. pane.css({
  152. top: 0,
  153. width: container.width() - originalPaddingTotalWidth
  154. });
  155. removeMousewheel();
  156. removeFocusHandler();
  157. removeKeyboardNav();
  158. removeClickOnTrack();
  159. unhijackInternalLinks();
  160. } else {
  161. elem.addClass('jspScrollable');
  162. isMaintainingPositon = settings.maintainPosition && (verticalDragPosition || horizontalDragPosition);
  163. if (isMaintainingPositon) {
  164. lastContentX = contentPositionX();
  165. lastContentY = contentPositionY();
  166. }
  167. initialiseVerticalScroll();
  168. initialiseHorizontalScroll();
  169. resizeScrollbars();
  170. if (isMaintainingPositon) {
  171. scrollToX(lastContentX, false);
  172. scrollToY(lastContentY, false);
  173. }
  174. initFocusHandler();
  175. initMousewheel();
  176. initTouch();
  177. if (settings.enableKeyboardNavigation) {
  178. initKeyboardNav();
  179. }
  180. if (settings.clickOnTrack) {
  181. initClickOnTrack();
  182. }
  183. observeHash();
  184. if (settings.hijackInternalLinks) {
  185. hijackInternalLinks();
  186. }
  187. }
  188. if (settings.autoReinitialise && !reinitialiseInterval) {
  189. reinitialiseInterval = setInterval(
  190. function()
  191. {
  192. initialise(settings);
  193. },
  194. settings.autoReinitialiseDelay
  195. );
  196. } else if (!settings.autoReinitialise && reinitialiseInterval) {
  197. clearInterval(reinitialiseInterval);
  198. }
  199. originalScrollTop && elem.scrollTop(0) && scrollToY(originalScrollTop, false);
  200. originalScrollLeft && elem.scrollLeft(0) && scrollToX(originalScrollLeft, false);
  201. elem.trigger('jsp-initialised', [isScrollableH || isScrollableV]);
  202. }
  203. function initialiseVerticalScroll()
  204. {
  205. if (isScrollableV) {
  206. container.append(
  207. $('<div class="jspVerticalBar" />').append(
  208. $('<div class="jspCap jspCapTop" />'),
  209. $('<div class="jspTrack" />').append(
  210. $('<div class="jspDrag" />').append(
  211. $('<div class="jspDragTop" />'),
  212. $('<div class="jspDragBottom" />')
  213. )
  214. ),
  215. $('<div class="jspCap jspCapBottom" />')
  216. )
  217. );
  218. verticalBar = container.find('>.jspVerticalBar');
  219. verticalTrack = verticalBar.find('>.jspTrack');
  220. verticalDrag = verticalTrack.find('>.jspDrag');
  221. if (settings.showArrows) {
  222. arrowUp = $('<a class="jspArrow jspArrowUp" />').bind(
  223. 'mousedown.jsp', getArrowScroll(0, -1)
  224. ).bind('click.jsp', nil);
  225. arrowDown = $('<a class="jspArrow jspArrowDown" />').bind(
  226. 'mousedown.jsp', getArrowScroll(0, 1)
  227. ).bind('click.jsp', nil);
  228. if (settings.arrowScrollOnHover) {
  229. arrowUp.bind('mouseover.jsp', getArrowScroll(0, -1, arrowUp));
  230. arrowDown.bind('mouseover.jsp', getArrowScroll(0, 1, arrowDown));
  231. }
  232. appendArrows(verticalTrack, settings.verticalArrowPositions, arrowUp, arrowDown);
  233. }
  234. verticalTrackHeight = paneHeight;
  235. container.find('>.jspVerticalBar>.jspCap:visible,>.jspVerticalBar>.jspArrow').each(
  236. function()
  237. {
  238. verticalTrackHeight -= $(this).outerHeight();
  239. }
  240. );
  241. verticalDrag.hover(
  242. function()
  243. {
  244. verticalDrag.addClass('jspHover');
  245. },
  246. function()
  247. {
  248. verticalDrag.removeClass('jspHover');
  249. }
  250. ).bind(
  251. 'mousedown.jsp',
  252. function(e)
  253. {
  254. // Stop IE from allowing text selection
  255. $('html').bind('dragstart.jsp selectstart.jsp', nil);
  256. verticalDrag.addClass('jspActive');
  257. var startY = e.pageY - verticalDrag.position().top;
  258. $('html').bind(
  259. 'mousemove.jsp',
  260. function(e)
  261. {
  262. positionDragY(e.pageY - startY, false);
  263. }
  264. ).bind('mouseup.jsp mouseleave.jsp', cancelDrag);
  265. return false;
  266. }
  267. );
  268. sizeVerticalScrollbar();
  269. }
  270. }
  271. function sizeVerticalScrollbar()
  272. {
  273. verticalTrack.height(verticalTrackHeight + 'px');
  274. verticalDragPosition = 0;
  275. scrollbarWidth = settings.verticalGutter + verticalTrack.outerWidth();
  276. // Make the pane thinner to allow for the vertical scrollbar
  277. pane.width(paneWidth - scrollbarWidth - originalPaddingTotalWidth);
  278. // Add margin to the left of the pane if scrollbars are on that side (to position
  279. // the scrollbar on the left or right set it's left or right property in CSS)
  280. if (verticalBar.position().left === 0) {
  281. pane.css('margin-left', scrollbarWidth + 'px');
  282. }
  283. }
  284. function initialiseHorizontalScroll()
  285. {
  286. if (isScrollableH) {
  287. container.append(
  288. $('<div class="jspHorizontalBar" />').append(
  289. $('<div class="jspCap jspCapLeft" />'),
  290. $('<div class="jspTrack" />').append(
  291. $('<div class="jspDrag" />').append(
  292. $('<div class="jspDragLeft" />'),
  293. $('<div class="jspDragRight" />')
  294. )
  295. ),
  296. $('<div class="jspCap jspCapRight" />')
  297. )
  298. );
  299. horizontalBar = container.find('>.jspHorizontalBar');
  300. horizontalTrack = horizontalBar.find('>.jspTrack');
  301. horizontalDrag = horizontalTrack.find('>.jspDrag');
  302. if (settings.showArrows) {
  303. arrowLeft = $('<a class="jspArrow jspArrowLeft" />').bind(
  304. 'mousedown.jsp', getArrowScroll(-1, 0)
  305. ).bind('click.jsp', nil);
  306. arrowRight = $('<a class="jspArrow jspArrowRight" />').bind(
  307. 'mousedown.jsp', getArrowScroll(1, 0)
  308. ).bind('click.jsp', nil);
  309. if (settings.arrowScrollOnHover) {
  310. arrowLeft.bind('mouseover.jsp', getArrowScroll(-1, 0, arrowLeft));
  311. arrowRight.bind('mouseover.jsp', getArrowScroll(1, 0, arrowRight));
  312. }
  313. appendArrows(horizontalTrack, settings.horizontalArrowPositions, arrowLeft, arrowRight);
  314. }
  315. horizontalDrag.hover(
  316. function()
  317. {
  318. horizontalDrag.addClass('jspHover');
  319. },
  320. function()
  321. {
  322. horizontalDrag.removeClass('jspHover');
  323. }
  324. ).bind(
  325. 'mousedown.jsp',
  326. function(e)
  327. {
  328. // Stop IE from allowing text selection
  329. $('html').bind('dragstart.jsp selectstart.jsp', nil);
  330. horizontalDrag.addClass('jspActive');
  331. var startX = e.pageX - horizontalDrag.position().left;
  332. $('html').bind(
  333. 'mousemove.jsp',
  334. function(e)
  335. {
  336. positionDragX(e.pageX - startX, false);
  337. }
  338. ).bind('mouseup.jsp mouseleave.jsp', cancelDrag);
  339. return false;
  340. }
  341. );
  342. horizontalTrackWidth = container.innerWidth();
  343. sizeHorizontalScrollbar();
  344. }
  345. }
  346. function sizeHorizontalScrollbar()
  347. {
  348. container.find('>.jspHorizontalBar>.jspCap:visible,>.jspHorizontalBar>.jspArrow').each(
  349. function()
  350. {
  351. horizontalTrackWidth -= $(this).outerWidth();
  352. }
  353. );
  354. horizontalTrack.width(horizontalTrackWidth + 'px');
  355. horizontalDragPosition = 0;
  356. }
  357. function resizeScrollbars()
  358. {
  359. if (isScrollableH && isScrollableV) {
  360. var horizontalTrackHeight = horizontalTrack.outerHeight(),
  361. verticalTrackWidth = verticalTrack.outerWidth();
  362. verticalTrackHeight -= horizontalTrackHeight;
  363. $(horizontalBar).find('>.jspCap:visible,>.jspArrow').each(
  364. function()
  365. {
  366. horizontalTrackWidth += $(this).outerWidth();
  367. }
  368. );
  369. horizontalTrackWidth -= verticalTrackWidth;
  370. paneHeight -= verticalTrackWidth;
  371. paneWidth -= horizontalTrackHeight;
  372. horizontalTrack.parent().append(
  373. $('<div class="jspCorner" />').css('width', horizontalTrackHeight + 'px')
  374. );
  375. sizeVerticalScrollbar();
  376. sizeHorizontalScrollbar();
  377. }
  378. // reflow content
  379. if (isScrollableH) {
  380. pane.width((container.outerWidth() - originalPaddingTotalWidth) + 'px');
  381. }
  382. contentHeight = pane.outerHeight();
  383. percentInViewV = contentHeight / paneHeight;
  384. if (isScrollableH) {
  385. horizontalDragWidth = Math.ceil(1 / percentInViewH * horizontalTrackWidth);
  386. if (horizontalDragWidth > settings.horizontalDragMaxWidth) {
  387. horizontalDragWidth = settings.horizontalDragMaxWidth;
  388. } else if (horizontalDragWidth < settings.horizontalDragMinWidth) {
  389. horizontalDragWidth = settings.horizontalDragMinWidth;
  390. }
  391. horizontalDrag.width(horizontalDragWidth + 'px');
  392. dragMaxX = horizontalTrackWidth - horizontalDragWidth;
  393. _positionDragX(horizontalDragPosition); // To update the state for the arrow buttons
  394. }
  395. if (isScrollableV) {
  396. verticalDragHeight = Math.ceil(1 / percentInViewV * verticalTrackHeight);
  397. if (verticalDragHeight > settings.verticalDragMaxHeight) {
  398. verticalDragHeight = settings.verticalDragMaxHeight;
  399. } else if (verticalDragHeight < settings.verticalDragMinHeight) {
  400. verticalDragHeight = settings.verticalDragMinHeight;
  401. }
  402. verticalDrag.height(verticalDragHeight + 'px');
  403. dragMaxY = verticalTrackHeight - verticalDragHeight;
  404. _positionDragY(verticalDragPosition); // To update the state for the arrow buttons
  405. }
  406. }
  407. function appendArrows(ele, p, a1, a2)
  408. {
  409. var p1 = "before", p2 = "after", aTemp;
  410. // Sniff for mac... Is there a better way to determine whether the arrows would naturally appear
  411. // at the top or the bottom of the bar?
  412. if (p == "os") {
  413. p = /Mac/.test(navigator.platform) ? "after" : "split";
  414. }
  415. if (p == p1) {
  416. p2 = p;
  417. } else if (p == p2) {
  418. p1 = p;
  419. aTemp = a1;
  420. a1 = a2;
  421. a2 = aTemp;
  422. }
  423. ele[p1](a1)[p2](a2);
  424. }
  425. function getArrowScroll(dirX, dirY, ele)
  426. {
  427. return function()
  428. {
  429. arrowScroll(dirX, dirY, this, ele);
  430. this.blur();
  431. return false;
  432. };
  433. }
  434. function arrowScroll(dirX, dirY, arrow, ele)
  435. {
  436. arrow = $(arrow).addClass('jspActive');
  437. var eve,
  438. scrollTimeout,
  439. isFirst = true,
  440. doScroll = function()
  441. {
  442. if (dirX !== 0) {
  443. jsp.scrollByX(dirX * settings.arrowButtonSpeed);
  444. }
  445. if (dirY !== 0) {
  446. jsp.scrollByY(dirY * settings.arrowButtonSpeed);
  447. }
  448. scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.arrowRepeatFreq);
  449. isFirst = false;
  450. };
  451. doScroll();
  452. eve = ele ? 'mouseout.jsp' : 'mouseup.jsp';
  453. ele = ele || $('html');
  454. ele.bind(
  455. eve,
  456. function()
  457. {
  458. arrow.removeClass('jspActive');
  459. scrollTimeout && clearTimeout(scrollTimeout);
  460. scrollTimeout = null;
  461. ele.unbind(eve);
  462. focusElem();
  463. }
  464. );
  465. }
  466. function initClickOnTrack()
  467. {
  468. removeClickOnTrack();
  469. if (isScrollableV) {
  470. verticalTrack.bind(
  471. 'mousedown.jsp',
  472. function(e)
  473. {
  474. if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
  475. var clickedTrack = $(this),
  476. offset = clickedTrack.offset(),
  477. direction = e.pageY - offset.top - verticalDragPosition,
  478. scrollTimeout,
  479. isFirst = true,
  480. doScroll = function()
  481. {
  482. var offset = clickedTrack.offset(),
  483. pos = e.pageY - offset.top - verticalDragHeight / 2,
  484. contentDragY = paneHeight * settings.scrollPagePercent,
  485. dragY = dragMaxY * contentDragY / (contentHeight - paneHeight);
  486. if (direction < 0) {
  487. if (verticalDragPosition - dragY > pos) {
  488. jsp.scrollByY(-contentDragY);
  489. } else {
  490. positionDragY(pos);
  491. }
  492. } else if (direction > 0) {
  493. if (verticalDragPosition + dragY < pos) {
  494. jsp.scrollByY(contentDragY);
  495. } else {
  496. positionDragY(pos);
  497. }
  498. } else {
  499. cancelClick();
  500. return;
  501. }
  502. scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.trackClickRepeatFreq);
  503. isFirst = false;
  504. },
  505. cancelClick = function()
  506. {
  507. scrollTimeout && clearTimeout(scrollTimeout);
  508. scrollTimeout = null;
  509. $(document).unbind('mouseup.jsp', cancelClick);
  510. focusElem();
  511. };
  512. doScroll();
  513. $(document).bind('mouseup.jsp', cancelClick);
  514. return false;
  515. }
  516. }
  517. );
  518. }
  519. if (isScrollableH) {
  520. horizontalTrack.bind(
  521. 'mousedown.jsp',
  522. function(e)
  523. {
  524. if (e.originalTarget === undefined || e.originalTarget == e.currentTarget) {
  525. var clickedTrack = $(this),
  526. offset = clickedTrack.offset(),
  527. direction = e.pageX - offset.left - horizontalDragPosition,
  528. scrollTimeout,
  529. isFirst = true,
  530. doScroll = function()
  531. {
  532. var offset = clickedTrack.offset(),
  533. pos = e.pageX - offset.left - horizontalDragWidth / 2,
  534. contentDragX = paneWidth * settings.scrollPagePercent,
  535. dragX = dragMaxX * contentDragX / (contentWidth - paneWidth);
  536. if (direction < 0) {
  537. if (horizontalDragPosition - dragX > pos) {
  538. jsp.scrollByX(-contentDragX);
  539. } else {
  540. positionDragX(pos);
  541. }
  542. } else if (direction > 0) {
  543. if (horizontalDragPosition + dragX < pos) {
  544. jsp.scrollByX(contentDragX);
  545. } else {
  546. positionDragX(pos);
  547. }
  548. } else {
  549. cancelClick();
  550. return;
  551. }
  552. scrollTimeout = setTimeout(doScroll, isFirst ? settings.initialDelay : settings.trackClickRepeatFreq);
  553. isFirst = false;
  554. },
  555. cancelClick = function()
  556. {
  557. scrollTimeout && clearTimeout(scrollTimeout);
  558. scrollTimeout = null;
  559. $(document).unbind('mouseup.jsp', cancelClick);
  560. focusElem();
  561. };
  562. doScroll();
  563. $(document).bind('mouseup.jsp', cancelClick);
  564. return false;
  565. }
  566. }
  567. );
  568. }
  569. }
  570. function removeClickOnTrack()
  571. {
  572. if (horizontalTrack) {
  573. horizontalTrack.unbind('mousedown.jsp');
  574. }
  575. if (verticalTrack) {
  576. verticalTrack.unbind('mousedown.jsp');
  577. }
  578. }
  579. function cancelDrag()
  580. {
  581. $('html').unbind('dragstart.jsp selectstart.jsp mousemove.jsp mouseup.jsp mouseleave.jsp');
  582. if (verticalDrag) {
  583. verticalDrag.removeClass('jspActive');
  584. }
  585. if (horizontalDrag) {
  586. horizontalDrag.removeClass('jspActive');
  587. }
  588. focusElem();
  589. }
  590. function positionDragY(destY, animate)
  591. {
  592. if (!isScrollableV) {
  593. return;
  594. }
  595. if (destY < 0) {
  596. destY = 0;
  597. } else if (destY > dragMaxY) {
  598. destY = dragMaxY;
  599. }
  600. // can't just check if(animate) because false is a valid value that could be passed in...
  601. if (animate === undefined) {
  602. animate = settings.animateScroll;
  603. }
  604. if (animate) {
  605. jsp.animate(verticalDrag, 'top', destY, _positionDragY);
  606. } else {
  607. verticalDrag.css('top', destY);
  608. _positionDragY(destY);
  609. }
  610. }
  611. function _positionDragY(destY)
  612. {
  613. if (destY === undefined) {
  614. destY = verticalDrag.position().top;
  615. }
  616. container.scrollTop(0);
  617. verticalDragPosition = destY;
  618. var isAtTop = verticalDragPosition === 0,
  619. isAtBottom = verticalDragPosition == dragMaxY,
  620. percentScrolled = destY/ dragMaxY,
  621. destTop = -percentScrolled * (contentHeight - paneHeight);
  622. if (wasAtTop != isAtTop || wasAtBottom != isAtBottom) {
  623. wasAtTop = isAtTop;
  624. wasAtBottom = isAtBottom;
  625. elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
  626. }
  627. updateVerticalArrows(isAtTop, isAtBottom);
  628. pane.css('top', destTop);
  629. elem.trigger('jsp-scroll-y', [-destTop, isAtTop, isAtBottom]).trigger('scroll');
  630. }
  631. function positionDragX(destX, animate)
  632. {
  633. if (!isScrollableH) {
  634. return;
  635. }
  636. if (destX < 0) {
  637. destX = 0;
  638. } else if (destX > dragMaxX) {
  639. destX = dragMaxX;
  640. }
  641. if (animate === undefined) {
  642. animate = settings.animateScroll;
  643. }
  644. if (animate) {
  645. jsp.animate(horizontalDrag, 'left', destX, _positionDragX);
  646. } else {
  647. horizontalDrag.css('left', destX);
  648. _positionDragX(destX);
  649. }
  650. }
  651. function _positionDragX(destX)
  652. {
  653. if (destX === undefined) {
  654. destX = horizontalDrag.position().left;
  655. }
  656. container.scrollTop(0);
  657. horizontalDragPosition = destX;
  658. var isAtLeft = horizontalDragPosition === 0,
  659. isAtRight = horizontalDragPosition == dragMaxX,
  660. percentScrolled = destX / dragMaxX,
  661. destLeft = -percentScrolled * (contentWidth - paneWidth);
  662. if (wasAtLeft != isAtLeft || wasAtRight != isAtRight) {
  663. wasAtLeft = isAtLeft;
  664. wasAtRight = isAtRight;
  665. elem.trigger('jsp-arrow-change', [wasAtTop, wasAtBottom, wasAtLeft, wasAtRight]);
  666. }
  667. updateHorizontalArrows(isAtLeft, isAtRight);
  668. pane.css('left', destLeft);
  669. elem.trigger('jsp-scroll-x', [-destLeft, isAtLeft, isAtRight]).trigger('scroll');
  670. }
  671. function updateVerticalArrows(isAtTop, isAtBottom)
  672. {
  673. if (settings.showArrows) {
  674. arrowUp[isAtTop ? 'addClass' : 'removeClass']('jspDisabled');
  675. arrowDown[isAtBottom ? 'addClass' : 'removeClass']('jspDisabled');
  676. }
  677. }
  678. function updateHorizontalArrows(isAtLeft, isAtRight)
  679. {
  680. if (settings.showArrows) {
  681. arrowLeft[isAtLeft ? 'addClass' : 'removeClass']('jspDisabled');
  682. arrowRight[isAtRight ? 'addClass' : 'removeClass']('jspDisabled');
  683. }
  684. }
  685. function scrollToY(destY, animate)
  686. {
  687. var percentScrolled = destY / (contentHeight - paneHeight);
  688. positionDragY(percentScrolled * dragMaxY, animate);
  689. }
  690. function scrollToX(destX, animate)
  691. {
  692. var percentScrolled = destX / (contentWidth - paneWidth);
  693. positionDragX(percentScrolled * dragMaxX, animate);
  694. }
  695. function scrollToElement(ele, stickToTop, animate)
  696. {
  697. var e, eleHeight, eleWidth, eleTop = 0, eleLeft = 0, viewportTop, maxVisibleEleTop, maxVisibleEleLeft, destY, destX;
  698. // Legal hash values aren't necessarily legal jQuery selectors so we need to catch any
  699. // errors from the lookup...
  700. try {
  701. e = $(ele);
  702. } catch (err) {
  703. return;
  704. }
  705. eleHeight = e.outerHeight();
  706. eleWidth= e.outerWidth();
  707. container.scrollTop(0);
  708. container.scrollLeft(0);
  709. // loop through parents adding the offset top of any elements that are relatively positioned between
  710. // the focused element and the jspPane so we can get the true distance from the top
  711. // of the focused element to the top of the scrollpane...
  712. while (!e.is('.jspPane')) {
  713. eleTop += e.position().top;
  714. eleLeft += e.position().left;
  715. e = e.offsetParent();
  716. if (/^body|html$/i.test(e[0].nodeName)) {
  717. // we ended up too high in the document structure. Quit!
  718. return;
  719. }
  720. }
  721. viewportTop = contentPositionY();
  722. maxVisibleEleTop = viewportTop + paneHeight;
  723. if (eleTop < viewportTop || stickToTop) { // element is above viewport
  724. destY = eleTop - settings.verticalGutter;
  725. } else if (eleTop + eleHeight > maxVisibleEleTop) { // element is below viewport
  726. destY = eleTop - paneHeight + eleHeight + settings.verticalGutter;
  727. }
  728. if (destY) {
  729. scrollToY(destY, animate);
  730. }
  731. viewportLeft = contentPositionX();
  732. maxVisibleEleLeft = viewportLeft + paneWidth;
  733. if (eleLeft < viewportLeft || stickToTop) { // element is to the left of viewport
  734. destX = eleLeft - settings.horizontalGutter;
  735. } else if (eleLeft + eleWidth > maxVisibleEleLeft) { // element is to the right viewport
  736. destX = eleLeft - paneWidth + eleWidth + settings.horizontalGutter;
  737. }
  738. if (destX) {
  739. scrollToX(destX, animate);
  740. }
  741. }
  742. function contentPositionX()
  743. {
  744. return -pane.position().left;
  745. }
  746. function contentPositionY()
  747. {
  748. return -pane.position().top;
  749. }
  750. function initMousewheel()
  751. {
  752. container.unbind(mwEvent).bind(
  753. mwEvent,
  754. function (event, delta, deltaX, deltaY) {
  755. var dX = horizontalDragPosition, dY = verticalDragPosition;
  756. jsp.scrollBy(deltaX * settings.mouseWheelSpeed, -deltaY * settings.mouseWheelSpeed, false);
  757. // return true if there was no movement so rest of screen can scroll
  758. return dX == horizontalDragPosition && dY == verticalDragPosition;
  759. }
  760. );
  761. }
  762. function removeMousewheel()
  763. {
  764. container.unbind(mwEvent);
  765. }
  766. function nil()
  767. {
  768. return false;
  769. }
  770. function initFocusHandler()
  771. {
  772. pane.find(':input,a').unbind('focus.jsp').bind(
  773. 'focus.jsp',
  774. function(e)
  775. {
  776. scrollToElement(e.target, false);
  777. }
  778. );
  779. }
  780. function removeFocusHandler()
  781. {
  782. pane.find(':input,a').unbind('focus.jsp');
  783. }
  784. function initKeyboardNav()
  785. {
  786. var keyDown, elementHasScrolled;
  787. // IE also focuses elements that don't have tabindex set.
  788. pane.focus(
  789. function()
  790. {
  791. elem.focus();
  792. }
  793. );
  794. elem.attr('tabindex', 0)
  795. .unbind('keydown.jsp keypress.jsp')
  796. .bind(
  797. 'keydown.jsp',
  798. function(e)
  799. {
  800. if (e.target !== this){
  801. return;
  802. }
  803. var dX = horizontalDragPosition, dY = verticalDragPosition;
  804. switch(e.keyCode) {
  805. case 40: // down
  806. case 38: // up
  807. case 34: // page down
  808. case 32: // space
  809. case 33: // page up
  810. case 39: // right
  811. case 37: // left
  812. keyDown = e.keyCode;
  813. keyDownHandler();
  814. break;
  815. case 35: // end
  816. scrollToY(contentHeight - paneHeight);
  817. keyDown = null;
  818. break;
  819. case 36: // home
  820. scrollToY(0);
  821. keyDown = null;
  822. break;
  823. }
  824. elementHasScrolled = e.keyCode == keyDown && dX != horizontalDragPosition || dY != verticalDragPosition;
  825. return !elementHasScrolled;
  826. }
  827. ).bind(
  828. 'keypress.jsp', // For FF/ OSX so that we can cancel the repeat key presses if the JSP scrolls...
  829. function(e)
  830. {
  831. if (e.keyCode == keyDown) {
  832. keyDownHandler();
  833. }
  834. return !elementHasScrolled;
  835. }
  836. );
  837. if (settings.hideFocus) {
  838. elem.css('outline', 'none');
  839. if ('hideFocus' in container[0]){
  840. elem.attr('hideFocus', true);
  841. }
  842. } else {
  843. elem.css('outline', '');
  844. if ('hideFocus' in container[0]){
  845. elem.attr('hideFocus', false);
  846. }
  847. }
  848. function keyDownHandler()
  849. {
  850. var dX = horizontalDragPosition, dY = verticalDragPosition;
  851. switch(keyDown) {
  852. case 40: // down
  853. jsp.scrollByY(settings.keyboardSpeed, false);
  854. break;
  855. case 38: // up
  856. jsp.scrollByY(-settings.keyboardSpeed, false);
  857. break;
  858. case 34: // page down
  859. case 32: // space
  860. jsp.scrollByY(paneHeight * settings.scrollPagePercent, false);
  861. break;
  862. case 33: // page up
  863. jsp.scrollByY(-paneHeight * settings.scrollPagePercent, false);
  864. break;
  865. case 39: // right
  866. jsp.scrollByX(settings.keyboardSpeed, false);
  867. break;
  868. case 37: // left
  869. jsp.scrollByX(-settings.keyboardSpeed, false);
  870. break;
  871. }
  872. elementHasScrolled = dX != horizontalDragPosition || dY != verticalDragPosition;
  873. return elementHasScrolled;
  874. }
  875. }
  876. function removeKeyboardNav()
  877. {
  878. elem.attr('tabindex', '-1')
  879. .removeAttr('tabindex')
  880. .unbind('keydown.jsp keypress.jsp');
  881. }
  882. function observeHash()
  883. {
  884. if (location.hash && location.hash.length > 1) {
  885. var e, retryInt;
  886. try {
  887. e = $(location.hash);
  888. } catch (err) {
  889. return;
  890. }
  891. if (e.length && pane.find(location.hash)) {
  892. // nasty workaround but it appears to take a little while before the hash has done its thing
  893. // to the rendered page so we just wait until the container's scrollTop has been messed up.
  894. if (container.scrollTop() === 0) {
  895. retryInt = setInterval(
  896. function()
  897. {
  898. if (container.scrollTop() > 0) {
  899. scrollToElement(location.hash, true);
  900. $(document).scrollTop(container.position().top);
  901. clearInterval(retryInt);
  902. }
  903. },
  904. 50
  905. );
  906. } else {
  907. scrollToElement(location.hash, true);
  908. $(document).scrollTop(container.position().top);
  909. }
  910. }
  911. }
  912. }
  913. function unhijackInternalLinks()
  914. {
  915. $('a.jspHijack').unbind('click.jsp-hijack').removeClass('jspHijack');
  916. }
  917. function hijackInternalLinks()
  918. {
  919. unhijackInternalLinks();
  920. $('a[href^=#]').addClass('jspHijack').bind(
  921. 'click.jsp-hijack',
  922. function()
  923. {
  924. var uriParts = this.href.split('#'), hash;
  925. if (uriParts.length > 1) {
  926. hash = uriParts[1];
  927. if (hash.length > 0 && pane.find('#' + hash).length > 0) {
  928. scrollToElement('#' + hash, true);
  929. // Need to return false otherwise things mess up... Would be nice to maybe also scroll
  930. // the window to the top of the scrollpane?
  931. return false;
  932. }
  933. }
  934. }
  935. );
  936. }
  937. // If no element has focus, focus elem to support keyboard navigation
  938. function focusElem()
  939. {
  940. if (!$(':focus').length) {
  941. elem.focus();
  942. }
  943. }
  944. // Init touch on iPad, iPhone, iPod, Android
  945. function initTouch()
  946. {
  947. var startX,
  948. startY,
  949. touchStartX,
  950. touchStartY,
  951. moved,
  952. moving = false;
  953. container.unbind('touchstart.jsp touchmove.jsp touchend.jsp click.jsp-touchclick').bind(
  954. 'touchstart.jsp',
  955. function(e)
  956. {
  957. var touch = e.originalEvent.touches[0];
  958. startX = contentPositionX();
  959. startY = contentPositionY();
  960. touchStartX = touch.pageX;
  961. touchStartY = touch.pageY;
  962. moved = false;
  963. moving = true;
  964. }
  965. ).bind(
  966. 'touchmove.jsp',
  967. function(ev)
  968. {
  969. if(!moving) {
  970. return;
  971. }
  972. var touchPos = ev.originalEvent.touches[0],
  973. dX = horizontalDragPosition, dY = verticalDragPosition;
  974. jsp.scrollTo(startX + touchStartX - touchPos.pageX, startY + touchStartY - touchPos.pageY);
  975. moved = moved || Math.abs(touchStartX - touchPos.pageX) > 5 || Math.abs(touchStartY - touchPos.pageY) > 5;
  976. // return true if there was no movement so rest of screen can scroll
  977. return dX == horizontalDragPosition && dY == verticalDragPosition;
  978. }
  979. ).bind(
  980. 'touchend.jsp',
  981. function(e)
  982. {
  983. moving = false;
  984. /*if(moved) {
  985. return false;
  986. }*/
  987. }
  988. ).bind(
  989. 'click.jsp-touchclick',
  990. function(e)
  991. {
  992. if(moved) {
  993. moved = false;
  994. return false;
  995. }
  996. }
  997. );
  998. }
  999. function destroy(){
  1000. var currentY = contentPositionY(),
  1001. currentX = contentPositionX();
  1002. elem.removeClass('jspScrollable').unbind('.jsp');
  1003. elem.replaceWith(originalElement.append(pane.children()));
  1004. originalElement.scrollTop(currentY);
  1005. originalElement.scrollLeft(currentX);
  1006. }
  1007. // Public API
  1008. $.extend(
  1009. jsp,
  1010. {
  1011. // Reinitialises the scroll pane (if it's internal dimensions have changed since the last time it
  1012. // was initialised). The settings object which is passed in will override any settings from the
  1013. // previous time it was initialised - if you don't pass any settings then the ones from the previous
  1014. // initialisation will be used.
  1015. reinitialise: function(s)
  1016. {
  1017. s = $.extend({}, settings, s);
  1018. initialise(s);
  1019. },
  1020. // Scrolls the specified element (a jQuery object, DOM node or jQuery selector string) into view so
  1021. // that it can be seen within the viewport. If stickToTop is true then the element will appear at
  1022. // the top of the viewport, if it is false then the viewport will scroll as little as possible to
  1023. // show the element. You can also specify if you want animation to occur. If you don't provide this
  1024. // argument then the animateScroll value from the settings object is used instead.
  1025. scrollToElement: function(ele, stickToTop, animate)
  1026. {
  1027. scrollToElement(ele, stickToTop, animate);
  1028. },
  1029. // Scrolls the pane so that the specified co-ordinates within the content are at the top left
  1030. // of the viewport. animate is optional and if not passed then the value of animateScroll from
  1031. // the settings object this jScrollPane was initialised with is used.
  1032. scrollTo: function(destX, destY, animate)
  1033. {
  1034. scrollToX(destX, animate);
  1035. scrollToY(destY, animate);
  1036. },
  1037. // Scrolls the pane so that the specified co-ordinate within the content is at the left of the
  1038. // viewport. animate is optional and if not passed then the value of animateScroll from the settings
  1039. // object this jScrollPane was initialised with is used.
  1040. scrollToX: function(destX, animate)
  1041. {
  1042. scrollToX(destX, animate);
  1043. },
  1044. // Scrolls the pane so that the specified co-ordinate within the content is at the top of the
  1045. // viewport. animate is optional and if not passed then the value of animateScroll from the settings
  1046. // object this jScrollPane was initialised with is used.
  1047. scrollToY: function(destY, animate)
  1048. {
  1049. scrollToY(destY, animate);
  1050. },
  1051. // Scrolls the pane to the specified percentage of its maximum horizontal scroll position. animate
  1052. // is optional and if not passed then the value of animateScroll from the settings object this
  1053. // jScrollPane was initialised with is used.
  1054. scrollToPercentX: function(destPercentX, animate)
  1055. {
  1056. scrollToX(destPercentX * (contentWidth - paneWidth), animate);
  1057. },
  1058. // Scrolls the pane to the specified percentage of its maximum vertical scroll position. animate
  1059. // is optional and if not passed then the value of animateScroll from the settings object this
  1060. // jScrollPane was initialised with is used.
  1061. scrollToPercentY: function(destPercentY, animate)
  1062. {
  1063. scrollToY(destPercentY * (contentHeight - paneHeight), animate);
  1064. },
  1065. // Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
  1066. // the value of animateScroll from the settings object this jScrollPane was initialised with is used.
  1067. scrollBy: function(deltaX, deltaY, animate)
  1068. {
  1069. jsp.scrollByX(deltaX, animate);
  1070. jsp.scrollByY(deltaY, animate);
  1071. },
  1072. // Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
  1073. // the value of animateScroll from the settings object this jScrollPane was initialised with is used.
  1074. scrollByX: function(deltaX, animate)
  1075. {
  1076. var destX = contentPositionX() + deltaX,
  1077. percentScrolled = destX / (contentWidth - paneWidth);
  1078. positionDragX(percentScrolled * dragMaxX, animate);
  1079. },
  1080. // Scrolls the pane by the specified amount of pixels. animate is optional and if not passed then
  1081. // the value of animateScroll from the settings object this jScrollPane was initialised with is used.
  1082. scrollByY: function(deltaY, animate)
  1083. {
  1084. var destY = contentPositionY() + deltaY,
  1085. percentScrolled = destY / (contentHeight - paneHeight);
  1086. positionDragY(percentScrolled * dragMaxY, animate);
  1087. },
  1088. // Positions the horizontal drag at the specified x position (and updates the viewport to reflect
  1089. // this). animate is optional and if not passed then the value of animateScroll from the settings
  1090. // object this jScrollPane was initialised with is used.
  1091. positionDragX: function(x, animate)
  1092. {
  1093. positionDragX(x, animate);
  1094. },
  1095. // Positions the vertical drag at the specified y position (and updates the viewport to reflect
  1096. // this). animate is optional and if not passed then the value of animateScroll from the settings
  1097. // object this jScrollPane was initialised with is used.
  1098. positionDragY: function(y, animate)
  1099. {
  1100. positionDragX(y, animate);
  1101. },
  1102. // This method is called when jScrollPane is trying to animate to a new position. You can override
  1103. // it if you want to provide advanced animation functionality. It is passed the following arguments:
  1104. // * ele - the element whose position is being animated
  1105. // * prop - the property that is being animated
  1106. // * value - the value it's being animated to
  1107. // * stepCallback - a function that you must execute each time you update the value of the property
  1108. // You can use the default implementation (below) as a starting point for your own implementation.
  1109. animate: function(ele, prop, value, stepCallback)
  1110. {
  1111. var params = {};
  1112. params[prop] = value;
  1113. ele.animate(
  1114. params,
  1115. {
  1116. 'duration' : settings.animateDuration,
  1117. 'ease' : settings.animateEase,
  1118. 'queue' : false,
  1119. 'step' : stepCallback
  1120. }
  1121. );
  1122. },
  1123. // Returns the current x position of the viewport with regards to the content pane.
  1124. getContentPositionX: function()
  1125. {
  1126. return contentPositionX();
  1127. },
  1128. // Returns the current y position of the viewport with regards to the content pane.
  1129. getContentPositionY: function()
  1130. {
  1131. return contentPositionY();
  1132. },
  1133. // Returns the width of the content within the scroll pane.
  1134. getContentWidth: function()
  1135. {
  1136. return contentWidth();
  1137. },
  1138. // Returns the height of the content within the scroll pane.
  1139. getContentHeight: function()
  1140. {
  1141. return contentHeight();
  1142. },
  1143. // Returns the horizontal position of the viewport within the pane content.
  1144. getPercentScrolledX: function()
  1145. {
  1146. return contentPositionX() / (contentWidth - paneWidth);
  1147. },
  1148. // Returns the vertical position of the viewport within the pane content.
  1149. getPercentScrolledY: function()
  1150. {
  1151. return contentPositionY() / (contentHeight - paneHeight);
  1152. },
  1153. // Returns whether or not this scrollpane has a horizontal scrollbar.
  1154. getIsScrollableH: function()
  1155. {
  1156. return isScrollableH;
  1157. },
  1158. // Returns whether or not this scrollpane has a vertical scrollbar.
  1159. getIsScrollableV: function()
  1160. {
  1161. return isScrollableV;
  1162. },
  1163. // Gets a reference to the content pane. It is important that you use this method if you want to
  1164. // edit the content of your jScrollPane as if you access the element directly then you may have some
  1165. // problems (as your original element has had additional elements for the scrollbars etc added into
  1166. // it).
  1167. getContentPane: function()
  1168. {
  1169. return pane;
  1170. },
  1171. // Scrolls this jScrollPane down as far as it can currently scroll. If animate isn't passed then the
  1172. // animateScroll value from settings is used instead.
  1173. scrollToBottom: function(animate)
  1174. {
  1175. positionDragY(dragMaxY, animate);
  1176. },
  1177. // Hijacks the links on the page which link to content inside the scrollpane. If you have changed
  1178. // the content of your page (e.g. via AJAX) and want to make sure any new anchor links to the
  1179. // contents of your scroll pane will work then call this function.
  1180. hijackInternalLinks: function()
  1181. {
  1182. hijackInternalLinks();
  1183. },
  1184. // Removes the jScrollPane and returns the page to the state it was in before jScrollPane was
  1185. // initialised.
  1186. destroy: function()
  1187. {
  1188. destroy();
  1189. }
  1190. }
  1191. );
  1192. initialise(s);
  1193. }
  1194. // Pluginifying code...
  1195. settings = $.extend({}, $.fn.jScrollPane.defaults, settings);
  1196. // Apply default speed
  1197. $.each(['mouseWheelSpeed', 'arrowButtonSpeed', 'trackClickSpeed', 'keyboardSpeed'], function() {
  1198. settings[this] = settings[this] || settings.speed;
  1199. });
  1200. var ret;
  1201. this.each(
  1202. function()
  1203. {
  1204. var elem = $(this), jspApi = elem.data('jsp');
  1205. if (jspApi) {
  1206. jspApi.reinitialise(settings);
  1207. } else {
  1208. jspApi = new JScrollPane(elem, settings);
  1209. elem.data('jsp', jspApi);
  1210. }
  1211. ret = ret ? ret.add(elem) : elem;
  1212. }
  1213. );
  1214. return ret;
  1215. };
  1216. $.fn.jScrollPane.defaults = {
  1217. showArrows : false,
  1218. maintainPosition : true,
  1219. clickOnTrack : true,
  1220. autoReinitialise : false,
  1221. autoReinitialiseDelay : 500,
  1222. verticalDragMinHeight : 0,
  1223. verticalDragMaxHeight : 99999,
  1224. horizontalDragMinWidth : 0,
  1225. horizontalDragMaxWidth : 99999,
  1226. animateScroll : false,
  1227. animateDuration : 300,
  1228. animateEase : 'linear',
  1229. hijackInternalLinks : false,
  1230. verticalGutter : 4,
  1231. horizontalGutter : 4,
  1232. mouseWheelSpeed : 0,
  1233. arrowButtonSpeed : 0,
  1234. arrowRepeatFreq : 50,
  1235. arrowScrollOnHover : false,
  1236. trackClickSpeed : 0,
  1237. trackClickRepeatFreq : 70,
  1238. verticalArrowPositions : 'split',
  1239. horizontalArrowPositions : 'split',
  1240. enableKeyboardNavigation : true,
  1241. hideFocus : false,
  1242. keyboardSpeed : 0,
  1243. initialDelay : 300, // Delay before starting repeating
  1244. speed : 30, // Default speed when others falsey
  1245. scrollPagePercent : .8 // Percent of visible area scrolled when pageUp/Down or track area pressed
  1246. };
  1247. })(jQuery,this);