Subversion Repositories SmartDukaan

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
449 rajveer 1
/* Copyright (c) 2009 Kelvin Luck (kelvin AT kelvinluck DOT com || http://www.kelvinluck.com)
2
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
3
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
4
 * 
5
 * See http://kelvinluck.com/assets/jquery/jScrollPane/
6
 * $Id: jScrollPane.js 93 2010-06-01 08:17:28Z kelvin.luck $
7
 */
8
 
9
/**
10
 * Replace the vertical scroll bars on any matched elements with a fancy
11
 * styleable (via CSS) version. With JS disabled the elements will
12
 * gracefully degrade to the browsers own implementation of overflow:auto.
13
 * If the mousewheel plugin has been included on the page then the scrollable areas will also
14
 * respond to the mouse wheel.
15
 *
16
 * @example jQuery(".scroll-pane").jScrollPane();
17
 *
18
 * @name jScrollPane
19
 * @type jQuery
20
 * @param Object	settings	hash with options, described below.
21
 *								scrollbarWidth	-	The width of the generated scrollbar in pixels
22
 *								scrollbarMargin	-	The amount of space to leave on the side of the scrollbar in pixels
23
 *								wheelSpeed		-	The speed the pane will scroll in response to the mouse wheel in pixels
24
 *								showArrows		-	Whether to display arrows for the user to scroll with
25
 *								arrowSize		-	The height of the arrow buttons if showArrows=true
26
 *								animateTo		-	Whether to animate when calling scrollTo and scrollBy
27
 *								dragMinHeight	-	The minimum height to allow the drag bar to be
28
 *								dragMaxHeight	-	The maximum height to allow the drag bar to be
29
 *								animateInterval	-	The interval in milliseconds to update an animating scrollPane (default 100)
30
 *								animateStep		-	The amount to divide the remaining scroll distance by when animating (default 3)
31
 *								maintainPosition-	Whether you want the contents of the scroll pane to maintain it's position when you re-initialise it - so it doesn't scroll as you add more content (default true)
32
 *								tabIndex		-	The tabindex for this jScrollPane to control when it is tabbed to when navigating via keyboard (default 0)
33
 *								enableKeyboardNavigation - Whether to allow keyboard scrolling of this jScrollPane when it is focused (default true)
34
 *								animateToInternalLinks - Whether the move to an internal link (e.g. when it's focused by tabbing or by a hash change in the URL) should be animated or instant (default false)
35
 *								scrollbarOnLeft	-	Display the scrollbar on the left side?  (needs stylesheet changes, see examples.html)
36
 *								reinitialiseOnImageLoad - Whether the jScrollPane should automatically re-initialise itself when any contained images are loaded (default false)
37
 *								topCapHeight	-	The height of the "cap" area between the top of the jScrollPane and the top of the track/ buttons
38
 *								bottomCapHeight	-	The height of the "cap" area between the bottom of the jScrollPane and the bottom of the track/ buttons
39
 *								observeHash		-	Whether jScrollPane should attempt to automagically scroll to the correct place when an anchor inside the scrollpane is linked to (default true)
40
 * @return jQuery
41
 * @cat Plugins/jScrollPane
42
 * @author Kelvin Luck (kelvin AT kelvinluck DOT com || http://www.kelvinluck.com)
43
 */
44
 
