PageSourceSearch

https://register.deca.ca/v3/global/vendor/asscrollable/jquery.asScrollable.all.js

js deca.ca collected 2026-10-01 15:46:16 UTC 58,707 bytes, 1,811 lines download raw bytes

1/*! jQuery asScrollable - v0.3.1 - 2015-06-15
2* https://github.com/amazingSurge/jquery-asScrollable
3* Copyright (c) 2015 amazingSurge; Licensed GPL */
4(function(window, document, $, undefined) {
5    "use strict";
6
7    var pluginName = 'asScrollbar';
8
9    /**
10     * Animation Frame
11     **/
12    if (!Date.now) {
13        Date.now = function() {
14            return new Date().getTime();
15        };
16    }
17
18    function getTime() {
19        if (typeof window.performance !== 'undefined' && window.performance.now) {
20            return window.performance.now();
21        } else {
22            return Date.now();
23        }
24    }
25
26    var vendors = ['webkit', 'moz'];
27    for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) {
28        var vp = vendors[i];
29        window.requestAnimationFrame = window[vp + 'RequestAnimationFrame'];
30        window.cancelAnimationFrame = (window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame']);
31    }
32    if (/iP(ad|hone|od).*OS (6|7|8)/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) {
33        var lastTime = 0;
34        window.requestAnimationFrame = function(callback) {
35            var now = getTime();
36            var nextTime = Math.max(lastTime + 16, now);
37            return setTimeout(function() {
38                    callback(lastTime = nextTime);
39                },
40                nextTime - now);
41        };
42        window.cancelAnimationFrame = clearTimeout;
43    }
44
45    /**
46     * Helper functions
47     **/
48    function isPercentage(n) {
49        return typeof n === 'string' && n.indexOf('%') != -1;
50    }
51
52    function convertPercentageToFloat(n) {
53        return parseFloat(n.slice(0, -1) / 100, 10);
54    }
55
56    function convertMatrixToArray(value) {
57        if (value && (value.substr(0, 6) == "matrix")) {
58            return value.replace(/^.*\((.*)\)$/g, "$1").replace(/px/g, '').split(/, +/);
59        }
60        return false;
61    }
62
63    /**
64     * Plugin constructor
65     **/
66    var Plugin = $[pluginName] = function(options, bar) {
67        this.$bar = $(bar);
68
69        options = this.options = $.extend({}, Plugin.defaults, options || {}, this.$bar.data('options') || {});
70
71        bar.direction = this.options.direction;
72
73        this.classes = {
74            directionClass: options.namespace + '-' + options.direction,
75            barClass: options.barClass ? options.barClass : options.namespace,
76            handleClass: options.handleClass ? options.handleClass : options.namespace + '-handle'
77        };
78
79        if (this.options.direction === 'vertical') {
80            this.attributes = {
81                axis: 'Y',
82                position: 'top',
83                length: 'height',
84                clientLength: 'clientHeight'
85            };
86        } else if (this.options.direction === 'horizontal') {
87            this.attributes = {
88                axis: 'X',
89                position: 'left',
90                length: 'width',
91                clientLength: 'clientWidth'
92            };
93        }
94
95        // Current state information.
96        this._states = {};
97
98        // Current state information for the drag operation.
99        this._drag = {
100            time: null,
101            pointer: null
102        };
103
104        // Current timeout
105        this._frameId = null;
106
107        // Current handle position
108        this.handlePosition = 0;
109
110        this.easing = Plugin.easing[this.options.easing] || Plugin.easing.ease;
111
112        this.init();
113    };
114
115    Plugin.defaults = {
116        namespace: 'asScrollbar',
117
118        skin: null,
119        handleSelector: null,
120        handleTemplate: '<div class="{{handle}}"></div>',
121
122        barClass: null,
123        handleClass: null,
124
125        disabledClass: 'is-disabled',
126        draggingClass: 'is-dragging',
127        hoveringClass: 'is-hovering',
128
129        direction: 'vertical',
130
131        barLength: null,
132        handleLength: null,
133
134        minHandleLength: 30,
135        maxHandleLength: null,
136
137        mouseDrag: true,
138        touchDrag: true,
139        pointerDrag: true,
140        clickMove: true,
141        clickMoveStep: 0.3, // 0 - 1
142        mousewheel: true,
143        mousewheelSpeed: 50,
144
145        keyboard: true,
146
147        useCssTransforms3d: true,
148        useCssTransforms: true,
149        useCssTransitions: true,
150
151        duration: '500',
152        easing: 'ease' // linear, ease-in, ease-out, ease-in-out
153    };
154
155    /**
156     * Css features detect
157     **/
158    var support = {};
159    Plugin.support = support;
160    (function(support) {
161        /**
162         * Borrowed from Owl carousel
163         **/
164        var style = $('<support>').get(0).style,
165            prefixes = ['webkit', 'Moz', 'O', 'ms'],
166            events = {
167                transition: {
168                    end: {
169                        WebkitTransition: 'webkitTransitionEnd',
170                        MozTransition: 'transitionend',
171                        OTransition: 'oTransitionEnd',
172                        transition: 'transitionend'
173                    }
174                },
175                animation: {
176                    end: {
177                        WebkitAnimation: 'webkitAnimationEnd',
178                        MozAnimation: 'animationend',
179                        OAnimation: 'oAnimationEnd',
180                        animation: 'animationend'
181                    }
182                }
183            },
184            tests = {
185                csstransforms: function() {
186                    return !!test('transform');
187                },
188                csstransforms3d: function() {
189                    return !!test('perspective');
190                },
191                csstransitions: function() {
192                    return !!test('transition');
193                },
194                cssanimations: function() {
195                    return !!test('animation');
196                }
197            };
198
199        function test(property, prefixed) {
200            var result = false,
201                upper = property.charAt(0).toUpperCase() + property.slice(1);
202
203            if (style[property] !== undefined) {
204                result = property;
205            }
206            if (!result) {
207                $.each(prefixes, function(i, prefix) {
208                    if (style[prefix + upper] !== undefined) {
209                        result = '-' + prefix.toLowerCase() + '-' + upper;
210                        return false;
211                    }
212                });
213            }
214
215            if (prefixed) {
216                return result;
217            }
218            if (result) {
219                return true;
220            } else {
221                return false;
222            }
223        }
224
225        function prefixed(property) {
226            return test(property, true);
227        }
228
229        if (tests.csstransitions()) {
230            /* jshint -W053 */
231            support.transition = new String(prefixed('transition'))
232            support.transition.end = events.transition.end[support.transition];
233        }
234
235        if (tests.cssanimations()) {
236            /* jshint -W053 */
237            support.animation = new String(prefixed('animation'))
238            support.animation.end = events.animation.end[support.animation];
239        }
240
241        if (tests.csstransforms()) {
242            /* jshint -W053 */
243            support.transform = new String(prefixed('transform'));
244            support.transform3d = tests.csstransforms3d();
245        }
246
247        if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
248            support.touch = true;
249        } else {
250            support.touch = false;
251        }
252
253        if (window.PointerEvent || window.MSPointerEvent) {
254            support.pointer = true;
255        } else {
256            support.pointer = false;
257        }
258
259        support.prefixPointerEvent = function(pointerEvent) {
260            return window.MSPointerEvent ?
261                'MSPointer' + pointerEvent.charAt(9).toUpperCase() + pointerEvent.substr(10) :
262                pointerEvent;
263        }
264    })(support);
265
266    var easingBezier = function(mX1, mY1, mX2, mY2) {
267        function a(aA1, aA2) {
268            return 1.0 - 3.0 * aA2 + 3.0 * aA1;
269        }
270
271        function b(aA1, aA2) {
272            return 3.0 * aA2 - 6.0 * aA1;
273        }
274
275        function c(aA1) {
276            return 3.0 * aA1;
277        }
278
279        // Returns x(t) given t, x1, and x2, or y(t) given t, y1, and y2.
280        function calcBezier(aT, aA1, aA2) {
281            return ((a(aA1, aA2) * aT + b(aA1, aA2)) * aT + c(aA1)) * aT;
282        }
283
284        // Returns dx/dt given t, x1, and x2, or dy/dt given t, y1, and y2.
285        function getSlope(aT, aA1, aA2) {
286            return 3.0 * a(aA1, aA2) * aT * aT + 2.0 * b(aA1, aA2) * aT + c(aA1);
287        }
288
289        function getTForX(aX) {
290            // Newton raphson iteration
291            var aGuessT = aX;
292            for (var i = 0; i < 4; ++i) {
293                var currentSlope = getSlope(aGuessT, mX1, mX2);
294                if (currentSlope === 0.0) return aGuessT;
295                var currentX = calcBezier(aGuessT, mX1, mX2) - aX;
296                aGuessT -= currentX / currentSlope;
297            }
298            return aGuessT;
299        }
300
301        if (mX1 === mY1 && mX2 === mY2) {
302            return {
303                css: 'linear',
304                fn: function(aX) {
305                    return aX;
306                }
307            };
308        } else {
309            return {
310                css: 'cubic-bezier(' + mX1 + ',' + mY1 + ',' + mX2 + ',' + mY2 + ')',
311                fn: function(aX) {
312                    return calcBezier(getTForX(aX), mY1, mY2);
313                }
314            }
315        }
316    };
317
318    $.extend(Plugin.easing = {}, {
319        'ease': easingBezier(0.25, 0.1, 0.25, 1.0),
320        'linear': easingBezier(0.00, 0.0, 1.00, 1.0),
321        'ease-in': easingBezier(0.42, 0.0, 1.00, 1.0),
322        'ease-out': easingBezier(0.00, 0.0, 0.58, 1.0),
323        'ease-in-out': easingBezier(0.42, 0.0, 0.58, 1.0)
324    });
325
326    Plugin.prototype = {
327        constructor: Plugin,
328        init: function() {
329            var options = this.options;
330
331            this.$handle = this.$bar.find(this.options.handleSelector);
332            if (this.$handle.length === 0) {
333                this.$handle = $(options.handleTemplate.replace(/\{\{handle\}\}/g, this.classes.handleClass)).appendTo(this.$bar);
334            } else {
335                this.$handle.addClass(this.classes.handleClass);
336            }
337
338            this.$bar.addClass(this.classes.barClass).addClass(this.classes.directionClass).attr('draggable', false);
339
340            if (options.skin) {
341                this.$bar.addClass(options.skin);
342            }
343            if (options.barLength !== null) {
344                this.setBarLength(options.barLength);
345            }
346
347            if (options.handleLength !== null) {
348                this.setHandleLength(options.handleLength);
349            }
350
351            this.updateLength();
352
353            this.bindEvents();
354        },
355
356        trigger: function(eventType) {
357            var method_arguments = Array.prototype.slice.call(arguments, 1),
358                data = [this].concat(method_arguments);
359
360            // event
361            this.$bar.trigger(pluginName + '::' + eventType, data);
362
363            // callback
364            eventType = eventType.replace(/\b\w+\b/g, function(word) {
365                return word.substring(0, 1).toUpperCase() + word.substring(1);
366            });
367            var onFunction = 'on' + eventType;
368
369            if (typeof this.options[onFunction] === 'function') {
370                this.options[onFunction].apply(this, method_arguments);
371            }
372        },
373
374        /**
375         * Checks whether the carousel is in a specific state or not.
376         */
377        is: function(state) {
378            return this._states[state] && this._states[state] > 0;
379        },
380
381        /**
382         * Enters a state.
383         */
384        enter: function(state) {
385            if (this._states[state] === undefined) {
386                this._states[state] = 0;
387            }
388
389            this._states[state] ++;
390        },
391
392        /**
393         * Leaves a state.
394         */
395        leave: function(state) {
396            this._states[state] --;
397        },
398
399        eventName: function(events) {
400            if (typeof events !== 'string' || events === '') {
401                return '.' + this.options.namespace;
402            }
403            events = events.split(' ');
404
405            var length = events.length;
406            for (var i = 0; i < length; i++) {
407                events[i] = events[i] + '.' + this.options.namespace;
408            }
409            return events.join(' ');
410        },
411
412        bindEvents: function() {
413            var self = this;
414
415            if (this.options.mouseDrag) {
416                this.$handle.on(this.eventName('mousedown'), $.proxy(this.onDragStart, this));
417                this.$handle.on(this.eventName('dragstart selectstart'), function() {
418                    return false
419                });
420            }
421
422            if (this.options.touchDrag && support.touch) {
423                this.$handle.on(this.eventName('touchstart'), $.proxy(this.onDragStart, this));
424                this.$handle.on(this.eventName('touchcancel'), $.proxy(this.onDragEnd, this));
425            }
426
427            if (this.options.pointerDrag && support.pointer) {
428                this.$handle.on(this.eventName(support.prefixPointerEvent('pointerdown')), $.proxy(this.onDragStart, this));
429                this.$handle.on(this.eventName(support.prefixPointerEvent('pointercancel')), $.proxy(this.onDragEnd, this));
430            }
431
432            if (this.options.clickMove) {
433                this.$bar.on(this.eventName('mousedown'), $.proxy(this.onClick, this));
434            }
435
436            if (this.options.mousewheel) {
437                this.$bar.on(this.eventName('mousewheel'), function(e, delta) {
438                    var offset = self.getHandlePosition();
439                    if (offset <= 0 && delta > 0) {
440                        return true;
441                    } else if (offset >= self.barLength && delta < 0) {
442                        return true;
443                    } else {
444                        offset = offset - self.options.mousewheelSpeed * delta;
445
446                        self.move(offset, true);
447                        return false;
448                    }
449                });
450            }
451
452            this.$bar.on(this.eventName('mouseenter'), function() {
453                self.$bar.addClass(self.options.hoveringClass);
454                self.enter('hovering');
455                self.trigger('hover');
456            });
457
458            this.$bar.on(this.eventName('mouseleave'), function() {
459                self.$bar.removeClass(self.options.hoveringClass);
460
461                if (!self.is('hovering')) {
462                    return;
463                }
464                self.leave('hovering');
465                self.trigger('hovered');
466            });
467
468            if (this.options.keyboard) {
469                $(document).on(this.eventName('keydown'), function(e) {
470                    if (e.isDefaultPrevented && e.isDefaultPrevented()) {
471                        return;
472                    }
473
474                    if (!self.is('hovering')) {
475                        return;
476                    }
477                    var activeElement = document.activeElement;
478                    // go deeper if element is a webcomponent
479                    while (activeElement.shadowRoot) {
480                        activeElement = activeElement.shadowRoot.activeElement;
481                    }
482                    if ($(activeElement).is(":input,select,option,[contenteditable]")) {
483                        return;
484                    }
485                    var by = 0,
486                        to = null;
487                    switch (e.which) {
488                        case 37: // left
489                        case 63232:
490                            by = -30;
491                            break;
492                        case 38: // up
493                        case 63233:
494                            by = -30;
495                            break;
496                        case 39: // right
497                        case 63234:
498                            by = 30;
499                            break;
500                        case 40: // down
501                        case 63235:
502                            by = 30;
503                            break;
504                        case 33: // page up
505                        case 63276:
506                            by = -90;
507                            break;
508                        case 32: // space bar
509                        case 34: // page down
510                        case 63277:
511                            by = -90;
512                            break;
513                        case 35: // end
514                        case 63275:
515                            to = '100%';
516                            break;
517                        case 36: // home
518                        case 63273:
519                            to = 0;
520                            break;
521                        default:
522                            return;
523                    }
524
525                    if (by || to !== null) {
526                        if (by) {
527                            self.moveBy(by, true);
528                        } else if (to !== null) {
529                            self.moveTo(to, true);
530                        }
531                        e.preventDefault();
532                    }
533                });
534            }
535        },
536
537        onClick: function(event) {
538            if (event.which === 3) {
539                return;
540            }
541
542            if (event.target === this.$handle[0]) {
543                return;
544            }
545
546            this._drag.time = new Date().getTime();
547            this._drag.pointer = this.pointer(event);
548
549            var offset = this.$handle.offset(),
550                distance = this.distance({
551                    x: offset.left,
552                    y: offset.top
553                }, this._drag.pointer),
554                factor = 1;
555
556            if (distance > 0) {
557                distance -= this.handleLength;
558            } else {
559                distance = Math.abs(distance);
560                factor = -1;
561            }
562
563            if (distance > this.barLength * this.options.clickMoveStep) {
564                distance = this.barLength * this.options.clickMoveStep;
565            }
566            this.moveBy(factor * distance, true);
567        },
568
569        /**
570         * Handles `touchstart` and `mousedown` events.
571         */
572        onDragStart: function(event) {
573            var self = this;
574
575            if (event.which === 3) {
576                return;
577            }
578
579            // this.$bar.toggleClass(this.options.draggingClass, event.type === 'mousedown');
580            this.$bar.addClass(this.options.draggingClass);
581
582            this._drag.time = new Date().getTime();
583            this._drag.pointer = this.pointer(event);
584
585            var callback = function() {
586                self.enter('dragging');
587                self.trigger('drag');
588            }
589
590            if (this.options.mouseDrag) {
591                $(document).on(self.eventName('mouseup'), $.proxy(this.onDragEnd, this));
592
593                $(document).one(self.eventName('mousemove'), $.proxy(function() {
594                    $(document).on(self.eventName('mousemove'), $.proxy(this.onDragMove, this));
595
596                    callback();
597                }, this));
598            }
599
600            if (this.options.touchDrag && support.touch) {
601                $(document).on(self.eventName('touchend'), $.proxy(this.onDragEnd, this));
602
603                $(document).one(self.eventName('touchmove'), $.proxy(function() {
604                    $(document).on(self.eventName('touchmove'), $.proxy(this.onDragMove, this));
605
606                    callback();
607                }, this));
608            }
609
610            if (this.options.pointerDrag && support.pointer) {
611                $(document).on(self.eventName(support.prefixPointerEvent('pointerup')), $.proxy(this.onDragEnd, this));
612
613                $(document).one(self.eventName(support.prefixPointerEvent('pointermove')), $.proxy(function() {
614                    $(document).on(self.eventName(support.prefixPointerEvent('pointermove')), $.proxy(this.onDragMove, this));
615
616                    callback();
617                }, this));
618            }
619
620            $(document).on(self.eventName('blur'), $.proxy(this.onDragEnd, this));
621        },
622
623        /**
624         * Handles the `touchmove` and `mousemove` events.
625         */
626        onDragMove: function(event) {
627            var distance = this.distance(this._drag.pointer, this.pointer(event));
628
629            if (!this.is('dragging')) {
630                return;
631            }
632
633            event.preventDefault();
634            this.moveBy(distance, true);
635        },
636
637        /**
638         * Handles the `touchend` and `mouseup` events.
639         */
640        onDragEnd: function() {
641            $(document).off(this.eventName('mousemove mouseup touchmove touchend pointermove pointerup MSPointerMove MSPointerUp blur'));
642
643            this.$bar.removeClass(this.options.draggingClass);
644            this.handlePosition = this.getHandlePosition();
645
646            if (!this.is('dragging')) {
647                return;
648            }
649
650            this.leave('dragging');
651            this.trigger('dragged');
652        },
653
654        /**
655         * Gets unified pointer coordinates from event.
656         * @returns {Object} - Contains `x` and `y` coordinates of current pointer position.
657         */
658        pointer: function(event) {
659            var result = {
660                x: null,
661                y: null
662            };
663
664            event = event.originalEvent || event || window.event;
665
666            event = event.touches && event.touches.length ?
667                event.touches[0] : event.changedTouches && event.changedTouches.length ?
668                event.changedTouches[0] : event;
669
670            if (event.pageX) {
671                result.x = event.pageX;
672                result.y = event.pageY;
673            } else {
674                result.x = event.clientX;
675                result.y = event.clientY;
676            }
677
678            return result;
679        },
680
681        /**
682         * Gets the distance of two pointer.
683         */
684        distance: function(first, second) {
685            if (this.options.direction === 'vertical') {
686                return second.y - first.y;
687            } else {
688                return second.x - first.x;
689            }
690        },
691
692        setBarLength: function(length, update) {
693            if (typeof length !== 'undefined') {
694                this.$bar.css(this.attributes.length, length);
695            }
696            if (update !== false) {
697                this.updateLength();
698            }
699        },
700
701        setHandleLength: function(length, update) {
702            if (typeof length !== 'undefined') {
703                if (length < this.options.minHandleLength) {
704                    length = this.options.minHandleLength;
705                } else if (this.options.maxHandleLength && length > this.options.maxHandleLength) {
706                    length = this.options.maxHandleLength;
707                }
708                this.$handle.css(this.attributes.length, length);
709
710                if (update !== false) {
711                    this.updateLength(length);
712                }
713            }
714        },
715
716        updateLength: function(length, barLength) {
717            if (typeof length !== 'undefined') {
718                this.handleLength = length;
719            } else {
720                this.handleLength = this.getHandleLenght();
721            }
722            if (typeof barLength !== 'undefined') {
723                this.barLength = barLength;
724            } else {
725                this.barLength = this.getBarLength();
726            }
727        },
728
729        getBarLength: function() {
730            return this.$bar[0][this.attributes.clientLength];
731        },
732
733        getHandleLenght: function() {
734            return this.$handle[0][this.attributes.clientLength];
735        },
736
737        getHandlePosition: function() {
738            var value;
739
740            if (this.options.useCssTransforms && support.transform) {
741                value = convertMatrixToArray(this.$handle.css(support.transform));
742
743                if (!value) {
744                    return 0;
745                }
746
747                if (this.attributes.axis === 'X') {
748                    value = value[12] || value[4];
749                } else {
750                    value = value[13] || value[5];
751                }
752            } else {
753                value = this.$handle.css(this.attributes.position);
754            }
755
756            return parseFloat(value.replace('px', ''));
757        },
758
759        makeHandlePositionStyle: function(value) {
760            var property, x = '0',
761                y = '0';
762
763            if (this.options.useCssTransforms && support.transform) {
764                if (this.attributes.axis === 'X') {
765                    x = value + 'px';
766                } else {
767                    y = value + 'px';
768                }
769
770                property = support.transform.toString();
771
772                if (this.options.useCssTransforms3d && support.transform3d) {
773                    value = "translate3d(" + x + "," + y + ",0)";
774                } else {
775                    value = "translate(" + x + "," + y + ")";
776                }
777            } else {
778                property = this.attributes.position;
779            }
780            var temp = {};
781            temp[property] = value;
782
783            return temp;
784        },
785
786        setHandlePosition: function(value) {
787            var style = this.makeHandlePositionStyle(value);
788            this.$handle.css(style);
789
790            if (!this.is('dragging')) {
791                this.handlePosition = parseFloat(value);
792            }
793        },
794
795        moveTo: function(value, trigger, sync) {
796            var type = typeof value;
797
798            if (type === "string") {
799                if (isPercentage(value)) {
800                    value = convertPercentageToFloat(value) * (this.barLength - this.handleLength);
801                }
802
803                value = parseFloat(value);
804                type = "number";
805            }
806
807            if (type !== "number") {
808                return;
809            }
810
811            this.move(value, trigger, sync);
812        },
813
814        moveBy: function(value, trigger, sync) {
815            var type = typeof value;
816
817            if (type === "string") {
818                if (isPercentage(value)) {
819                    value = convertPercentageToFloat(value) * (this.barLength - this.handleLength);
820                }
821
822                value = parseFloat(value);
823                type = "number";
824            }
825
826            if (type !== "number") {
827                return;
828            }
829
830            this.move(this.handlePosition + value, trigger, sync);
831        },
832
833        move: function(value, trigger, sync) {
834            if (typeof value !== "number" || this.is('disabled')) {
835                return;
836            }
837
838            if (value < 0) {
839                value = 0;
840            } else if (value + this.handleLength > this.barLength) {
841                value = this.barLength - this.handleLength;
842            }
843
844            if (!this.is('dragging') && sync !== true) {
845                this.doMove(value, this.options.duration, this.options.easing, trigger);
846            } else {
847                this.setHandlePosition(value);
848
849                if (trigger) {
850                    this.trigger('change', value / (this.barLength - this.handleLength));
851                }
852            }
853        },
854
855        doMove: function(value, duration, easing, trigger) {
856            this.enter('moving');
857            duration = duration ? duration : this.options.duration;
858            easing = easing ? easing : this.options.easing;
859
860            var self = this,
861                style = this.makeHandlePositionStyle(value);
862            for (var property in style) {
863                break;
864            }
865
866            if (this.options.useCssTransitions && support.transition) {
867                self.enter('transition');
868                this.prepareTransition(property, duration, easing);
869
870                this.$handle.one(support.transition.end, function() {
871                    self.$handle.css(support.transition, '');
872
873                    if (trigger) {
874                        self.trigger('change', value / (self.barLength - self.handleLength));
875                    }
876                    self.leave('transition');
877                    self.leave('moving');
878                });
879
880                self.setHandlePosition(value);
881            } else {
882                self.enter('animating');
883
884                var startTime = getTime();
885                var start = self.getHandlePosition();
886                var end = value;
887
888                var run = function(time) {
889                    var percent = (time - startTime) / self.options.duration;
890
891                    if (percent > 1) {
892                        percent = 1;
893                    }
894
895                    percent = self.easing.fn(percent);
896
897                    var current = parseFloat(start + percent * (end - start), 10);
898                    self.setHandlePosition(current);
899
900                    if (trigger) {
901                        self.trigger('change', current / (self.barLength - self.handleLength));
902                    }
903
904                    if (percent === 1) {
905                        window.cancelAnimationFrame(self._frameId);
906                        self._frameId = null;
907
908                        self.leave('animating');
909                        self.leave('moving');
910                    } else {
911                        self._frameId = window.requestAnimationFrame(run);
912                    }
913                };
914
915                self._frameId = window.requestAnimationFrame(run);
916            }
917        },
918
919        prepareTransition: function(property, duration, easing, delay) {
920            var temp = [];
921            if (property) {
922                temp.push(property);
923            }
924            if (duration) {
925                if ($.isNumeric(duration)) {
926                    duration = duration + 'ms';
927                }
928                temp.push(duration);
929            }
930            if (easing) {
931                temp.push(easing);
932            } else {
933                temp.push(this.easing.css);
934            }
935            if (delay) {
936                temp.push(delay);
937            }
938            this.$handle.css(support.transition, temp.join(' '));
939        },
940
941        enable: function() {
942            this._states.disabled = 0;
943
944            this.$bar.removeClass(this.options.disabledClass);
945        },
946
947        disable: function() {
948            this._states.disabled = 1;
949
950            this.$bar.addClass(this.options.disabledClass);
951        },
952
953        destory: function() {
954            this.$bar.on(this.eventName());
955        }
956    };
957
958    $.fn[pluginName] = function(options) {
959        if (typeof options === 'string') {
960            var args = Array.prototype.slice.call(arguments, 1);
961            this.each(function() {
962                var instance = $(this).data(pluginName);
963                if (!instance) {
964                    return false;
965                }
966                if (!$.isFunction(instance[options]) || options.charAt(0) === "_") {
967                    return false;
968                }
969                // apply method
970                instance[options].apply(instance, args);
971            });
972        } else {
973            return this.each(function() {
974                if (!$(this).data(pluginName)) {
975                    $(this).data(pluginName, new Plugin(options, this));
976                }
977            });
978        }
979    };
980})(window, document, jQuery, undefined);
981
982(function(window, document, $, Scrollbar, undefined) {
983    "use strict";
984
985    var pluginName = 'asScrollable';
986    var instanceId = 0;
987
988    /**
989     * Helper functions
990     **/
991    function getTime() {
992        if (typeof window.performance !== 'undefined' && window.performance.now) {
993            return window.performance.now();
994        } else {
995            return Date.now();
996        }
997    }
998
999    function isPercentage(n) {
1000        return typeof n === 'string' && n.indexOf('%') != -1;
1001    }
1002
1003    function conventToPercentage(n) {
1004        if (n < 0) {
1005            n = 0;
1006        } else if (n > 1) {
1007            n = 1;
1008        }
1009        return parseFloat(n).toFixed(4) * 100 + '%';
1010    }
1011
1012    function convertPercentageToFloat(n) {
1013        return parseFloat(n.slice(0, -1) / 100, 10);
1014    }
1015
1016    var isFFLionScrollbar = (function() {
1017        var isOSXFF, ua, version;
1018        ua = window.navigator.userAgent;
1019        isOSXFF = /(?=.+Mac OS X)(?=.+Firefox)/.test(ua);
1020        if (!isOSXFF) {
1021            return false;
1022        }
1023        version = /Firefox\/\d{2}\./.exec(ua);
1024        if (version) {
1025            version = version[0].replace(/\D+/g, '');
1026        }
1027        return isOSXFF && +version > 23;
1028    })();
1029
1030    var Plugin = $[pluginName] = function(options, element) {
1031        this.$element = $(element);
1032        options = this.options = $.extend({}, Plugin.defaults, options || {}, this.$element.data('options') || {});
1033
1034        this.classes = {
1035            wrap: options.namespace,
1036            content: options.namespace + '-content',
1037            container: options.namespace + '-container',
1038            bar: options.namespace + '-bar',
1039            barHide: options.namespace + '-bar-hide',
1040            skin: options.skin
1041        };
1042
1043        this.attributes = {
1044            vertical: {
1045                axis: 'Y',
1046                overflow: 'overflow-y',
1047
1048                scroll: 'scrollTop',
1049                scrollLength: 'scrollHeight',
1050                pageOffset: 'pageYOffset',
1051
1052                ffPadding: 'padding-right',
1053
1054                length: 'height',
1055                clientLength: 'clientHeight',
1056                offset: 'offsetHeight',
1057
1058                crossLength: 'width',
1059                crossClientLength: 'clientWidth',
1060                crossOffset: 'offsetWidth'
1061            },
1062            horizontal: {
1063                axis: 'X',
1064                overflow: 'overflow-x',
1065
1066                scroll: 'scrollLeft',
1067                scrollLength: 'scrollWidth',
1068                pageOffset: 'pageXOffset',
1069
1070                ffPadding: 'padding-bottom',
1071
1072                length: 'width',
1073                clientLength: 'clientWidth',
1074                offset: 'offsetWidth',
1075
1076                crossLength: 'height',
1077                crossClientLength: 'clientHeight',
1078                crossOffset: 'offsetHeight'
1079            }
1080        };
1081
1082        // Current state information.
1083        this._states = {};
1084
1085        // Supported direction
1086        this.horizontal = null;
1087        this.vertical = null;
1088
1089        this.$bar = null;
1090
1091        // Current timeout
1092        this._frameId = null;
1093        this._timeoutId = null;
1094
1095        this.instanceId = (++instanceId);
1096
1097        this.easing = Scrollbar.easing[this.options.easing] || Scrollbar.easing.ease;
1098
1099        var position = this.$element.css('position');
1100        if (this.options.containerSelector) {
1101            this.$container = this.$element.find(this.options.containerSelector);
1102            this.$wrap = this.$element;
1103
1104            if (position == 'static') {
1105                this.$wrap.css('position', 'relative');
1106            }
1107        } else {
1108            this.$container = this.$element.wrap('<div>');
1109            this.$wrap = this.$container.parent();
1110            this.$wrap.height(this.$element.height());
1111
1112            if (position !== 'static') {
1113                this.$wrap.css('position', position);
1114            } else {
1115                this.$wrap.css('position', 'relative');
1116            }
1117        }
1118
1119        if (this.options.contentSelector) {
1120            this.$content = this.$container.find(this.options.contentSelector);
1121        } else {
1122            this.$content = this.$container.wrap('<div>');
1123            this.$container = this.$content.parent();
1124        }
1125
1126        this.init();
1127    };
1128
1129    Plugin.defaults = {
1130        namespace: pluginName,
1131
1132        skin: null,
1133
1134        contentSelector: null,
1135        containerSelector: null,
1136
1137        enabledClass: 'is-enabled',
1138        disabledClass: 'is-disabled',
1139
1140        draggingClass: 'is-dragging',
1141        hoveringClass: 'is-hovering',
1142        scrollingClass: 'is-scrolling',
1143
1144        direction: 'vertical', // vertical, horizontal, both, auto
1145
1146        showOnHover: true,
1147        showOnBarHover: false,
1148
1149        duration: 500,
1150        easing: 'ease-in', // linear, ease, ease-in, ease-out, ease-in-out
1151
1152        responsive: true,
1153        throttle: 20,
1154
1155        scrollbar: {}
1156    };
1157
1158    Plugin.prototype = {
1159        constructor: Plugin,
1160
1161        init: function() {
1162            switch (this.options.direction) {
1163                case 'vertical':
1164                    this.vertical = true;
1165                    break;
1166                case 'horizontal':
1167                    this.horizontal = true;
1168                    break;
1169                case 'both':
1170                    this.horizontal = true;
1171                    this.vertical = true;
1172                    break;
1173                case 'auto':
1174                    var overflowX = this.$element.css('overflow-x'),
1175                        overflowY = this.$element.css('overflow-y');
1176
1177                    if (overflowX === 'scroll' || overflowX === 'auto') {
1178                        this.horizontal = true;
1179                    }
1180                    if (overflowY === 'scroll' || overflowY === 'auto') {
1181                        this.vertical = true;
1182                    }
1183                    break;
1184            }
1185
1186            if (!this.vertical && !this.horizontal) {
1187                return;
1188            }
1189
1190            this.$wrap.addClass(this.classes.wrap);
1191            this.$container.addClass(this.classes.container);
1192            this.$content.addClass(this.classes.content);
1193
1194            if (this.options.skin) {
1195                this.$wrap.addClass(this.classes.skin);
1196            }
1197
1198            this.$wrap.addClass(this.options.enabledClass);
1199
1200            if (this.vertical) {
1201                this.$wrap.addClass(this.classes.wrap + '-vertical');
1202                this.initLayout('vertical');
1203                this.createBar('vertical');
1204            }
1205
1206            if (this.horizontal) {
1207                this.$wrap.addClass(this.classes.wrap + '-horizontal');
1208                this.initLayout('horizontal');
1209                this.createBar('horizontal');
1210            }
1211
1212            this.bindEvents();
1213        },
1214
1215        bindEvents: function() {
1216            var self = this;
1217            var options = this.options;
1218
1219            if (options.responsive) {
1220                $(window).on(this.eventNameWithId('orientationchange'), function() {
1221                    self.update.call(self);
1222                });
1223                $(window).on(this.eventNameWithId('resize'), this.throttle(function() {
1224                    self.update.call(self);
1225                }, options.throttle));
1226            }
1227
1228            if (!this.horizontal && !this.vertical) {
1229                return;
1230            }
1231
1232            this.$wrap.on(this.eventName('mouseenter'), function() {
1233                self.$wrap.addClass(self.options.hoveringClass);
1234                self.enter('hovering');
1235                self.trigger('hover');
1236            });
1237
1238            this.$wrap.on(this.eventName('mouseleave'), function() {
1239                self.$wrap.removeClass(self.options.hoveringClass);
1240
1241                if (!self.is('hovering')) {
1242                    return;
1243                }
1244                self.leave('hovering');
1245                self.trigger('hovered');
1246            });
1247
1248            if (options.showOnHover) {
1249                if (options.showOnBarHover) {
1250                    this.$bar.on('asScrollbar::hover', function() {
1251                        self.showBar(this.direction);
1252                    }).on('asScrollbar::hovered', function() {
1253                        self.hideBar(this.direction);
1254                    });
1255                } else {
1256                    this.$element.on(pluginName + '::hover', $.proxy(this.showBar, this));
1257                    this.$element.on(pluginName + '::hovered', $.proxy(this.hideBar, this));
1258                }
1259            }
1260
1261            this.$container.on(this.eventName('scroll'), function() {
1262                if (self.horizontal) {
1263                    var oldLeft = self.offsetLeft;
1264                    self.offsetLeft = self.getOffset('horizontal');
1265
1266                    if (oldLeft !== self.offsetLeft) {
1267                        self.trigger('scroll', self.getPercentOffset('horizontal'), 'horizontal');
1268
1269                        if (self.offsetLeft === 0) {
1270                            self.trigger('scrolltop', 'horizontal');
1271                        }
1272                        if (self.offsetLeft === self.getScrollLength('horizontal')) {
1273                            self.trigger('scrollend', 'horizontal');
1274                        }
1275                    }
1276                }
1277
1278                if (self.vertical) {
1279                    var oldTop = self.offsetTop;
1280
1281                    self.offsetTop = self.getOffset('vertical');
1282
1283                    if (oldTop !== self.offsetTop) {
1284                        self.trigger('scroll', self.getPercentOffset('vertical'), 'vertical');
1285
1286                        if (self.offsetTop === 0) {
1287                            self.trigger('scrolltop', 'vertical');
1288                        }
1289                        if (self.offsetTop === self.getScrollLength('vertical')) {
1290                            self.trigger('scrollend', 'vertical');
1291                        }
1292                    }
1293                }
1294            });
1295
1296            this.$element.on(pluginName + '::scroll', function(e, api, value, direction) {
1297                if (!self.is('scrolling')) {
1298                    self.enter('scrolling');
1299                    self.$wrap.addClass(self.options.scrollingClass);
1300                }
1301                var bar = api.getBarApi(direction);
1302
1303                bar.moveTo(conventToPercentage(value), false, true);
1304
1305                clearTimeout(self._timeoutId);
1306                self._timeoutId = setTimeout(function() {
1307                    self.$wrap.removeClass(self.options.scrollingClass);
1308                    self.leave('scrolling');
1309                }, 200);
1310            });
1311
1312            this.$bar.on('asScrollbar::change', function(e, api, value) {
1313                self.scrollTo(this.direction, conventToPercentage(value), false, true);
1314            });
1315
1316            this.$bar.on('asScrollbar::drag', function() {
1317                self.$wrap.addClass(self.options.draggingClass);
1318            }).on('asScrollbar::dragged', function() {
1319                self.$wrap.removeClass(self.options.draggingClass);
1320            });
1321        },
1322
1323        unbindEvents: function() {
1324            this.$wrap.off(this.eventName());
1325            this.$element.off(pluginName + '::scroll').off(pluginName + '::hover').off(pluginName + '::hovered');
1326            this.$container.off(this.eventName());
1327            $(window).off(this.eventNameWithId());
1328        },
1329
1330        initLayout: function(direction) {
1331            if (direction === 'vertical') {
1332                this.$container.css('height', this.$wrap.height());
1333            }
1334            var attributes = this.attributes[direction],
1335                container = this.$container[0];
1336
1337            // this.$container.css(attributes.overflow, 'scroll');
1338
1339            var scrollbarWidth = this.getBrowserScrollbarWidth(direction),
1340                parentLength = container.parentNode[attributes.crossClientLength];
1341
1342            this.$content.css(attributes.crossLength, parentLength + 'px');
1343            this.$container.css(attributes.crossLength, scrollbarWidth + parentLength + 'px');
1344
1345            if (scrollbarWidth === 0 && isFFLionScrollbar) {
1346                this.$container.css(attributes.ffPadding, 16);
1347            }
1348        },
1349
1350        createBar: function(direction) {
1351            var options = $.extend(this.options.scrollbar, {
1352                namespace: this.classes.bar,
1353                direction: direction,
1354                useCssTransitions: false,
1355                keyboard: false
1356                    //mousewheel: false
1357            });
1358            var $bar = $('<div>');
1359            $bar.asScrollbar(options);
1360
1361            if (this.options.showOnHover) {
1362                $bar.addClass(this.classes.barHide);
1363            }
1364
1365            $bar.appendTo(this.$wrap);
1366
1367            this['$' + direction] = $bar;
1368
1369            if (this.$bar === null) {
1370                this.$bar = $bar;
1371            } else {
1372                this.$bar = this.$bar.add($bar);
1373            }
1374
1375            this.updateBarHandle(direction);
1376        },
1377
1378        trigger: function(eventType) {
1379            var method_arguments = Array.prototype.slice.call(arguments, 1),
1380                data = [this].concat(method_arguments);
1381
1382            // event
1383            this.$element.trigger(pluginName + '::' + eventType, data);
1384
1385            // callback
1386            eventType = eventType.replace(/\b\w+\b/g, function(word) {
1387                return word.substring(0, 1).toUpperCase() + word.substring(1);
1388            });
1389            var onFunction = 'on' + eventType;
1390
1391            if (typeof this.options[onFunction] === 'function') {
1392                this.options[onFunction].apply(this, method_arguments);
1393            }
1394        },
1395
1396        /**
1397         * Checks whether the carousel is in a specific state or not.
1398         */
1399        is: function(state) {
1400            return this._states[state] && this._states[state] > 0;
1401        },
1402
1403        /**
1404         * Enters a state.
1405         */
1406        enter: function(state) {
1407            if (this._states[state] === undefined) {
1408                this._states[state] = 0;
1409            }
1410
1411            this._states[state] ++;
1412        },
1413
1414        /**
1415         * Leaves a state.
1416         */
1417        leave: function(state) {
1418            this._states[state] --;
1419        },
1420
1421        eventName: function(events) {
1422            if (typeof events !== 'string' || events === '') {
1423                return '.' + this.options.namespace;
1424            }
1425
1426            events = events.split(' ');
1427            var length = events.length;
1428            for (var i = 0; i < length; i++) {
1429                events[i] = events[i] + '.' + this.options.namespace;
1430            }
1431            return events.join(' ');
1432        },
1433
1434        eventNameWithId: function(events) {
1435            if (typeof events !== 'string' || events === '') {
1436                return this.options.namespace + '-' + this.instanceId;
1437            }
1438
1439            events = events.split(' ');
1440            var length = events.length;
1441            for (var i = 0; i < length; i++) {
1442                events[i] = events[i] + '.' + this.options.namespace + '-' + this.instanceId;
1443            }
1444            return events.join(' ');
1445        },
1446
1447        /**
1448         * _throttle
1449         * @description Borrowed from Underscore.js
1450         */
1451        throttle: function(func, wait) {
1452            var _now = Date.now || function() {
1453                return new Date().getTime();
1454            };
1455            var context, args, result;
1456            var timeout = null;
1457            var previous = 0;
1458            var later = function() {
1459                previous = _now();
1460                timeout = null;
1461                result = func.apply(context, args);
1462                context = args = null;
1463            };
1464            return function() {
1465                var now = _now();
1466                var remaining = wait - (now - previous);
1467                context = this;
1468                args = arguments;
1469                if (remaining <= 0) {
1470                    clearTimeout(timeout);
1471                    timeout = null;
1472                    previous = now;
1473                    result = func.apply(context, args);
1474                    context = args = null;
1475                } else if (!timeout) {
1476                    timeout = setTimeout(later, remaining);
1477                }
1478                return result;
1479            };
1480        },
1481
1482        getBrowserScrollbarWidth: function(direction) {
1483            var attributes = this.attributes[direction],
1484                outer, outerStyle;
1485            if (attributes.scrollbarWidth) {
1486                return attributes.scrollbarWidth;
1487            }
1488            outer = document.createElement('div');
1489            outerStyle = outer.style;
1490            outerStyle.position = 'absolute';
1491            outerStyle.width = '100px';
1492            outerStyle.height = '100px';
1493            outerStyle.overflow = 'scroll';
1494            outerStyle.top = '-9999px';
1495            document.body.appendChild(outer);
1496            attributes.scrollbarWidth = outer[attributes.offset] - outer[attributes.clientLength];
1497            document.body.removeChild(outer);
1498            return attributes.scrollbarWidth;
1499        },
1500
1501        getOffset: function(direction) {
1502            var attributes = this.attributes[direction],
1503                container = this.$container[0];
1504
1505            return (container[attributes.pageOffset] || container[attributes.scroll]);
1506        },
1507
1508        getPercentOffset: function(direction) {
1509            return this.getOffset(direction) / this.getScrollLength(direction);
1510        },
1511
1512        getContainerLength: function(direction) {
1513            return this.$container[0][this.attributes[direction].clientLength];
1514        },
1515
1516        getScrollLength: function(direction) {
1517            var scrollLength = this.$content[0][this.attributes[direction].scrollLength];
1518            return scrollLength - this.getContainerLength(direction);
1519        },
1520
1521        scrollTo: function(direction, value, trigger, sync) {
1522            var type = typeof value;
1523
1524            if (type === "string") {
1525                if (isPercentage(value)) {
1526                    value = convertPercentageToFloat(value) * this.getScrollLength(direction);
1527                }
1528
1529                value = parseFloat(value);
1530                type = "number";
1531            }
1532
1533            if (type !== "number") {
1534                return;
1535            }
1536
1537            this.move(direction, value, trigger, sync);
1538        },
1539
1540        scrollBy: function(direction, value, trigger, sync) {
1541            var type = typeof value;
1542
1543            if (type === "string") {
1544                if (isPercentage(value)) {
1545                    value = convertPercentageToFloat(value) * this.getScrollLength(direction);
1546                }
1547
1548                value = parseFloat(value);
1549                type = "number";
1550            }
1551
1552            if (type !== "number") {
1553                return;
1554            }
1555
1556            this.move(direction, this.getOffset(direction) + value, trigger, sync);
1557        },
1558
1559        move: function(direction, value, trigger, sync) {
1560            if (this[direction] !== true || typeof value !== "number") {
1561                return;
1562            }
1563            var self = this;
1564
1565            this.enter('moving');
1566
1567            if (value < 0) {
1568                value = 0;
1569            } else if (value >
1569 this.getScrollLength(direction)) {
1570                value = this.getScrollLength(direction);
1571            }
1572
1573            var attributes = this.attributes[direction];
1574
1575            var callback = function() {
1576                self.leave('moving');
1577            }
1578
1579            if (sync) {
1580                this.$container[0][attributes.scroll] = value;
1581
1582                if (trigger !== false) {
1583                    this.trigger('change', value / this.getScrollLength(direction));
1584                }
1585                callback();
1586            } else {
1587                self.enter('animating');
1588                var startTime = getTime();
1589                var start = self.getOffset(direction);
1590                var end = value;
1591
1592                var run = function(time) {
1593                    var percent = (time - startTime) / self.options.duration;
1594
1595                    if (percent > 1) {
1596                        percent = 1;
1597                    }
1598
1599                    percent = self.easing.fn(percent);
1600
1601                    var current = parseFloat(start + percent * (end - start), 10);
1602                    self.$container[0][attributes.scroll] = current;
1603
1604                    if (trigger !== false) {
1605                        self.trigger('change', value / self.getScrollLength(direction));
1606                    }
1607
1608                    if (percent === 1) {
1609                        window.cancelAnimationFrame(self._frameId);
1610                        self._frameId = null;
1611
1612                        self.leave('animating');
1613                        callback();
1614                    } else {
1615                        self._frameId = window.requestAnimationFrame(run);
1616                    }
1617                };
1618
1619                self._frameId = window.requestAnimationFrame(run);
1620            }
1621        },
1622
1623        scrollXto: function(value, trigger, sync) {
1624            return this.scrollTo('horizontal', value, trigger, sync);
1625        },
1626
1627        scrollYto: function(value, trigger, sync) {
1628            return this.scrollTo('vertical', value, trigger, sync);
1629        },
1630
1631        scrollXby: function(value, trigger, sync) {
1632            return this.scrollBy('horizontal', value, trigger, sync);
1633        },
1634
1635        scrollYby: function(value, trigger, sync) {
1636            return this.scrollBy('vertical', value, trigger, sync);
1637        },
1638
1639        getBar: function(direction) {
1640            if (direction && this['$' + direction]) {
1641                return this['$' + direction];
1642            } else {
1643                return this.$bar;
1644            }
1645        },
1646
1647        getBarApi: function(direction) {
1648            return this.getBar(direction).data('asScrollbar');
1649        },
1650
1651        getBarX: function() {
1652            return this.getBar('horizontal');
1653        },
1654
1655        getBarY: function() {
1656            return this.getBar('vertical');
1657        },
1658
1659        showBar: function(direction) {
1660            this.getBar(direction).removeClass(this.classes.barHide);
1661        },
1662
1663        hideBar: function(direction) {
1664            this.getBar(direction).addClass(this.classes.barHide);
1665        },
1666
1667        updateBarHandle: function(direction) {
1668            var api = this.getBarApi(direction);
1669
1670            var scrollLength = this.getScrollLength(direction),
1671                containerLength = this.getContainerLength(direction);
1672
1673            if (scrollLength > 0) {
1674                if (api.is('disabled')) {
1675                    api.enable();
1676                }
1677                api.setHandleLength(api.getBarLength() * containerLength / (scrollLength + containerLength), true);
1678            } else {
1679                api.disable();
1680            }
1681        },
1682
1683        disable: function() {
1684            if (!this.is('disabled')) {
1685                this.enter('disabled');
1686                this.$wrap.addClass(this.options.disabledClass).removeClass(this.options.enabledClass);
1687
1688                this.unbindEvents();
1689                this.unStyle();
1690            }
1691        },
1692
1693        enable: function() {
1694            if (this.is('disabled')) {
1695                this.leave('disabled');
1696                this.$wrap.addClass(this.options.enabledClass).removeClass(this.options.disabledClass);
1697
1698                this.bindEvents();
1699                this.update();
1700            }
1701        },
1702
1703        update: function() {
1704            if (this.is('disabled')) {
1705                return;
1706            }
1707            if (this.vertical) {
1708                this.initLayout('vertical');
1709                this.updateBarHandle('vertical');
1710            }
1711            if (this.horizontal) {
1712                this.initLayout('horizontal');
1713                this.updateBarHandle('horizontal');
1714            }
1715        },
1716        unStyle: function() {
1717            if (this.horizontal) {
1718                this.$container.css({
1719                    'height': '',
1720                    'padding-bottom': ''
1721                });
1722                this.$content.css({
1723                    'height': ''
1724                });
1725            }
1726            if (this.vertical) {
1727                this.$container.css({
1728                    'width': '',
1729                    'height': '',
1730                    'padding-right': ''
1731                });
1732                this.$content.css({
1733                    'width': ''
1734                });
1735            }
1736            if (!this.options.containerSelector) {
1737                this.$wrap.css({
1738                    'height': ''
1739                });
1740            }
1741        },
1742
1743        destory: function() {
1744            this.$wrap.removeClass(this.classes.wrap + '-vertical')
1745                .removeClass(this.classes.wrap + '-horizontal')
1746                .removeClass(this.classes.wrap)
1747                .removeClass(this.options.enabledClass)
1748                .removeClass(this.classes.disabledClass);
1749            this.unStyle();
1750
1751            if (this.$bar) {
1752                this.$bar.remove();
1753            }
1754
1755            this.unbindEvents();
1756
1757
1758            if (this.options.containerSelector) {
1759                this.$container.removeClass(this.classes.container);
1760            } else {
1761                this.$container.unwrap();
1762            }
1763            if (!this.options.contentSelector) {
1764                this.$content.unwrap();
1765            }
1766            this.$content.removeClass(this.classes.content);
1767            this.$element.data(pluginName, null);
1768        }
1769    }
1770
1771    $.fn[pluginName] = function(options) {
1772        if (typeof options === 'string') {
1773            var method = options;
1774            var method_arguments = Array.prototype.slice.call(arguments, 1);
1775
1776            if (/^\_/.test(method)) {
1777                return false;
1778            } else if ((/^(get)/.test(method))) {
1779                var api = this.first().data(pluginName);
1780                if (api && typeof api[method] === 'function') {
1781                    return api[method].apply(api, method_arguments);
1782                }
1783            } else {
1784                return this.each(function() {
1785                    var api = $.data(this, pluginName);
1786                    if (api && typeof api[method] === 'function') {
1787                        api[method].apply(api, method_arguments);
1788                    }
1789                });
1790            }
1791        } else {
1792            return this.each(function() {
1793                if (!$(this).data(pluginName)) {
1794                    $(this).data(pluginName, new Plugin(options, this));
1795                } else {
1796                    $(this).data(pluginName).update();
1797                }
1798            });
1799        }
1800        return this;
1801    };
1802
1803})(window, document, jQuery, (function($) {
1804    "use strict"
1805    if ($.asScrollbar === undefined) {
1806        // console.info('lost dependency lib of $.asScrollbar , please load it first !');
1807        return false;
1808    } else {
1809        return $.asScrollbar;
1810    }
1811}(jQuery)));

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