File indexing completed on 2026-04-09 07:58:30
0001
0002
0003
0004
0005
0006 'use strict';
0007
0008 function get(element) {
0009 return getComputedStyle(element);
0010 }
0011
0012 function set(element, obj) {
0013 for (var key in obj) {
0014 var val = obj[key];
0015 if (typeof val === 'number') {
0016 val = val + "px";
0017 }
0018 element.style[key] = val;
0019 }
0020 return element;
0021 }
0022
0023 function div(className) {
0024 var div = document.createElement('div');
0025 div.className = className;
0026 return div;
0027 }
0028
0029 var elMatches =
0030 typeof Element !== 'undefined' &&
0031 (Element.prototype.matches ||
0032 Element.prototype.webkitMatchesSelector ||
0033 Element.prototype.msMatchesSelector);
0034
0035 function matches(element, query) {
0036 if (!elMatches) {
0037 throw new Error('No element matching method supported');
0038 }
0039
0040 return elMatches.call(element, query);
0041 }
0042
0043 function remove(element) {
0044 if (element.remove) {
0045 element.remove();
0046 } else {
0047 if (element.parentNode) {
0048 element.parentNode.removeChild(element);
0049 }
0050 }
0051 }
0052
0053 function queryChildren(element, selector) {
0054 return Array.prototype.filter.call(element.children, function (child) { return matches(child, selector); }
0055 );
0056 }
0057
0058 var cls = {
0059 main: 'ps',
0060 element: {
0061 thumb: function (x) { return ("ps__thumb-" + x); },
0062 rail: function (x) { return ("ps__rail-" + x); },
0063 consuming: 'ps__child--consume',
0064 },
0065 state: {
0066 focus: 'ps--focus',
0067 active: function (x) { return ("ps--active-" + x); },
0068 scrolling: function (x) { return ("ps--scrolling-" + x); },
0069 },
0070 };
0071
0072
0073
0074
0075 var scrollingClassTimeout = { x: null, y: null };
0076
0077 function addScrollingClass(i, x) {
0078 var classList = i.element.classList;
0079 var className = cls.state.scrolling(x);
0080
0081 if (classList.contains(className)) {
0082 clearTimeout(scrollingClassTimeout[x]);
0083 } else {
0084 classList.add(className);
0085 }
0086 }
0087
0088 function removeScrollingClass(i, x) {
0089 scrollingClassTimeout[x] = setTimeout(
0090 function () { return i.isAlive && i.element.classList.remove(cls.state.scrolling(x)); },
0091 i.settings.scrollingThreshold
0092 );
0093 }
0094
0095 function setScrollingClassInstantly(i, x) {
0096 addScrollingClass(i, x);
0097 removeScrollingClass(i, x);
0098 }
0099
0100 var EventElement = function EventElement(element) {
0101 this.element = element;
0102 this.handlers = {};
0103 };
0104
0105 var prototypeAccessors = { isEmpty: { configurable: true } };
0106
0107 EventElement.prototype.bind = function bind (eventName, handler) {
0108 if (typeof this.handlers[eventName] === 'undefined') {
0109 this.handlers[eventName] = [];
0110 }
0111 this.handlers[eventName].push(handler);
0112 this.element.addEventListener(eventName, handler, false);
0113 };
0114
0115 EventElement.prototype.unbind = function unbind (eventName, target) {
0116 var this$1 = this;
0117
0118 this.handlers[eventName] = this.handlers[eventName].filter(function (handler) {
0119 if (target && handler !== target) {
0120 return true;
0121 }
0122 this$1.element.removeEventListener(eventName, handler, false);
0123 return false;
0124 });
0125 };
0126
0127 EventElement.prototype.unbindAll = function unbindAll () {
0128 var this$1 = this;
0129
0130 for (var name in this$1.handlers) {
0131 this$1.unbind(name);
0132 }
0133 };
0134
0135 prototypeAccessors.isEmpty.get = function () {
0136 var this$1 = this;
0137
0138 return Object.keys(this.handlers).every(
0139 function (key) { return this$1.handlers[key].length === 0; }
0140 );
0141 };
0142
0143 Object.defineProperties( EventElement.prototype, prototypeAccessors );
0144
0145 var EventManager = function EventManager() {
0146 this.eventElements = [];
0147 };
0148
0149 EventManager.prototype.eventElement = function eventElement (element) {
0150 var ee = this.eventElements.filter(function (ee) { return ee.element === element; })[0];
0151 if (!ee) {
0152 ee = new EventElement(element);
0153 this.eventElements.push(ee);
0154 }
0155 return ee;
0156 };
0157
0158 EventManager.prototype.bind = function bind (element, eventName, handler) {
0159 this.eventElement(element).bind(eventName, handler);
0160 };
0161
0162 EventManager.prototype.unbind = function unbind (element, eventName, handler) {
0163 var ee = this.eventElement(element);
0164 ee.unbind(eventName, handler);
0165
0166 if (ee.isEmpty) {
0167
0168 this.eventElements.splice(this.eventElements.indexOf(ee), 1);
0169 }
0170 };
0171
0172 EventManager.prototype.unbindAll = function unbindAll () {
0173 this.eventElements.forEach(function (e) { return e.unbindAll(); });
0174 this.eventElements = [];
0175 };
0176
0177 EventManager.prototype.once = function once (element, eventName, handler) {
0178 var ee = this.eventElement(element);
0179 var onceHandler = function (evt) {
0180 ee.unbind(eventName, onceHandler);
0181 handler(evt);
0182 };
0183 ee.bind(eventName, onceHandler);
0184 };
0185
0186 function createEvent(name) {
0187 if (typeof window.CustomEvent === 'function') {
0188 return new CustomEvent(name);
0189 } else {
0190 var evt = document.createEvent('CustomEvent');
0191 evt.initCustomEvent(name, false, false, undefined);
0192 return evt;
0193 }
0194 }
0195
0196 var processScrollDiff = function(
0197 i,
0198 axis,
0199 diff,
0200 useScrollingClass,
0201 forceFireReachEvent
0202 ) {
0203 if ( useScrollingClass === void 0 ) useScrollingClass = true;
0204 if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false;
0205
0206 var fields;
0207 if (axis === 'top') {
0208 fields = [
0209 'contentHeight',
0210 'containerHeight',
0211 'scrollTop',
0212 'y',
0213 'up',
0214 'down' ];
0215 } else if (axis === 'left') {
0216 fields = [
0217 'contentWidth',
0218 'containerWidth',
0219 'scrollLeft',
0220 'x',
0221 'left',
0222 'right' ];
0223 } else {
0224 throw new Error('A proper axis should be provided');
0225 }
0226
0227 processScrollDiff$1(i, diff, fields, useScrollingClass, forceFireReachEvent);
0228 };
0229
0230 function processScrollDiff$1(
0231 i,
0232 diff,
0233 ref,
0234 useScrollingClass,
0235 forceFireReachEvent
0236 ) {
0237 var contentHeight = ref[0];
0238 var containerHeight = ref[1];
0239 var scrollTop = ref[2];
0240 var y = ref[3];
0241 var up = ref[4];
0242 var down = ref[5];
0243 if ( useScrollingClass === void 0 ) useScrollingClass = true;
0244 if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false;
0245
0246 var element = i.element;
0247
0248
0249 i.reach[y] = null;
0250
0251
0252 if (element[scrollTop] < 1) {
0253 i.reach[y] = 'start';
0254 }
0255
0256
0257 if (element[scrollTop] > i[contentHeight] - i[containerHeight] - 1) {
0258 i.reach[y] = 'end';
0259 }
0260
0261 if (diff) {
0262 element.dispatchEvent(createEvent(("ps-scroll-" + y)));
0263
0264 if (diff < 0) {
0265 element.dispatchEvent(createEvent(("ps-scroll-" + up)));
0266 } else if (diff > 0) {
0267 element.dispatchEvent(createEvent(("ps-scroll-" + down)));
0268 }
0269
0270 if (useScrollingClass) {
0271 setScrollingClassInstantly(i, y);
0272 }
0273 }
0274
0275 if (i.reach[y] && (diff || forceFireReachEvent)) {
0276 element.dispatchEvent(createEvent(("ps-" + y + "-reach-" + (i.reach[y]))));
0277 }
0278 }
0279
0280 function toInt(x) {
0281 return parseInt(x, 10) || 0;
0282 }
0283
0284 function isEditable(el) {
0285 return (
0286 matches(el, 'input,[contenteditable]') ||
0287 matches(el, 'select,[contenteditable]') ||
0288 matches(el, 'textarea,[contenteditable]') ||
0289 matches(el, 'button,[contenteditable]')
0290 );
0291 }
0292
0293 function outerWidth(element) {
0294 var styles = get(element);
0295 return (
0296 toInt(styles.width) +
0297 toInt(styles.paddingLeft) +
0298 toInt(styles.paddingRight) +
0299 toInt(styles.borderLeftWidth) +
0300 toInt(styles.borderRightWidth)
0301 );
0302 }
0303
0304 var env = {
0305 isWebKit:
0306 typeof document !== 'undefined' &&
0307 'WebkitAppearance' in document.documentElement.style,
0308 supportsTouch:
0309 typeof window !== 'undefined' &&
0310 ('ontouchstart' in window ||
0311 (window.DocumentTouch && document instanceof window.DocumentTouch)),
0312 supportsIePointer:
0313 typeof navigator !== 'undefined' && navigator.msMaxTouchPoints,
0314 isChrome:
0315 typeof navigator !== 'undefined' &&
0316 /Chrome/i.test(navigator && navigator.userAgent),
0317 };
0318
0319 var updateGeometry = function(i) {
0320 var element = i.element;
0321
0322 i.containerWidth = element.clientWidth;
0323 i.containerHeight = element.clientHeight;
0324 i.contentWidth = element.scrollWidth;
0325 i.contentHeight = element.scrollHeight;
0326
0327 if (!element.contains(i.scrollbarXRail)) {
0328
0329 queryChildren(element, cls.element.rail('x')).forEach(function (el) { return remove(el); }
0330 );
0331 element.appendChild(i.scrollbarXRail);
0332 }
0333 if (!element.contains(i.scrollbarYRail)) {
0334
0335 queryChildren(element, cls.element.rail('y')).forEach(function (el) { return remove(el); }
0336 );
0337 element.appendChild(i.scrollbarYRail);
0338 }
0339
0340 if (
0341 !i.settings.suppressScrollX &&
0342 i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth
0343 ) {
0344 i.scrollbarXActive = true;
0345 i.railXWidth = i.containerWidth - i.railXMarginWidth;
0346 i.railXRatio = i.containerWidth / i.railXWidth;
0347 i.scrollbarXWidth = getThumbSize(
0348 i,
0349 toInt(i.railXWidth * i.containerWidth / i.contentWidth)
0350 );
0351 i.scrollbarXLeft = toInt(
0352 (i.negativeScrollAdjustment + element.scrollLeft) *
0353 (i.railXWidth - i.scrollbarXWidth) /
0354 (i.contentWidth - i.containerWidth)
0355 );
0356 } else {
0357 i.scrollbarXActive = false;
0358 }
0359
0360 if (
0361 !i.settings.suppressScrollY &&
0362 i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight
0363 ) {
0364 i.scrollbarYActive = true;
0365 i.railYHeight = i.containerHeight - i.railYMarginHeight;
0366 i.railYRatio = i.containerHeight / i.railYHeight;
0367 i.scrollbarYHeight = getThumbSize(
0368 i,
0369 toInt(i.railYHeight * i.containerHeight / i.contentHeight)
0370 );
0371 i.scrollbarYTop = toInt(
0372 element.scrollTop *
0373 (i.railYHeight - i.scrollbarYHeight) /
0374 (i.contentHeight - i.containerHeight)
0375 );
0376 } else {
0377 i.scrollbarYActive = false;
0378 }
0379
0380 if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) {
0381 i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth;
0382 }
0383 if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) {
0384 i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight;
0385 }
0386
0387 updateCss(element, i);
0388
0389 if (i.scrollbarXActive) {
0390 element.classList.add(cls.state.active('x'));
0391 } else {
0392 element.classList.remove(cls.state.active('x'));
0393 i.scrollbarXWidth = 0;
0394 i.scrollbarXLeft = 0;
0395 element.scrollLeft = 0;
0396 }
0397 if (i.scrollbarYActive) {
0398 element.classList.add(cls.state.active('y'));
0399 } else {
0400 element.classList.remove(cls.state.active('y'));
0401 i.scrollbarYHeight = 0;
0402 i.scrollbarYTop = 0;
0403 element.scrollTop = 0;
0404 }
0405 };
0406
0407 function getThumbSize(i, thumbSize) {
0408 if (i.settings.minScrollbarLength) {
0409 thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength);
0410 }
0411 if (i.settings.maxScrollbarLength) {
0412 thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength);
0413 }
0414 return thumbSize;
0415 }
0416
0417 function updateCss(element, i) {
0418 var xRailOffset = { width: i.railXWidth };
0419 if (i.isRtl) {
0420 xRailOffset.left =
0421 i.negativeScrollAdjustment +
0422 element.scrollLeft +
0423 i.containerWidth -
0424 i.contentWidth;
0425 } else {
0426 xRailOffset.left = element.scrollLeft;
0427 }
0428 if (i.isScrollbarXUsingBottom) {
0429 xRailOffset.bottom = i.scrollbarXBottom - element.scrollTop;
0430 } else {
0431 xRailOffset.top = i.scrollbarXTop + element.scrollTop;
0432 }
0433 set(i.scrollbarXRail, xRailOffset);
0434
0435 var yRailOffset = { top: element.scrollTop, height: i.railYHeight };
0436 if (i.isScrollbarYUsingRight) {
0437 if (i.isRtl) {
0438 yRailOffset.right =
0439 i.contentWidth -
0440 (i.negativeScrollAdjustment + element.scrollLeft) -
0441 i.scrollbarYRight -
0442 i.scrollbarYOuterWidth;
0443 } else {
0444 yRailOffset.right = i.scrollbarYRight - element.scrollLeft;
0445 }
0446 } else {
0447 if (i.isRtl) {
0448 yRailOffset.left =
0449 i.negativeScrollAdjustment +
0450 element.scrollLeft +
0451 i.containerWidth * 2 -
0452 i.contentWidth -
0453 i.scrollbarYLeft -
0454 i.scrollbarYOuterWidth;
0455 } else {
0456 yRailOffset.left = i.scrollbarYLeft + element.scrollLeft;
0457 }
0458 }
0459 set(i.scrollbarYRail, yRailOffset);
0460
0461 set(i.scrollbarX, {
0462 left: i.scrollbarXLeft,
0463 width: i.scrollbarXWidth - i.railBorderXWidth,
0464 });
0465 set(i.scrollbarY, {
0466 top: i.scrollbarYTop,
0467 height: i.scrollbarYHeight - i.railBorderYWidth,
0468 });
0469 }
0470
0471 var clickRail = function(i) {
0472 i.event.bind(i.scrollbarY, 'mousedown', function (e) { return e.stopPropagation(); });
0473 i.event.bind(i.scrollbarYRail, 'mousedown', function (e) {
0474 var positionTop =
0475 e.pageY -
0476 window.pageYOffset -
0477 i.scrollbarYRail.getBoundingClientRect().top;
0478 var direction = positionTop > i.scrollbarYTop ? 1 : -1;
0479
0480 i.element.scrollTop += direction * i.containerHeight;
0481 updateGeometry(i);
0482
0483 e.stopPropagation();
0484 });
0485
0486 i.event.bind(i.scrollbarX, 'mousedown', function (e) { return e.stopPropagation(); });
0487 i.event.bind(i.scrollbarXRail, 'mousedown', function (e) {
0488 var positionLeft =
0489 e.pageX -
0490 window.pageXOffset -
0491 i.scrollbarXRail.getBoundingClientRect().left;
0492 var direction = positionLeft > i.scrollbarXLeft ? 1 : -1;
0493
0494 i.element.scrollLeft += direction * i.containerWidth;
0495 updateGeometry(i);
0496
0497 e.stopPropagation();
0498 });
0499 };
0500
0501 var dragThumb = function(i) {
0502 bindMouseScrollHandler(i, [
0503 'containerWidth',
0504 'contentWidth',
0505 'pageX',
0506 'railXWidth',
0507 'scrollbarX',
0508 'scrollbarXWidth',
0509 'scrollLeft',
0510 'x' ]);
0511 bindMouseScrollHandler(i, [
0512 'containerHeight',
0513 'contentHeight',
0514 'pageY',
0515 'railYHeight',
0516 'scrollbarY',
0517 'scrollbarYHeight',
0518 'scrollTop',
0519 'y' ]);
0520 };
0521
0522 function bindMouseScrollHandler(
0523 i,
0524 ref
0525 ) {
0526 var containerHeight = ref[0];
0527 var contentHeight = ref[1];
0528 var pageY = ref[2];
0529 var railYHeight = ref[3];
0530 var scrollbarY = ref[4];
0531 var scrollbarYHeight = ref[5];
0532 var scrollTop = ref[6];
0533 var y = ref[7];
0534
0535 var element = i.element;
0536
0537 var startingScrollTop = null;
0538 var startingMousePageY = null;
0539 var scrollBy = null;
0540
0541 function mouseMoveHandler(e) {
0542 element[scrollTop] =
0543 startingScrollTop + scrollBy * (e[pageY] - startingMousePageY);
0544 addScrollingClass(i, y);
0545 updateGeometry(i);
0546
0547 e.stopPropagation();
0548 e.preventDefault();
0549 }
0550
0551 function mouseUpHandler() {
0552 removeScrollingClass(i, y);
0553 i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler);
0554 }
0555
0556 i.event.bind(i[scrollbarY], 'mousedown', function (e) {
0557 startingScrollTop = element[scrollTop];
0558 startingMousePageY = e[pageY];
0559 scrollBy =
0560 (i[contentHeight] - i[containerHeight]) /
0561 (i[railYHeight] - i[scrollbarYHeight]);
0562
0563 i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler);
0564 i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler);
0565
0566 e.stopPropagation();
0567 e.preventDefault();
0568 });
0569 }
0570
0571 var keyboard = function(i) {
0572 var element = i.element;
0573
0574 var elementHovered = function () { return matches(element, ':hover'); };
0575 var scrollbarFocused = function () { return matches(i.scrollbarX, ':focus') || matches(i.scrollbarY, ':focus'); };
0576
0577 function shouldPreventDefault(deltaX, deltaY) {
0578 var scrollTop = element.scrollTop;
0579 if (deltaX === 0) {
0580 if (!i.scrollbarYActive) {
0581 return false;
0582 }
0583 if (
0584 (scrollTop === 0 && deltaY > 0) ||
0585 (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0)
0586 ) {
0587 return !i.settings.wheelPropagation;
0588 }
0589 }
0590
0591 var scrollLeft = element.scrollLeft;
0592 if (deltaY === 0) {
0593 if (!i.scrollbarXActive) {
0594 return false;
0595 }
0596 if (
0597 (scrollLeft === 0 && deltaX < 0) ||
0598 (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0)
0599 ) {
0600 return !i.settings.wheelPropagation;
0601 }
0602 }
0603 return true;
0604 }
0605
0606 i.event.bind(i.ownerDocument, 'keydown', function (e) {
0607 if (
0608 (e.isDefaultPrevented && e.isDefaultPrevented()) ||
0609 e.defaultPrevented
0610 ) {
0611 return;
0612 }
0613
0614 if (!elementHovered() && !scrollbarFocused()) {
0615 return;
0616 }
0617
0618 var activeElement = document.activeElement
0619 ? document.activeElement
0620 : i.ownerDocument.activeElement;
0621 if (activeElement) {
0622 if (activeElement.tagName === 'IFRAME') {
0623 activeElement = activeElement.contentDocument.activeElement;
0624 } else {
0625
0626 while (activeElement.shadowRoot) {
0627 activeElement = activeElement.shadowRoot.activeElement;
0628 }
0629 }
0630 if (isEditable(activeElement)) {
0631 return;
0632 }
0633 }
0634
0635 var deltaX = 0;
0636 var deltaY = 0;
0637
0638 switch (e.which) {
0639 case 37:
0640 if (e.metaKey) {
0641 deltaX = -i.contentWidth;
0642 } else if (e.altKey) {
0643 deltaX = -i.containerWidth;
0644 } else {
0645 deltaX = -30;
0646 }
0647 break;
0648 case 38:
0649 if (e.metaKey) {
0650 deltaY = i.contentHeight;
0651 } else if (e.altKey) {
0652 deltaY = i.containerHeight;
0653 } else {
0654 deltaY = 30;
0655 }
0656 break;
0657 case 39:
0658 if (e.metaKey) {
0659 deltaX = i.contentWidth;
0660 } else if (e.altKey) {
0661 deltaX = i.containerWidth;
0662 } else {
0663 deltaX = 30;
0664 }
0665 break;
0666 case 40:
0667 if (e.metaKey) {
0668 deltaY = -i.contentHeight;
0669 } else if (e.altKey) {
0670 deltaY = -i.containerHeight;
0671 } else {
0672 deltaY = -30;
0673 }
0674 break;
0675 case 32:
0676 if (e.shiftKey) {
0677 deltaY = i.containerHeight;
0678 } else {
0679 deltaY = -i.containerHeight;
0680 }
0681 break;
0682 case 33:
0683 deltaY = i.containerHeight;
0684 break;
0685 case 34:
0686 deltaY = -i.containerHeight;
0687 break;
0688 case 36:
0689 deltaY = i.contentHeight;
0690 break;
0691 case 35:
0692 deltaY = -i.contentHeight;
0693 break;
0694 default:
0695 return;
0696 }
0697
0698 if (i.settings.suppressScrollX && deltaX !== 0) {
0699 return;
0700 }
0701 if (i.settings.suppressScrollY && deltaY !== 0) {
0702 return;
0703 }
0704
0705 element.scrollTop -= deltaY;
0706 element.scrollLeft += deltaX;
0707 updateGeometry(i);
0708
0709 if (shouldPreventDefault(deltaX, deltaY)) {
0710 e.preventDefault();
0711 }
0712 });
0713 };
0714
0715 var wheel = function(i) {
0716 var element = i.element;
0717
0718 function shouldPreventDefault(deltaX, deltaY) {
0719 var isTop = element.scrollTop === 0;
0720 var isBottom =
0721 element.scrollTop + element.offsetHeight === element.scrollHeight;
0722 var isLeft = element.scrollLeft === 0;
0723 var isRight =
0724 element.scrollLeft + element.offsetWidth === element.offsetWidth;
0725
0726 var hitsBound;
0727
0728
0729 if (Math.abs(deltaY) > Math.abs(deltaX)) {
0730 hitsBound = isTop || isBottom;
0731 } else {
0732 hitsBound = isLeft || isRight;
0733 }
0734
0735 return hitsBound ? !i.settings.wheelPropagation : true;
0736 }
0737
0738 function getDeltaFromEvent(e) {
0739 var deltaX = e.deltaX;
0740 var deltaY = -1 * e.deltaY;
0741
0742 if (typeof deltaX === 'undefined' || typeof deltaY === 'undefined') {
0743
0744 deltaX = -1 * e.wheelDeltaX / 6;
0745 deltaY = e.wheelDeltaY / 6;
0746 }
0747
0748 if (e.deltaMode && e.deltaMode === 1) {
0749
0750 deltaX *= 10;
0751 deltaY *= 10;
0752 }
0753
0754 if (deltaX !== deltaX && deltaY !== deltaY ) {
0755
0756 deltaX = 0;
0757 deltaY = e.wheelDelta;
0758 }
0759
0760 if (e.shiftKey) {
0761
0762 return [-deltaY, -deltaX];
0763 }
0764 return [deltaX, deltaY];
0765 }
0766
0767 function shouldBeConsumedByChild(target, deltaX, deltaY) {
0768
0769 if (!env.isWebKit && element.querySelector('select:focus')) {
0770 return true;
0771 }
0772
0773 if (!element.contains(target)) {
0774 return false;
0775 }
0776
0777 var cursor = target;
0778
0779 while (cursor && cursor !== element) {
0780 if (cursor.classList.contains(cls.element.consuming)) {
0781 return true;
0782 }
0783
0784 var style = get(cursor);
0785 var overflow = [style.overflow, style.overflowX, style.overflowY].join(
0786 ''
0787 );
0788
0789
0790 if (overflow.match(/(scroll|auto)/)) {
0791 var maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
0792 if (maxScrollTop > 0) {
0793 if (
0794 !(cursor.scrollTop === 0 && deltaY > 0) &&
0795 !(cursor.scrollTop === maxScrollTop && deltaY < 0)
0796 ) {
0797 return true;
0798 }
0799 }
0800 var maxScrollLeft = cursor.scrollLeft - cursor.clientWidth;
0801 if (maxScrollLeft > 0) {
0802 if (
0803 !(cursor.scrollLeft === 0 && deltaX < 0) &&
0804 !(cursor.scrollLeft === maxScrollLeft && deltaX > 0)
0805 ) {
0806 return true;
0807 }
0808 }
0809 }
0810
0811 cursor = cursor.parentNode;
0812 }
0813
0814 return false;
0815 }
0816
0817 function mousewheelHandler(e) {
0818 var ref = getDeltaFromEvent(e);
0819 var deltaX = ref[0];
0820 var deltaY = ref[1];
0821
0822 if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) {
0823 return;
0824 }
0825
0826 var shouldPrevent = false;
0827 if (!i.settings.useBothWheelAxes) {
0828
0829
0830 element.scrollTop -= deltaY * i.settings.wheelSpeed;
0831 element.scrollLeft += deltaX * i.settings.wheelSpeed;
0832 } else if (i.scrollbarYActive && !i.scrollbarXActive) {
0833
0834
0835 if (deltaY) {
0836 element.scrollTop -= deltaY * i.settings.wheelSpeed;
0837 } else {
0838 element.scrollTop += deltaX * i.settings.wheelSpeed;
0839 }
0840 shouldPrevent = true;
0841 } else if (i.scrollbarXActive && !i.scrollbarYActive) {
0842
0843
0844 if (deltaX) {
0845 element.scrollLeft += deltaX * i.settings.wheelSpeed;
0846 } else {
0847 element.scrollLeft -= deltaY * i.settings.wheelSpeed;
0848 }
0849 shouldPrevent = true;
0850 }
0851
0852 updateGeometry(i);
0853
0854 shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY);
0855 if (shouldPrevent && !e.ctrlKey) {
0856 e.stopPropagation();
0857 e.preventDefault();
0858 }
0859 }
0860
0861 if (typeof window.onwheel !== 'undefined') {
0862 i.event.bind(element, 'wheel', mousewheelHandler);
0863 } else if (typeof window.onmousewheel !== 'undefined') {
0864 i.event.bind(element, 'mousewheel', mousewheelHandler);
0865 }
0866 };
0867
0868 var touch = function(i) {
0869 if (!env.supportsTouch && !env.supportsIePointer) {
0870 return;
0871 }
0872
0873 var element = i.element;
0874
0875 function shouldPrevent(deltaX, deltaY) {
0876 var scrollTop = element.scrollTop;
0877 var scrollLeft = element.scrollLeft;
0878 var magnitudeX = Math.abs(deltaX);
0879 var magnitudeY = Math.abs(deltaY);
0880
0881 if (magnitudeY > magnitudeX) {
0882
0883
0884 if (
0885 (deltaY < 0 && scrollTop === i.contentHeight - i.containerHeight) ||
0886 (deltaY > 0 && scrollTop === 0)
0887 ) {
0888
0889 return window.scrollY === 0 && deltaY > 0 && env.isChrome;
0890 }
0891 } else if (magnitudeX > magnitudeY) {
0892
0893
0894 if (
0895 (deltaX < 0 && scrollLeft === i.contentWidth - i.containerWidth) ||
0896 (deltaX > 0 && scrollLeft === 0)
0897 ) {
0898 return true;
0899 }
0900 }
0901
0902 return true;
0903 }
0904
0905 function applyTouchMove(differenceX, differenceY) {
0906 element.scrollTop -= differenceY;
0907 element.scrollLeft -= differenceX;
0908
0909 updateGeometry(i);
0910 }
0911
0912 var startOffset = {};
0913 var startTime = 0;
0914 var speed = {};
0915 var easingLoop = null;
0916
0917 function getTouch(e) {
0918 if (e.targetTouches) {
0919 return e.targetTouches[0];
0920 } else {
0921
0922 return e;
0923 }
0924 }
0925
0926 function shouldHandle(e) {
0927 if (e.pointerType && e.pointerType === 'pen' && e.buttons === 0) {
0928 return false;
0929 }
0930 if (e.targetTouches && e.targetTouches.length === 1) {
0931 return true;
0932 }
0933 if (
0934 e.pointerType &&
0935 e.pointerType !== 'mouse' &&
0936 e.pointerType !== e.MSPOINTER_TYPE_MOUSE
0937 ) {
0938 return true;
0939 }
0940 return false;
0941 }
0942
0943 function touchStart(e) {
0944 if (!shouldHandle(e)) {
0945 return;
0946 }
0947
0948 var touch = getTouch(e);
0949
0950 startOffset.pageX = touch.pageX;
0951 startOffset.pageY = touch.pageY;
0952
0953 startTime = new Date().getTime();
0954
0955 if (easingLoop !== null) {
0956 clearInterval(easingLoop);
0957 }
0958 }
0959
0960 function shouldBeConsumedByChild(target, deltaX, deltaY) {
0961 if (!element.contains(target)) {
0962 return false;
0963 }
0964
0965 var cursor = target;
0966
0967 while (cursor && cursor !== element) {
0968 if (cursor.classList.contains(cls.element.consuming)) {
0969 return true;
0970 }
0971
0972 var style = get(cursor);
0973 var overflow = [style.overflow, style.overflowX, style.overflowY].join(
0974 ''
0975 );
0976
0977
0978 if (overflow.match(/(scroll|auto)/)) {
0979 var maxScrollTop = cursor.scrollHeight - cursor.clientHeight;
0980 if (maxScrollTop > 0) {
0981 if (
0982 !(cursor.scrollTop === 0 && deltaY > 0) &&
0983 !(cursor.scrollTop === maxScrollTop && deltaY < 0)
0984 ) {
0985 return true;
0986 }
0987 }
0988 var maxScrollLeft = cursor.scrollLeft - cursor.clientWidth;
0989 if (maxScrollLeft > 0) {
0990 if (
0991 !(cursor.scrollLeft === 0 && deltaX < 0) &&
0992 !(cursor.scrollLeft === maxScrollLeft && deltaX > 0)
0993 ) {
0994 return true;
0995 }
0996 }
0997 }
0998
0999 cursor = cursor.parentNode;
1000 }
1001
1002 return false;
1003 }
1004
1005 function touchMove(e) {
1006 if (shouldHandle(e)) {
1007 var touch = getTouch(e);
1008
1009 var currentOffset = { pageX: touch.pageX, pageY: touch.pageY };
1010
1011 var differenceX = currentOffset.pageX - startOffset.pageX;
1012 var differenceY = currentOffset.pageY - startOffset.pageY;
1013
1014 if (shouldBeConsumedByChild(e.target, differenceX, differenceY)) {
1015 return;
1016 }
1017
1018 applyTouchMove(differenceX, differenceY);
1019 startOffset = currentOffset;
1020
1021 var currentTime = new Date().getTime();
1022
1023 var timeGap = currentTime - startTime;
1024 if (timeGap > 0) {
1025 speed.x = differenceX / timeGap;
1026 speed.y = differenceY / timeGap;
1027 startTime = currentTime;
1028 }
1029
1030 if (shouldPrevent(differenceX, differenceY)) {
1031 e.preventDefault();
1032 }
1033 }
1034 }
1035 function touchEnd() {
1036 if (i.settings.swipeEasing) {
1037 clearInterval(easingLoop);
1038 easingLoop = setInterval(function() {
1039 if (i.isInitialized) {
1040 clearInterval(easingLoop);
1041 return;
1042 }
1043
1044 if (!speed.x && !speed.y) {
1045 clearInterval(easingLoop);
1046 return;
1047 }
1048
1049 if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) {
1050 clearInterval(easingLoop);
1051 return;
1052 }
1053
1054 applyTouchMove(speed.x * 30, speed.y * 30);
1055
1056 speed.x *= 0.8;
1057 speed.y *= 0.8;
1058 }, 10);
1059 }
1060 }
1061
1062 if (env.supportsTouch) {
1063 i.event.bind(element, 'touchstart', touchStart);
1064 i.event.bind(element, 'touchmove', touchMove);
1065 i.event.bind(element, 'touchend', touchEnd);
1066 } else if (env.supportsIePointer) {
1067 if (window.PointerEvent) {
1068 i.event.bind(element, 'pointerdown', touchStart);
1069 i.event.bind(element, 'pointermove', touchMove);
1070 i.event.bind(element, 'pointerup', touchEnd);
1071 } else if (window.MSPointerEvent) {
1072 i.event.bind(element, 'MSPointerDown', touchStart);
1073 i.event.bind(element, 'MSPointerMove', touchMove);
1074 i.event.bind(element, 'MSPointerUp', touchEnd);
1075 }
1076 }
1077 };
1078
1079 var defaultSettings = function () { return ({
1080 handlers: ['click-rail', 'drag-thumb', 'keyboard', 'wheel', 'touch'],
1081 maxScrollbarLength: null,
1082 minScrollbarLength: null,
1083 scrollingThreshold: 1000,
1084 scrollXMarginOffset: 0,
1085 scrollYMarginOffset: 0,
1086 suppressScrollX: false,
1087 suppressScrollY: false,
1088 swipeEasing: true,
1089 useBothWheelAxes: false,
1090 wheelPropagation: false,
1091 wheelSpeed: 1,
1092 }); };
1093
1094 var handlers = {
1095 'click-rail': clickRail,
1096 'drag-thumb': dragThumb,
1097 keyboard: keyboard,
1098 wheel: wheel,
1099 touch: touch,
1100 };
1101
1102 var PerfectScrollbar = function PerfectScrollbar(element, userSettings) {
1103 var this$1 = this;
1104 if ( userSettings === void 0 ) userSettings = {};
1105
1106 if (typeof element === 'string') {
1107 element = document.querySelector(element);
1108 }
1109
1110 if (!element || !element.nodeName) {
1111 throw new Error('no element is specified to initialize PerfectScrollbar');
1112 }
1113
1114 this.element = element;
1115
1116 element.classList.add(cls.main);
1117
1118 this.settings = defaultSettings();
1119 for (var key in userSettings) {
1120 this$1.settings[key] = userSettings[key];
1121 }
1122
1123 this.containerWidth = null;
1124 this.containerHeight = null;
1125 this.contentWidth = null;
1126 this.contentHeight = null;
1127
1128 var focus = function () { return element.classList.add(cls.state.focus); };
1129 var blur = function () { return element.classList.remove(cls.state.focus); };
1130
1131 this.isRtl = get(element).direction === 'rtl';
1132 this.isNegativeScroll = (function () {
1133 var originalScrollLeft = element.scrollLeft;
1134 var result = null;
1135 element.scrollLeft = -1;
1136 result = element.scrollLeft < 0;
1137 element.scrollLeft = originalScrollLeft;
1138 return result;
1139 })();
1140 this.negativeScrollAdjustment = this.isNegativeScroll
1141 ? element.scrollWidth - element.clientWidth
1142 : 0;
1143 this.event = new EventManager();
1144 this.ownerDocument = element.ownerDocument || document;
1145
1146 this.scrollbarXRail = div(cls.element.rail('x'));
1147 element.appendChild(this.scrollbarXRail);
1148 this.scrollbarX = div(cls.element.thumb('x'));
1149 this.scrollbarXRail.appendChild(this.scrollbarX);
1150 this.scrollbarX.setAttribute('tabindex', 0);
1151 this.event.bind(this.scrollbarX, 'focus', focus);
1152 this.event.bind(this.scrollbarX, 'blur', blur);
1153 this.scrollbarXActive = null;
1154 this.scrollbarXWidth = null;
1155 this.scrollbarXLeft = null;
1156 var railXStyle = get(this.scrollbarXRail);
1157 this.scrollbarXBottom = parseInt(railXStyle.bottom, 10);
1158 if (isNaN(this.scrollbarXBottom)) {
1159 this.isScrollbarXUsingBottom = false;
1160 this.scrollbarXTop = toInt(railXStyle.top);
1161 } else {
1162 this.isScrollbarXUsingBottom = true;
1163 }
1164 this.railBorderXWidth =
1165 toInt(railXStyle.borderLeftWidth) + toInt(railXStyle.borderRightWidth);
1166
1167 set(this.scrollbarXRail, { display: 'block' });
1168 this.railXMarginWidth =
1169 toInt(railXStyle.marginLeft) + toInt(railXStyle.marginRight);
1170 set(this.scrollbarXRail, { display: '' });
1171 this.railXWidth = null;
1172 this.railXRatio = null;
1173
1174 this.scrollbarYRail = div(cls.element.rail('y'));
1175 element.appendChild(this.scrollbarYRail);
1176 this.scrollbarY = div(cls.element.thumb('y'));
1177 this.scrollbarYRail.appendChild(this.scrollbarY);
1178 this.scrollbarY.setAttribute('tabindex', 0);
1179 this.event.bind(this.scrollbarY, 'focus', focus);
1180 this.event.bind(this.scrollbarY, 'blur', blur);
1181 this.scrollbarYActive = null;
1182 this.scrollbarYHeight = null;
1183 this.scrollbarYTop = null;
1184 var railYStyle = get(this.scrollbarYRail);
1185 this.scrollbarYRight = parseInt(railYStyle.right, 10);
1186 if (isNaN(this.scrollbarYRight)) {
1187 this.isScrollbarYUsingRight = false;
1188 this.scrollbarYLeft = toInt(railYStyle.left);
1189 } else {
1190 this.isScrollbarYUsingRight = true;
1191 }
1192 this.scrollbarYOuterWidth = this.isRtl ? outerWidth(this.scrollbarY) : null;
1193 this.railBorderYWidth =
1194 toInt(railYStyle.borderTopWidth) + toInt(railYStyle.borderBottomWidth);
1195 set(this.scrollbarYRail, { display: 'block' });
1196 this.railYMarginHeight =
1197 toInt(railYStyle.marginTop) + toInt(railYStyle.marginBottom);
1198 set(this.scrollbarYRail, { display: '' });
1199 this.railYHeight = null;
1200 this.railYRatio = null;
1201
1202 this.reach = {
1203 x:
1204 element.scrollLeft <= 0
1205 ? 'start'
1206 : element.scrollLeft >= this.contentWidth - this.containerWidth
1207 ? 'end'
1208 : null,
1209 y:
1210 element.scrollTop <= 0
1211 ? 'start'
1212 : element.scrollTop >= this.contentHeight - this.containerHeight
1213 ? 'end'
1214 : null,
1215 };
1216
1217 this.isAlive = true;
1218
1219 this.settings.handlers.forEach(function (handlerName) { return handlers[handlerName](this$1); });
1220
1221 this.lastScrollTop = element.scrollTop;
1222 this.lastScrollLeft = element.scrollLeft;
1223 this.event.bind(this.element, 'scroll', function (e) { return this$1.onScroll(e); });
1224 updateGeometry(this);
1225 };
1226
1227 PerfectScrollbar.prototype.update = function update () {
1228 if (!this.isAlive) {
1229 return;
1230 }
1231
1232
1233 this.negativeScrollAdjustment = this.isNegativeScroll
1234 ? this.element.scrollWidth - this.element.clientWidth
1235 : 0;
1236
1237
1238 set(this.scrollbarXRail, { display: 'block' });
1239 set(this.scrollbarYRail, { display: 'block' });
1240 this.railXMarginWidth =
1241 toInt(get(this.scrollbarXRail).marginLeft) +
1242 toInt(get(this.scrollbarXRail).marginRight);
1243 this.railYMarginHeight =
1244 toInt(get(this.scrollbarYRail).marginTop) +
1245 toInt(get(this.scrollbarYRail).marginBottom);
1246
1247
1248 set(this.scrollbarXRail, { display: 'none' });
1249 set(this.scrollbarYRail, { display: 'none' });
1250
1251 updateGeometry(this);
1252
1253 processScrollDiff(this, 'top', 0, false, true);
1254 processScrollDiff(this, 'left', 0, false, true);
1255
1256 set(this.scrollbarXRail, { display: '' });
1257 set(this.scrollbarYRail, { display: '' });
1258 };
1259
1260 PerfectScrollbar.prototype.onScroll = function onScroll (e) {
1261 if (!this.isAlive) {
1262 return;
1263 }
1264
1265 updateGeometry(this);
1266 processScrollDiff(this, 'top', this.element.scrollTop - this.lastScrollTop);
1267 processScrollDiff(
1268 this,
1269 'left',
1270 this.element.scrollLeft - this.lastScrollLeft
1271 );
1272
1273 this.lastScrollTop = this.element.scrollTop;
1274 this.lastScrollLeft = this.element.scrollLeft;
1275 };
1276
1277 PerfectScrollbar.prototype.destroy = function destroy () {
1278 if (!this.isAlive) {
1279 return;
1280 }
1281
1282 this.event.unbindAll();
1283 remove(this.scrollbarX);
1284 remove(this.scrollbarY);
1285 remove(this.scrollbarXRail);
1286 remove(this.scrollbarYRail);
1287 this.removePsClasses();
1288
1289
1290 this.element = null;
1291 this.scrollbarX = null;
1292 this.scrollbarY = null;
1293 this.scrollbarXRail = null;
1294 this.scrollbarYRail = null;
1295
1296 this.isAlive = false;
1297 };
1298
1299 PerfectScrollbar.prototype.removePsClasses = function removePsClasses () {
1300 this.element.className = this.element.className
1301 .split(' ')
1302 .filter(function (name) { return !name.match(/^ps([-_].+|)$/); })
1303 .join(' ');
1304 };
1305
1306 module.exports = PerfectScrollbar;