jscrollpane-rails 2.0.22 → 2.0.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  }));