PageRenderTime 37ms CodeModel.GetById 22ms RepoModel.GetById 0ms app.codeStats 0ms

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

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