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