jscrollpane-rails 2.0.17.1

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