PageSourceSearch

https://thebestsong.co/wp-content/themes/Morpheus/morpheus/js/perfect-scrollbar.js

js thebestsong.co collected 2026-10-05 06:58:53 UTC 25,451 bytes, 604 lines download raw bytes

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

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.