45
(function($) {
46
 
47
$.jScrollPane = {
48
	active : []
49
};
50
$.fn.jScrollPane = function(settings)
51
{
52
	settings = $.extend({}, $.fn.jScrollPane.defaults, settings);
53
 
54
	var rf = function() { return false; };
55
 
56
	return this.each(
57
		function()
58
		{
59
			var $this = $(this);
60
			var paneEle = this;
61
			var currentScrollPosition = 0;
62
			var paneWidth;
63
			var paneHeight;
64
			var trackHeight;
65
			var trackOffset = settings.topCapHeight;
66
			var $container;
67
 
68
			if ($(this).parent().is('.jScrollPaneContainer')) {
69
				$container = $(this).parent();
70
				currentScrollPosition = settings.maintainPosition ? $this.position().top : 0;
71
				var $c = $(this).parent();
72
				paneWidth = $c.innerWidth();
73
				paneHeight = $c.outerHeight();
74
				$('>.jScrollPaneTrack, >.jScrollArrowUp, >.jScrollArrowDown, >.jScrollCap', $c).remove();
75
				$this.css({'top':0});
76
			} else {
77
				$this.data('originalStyleTag', $this.attr('style'));
78
				// Switch the element's overflow to hidden to ensure we get the size of the element without the scrollbars [http://plugins.jquery.com/node/1208]
79
				$this.css('overflow', 'hidden');
80
				this.originalPadding = $this.css('paddingTop') + ' ' + $this.css('paddingRight') + ' ' + $this.css('paddingBottom') + ' ' + $this.css('paddingLeft');
81
				this.originalSidePaddingTotal = (parseInt($this.css('paddingLeft')) || 0) + (parseInt($this.css('paddingRight')) || 0);
82
				paneWidth = $this.innerWidth();
83
				paneHeight = $this.innerHeight();
84
				$container = $('<div></div>')
85
					.attr({'className':'jScrollPaneContainer'})
86
					.css(
87
						{
88
							'height':paneHeight+'px', 
89
							'width':100+'%'
90
						}
91
					);
92
				if (settings.enableKeyboardNavigation) {
93
					$container.attr(
94
						'tabindex', 
95
						settings.tabIndex
96
					);
97
				}
98
				$this.wrap($container);
99
				$container = $this.parent();
100
				// deal with text size changes (if the jquery.em plugin is included)
101
				// and re-initialise the scrollPane so the track maintains the
102
				// correct size
103
				$(document).bind(
104
					'emchange', 
105
					function(e, cur, prev)
106
					{
107
						$this.jScrollPane(settings);
108
					}
109
				);
110
 
111
			}
112
			trackHeight = paneHeight;
113
 
114
			if (settings.reinitialiseOnImageLoad) {
115
				// code inspired by jquery.onImagesLoad: http://plugins.jquery.com/project/onImagesLoad
116
				// except we re-initialise the scroll pane when each image loads so that the scroll pane is always up to size...
117
				// TODO: Do I even need to store it in $.data? Is a local variable here the same since I don't pass the reinitialiseOnImageLoad when I re-initialise?
118
				var $imagesToLoad = $.data(paneEle, 'jScrollPaneImagesToLoad') || $('img', $this);
119
				var loadedImages = [];
120
 
121
				if ($imagesToLoad.length) {
122
					$imagesToLoad.each(function(i, val)	{
123
						$(this).bind('load readystatechange', function() {
124
							if($.inArray(i, loadedImages) == -1){ //don't double count images
125
								loadedImages.push(val); //keep a record of images we've seen
126
								$imagesToLoad = $.grep($imagesToLoad, function(n, i) {
127
									return n != val;
128
								});
129
								$.data(paneEle, 'jScrollPaneImagesToLoad', $imagesToLoad);
130
								var s2 = $.extend(settings, {reinitialiseOnImageLoad:false});
131
								$this.jScrollPane(s2); // re-initialise
132
							}
133
						}).each(function(i, val) {
134
							if(this.complete || this.complete===undefined) { 
135
								//needed for potential cached images
136
								this.src = this.src; 
137
							} 
138
						});
139
					});
140
				};
141
			}
142
 
143
			var p = this.originalSidePaddingTotal;
144
			var realPaneWidth = paneWidth - settings.scrollbarWidth - settings.scrollbarMargin - p;
145
 
146
			var cssToApply = {
147
				'height':'auto',
148
				'width': realPaneWidth + 'px'
149
			}
150
 
151
			if(settings.scrollbarOnLeft) {
152
				cssToApply.paddingLeft = settings.scrollbarMargin + settings.scrollbarWidth + 'px';
153
			} else {
154
				cssToApply.paddingRight = settings.scrollbarMargin + 'px';
155
			}
156
 
157
			$this.css(cssToApply);
158
 
159
			var contentHeight = $this.outerHeight();
160
			var percentInView = paneHeight / contentHeight;
161
 
162
			var isScrollable = percentInView < .99;
163
			$container[isScrollable ? 'addClass' : 'removeClass']('jScrollPaneScrollable');
164
 
165
			if (isScrollable) {
166
				$container.append(
167
					$('<div></div>').addClass('jScrollCap jScrollCapTop').css({height:settings.topCapHeight}),
168
					$('<div></div>').attr({'className':'jScrollPaneTrack'}).css({'width':settings.scrollbarWidth+'px'}).append(
169
						$('<div></div>').attr({'className':'jScrollPaneDrag'}).css({'width':settings.scrollbarWidth+'px'}).append(
170
							$('<div></div>').attr({'className':'jScrollPaneDragTop'}).css({'width':settings.scrollbarWidth+'px'}),
171
							$('<div></div>').attr({'className':'jScrollPaneDragBottom'}).css({'width':settings.scrollbarWidth+'px'})
172
						)
173
					),
174
					$('<div></div>').addClass('jScrollCap jScrollCapBottom').css({height:settings.bottomCapHeight})
175
				);
176
 
177
				var $track = $('>.jScrollPaneTrack', $container);
178
				var $drag = $('>.jScrollPaneTrack .jScrollPaneDrag', $container);
179
 
180
 
181
				var currentArrowDirection;
182
				var currentArrowTimerArr = [];// Array is used to store timers since they can stack up when dealing with keyboard events. This ensures all timers are cleaned up in the end, preventing an acceleration bug.
183
				var currentArrowInc;
184
				var whileArrowButtonDown = function() 
185
				{
186
					if (currentArrowInc > 4 || currentArrowInc % 4 == 0) {
187
						positionDrag(dragPosition + currentArrowDirection * mouseWheelMultiplier);
188
					}
189
					currentArrowInc++;
190
				};
191
 
192
				if (settings.enableKeyboardNavigation) {
193
					$container.bind(
194
						'keydown.jscrollpane',
195
						function(e) 
196
						{
197
							switch (e.keyCode) {
198
								case 38: //up
199
									currentArrowDirection = -1;
200
									currentArrowInc = 0;
201
									whileArrowButtonDown();
202
									currentArrowTimerArr[currentArrowTimerArr.length] = setInterval(whileArrowButtonDown, 100);
203
									return false;
204
								case 40: //down
205
									currentArrowDirection = 1;
206
									currentArrowInc = 0;
207
									whileArrowButtonDown();
208
									currentArrowTimerArr[currentArrowTimerArr.length] = setInterval(whileArrowButtonDown, 100);
209
									return false;
210
								case 33: // page up
211
								case 34: // page down
212
									// TODO
213
									return false;
214
								default:
215
							}
216
						}
217
					).bind(
218
						'keyup.jscrollpane',
219
						function(e) 
220
						{
221
							if (e.keyCode == 38 || e.keyCode == 40) {
222
								for (var i = 0; i < currentArrowTimerArr.length; i++) {
223
									clearInterval(currentArrowTimerArr[i]);
224
								}
225
								return false;
226
							}
227
						}
228
					);
229
				}
230
 
231
				if (settings.showArrows) {
232
 
233
					var currentArrowButton;
234
					var currentArrowInterval;
235
 
236
					var onArrowMouseUp = function(event)
237
					{
238
						$('html').unbind('mouseup', onArrowMouseUp);
239
						currentArrowButton.removeClass('jScrollActiveArrowButton');
240
						clearInterval(currentArrowInterval);
241
					};
242
					var onArrowMouseDown = function() {
243
						$('html').bind('mouseup', onArrowMouseUp);
244
						currentArrowButton.addClass('jScrollActiveArrowButton');
245
						currentArrowInc = 0;
246
						whileArrowButtonDown();
247
						currentArrowInterval = setInterval(whileArrowButtonDown, 100);
248
					};
249
					$container
250
						.append(
251
							$('<a></a>')
252
								.attr(
253
									{
254
										'href':'javascript:;', 
255
										'className':'jScrollArrowUp', 
256
										'tabindex':-1
257
									}
258
								)
259
								.css(
260
									{
261
										'width':settings.scrollbarWidth+'px',
262
										'top':settings.topCapHeight + 'px'
263
									}
264
								)
265
								.html('Scroll up')
266
								.bind('mousedown', function()
267
								{
268
									currentArrowButton = $(this);
269
									currentArrowDirection = -1;
270
									onArrowMouseDown();
271
									this.blur();
272
									return false;
273
								})
274
								.bind('click', rf),
275
							$('<a></a>')
276
								.attr(
277
									{
278
										'href':'javascript:;', 
279
										'className':'jScrollArrowDown', 
280
										'tabindex':-1
281
									}
282
								)
283
								.css(
284
									{
285
										'width':settings.scrollbarWidth+'px',
286
										'bottom':settings.bottomCapHeight + 'px'
287
									}
288
								)
289
								.html('Scroll down')
290
								.bind('mousedown', function()
291
								{
292
									currentArrowButton = $(this);
293
									currentArrowDirection = 1;
294
									onArrowMouseDown();
295
									this.blur();
296
									return false;
297
								})
298
								.bind('click', rf)
299
						);
300
					var $upArrow = $('>.jScrollArrowUp', $container);
301
					var $downArrow = $('>.jScrollArrowDown', $container);
302
				}
303
 
304
				if (settings.arrowSize) {
305
					trackHeight = paneHeight - settings.arrowSize - settings.arrowSize;
306
					trackOffset += settings.arrowSize;
307
				} else if ($upArrow) {
308
					var topArrowHeight = $upArrow.height();
309
					settings.arrowSize = topArrowHeight;
310
					trackHeight = paneHeight - topArrowHeight - $downArrow.height();
311
					trackOffset += topArrowHeight;
312
				}
313
				trackHeight -= settings.topCapHeight + settings.bottomCapHeight;
314
				$track.css({'height': trackHeight+'px', top:trackOffset+'px'})
315
 
316
				var $pane = $(this).css({'position':'absolute', 'overflow':'visible'});
317
 
318
				var currentOffset;
319
				var maxY;
320
				var mouseWheelMultiplier;
321
				// store this in a seperate variable so we can keep track more accurately than just updating the css property..
322
				var dragPosition = 0;
323
				var dragMiddle = percentInView*paneHeight/2;
324
 
325
				// pos function borrowed from tooltip plugin and adapted...
326
				var getPos = function (event, c) {
327
					var p = c == 'X' ? 'Left' : 'Top';
328
					return event['page' + c] || (event['client' + c] + (document.documentElement['scroll' + p] || document.body['scroll' + p])) || 0;
329
				};
330
 
331
				var ignoreNativeDrag = function() {	return false; };
332
 
333
				var initDrag = function()
334
				{
335
					ceaseAnimation();
336
					currentOffset = $drag.offset(false);
337
					currentOffset.top -= dragPosition;
338
					maxY = trackHeight - $drag[0].offsetHeight;
339
					mouseWheelMultiplier = 2 * settings.wheelSpeed * maxY / contentHeight;
340
				};
341
 
342
				var onStartDrag = function(event)
343
				{
344
					initDrag();
345
					dragMiddle = getPos(event, 'Y') - dragPosition - currentOffset.top;
346
					$('html').bind('mouseup', onStopDrag).bind('mousemove', updateScroll).bind('mouseleave', onStopDrag)
347
					if ($.browser.msie) {
348
						$('html').bind('dragstart', ignoreNativeDrag).bind('selectstart', ignoreNativeDrag);
349
					}
350
					return false;
351
				};
352
				var onStopDrag = function()
353
				{
354
					$('html').unbind('mouseup', onStopDrag).unbind('mousemove', updateScroll);
355
					dragMiddle = percentInView*paneHeight/2;
356
					if ($.browser.msie) {
357
						$('html').unbind('dragstart', ignoreNativeDrag).unbind('selectstart', ignoreNativeDrag);
358
					}
359
				};
360
				var positionDrag = function(destY)
361
				{
362
					$container.scrollTop(0);
363
					destY = destY < 0 ? 0 : (destY > maxY ? maxY : destY);
364
					dragPosition = destY;
365
					$drag.css({'top':destY+'px'});
366
					var p = destY / maxY;
367
					$this.data('jScrollPanePosition', (paneHeight-contentHeight)*-p);
368
					$pane.css({'top':((paneHeight-contentHeight)*p) + 'px'});
369
					$this.trigger('scroll');
370
					if (settings.showArrows) {
371
						$upArrow[destY == 0 ? 'addClass' : 'removeClass']('disabled');
372
						$downArrow[destY == maxY ? 'addClass' : 'removeClass']('disabled');
373
					}
374
				};
375
				var updateScroll = function(e)
376
				{
377
					positionDrag(getPos(e, 'Y') - currentOffset.top - dragMiddle);
378
				};
379
 
380
				var dragH = Math.max(Math.min(percentInView*(paneHeight-settings.arrowSize*2), settings.dragMaxHeight), settings.dragMinHeight);
381
 
382
				$drag.css(
383
					{'height':dragH+'px'}
384
				).bind('mousedown', onStartDrag);
385
 
386
				var trackScrollInterval;
387
				var trackScrollInc;
388
				var trackScrollMousePos;
389
				var doTrackScroll = function()
390
				{
391
					if (trackScrollInc > 8 || trackScrollInc%4==0) {
392
						positionDrag((dragPosition - ((dragPosition - trackScrollMousePos) / 2)));
393
					}
394
					trackScrollInc ++;
395
				};
396
				var onStopTrackClick = function()
397
				{
398
					clearInterval(trackScrollInterval);
399
					$('html').unbind('mouseup', onStopTrackClick).unbind('mousemove', onTrackMouseMove);
400
				};
401
				var onTrackMouseMove = function(event)
402
				{
403
					trackScrollMousePos = getPos(event, 'Y') - currentOffset.top - dragMiddle;
404
				};
405
				var onTrackClick = function(event)
406
				{
407
					initDrag();
408
					onTrackMouseMove(event);
409
					trackScrollInc = 0;
410
					$('html').bind('mouseup', onStopTrackClick).bind('mousemove', onTrackMouseMove);
411
					trackScrollInterval = setInterval(doTrackScroll, 100);
412
					doTrackScroll();
413
					return false;
414
				};
415
 
416
				$track.bind('mousedown', onTrackClick);
417
 
418
				$container.bind(
419
					'mousewheel',
420
					function (event, delta) {
421
						delta = delta || (event.wheelDelta ? event.wheelDelta / 120 : (event.detail) ?
422
-event.detail/3 : 0);
423
						initDrag();
424
						ceaseAnimation();
425
						var d = dragPosition;
426
						positionDrag(dragPosition - delta * mouseWheelMultiplier);
427
						var dragOccured = d != dragPosition;
428
						return !dragOccured;
429
					}
430
				);
431
 
432
				var _animateToPosition;
433
				var _animateToInterval;
434
				function animateToPosition()
435
				{
436
					var diff = (_animateToPosition - dragPosition) / settings.animateStep;
437
					if (diff > 1 || diff < -1) {
438
						positionDrag(dragPosition + diff);
439
					} else {
440
						positionDrag(_animateToPosition);
441
						ceaseAnimation();
442
					}
443
				}
444
				var ceaseAnimation = function()
445
				{
446
					if (_animateToInterval) {
447
						clearInterval(_animateToInterval);
448
						delete _animateToPosition;
449
					}
450
				};
451
				var scrollTo = function(pos, preventAni)
452
				{
453
					if (typeof pos == "string") {
454
						// Legal hash values aren't necessarily legal jQuery selectors so we need to catch any
455
						// errors from the lookup...
456
						try {
457
							$e = $(pos, $this);
458
						} catch (err) {
459
							return;
460
						}
461
						if (!$e.length) return;
462
						pos = $e.offset().top - $this.offset().top;
463
					}
464
					ceaseAnimation();
465
					var maxScroll = contentHeight - paneHeight;
466
					pos = pos > maxScroll ? maxScroll : pos;
467
					$this.data('jScrollPaneMaxScroll', maxScroll);
468
					var destDragPosition = pos/maxScroll * maxY;
469
					if (preventAni || !settings.animateTo) {
470
						positionDrag(destDragPosition);
471
					} else {
472
						$container.scrollTop(0);
473
						_animateToPosition = destDragPosition;
474
						_animateToInterval = setInterval(animateToPosition, settings.animateInterval);
475
					}
476
				};
477
				$this[0].scrollTo = scrollTo;
478
 
479
				$this[0].scrollBy = function(delta)
480
				{
481
					var currentPos = -parseInt($pane.css('top')) || 0;
482
					scrollTo(currentPos + delta);
483
				};
484
 
485
				initDrag();
486
 
487
				scrollTo(-currentScrollPosition, true);
488
 
489
				// Deal with it when the user tabs to a link or form element within this scrollpane
490
				$('*', this).bind(
491
					'focus',
492
					function(event)
493
					{
494
						var $e = $(this);
495
 
496
						// loop through parents adding the offset top of any elements that are relatively positioned between
497
						// the focused element and the jScrollPaneContainer so we can get the true distance from the top
498
						// of the focused element to the top of the scrollpane...
499
						var eleTop = 0;
500
 
501
						var preventInfiniteLoop = 100;
502
 
503
						while ($e[0] != $this[0]) {
504
							eleTop += $e.position().top;
505
							$e = $e.offsetParent();
506
							if (!preventInfiniteLoop--) {
507
								return;
508
							}
509
						}
510
 
511
						var viewportTop = -parseInt($pane.css('top')) || 0;
512
						var maxVisibleEleTop = viewportTop + paneHeight;
513
						var eleInView = eleTop > viewportTop && eleTop < maxVisibleEleTop;
514
						if (!eleInView) {
515
							var destPos = eleTop - settings.scrollbarMargin;
516
							if (eleTop > viewportTop) { // element is below viewport - scroll so it is at bottom.
517
								destPos += $(this).height() + 15 + settings.scrollbarMargin - paneHeight;
518
							}
519
							scrollTo(destPos);
520
						}
521
					}
522
				)
523
 
524
 
525
				if (settings.observeHash) {
526
					if (location.hash && location.hash.length > 1) {
527
						setTimeout(function(){
528
							scrollTo(location.hash);
529
						}, $.browser.safari ? 100 : 0);
530
					}
531
 
532
					// use event delegation to listen for all clicks on links and hijack them if they are links to
533
					// anchors within our content...
534
					$(document).bind('click', function(e){
535
						$target = $(e.target);
536
						if ($target.is('a')) {
537
							var h = $target.attr('href');
538
							if (h && h.substr(0, 1) == '#' && h.length > 1) {
539
								setTimeout(function(){
540
									scrollTo(h, !settings.animateToInternalLinks);
541
								}, $.browser.safari ? 100 : 0);
542
							}
543
						}
544
					});
545
				}
546
 
547
				// Deal with dragging and selecting text to make the scrollpane scroll...
548
				function onSelectScrollMouseDown(e)
549
				{
550
				   $(document).bind('mousemove.jScrollPaneDragging', onTextSelectionScrollMouseMove);
551
				   $(document).bind('mouseup.jScrollPaneDragging',   onSelectScrollMouseUp);
552
 
553
				}
554
 
555
				var textDragDistanceAway;
556
				var textSelectionInterval;
557
 
558
				function onTextSelectionInterval()
559
				{
560
					direction = textDragDistanceAway < 0 ? -1 : 1;
561
					$this[0].scrollBy(textDragDistanceAway / 2);
562
				}
563
 
564
				function clearTextSelectionInterval()
565
				{
566
					if (textSelectionInterval) {
567
						clearInterval(textSelectionInterval);
568
						textSelectionInterval = undefined;
569
					}
570
				}
571
 
572
				function onTextSelectionScrollMouseMove(e)
573
				{
574
					var offset = $this.parent().offset().top;
575
					var maxOffset = offset + paneHeight;
576
					var mouseOffset = getPos(e, 'Y');
577
					textDragDistanceAway = mouseOffset < offset ? mouseOffset - offset : (mouseOffset > maxOffset ? mouseOffset - maxOffset : 0);
578
					if (textDragDistanceAway == 0) {
579
						clearTextSelectionInterval();
580
					} else {
581
						if (!textSelectionInterval) {
582
							textSelectionInterval  = setInterval(onTextSelectionInterval, 100);
583
						}
584
					}
585
				}
586
 
587
				function onSelectScrollMouseUp(e)
588
				{
589
				   $(document)
590
					  .unbind('mousemove.jScrollPaneDragging')
591
					  .unbind('mouseup.jScrollPaneDragging');
592
				   clearTextSelectionInterval();
593
				}
594
 
595
				$container.bind('mousedown.jScrollPane', onSelectScrollMouseDown);
596
 
597
 
598
				$.jScrollPane.active.push($this[0]);
599
 
600
			} else {
601
				$this.css(
602
					{
603
						'height':paneHeight+'px',
604
						'width':paneWidth-this.originalSidePaddingTotal+'px',
605
						'padding':this.originalPadding
606
					}
607
				);
608
				$this[0].scrollTo = $this[0].scrollBy = function() {};
609
				// clean up listeners
610
				$this.parent().unbind('mousewheel').unbind('mousedown.jScrollPane').unbind('keydown.jscrollpane').unbind('keyup.jscrollpane');
611
			}
612
 
613
		}
614
	)
615
};
616
 
617
$.fn.jScrollPaneRemove = function()
618
{
619
	$(this).each(function()
620
	{
621
		$this = $(this);
622
		var $c = $this.parent();
623
		if ($c.is('.jScrollPaneContainer')) {
624
			$this.css(
625
				{
626
					'top':'',
627
					'height':'',
628
					'width':'',
629
					'padding':'',
630
					'overflow':'',
631
					'position':''
632
				}
633
			);
634
			$this.attr('style', $this.data('originalStyleTag'));
635
			$c.after($this).remove();
636
		}
637
	});
638
}
639
 
640
$.fn.jScrollPane.defaults = {
641
	scrollbarWidth : 10,
642
	scrollbarMargin : 5,
643
	wheelSpeed : 18,
644
	showArrows : false,
645
	arrowSize : 0,
646
	animateTo : false,
647
	dragMinHeight : 1,
648
	dragMaxHeight : 99999,
649
	animateInterval : 100,
650
	animateStep: 3,
651
	maintainPosition: true,
652
	scrollbarOnLeft: false,
653
	reinitialiseOnImageLoad: false,
654
	tabIndex : 0,
655
	enableKeyboardNavigation: true,
656
	animateToInternalLinks: false,
657
	topCapHeight: 0,
658
	bottomCapHeight: 0,
659
	observeHash: true
660
};
661
 
662
// clean up the scrollTo expandos
663
$(window)
664
	.bind('unload', function() {
665
		var els = $.jScrollPane.active; 
666
		for (var i=0; i<els.length; i++) {
667
			els[i].scrollTo = els[i].scrollBy = null;
668
		}
669
	}
670
);
671
 
672
})(jQuery);