Administrator
2022-09-14 58d006e05dcf2a20d0ec5367dd03d66a61db6849
提交 | 用户 | 时间
58d006 1 /*! Copyright (c) 2011 Piotr Rochala (http://rocha.la)
A 2  * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
3  * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
4  *
5  * Version: 1.3.7
6  *
7  */
8 (function($) {
9
10   $.fn.extend({
11     slimScroll: function(options) {
12
13       var defaults = {
14
15         // width in pixels of the visible scroll area
16         width : 'auto',
17
18         // height in pixels of the visible scroll area
19         height : '250px',
20
21         // width in pixels of the scrollbar and rail
22         size : '7px',
23
24         // scrollbar color, accepts any hex/color value
25         color: '#000',
26
27         // scrollbar position - left/right
28         position : 'right',
29
30         // distance in pixels between the side edge and the scrollbar
31         distance : '1px',
32
33         // default scroll position on load - top / bottom / $('selector')
34         start : 'top',
35
36         // sets scrollbar opacity
37         opacity : .4,
38
39         // enables always-on mode for the scrollbar
40         alwaysVisible : false,
41
42         // check if we should hide the scrollbar when user is hovering over
43         disableFadeOut : false,
44
45         // sets visibility of the rail
46         railVisible : false,
47
48         // sets rail color
49         railColor : '#333',
50
51         // sets rail opacity
52         railOpacity : .2,
53
54         // whether  we should use jQuery UI Draggable to enable bar dragging
55         railDraggable : true,
56
57         // defautlt CSS class of the slimscroll rail
58         railClass : 'slimScrollRail',
59
60         // defautlt CSS class of the slimscroll bar
61         barClass : 'slimScrollBar',
62
63         // defautlt CSS class of the slimscroll wrapper
64         wrapperClass : 'slimScrollDiv',
65
66         // check if mousewheel should scroll the window if we reach top/bottom
67         allowPageScroll : false,
68
69         // scroll amount applied to each mouse wheel step
70         wheelStep : 20,
71
72         // scroll amount applied when user is using gestures
73         touchScrollStep : 200,
74
75         // sets border radius
76         borderRadius: '7px',
77
78         // sets border radius of the rail
79         railBorderRadius : '7px'
80       };
81
82       var o = $.extend(defaults, options);
83
84       // do it for every element that matches selector
85       this.each(function(){
86
87       var isOverPanel, isOverBar, isDragg, queueHide, touchDif,
88         barHeight, percentScroll, lastScroll,
89         divS = '<div></div>',
90         minBarHeight = 30,
91         releaseScroll = false;
92
93         // used in event handlers and for better minification
94         var me = $(this);
95
96         // ensure we are not binding it again
97         if (me.parent().hasClass(o.wrapperClass))
98         {
99             // start from last bar position
100             var offset = me.scrollTop();
101
102             // find bar and rail
103             bar = me.siblings('.' + o.barClass);
104             rail = me.siblings('.' + o.railClass);
105
106             getBarHeight();
107
108             // check if we should scroll existing instance
109             if ($.isPlainObject(options))
110             {
111               // Pass height: auto to an existing slimscroll object to force a resize after contents have changed
112               if ( 'height' in options && options.height == 'auto' ) {
113                 me.parent().css('height', 'auto');
114                 me.css('height', 'auto');
115                 var height = me.parent().parent().height();
116                 me.parent().css('height', height);
117                 me.css('height', height);
118               } else if ('height' in options) {
119                 var h = options.height;
120                 me.parent().css('height', h);
121                 me.css('height', h);
122               }
123
124               if ('scrollTo' in options)
125               {
126                 // jump to a static point
127                 offset = parseInt(o.scrollTo);
128               }
129               else if ('scrollBy' in options)
130               {
131                 // jump by value pixels
132                 offset += parseInt(o.scrollBy);
133               }
134               else if ('destroy' in options)
135               {
136                 // remove slimscroll elements
137                 bar.remove();
138                 rail.remove();
139                 me.unwrap();
140                 return;
141               }
142
143               // scroll content by the given offset
144               scrollContent(offset, false, true);
145             }
146
147             return;
148         }
149         else if ($.isPlainObject(options))
150         {
151             if ('destroy' in options)
152             {
153                 return;
154             }
155         }
156
157         // optionally set height to the parent's height
158         o.height = (o.height == 'auto') ? me.parent().height() : o.height;
159
160         // wrap content
161         var wrapper = $(divS)
162           .addClass(o.wrapperClass)
163           .css({
164             position: 'relative',
165             overflow: 'hidden',
166             width: o.width,
167             height: o.height
168           });
169
170         // update style for the div
171         me.css({
172           overflow: 'hidden',
173           width: o.width,
174           height: o.height
175         });
176
177         // create scrollbar rail
178         var rail = $(divS)
179           .addClass(o.railClass)
180           .css({
181             width: o.size,
182             height: '100%',
183             position: 'absolute',
184             top: 0,
185             display: (o.alwaysVisible && o.railVisible) ? 'block' : 'none',
186             'border-radius': o.railBorderRadius,
187             background: o.railColor,
188             opacity: o.railOpacity,
189             zIndex: 90
190           });
191
192         // create scrollbar
193         var bar = $(divS)
194           .addClass(o.barClass)
195           .css({
196             background: o.color,
197             width: o.size,
198             position: 'absolute',
199             top: 0,
200             opacity: o.opacity,
201             display: o.alwaysVisible ? 'block' : 'none',
202             'border-radius' : o.borderRadius,
203             BorderRadius: o.borderRadius,
204             MozBorderRadius: o.borderRadius,
205             WebkitBorderRadius: o.borderRadius,
206             zIndex: 99
207           });
208
209         // set position
210         var posCss = (o.position == 'right') ? { right: o.distance } : { left: o.distance };
211         rail.css(posCss);
212         bar.css(posCss);
213
214         // wrap it
215         me.wrap(wrapper);
216
217         // append to parent div
218         me.parent().append(bar);
219         me.parent().append(rail);
220
221         // make it draggable and no longer dependent on the jqueryUI
222         if (o.railDraggable){
223           bar.bind("mousedown", function(e) {
224             var $doc = $(document);
225             isDragg = true;
226             t = parseFloat(bar.css('top'));
227             pageY = e.pageY;
228
229             $doc.bind("mousemove.slimscroll", function(e){
230               currTop = t + e.pageY - pageY;
231               bar.css('top', currTop);
232               scrollContent(0, bar.position().top, false);// scroll content
233             });
234
235             $doc.bind("mouseup.slimscroll", function(e) {
236               isDragg = false;hideBar();
237               $doc.unbind('.slimscroll');
238             });
239             return false;
240           }).bind("selectstart.slimscroll", function(e){
241             e.stopPropagation();
242             e.preventDefault();
243             return false;
244           });
245         }
246
247         // on rail over
248         rail.hover(function(){
249           showBar();
250         }, function(){
251           hideBar();
252         });
253
254         // on bar over
255         bar.hover(function(){
256           isOverBar = true;
257         }, function(){
258           isOverBar = false;
259         });
260
261         // show on parent mouseover
262         me.hover(function(){
263           isOverPanel = true;
264           showBar();
265           hideBar();
266         }, function(){
267           isOverPanel = false;
268           hideBar();
269         });
270
271         // support for mobile
272         me.bind('touchstart', function(e,b){
273           if (e.originalEvent.touches.length)
274           {
275             // record where touch started
276             touchDif = e.originalEvent.touches[0].pageY;
277           }
278         });
279
280         me.bind('touchmove', function(e){
281           // prevent scrolling the page if necessary
282           if(!releaseScroll)
283           {
284                 e.originalEvent.preventDefault();
285               }
286           if (e.originalEvent.touches.length)
287           {
288             // see how far user swiped
289             var diff = (touchDif - e.originalEvent.touches[0].pageY) / o.touchScrollStep;
290             // scroll content
291             scrollContent(diff, true);
292             touchDif = e.originalEvent.touches[0].pageY;
293           }
294         });
295
296         // set up initial height
297         getBarHeight();
298
299         // check start position
300         if (o.start === 'bottom')
301         {
302           // scroll content to bottom
303           bar.css({ top: me.outerHeight() - bar.outerHeight() });
304           scrollContent(0, true);
305         }
306         else if (o.start !== 'top')
307         {
308           // assume jQuery selector
309           scrollContent($(o.start).position().top, null, true);
310
311           // make sure bar stays hidden
312           if (!o.alwaysVisible) { bar.hide(); }
313         }
314
315         // attach scroll events
316         attachWheel(this);
317
318         function _onWheel(e)
319         {
320           // use mouse wheel only when mouse is over
321           if (!isOverPanel) { return; }
322
323           var e = e || window.event;
324
325           var delta = 0;
326           if (e.wheelDelta) { delta = -e.wheelDelta/120; }
327           if (e.detail) { delta = e.detail / 3; }
328
329           var target = e.target || e.srcTarget || e.srcElement;
330           if ($(target).closest('.' + o.wrapperClass).is(me.parent())) {
331             // scroll content
332             scrollContent(delta, true);
333           }
334
335           // stop window scroll
336           if (e.preventDefault && !releaseScroll) { e.preventDefault(); }
337           if (!releaseScroll) { e.returnValue = false; }
338         }
339
340         function scrollContent(y, isWheel, isJump)
341         {
342           releaseScroll = false;
343           var delta = y;
344           var maxTop = me.outerHeight() - bar.outerHeight();
345
346           if (isWheel)
347           {
348             // move bar with mouse wheel
349             delta = parseInt(bar.css('top')) + y * parseInt(o.wheelStep) / 100 * bar.outerHeight();
350
351             // move bar, make sure it doesn't go out
352             delta = Math.min(Math.max(delta, 0), maxTop);
353
354             // if scrolling down, make sure a fractional change to the
355             // scroll position isn't rounded away when the scrollbar's CSS is set
356             // this flooring of delta would happened automatically when
357             // bar.css is set below, but we floor here for clarity
358             delta = (y > 0) ? Math.ceil(delta) : Math.floor(delta);
359
360             // scroll the scrollbar
361             bar.css({ top: delta + 'px' });
362           }
363
364           // calculate actual scroll amount
365           percentScroll = parseInt(bar.css('top')) / (me.outerHeight() - bar.outerHeight());
366           delta = percentScroll * (me[0].scrollHeight - me.outerHeight());
367
368           if (isJump)
369           {
370             delta = y;
371             var offsetTop = delta / me[0].scrollHeight * me.outerHeight();
372             offsetTop = Math.min(Math.max(offsetTop, 0), maxTop);
373             bar.css({ top: offsetTop + 'px' });
374           }
375
376           // scroll content
377           me.scrollTop(delta);
378
379           // fire scrolling event
380           me.trigger('slimscrolling', ~~delta);
381
382           // ensure bar is visible
383           showBar();
384
385           // trigger hide when scroll is stopped
386           hideBar();
387         }
388
389         function attachWheel(target)
390         {
391           if (window.addEventListener)
392           {
393             target.addEventListener('DOMMouseScroll', _onWheel, false );
394             target.addEventListener('mousewheel', _onWheel, false );
395           }
396           else
397           {
398             document.attachEvent("onmousewheel", _onWheel)
399           }
400         }
401
402         function getBarHeight()
403         {
404           // calculate scrollbar height and make sure it is not too small
405           barHeight = Math.max((me.outerHeight() / me[0].scrollHeight) * me.outerHeight(), minBarHeight);
406           bar.css({ height: barHeight + 'px' });
407
408           // hide scrollbar if content is not long enough
409           var display = barHeight == me.outerHeight() ? 'none' : 'block';
410           bar.css({ display: display });
411         }
412
413         function showBar()
414         {
415           // recalculate bar height
416           getBarHeight();
417           clearTimeout(queueHide);
418
419           // when bar reached top or bottom
420           if (percentScroll == ~~percentScroll)
421           {
422             //release wheel
423             releaseScroll = o.allowPageScroll;
424
425             // publish approporiate event
426             if (lastScroll != percentScroll)
427             {
428                 var msg = (~~percentScroll == 0) ? 'top' : 'bottom';
429                 me.trigger('slimscroll', msg);
430             }
431           }
432           else
433           {
434             releaseScroll = false;
435           }
436           lastScroll = percentScroll;
437
438           // show only when required
439           if(barHeight >= me.outerHeight()) {
440             //allow window scroll
441             releaseScroll = true;
442             return;
443           }
444           bar.stop(true,true).fadeIn('fast');
445           if (o.railVisible) { rail.stop(true,true).fadeIn('fast'); }
446         }
447
448         function hideBar()
449         {
450           // only hide when options allow it
451           if (!o.alwaysVisible)
452           {
453             queueHide = setTimeout(function(){
454               if (!(o.disableFadeOut && isOverPanel) && !isOverBar && !isDragg)
455               {
456                 bar.fadeOut('slow');
457                 rail.fadeOut('slow');
458               }
459             }, 1000);
460           }
461         }
462
463       });
464
465       // maintain chainability
466       return this;
467     }
468   });
469
470   $.fn.extend({
471     slimscroll: $.fn.slimScroll
472   });
473
474 })(jQuery);