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); |
---|