PageSourceSearch

https://www.schiffestival.com/wp-content/themes/amy-movie/js/vendor/smoothdivscroll.js?ver=1.3

js schiffestival.com collected 2026-10-02 22:16:54 UTC 49,516 bytes, 1,367 lines download raw bytes

1/*
2 * jQuery SmoothDivScroll 1.3
3 *
4 * Copyright (c) 2013 Thomas Kahn
5 * Licensed under the GPL license.
6 *
7 * http://www.smoothdivscroll.com/
8 *
9 * Depends:
10 * jquery-1.10.2.min.js
11   Please use https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js
12   ...or later
13
14 * jquery-ui-1.10.3.custom.min
15   Make your own custom download at http://jqueryui.com/download.
16   First deselect all components. Then check just "Widget" and "Effects Core".
17   Download the file and put it in your javascript folder.
18
19 * jquery.mousewheel.min.js
20   Used for mousewheel functionality.
21   Download the latest version at https://github.com/brandonaaron/jquery-mousewheel
22 *
23
24 * jquery.kinetic.min.js
25   Used for scrolling by dragging, mainly used on touch devices.
26   Download the latest version at https://github.com/davetayls/jquery.kinetic
27 *
28 */
29(function ($) {
30
31	$.widget("thomaskahn.smoothDivScroll", {
32		// Default options
33		options: {
34			// Classes for elements added by Smooth Div Scroll
35			scrollingHotSpotLeftClass: "scrollingHotSpotLeft", // String
36			scrollingHotSpotRightClass: "scrollingHotSpotRight", // String
37			scrollingHotSpotLeftVisibleClass: "scrollingHotSpotLeftVisible", // String
38			scrollingHotSpotRightVisibleClass: "scrollingHotSpotRightVisible", // String
39			scrollableAreaClass: "scrollableArea", // String
40			scrollWrapperClass: "scrollWrapper", // String
41
42			// Misc settings
43			hiddenOnStart: false, // Boolean
44			getContentOnLoad: {}, // Object
45			countOnlyClass: "", // String
46			startAtElementId: "", // String
47
48			// Hotspot scrolling
49			hotSpotScrolling: true, // Boolean
50			hotSpotScrollingStep: 15, // Pixels
51			hotSpotScrollingInterval: 10, // Milliseconds
52			hotSpotMouseDownSpeedBooster: 3, // Integer
53			visibleHotSpotBackgrounds: "hover", // always, onStart, hover or empty (no visible hotspots)
54			hotSpotsVisibleTime: 5000, // Milliseconds
55			easingAfterHotSpotScrolling: true, // Boolean
56			easingAfterHotSpotScrollingDistance: 10, // Pixels
57			easingAfterHotSpotScrollingDuration: 300, // Milliseconds
58			easingAfterHotSpotScrollingFunction: "easeOutQuart", // String
59
60			// Mousewheel scrolling
61			mousewheelScrolling: "", // vertical, horizontal, allDirections or empty (no mousewheel scrolling) String
62			mousewheelScrollingStep: 70, // Pixels
63			easingAfterMouseWheelScrolling: true, // Boolean
64			easingAfterMouseWheelScrollingDuration: 300, // Milliseconds
65			easingAfterMouseWheelScrollingFunction: "easeOutQuart", // String
66
67			// Manual scrolling (hotspot and/or mousewheel scrolling)
68			manualContinuousScrolling: false, // Boolean
69
70			// Autoscrolling
71			autoScrollingMode: "", // always, onStart or empty (no auto scrolling) String
72			autoScrollingDirection: "endlessLoopRight", // right, left, backAndForth, endlessLoopRight, endlessLoopLeft String
73			autoScrollingStep: 1, // Pixels
74			autoScrollingInterval: 10, // Milliseconds
75
76			// Touch scrolling
77			touchScrolling: false,
78
79			// Easing for when the scrollToElement method is used
80			scrollToAnimationDuration: 1000, // Milliseconds
81			scrollToEasingFunction: "easeOutQuart" // String
82		},
83		_create: function () {
84			var self = this, o = this.options, el = this.element;
85
86			// Create variables for any existing or not existing 
87			// scroller elements on the page.
88			el.data("scrollWrapper", el.find("." + o.scrollWrapperClass));
89			el.data("scrollingHotSpotRight", el.find("." + o.scrollingHotSpotRightClass));
90			el.data("scrollingHotSpotLeft", el.find("." + o.scrollingHotSpotLeftClass));
91			el.data("scrollableArea", el.find("." + o.scrollableAreaClass));
92
93			// Check which elements are already present on the page. 
94			// Create any elements needed by the plugin if
95			// the user hasn't already created them.
96
97			// First detach any present hot spots
98			if (el.data("scrollingHotSpotRight").length > 0) {
99
100				el.data("scrollingHotSpotRight").detach();
101			}
102			if (el.data("scrollingHotSpotLeft").length > 0) {
103
104				el.data("scrollingHotSpotLeft").detach();
105			}
106
107			// Both the scrollable area and the wrapper are missing
108			if (el.data("scrollableArea").length === 0 && el.data("scrollWrapper").length === 0) {
109				el.wrapInner("<div class='" + o.scrollableAreaClass + "'>").wrapInner("<div class='" + o.scrollWrapperClass + "'>");
110
111				el.data("scrollWrapper", el.find("." + o.scrollWrapperClass));
112				el.data("scrollableArea", el.find("." + o.scrollableAreaClass));
113			}
114			// Only the wrapper is missing
115			else if (el.data("scrollWrapper").length === 0) {
116				el.wrapInner("<div class='" + o.scrollWrapperClass + "'>");
117				el.data("scrollWrapper", el.find("." + o.scrollWrapperClass));
118			}
119			// Only the scrollable area is missing
120			else if (el.data("scrollableArea").length === 0) {
121				el.data("scrollWrapper").wrapInner("<div class='" + o.scrollableAreaClass + "'>");
122				el.data("scrollableArea", el.find("." + o.scrollableAreaClass));
123			}
124
125			// Put the right and left hot spot back into the scroller again
126			// or create them if they where not present from the beginning.
127			if (el.data("scrollingHotSpotRight").length === 0) {
128				el.prepend("<div class='" + o.scrollingHotSpotRightClass + "'></div>");
129				el.data("scrollingHotSpotRight", el.find("." + o.scrollingHotSpotRightClass));
130			} else {
131				el.prepend(el.data("scrollingHotSpotRight"));
132			}
133
134			if (el.data("scrollingHotSpotLeft").length === 0) {
135				el.prepend("<div class='" + o.scrollingHotSpotLeftClass + "'></div>");
136				el.data("scrollingHotSpotLeft", el.find("." + o.scrollingHotSpotLeftClass));
137			} else {
138				el.prepend(el.data("scrollingHotSpotLeft"));
139			}
140
141
142			// Create variables in the element data storage
143			el.data("speedBooster", 1);
144			el.data("scrollXPos", 0);
145			el.data("hotSpotWidth", el.data("scrollingHotSpotLeft").innerWidth());
146			el.data("scrollableAreaWidth", 0);
147			el.data("startingPosition", 0);
148			el.data("rightScrollingInterval", null);
149			el.data("leftScrollingInterval", null);
150			el.data("autoScrollingInterval", null);
151			el.data("hideHotSpotBackgroundsInterval", null);
152			el.data("previousScrollLeft", 0);
153			el.data("pingPongDirection", "right");
154			el.data("getNextElementWidth", true);
155			el.data("swapAt", null);
156			el.data("startAtElementHasNotPassed", true);
157			el.data("swappedElement", null);
158			el.data("originalElements", el.data("scrollableArea").children(o.countOnlyClass));
159			el.data("visible", true);
160			el.data("enabled", true);
161			el.data("scrollableAreaHeight", el.data("scrollableArea").height());
162			el.data("scrollerOffset", el.offset());
163
164			/*****************************************
165			SET UP EVENTS FOR TOUCH SCROLLING
166			*****************************************/
167			if (o.touchScrolling && el.data("enabled")) {
168				// Use jquery.kinetic.js for touch scrolling
169				// Vertical scrolling disabled
170				el.data("scrollWrapper").kinetic({
171					y: false,
172					moved: function (settings) {
173						if (o.manualContinuousScrolling) {
174							if (el.data("scrollWrapper").scrollLeft() <= 0) {
175								self._checkContinuousSwapLeft();
176							} else {
177								self._checkContinuousSwapRight();
178							}
179						}
180						
181						// Callback
182						self._trigger("touchMoved");
183					},
184					stopped: function (settings) {
185						// Stop any ongoing animations
186						el.data("scrollWrapper").stop(true, false);
187
188						// Stop any ongoing auto scrolling
189						self.stopAutoScrolling();
190						
191						// Callback
192						self._trigger("touchStopped");
193					}
194				});
195			}
196
197			/*****************************************
198			SET UP EVENTS FOR SCROLLING RIGHT
199			*****************************************/
200			// Check the mouse X position and calculate 
201			// the relative X position inside the right hotspot
202			el.data("scrollingHotSpotRight").bind("mousemove", function (e) {
203				if (o.hotSpotScrolling) {
204					var x = e.pageX - $(this).offset().left;
205					el.data("scrollXPos", Math.round((x / el.data("hotSpotWidth")) * o.hotSpotScrollingStep));
206
207					// If the position is less then 1, it's set to 1
208					if (el.data("scrollXPos") === Infinity || el.data("scrollXPos") < 1) {
209						el.data("scrollXPos", 1);
210					}
211				}
212			});
213
214			// Mouseover right hotspot - scrolling
215			el.data("scrollingHotSpotRight").bind("mouseover", function () {
216				if (o.hotSpotScrolling) {
217					// Stop any ongoing animations
218					el.data("scrollWrapper").stop(true, false);
219
220					// Stop any ongoing auto scrolling
221					self.stopAutoScrolling();
222
223					// Start the scrolling interval
224					el.data("rightScrollingInterval", setInterval(function () {
225						if (el.data("scrollXPos") > 0 && el.data("enabled")) {
226							el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() + (el.data("scrollXPos") * el.data("speedBooster")));
227
228							if (o.manualContinuousScrolling) {
229								self._checkContinuousSwapRight();
230							}
231
232							self._showHideHotSpots();
233						}
234					}, o.hotSpotScrollingInterval));
235
236					// Callback
237					self._trigger("mouseOverRightHotSpot");
238				}
239			});
240
241			// Mouseout right hotspot - stop scrolling
242			el.data("scrollingHotSpotRight").bind("mouseout", function () {
243				if (o.hotSpotScrolling) {
244					clearInterval(el.data("rightScrollingInterval"));
245					el.data("scrollXPos", 0);
246
247					// Easing out after scrolling
248					if (o.easingAfterHotSpotScrolling && el.data("enabled")) {
249						el.data("scrollWrapper").animate({ scrollLeft: el.data("scrollWrapper").scrollLeft() + o.easingAfterHotSpotScrollingDistance }, { duration: o.easingAfterHotSpotScrollingDuration, easing: o.easingAfterHotSpotScrollingFunction });
250					}
251				}
252			});
253
254
255			// mousedown right hotspot (add scrolling speed booster)
256			el.data("scrollingHotSpotRight").bind("mousedown", function () {
257				el.data("speedBooster", o.hotSpotMouseDownSpeedBooster);
258			});
259
260			// mouseup anywhere (stop boosting the scrolling speed)
261			$("body").bind("mouseup", function () {
262				el.data("speedBooster", 1);
263			});
264
265			/*****************************************
266			SET UP EVENTS FOR SCROLLING LEFT
267			*****************************************/
268			// Check the mouse X position and calculate
269			// the relative X position inside the left hotspot
270			el.data("scrollingHotSpotLeft").bind("mousemove", function (e) {
271				if (o.hotSpotScrolling) {
272					var x = el.data("hotSpotWidth") - (e.pageX - $(this).offset().left);
273
274					el.data("scrollXPos", Math.round((x / el.data("hotSpotWidth")) * o.hotSpotScrollingStep));
275
276					// If the position is less then 1, it's set to 1
277					if (el.data("scrollXPos") === Infinity || el.data("scrollXPos") < 1) {
278						el.data("scrollXPos", 1);
279					}
280				}
281			});
282
283			// Mouseover left hotspot
284			el.data("scrollingHotSpotLeft").bind("mouseover", function () {
285				if (o.hotSpotScrolling) {
286					// Stop any ongoing animations
287					el.data("scrollWrapper").stop(true, false);
288
289					// Stop any ongoing auto scrolling
290					self.stopAutoScrolling();
291
292					el.data("leftScrollingInterval", setInterval(function () {
293						if (el.data("scrollXPos") > 0 && el.data("enabled")) {
294							el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() - (el.data("scrollXPos") * el.data("speedBooster")));
295
296							if (o.manualContinuousScrolling) {
297								self._checkContinuousSwapLeft();
298							}
299
300							self._showHideHotSpots();
301						}
302					}, o.hotSpotScrollingInterval));
303
304					// Callback
305					self._trigger("mouseOverLeftHotSpot");
306				}
307			});
308
309			// mouseout left hotspot
310			el.data("scrollingHotSpotLeft").bind("mouseout", function () {
311				if (o.hotSpotScrolling) {
312					clearInterval(el.data("leftScrollingInterval"));
313					el.data("scrollXPos", 0);
314
315					// Easing out after scrolling
316					if (o.easingAfterHotSpotScrolling && el.data("enabled")) {
317						el.data("scrollWrapper").animate({ scrollLeft: el.data("scrollWrapper").scrollLeft() - o.easingAfterHotSpotScrollingDistance }, { duration: o.easingAfterHotSpotScrollingDuration, easing: o.easingAfterHotSpotScrollingFunction });
318					}
319				}
320			});
321
322			// mousedown left hotspot (add scrolling speed booster)
323			el.data("scrollingHotSpotLeft").bind("mousedown", function () {
324				el.data("speedBooster", o.hotSpotMouseDownSpeedBooster);
325			});
326
327			/*****************************************
328			SET UP EVENT FOR MOUSEWHEEL SCROLLING
329			*****************************************/
330			el.data("scrollableArea").mousewheel(function (event, delta, deltaX, deltaY) {
331
332				if (el.data("enabled") && o.mousewheelScrolling.length > 0) {
333					var pixels;
334
335					// Can be either positive or negative
336					// Is multiplied/inverted by minus one since you want it to scroll 
337					// left when moving the wheel down/right and right when moving the wheel up/left
338					if (o.mousewheelScrolling === "vertical" && deltaY !== 0) {
339						// Stop any ongoing auto scrolling if it's running
340						self.stopAutoScrolling();
341						event.preventDefault();
342						pixels = Math.round((o.mousewheelScrollingStep * deltaY) * -1);
343						self.move(pixels);
344					} else if (o.mousewheelScrolling === "horizontal" && deltaX !== 0) {
345						// Stop any ongoing auto scrolling if it's running
346						self.stopAutoScrolling();
347						event.preventDefault();
348						pixels = Math.round((o.mousewheelScrollingStep * deltaX) * -1);
349						self.move(pixels);
350					} else if (o.mousewheelScrolling === "allDirections") {
351						// Stop any ongoing auto scrolling if it's running
352						self.stopAutoScrolling();
353						event.preventDefault();
354						pixels = Math.round((o.mousewheelScrollingStep * delta) * -1);
355						self.move(pixels);
356					}
357
358
359				}
360			});
361
362			// Capture and disable mousewheel events when the pointer
363			// is over any of the hotspots
364			if (o.mousewheelScrolling) {
365				el.data("scrollingHotSpotLeft").add(el.data("scrollingHotSpotRight")).mousewheel(function (event) {
366					event.preventDefault();
367				});
368			}
369
370			/*****************************************
371			SET UP EVENT FOR RESIZING THE BROWSER WINDOW
372			*****************************************/
373			$(window).bind("resize", function () {
374				self._showHideHotSpots();
375				self._trigger("windowResized");
376			});
377
378			/*****************************************
379			FETCHING CONTENT ON INITIALIZATION
380			*****************************************/
381			// If getContentOnLoad is present in the options, 
382			// sort out the method and parameters and get the content
383
384			if (!(jQuery.isEmptyObject(o.getContentOnLoad))) {
385				self[o.getContentOnLoad.method](o.getContentOnLoad.content, o.getContentOnLoad.manipulationMethod, o.getContentOnLoad.addWhere, o.getContentOnLoad.filterTag);
386			}
387
388			// Should it be hidden on start?
389			if (o.hiddenOnStart) {
390				self.hide();
391			}
392
393			/*****************************************
394			AUTOSCROLLING
395			*****************************************/
396			// The $(window).load event handler is used because the width of the elements are not calculated
397			// properly until then, at least not in Google Chrome. The start of the auto scrolling and the
398			// setting of the hotspot backgrounds is started here as well for the same reason. 
399			// If the auto scrolling is not started in $(window).load, it won't start because it 
400			// will interpret the scrollable areas as too short.
401			$(window).load(function () {
402
403				// If scroller is not hidden, recalculate the scrollable area
404				if (!(o.hiddenOnStart)) {
405					self.recalculateScrollableArea();
406				}
407
408				// Autoscrolling is active
409				if ((o.autoScrollingMode.length > 0) && !(o.hiddenOnStart)) {
410					self.startAutoScrolling();
411				}
412
413				// If the user wants to have visible hotspot backgrounds, 
414				// here is where it's taken care of
415				if (o.autoScrollingMode !== "always") {
416
417					switch (o.visibleHotSpotBackgrounds) {
418						case "always":
419							self.showHotSpotBackgrounds();
420							break;
421						case "onStart":
422							self.showHotSpotBackgrounds();
423							el.data("hideHotSpotBackgroundsInterval", setTimeout(function () {
424								self.hideHotSpotBackgrounds(250);
425							}, o.hotSpotsVisibleTime));
426							break;
427						case "hover":
428							el.mouseenter(function (event) {
429								if (o.hotSpotScrolling) {
430									event.stopPropagation();
431									self.showHotSpotBackgrounds(250);
432								}
433							}).mouseleave(function (event) {
434								if (o.hotSpotScrolling) {
435									event.stopPropagation();
436									self.hideHotSpotBackgrounds(250);
437								}
438							});
439							break;
440						default:
441							break;
442					}
443				}
444
445				self._showHideHotSpots();
446
447				self._trigger("setupComplete");
448
449			});
450
451		},
452		/**********************************************************
453		_init 
454		**********************************************************/
455		// When the contents of the scrollable area is changed outside the widget,
456		// the widget must be reinitilaized.
457		// This code is run every time the widget is called without arguments
458		 _init: function () {
459			var self = this, el = this.element;
460		 
461			// Recalculate the total width of the elements inside the scrollable area
462			self.recalculateScrollableArea();
463		 
464			// Determine which hotspots to show
465			self._showHideHotSpots();
466		
467			// Trigger callback
468			self._trigger("initializationComplete");
469		},
470		/**********************************************************
471		Override _setOption and handle altered options
472		**********************************************************/
473		_setOption: function (key, value) {
474			var self = this, o = this.options, el = this.element;
475
476			// Update option
477			o[key] = value;
478
479			if (key === "hotSpotScrolling") {
480				// Handler if the option hotSpotScrolling is altered
481				if (value === true) {
482					self._showHideHotSpots();
483				} else {
484					el.data("scrollingHotSpotLeft").hide();
485					el.data("scrollingHotSpotRight").hide();
486				}
487			} else if (key === "autoScrollingStep" ||
488			// Make sure that certain values are integers, otherwise
489			// they will summon bad spirits in the plugin
490				key === "easingAfterHotSpotScrollingDistance" ||
491				key === "easingAfterHotSpotScrollingDuration" ||
492				key === "easingAfterMouseWheelScrollingDuration") {
493				o[key] = parseInt(value, 10);
494			} else if (key === "autoScrollingInterval") {
495				// Handler if the autoScrollingInterval is altered
496				o[key] = parseInt(value, 10);
497				self.startAutoScrolling();
498			}
499
500		},
501		/**********************************************************
502		Hotspot functions
503		**********************************************************/
504		showHotSpotBackgrounds: function (fadeSpeed) {
505
506			// Alter the CSS (SmoothDivScroll.css) if you want to customize
507			// the look'n'feel of the visible hotspots
508			var self = this, el = this.element, o = this.options;
509
510
511			// Fade in the hotspot backgrounds
512			if (fadeSpeed !== undefined) {
513				// Before the fade-in starts, we need to make sure the opacity is zero
514				//el.data("scrollingHotSpotLeft").add(el.data("scrollingHotSpotRight")).css("opacity", "0.0");
515
516				el.data("scrollingHotSpotLeft").addClass(o.scrollingHotSpotLeftVisibleClass);
517				el.data("scrollingHotSpotRight").addClass(o.scrollingHotSpotRightVisibleClass);
518
519				// Fade in the hotspots
520				el.data("scrollingHotSpotLeft").add(el.data("scrollingHotSpotRight")).fadeTo(fadeSpeed, 0.35);
521			}
522			// Don't fade, just show them
523			else {
524
525				// The left hotspot
526				el.data("scrollingHotSpotLeft").addClass(o.scrollingHotSpotLeftVisibleClass);
527				el.data("scrollingHotSpotLeft").removeAttr("style");
528
529				// The right hotspot
530				el.data("scrollingHotSpotRight").addClass(o.scrollingHotSpotRightVisibleClass);
531				el.data("scrollingHotSpotRight").removeAttr("style");
532			}
533
534			self._showHideHotSpots();
535
536		},
537		hideHotSpotBackgrounds: function (fadeSpeed) {
538			var el = this.element, o = this.options;
539
540			// Fade out the hotspot backgrounds
541			if (fadeSpeed !== undefined) {
542
543				// Fade out the left hotspot
544				el.data("scrollingHotSpotLeft").fadeTo(fadeSpeed, 0.0, function () {
545					el.data("scrollingHotSpotLeft").removeClass(o.scrollingHotSpotLeftVisibleClass);
546				});
547
548				// Fade out the right hotspot
549				el.data("scrollingHotSpotRight").fadeTo(fadeSpeed, 0.0, function () {
550					el.data("scrollingHotSpotRight").removeClass(o.scrollingHotSpotRightVisibleClass);
551				});
552
553			}
554			// Don't fade, just hide them
555			else {
556				el.data("scrollingHotSpotLeft").removeClass(o.scrollingHotSpotLeftVisibleClass).removeAttr("style");
557				el.data("scrollingHotSpotRight").removeClass(o.scrollingHotSpotRightVisibleClass).removeAttr("style");
558			}
559
560		},
561		// Function for showing and hiding hotspots depending on the
562		// offset of the scrolling
563		_showHideHotSpots: function () {
564			var self = this, el = this.element, o = this.options;
565
566			// Hot spot scrolling is not enabled so show no hot spots
567			if (!(o.hotSpotScrolling)) {
568				el.data("scrollingHotSpotLeft").hide();
569				el.data("scrollingHotSpotRight").hide();
570			} else {
571
572				// If the manual continuous scrolling option is set show both
573				if (o.hotSpotScrolling && o.autoScrollingMode !== "always" && el.data("autoScrollingInterval") !== null) {
574					el.data("scrollingHotSpotLeft").show();
575					el.data("scrollingHotSpotRight").show();
576				}
577				// Autoscrolling not set to always and hotspot scrolling enabled.
578				// Regular hot spot scrolling.
579				else if (o.autoScrollingMode !== "always" && o.hotSpotScrolling) {
580					// If the scrollable area is shorter than the scroll wrapper, both hotspots
581					// should be hidden
582					if (el.data("scrollableAreaWidth") <= (el.data("scrollWrapper").innerWidth())) {
583						el.data("scrollingHotSpotLeft").hide();
584						el.data("scrollingHotSpotRight").hide();
585					}
586					// When you can't scroll further left the left scroll hotspot should be hidden
587					// and the right hotspot visible.
588					else if (el.data("scrollWrapper").scrollLeft() === 0) {
589						el.data("scrollingHotSpotLeft").hide();
590						el.data("scrollingHotSpotRight").show();
591						// Callback
592						self._trigger("scrollerLeftLimitReached");
593						// Clear interval
594						clearInterval(el.data("leftScrollingInterval"));
595						el.data("leftScrollingInterval", null);
596					}
597					// When you can't scroll further right
598					// the right scroll hotspot should be hidden
599					// and the left hotspot visible
600					else if (el.data("scrollableAreaWidth") <= (el.data("scrollWrapper").innerWidth() + el.data("scrollWrapper").scrollLeft())) {
601						el.data("scrollingHotSpotLeft").show();
602						el.data("scrollingHotSpotRight").hide();
603						// Callback
604						self._trigger("scrollerRightLimitReached");
605						// Clear interval
606						clearInterval(el.data("rightScrollingInterval"));
607						el.data("rightScrollingInterval", null);
608					}
609					// If you are somewhere in the middle of your
610					// scrolling, both hotspots should be visible
611					else {
612						el.data("scrollingHotSpotLeft").show();
613						el.data("scrollingHotSpotRight").show();
614					}
615				}
616				// If auto scrolling is set to always, there should be no hotspots
617				else {
618					el.data("scrollingHotSpotLeft").hide();
619					el.data("scrollingHotSpotRight").hide();
620				}
621			}
622
623
624
625		},
626		// Function for calculating the scroll position of a certain element
627		_setElementScrollPosition: function (method, element) {
628			var el = this.element, o = this.options, tempScrollPosition = 0;
629
630			switch (method) {
631				case "first":
632					el.data("scrollXPos", 0);
633					return true;
634				case "start":
635					// Check to see if there is a specified start element in the options 
636					// and that the element exists in the DOM
637					if (o.startAtElementId !== "") {
638						if (el.data("scrollableArea").has("#" + o.startAtElementId)) {
639							tempScrollPosition = $("#" + o.startAtElementId).position().left;
640							el.data("scrollXPos", tempScrollPosition);
641							return true;
642						}
643					}
644					return false;
645				case "last":
646					el.data("scrollXPos", (el.data("scrollableAreaWidth") - el.data("scrollWrapper").innerWidth()));
647					return true;
648				case "number":
649					// Check to see that an element number is passed
650					if (!(isNaN(element))) {
651						tempScrollPosition = el.data("scrollableArea").children(o.countOnlyClass).eq(element - 1).position().left;
652						el.data("scrollXPos", tempScrollPosition);
653						return true;
654					}
655					return false;
656				case "id":
657					// Check that an element id is passed and that the element exists in the DOM
658					if (element.length > 0) {
659						if (el.data("scrollableArea").has("#" + element)) {
660							tempScrollPosition = $("#" + element).position().left;
661							el.data("scrollXPos", tempScrollPosition);
662							return true;
663						}
664					}
665					return false;
666				default:
667					return false;
668			}
669
670
671		},
672		/**********************************************************
673		Jumping to a certain element
674		**********************************************************/
675		jumpToElement: function (jumpTo, element) {
676			var self = this, el = this.element;
677
678			// Check to see that the scroller is enabled
679			if (el.data("enabled")) {
680				// Get the position of the element to scroll to
681				if (self._setElementScrollPosition(jumpTo, element)) {
682					// Jump to the element
683					el.data("scrollWrapper").scrollLeft(el.data("scrollXPos"));
684					// Check the hotspots
685					self._showHideHotSpots();
686					// Trigger the right callback
687					switch (jumpTo) {
688						case "first":
689							self._trigger("jumpedToFirstElement");
690							break;
691						case "start":
692							self._trigger("jumpedToStartElement");
693							break;
694						case "last":
695							self._trigger("jumpedToLastElement");
696							break;
697						case "number":
698							self._trigger("jumpedToElementNumber", null, { "elementNumber": element });
699							break;
700						case "id":
701							self._trigger("jumpedToElementId", null, { "elementId": element });
702							break;
703						default:
704							break;
705					}
706
707				}
708			}
709		},
710		/**********************************************************
711		Scrolling to a certain element
712		**********************************************************/
713		scrollToElement: function (scrollTo, element) {
714			var self = this, el = this.element, o = this.options, autoscrollingWasRunning = false;
715
716			if (el.data("enabled")) {
717				// Get the position of the element to scroll to
718				if (self._setElementScrollPosition(scrollTo, element)) {
719					// Stop any ongoing auto scrolling
720					if (el.data("autoScrollingInterval") !== null) {
721						self.stopAutoScrolling();
722						autoscrollingWasRunning = true;
723					}
724
725					// Stop any other running animations
726					// (clear queue but don't jump to the end)
727					el.data("scrollWrapper").stop(true, false);
728
729					// Do the scolling animation
730					el.data("scrollWrapper").animate({
731						scrollLeft: el.data("scrollXPos")
732					}, { duration: o.scrollToAnimationDuration, easing: o.scrollToEasingFunction, complete: function () {
733						// If auto scrolling was running before, start it again
734						if (autoscrollingWasRunning) {
735							self.startAutoScrolling();
736						}
737
738						self._showHideHotSpots();
739
740						// Trigger the right callback
741						switch (scrollTo) {
742							case "first":
743								self._trigger("scrolledToFirstElement");
744								break;
745							case "start":
746								self._trigger("scrolledToStartElement");
747								break;
748							case "last":
749								self._trigger("scrolledToLastElement");
750								break;
751							case "number":
752								self._trigger("scrolledToElementNumber", null, { "elementNumber": element });
753								break;
754							case "id":
755								self._trigger("scrolledToElementId", null, { "elementId": element });
756								break;
757							default:
758								break;
759						}
760					}
761					});
762				}
763			}
764
765		},
766		move: function (pixels) {
767			var self = this, el = this.element, o = this.options;
768			// clear queue, move to end
769			el.data("scrollWrapper").stop(true, true);
770
771			// Only run this code if it's possible to scroll left or right,
772			if ((pixels < 0 && el.data("scrollWrapper").scrollLeft() > 0) || (pixels > 0 && el.data("scrollableAreaWidth") > (el.data("scrollWrapper").innerWidth() + el.data("scrollWrapper").scrollLeft())) || o.manualContinuousScrolling) {
773
774        var scrollLength = el.data("scrollableArea").width() - el.data("scrollWrapper").width();
775        var sOffset = el.data("scrollWrapper").scrollLeft() + pixels;
776
777        if(sOffset < 0) { // Swap last element to be the first one if scroll out of the left edge of view
778                
779            var forceSwapElementLeft = function(){
780              el.data("swappedElement", el.data("scrollableArea").children(":last").detach());
781              el.data("scrollableArea").prepend(el.data("swappedElement"));
782              el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() + el.data("swappedElement").outerWidth(true));              
783            };
784            
785            while(sOffset < 0){ // keep swap elements left until it has enough length for scrolling left
786              forceSwapElementLeft();
787              sOffset = el.data("scrollableArea").children(":first").outerWidth(true) + sOffset;                   
788            }
789
790        } else if(sOffset - scrollLength > 0){ // Swap the first element to be the last one if scroll out of the right edge of view
791           
792          var forceSwapElementRight = function(){            
793            el.data("swappedElement", el.data("scrollableArea").children(":first").detach());
794            el.data("scrollableArea").append(el.data("swappedElement"));
795            var wrapperLeft = el.data("scrollWrapper").scrollLeft();
796            el.data("scrollWrapper").scrollLeft(wrapperLeft - el.data("swappedElement").outerWidth(true));            
797          };
798          
799          while(sOffset - scrollLength > 0){ // keep swap elements right until it has enough length for scrolling right
800            forceSwapElementRight();
801            sOffset = sOffset - el.data("scrollableArea").children(":last").outerWidth(true);              
802          }
803          
804        }
805          
806				if (o.easingAfterMouseWheelScrolling) {
807        
808          el.data("scrollWrapper").animate({ scrollLeft: el.data("scrollWrapper").scrollLeft() + pixels }, { duration: o.easingAfterMouseWheelScrollingDuration, easing: o.easingAfterMouseWheelFunction, complete: function () {
809            self._showHideHotSpots();
810            if (o.manualContinuousScrolling) {
811              if (pixels > 0) {
812                self._checkContinuousSwapRight();
813              } else {
814                self._checkContinuousSwapLeft();
815              }
816            }
817          }
818          });
819          
820				} else {
821					el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() + pixels);
822					self._showHideHotSpots();
823
824					if (o.manualContinuousScrolling) {
825						if (pixels > 0) {
826							self._checkContinuousSwapRight();
827						} else {
828							self._checkContinuousSwapLeft();
829						}
830					}
831				}
832         
833
834			}
835
836   },
837		/**********************************************************
838		Adding or replacing content
839		**********************************************************/
840		/*  Arguments are:
841		content - a valid URL to a Flickr feed - string
842		manipulationMethod - addFirst, addLast or replace (default) - string
843		*/
844		getFlickrContent: function (content, manipulationMethod) {
845			var self = this, el = this.element;
846
847			$.getJSON(content, function (data) {
848				// small square - size is 75x75
849				// thumbnail -> large - size is the longest side
850				var flickrImageSizes = [{ size: "small square", pixels: 75, letter: "_s" },
851										{ size: "thumbnail", pixels: 100, letter: "_t" },
852										{ size: "small", pixels: 240, letter: "_m" },
853										{ size: "medium", pixels: 500, letter: "" },
854										{ size: "medium 640", pixels: 640, letter: "_z" },
855										{ size: "large", pixels: 1024, letter: "_b"}];
856				var loadedFlickrImages = [];
857				var imageIdStringBuffer = [];
858				var startingIndex;
859				var numberOfFlickrItems = data.items.length;
860				var loadedFlickrImagesCounter = 0;
861
862				// Determine a plausible starting value for the
863				// image height
864				if (el.data("scrollableAreaHeight") <= 75) {
865					startingIndex = 0;
866				} else if (el.data("scrollableAreaHeight") <= 100) {
867					startingIndex = 1;
868				} else if (el.data("scrollableAreaHeight") <= 240) {
869					startingIndex = 2;
870				} else if (el.data("scrollableAreaHeight") <= 500) {
871					startingIndex = 3;
872				} else if (el.data("scrollableAreaHeight") <= 640) {
873					startingIndex = 4;
874				} else {
875					startingIndex = 5;
876				}
877
878				// Put all items from the feed in an array.
879				// This is necessary
880				$.each(data.items, function (index, item) {
881					loadFlickrImage(item, startingIndex);
882				});
883
884				function loadFlickrImage(item, sizeIndex) {
885					var path = item.media.m;
886					var imgSrc = path.replace("_m", flickrImageSizes[sizeIndex].letter);
887					var tempImg = $("<img />").attr("src", imgSrc);
888
889					tempImg.load(function () {
890						// Is it still smaller? Load next size
891						if (this.height < el.data("scrollableAreaHeight")) {
892							// Load a bigger image, if possible
893							if ((sizeIndex + 1) < flickrImageSizes.length) {
894								loadFlickrImage(item, sizeIndex + 1);
895							} else {
896								addImageToLoadedImages(this);
897							}
898						}
899						else {
900							addImageToLoadedImages(this);
901						}
902
903						// Finishing stuff to do when all images have been loaded
904						if (loadedFlickrImagesCounter === numberOfFlickrItems) {
905							switch (manipulationMethod) {
906								case "addFirst":
907									// Add the loaded content first in the scrollable area
908									el.data("scrollableArea").children(":first").before(loadedFlickrImages);
909									break;
910								case "addLast":
911									// Add the loaded content last in the scrollable area
912									el.data("scrollableArea").children(":last").after(loadedFlickrImages);
913									break;
914								default:
915									// Replace the content in the scrollable area
916									el.data("scrollableArea").html(loadedFlickrImages);
917									break;
918							}
919
920							// Recalculate the total width of the elements inside the scrollable area
921							self.recalculateScrollableArea();
922
923							// Determine which hotspots to show
924							self._showHideHotSpots();
925
926							// Trigger callback
927							self._trigger("addedFlickrContent", null, { "addedElementIds": imageIdStringBuffer });
928						}
929
930					});
931				}
932
933				// Add the loaded content first or last in the scrollable area
934				function addImageToLoadedImages(imageObj) {
935					// Calculate the scaled width
936					var widthScalingFactor = el.data("scrollableAreaHeight") / imageObj.height;
937					var tempWidth = Math.round(imageObj.width * widthScalingFactor);
938					// Set an id for the image - the filename is used as an id
939					var tempIdArr = $(imageObj).attr("src").split("/");
940					var lastElemIndex = (tempIdArr.length - 1);
941					tempIdArr = tempIdArr[lastElemIndex].split(".");
942					$(imageObj).attr("id", tempIdArr[0]);
943					// Set the height of the image to the height of the scrollable area and add the width
944					$(imageObj).css({ "height": el.data("scrollableAreaHeight"), "width": tempWidth });
945					// Add the id of the image to the array of id's - this
946					// is used as a parameter when the callback is triggered
947					imageIdStringBuffer.push(tempIdArr[0]);
948					// Add the image to the array of loaded images
949					loadedFlickrImages.push(imageObj);
950
951					// Increment counter for loaded images
952					loadedFlickrImagesCounter++;
953				}
954
955			});
956		},
957		/*  Arguments are:
958		content - a valid URL to an AJAX content source - string
959		manipulationMethod - addFirst, addLast or replace (default) - string
960		filterTag - a jQuery selector that matches the elements from the AJAX content
961		source that you want, for example ".myClass" or "#thisDiv" or "div" - string
962		*/
963		getAjaxContent: function (content, manipulationMethod, filterTag) {
964			var self = this, el = this.element;
965			$.ajaxSetup({ cache: false });
966
967			$.get(content, function (data) {
968				var filteredContent;
969
970				if (filterTag !== undefined) {
971					if (filterTag.length > 0) {
972						// A bit of a hack since I can't know if the element
973						// that the user wants is a direct child of body (= use filter)
974						// or other types of elements (= use find)
975						filteredContent = $("<div>").html(data).find(filterTag);
976					} else {
977						filteredContent = content;
978					}
979				} else {
980					filteredContent = data;
981				}
982
983				switch (manipulationMethod) {
984					case "addFirst":
985						// Add the loaded content first in the scrollable area
986						el.data("scrollableArea").children(":first").before(filteredContent);
987						break;
988					case "addLast":
989						// Add the loaded content last in the scrollable area
990						el.data("scrollableArea").children(":last").after(filteredContent);
991						break;
992					default:
993						// Replace the content in the scrollable area
994						el.data("scrollableArea").html(filteredContent);
995						break;
996				}
997
998				// Recalculate the total width of the elements inside the scrollable area
999				self.recalculateScrollableArea();
1000
1001				// Determine which hotspots to show
1002				self._showHideHotSpots();
1003
1004				// Trigger callback
1005				self._trigger("addedAjaxContent");
1006
1007			});
1008		},
1009		getHtmlContent: function (content, manipulationMethod, filterTag) {
1010			var self = this, el = this.element;
1011
1012			// No AJAX involved at all - just add raw HTML-content
1013			/* Arguments are:
1014			content - any raw HTML that you want - string
1015			manipulationMethod - addFirst, addLast or replace (default) - string
1016			filterTag - a jQuery selector that matches the elements from the AJAX content
1017			source that you want, for example ".myClass" or "#thisDiv" or "div" - string
1018			*/
1019			var filteredContent;
1020			if (filterTag !== undefined) {
1021				if (filterTag.length > 0) {
1022					// A bit of a hack since I can't know if the element
1023					// that the user wants is a direct child of body (= use filter)
1024					// or other types of elements (= use find)
1025					filteredContent = $("<div>").html(content).find(filterTag);
1026				} else {
1027					filteredContent = content;
1028				}
1029			} else {
1030				filteredContent = content;
1031			}
1032
1033			switch (manipulationMethod) {
1034				case "addFirst":
1035					// Add the loaded content first in the scrollable area
1036					el.data("scrollableArea").children(":first").before(filteredContent);
1037					break;
1038				case "addLast":
1039					// Add the loaded content last in the scrollable area
1040					el.data("scrollableArea").children(":last").after(filteredContent);
1041					break;
1042				default:
1043					// Replace the content in the scrollable area
1044					el.data("scrollableArea").html(filteredContent);
1045					break;
1046			}
1047
1048			// Recalculate the total width of the elements inside the scrollable area
1049			self.recalculateScrollableArea();
1050	
1051			// Determine which hotspots to show
1052			self._showHideHotSpots();
1053
1054			// Trigger callback
1055			self._trigger("addedHtmlContent");
1056
1057		},
1058		/**********************************************************
1059		Recalculate the scrollable area
1060		**********************************************************/
1061		recalculateScrollableArea: function () {
1062
1063			var tempScrollableAreaWidth = 0, foundStartAtElement = false, o = this.options, el = this.element;
1064
1065			// Add up the total width of all the items inside the scrollable area
1066			el.data("scrollableArea").children(o.countOnlyClass).each(function () {
1067				// Check to see if the current element in the loop is the one where the scrolling should start
1068				if ((o.startAtElementId.length > 0) && (($(this).attr("id")) === o.startAtElementId)) {
1069					el.data("startingPosition", tempScrollableAreaWidth);
1070					foundStartAtElement = true;
1071				}
1072				tempScrollableAreaWidth = tempScrollableAreaWidth + $(this).outerWidth(true);
1073
1074			});
1075
1076			// If the element with the ID specified by startAtElementId
1077			// is not found, reset it
1078			if (!(foundStartAtElement)) {
1079				el.data("startAtElementId", "");
1080			}
1081
1082			// Set the width of the scrollable area
1083			el.data("scrollableAreaWidth", tempScrollableAreaWidth);
1084			el.data("scrollableArea").width(el.data("scrollableAreaWidth"));
1085
1086			// Move to the starting position
1087			el.data("scrollWrapper").scrollLeft(el.data("startingPosition"));
1088			el.data("scrollXPos", el.data("startingPosition"));
1089		},
1090		/**********************************************************
1091		Get current scrolling left offset
1092		**********************************************************/
1093		getScrollerOffset: function () {
1094			var el = this.element;
1095
1096			// Returns the current left offset
1097			// Please remember that if the scroller is in continuous
1098			// mode, the offset is not that relevant anymore since
1099			// the plugin will swap the elements inside the scroller
1100			// around and manipulate the offset in this process.
1101			return el.data("scrollWrapper").scrollLeft();
1102		},
1103		/**********************************************************
1104		Stopping, starting and doing the auto scrolling
1105		**********************************************************/
1106		stopAutoScrolling: function () {
1107			var self = this, el = this.element;
1108
1109			if (el.data("autoScrollingInterval") !== null) {
1110				clearInterval(el.data("autoScrollingInterval"));
1111				el.data("autoScrollingInterval", null);
1112
1113				// Check to see which hotspots should be active
1114				// in the position where the scroller has stopped
1115				self._showHideHotSpots();
1116
1117				self._trigger("autoScrollingStopped");
1118			}
1119		},
1120		/**********************************************************
1121		Start Autoscrolling
1122		**********************************************************/
1123		startAutoScrolling: function () {
1124			var self = this, el = this.element, o = this.options;
1125
1126			if (el.data("enabled")) {
1127				self._showHideHotSpots();
1128
1129				// Stop any running interval
1130				clearInterval(el.data("autoScrollingInterval"));
1131				el.data("autoScrollingInterval", null);
1132
1133				// Callback
1134				self._trigger("autoScrollingStarted");
1135
1136				// Start interval
1137				el.data("autoScrollingInterval", setInterval(function () {
1138
1139					// If the scroller is not visible or
1140					// if the scrollable area is shorter than the scroll wrapper
1141					// any running auto scroll interval should stop.
1142					if (!(el.data("visible")) || (el.data("scrollableAreaWidth") <= (el.data("scrollWrapper").innerWidth()))) {
1143						// Stop any running interval
1144						clearInterval(el.data("autoScrollingInterval"));
1145						el.data("autoScrollingInterval", null);
1146
1147					}
1148					else {
1149
1150						// Store the old scrollLeft value to see if the scrolling has reached the end
1151						el.data("previousScrollLeft", el.data("scrollWrapper").scrollLeft());
1152
1153						switch (o.autoScrollingDirection) {
1154							case "right":
1155
1156								el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() + o.autoScrollingStep);
1157								if (el.data("previousScrollLeft") === el.data("scrollWrapper").scrollLeft()) {
1158									self._trigger("autoScrollingRightLimitReached");
1159									self.stopAutoScrolling();
1160								}
1161								break;
1162
1163							case "left":
1164								el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() - o.autoScrollingStep);
1165								if (el.data("previousScrollLeft") === el.data("scrollWrapper").scrollLeft()) {
1166									self._trigger("autoScrollingLeftLimitReached");
1167									self.stopAutoScrolling();
1168								}
1169								break;
1170
1171							case "backAndForth":
1172								if (el.data("pingPongDirection") === "right") {
1173									el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() + (o.autoScrollingStep));
1174								}
1175								else {
1176									el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() - (o.autoScrollingStep));
1177								}
1178
1179								// If the scrollLeft hasnt't changed it means that the scrolling has reached
1180								// the end and the direction should be switched
1181								if (el.data("previousScrollLeft") === el.data("scrollWrapper").scrollLeft()) {
1182									if (el.data("pingPongDirection") === "right") {
1183										el.data("pingPongDirection", "left");
1184										self._trigger("autoScrollingRightLimitReached");
1185									}
1186									else {
1187										el.data("pingPongDirection", "right");
1188										self._trigger("autoScrollingLeftLimitReached");
1189									}
1190								}
1191								break;
1192
1193							case "endlessLoopRight":
1194
1195								// Do the auto scrolling
1196								el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() + o.autoScrollingStep);
1197
1198								self._checkContinuousSwapRight();
1199								break;
1200							case "endlessLoopLeft":
1201
1202								// Do the auto scrolling
1203								el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() - o.autoScrollingStep);
1204
1205								self._checkContinuousSwapLeft();
1206								break;
1207							default:
1208								break;
1209
1210						}
1211					}
1212				}, o.autoScrollingInterval));
1213			}
1214		},
1215		/**********************************************************
1216		Check Continuos Swap Right
1217		**********************************************************/
1218		_checkContinuousSwapRight: function () {
1219			var el = this.element, o = this.options;
1220
1221			// Get the width of the first element. When it has scrolled out of view,
1222			// the element swapping should be executed. A true/false variable is used
1223			// as a flag variable so the swapAt value doesn't have to be recalculated
1224			// in each loop.  
1225			if (el.data("getNextElementWidth")) {
1226
1227				if ((o.startAtElementId.length > 0) && (el.data("startAtElementHasNotPassed"))) {
1228					// If the user has set a certain element to start at, set swapAt 
1229					// to that element width. This happens once.
1230					el.data("swapAt", $("#" + o.startAtElementId).outerWidth(true));
1231					el.data("startAtElementHasNotPassed", false);
1232				}
1233				else {
1234					// Set swapAt to the first element in the scroller
1235					el.data("swapAt", el.data("scrollableArea").children(":first").outerWidth(true));
1236				}
1237				el.data("getNextElementWidth", false);
1238			}
1239
1240
1241			// Check to see if the swap should be done
1242			if (el.data("swapAt") <= el.data("scrollWrapper").scrollLeft()) {
1243				el.data("swappedElement", el.data("scrollableArea").children(":first").detach());
1244				el.data("scrollableArea").append(el.data("swappedElement"));
1245				var wrapperLeft = el.data("scrollWrapper").scrollLeft();
1246				el.data("scrollWrapper").scrollLeft(wrapperLeft - el.data("swappedElement").outerWidth(true));
1247				el.data("getNextElementWidth", true);
1248			}
1249		},
1250		/**********************************************************
1251		Check Continuos Swap Left
1252		**********************************************************/
1253		_checkContinuousSwapLeft: function () {
1254			var el = this.element, o = this.options;
1255
1256			// Get the width of the first element. When it has scrolled out of view,
1257			// the element swapping should be executed. A true/false variable is used
1258			// as a flag variable so the swapAt value doesn't have to be recalculated
1259			// in each loop.
1260
1261			if (el.data("getNextElementWidth")) {
1262				if ((o.startAtElementId.length > 0) && (el.data("startAtElementHasNotPassed"))) {
1263					el.data("swapAt", $("#" + o.startAtElementId).outerWidth(true));
1264					el.data("startAtElementHasNotPassed", false);
1265				}
1266				else {
1267					el.data("swapAt", el.data("scrollableArea").children(":first").outerWidth(true));
1268				}
1269
1270				el.data("getNextElementWidth", false);
1271			}
1272
1273			// Check to see if the swap should be done
1274			if (el.data("scrollWrapper").scrollLeft() === 0) {
1275       
1276				el.data("swappedElement", el.data("scrollableArea").children(":last").detach());
1277				el.data("scrollableArea").prepend(el.data("swappedElement"));
1278				el.data("scrollWrapper").scrollLeft(el.data("scrollWrapper").scrollLeft() + el.data("swappedElement").outerWidth(true));
1279				el.data("getNextElementWidth", true);
1280        
1281			}
1282
1283		},
1284		restoreOriginalElements: function () {
1285			var self = this, el = this.element;
1286
1287			// Restore the original content of the scrollable area
1288			el.data("scrollableArea").html(el.data("originalElements"));
1289			self.recalculateScrollableArea();
1290			self.jumpToElement("first");
1291		},
1292		show: function () {
1293			var el = this.element;
1294			el.data("visible", true);
1295			el.show();
1296		},
1297		hide: function () {
1298			var el = this.element;
1299			el.data("visible", false);
1300			el.hide();
1301		},
1302		enable: function () {
1303			var el = this.element;
1304
1305			// Enable touch scrolling
1306			if (this.options.touchScrolling) {
1307				el.data("scrollWrapper").kinetic('attach');
1308			}
1309
1310			// Set enabled to true
1311			el.data("enabled", true);
1312		},
1313		disable: function () {
1314			var self = this, el = this.element;
1315
1316			// Clear all running intervals
1317			self.stopAutoScrolling();
1318			clearInterval(el.data("rightScrollingInterval"));
1319			clearInterval(el.data("leftScrollingInterval"));
1320			clearInterval(el.data("hideHotSpotBackgroundsInterval"));
1321
1322			// Disable touch scrolling
1323			if (this.options.touchScrolling) {
1324				el.data("scrollWrapper").kinetic('detach');
1325			}
1326
1327			// Set enabled to false
1328			el.data("enabled", false);
1329		},
1330		destroy: function () {
1331			var self = this, el = this.element;
1332
1333			// Clear all running intervals
1334			self.stopAutoScrolling();
1335			clearInterval(el.data("rightScrollingInterval"));
1336			clearInterval(el.data("leftScrollingInterval"));
1337			clearInterval(el.data("hideHotSpotBackgroundsInterval"));
1338
1339			// Remove all element specific events
1340			el.data("scrollingHotSpotRight").unbind("mouseover");
1341			el.data("scrollingHotSpotRight").unbind("mouseout");
1342			el.data("scrollingHotSpotRight").unbind("mousedown");
1343
1344			el.data("scrollingHotSpotLeft").unbind("mouseover");
1345			el.data("scrollingHotSpotLeft").unbind("mouseout");
1346			el.data("scrollingHotSpotLeft").unbind("mousedown");
1347
1348			el.unbind("mousenter");
1349			el.unbind("mouseleave");
1350
1351			// Remove all elements created by the plugin
1352			el.data("scrollingHotSpotRight").remove();
1353			el.data("scrollingHotSpotLeft").remove();
1354			el.data("scrollableArea").remove();
1355			el.data("scrollWrapper").remove();
1356
1357			// Restore the original content of the scrollable area
1358			el.html(el.data("originalElements"));
1359
1360			// Call the base destroy function
1361			$.Widget.prototype.destroy.apply(this, arguments);
1362
1363		}
1364
1365
1366	});
1367})(jQuery);

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.