Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-04-09 07:58:30

0001 /*!

0002  * perfect-scrollbar v1.3.0

0003  * (c) 2017 Hyunje Jun

0004  * @license MIT

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  * Helper methods

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     // remove

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   // reset reach

0249   i.reach[y] = null;
0250 
0251   // 1 for subpixel rounding

0252   if (element[scrollTop] < 1) {
0253     i.reach[y] = 'start';
0254   }
0255 
0256   // 1 for subpixel rounding

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     // clean up and append

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     // clean up and append

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         // go deeper if element is a webcomponent

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: // left

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: // up

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: // right

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: // down

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: // space bar

0676         if (e.shiftKey) {
0677           deltaY = i.containerHeight;
0678         } else {
0679           deltaY = -i.containerHeight;
0680         }
0681         break;
0682       case 33: // page up

0683         deltaY = i.containerHeight;
0684         break;
0685       case 34: // page down

0686         deltaY = -i.containerHeight;
0687         break;
0688       case 36: // home

0689         deltaY = i.contentHeight;
0690         break;
0691       case 35: // end

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     // pick axis with primary direction

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       // OS X Safari

0744       deltaX = -1 * e.wheelDeltaX / 6;
0745       deltaY = e.wheelDeltaY / 6;
0746     }
0747 
0748     if (e.deltaMode && e.deltaMode === 1) {
0749       // Firefox in deltaMode 1: Line scrolling

0750       deltaX *= 10;
0751       deltaY *= 10;
0752     }
0753 
0754     if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) {
0755       // IE in some mouse drivers

0756       deltaX = 0;
0757       deltaY = e.wheelDelta;
0758     }
0759 
0760     if (e.shiftKey) {
0761       // reverse axis with shift key

0762       return [-deltaY, -deltaX];
0763     }
0764     return [deltaX, deltaY];
0765   }
0766 
0767   function shouldBeConsumedByChild(target, deltaX, deltaY) {
0768     // FIXME: this is a workaround for <select> issue in FF and IE #571

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       // if scrollable

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       // deltaX will only be used for horizontal scrolling and deltaY will

0829       // only be used for vertical scrolling - this is the default

0830       element.scrollTop -= deltaY * i.settings.wheelSpeed;
0831       element.scrollLeft += deltaX * i.settings.wheelSpeed;
0832     } else if (i.scrollbarYActive && !i.scrollbarXActive) {
0833       // only vertical scrollbar is active and useBothWheelAxes option is

0834       // active, so let's scroll vertical bar using both mouse wheel axes

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       // useBothWheelAxes and only horizontal bar is active, so use both

0843       // wheel axes for horizontal bar

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       // user is perhaps trying to swipe up/down the page

0883 
0884       if (
0885         (deltaY < 0 && scrollTop === i.contentHeight - i.containerHeight) ||
0886         (deltaY > 0 && scrollTop === 0)
0887       ) {
0888         // set prevent for mobile Chrome refresh

0889         return window.scrollY === 0 && deltaY > 0 && env.isChrome;
0890       }
0891     } else if (magnitudeX > magnitudeY) {
0892       // user is perhaps trying to swipe left/right across the page

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       // Maybe IE pointer

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       // if scrollable

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   // Set rail to display:block to calculate margins

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; // for onScroll only

1222   this.lastScrollLeft = element.scrollLeft; // for onScroll only

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   // Recalcuate negative scrollLeft adjustment

1233   this.negativeScrollAdjustment = this.isNegativeScroll
1234     ? this.element.scrollWidth - this.element.clientWidth
1235     : 0;
1236 
1237   // Recalculate rail margins

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   // Hide scrollbars not to affect scrollWidth and scrollHeight

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   // unset elements

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;