/*! * perfect-scrollbar v1.4.0 * (c) 2018 Hyunje Jun * @license MIT */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : typeof define === 'function' && define.amd ? define(factory) : (global.PerfectScrollbar = factory()); }(this, (function () { 'use strict'; function get(element) { return getComputedStyle(element); } function set(element, obj) { for (var key in obj) { var val = obj[key]; if (typeof val === 'number') { val = val + "px"; } element.style[key] = val; } return element; } function div(className) { var div = document.createElement('div'); div.className = className; return div; } var elMatches = typeof Element !== 'undefined' && (Element.prototype.matches || Element.prototype.webkitMatchesSelector || Element.prototype.mozMatchesSelector || Element.prototype.msMatchesSelector); function matches(element, query) { if (!elMatches) { throw new Error('No element matching method supported'); } return elMatches.call(element, query); } function remove(element) { if (element.remove) { element.remove(); } else { if (element.parentNode) { element.parentNode.removeChild(element); } } } function queryChildren(element, selector) { return Array.prototype.filter.call(element.children, function (child) { return matches(child, selector); } ); } var cls = { main: 'ps', element: { thumb: function (x) { return ("ps__thumb-" + x); }, rail: function (x) { return ("ps__rail-" + x); }, consuming: 'ps__child--consume', }, state: { focus: 'ps--focus', clicking: 'ps--clicking', active: function (x) { return ("ps--active-" + x); }, scrolling: function (x) { return ("ps--scrolling-" + x); }, }, }; /* * Helper methods */ var scrollingClassTimeout = { x: null, y: null }; function addScrollingClass(i, x) { var classList = i.element.classList; var className = cls.state.scrolling(x); if (classList.contains(className)) { clearTimeout(scrollingClassTimeout[x]); } else { classList.add(className); } } function removeScrollingClass(i, x) { scrollingClassTimeout[x] = setTimeout( function () { return i.isAlive && i.element.classList.remove(cls.state.scrolling(x)); }, i.settings.scrollingThreshold ); } function setScrollingClassInstantly(i, x) { addScrollingClass(i, x); removeScrollingClass(i, x); } var EventElement = function EventElement(element) { this.element = element; this.handlers = {}; }; var prototypeAccessors = { isEmpty: { configurable: true } }; EventElement.prototype.bind = function bind (eventName, handler) { if (typeof this.handlers[eventName] === 'undefined') { this.handlers[eventName] = []; } this.handlers[eventName].push(handler); this.element.addEventListener(eventName, handler, false); }; EventElement.prototype.unbind = function unbind (eventName, target) { var this$1 = this; this.handlers[eventName] = this.handlers[eventName].filter(function (handler) { if (target && handler !== target) { return true; } this$1.element.removeEventListener(eventName, handler, false); return false; }); }; EventElement.prototype.unbindAll = function unbindAll () { var this$1 = this; for (var name in this$1.handlers) { this$1.unbind(name); } }; prototypeAccessors.isEmpty.get = function () { var this$1 = this; return Object.keys(this.handlers).every( function (key) { return this$1.handlers[key].length === 0; } ); }; Object.defineProperties( EventElement.prototype, prototypeAccessors ); var EventManager = function EventManager() { this.eventElements = []; }; EventManager.prototype.eventElement = function eventElement (element) { var ee = this.eventElements.filter(function (ee) { return ee.element === element; })[0]; if (!ee) { ee = new EventElement(element); this.eventElements.push(ee); } return ee; }; EventManager.prototype.bind = function bind (element, eventName, handler) { this.eventElement(element).bind(eventName, handler); }; EventManager.prototype.unbind = function unbind (element, eventName, handler) { var ee = this.eventElement(element); ee.unbind(eventName, handler); if (ee.isEmpty) { // remove this.eventElements.splice(this.eventElements.indexOf(ee), 1); } }; EventManager.prototype.unbindAll = function unbindAll () { this.eventElements.forEach(function (e) { return e.unbindAll(); }); this.eventElements = []; }; EventManager.prototype.once = function once (element, eventName, handler) { var ee = this.eventElement(element); var onceHandler = function (evt) { ee.unbind(eventName, onceHandler); handler(evt); }; ee.bind(eventName, onceHandler); }; function createEvent(name) { if (typeof window.CustomEvent === 'function') { return new CustomEvent(name); } else { var evt = document.createEvent('CustomEvent'); evt.initCustomEvent(name, false, false, undefined); return evt; } } var processScrollDiff = function( i, axis, diff, useScrollingClass, forceFireReachEvent ) { if ( useScrollingClass === void 0 ) useScrollingClass = true; if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false; var fields; if (axis === 'top') { fields = [ 'contentHeight', 'containerHeight', 'scrollTop', 'y', 'up', 'down' ]; } else if (axis === 'left') { fields = [ 'contentWidth', 'containerWidth', 'scrollLeft', 'x', 'left', 'right' ]; } else { throw new Error('A proper axis should be provided'); } processScrollDiff$1(i, diff, fields, useScrollingClass, forceFireReachEvent); }; function processScrollDiff$1( i, diff, ref, useScrollingClass, forceFireReachEvent ) { var contentHeight = ref[0]; var containerHeight = ref[1]; var scrollTop = ref[2]; var y = ref[3]; var up = ref[4]; var down = ref[5]; if ( useScrollingClass === void 0 ) useScrollingClass = true; if ( forceFireReachEvent === void 0 ) forceFireReachEvent = false; var element = i.element; // reset reach i.reach[y] = null; // 1 for subpixel rounding if (element[scrollTop] < 1) { i.reach[y] = 'start'; } // 1 for subpixel rounding if (element[scrollTop] > i[contentHeight] - i[containerHeight] - 1) { i.reach[y] = 'end'; } if (diff) { element.dispatchEvent(createEvent(("ps-scroll-" + y))); if (diff < 0) { element.dispatchEvent(createEvent(("ps-scroll-" + up))); } else if (diff > 0) { element.dispatchEvent(createEvent(("ps-scroll-" + down))); } if (useScrollingClass) { setScrollingClassInstantly(i, y); } } if (i.reach[y] && (diff || forceFireReachEvent)) { element.dispatchEvent(createEvent(("ps-" + y + "-reach-" + (i.reach[y])))); } } function toInt(x) { return parseInt(x, 10) || 0; } function isEditable(el) { return ( matches(el, 'input,[contenteditable]') || matches(el, 'select,[contenteditable]') || matches(el, 'textarea,[contenteditable]') || matches(el, 'button,[contenteditable]') ); } function outerWidth(element) { var styles = get(element); return ( toInt(styles.width) + toInt(styles.paddingLeft) + toInt(styles.paddingRight) + toInt(styles.borderLeftWidth) + toInt(styles.borderRightWidth) ); } var env = { isWebKit: typeof document !== 'undefined' && 'WebkitAppearance' in document.documentElement.style, supportsTouch: typeof window !== 'undefined' && ('ontouchstart' in window || (window.DocumentTouch && document instanceof window.DocumentTouch)), supportsIePointer: typeof navigator !== 'undefined' && navigator.msMaxTouchPoints, isChrome: typeof navigator !== 'undefined' && /Chrome/i.test(navigator && navigator.userAgent), }; var updateGeometry = function(i) { var element = i.element; var roundedScrollTop = Math.floor(element.scrollTop); i.containerWidth = element.clientWidth; i.containerHeight = element.clientHeight; i.contentWidth = element.scrollWidth; i.contentHeight = element.scrollHeight; if (!element.contains(i.scrollbarXRail)) { // clean up and append queryChildren(element, cls.element.rail('x')).forEach(function (el) { return remove(el); } ); element.appendChild(i.scrollbarXRail); } if (!element.contains(i.scrollbarYRail)) { // clean up and append queryChildren(element, cls.element.rail('y')).forEach(function (el) { return remove(el); } ); element.appendChild(i.scrollbarYRail); } if ( !i.settings.suppressScrollX && i.containerWidth + i.settings.scrollXMarginOffset < i.contentWidth ) { i.scrollbarXActive = true; i.railXWidth = i.containerWidth - i.railXMarginWidth; i.railXRatio = i.containerWidth / i.railXWidth; i.scrollbarXWidth = getThumbSize( i, toInt(i.railXWidth * i.containerWidth / i.contentWidth) ); i.scrollbarXLeft = toInt( (i.negativeScrollAdjustment + element.scrollLeft) * (i.railXWidth - i.scrollbarXWidth) / (i.contentWidth - i.containerWidth) ); } else { i.scrollbarXActive = false; } if ( !i.settings.suppressScrollY && i.containerHeight + i.settings.scrollYMarginOffset < i.contentHeight ) { i.scrollbarYActive = true; i.railYHeight = i.containerHeight - i.railYMarginHeight; i.railYRatio = i.containerHeight / i.railYHeight; i.scrollbarYHeight = getThumbSize( i, toInt(i.railYHeight * i.containerHeight / i.contentHeight) ); i.scrollbarYTop = toInt( roundedScrollTop * (i.railYHeight - i.scrollbarYHeight) / (i.contentHeight - i.containerHeight) ); } else { i.scrollbarYActive = false; } if (i.scrollbarXLeft >= i.railXWidth - i.scrollbarXWidth) { i.scrollbarXLeft = i.railXWidth - i.scrollbarXWidth; } if (i.scrollbarYTop >= i.railYHeight - i.scrollbarYHeight) { i.scrollbarYTop = i.railYHeight - i.scrollbarYHeight; } updateCss(element, i); if (i.scrollbarXActive) { element.classList.add(cls.state.active('x')); } else { element.classList.remove(cls.state.active('x')); i.scrollbarXWidth = 0; i.scrollbarXLeft = 0; element.scrollLeft = 0; } if (i.scrollbarYActive) { element.classList.add(cls.state.active('y')); } else { element.classList.remove(cls.state.active('y')); i.scrollbarYHeight = 0; i.scrollbarYTop = 0; element.scrollTop = 0; } }; function getThumbSize(i, thumbSize) { if (i.settings.minScrollbarLength) { thumbSize = Math.max(thumbSize, i.settings.minScrollbarLength); } if (i.settings.maxScrollbarLength) { thumbSize = Math.min(thumbSize, i.settings.maxScrollbarLength); } return thumbSize; } function updateCss(element, i) { var xRailOffset = { width: i.railXWidth }; var roundedScrollTop = Math.floor(element.scrollTop); if (i.isRtl) { xRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth - i.contentWidth; } else { xRailOffset.left = element.scrollLeft; } if (i.isScrollbarXUsingBottom) { xRailOffset.bottom = i.scrollbarXBottom - roundedScrollTop; } else { xRailOffset.top = i.scrollbarXTop + roundedScrollTop; } set(i.scrollbarXRail, xRailOffset); var yRailOffset = { top: roundedScrollTop, height: i.railYHeight }; if (i.isScrollbarYUsingRight) { if (i.isRtl) { yRailOffset.right = i.contentWidth - (i.negativeScrollAdjustment + element.scrollLeft) - i.scrollbarYRight - i.scrollbarYOuterWidth; } else { yRailOffset.right = i.scrollbarYRight - element.scrollLeft; } } else { if (i.isRtl) { yRailOffset.left = i.negativeScrollAdjustment + element.scrollLeft + i.containerWidth * 2 - i.contentWidth - i.scrollbarYLeft - i.scrollbarYOuterWidth; } else { yRailOffset.left = i.scrollbarYLeft + element.scrollLeft; } } set(i.scrollbarYRail, yRailOffset); set(i.scrollbarX, { left: i.scrollbarXLeft, width: i.scrollbarXWidth - i.railBorderXWidth, }); set(i.scrollbarY, { top: i.scrollbarYTop, height: i.scrollbarYHeight - i.railBorderYWidth, }); } var clickRail = function(i) { i.event.bind(i.scrollbarY, 'mousedown', function (e) { return e.stopPropagation(); }); i.event.bind(i.scrollbarYRail, 'mousedown', function (e) { var positionTop = e.pageY - window.pageYOffset - i.scrollbarYRail.getBoundingClientRect().top; var direction = positionTop > i.scrollbarYTop ? 1 : -1; i.element.scrollTop += direction * i.containerHeight; updateGeometry(i); e.stopPropagation(); }); i.event.bind(i.scrollbarX, 'mousedown', function (e) { return e.stopPropagation(); }); i.event.bind(i.scrollbarXRail, 'mousedown', function (e) { var positionLeft = e.pageX - window.pageXOffset - i.scrollbarXRail.getBoundingClientRect().left; var direction = positionLeft > i.scrollbarXLeft ? 1 : -1; i.element.scrollLeft += direction * i.containerWidth; updateGeometry(i); e.stopPropagation(); }); }; var dragThumb = function(i) { bindMouseScrollHandler(i, [ 'containerWidth', 'contentWidth', 'pageX', 'railXWidth', 'scrollbarX', 'scrollbarXWidth', 'scrollLeft', 'x', 'scrollbarXRail' ]); bindMouseScrollHandler(i, [ 'containerHeight', 'contentHeight', 'pageY', 'railYHeight', 'scrollbarY', 'scrollbarYHeight', 'scrollTop', 'y', 'scrollbarYRail' ]); }; function bindMouseScrollHandler( i, ref ) { var containerHeight = ref[0]; var contentHeight = ref[1]; var pageY = ref[2]; var railYHeight = ref[3]; var scrollbarY = ref[4]; var scrollbarYHeight = ref[5]; var scrollTop = ref[6]; var y = ref[7]; var scrollbarYRail = ref[8]; var element = i.element; var startingScrollTop = null; var startingMousePageY = null; var scrollBy = null; function mouseMoveHandler(e) { element[scrollTop] = startingScrollTop + scrollBy * (e[pageY] - startingMousePageY); addScrollingClass(i, y); updateGeometry(i); e.stopPropagation(); e.preventDefault(); } function mouseUpHandler() { removeScrollingClass(i, y); i[scrollbarYRail].classList.remove(cls.state.clicking); i.event.unbind(i.ownerDocument, 'mousemove', mouseMoveHandler); } i.event.bind(i[scrollbarY], 'mousedown', function (e) { startingScrollTop = element[scrollTop]; startingMousePageY = e[pageY]; scrollBy = (i[contentHeight] - i[containerHeight]) / (i[railYHeight] - i[scrollbarYHeight]); i.event.bind(i.ownerDocument, 'mousemove', mouseMoveHandler); i.event.once(i.ownerDocument, 'mouseup', mouseUpHandler); i[scrollbarYRail].classList.add(cls.state.clicking); e.stopPropagation(); e.preventDefault(); }); } var keyboard = function(i) { var element = i.element; var elementHovered = function () { return matches(element, ':hover'); }; var scrollbarFocused = function () { return matches(i.scrollbarX, ':focus') || matches(i.scrollbarY, ':focus'); }; function shouldPreventDefault(deltaX, deltaY) { var scrollTop = Math.floor(element.scrollTop); if (deltaX === 0) { if (!i.scrollbarYActive) { return false; } if ( (scrollTop === 0 && deltaY > 0) || (scrollTop >= i.contentHeight - i.containerHeight && deltaY < 0) ) { return !i.settings.wheelPropagation; } } var scrollLeft = element.scrollLeft; if (deltaY === 0) { if (!i.scrollbarXActive) { return false; } if ( (scrollLeft === 0 && deltaX < 0) || (scrollLeft >= i.contentWidth - i.containerWidth && deltaX > 0) ) { return !i.settings.wheelPropagation; } } return true; } i.event.bind(i.ownerDocument, 'keydown', function (e) { if ( (e.isDefaultPrevented && e.isDefaultPrevented()) || e.defaultPrevented ) { return; } if (!elementHovered() && !scrollbarFocused()) { return; } var activeElement = document.activeElement ? document.activeElement : i.ownerDocument.activeElement; if (activeElement) { if (activeElement.tagName === 'IFRAME') { activeElement = activeElement.contentDocument.activeElement; } else { // go deeper if element is a webcomponent while (activeElement.shadowRoot) { activeElement = activeElement.shadowRoot.activeElement; } } if (isEditable(activeElement)) { return; } } var deltaX = 0; var deltaY = 0; switch (e.which) { case 37: // left if (e.metaKey) { deltaX = -i.contentWidth; } else if (e.altKey) { deltaX = -i.containerWidth; } else { deltaX = -30; } break; case 38: // up if (e.metaKey) { deltaY = i.contentHeight; } else if (e.altKey) { deltaY = i.containerHeight; } else { deltaY = 30; } break; case 39: // right if (e.metaKey) { deltaX = i.contentWidth; } else if (e.altKey) { deltaX = i.containerWidth; } else { deltaX = 30; } break; case 40: // down if (e.metaKey) { deltaY = -i.contentHeight; } else if (e.altKey) { deltaY = -i.containerHeight; } else { deltaY = -30; } break; case 32: // space bar if (e.shiftKey) { deltaY = i.containerHeight; } else { deltaY = -i.containerHeight; } break; case 33: // page up deltaY = i.containerHeight; break; case 34: // page down deltaY = -i.containerHeight; break; case 36: // home deltaY = i.contentHeight; break; case 35: // end deltaY = -i.contentHeight; break; default: return; } if (i.settings.suppressScrollX && deltaX !== 0) { return; } if (i.settings.suppressScrollY && deltaY !== 0) { return; } element.scrollTop -= deltaY; element.scrollLeft += deltaX; updateGeometry(i); if (shouldPreventDefault(deltaX, deltaY)) { e.preventDefault(); } }); }; var wheel = function(i) { var element = i.element; function shouldPreventDefault(deltaX, deltaY) { var roundedScrollTop = Math.floor(element.scrollTop); var isTop = element.scrollTop === 0; var isBottom = roundedScrollTop + element.offsetHeight === element.scrollHeight; var isLeft = element.scrollLeft === 0; var isRight = element.scrollLeft + element.offsetWidth === element.scrollWidth; var hitsBound; // pick axis with primary direction if (Math.abs(deltaY) > Math.abs(deltaX)) { hitsBound = isTop || isBottom; } else { hitsBound = isLeft || isRight; } return hitsBound ? !i.settings.wheelPropagation : true; } function getDeltaFromEvent(e) { var deltaX = e.deltaX; var deltaY = -1 * e.deltaY; if (typeof deltaX === 'undefined' || typeof deltaY === 'undefined') { // OS X Safari deltaX = -1 * e.wheelDeltaX / 6; deltaY = e.wheelDeltaY / 6; } if (e.deltaMode && e.deltaMode === 1) { // Firefox in deltaMode 1: Line scrolling deltaX *= 10; deltaY *= 10; } if (deltaX !== deltaX && deltaY !== deltaY /* NaN checks */) { // IE in some mouse drivers deltaX = 0; deltaY = e.wheelDelta; } if (e.shiftKey) { // reverse axis with shift key return [-deltaY, -deltaX]; } return [deltaX, deltaY]; } function shouldBeConsumedByChild(target, deltaX, deltaY) { // FIXME: this is a workaround for <select> issue in FF and IE #571 if (!env.isWebKit && element.querySelector('select:focus')) { return true; } if (!element.contains(target)) { return false; } var cursor = target; while (cursor && cursor !== element) { if (cursor.classList.contains(cls.element.consuming)) { return true; } var style = get(cursor); var overflow = [style.overflow, style.overflowX, style.overflowY].join( '' ); // if scrollable if (overflow.match(/(scroll|auto)/)) { var maxScrollTop = cursor.scrollHeight - cursor.clientHeight; if (maxScrollTop > 0) { if ( !(cursor.scrollTop === 0 && deltaY > 0) && !(cursor.scrollTop === maxScrollTop && deltaY < 0) ) { return true; } } var maxScrollLeft = cursor.scrollWidth - cursor.clientWidth; if (maxScrollLeft > 0) { if ( !(cursor.scrollLeft === 0 && deltaX < 0) && !(cursor.scrollLeft === maxScrollLeft && deltaX > 0) ) { return true; } } } cursor = cursor.parentNode; } return false; } function mousewheelHandler(e) { var ref = getDeltaFromEvent(e); var deltaX = ref[0]; var deltaY = ref[1]; if (shouldBeConsumedByChild(e.target, deltaX, deltaY)) { return; } var shouldPrevent = false; if (!i.settings.useBothWheelAxes) { // deltaX will only be used for horizontal scrolling and deltaY will // only be used for vertical scrolling - this is the default element.scrollTop -= deltaY * i.settings.wheelSpeed; element.scrollLeft += deltaX * i.settings.wheelSpeed; } else if (i.scrollbarYActive && !i.scrollbarXActive) { // only vertical scrollbar is active and useBothWheelAxes option is // active, so let's scroll vertical bar using both mouse wheel axes if (deltaY) { element.scrollTop -= deltaY * i.settings.wheelSpeed; } else { element.scrollTop += deltaX * i.settings.wheelSpeed; } shouldPrevent = true; } else if (i.scrollbarXActive && !i.scrollbarYActive) { // useBothWheelAxes and only horizontal bar is active, so use both // wheel axes for horizontal bar if (deltaX) { element.scrollLeft += deltaX * i.settings.wheelSpeed; } else { element.scrollLeft -= deltaY * i.settings.wheelSpeed; } shouldPrevent = true; } updateGeometry(i); shouldPrevent = shouldPrevent || shouldPreventDefault(deltaX, deltaY); if (shouldPrevent && !e.ctrlKey) { e.stopPropagation(); e.preventDefault(); } } if (typeof window.onwheel !== 'undefined') { i.event.bind(element, 'wheel', mousewheelHandler); } else if (typeof window.onmousewheel !== 'undefined') { i.event.bind(element, 'mousewheel', mousewheelHandler); } }; var touch = function(i) { if (!env.supportsTouch && !env.supportsIePointer) { return; } var element = i.element; function shouldPrevent(deltaX, deltaY) { var scrollTop = Math.floor(element.scrollTop); var scrollLeft = element.scrollLeft; var magnitudeX = Math.abs(deltaX); var magnitudeY = Math.abs(deltaY); if (magnitudeY > magnitudeX) { // user is perhaps trying to swipe up/down the page if ( (deltaY < 0 && scrollTop === i.contentHeight - i.containerHeight) || (deltaY > 0 && scrollTop === 0) ) { // set prevent for mobile Chrome refresh return window.scrollY === 0 && deltaY > 0 && env.isChrome; } } else if (magnitudeX > magnitudeY) { // user is perhaps trying to swipe left/right across the page if ( (deltaX < 0 && scrollLeft === i.contentWidth - i.containerWidth) || (deltaX > 0 && scrollLeft === 0) ) { return true; } } return true; } function applyTouchMove(differenceX, differenceY) { element.scrollTop -= differenceY; element.scrollLeft -= differenceX; updateGeometry(i); } var startOffset = {}; var startTime = 0; var speed = {}; var easingLoop = null; function getTouch(e) { if (e.targetTouches) { return e.targetTouches[0]; } else { // Maybe IE pointer return e; } } function shouldHandle(e) { if (e.pointerType && e.pointerType === 'pen' && e.buttons === 0) { return false; } if (e.targetTouches && e.targetTouches.length === 1) { return true; } if ( e.pointerType && e.pointerType !== 'mouse' && e.pointerType !== e.MSPOINTER_TYPE_MOUSE ) { return true; } return false; } function touchStart(e) { if (!shouldHandle(e)) { return; } var touch = getTouch(e); startOffset.pageX = touch.pageX; startOffset.pageY = touch.pageY; startTime = new Date().getTime(); if (easingLoop !== null) { clearInterval(easingLoop); } } function shouldBeConsumedByChild(target, deltaX, deltaY) { if (!element.contains(target)) { return false; } var cursor = target; while (cursor && cursor !== element) { if (cursor.classList.contains(cls.element.consuming)) { return true; } var style = get(cursor); var overflow = [style.overflow, style.overflowX, style.overflowY].join( '' ); // if scrollable if (overflow.match(/(scroll|auto)/)) { var maxScrollTop = cursor.scrollHeight - cursor.clientHeight; if (maxScrollTop > 0) { if ( !(cursor.scrollTop === 0 && deltaY > 0) && !(cursor.scrollTop === maxScrollTop && deltaY < 0) ) { return true; } } var maxScrollLeft = cursor.scrollLeft - cursor.clientWidth; if (maxScrollLeft > 0) { if ( !(cursor.scrollLeft === 0 && deltaX < 0) && !(cursor.scrollLeft === maxScrollLeft && deltaX > 0) ) { return true; } } } cursor = cursor.parentNode; } return false; } function touchMove(e) { if (shouldHandle(e)) { var touch = getTouch(e); var currentOffset = { pageX: touch.pageX, pageY: touch.pageY }; var differenceX = currentOffset.pageX - startOffset.pageX; var differenceY = currentOffset.pageY - startOffset.pageY; if (shouldBeConsumedByChild(e.target, differenceX, differenceY)) { return; } applyTouchMove(differenceX, differenceY); startOffset = currentOffset; var currentTime = new Date().getTime(); var timeGap = currentTime - startTime; if (timeGap > 0) { speed.x = differenceX / timeGap; speed.y = differenceY / timeGap; startTime = currentTime; } if (shouldPrevent(differenceX, differenceY)) { e.preventDefault(); } } } function touchEnd() { if (i.settings.swipeEasing) { clearInterval(easingLoop); easingLoop = setInterval(function() { if (i.isInitialized) { clearInterval(easingLoop); return; } if (!speed.x && !speed.y) { clearInterval(easingLoop); return; } if (Math.abs(speed.x) < 0.01 && Math.abs(speed.y) < 0.01) { clearInterval(easingLoop); return; } applyTouchMove(speed.x * 30, speed.y * 30); speed.x *= 0.8; speed.y *= 0.8; }, 10); } } if (env.supportsTouch) { i.event.bind(element, 'touchstart', touchStart); i.event.bind(element, 'touchmove', touchMove); i.event.bind(element, 'touchend', touchEnd); } else if (env.supportsIePointer) { if (window.PointerEvent) { i.event.bind(element, 'pointerdown', touchStart); i.event.bind(element, 'pointermove', touchMove); i.event.bind(element, 'pointerup', touchEnd); } else if (window.MSPointerEvent) { i.event.bind(element, 'MSPointerDown', touchStart); i.event.bind(element, 'MSPointerMove', touchMove); i.event.bind(element, 'MSPointerUp', touchEnd); } } }; var defaultSettings = function () { return ({ handlers: ['click-rail', 'drag-thumb', 'keyboard', 'wheel', 'touch'], maxScrollbarLength: null, minScrollbarLength: null, scrollingThreshold: 1000, scrollXMarginOffset: 0, scrollYMarginOffset: 0, suppressScrollX: false, suppressScrollY: false, swipeEasing: true, useBothWheelAxes: false, wheelPropagation: true, wheelSpeed: 1, }); }; var handlers = { 'click-rail': clickRail, 'drag-thumb': dragThumb, keyboard: keyboard, wheel: wheel, touch: touch, }; var PerfectScrollbar = function PerfectScrollbar(element, userSettings) { var this$1 = this; if ( userSettings === void 0 ) userSettings = {}; if (typeof element === 'string') { element = document.querySelector(element); } if (!element || !element.nodeName) { throw new Error('no element is specified to initialize PerfectScrollbar'); } this.element = element; element.classList.add(cls.main); this.settings = defaultSettings(); for (var key in userSettings) { this$1.settings[key] = userSettings[key]; } this.containerWidth = null; this.containerHeight = null; this.contentWidth = null; this.contentHeight = null; var focus = function () { return element.classList.add(cls.state.focus); }; var blur = function () { return element.classList.remove(cls.state.focus); }; this.isRtl = get(element).direction === 'rtl'; this.isNegativeScroll = (function () { var originalScrollLeft = element.scrollLeft; var result = null; element.scrollLeft = -1; result = element.scrollLeft < 0; element.scrollLeft = originalScrollLeft; return result; })(); this.negativeScrollAdjustment = this.isNegativeScroll ? element.scrollWidth - element.clientWidth : 0; this.event = new EventManager(); this.ownerDocument = element.ownerDocument || document; this.scrollbarXRail = div(cls.element.rail('x')); element.appendChild(this.scrollbarXRail); this.scrollbarX = div(cls.element.thumb('x')); this.scrollbarXRail.appendChild(this.scrollbarX); this.scrollbarX.setAttribute('tabindex', 0); this.event.bind(this.scrollbarX, 'focus', focus); this.event.bind(this.scrollbarX, 'blur', blur); this.scrollbarXActive = null; this.scrollbarXWidth = null; this.scrollbarXLeft = null; var railXStyle = get(this.scrollbarXRail); this.scrollbarXBottom = parseInt(railXStyle.bottom, 10); if (isNaN(this.scrollbarXBottom)) { this.isScrollbarXUsingBottom = false; this.scrollbarXTop = toInt(railXStyle.top); } else { this.isScrollbarXUsingBottom = true; } this.railBorderXWidth = toInt(railXStyle.borderLeftWidth) + toInt(railXStyle.borderRightWidth); // Set rail to display:block to calculate margins set(this.scrollbarXRail, { display: 'block' }); this.railXMarginWidth = toInt(railXStyle.marginLeft) + toInt(railXStyle.marginRight); set(this.scrollbarXRail, { display: '' }); this.railXWidth = null; this.railXRatio = null; this.scrollbarYRail = div(cls.element.rail('y')); element.appendChild(this.scrollbarYRail); this.scrollbarY = div(cls.element.thumb('y')); this.scrollbarYRail.appendChild(this.scrollbarY); this.scrollbarY.setAttribute('tabindex', 0); this.event.bind(this.scrollbarY, 'focus', focus); this.event.bind(this.scrollbarY, 'blur', blur); this.scrollbarYActive = null; this.scrollbarYHeight = null; this.scrollbarYTop = null; var railYStyle = get(this.scrollbarYRail); this.scrollbarYRight = parseInt(railYStyle.right, 10); if (isNaN(this.scrollbarYRight)) { this.isScrollbarYUsingRight = false; this.scrollbarYLeft = toInt(railYStyle.left); } else { this.isScrollbarYUsingRight = true; } this.scrollbarYOuterWidth = this.isRtl ? outerWidth(this.scrollbarY) : null; this.railBorderYWidth = toInt(railYStyle.borderTopWidth) + toInt(railYStyle.borderBottomWidth); set(this.scrollbarYRail, { display: 'block' }); this.railYMarginHeight = toInt(railYStyle.marginTop) + toInt(railYStyle.marginBottom); set(this.scrollbarYRail, { display: '' }); this.railYHeight = null; this.railYRatio = null; this.reach = { x: element.scrollLeft <= 0 ? 'start' : element.scrollLeft >= this.contentWidth - this.containerWidth ? 'end' : null, y: element.scrollTop <= 0 ? 'start' : element.scrollTop >= this.contentHeight - this.containerHeight ? 'end' : null, }; this.isAlive = true; this.settings.handlers.forEach(function (handlerName) { return handlers[handlerName](this$1); }); this.lastScrollTop = Math.floor(element.scrollTop); // for onScroll only this.lastScrollLeft = element.scrollLeft; // for onScroll only this.event.bind(this.element, 'scroll', function (e) { return this$1.onScroll(e); }); updateGeometry(this); }; PerfectScrollbar.prototype.update = function update () { if (!this.isAlive) { return; } // Recalcuate negative scrollLeft adjustment this.negativeScrollAdjustment = this.isNegativeScroll ? this.element.scrollWidth - this.element.clientWidth : 0; // Recalculate rail margins set(this.scrollbarXRail, { display: 'block' }); set(this.scrollbarYRail, { display: 'block' }); this.railXMarginWidth = toInt(get(this.scrollbarXRail).marginLeft) + toInt(get(this.scrollbarXRail).marginRight); this.railYMarginHeight = toInt(get(this.scrollbarYRail).marginTop) + toInt(get(this.scrollbarYRail).marginBottom); // Hide scrollbars not to affect scrollWidth and scrollHeight set(this.scrollbarXRail, { display: 'none' }); set(this.scrollbarYRail, { display: 'none' }); updateGeometry(this); processScrollDiff(this, 'top', 0, false, true); processScrollDiff(this, 'left', 0, false, true); set(this.scrollbarXRail, { display: '' }); set(this.scrollbarYRail, { display: '' }); }; PerfectScrollbar.prototype.onScroll = function onScroll (e) { if (!this.isAlive) { return; } updateGeometry(this); processScrollDiff(this, 'top', this.element.scrollTop - this.lastScrollTop); processScrollDiff( this, 'left', this.element.scrollLeft - this.lastScrollLeft ); this.lastScrollTop = Math.floor(this.element.scrollTop); this.lastScrollLeft = this.element.scrollLeft; }; PerfectScrollbar.prototype.destroy = function destroy () { if (!this.isAlive) { return; } this.event.unbindAll(); remove(this.scrollbarX); remove(this.scrollbarY); remove(this.scrollbarXRail); remove(this.scrollbarYRail); this.removePsClasses(); // unset elements this.element = null; this.scrollbarX = null; this.scrollbarY = null; this.scrollbarXRail = null; this.scrollbarYRail = null; this.isAlive = false; }; PerfectScrollbar.prototype.removePsClasses = function removePsClasses () { this.element.className = this.element.className .split(' ') .filter(function (name) { return !name.match(/^ps([-_].+|)$/); }) .join(' '); }; return PerfectScrollbar; })));