jscrollpane-rails 2.0.22 → 2.0.23

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