|
1 /* |
|
2 == malihu jquery custom scrollbars plugin == |
|
3 version: 2.8.3 |
|
4 author: malihu (http://manos.malihu.gr) |
|
5 plugin home: http://manos.malihu.gr/jquery-custom-content-scroller |
|
6 */ |
|
7 |
|
8 /* |
|
9 Copyright 2010-2013 Manos Malihutsakis |
|
10 |
|
11 This program is free software: you can redistribute it and/or modify |
|
12 it under the terms of the GNU Lesser General Public License as published by |
|
13 the Free Software Foundation, either version 3 of the License, or |
|
14 any later version. |
|
15 |
|
16 This program is distributed in the hope that it will be useful, |
|
17 but WITHOUT ANY WARRANTY; without even the implied warranty of |
|
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|
19 GNU Lesser General Public License for more details. |
|
20 |
|
21 You should have received a copy of the GNU Lesser General Public License |
|
22 along with this program. If not, see http://www.gnu.org/licenses/lgpl.html. |
|
23 */ |
|
24 (function ($) { |
|
25 /*plugin script*/ |
|
26 var methods = { |
|
27 init: function (options) { |
|
28 var defaults = { |
|
29 set_width: false, /*optional element width: boolean, pixels, percentage*/ |
|
30 set_height: false, /*optional element height: boolean, pixels, percentage*/ |
|
31 horizontalScroll: false, /*scroll horizontally: boolean*/ |
|
32 scrollInertia: 950, /*scrolling inertia: integer (milliseconds)*/ |
|
33 mouseWheel: true, /*mousewheel support: boolean*/ |
|
34 mouseWheelPixels: "auto", /*mousewheel pixels amount: integer, "auto"*/ |
|
35 autoDraggerLength: true, /*auto-adjust scrollbar dragger length: boolean*/ |
|
36 autoHideScrollbar: false, /*auto-hide scrollbar when idle*/ |
|
37 alwaysShowScrollbar: false, /*always show scrollbar even when there's nothing to scroll (disables autoHideScrollbar): boolean*/ |
|
38 snapAmount: null, /* optional element always snaps to a multiple of this number in pixels */ |
|
39 snapOffset: 0, /* when snapping, snap with this number in pixels as an offset */ |
|
40 scrollButtons: { /*scroll buttons*/ |
|
41 enable: false, /*scroll buttons support: boolean*/ |
|
42 scrollType: "continuous", /*scroll buttons scrolling type: "continuous", "pixels"*/ |
|
43 scrollSpeed: "auto", /*scroll buttons continuous scrolling speed: integer, "auto"*/ |
|
44 scrollAmount: 40 /*scroll buttons pixels scroll amount: integer (pixels)*/ |
|
45 }, |
|
46 advanced: { |
|
47 updateOnBrowserResize: true, /*update scrollbars on browser resize (for layouts based on percentages): boolean*/ |
|
48 updateOnContentResize: false, /*auto-update scrollbars on content resize (for dynamic content): boolean*/ |
|
49 autoExpandHorizontalScroll: false, /*auto-expand width for horizontal scrolling: boolean*/ |
|
50 autoScrollOnFocus: true, /*auto-scroll on focused elements: boolean*/ |
|
51 normalizeMouseWheelDelta: false /*normalize mouse-wheel delta (-1/1)*/ |
|
52 }, |
|
53 contentTouchScroll: true, /*scrolling by touch-swipe content: boolean*/ |
|
54 callbacks: { |
|
55 onScrollStart: function () { |
|
56 }, /*user custom callback function on scroll start event*/ |
|
57 onScroll: function () { |
|
58 }, /*user custom callback function on scroll event*/ |
|
59 onTotalScroll: function () { |
|
60 }, /*user custom callback function on scroll end reached event*/ |
|
61 onTotalScrollBack: function () { |
|
62 }, /*user custom callback function on scroll begin reached event*/ |
|
63 onTotalScrollOffset: 0, /*scroll end reached offset: integer (pixels)*/ |
|
64 onTotalScrollBackOffset: 0, /*scroll begin reached offset: integer (pixels)*/ |
|
65 whileScrolling: function () { |
|
66 } /*user custom callback function on scrolling event*/ |
|
67 }, |
|
68 theme: "light" /*"light", "dark", "light-2", "dark-2", "light-thick", "dark-thick", "light-thin", "dark-thin"*/ |
|
69 }, |
|
70 options = $.extend(true, defaults, options); |
|
71 return this.each(function () { |
|
72 var $this = $(this); |
|
73 /*set element width/height, create markup for custom scrollbars, add classes*/ |
|
74 if (options.set_width) { |
|
75 $this.css("width", options.set_width); |
|
76 } |
|
77 if (options.set_height) { |
|
78 $this.css("height", options.set_height); |
|
79 } |
|
80 if (!$(document).data("mCustomScrollbar-index")) { |
|
81 $(document).data("mCustomScrollbar-index", "1"); |
|
82 } else { |
|
83 var mCustomScrollbarIndex = parseInt($(document).data("mCustomScrollbar-index")); |
|
84 $(document).data("mCustomScrollbar-index", mCustomScrollbarIndex + 1); |
|
85 } |
|
86 $this.wrapInner("<div class='mCustomScrollBox" + " mCS-" + options.theme + "' id='mCSB_" + $(document).data("mCustomScrollbar-index") + "' style='position:relative; height:100%; overflow:hidden; max-width:100%;' />").addClass("mCustomScrollbar _mCS_" + $(document).data("mCustomScrollbar-index")); |
|
87 var mCustomScrollBox = $this.children(".mCustomScrollBox"); |
|
88 if (options.horizontalScroll) { |
|
89 mCustomScrollBox.addClass("mCSB_horizontal").wrapInner("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />"); |
|
90 var mCSB_h_wrapper = mCustomScrollBox.children(".mCSB_h_wrapper"); |
|
91 mCSB_h_wrapper.wrapInner("<div class='mCSB_container' style='position:absolute; left:0;' />").children(".mCSB_container").css({"width": mCSB_h_wrapper.children().outerWidth(), "position": "relative"}).unwrap(); |
|
92 } else { |
|
93 mCustomScrollBox.wrapInner("<div class='mCSB_container' style='position:relative; top:0;' />"); |
|
94 } |
|
95 var mCSB_container = mCustomScrollBox.children(".mCSB_container"); |
|
96 if ($.support.touch) { |
|
97 mCSB_container.addClass("mCS_touch"); |
|
98 } |
|
99 mCSB_container.after("<div class='mCSB_scrollTools' style='position:absolute;'><div class='mCSB_draggerContainer'><div class='mCSB_dragger' style='position:absolute;' oncontextmenu='return false;'><div class='mCSB_dragger_bar' style='position:relative;'></div></div><div class='mCSB_draggerRail'></div></div></div>"); |
|
100 var mCSB_scrollTools = mCustomScrollBox.children(".mCSB_scrollTools"), |
|
101 mCSB_draggerContainer = mCSB_scrollTools.children(".mCSB_draggerContainer"), |
|
102 mCSB_dragger = mCSB_draggerContainer.children(".mCSB_dragger"); |
|
103 if (options.horizontalScroll) { |
|
104 mCSB_dragger.data("minDraggerWidth", mCSB_dragger.width()); |
|
105 } else { |
|
106 mCSB_dragger.data("minDraggerHeight", mCSB_dragger.height()); |
|
107 } |
|
108 if (options.scrollButtons.enable) { |
|
109 if (options.horizontalScroll) { |
|
110 mCSB_scrollTools.prepend("<a class='mCSB_buttonLeft' oncontextmenu='return false;'></a>").append("<a class='mCSB_buttonRight' oncontextmenu='return false;'></a>"); |
|
111 } else { |
|
112 mCSB_scrollTools.prepend("<a class='mCSB_buttonUp' oncontextmenu='return false;'></a>").append("<a class='mCSB_buttonDown' oncontextmenu='return false;'></a>"); |
|
113 } |
|
114 } |
|
115 /*mCustomScrollBox scrollTop and scrollLeft is always 0 to prevent browser focus scrolling*/ |
|
116 mCustomScrollBox.bind("scroll", function () { |
|
117 if (!$this.is(".mCS_disabled")) { /*native focus scrolling for disabled scrollbars*/ |
|
118 mCustomScrollBox.scrollTop(0).scrollLeft(0); |
|
119 } |
|
120 }); |
|
121 /*store options, global vars/states, intervals*/ |
|
122 $this.data({ |
|
123 /*init state*/ |
|
124 "mCS_Init": true, |
|
125 /*instance index*/ |
|
126 "mCustomScrollbarIndex": $(document).data("mCustomScrollbar-index"), |
|
127 /*option parameters*/ |
|
128 "horizontalScroll": options.horizontalScroll, |
|
129 "scrollInertia": options.scrollInertia, |
|
130 "scrollEasing": "mcsEaseOut", |
|
131 "mouseWheel": options.mouseWheel, |
|
132 "mouseWheelPixels": options.mouseWheelPixels, |
|
133 "autoDraggerLength": options.autoDraggerLength, |
|
134 "autoHideScrollbar": options.autoHideScrollbar, |
|
135 "alwaysShowScrollbar": options.alwaysShowScrollbar, |
|
136 "snapAmount": options.snapAmount, |
|
137 "snapOffset": options.snapOffset, |
|
138 "scrollButtons_enable": options.scrollButtons.enable, |
|
139 "scrollButtons_scrollType": options.scrollButtons.scrollType, |
|
140 "scrollButtons_scrollSpeed": options.scrollButtons.scrollSpeed, |
|
141 "scrollButtons_scrollAmount": options.scrollButtons.scrollAmount, |
|
142 "autoExpandHorizontalScroll": options.advanced.autoExpandHorizontalScroll, |
|
143 "autoScrollOnFocus": options.advanced.autoScrollOnFocus, |
|
144 "normalizeMouseWheelDelta": options.advanced.normalizeMouseWheelDelta, |
|
145 "contentTouchScroll": options.contentTouchScroll, |
|
146 "onScrollStart_Callback": options.callbacks.onScrollStart, |
|
147 "onScroll_Callback": options.callbacks.onScroll, |
|
148 "onTotalScroll_Callback": options.callbacks.onTotalScroll, |
|
149 "onTotalScrollBack_Callback": options.callbacks.onTotalScrollBack, |
|
150 "onTotalScroll_Offset": options.callbacks.onTotalScrollOffset, |
|
151 "onTotalScrollBack_Offset": options.callbacks.onTotalScrollBackOffset, |
|
152 "whileScrolling_Callback": options.callbacks.whileScrolling, |
|
153 /*events binding state*/ |
|
154 "bindEvent_scrollbar_drag": false, |
|
155 "bindEvent_content_touch": false, |
|
156 "bindEvent_scrollbar_click": false, |
|
157 "bindEvent_mousewheel": false, |
|
158 "bindEvent_buttonsContinuous_y": false, |
|
159 "bindEvent_buttonsContinuous_x": false, |
|
160 "bindEvent_buttonsPixels_y": false, |
|
161 "bindEvent_buttonsPixels_x": false, |
|
162 "bindEvent_focusin": false, |
|
163 "bindEvent_autoHideScrollbar": false, |
|
164 /*buttons intervals*/ |
|
165 "mCSB_buttonScrollRight": false, |
|
166 "mCSB_buttonScrollLeft": false, |
|
167 "mCSB_buttonScrollDown": false, |
|
168 "mCSB_buttonScrollUp": false |
|
169 }); |
|
170 /*max-width/max-height*/ |
|
171 if (options.horizontalScroll) { |
|
172 if ($this.css("max-width") !== "none") { |
|
173 if (!options.advanced.updateOnContentResize) { /*needs updateOnContentResize*/ |
|
174 options.advanced.updateOnContentResize = true; |
|
175 } |
|
176 } |
|
177 } else { |
|
178 if ($this.css("max-height") !== "none") { |
|
179 var percentage = false, maxHeight = parseInt($this.css("max-height")); |
|
180 if ($this.css("max-height").indexOf("%") >= 0) { |
|
181 percentage = maxHeight, |
|
182 maxHeight = $this.parent().height() * percentage / 100; |
|
183 } |
|
184 $this.css("overflow", "hidden"); |
|
185 mCustomScrollBox.css("max-height", maxHeight); |
|
186 } |
|
187 } |
|
188 $this.mCustomScrollbar("update"); |
|
189 /*window resize fn (for layouts based on percentages)*/ |
|
190 if (options.advanced.updateOnBrowserResize) { |
|
191 var mCSB_resizeTimeout, currWinWidth = $(window).width(), currWinHeight = $(window).height(); |
|
192 $(window).bind("resize." + $this.data("mCustomScrollbarIndex"), function () { |
|
193 if (mCSB_resizeTimeout) { |
|
194 clearTimeout(mCSB_resizeTimeout); |
|
195 } |
|
196 mCSB_resizeTimeout = setTimeout(function () { |
|
197 if (!$this.is(".mCS_disabled") && !$this.is(".mCS_destroyed")) { |
|
198 var winWidth = $(window).width(), winHeight = $(window).height(); |
|
199 if (currWinWidth !== winWidth || currWinHeight !== winHeight) { /*ie8 fix*/ |
|
200 if ($this.css("max-height") !== "none" && percentage) { |
|
201 mCustomScrollBox.css("max-height", $this.parent().height() * percentage / 100); |
|
202 } |
|
203 $this.mCustomScrollbar("update"); |
|
204 currWinWidth = winWidth; |
|
205 currWinHeight = winHeight; |
|
206 } |
|
207 } |
|
208 }, 150); |
|
209 }); |
|
210 } |
|
211 /*content resize fn (for dynamically generated content)*/ |
|
212 if (options.advanced.updateOnContentResize) { |
|
213 var mCSB_onContentResize; |
|
214 if (options.horizontalScroll) { |
|
215 var mCSB_containerOldSize = mCSB_container.outerWidth(); |
|
216 } else { |
|
217 var mCSB_containerOldSize = mCSB_container.outerHeight(); |
|
218 } |
|
219 mCSB_onContentResize = setInterval(function () { |
|
220 if (options.horizontalScroll) { |
|
221 if (options.advanced.autoExpandHorizontalScroll) { |
|
222 mCSB_container.css({"position": "absolute", "width": "auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({"width": mCSB_container.outerWidth(), "position": "relative"}).unwrap(); |
|
223 } |
|
224 var mCSB_containerNewSize = mCSB_container.outerWidth(); |
|
225 } else { |
|
226 var mCSB_containerNewSize = mCSB_container.outerHeight(); |
|
227 } |
|
228 if (mCSB_containerNewSize != mCSB_containerOldSize) { |
|
229 $this.mCustomScrollbar("update"); |
|
230 mCSB_containerOldSize = mCSB_containerNewSize; |
|
231 } |
|
232 }, 300); |
|
233 } |
|
234 }); |
|
235 }, |
|
236 update: function () { |
|
237 var $this = $(this), |
|
238 mCustomScrollBox = $this.children(".mCustomScrollBox"), |
|
239 mCSB_container = mCustomScrollBox.children(".mCSB_container"); |
|
240 mCSB_container.removeClass("mCS_no_scrollbar"); |
|
241 $this.removeClass("mCS_disabled mCS_destroyed"); |
|
242 mCustomScrollBox.scrollTop(0).scrollLeft(0); |
|
243 /*reset scrollTop/scrollLeft to prevent browser focus scrolling*/ |
|
244 var mCSB_scrollTools = mCustomScrollBox.children(".mCSB_scrollTools"), |
|
245 mCSB_draggerContainer = mCSB_scrollTools.children(".mCSB_draggerContainer"), |
|
246 mCSB_dragger = mCSB_draggerContainer.children(".mCSB_dragger"); |
|
247 if ($this.data("horizontalScroll")) { |
|
248 var mCSB_buttonLeft = mCSB_scrollTools.children(".mCSB_buttonLeft"), |
|
249 mCSB_buttonRight = mCSB_scrollTools.children(".mCSB_buttonRight"), |
|
250 mCustomScrollBoxW = mCustomScrollBox.width(); |
|
251 if ($this.data("autoExpandHorizontalScroll")) { |
|
252 mCSB_container.css({"position": "absolute", "width": "auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({"width": mCSB_container.outerWidth(), "position": "relative"}).unwrap(); |
|
253 } |
|
254 var mCSB_containerW = mCSB_container.outerWidth(); |
|
255 } else { |
|
256 var mCSB_buttonUp = mCSB_scrollTools.children(".mCSB_buttonUp"), |
|
257 mCSB_buttonDown = mCSB_scrollTools.children(".mCSB_buttonDown"), |
|
258 mCustomScrollBoxH = mCustomScrollBox.height(), |
|
259 mCSB_containerH = mCSB_container.outerHeight(); |
|
260 } |
|
261 if (mCSB_containerH > mCustomScrollBoxH && !$this.data("horizontalScroll")) { /*content needs vertical scrolling*/ |
|
262 mCSB_scrollTools.css("display", "block"); |
|
263 var mCSB_draggerContainerH = mCSB_draggerContainer.height(); |
|
264 /*auto adjust scrollbar dragger length analogous to content*/ |
|
265 if ($this.data("autoDraggerLength")) { |
|
266 var draggerH = Math.round(mCustomScrollBoxH / mCSB_containerH * mCSB_draggerContainerH), |
|
267 minDraggerH = mCSB_dragger.data("minDraggerHeight"); |
|
268 if (draggerH <= minDraggerH) { /*min dragger height*/ |
|
269 mCSB_dragger.css({"height": minDraggerH}); |
|
270 } else if (draggerH >= mCSB_draggerContainerH - 10) { /*max dragger height*/ |
|
271 var mCSB_draggerContainerMaxH = mCSB_draggerContainerH - 10; |
|
272 mCSB_dragger.css({"height": mCSB_draggerContainerMaxH}); |
|
273 } else { |
|
274 mCSB_dragger.css({"height": draggerH}); |
|
275 } |
|
276 mCSB_dragger.children(".mCSB_dragger_bar").css({"line-height": mCSB_dragger.height() + "px"}); |
|
277 } |
|
278 var mCSB_draggerH = mCSB_dragger.height(), |
|
279 /*calculate and store scroll amount, add scrolling*/ |
|
280 scrollAmount = (mCSB_containerH - mCustomScrollBoxH) / (mCSB_draggerContainerH - mCSB_draggerH); |
|
281 $this.data("scrollAmount", scrollAmount).mCustomScrollbar("scrolling", mCustomScrollBox, mCSB_container, mCSB_draggerContainer, mCSB_dragger, mCSB_buttonUp, mCSB_buttonDown, mCSB_buttonLeft, mCSB_buttonRight); |
|
282 /*scroll*/ |
|
283 var mCSB_containerP = Math.abs(mCSB_container.position().top); |
|
284 $this.mCustomScrollbar("scrollTo", mCSB_containerP, {scrollInertia: 0, trigger: "internal"}); |
|
285 } else if (mCSB_containerW > mCustomScrollBoxW && $this.data("horizontalScroll")) { /*content needs horizontal scrolling*/ |
|
286 mCSB_scrollTools.css("display", "block"); |
|
287 var mCSB_draggerContainerW = mCSB_draggerContainer.width(); |
|
288 /*auto adjust scrollbar dragger length analogous to content*/ |
|
289 if ($this.data("autoDraggerLength")) { |
|
290 var draggerW = Math.round(mCustomScrollBoxW / mCSB_containerW * mCSB_draggerContainerW), |
|
291 minDraggerW = mCSB_dragger.data("minDraggerWidth"); |
|
292 if (draggerW <= minDraggerW) { /*min dragger height*/ |
|
293 mCSB_dragger.css({"width": minDraggerW}); |
|
294 } else if (draggerW >= mCSB_draggerContainerW - 10) { /*max dragger height*/ |
|
295 var mCSB_draggerContainerMaxW = mCSB_draggerContainerW - 10; |
|
296 mCSB_dragger.css({"width": mCSB_draggerContainerMaxW}); |
|
297 } else { |
|
298 mCSB_dragger.css({"width": draggerW}); |
|
299 } |
|
300 } |
|
301 var mCSB_draggerW = mCSB_dragger.width(), |
|
302 /*calculate and store scroll amount, add scrolling*/ |
|
303 scrollAmount = (mCSB_containerW - mCustomScrollBoxW) / (mCSB_draggerContainerW - mCSB_draggerW); |
|
304 $this.data("scrollAmount", scrollAmount).mCustomScrollbar("scrolling", mCustomScrollBox, mCSB_container, mCSB_draggerContainer, mCSB_dragger, mCSB_buttonUp, mCSB_buttonDown, mCSB_buttonLeft, mCSB_buttonRight); |
|
305 /*scroll*/ |
|
306 var mCSB_containerP = Math.abs(mCSB_container.position().left); |
|
307 $this.mCustomScrollbar("scrollTo", mCSB_containerP, {scrollInertia: 0, trigger: "internal"}); |
|
308 } else { /*content does not need scrolling*/ |
|
309 /*unbind events, reset content position, hide scrollbars, remove classes*/ |
|
310 mCustomScrollBox.unbind("mousewheel focusin"); |
|
311 if ($this.data("horizontalScroll")) { |
|
312 mCSB_dragger.add(mCSB_container).css("left", 0); |
|
313 } else { |
|
314 mCSB_dragger.add(mCSB_container).css("top", 0); |
|
315 } |
|
316 if ($this.data("alwaysShowScrollbar")) { |
|
317 if (!$this.data("horizontalScroll")) { /*vertical scrolling*/ |
|
318 mCSB_dragger.css({"height": mCSB_draggerContainer.height()}); |
|
319 } else if ($this.data("horizontalScroll")) { /*horizontal scrolling*/ |
|
320 mCSB_dragger.css({"width": mCSB_draggerContainer.width()}); |
|
321 } |
|
322 } else { |
|
323 mCSB_scrollTools.css("display", "none"); |
|
324 mCSB_container.addClass("mCS_no_scrollbar"); |
|
325 } |
|
326 $this.data({"bindEvent_mousewheel": false, "bindEvent_focusin": false}); |
|
327 } |
|
328 }, |
|
329 scrolling: function (mCustomScrollBox, mCSB_container, mCSB_draggerContainer, mCSB_dragger, mCSB_buttonUp, mCSB_buttonDown, mCSB_buttonLeft, mCSB_buttonRight) { |
|
330 var $this = $(this); |
|
331 /*scrollbar drag scrolling*/ |
|
332 if (!$this.data("bindEvent_scrollbar_drag")) { |
|
333 var mCSB_draggerDragY, mCSB_draggerDragX, |
|
334 mCSB_dragger_downEvent, mCSB_dragger_moveEvent, mCSB_dragger_upEvent; |
|
335 if ($.support.pointer) { /*pointer*/ |
|
336 mCSB_dragger_downEvent = "pointerdown"; |
|
337 mCSB_dragger_moveEvent = "pointermove"; |
|
338 mCSB_dragger_upEvent = "pointerup"; |
|
339 } else if ($.support.msPointer) { /*MSPointer*/ |
|
340 mCSB_dragger_downEvent = "MSPointerDown"; |
|
341 mCSB_dragger_moveEvent = "MSPointerMove"; |
|
342 mCSB_dragger_upEvent = "MSPointerUp"; |
|
343 } |
|
344 if ($.support.pointer || $.support.msPointer) { /*pointer, MSPointer*/ |
|
345 mCSB_dragger.bind(mCSB_dragger_downEvent, function (e) { |
|
346 e.preventDefault(); |
|
347 $this.data({"on_drag": true}); |
|
348 mCSB_dragger.addClass("mCSB_dragger_onDrag"); |
|
349 var elem = $(this), |
|
350 elemOffset = elem.offset(), |
|
351 x = e.originalEvent.pageX - elemOffset.left, |
|
352 y = e.originalEvent.pageY - elemOffset.top; |
|
353 if (x < elem.width() && x > 0 && y < elem.height() && y > 0) { |
|
354 mCSB_draggerDragY = y; |
|
355 mCSB_draggerDragX = x; |
|
356 } |
|
357 }); |
|
358 $(document).bind(mCSB_dragger_moveEvent + "." + $this.data("mCustomScrollbarIndex"),function (e) { |
|
359 e.preventDefault(); |
|
360 if ($this.data("on_drag")) { |
|
361 var elem = mCSB_dragger, |
|
362 elemOffset = elem.offset(), |
|
363 x = e.originalEvent.pageX - elemOffset.left, |
|
364 y = e.originalEvent.pageY - elemOffset.top; |
|
365 scrollbarDrag(mCSB_draggerDragY, mCSB_draggerDragX, y, x); |
|
366 } |
|
367 }).bind(mCSB_dragger_upEvent + "." + $this.data("mCustomScrollbarIndex"), function (e) { |
|
368 $this.data({"on_drag": false}); |
|
369 mCSB_dragger.removeClass("mCSB_dragger_onDrag"); |
|
370 }); |
|
371 } else { /*mouse/touch*/ |
|
372 mCSB_dragger.bind("mousedown touchstart",function (e) { |
|
373 e.preventDefault(); |
|
374 e.stopImmediatePropagation(); |
|
375 var elem = $(this), elemOffset = elem.offset(), x, y; |
|
376 if (e.type === "touchstart") { |
|
377 var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; |
|
378 x = touch.pageX - elemOffset.left; |
|
379 y = touch.pageY - elemOffset.top; |
|
380 } else { |
|
381 $this.data({"on_drag": true}); |
|
382 mCSB_dragger.addClass("mCSB_dragger_onDrag"); |
|
383 x = e.pageX - elemOffset.left; |
|
384 y = e.pageY - elemOffset.top; |
|
385 } |
|
386 if (x < elem.width() && x > 0 && y < elem.height() && y > 0) { |
|
387 mCSB_draggerDragY = y; |
|
388 mCSB_draggerDragX = x; |
|
389 } |
|
390 }).bind("touchmove", function (e) { |
|
391 e.preventDefault(); |
|
392 e.stopImmediatePropagation(); |
|
393 var touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0], |
|
394 elem = $(this), |
|
395 elemOffset = elem.offset(), |
|
396 x = touch.pageX - elemOffset.left, |
|
397 y = touch.pageY - elemOffset.top; |
|
398 scrollbarDrag(mCSB_draggerDragY, mCSB_draggerDragX, y, x); |
|
399 }); |
|
400 $(document).bind("mousemove." + $this.data("mCustomScrollbarIndex"),function (e) { |
|
401 if ($this.data("on_drag")) { |
|
402 var elem = mCSB_dragger, |
|
403 elemOffset = elem.offset(), |
|
404 x = e.pageX - elemOffset.left, |
|
405 y = e.pageY - elemOffset.top; |
|
406 scrollbarDrag(mCSB_draggerDragY, mCSB_draggerDragX, y, x); |
|
407 } |
|
408 }).bind("mouseup." + $this.data("mCustomScrollbarIndex"), function (e) { |
|
409 $this.data({"on_drag": false}); |
|
410 mCSB_dragger.removeClass("mCSB_dragger_onDrag"); |
|
411 }); |
|
412 } |
|
413 $this.data({"bindEvent_scrollbar_drag": true}); |
|
414 } |
|
415 function scrollbarDrag(mCSB_draggerDragY, mCSB_draggerDragX, y, x) { |
|
416 if ($this.data("horizontalScroll")) { |
|
417 $this.mCustomScrollbar("scrollTo", (mCSB_dragger.position().left - (mCSB_draggerDragX)) + x, {moveDragger: true, trigger: "internal"}); |
|
418 } else { |
|
419 $this.mCustomScrollbar("scrollTo", (mCSB_dragger.position().top - (mCSB_draggerDragY)) + y, {moveDragger: true, trigger: "internal"}); |
|
420 } |
|
421 } |
|
422 |
|
423 /*content touch-drag*/ |
|
424 if ($.support.touch && $this.data("contentTouchScroll")) { |
|
425 if (!$this.data("bindEvent_content_touch")) { |
|
426 var touch, |
|
427 elem, elemOffset, y, x, mCSB_containerTouchY, mCSB_containerTouchX; |
|
428 mCSB_container.bind("touchstart", function (e) { |
|
429 e.stopImmediatePropagation(); |
|
430 touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; |
|
431 elem = $(this); |
|
432 elemOffset = elem.offset(); |
|
433 x = touch.pageX - elemOffset.left; |
|
434 y = touch.pageY - elemOffset.top; |
|
435 mCSB_containerTouchY = y; |
|
436 mCSB_containerTouchX = x; |
|
437 }); |
|
438 mCSB_container.bind("touchmove", function (e) { |
|
439 e.preventDefault(); |
|
440 e.stopImmediatePropagation(); |
|
441 touch = e.originalEvent.touches[0] || e.originalEvent.changedTouches[0]; |
|
442 elem = $(this).parent(); |
|
443 elemOffset = elem.offset(); |
|
444 x = touch.pageX - elemOffset.left; |
|
445 y = touch.pageY - elemOffset.top; |
|
446 if ($this.data("horizontalScroll")) { |
|
447 $this.mCustomScrollbar("scrollTo", mCSB_containerTouchX - x, {trigger: "internal"}); |
|
448 } else { |
|
449 $this.mCustomScrollbar("scrollTo", mCSB_containerTouchY - y, {trigger: "internal"}); |
|
450 } |
|
451 }); |
|
452 } |
|
453 } |
|
454 /*dragger rail click scrolling*/ |
|
455 if (!$this.data("bindEvent_scrollbar_click")) { |
|
456 mCSB_draggerContainer.bind("click", function (e) { |
|
457 var scrollToPos = (e.pageY - mCSB_draggerContainer.offset().top) * $this.data("scrollAmount"), target = $(e.target); |
|
458 if ($this.data("horizontalScroll")) { |
|
459 scrollToPos = (e.pageX - mCSB_draggerContainer.offset().left) * $this.data("scrollAmount"); |
|
460 } |
|
461 if (target.hasClass("mCSB_draggerContainer") || target.hasClass("mCSB_draggerRail")) { |
|
462 $this.mCustomScrollbar("scrollTo", scrollToPos, {trigger: "internal", scrollEasing: "draggerRailEase"}); |
|
463 } |
|
464 }); |
|
465 $this.data({"bindEvent_scrollbar_click": true}); |
|
466 } |
|
467 /*mousewheel scrolling*/ |
|
468 if ($this.data("mouseWheel")) { |
|
469 if (!$this.data("bindEvent_mousewheel")) { |
|
470 mCustomScrollBox.bind("mousewheel", function (e, delta) { |
|
471 var scrollTo, mouseWheelPixels = $this.data("mouseWheelPixels"), absPos = Math.abs(mCSB_container.position().top), |
|
472 draggerPos = mCSB_dragger.position().top, limit = mCSB_draggerContainer.height() - mCSB_dragger.height(); |
|
473 if ($this.data("normalizeMouseWheelDelta")) { |
|
474 if (delta < 0) { |
|
475 delta = -1; |
|
476 } else { |
|
477 delta = 1; |
|
478 } |
|
479 } |
|
480 if (mouseWheelPixels === "auto") { |
|
481 mouseWheelPixels = 100 + Math.round($this.data("scrollAmount") / 2); |
|
482 } |
|
483 if ($this.data("horizontalScroll")) { |
|
484 draggerPos = mCSB_dragger.position().left; |
|
485 limit = mCSB_draggerContainer.width() - mCSB_dragger.width(); |
|
486 absPos = Math.abs(mCSB_container.position().left); |
|
487 } |
|
488 if ((delta > 0 && draggerPos !== 0) || (delta < 0 && draggerPos !== limit)) { |
|
489 e.preventDefault(); |
|
490 e.stopImmediatePropagation(); |
|
491 } |
|
492 scrollTo = absPos - (delta * mouseWheelPixels); |
|
493 $this.mCustomScrollbar("scrollTo", scrollTo, {trigger: "internal"}); |
|
494 }); |
|
495 $this.data({"bindEvent_mousewheel": true}); |
|
496 } |
|
497 } |
|
498 /*buttons scrolling*/ |
|
499 if ($this.data("scrollButtons_enable")) { |
|
500 if ($this.data("scrollButtons_scrollType") === "pixels") { /*scroll by pixels*/ |
|
501 if ($this.data("horizontalScroll")) { |
|
502 mCSB_buttonRight.add(mCSB_buttonLeft).unbind("mousedown touchstart MSPointerDown pointerdown mouseup MSPointerUp pointerup mouseout MSPointerOut pointerout touchend", mCSB_buttonRight_stop, mCSB_buttonLeft_stop); |
|
503 $this.data({"bindEvent_buttonsContinuous_x": false}); |
|
504 if (!$this.data("bindEvent_buttonsPixels_x")) { |
|
505 /*scroll right*/ |
|
506 mCSB_buttonRight.bind("click", function (e) { |
|
507 e.preventDefault(); |
|
508 PixelsScrollTo(Math.abs(mCSB_container.position().left) + $this.data("scrollButtons_scrollAmount")); |
|
509 }); |
|
510 /*scroll left*/ |
|
511 mCSB_buttonLeft.bind("click", function (e) { |
|
512 e.preventDefault(); |
|
513 PixelsScrollTo(Math.abs(mCSB_container.position().left) - $this.data("scrollButtons_scrollAmount")); |
|
514 }); |
|
515 $this.data({"bindEvent_buttonsPixels_x": true}); |
|
516 } |
|
517 } else { |
|
518 mCSB_buttonDown.add(mCSB_buttonUp).unbind("mousedown touchstart MSPointerDown pointerdown mouseup MSPointerUp pointerup mouseout MSPointerOut pointerout touchend", mCSB_buttonRight_stop, mCSB_buttonLeft_stop); |
|
519 $this.data({"bindEvent_buttonsContinuous_y": false}); |
|
520 if (!$this.data("bindEvent_buttonsPixels_y")) { |
|
521 /*scroll down*/ |
|
522 mCSB_buttonDown.bind("click", function (e) { |
|
523 e.preventDefault(); |
|
524 PixelsScrollTo(Math.abs(mCSB_container.position().top) + $this.data("scrollButtons_scrollAmount")); |
|
525 }); |
|
526 /*scroll up*/ |
|
527 mCSB_buttonUp.bind("click", function (e) { |
|
528 e.preventDefault(); |
|
529 PixelsScrollTo(Math.abs(mCSB_container.position().top) - $this.data("scrollButtons_scrollAmount")); |
|
530 }); |
|
531 $this.data({"bindEvent_buttonsPixels_y": true}); |
|
532 } |
|
533 } |
|
534 function PixelsScrollTo(to) { |
|
535 if (!mCSB_dragger.data("preventAction")) { |
|
536 mCSB_dragger.data("preventAction", true); |
|
537 $this.mCustomScrollbar("scrollTo", to, {trigger: "internal"}); |
|
538 } |
|
539 } |
|
540 } else { /*continuous scrolling*/ |
|
541 if ($this.data("horizontalScroll")) { |
|
542 mCSB_buttonRight.add(mCSB_buttonLeft).unbind("click"); |
|
543 $this.data({"bindEvent_buttonsPixels_x": false}); |
|
544 if (!$this.data("bindEvent_buttonsContinuous_x")) { |
|
545 /*scroll right*/ |
|
546 mCSB_buttonRight.bind("mousedown touchstart MSPointerDown pointerdown", function (e) { |
|
547 e.preventDefault(); |
|
548 var scrollButtonsSpeed = ScrollButtonsSpeed(); |
|
549 $this.data({"mCSB_buttonScrollRight": setInterval(function () { |
|
550 $this.mCustomScrollbar("scrollTo", Math.abs(mCSB_container.position().left) + scrollButtonsSpeed, {trigger: "internal", scrollEasing: "easeOutCirc"}); |
|
551 }, 17)}); |
|
552 }); |
|
553 var mCSB_buttonRight_stop = function (e) { |
|
554 e.preventDefault(); |
|
555 clearInterval($this.data("mCSB_buttonScrollRight")); |
|
556 } |
|
557 mCSB_buttonRight.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout", mCSB_buttonRight_stop); |
|
558 /*scroll left*/ |
|
559 mCSB_buttonLeft.bind("mousedown touchstart MSPointerDown pointerdown", function (e) { |
|
560 e.preventDefault(); |
|
561 var scrollButtonsSpeed = ScrollButtonsSpeed(); |
|
562 $this.data({"mCSB_buttonScrollLeft": setInterval(function () { |
|
563 $this.mCustomScrollbar("scrollTo", Math.abs(mCSB_container.position().left) - scrollButtonsSpeed, {trigger: "internal", scrollEasing: "easeOutCirc"}); |
|
564 }, 17)}); |
|
565 }); |
|
566 var mCSB_buttonLeft_stop = function (e) { |
|
567 e.preventDefault(); |
|
568 clearInterval($this.data("mCSB_buttonScrollLeft")); |
|
569 } |
|
570 mCSB_buttonLeft.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout", mCSB_buttonLeft_stop); |
|
571 $this.data({"bindEvent_buttonsContinuous_x": true}); |
|
572 } |
|
573 } else { |
|
574 mCSB_buttonDown.add(mCSB_buttonUp).unbind("click"); |
|
575 $this.data({"bindEvent_buttonsPixels_y": false}); |
|
576 if (!$this.data("bindEvent_buttonsContinuous_y")) { |
|
577 /*scroll down*/ |
|
578 mCSB_buttonDown.bind("mousedown touchstart MSPointerDown pointerdown", function (e) { |
|
579 e.preventDefault(); |
|
580 var scrollButtonsSpeed = ScrollButtonsSpeed(); |
|
581 $this.data({"mCSB_buttonScrollDown": setInterval(function () { |
|
582 $this.mCustomScrollbar("scrollTo", Math.abs(mCSB_container.position().top) + scrollButtonsSpeed, {trigger: "internal", scrollEasing: "easeOutCirc"}); |
|
583 }, 17)}); |
|
584 }); |
|
585 var mCSB_buttonDown_stop = function (e) { |
|
586 e.preventDefault(); |
|
587 clearInterval($this.data("mCSB_buttonScrollDown")); |
|
588 } |
|
589 mCSB_buttonDown.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout", mCSB_buttonDown_stop); |
|
590 /*scroll up*/ |
|
591 mCSB_buttonUp.bind("mousedown touchstart MSPointerDown pointerdown", function (e) { |
|
592 e.preventDefault(); |
|
593 var scrollButtonsSpeed = ScrollButtonsSpeed(); |
|
594 $this.data({"mCSB_buttonScrollUp": setInterval(function () { |
|
595 $this.mCustomScrollbar("scrollTo", Math.abs(mCSB_container.position().top) - scrollButtonsSpeed, {trigger: "internal", scrollEasing: "easeOutCirc"}); |
|
596 }, 17)}); |
|
597 }); |
|
598 var mCSB_buttonUp_stop = function (e) { |
|
599 e.preventDefault(); |
|
600 clearInterval($this.data("mCSB_buttonScrollUp")); |
|
601 } |
|
602 mCSB_buttonUp.bind("mouseup touchend MSPointerUp pointerup mouseout MSPointerOut pointerout", mCSB_buttonUp_stop); |
|
603 $this.data({"bindEvent_buttonsContinuous_y": true}); |
|
604 } |
|
605 } |
|
606 function ScrollButtonsSpeed() { |
|
607 var speed = $this.data("scrollButtons_scrollSpeed"); |
|
608 if ($this.data("scrollButtons_scrollSpeed") === "auto") { |
|
609 speed = Math.round(($this.data("scrollInertia") + 100) / 40); |
|
610 } |
|
611 return speed; |
|
612 } |
|
613 } |
|
614 } |
|
615 /*scrolling on element focus (e.g. via TAB key)*/ |
|
616 if ($this.data("autoScrollOnFocus")) { |
|
617 if (!$this.data("bindEvent_focusin")) { |
|
618 mCustomScrollBox.bind("focusin", function () { |
|
619 mCustomScrollBox.scrollTop(0).scrollLeft(0); |
|
620 var focusedElem = $(document.activeElement); |
|
621 if (focusedElem.is("input,textarea,select,button,a[tabindex],area,object")) { |
|
622 var mCSB_containerPos = mCSB_container.position().top, |
|
623 focusedElemPos = focusedElem.position().top, |
|
624 visibleLimit = mCustomScrollBox.height() - focusedElem.outerHeight(); |
|
625 if ($this.data("horizontalScroll")) { |
|
626 mCSB_containerPos = mCSB_container.position().left; |
|
627 focusedElemPos = focusedElem.position().left; |
|
628 visibleLimit = mCustomScrollBox.width() - focusedElem.outerWidth(); |
|
629 } |
|
630 if (mCSB_containerPos + focusedElemPos < 0 || mCSB_containerPos + focusedElemPos > visibleLimit) { |
|
631 $this.mCustomScrollbar("scrollTo", focusedElemPos, {trigger: "internal"}); |
|
632 } |
|
633 } |
|
634 }); |
|
635 $this.data({"bindEvent_focusin": true}); |
|
636 } |
|
637 } |
|
638 /*auto-hide scrollbar*/ |
|
639 if ($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")) { |
|
640 if (!$this.data("bindEvent_autoHideScrollbar")) { |
|
641 mCustomScrollBox.bind("mouseenter",function (e) { |
|
642 mCustomScrollBox.addClass("mCS-mouse-over"); |
|
643 functions.showScrollbar.call(mCustomScrollBox.children(".mCSB_scrollTools")); |
|
644 }).bind("mouseleave touchend", function (e) { |
|
645 mCustomScrollBox.removeClass("mCS-mouse-over"); |
|
646 if (e.type === "mouseleave") { |
|
647 functions.hideScrollbar.call(mCustomScrollBox.children(".mCSB_scrollTools")); |
|
648 } |
|
649 }); |
|
650 $this.data({"bindEvent_autoHideScrollbar": true}); |
|
651 } |
|
652 } |
|
653 }, |
|
654 scrollTo: function (scrollTo, options) { |
|
655 var $this = $(this), |
|
656 defaults = { |
|
657 moveDragger: false, |
|
658 trigger: "external", |
|
659 callbacks: true, |
|
660 scrollInertia: $this.data("scrollInertia"), |
|
661 scrollEasing: $this.data("scrollEasing") |
|
662 }, |
|
663 options = $.extend(defaults, options), |
|
664 draggerScrollTo, |
|
665 mCustomScrollBox = $this.children(".mCustomScrollBox"), |
|
666 mCSB_container = mCustomScrollBox.children(".mCSB_container"), |
|
667 mCSB_scrollTools = mCustomScrollBox.children(".mCSB_scrollTools"), |
|
668 mCSB_draggerContainer = mCSB_scrollTools.children(".mCSB_draggerContainer"), |
|
669 mCSB_dragger = mCSB_draggerContainer.children(".mCSB_dragger"), |
|
670 contentSpeed = draggerSpeed = options.scrollInertia, |
|
671 scrollBeginning, scrollBeginningOffset, totalScroll, totalScrollOffset; |
|
672 if (!mCSB_container.hasClass("mCS_no_scrollbar")) { |
|
673 $this.data({"mCS_trigger": options.trigger}); |
|
674 if ($this.data("mCS_Init")) { |
|
675 options.callbacks = false; |
|
676 } |
|
677 if (scrollTo || scrollTo === 0) { |
|
678 if (typeof(scrollTo) === "number") { /*if integer, scroll by number of pixels*/ |
|
679 if (options.moveDragger) { /*scroll dragger*/ |
|
680 draggerScrollTo = scrollTo; |
|
681 if ($this.data("horizontalScroll")) { |
|
682 scrollTo = mCSB_dragger.position().left * $this.data("scrollAmount"); |
|
683 } else { |
|
684 scrollTo = mCSB_dragger.position().top * $this.data("scrollAmount"); |
|
685 } |
|
686 draggerSpeed = 0; |
|
687 } else { /*scroll content by default*/ |
|
688 draggerScrollTo = scrollTo / $this.data("scrollAmount"); |
|
689 } |
|
690 } else if (typeof(scrollTo) === "string") { /*if string, scroll by element position*/ |
|
691 var target; |
|
692 if (scrollTo === "top") { /*scroll to top*/ |
|
693 target = 0; |
|
694 } else if (scrollTo === "bottom" && !$this.data("horizontalScroll")) { /*scroll to bottom*/ |
|
695 target = mCSB_container.outerHeight() - mCustomScrollBox.height(); |
|
696 } else if (scrollTo === "left") { /*scroll to left*/ |
|
697 target = 0; |
|
698 } else if (scrollTo === "right" && $this.data("horizontalScroll")) { /*scroll to right*/ |
|
699 target = mCSB_container.outerWidth() - mCustomScrollBox.width(); |
|
700 } else if (scrollTo === "first") { /*scroll to first element position*/ |
|
701 target = $this.find(".mCSB_container").find(":first"); |
|
702 } else if (scrollTo === "last") { /*scroll to last element position*/ |
|
703 target = $this.find(".mCSB_container").find(":last"); |
|
704 } else { /*scroll to element position*/ |
|
705 target = $this.find(scrollTo); |
|
706 } |
|
707 if (target.length === 1) { /*if such unique element exists, scroll to it*/ |
|
708 if ($this.data("horizontalScroll")) { |
|
709 scrollTo = target.position().left; |
|
710 } else { |
|
711 scrollTo = target.position().top; |
|
712 } |
|
713 draggerScrollTo = scrollTo / $this.data("scrollAmount"); |
|
714 } else { |
|
715 draggerScrollTo = scrollTo = target; |
|
716 } |
|
717 } |
|
718 /*scroll to*/ |
|
719 if ($this.data("horizontalScroll")) { |
|
720 if ($this.data("onTotalScrollBack_Offset")) { /*scroll beginning offset*/ |
|
721 scrollBeginningOffset = -$this.data("onTotalScrollBack_Offset"); |
|
722 } |
|
723 if ($this.data("onTotalScroll_Offset")) { /*total scroll offset*/ |
|
724 totalScrollOffset = mCustomScrollBox.width() - mCSB_container.outerWidth() + $this.data("onTotalScroll_Offset"); |
|
725 } |
|
726 if (draggerScrollTo < 0) { /*scroll start position*/ |
|
727 draggerScrollTo = scrollTo = 0; |
|
728 clearInterval($this.data("mCSB_buttonScrollLeft")); |
|
729 if (!scrollBeginningOffset) { |
|
730 scrollBeginning = true; |
|
731 } |
|
732 } else if (draggerScrollTo >= mCSB_draggerContainer.width() - mCSB_dragger.width()) { /*scroll end position*/ |
|
733 draggerScrollTo = mCSB_draggerContainer.width() - mCSB_dragger.width(); |
|
734 scrollTo = mCustomScrollBox.width() - mCSB_container.outerWidth(); |
|
735 clearInterval($this.data("mCSB_buttonScrollRight")); |
|
736 if (!totalScrollOffset) { |
|
737 totalScroll = true; |
|
738 } |
|
739 } else { |
|
740 scrollTo = -scrollTo; |
|
741 } |
|
742 var snapAmount = $this.data("snapAmount"); |
|
743 if (snapAmount) { |
|
744 scrollTo = Math.round(scrollTo / snapAmount) * snapAmount - $this.data("snapOffset"); |
|
745 } |
|
746 /*scrolling animation*/ |
|
747 functions.mTweenAxis.call(this, mCSB_dragger[0], "left", Math.round(draggerScrollTo), draggerSpeed, options.scrollEasing); |
|
748 functions.mTweenAxis.call(this, mCSB_container[0], "left", Math.round(scrollTo), contentSpeed, options.scrollEasing, { |
|
749 onStart: function () { |
|
750 if (options.callbacks && !$this.data("mCS_tweenRunning")) { |
|
751 callbacks("onScrollStart"); |
|
752 } |
|
753 if ($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")) { |
|
754 functions.showScrollbar.call(mCSB_scrollTools); |
|
755 } |
|
756 }, |
|
757 onUpdate: function () { |
|
758 if (options.callbacks) { |
|
759 callbacks("whileScrolling"); |
|
760 } |
|
761 }, |
|
762 onComplete: function () { |
|
763 if (options.callbacks) { |
|
764 callbacks("onScroll"); |
|
765 if (scrollBeginning || (scrollBeginningOffset && mCSB_container.position().left >= scrollBeginningOffset)) { |
|
766 callbacks("onTotalScrollBack"); |
|
767 } |
|
768 if (totalScroll || (totalScrollOffset && mCSB_container.position().left <= totalScrollOffset)) { |
|
769 callbacks("onTotalScroll"); |
|
770 } |
|
771 } |
|
772 mCSB_dragger.data("preventAction", false); |
|
773 $this.data("mCS_tweenRunning", false); |
|
774 if ($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")) { |
|
775 if (!mCustomScrollBox.hasClass("mCS-mouse-over")) { |
|
776 functions.hideScrollbar.call(mCSB_scrollTools); |
|
777 } |
|
778 } |
|
779 } |
|
780 }); |
|
781 } else { |
|
782 if ($this.data("onTotalScrollBack_Offset")) { /*scroll beginning offset*/ |
|
783 scrollBeginningOffset = -$this.data("onTotalScrollBack_Offset"); |
|
784 } |
|
785 if ($this.data("onTotalScroll_Offset")) { /*total scroll offset*/ |
|
786 totalScrollOffset = mCustomScrollBox.height() - mCSB_container.outerHeight() + $this.data("onTotalScroll_Offset"); |
|
787 } |
|
788 if (draggerScrollTo < 0) { /*scroll start position*/ |
|
789 draggerScrollTo = scrollTo = 0; |
|
790 clearInterval($this.data("mCSB_buttonScrollUp")); |
|
791 if (!scrollBeginningOffset) { |
|
792 scrollBeginning = true; |
|
793 } |
|
794 } else if (draggerScrollTo >= mCSB_draggerContainer.height() - mCSB_dragger.height()) { /*scroll end position*/ |
|
795 draggerScrollTo = mCSB_draggerContainer.height() - mCSB_dragger.height(); |
|
796 scrollTo = mCustomScrollBox.height() - mCSB_container.outerHeight(); |
|
797 clearInterval($this.data("mCSB_buttonScrollDown")); |
|
798 if (!totalScrollOffset) { |
|
799 totalScroll = true; |
|
800 } |
|
801 } else { |
|
802 scrollTo = -scrollTo; |
|
803 } |
|
804 var snapAmount = $this.data("snapAmount"); |
|
805 if (snapAmount) { |
|
806 scrollTo = Math.round(scrollTo / snapAmount) * snapAmount - $this.data("snapOffset"); |
|
807 } |
|
808 /*scrolling animation*/ |
|
809 functions.mTweenAxis.call(this, mCSB_dragger[0], "top", Math.round(draggerScrollTo), draggerSpeed, options.scrollEasing); |
|
810 functions.mTweenAxis.call(this, mCSB_container[0], "top", Math.round(scrollTo), contentSpeed, options.scrollEasing, { |
|
811 onStart: function () { |
|
812 if (options.callbacks && !$this.data("mCS_tweenRunning")) { |
|
813 callbacks("onScrollStart"); |
|
814 } |
|
815 if ($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")) { |
|
816 functions.showScrollbar.call(mCSB_scrollTools); |
|
817 } |
|
818 }, |
|
819 onUpdate: function () { |
|
820 if (options.callbacks) { |
|
821 callbacks("whileScrolling"); |
|
822 } |
|
823 }, |
|
824 onComplete: function () { |
|
825 if (options.callbacks) { |
|
826 callbacks("onScroll"); |
|
827 if (scrollBeginning || (scrollBeginningOffset && mCSB_container.position().top >= scrollBeginningOffset)) { |
|
828 callbacks("onTotalScrollBack"); |
|
829 } |
|
830 if (totalScroll || (totalScrollOffset && mCSB_container.position().top <= totalScrollOffset)) { |
|
831 callbacks("onTotalScroll"); |
|
832 } |
|
833 } |
|
834 mCSB_dragger.data("preventAction", false); |
|
835 $this.data("mCS_tweenRunning", false); |
|
836 if ($this.data("autoHideScrollbar") && !$this.data("alwaysShowScrollbar")) { |
|
837 if (!mCustomScrollBox.hasClass("mCS-mouse-over")) { |
|
838 functions.hideScrollbar.call(mCSB_scrollTools); |
|
839 } |
|
840 } |
|
841 } |
|
842 }); |
|
843 } |
|
844 if ($this.data("mCS_Init")) { |
|
845 $this.data({"mCS_Init": false}); |
|
846 } |
|
847 } |
|
848 } |
|
849 /*callbacks*/ |
|
850 function callbacks(cb) { |
|
851 if ($this.data("mCustomScrollbarIndex")) { |
|
852 this.mcs = { |
|
853 top: mCSB_container.position().top, left: mCSB_container.position().left, |
|
854 draggerTop: mCSB_dragger.position().top, draggerLeft: mCSB_dragger.position().left, |
|
855 topPct: Math.round((100 * Math.abs(mCSB_container.position().top)) / Math.abs(mCSB_container.outerHeight() - mCustomScrollBox.height())), |
|
856 leftPct: Math.round((100 * Math.abs(mCSB_container.position().left)) / Math.abs(mCSB_container.outerWidth() - mCustomScrollBox.width())) |
|
857 }; |
|
858 switch (cb) { |
|
859 /*start scrolling callback*/ |
|
860 case "onScrollStart": |
|
861 $this.data("mCS_tweenRunning", true).data("onScrollStart_Callback").call($this, this.mcs); |
|
862 break; |
|
863 case "whileScrolling": |
|
864 $this.data("whileScrolling_Callback").call($this, this.mcs); |
|
865 break; |
|
866 case "onScroll": |
|
867 $this.data("onScroll_Callback").call($this, this.mcs); |
|
868 break; |
|
869 case "onTotalScrollBack": |
|
870 $this.data("onTotalScrollBack_Callback").call($this, this.mcs); |
|
871 break; |
|
872 case "onTotalScroll": |
|
873 $this.data("onTotalScroll_Callback").call($this, this.mcs); |
|
874 break; |
|
875 } |
|
876 } |
|
877 } |
|
878 }, |
|
879 stop: function () { |
|
880 var $this = $(this), |
|
881 mCSB_container = $this.children().children(".mCSB_container"), |
|
882 mCSB_dragger = $this.children().children().children().children(".mCSB_dragger"); |
|
883 functions.mTweenAxisStop.call(this, mCSB_container[0]); |
|
884 functions.mTweenAxisStop.call(this, mCSB_dragger[0]); |
|
885 }, |
|
886 disable: function (resetScroll) { |
|
887 var $this = $(this), |
|
888 mCustomScrollBox = $this.children(".mCustomScrollBox"), |
|
889 mCSB_container = mCustomScrollBox.children(".mCSB_container"), |
|
890 mCSB_scrollTools = mCustomScrollBox.children(".mCSB_scrollTools"), |
|
891 mCSB_dragger = mCSB_scrollTools.children().children(".mCSB_dragger"); |
|
892 mCustomScrollBox.unbind("mousewheel focusin mouseenter mouseleave touchend"); |
|
893 mCSB_container.unbind("touchstart touchmove") |
|
894 if (resetScroll) { |
|
895 if ($this.data("horizontalScroll")) { |
|
896 mCSB_dragger.add(mCSB_container).css("left", 0); |
|
897 } else { |
|
898 mCSB_dragger.add(mCSB_container).css("top", 0); |
|
899 } |
|
900 } |
|
901 mCSB_scrollTools.css("display", "none"); |
|
902 mCSB_container.addClass("mCS_no_scrollbar"); |
|
903 $this.data({"bindEvent_mousewheel": false, "bindEvent_focusin": false, "bindEvent_content_touch": false, "bindEvent_autoHideScrollbar": false}).addClass("mCS_disabled"); |
|
904 }, |
|
905 destroy: function () { |
|
906 var $this = $(this); |
|
907 $this.removeClass("mCustomScrollbar _mCS_" + $this.data("mCustomScrollbarIndex")).addClass("mCS_destroyed").children().children(".mCSB_container").unwrap().children().unwrap().siblings(".mCSB_scrollTools").remove(); |
|
908 $(document).unbind("mousemove." + $this.data("mCustomScrollbarIndex") + " mouseup." + $this.data("mCustomScrollbarIndex") + " MSPointerMove." + $this.data("mCustomScrollbarIndex") + " MSPointerUp." + $this.data("mCustomScrollbarIndex")); |
|
909 $(window).unbind("resize." + $this.data("mCustomScrollbarIndex")); |
|
910 } |
|
911 }, |
|
912 functions = { |
|
913 /*hide/show scrollbar*/ |
|
914 showScrollbar: function () { |
|
915 this.stop().animate({opacity: 1}, "fast"); |
|
916 }, |
|
917 hideScrollbar: function () { |
|
918 this.stop().animate({opacity: 0}, "fast"); |
|
919 }, |
|
920 /*js animation tween*/ |
|
921 mTweenAxis: function (el, prop, to, duration, easing, callbacks) { |
|
922 var callbacks = callbacks || {}, |
|
923 onStart = callbacks.onStart || function () { |
|
924 }, onUpdate = callbacks.onUpdate || function () { |
|
925 }, onComplete = callbacks.onComplete || function () { |
|
926 }; |
|
927 var startTime = _getTime(), _delay, progress = 0, from = el.offsetTop, elStyle = el.style; |
|
928 if (prop === "left") { |
|
929 from = el.offsetLeft; |
|
930 } |
|
931 var diff = to - from; |
|
932 _cancelTween(); |
|
933 _startTween(); |
|
934 function _getTime() { |
|
935 if (window.performance && window.performance.now) { |
|
936 return window.performance.now(); |
|
937 } else { |
|
938 if (window.performance && window.performance.webkitNow) { |
|
939 return window.performance.webkitNow(); |
|
940 } else { |
|
941 if (Date.now) { |
|
942 return Date.now(); |
|
943 } else { |
|
944 return new Date().getTime(); |
|
945 } |
|
946 } |
|
947 } |
|
948 } |
|
949 |
|
950 function _step() { |
|
951 if (!progress) { |
|
952 onStart.call(); |
|
953 } |
|
954 progress = _getTime() - startTime; |
|
955 _tween(); |
|
956 if (progress >= el._time) { |
|
957 el._time = (progress > el._time) ? progress + _delay - (progress - el._time) : progress + _delay - 1; |
|
958 if (el._time < progress + 1) { |
|
959 el._time = progress + 1; |
|
960 } |
|
961 } |
|
962 if (el._time < duration) { |
|
963 el._id = _request(_step); |
|
964 } else { |
|
965 onComplete.call(); |
|
966 } |
|
967 } |
|
968 |
|
969 function _tween() { |
|
970 if (duration > 0) { |
|
971 el.currVal = _ease(el._time, from, diff, duration, easing); |
|
972 elStyle[prop] = Math.round(el.currVal) + "px"; |
|
973 } else { |
|
974 elStyle[prop] = to + "px"; |
|
975 } |
|
976 onUpdate.call(); |
|
977 } |
|
978 |
|
979 function _startTween() { |
|
980 _delay = 1000 / 60; |
|
981 el._time = progress + _delay; |
|
982 _request = (!window.requestAnimationFrame) ? function (f) { |
|
983 _tween(); |
|
984 return setTimeout(f, 0.01); |
|
985 } : window.requestAnimationFrame; |
|
986 el._id = _request(_step); |
|
987 } |
|
988 |
|
989 function _cancelTween() { |
|
990 if (el._id == null) { |
|
991 return; |
|
992 } |
|
993 if (!window.requestAnimationFrame) { |
|
994 clearTimeout(el._id); |
|
995 } else { |
|
996 window.cancelAnimationFrame(el._id); |
|
997 } |
|
998 el._id = null; |
|
999 } |
|
1000 |
|
1001 function _ease(t, b, c, d, type) { |
|
1002 switch (type) { |
|
1003 case "linear": |
|
1004 return c * t / d + b; |
|
1005 break; |
|
1006 case "easeOutQuad": |
|
1007 t /= d; |
|
1008 return -c * t * (t - 2) + b; |
|
1009 break; |
|
1010 case "easeInOutQuad": |
|
1011 t /= d / 2; |
|
1012 if (t < 1) return c / 2 * t * t + b; |
|
1013 t--; |
|
1014 return -c / 2 * (t * (t - 2) - 1) + b; |
|
1015 break; |
|
1016 case "easeOutCubic": |
|
1017 t /= d; |
|
1018 t--; |
|
1019 return c * (t * t * t + 1) + b; |
|
1020 break; |
|
1021 case "easeOutQuart": |
|
1022 t /= d; |
|
1023 t--; |
|
1024 return -c * (t * t * t * t - 1) + b; |
|
1025 break; |
|
1026 case "easeOutQuint": |
|
1027 t /= d; |
|
1028 t--; |
|
1029 return c * (t * t * t * t * t + 1) + b; |
|
1030 break; |
|
1031 case "easeOutCirc": |
|
1032 t /= d; |
|
1033 t--; |
|
1034 return c * Math.sqrt(1 - t * t) + b; |
|
1035 break; |
|
1036 case "easeOutSine": |
|
1037 return c * Math.sin(t / d * (Math.PI / 2)) + b; |
|
1038 break; |
|
1039 case "easeOutExpo": |
|
1040 return c * ( -Math.pow(2, -10 * t / d) + 1 ) + b; |
|
1041 break; |
|
1042 case "mcsEaseOut": |
|
1043 var ts = (t /= d) * t, tc = ts * t; |
|
1044 return b + c * (0.499999999999997 * tc * ts + -2.5 * ts * ts + 5.5 * tc + -6.5 * ts + 4 * t); |
|
1045 break; |
|
1046 case "draggerRailEase": |
|
1047 t /= d / 2; |
|
1048 if (t < 1) return c / 2 * t * t * t + b; |
|
1049 t -= 2; |
|
1050 return c / 2 * (t * t * t + 2) + b; |
|
1051 break; |
|
1052 } |
|
1053 } |
|
1054 }, |
|
1055 /*stop js animation tweens*/ |
|
1056 mTweenAxisStop: function (el) { |
|
1057 if (el._id == null) { |
|
1058 return; |
|
1059 } |
|
1060 if (!window.requestAnimationFrame) { |
|
1061 clearTimeout(el._id); |
|
1062 } else { |
|
1063 window.cancelAnimationFrame(el._id); |
|
1064 } |
|
1065 el._id = null; |
|
1066 }, |
|
1067 /*detect requestAnimationFrame and polyfill*/ |
|
1068 rafPolyfill: function () { |
|
1069 var pfx = ["ms", "moz", "webkit", "o"], i = pfx.length; |
|
1070 while (--i > -1 && !window.requestAnimationFrame) { |
|
1071 window.requestAnimationFrame = window[pfx[i] + "RequestAnimationFrame"]; |
|
1072 window.cancelAnimationFrame = window[pfx[i] + "CancelAnimationFrame"] || window[pfx[i] + "CancelRequestAnimationFrame"]; |
|
1073 } |
|
1074 } |
|
1075 } |
|
1076 /*detect features*/ |
|
1077 functions.rafPolyfill.call(); |
|
1078 /*requestAnimationFrame*/ |
|
1079 $.support.touch = !!('ontouchstart' in window); |
|
1080 /*touch*/ |
|
1081 $.support.pointer = window.navigator.pointerEnabled; |
|
1082 /*pointer support*/ |
|
1083 $.support.msPointer = window.navigator.msPointerEnabled; |
|
1084 /*MSPointer support*/ |
|
1085 /*plugin dependencies*/ |
|
1086 var _dlp = ("https:" == document.location.protocol) ? "https:" : "http:"; |
|
1087 $.event.special.mousewheel || document.write('<script src="' + _dlp + '//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.0.6/jquery.mousewheel.min.js"><\/script>'); |
|
1088 /*plugin fn*/ |
|
1089 $.fn.mCustomScrollbar = function (method) { |
|
1090 if (methods[method]) { |
|
1091 return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); |
|
1092 } else if (typeof method === "object" || !method) { |
|
1093 return methods.init.apply(this, arguments); |
|
1094 } else { |
|
1095 $.error("Method " + method + " does not exist"); |
|
1096 } |
|
1097 }; |
|
1098 })(jQuery); |