PageSourceSearch

https://snoutup.com/games/templates/js/yvp/packages/perfect-scrollbar/perfect-scrollbar.js

js snoutup.com collected 2026-09-24 11:00:30 UTC 24,148 bytes, 693 lines download raw bytes

1/*! perfect-scrollbar - v0.4.11
2* http://noraesae.github.com/perfect-scrollbar/
3* Copyright (c) 2014 Hyeonje Alex Jun; Licensed MIT
4*
5* Edited by Rik de Vos (www.rikdevos.com)
6* 
7*/
8(function (factory) {
9  'use strict';
10
11  if (typeof define === 'function' && define.amd) {
12    // AMD. Register as an anonymous module.
13    define(['jquery'], factory);
14  } else if (typeof exports === 'object') {
15    // Node/CommonJS
16    factory(require('jquery'));
17  } else {
18    // Browser globals
19    factory(jQuery);
20  }
21}(function ($) {
22  'use strict';
23
24  // The default settings for the plugin
25  var defaultSettings = {
26    wheelSpeed: 10,
27    wheelPropagation: false,
28    minScrollbarLength: null,
29    maxScrollbarLength: null,
30    useBothWheelAxes: false,
31    useKeyboard: true,
32    suppressScrollX: false,
33    suppressScrollY: false,
34    scrollXMarginOffset: 0,
35    scrollYMarginOffset: 0,
36    includePadding: false
37  };
38
39  var getEventClassName = (function () {
40    var incrementingId = 0;
41    return function () {
42      var id = incrementingId;
43      incrementingId += 1;
44      return '.perfect-scrollbar-' + id;
45    };
46  }());
47
48  $.fn.perfectScrollbar = function (suppliedSettings, option) {
49
50    return this.each(function () {
51      // Use the default settings
52      var settings = $.extend(true, {}, defaultSettings),
53          $this = $(this);
54
55      if (typeof suppliedSettings === "object") {
56        // But over-ride any supplied
57        $.extend(true, settings, suppliedSettings);
58      } else {
59        // If no settings were supplied, then the first param must be the option
60        option = suppliedSettings;
61      }
62
63      // Catch options
64
65      if (option === 'update') {
66        if ($this.data('perfect-scrollbar-update')) {
67          $this.data('perfect-scrollbar-update')();
68        }
69        return $this;
70      }
71      else if (option === 'destroy') {
72        if ($this.data('perfect-scrollbar-destroy')) {
73          $this.data('perfect-scrollbar-destroy')();
74        }
75        return $this;
76      }
77
78      if ($this.data('perfect-scrollbar')) {
79        // if there's already perfect-scrollbar
80        return $this.data('perfect-scrollbar');
81      }
82
83
84      // Or generate new perfectScrollbar
85
86      // Set class to the container
87      $this.addClass('ps-container');
88
89      var $scrollbarXRail = $("<div class='ps-scrollbar-x-rail'></div>").appendTo($this),
90          $scrollbarYRail = $("<div class='ps-scrollbar-y-rail'></div>").appendTo($this),
91          $scrollbarX = $("<div class='ps-scrollbar-x'></div>").appendTo($scrollbarXRail),
92          $scrollbarY = $("<div class='ps-scrollbar-y'></div>").appendTo($scrollbarYRail),
93          scrollbarXActive,
94          scrollbarYActive,
95          containerWidth,
96          containerHeight,
97          contentWidth,
98          contentHeight,
99          scrollbarXWidth,
100          scrollbarXLeft,
101          scrollbarXBottom = parseInt($scrollbarXRail.css('bottom'), 10),
102          isScrollbarXUsingBottom = scrollbarXBottom === scrollbarXBottom, // !isNaN
103          scrollbarXTop = isScrollbarXUsingBottom ? null : parseInt($scrollbarXRail.css('top'), 10),
104          scrollbarYHeight,
105          scrollbarYTop,
106          scrollbarYRight = parseInt($scrollbarYRail.css('right'), 10),
107          isScrollbarYUsingRight = scrollbarYRight === scrollbarYRight, // !isNaN
108          scrollbarYLeft = isScrollbarYUsingRight ? null: parseInt($scrollbarYRail.css('left'), 10),
109          isRtl = $this.css('direction') === "rtl",
110          eventClassName = getEventClassName(),
111          railBorderXWidth = parseInt($scrollbarXRail.css('borderLeftWidth'), 10) + parseInt($scrollbarXRail.css('borderRightWidth'), 10),
112          railBorderYWidth = parseInt($scrollbarXRail.css('borderTopWidth'), 10) + parseInt($scrollbarXRail.css('borderBottomWidth'), 10);
113
114      var updateContentScrollTop = function (currentTop, deltaY) {
115        var newTop = currentTop + deltaY,
116            maxTop = containerHeight - scrollbarYHeight;
117
118        if (newTop < 0) {
119          scrollbarYTop = 0;
120        }
121        else if (newTop > maxTop) {
122          scrollbarYTop = maxTop;
123        }
124        else {
125          scrollbarYTop = newTop;
126        }
127
128        var scrollTop = parseInt(scrollbarYTop * (contentHeight - containerHeight) / (containerHeight - scrollbarYHeight), 10);
129        $this.scrollTop(scrollTop);
130      };
131
132      var updateContentScrollLeft = function (currentLeft, deltaX) {
133        var newLeft = currentLeft + deltaX,
134            maxLeft = containerWidth - scrollbarXWidth;
135
136        if (newLeft < 0) {
137          scrollbarXLeft = 0;
138        }
139        else if (newLeft > maxLeft) {
140          scrollbarXLeft = maxLeft;
141        }
142        else {
143          scrollbarXLeft = newLeft;
144        }
145
146        var scrollLeft = parseInt(scrollbarXLeft * (contentWidth - containerWidth) / (containerWidth - scrollbarXWidth), 10);
147        $this.scrollLeft(scrollLeft);
148      };
149
150      var getSettingsAdjustedThumbSize = function (thumbSize) {
151        if (settings.minScrollbarLength) {
152          thumbSize = Math.max(thumbSize, settings.minScrollbarLength);
153        }
154        if (settings.maxScrollbarLength) {
155          thumbSize = Math.min(thumbSize, settings.maxScrollbarLength);
156        }
157        return thumbSize;
158      };
159
160      var updateScrollbarCss = function () {
161        var scrollbarXStyles = {width: containerWidth, display: scrollbarXActive ? "inherit": "none"};
162        if (isRtl) {
163          scrollbarXStyles.left = $this.scrollLeft() + containerWidth - contentWidth;
164        } else {
165          scrollbarXStyles.left = $this.scrollLeft();
166        }
167        if (isScrollbarXUsingBottom) {
168          scrollbarXStyles.bottom = scrollbarXBottom - $this.scrollTop();
169        } else {
170          scrollbarXStyles.top = scrollbarXTop + $this.scrollTop();
171        }
172        $scrollbarXRail.css(scrollbarXStyles);
173
174        var scrollbarYStyles = {top: $this.scrollTop(), height: containerHeight, display: scrollbarYActive ? "inherit": "none"};
175
176        if (isScrollbarYUsingRight) {
177          if (isRtl) {
178            scrollbarYStyles.right = contentWidth - $this.scrollLeft() - scrollbarYRight - $scrollbarY.outerWidth();
179          } else {
180            scrollbarYStyles.right = scrollbarYRight - $this.scrollLeft();
181          }
182        } else {
183          if (isRtl) {
184            scrollbarYStyles.left = $this.scrollLeft() + containerWidth * 2 - contentWidth - scrollbarYLeft - $scrollbarY.outerWidth();
185          } else {
186            scrollbarYStyles.left = scrollbarYLeft + $this.scrollLeft();
187          }
188        }
189        $scrollbarYRail.css(scrollbarYStyles);
190
191        $scrollbarX.css({left: scrollbarXLeft, width: scrollbarXWidth - railBorderXWidth});
192        $scrollbarY.css({top: scrollbarYTop, height: scrollbarYHeight - railBorderYWidth});
193
194        if (scrollbarXActive) {
195          $this.addClass('ps-active-x');
196        } else {
197          $this.removeClass('ps-active-x');
198        }
199
200        if (scrollbarYActive) {
201          $this.addClass('ps-active-y');
202        } else {
203          $this.removeClass('ps-active-y');
204        }
205      };
206
207      var updateBarSizeAndPosition = function () {
208        containerWidth = settings.includePadding ? $this.innerWidth() : $this.width();
209        containerHeight = settings.includePadding ? $this.innerHeight() : $this.height();
210        contentWidth = $this.prop('scrollWidth');
211        contentHeight = $this.prop('scrollHeight');
212
213        if (!settings.suppressScrollX && containerWidth + settings.scrollXMarginOffset < contentWidth) {
214          scrollbarXActive = true;
215          scrollbarXWidth = getSettingsAdjustedThumbSize(parseInt(containerWidth * containerWidth / contentWidth, 10));
216          scrollbarXLeft = parseInt($this.scrollLeft() * (containerWidth - scrollbarXWidth) / (contentWidth - containerWidth), 10);
217        }
218        else {
219          scrollbarXActive = false;
220          scrollbarXWidth = 0;
221          scrollbarXLeft = 0;
222          $this.scrollLeft(0);
223        }
224
225        if (!settings.suppressScrollY && containerHeight + settings.scrollYMarginOffset < contentHeight) {
226          scrollbarYActive = true;
227          scrollbarYHeight = getSettingsAdjustedThumbSize(parseInt(containerHeight * containerHeight / contentHeight, 10));
228          scrollbarYTop = parseInt($this.scrollTop() * (containerHeight - scrollbarYHeight) / (contentHeight - containerHeight), 10);
229        }
230        else {
231          scrollbarYActive = false;
232          scrollbarYHeight = 0;
233          scrollbarYTop = 0;
234          $this.scrollTop(0);
235        }
236
237        if (scrollbarYTop >= containerHeight - scrollbarYHeight) {
238          scrollbarYTop = containerHeight - scrollbarYHeight;
239        }
240        if (scrollbarXLeft >= containerWidth - scrollbarXWidth) {
241          scrollbarXLeft = containerWidth - scrollbarXWidth;
242        }
243
244        updateScrollbarCss();
245      };
246
247      var bindMouseScrollXHandler = function () {
248        var currentLeft,
249            currentPageX;
250
251        $scrollbarX.bind('mousedown' + eventClassName, function (e) {
252          currentPageX = e.pageX;
253          currentLeft = $scrollbarX.position().left;
254          $scrollbarXRail.addClass('in-scrolling');
255          e.stopPropagation();
256          e.preventDefault();
257        });
258
259        $(document).bind('mousemove' + eventClassName, function (e) {
260          if ($scrollbarXRail.hasClass('in-scrolling')) {
261            updateContentScrollLeft(currentLeft, e.pageX - currentPageX);
262            updateBarSizeAndPosition();
263            e.stopPropagation();
264            e.preventDefault();
265          }
266        });
267
268        $(document).bind('mouseup' + eventClassName, function (e) {
269          if ($scrollbarXRail.hasClass('in-scrolling')) {
270            $scrollbarXRail.removeClass('in-scrolling');
271          }
272        });
273
274        currentLeft =
275        currentPageX = null;
276      };
277
278      var bindMouseScrollYHandler = function () {
279        var currentTop,
280            currentPageY;
281
282        $scrollbarY.bind('mousedown' + eventClassName, function (e) {
283          currentPageY = e.pageY;
284          currentTop = $scrollbarY.position().top;
285          $scrollbarYRail.addClass('in-scrolling');
286          e.stopPropagation();
287          e.preventDefault();
288        });
289
290        $(document).bind('mousemove' + eventClassName, function (e) {
291          if ($scrollbarYRail.hasClass('in-scrolling')) {
292            updateContentScrollTop(currentTop, e.pageY - currentPageY);
293            updateBarSizeAndPosition();
294            e.stopPropagation();
295            e.preventDefault();
296          }
297        });
298
299        $(document).bind('mouseup' + eventClassName, function (e) {
300          if ($scrollbarYRail.hasClass('in-scrolling')) {
301            $scrollbarYRail.removeClass('in-scrolling');
302          }
303        });
304
305        currentTop =
306        currentPageY = null;
307      };
308
309      // check if the default scrolling should be prevented.
310      var shouldPreventDefault = function (deltaX, deltaY) {
311        var scrollTop = $this.scrollTop();
312        if (deltaX === 0) {
313          if (!scrollbarYActive) {
314            return false;
315          }
316          if ((scrollTop === 0 && deltaY > 0) || (scrollTop >= contentHeight - containerHeight && deltaY < 0)) {
317            return !settings.wheelPropagation;
318          }
319        }
320
321        var scrollLeft = $this.scrollLeft();
322        if (deltaY === 0) {
323          if (!scrollbarXActive) {
324            return false;
325          }
326          if ((scrollLeft === 0 && deltaX < 0) || (scrollLeft >= contentWidth - containerWidth && deltaX > 0)) {
327            return !settings.wheelPropagation;
328          }
329        }
330        return true;
331      };
332
333      // bind handlers
334      var bindMouseWheelHandler = function () {
335        // FIXME: Backward compatibility.
336        // After e.deltaFactor applied, wheelSpeed should have smaller value.
337        // Currently, there's no way to change the settings after the scrollbar initialized.
338        // But if the way is implemented in the future, wheelSpeed should be reset.
339        settings.wheelSpeed /= 10;
340
341        var shouldPrevent = false;
342        $this.bind('mousewheel' + eventClassName, function (e, deprecatedDelta, deprecatedDeltaX, deprecatedDeltaY) {
343          var deltaX = e.deltaX * e.deltaFactor || deprecatedDeltaX,
344              deltaY = e.deltaY * e.deltaFactor || deprecatedDeltaY;
345
346          shouldPrevent = false;
347          if (!settings.useBothWheelAxes) {
348            // deltaX will only be used for horizontal scrolling and deltaY will
349            // only be used for vertical scrolling - this is the default
350            $this.scrollTop($this.scrollTop() - (deltaY * settings.wheelSpeed));
351            $this.scrollLeft($this.scrollLeft() + (deltaX * settings.wheelSpeed));
352          } else if (scrollbarYActive && !scrollbarXActive) {
353            // only vertical scrollbar is active and useBothWheelAxes option is
354            // active, so let's scroll vertical bar using both mouse wheel axes
355            if (deltaY) {
356              $this.scrollTop($this.scrollTop() - (deltaY * settings.wheelSpeed));
357            } else {
358              $this.scrollTop($this.scrollTop() + (deltaX * settings.wheelSpeed));
359            }
360            shouldPrevent = true;
361          } else if (scrollbarXActive && !scrollbarYActive) {
362            // useBothWheelAxes and only horizontal bar is active, so use both
363            // wheel axes for horizontal bar
364            if (deltaX) {
365              $this.scrollLeft($this.scrollLeft() + (deltaX * settings.wheelSpeed));
366            } else {
367              $this.scrollLeft($this.scrollLeft() - (deltaY * settings.wheelSpeed));
368            }
369            shouldPrevent = true;
370          }
371
372          // update bar position
373          updateBarSizeAndPosition();
374
375          shouldPrevent = (shouldPrevent || shouldPreventDefault(deltaX, deltaY));
376          if (shouldPrevent) {
377            e.stopPropagation();
378            e.preventDefault();
379          }
380        });
381
382        // fix Firefox scroll problem
383        $this.bind('MozMousePixelScroll' + eventClassName, function (e) {
384          if (shouldPrevent) {
385            e.preventDefault();
386          }
387        });
388      };
389
390      var bindKeyboardHandler = function () {
391        var hovered = false;
392        $this.bind('mouseenter' + eventClassName, function (e) {
393          hovered = true;
394        });
395        $this.bind('mouseleave' + eventClassName, function (e) {
396          hovered = false;
397        });
398
399        var shouldPrevent = false;
400        $(document).bind('keydown' + eventClassName, function (e) {
401          if (e.isDefaultPrevented && e.isDefaultPrevented()) {
402            return;
403          }
404
405          if (!hovered || $(document.activeElement).is(":input,[contenteditable]")) {
406            return;
407          }
408
409          var deltaX = 0,
410              deltaY = 0;
411
412          switch (e.which) {
413          case 37: // left
414            deltaX = -30;
415            break;
416          case 38: // up
417            deltaY = 30;
418            break;
419          case 39: // right
420            deltaX = 30;
421            break;
422          case 40: // down
423            deltaY = -30;
424            break;
425          case 33: // page up
426            deltaY = 90;
427            break;
428          case 32: // space bar
429          case 34: // page down
430            deltaY = -90;
431            break;
432          case 35: // end
433            deltaY = -containerHeight;
434            break;
435          case 36: // home
436            deltaY = containerHeight;
437            break;
438          default:
439            return;
440          }
441
442          $this.scrollTop($this.scrollTop() - deltaY);
443          $this.scrollLeft($this.scrollLeft() + deltaX);
444
445          shouldPrevent = shouldPreventDefault(deltaX, deltaY);
446          if (shouldPrevent) {
447            e.preventDefault();
448          }
449        });
450      };
451
452      var bindRailClickHandler = function () {
453        var stopPropagation = function (e) { e.stopPropagation(); };
454
455        $scrollbarY.bind('click' + eventClassName, stopPropagation);
456        $scrollbarYRail.bind('click' + eventClassName, function (e) {
457          var halfOfScrollbarLength = parseInt(scrollbarYHeight / 2, 10),
458              positionTop = e.pageY - $scrollbarYRail.offset().top - halfOfScrollbarLength,
459              maxPositionTop = containerHeight - scrollbarYHeight,
460              positionRatio = positionTop / maxPositionTop;
461
462          if (positionRatio < 0) {
463            positionRatio = 0;
464          } else if (positionRatio > 1) {
465            positionRatio = 1;
466          }
467
468          $this.scrollTop((contentHeight - containerHeight) * positionRatio);
469        });
470
471        $scrollbarX.bind('click' + eventClassName, stopPropagation);
472        $scrollbarXRail.bind('click' + eventClassName, function (e) {
473          var halfOfScrollbarLength = parseInt(scrollbarXWidth / 2, 10),
474              positionLeft = e.pageX - $scrollbarXRail.offset().left - halfOfScrollbarLength,
475              maxPositionLeft = containerWidth - scrollbarXWidth,
476              positionRatio = positionLeft / maxPositionLeft;
477
478          if (positionRatio < 0) {
479            positionRatio = 0;
480          } else if (positionRatio > 1) {
481            positionRatio = 1;
482          }
483
484          $this.scrollLeft((contentWidth - containerWidth) * positionRatio);
485        });
486      };
487
488      // bind mobile touch handler
489      var bindMobileTouchHandler = function () {
490        var applyTouchMove = function (differenceX, differenceY) {
491          if(isNaN(differenceY) || differenceY == NaN || !differenceY) {
492            return;
493          }
494          $this.scrollTop($this.scrollTop() - differenceY);
495          $this.scrollLeft($this.scrollLeft() - differenceX);
496
497          // update bar position
498          updateBarSizeAndPosition();
499        };
500
501        var startCoords = {},
502            startTime = 0,
503            speed = {},
504            breakingProcess = null,
505            inGlobalTouch = false;
506
507        $(window).bind("touchstart" + eventClassName, function (e) {
508          inGlobalTouch = true;
509        });
510        $(window).bind("touchend" + eventClassName, function (e) {
511          inGlobalTouch = false;
512        });
513
514        $this.bind("touchstart" + eventClassName, function (e) {
515          var touch = e.originalEvent.targetTouches[0];
516
517          startCoords.pageX = touch.pageX;
518          startCoords.pageY = touch.pageY;
519
520          startTime = (new Date()).getTime();
521
522          if (breakingProcess !== null) {
523            clearInterval(breakingProcess);
524          }
525
526          e.stopPropagation();
527        });
528        $this.bind("touchmove" + eventClassName, function (e) {
529          if (!inGlobalTouch && e.originalEvent.targetTouches.length === 1) {
530            var touch = e.originalEvent.targetTouches[0];
531
532            var currentCoords = {};
533            currentCoords.pageX = touch.pageX;
534            currentCoords.pageY = touch.pageY;
535
536            var differenceX = currentCoords.pageX - startCoords.pageX,
537              differenceY = currentCoords.pageY - startCoords.pageY;
538
539            applyTouchMove(differenceX, differenceY);
540            startCoords = currentCoords;
541
542            var currentTime = (new Date()).getTime();
543
544            var timeGap = currentTime - startTime;
545            if (timeGap > 0) {
546              speed.x = differenceX / timeGap;
547              speed.y = differenceY / timeGap;
548              startTime = currentTime;
549            }
550
551            e.preventDefault();
552          }
553        });
554        $this.bind("touchend" + eventClassName, function (e) {
555          clearInterval(breakingProcess);
556          breakingProcess = setInterval(function () {
557            if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
558              clearInterval(breakingProcess);
559              return;
560            }
561
562            applyTouchMove(speed.x * 30, speed.y * 30);
563
564            speed.x *= 0.8;
565            speed.y *= 0.8;
566          }, 10);
567        });
568      };
569
570      var bindScrollHandler = function () {
571        $this.bind('scroll' + eventClassName, function (e) {
572          updateBarSizeAndPosition();
573        });
574      };
575
576      var destroy = function () {
577        $this.unbind(eventClassName);
578        $(window).unbind(eventClassName);
579        $(document).unbind(eventClassName);
580        $this.data('perfect-scrollbar', null);
581        $this.data('perfect-scrollbar-update', null);
582        $this.data('perfect-scrollbar-destroy', null);
583        $scrollbarX.remove();
584        $scrollbarY.remove();
585        $scrollbarXRail.remove();
586        $scrollbarYRail.remove();
587
588        // clean all variables
589        $scrollbarXRail =
590        $scrollbarYRail =
591        $scrollbarX =
592        $scrollbarY =
593        scrollbarXActive =
594        scrollbarYActive =
595        containerWidth =
596        containerHeight =
597        contentWidth =
598        contentHeight =
599        scrollbarXWidth =
600        scrollbarXLeft =
601        scrollbarXBottom =
602        isScrollbarXUsingBottom =
603        scrollbarXTop =
604        scrollbarYHeight =
605        scrollbarYTop =
606        scrollbarYRight =
607        isScrollbarYUsingRight =
608        scrollbarYLeft =
609        isRtl =
610        eventClassName = null;
611      };
612
613      var ieSupport = function (version) {
614        $this.addClass('ie').addClass('ie' + version);
615
616        var bindHoverHandlers = function () {
617          var mouseenter = function () {
618            $(this).addClass('hover');
619          };
620          var mouseleave = function () {
621            $(this).removeClass('hover');
622          };
623          $this.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
624          $scrollbarXRail.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
625          $scrollbarYRail.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
626          $scrollbarX.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
627          $scrollbarY.bind('mouseenter' + eventClassName, mouseenter).bind('mouseleave' + eventClassName, mouseleave);
628        };
629
630        var fixIe6ScrollbarPosition = function () {
631          updateScrollbarCss = function () {
632            var scrollbarXStyles = {left: scrollbarXLeft + $this.scrollLeft(), width: scrollbarXWidth};
633            if (isScrollbarXUsingBottom) {
634              scrollbarXStyles.bottom = scrollbarXBottom;
635            } else {
636              scrollbarXStyles.top = scrollbarXTop;
637            }
638            $scrollbarX.css(scrollbarXStyles);
639
640            var scrollbarYStyles = {top: scrollbarYTop + $this.scrollTop(), height: scrollbarYHeight};
641            if (isScrollbarYUsingRight) {
642              scrollbarYStyles.right = scrollbarYRight;
643            } else {
644              scrollbarYStyles.left = scrollbarYLeft;
645            }
646
647            $scrollbarY.css(scrollbarYStyles);
648            $scrollbarX.hide().show();
649            $scrollbarY.hide().show();
650          };
651        };
652
653        if (version === 6) {
654          bindHoverHandlers();
655          fixIe6ScrollbarPosition();
656        }
657      };
658
659      var supportsTouch = (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch);
660
661      var initialize = function () {
662        var ieMatch = navigator.userAgent.toLowerCase().match(/(msie) ([\w.]+)/);
663        if (ieMatch && ieMatch[1] === 'msie') {
664          // must be executed at first, because 'ieSupport' may addClass to the container
665          ieSupport(parseInt(ieMatch[2], 10));
666        }
667
668        updateBarSizeAndPosition();
669        bindScrollHandler();
670        bindMouseScrollXHandler();
671        bindMouseScrollYHandler();
672        bindRailClickHandler();
673        if (supportsTouch) {
674          bindMobileTouchHandler();
675        }
676        if ($this.mousewheel) {
677          bindMouseWheelHandler();
678        }
679        if (settings.useKeyboard) {
680          bindKeyboardHandler();
681        }
682        $this.data('perfect-scrollbar', $this);
683        $this.data('perfect-scrollbar-update', updateBarSizeAndPosition);
684        $this.data('perfect-scrollbar-destroy', destroy);
685      };
686
687      // initialize
688      initialize();
689
690      return $this;
691    });
692  };
693}));

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.