/* * Vuescroll v4.16.1 * (c) 2018-2020 Yi(Yves) Wang * Released under the MIT License * Github: https://github.com/YvesCoding/vuescroll * Website: http://vuescrolljs.yvescoding.org/ */ (function (global, factory) { typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory(require('vue')) : typeof define === 'function' && define.amd ? define(['vue'], factory) : (global.vuescroll = factory(global.Vue)); }(this, (function (Vue) { 'use strict'; Vue = Vue && Vue.hasOwnProperty('default') ? Vue['default'] : Vue; var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; var classCallCheck = function (instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }; var createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); var defineProperty = function (obj, key, value) { if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }; var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; var toConsumableArray = function (arr) { if (Array.isArray(arr)) { for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) arr2[i] = arr[i]; return arr2; } else { return Array.from(arr); } }; function isIE() { /* istanbul ignore if */ if (isServer()) return false; var agent = navigator.userAgent.toLowerCase(); return agent.indexOf('msie') !== -1 || agent.indexOf('trident') !== -1 || agent.indexOf(' edge/') !== -1; } var isIos = function isIos() { /* istanbul ignore if */ if (isServer()) return false; var u = navigator.userAgent; return !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); }; /* istanbul ignore next */ var isServer = function isServer() { return Vue.prototype.$isServer; }; var touchManager = function () { function touchManager() { classCallCheck(this, touchManager); } createClass(touchManager, [{ key: 'getEventObject', value: function getEventObject(originEvent) { return this.touchObject ? this.isTouch ? originEvent.touches : [originEvent] : null; } }, { key: 'getTouchObject', value: function getTouchObject() /* istanbul ignore next */{ if (isServer()) return null; this.isTouch = false; var agent = navigator.userAgent, platform = navigator.platform, touchObject = {}; touchObject.touch = !!('ontouchstart' in window && !window.opera || 'msmaxtouchpoints' in window.navigator || 'maxtouchpoints' in window.navigator || navigator.maxTouchPoints > 0 || navigator.msMaxTouchPoints > 0); touchObject.nonDeskTouch = touchObject.touch && !/win32/i.test(platform) || touchObject.touch && /win32/i.test(platform) && /mobile/i.test(agent); touchObject.eventType = 'onmousedown' in window && !touchObject.nonDeskTouch ? 'mouse' : 'ontouchstart' in window ? 'touch' : 'msmaxtouchpoints' in window.navigator || navigator.msMaxTouchPoints > 0 ? 'mstouchpoints' : 'maxtouchpoints' in window.navigator || navigator.maxTouchPoints > 0 ? 'touchpoints' : 'mouse'; switch (touchObject.eventType) { case 'mouse': touchObject.touchstart = 'mousedown'; touchObject.touchend = 'mouseup'; touchObject.touchmove = 'mousemove'; touchObject.touchenter = 'mouseenter'; touchObject.touchmove = 'mousemove'; touchObject.touchleave = 'mouseleave'; break; case 'touch': touchObject.touchstart = 'touchstart'; touchObject.touchend = 'touchend'; touchObject.touchmove = 'touchmove'; touchObject.touchcancel = 'touchcancel'; touchObject.touchenter = 'touchstart'; touchObject.touchmove = 'touchmove'; touchObject.touchleave = 'touchend'; this.isTouch = true; break; case 'mstouchpoints': touchObject.touchstart = 'MSPointerDown'; touchObject.touchend = 'MSPointerUp'; touchObject.touchmove = 'MSPointerMove'; touchObject.touchcancel = 'MSPointerCancel'; touchObject.touchenter = 'MSPointerDown'; touchObject.touchmove = 'MSPointerMove'; touchObject.touchleave = 'MSPointerUp'; break; case 'touchpoints': touchObject.touchstart = 'pointerdown'; touchObject.touchend = 'pointerup'; touchObject.touchmove = 'pointermove'; touchObject.touchcancel = 'pointercancel'; touchObject.touchenter = 'pointerdown'; touchObject.touchmove = 'pointermove'; touchObject.touchleave = 'pointerup'; break; } return this.touchObject = touchObject; } }]); return touchManager; }(); function deepCopy(from, to, shallow) { if (shallow && isUndef(to)) { return from; } if (isArray(from)) { to = []; from.forEach(function (item, index) { to[index] = deepCopy(item, to[index]); }); } else if (from) { if (!isPlainObj(from)) { return from; } to = {}; for (var key in from) { to[key] = _typeof(from[key]) === 'object' ? deepCopy(from[key], to[key]) : from[key]; } } return to; } function mergeObject(from, to, force, shallow) { if (shallow && isUndef(to)) { return from; } to = to || {}; if (isArray(from)) { if (!isArray(to) && force) { to = []; } if (isArray(to)) { from.forEach(function (item, index) { to[index] = mergeObject(item, to[index], force, shallow); }); } } else if (from) { if (!isPlainObj(from)) { if (force) { to = from; } } else { for (var key in from) { if (_typeof(from[key]) === 'object') { if (isUndef(to[key])) { to[key] = deepCopy(from[key], to[key], shallow); } else { mergeObject(from[key], to[key], force, shallow); } } else { if (isUndef(to[key]) || force) to[key] = from[key]; } } } } return to; } function defineReactive(target, key, source, souceKey) { /* istanbul ignore if */ if (!source[key] && typeof source !== 'function') { return; } souceKey = souceKey || key; Object.defineProperty(target, key, { get: function get$$1() { return source[souceKey]; }, configurable: true }); } var scrollBarWidth = void 0; function getGutter() { /* istanbul ignore next */ if (isServer()) return 0; if (scrollBarWidth !== undefined) return scrollBarWidth; var outer = document.createElement('div'); outer.style.visibility = 'hidden'; outer.style.width = '100px'; outer.style.position = 'absolute'; outer.style.top = '-9999px'; document.body.appendChild(outer); var widthNoScroll = outer.offsetWidth; outer.style.overflow = 'scroll'; var inner = document.createElement('div'); inner.style.width = '100%'; outer.appendChild(inner); var widthWithScroll = inner.offsetWidth; outer.parentNode.removeChild(outer); scrollBarWidth = widthNoScroll - widthWithScroll; return scrollBarWidth; } function eventCenter(dom, eventName, hander) { var capture = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : false; var type = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 'on'; type == 'on' ? dom.addEventListener(eventName, hander, capture) : dom.removeEventListener(eventName, hander, capture); } var warn = function warn(msg) { console.warn('[vuescroll] ' + msg); }; function isChildInParent(child, parent) { var flag = false; if (!child || !parent) { return flag; } while (child.parentNode !== parent && child.parentNode.nodeType !== 9 && !child.parentNode._isVuescroll) { child = child.parentNode; } if (child.parentNode == parent) { flag = true; } return flag; } function getPrefix(global) { var docStyle = document.documentElement.style; var engine; /* istanbul ignore if */ if (global.opera && Object.prototype.toString.call(opera) === '[object Opera]') { engine = 'presto'; } /* istanbul ignore next */else if ('MozAppearance' in docStyle) { engine = 'gecko'; } else if ('WebkitAppearance' in docStyle) { engine = 'webkit'; } /* istanbul ignore next */else if (typeof navigator.cpuClass === 'string') { engine = 'trident'; } var vendorPrefix = { trident: 'ms', gecko: 'moz', webkit: 'webkit', presto: 'O' }[engine]; return vendorPrefix; } function getComplitableStyle(property, value) { /* istanbul ignore if */ if (isServer()) return false; var compatibleValue = '-' + getPrefix(window) + '-' + value; var testElm = document.createElement('div'); testElm.style[property] = compatibleValue; if (testElm.style[property] == compatibleValue) { return compatibleValue; } /* istanbul ignore next */ return false; } /** * Insert children into user-passed slot at vnode level */ function insertChildrenIntoSlot(h) { var parentVnode = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : []; var childVNode = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; var data = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {}; var swapChildren = arguments[4]; /* istanbul ignore if */ if (parentVnode && parentVnode.length > 1) { return swapChildren ? [].concat(toConsumableArray(childVNode), toConsumableArray(parentVnode)) : [].concat(toConsumableArray(parentVnode), toConsumableArray(childVNode)); } parentVnode = parentVnode[0]; var _getVnodeInfo = getVnodeInfo(parentVnode), ch = _getVnodeInfo.ch, tag = _getVnodeInfo.tag, isComponent = _getVnodeInfo.isComponent; if (isComponent) { parentVnode.data = mergeObject({ attrs: parentVnode.componentOptions.propsData }, parentVnode.data, false, // force: false true // shallow: true ); } ch = swapChildren ? [].concat(toConsumableArray(childVNode), toConsumableArray(ch)) : [].concat(toConsumableArray(ch), toConsumableArray(childVNode)); delete parentVnode.data.slot; return h(tag, mergeObject(data, parentVnode.data, false, true), ch); } /** * Get the info of a vnode, * vnode must be parentVnode */ function getVnodeInfo(vnode) { if (!vnode || vnode.length > 1) return {}; vnode = vnode[0] ? vnode[0] : vnode; var isComponent = !!vnode.componentOptions; var ch = void 0; var tag = void 0; if (isComponent) { ch = vnode.componentOptions.children || []; tag = vnode.componentOptions.tag; } else { ch = vnode.children || []; tag = vnode.tag; } return { isComponent: isComponent, ch: ch, tag: tag }; } /** * Get the vuescroll instance instead of * user pass component like slot. */ function getRealParent(ctx) { var parent = ctx.$parent; if (!parent._isVuescrollRoot && parent) { parent = parent.$parent; } return parent; } var isArray = function isArray(_) { return Array.isArray(_); }; var isPlainObj = function isPlainObj(_) { return Object.prototype.toString.call(_) == '[object Object]'; }; var isUndef = function isUndef(_) { return typeof _ === 'undefined'; }; function getNumericValue(distance, size) { var number = void 0; if (!(number = /(-?\d+(?:\.\d+?)?)%$/.exec(distance))) { number = distance - 0; } else { number = number[1] - 0; number = size * number / 100; } return number; } function createStyle(styleId, cssText) { /* istanbul ignore if */ if (isServer() || document.getElementById(styleId)) { return; } var head = document.head || doc.getElementsByTagName('head')[0]; var style = document.createElement('style'); style.id = styleId; style.type = 'text/css'; /* istanbul ignore if */ if (style.styleSheet) { style.styleSheet.cssText = cssText; } else { style.appendChild(document.createTextNode(cssText)); } head.appendChild(style); } // Hide the ios native scrollbar. function createHideBarStyle() { /* istanbul ignore next */ { var cssText = '.__hidebar::-webkit-scrollbar {\n width: 0;\n height: 0;\n }'; createStyle('vuescroll-hide-ios-bar', cssText); } } // create slide mode style var api = { mounted: function mounted() { vsInstances[this._uid] = this; }, beforeDestroy: function beforeDestroy() { delete vsInstances[this._uid]; }, methods: { // public api scrollTo: function scrollTo(_ref, speed, easing) { var x = _ref.x, y = _ref.y; // istanbul ignore if if (speed === true || typeof speed == 'undefined') { speed = this.mergedOptions.scrollPanel.speed; } this.internalScrollTo(x, y, speed, easing); }, scrollBy: function scrollBy(_ref2, speed, easing) { var _ref2$dx = _ref2.dx, dx = _ref2$dx === undefined ? 0 : _ref2$dx, _ref2$dy = _ref2.dy, dy = _ref2$dy === undefined ? 0 : _ref2$dy; var _getPosition = this.getPosition(), _getPosition$scrollLe = _getPosition.scrollLeft, scrollLeft = _getPosition$scrollLe === undefined ? 0 : _getPosition$scrollLe, _getPosition$scrollTo = _getPosition.scrollTop, scrollTop = _getPosition$scrollTo === undefined ? 0 : _getPosition$scrollTo; if (dx) { scrollLeft += getNumericValue(dx, this.scrollPanelElm.scrollWidth - this.$el.clientWidth); } if (dy) { scrollTop += getNumericValue(dy, this.scrollPanelElm.scrollHeight - this.$el.clientHeight); } this.internalScrollTo(scrollLeft, scrollTop, speed, easing); }, scrollIntoView: function scrollIntoView(elm) { var animate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true; var parentElm = this.$el; if (typeof elm === 'string') { elm = parentElm.querySelector(elm); } if (!isChildInParent(elm, parentElm)) { warn('The element or selector you passed is not the element of Vuescroll, please pass the element that is in Vuescroll to scrollIntoView API. '); return; } // parent elm left, top var _$el$getBoundingClien = this.$el.getBoundingClientRect(), left = _$el$getBoundingClien.left, top = _$el$getBoundingClien.top; // child elm left, top var _elm$getBoundingClien = elm.getBoundingClientRect(), childLeft = _elm$getBoundingClien.left, childTop = _elm$getBoundingClien.top; var diffX = left - childLeft; var diffY = top - childTop; this.scrollBy({ dx: -diffX, dy: -diffY }, animate); }, refresh: function refresh() { this.refreshInternalStatus(); // refresh again to keep status is correct this.$nextTick(this.refreshInternalStatus); } } }; /** Public Api */ /** * Refresh all */ var vsInstances = {}; function refreshAll() { for (var vs in vsInstances) { vsInstances[vs].refresh(); } } var baseConfig = { // vuescroll vuescroll: { // vuescroll's size(height/width) should be a percent(100%) // or be a number that is equal to its parentNode's width or // height ? sizeStrategy: 'percent', /** Whether to detect dom resize or not */ detectResize: true }, scrollPanel: { // when component mounted.. it will automatically scrolls. initialScrollY: false, initialScrollX: false, // feat: #11 scrollingX: true, scrollingY: true, speed: 300, easing: undefined, // Sometimes, the nativebar maybe on the left, // See https://github.com/YvesCoding/vuescroll/issues/64 verticalNativeBarPos: 'right', maxHeight: undefined, maxWidth: undefined }, // rail: { background: '#01a99a', opacity: 0, border: 'none', /** Rail's size(Height/Width) , default -> 6px */ size: '6px', /** Specify rail's border-radius, or the border-radius of rail and bar will be equal to the rail's size. default -> false **/ specifyBorderRadius: false, /** Rail the distance from the two ends of the X axis and Y axis. **/ gutterOfEnds: null, /** Rail the distance from the side of container. **/ gutterOfSide: '2px', /** Whether to keep rail show or not, default -> false, event content height is not enough */ keepShow: false }, bar: { /** How long to hide bar after mouseleave, default -> 500 */ showDelay: 500, /** Specify bar's border-radius, or the border-radius of rail and bar will be equal to the rail's size. default -> false **/ specifyBorderRadius: false, /** Whether to show bar on scrolling, default -> true */ onlyShowBarOnScroll: true, /** Whether to keep show or not, default -> false */ keepShow: false, /** Bar's background , default -> #00a650 */ background: 'rgb(3, 185, 118)', /** Bar's opacity, default -> 1 */ opacity: 1, /** bar's size(Height/Width) , default -> 6px */ size: '6px', minSize: 0, disable: false }, scrollButton: { enable: false, background: 'rgb(3, 185, 118)', opacity: 1, step: 180, mousedownStep: 30 } }; /** * validate the options * @export * @param {any} ops */ function validateOps(ops) { var renderError = false; var scrollPanel = ops.scrollPanel; var _ops$bar = ops.bar, vBar = _ops$bar.vBar, hBar = _ops$bar.hBar; var _ops$rail = ops.rail, vRail = _ops$rail.vRail, hRail = _ops$rail.hRail; // validate scrollPanel var initialScrollY = scrollPanel['initialScrollY']; var initialScrollX = scrollPanel['initialScrollX']; if (initialScrollY && !String(initialScrollY).match(/^\d+(\.\d+)?(%)?$/)) { warn('The prop `initialScrollY` or `initialScrollX` should be a percent number like `10%` or an exact number that greater than or equal to 0 like `100`.'); } if (initialScrollX && !String(initialScrollX).match(/^\d+(\.\d+)?(%)?$/)) { warn('The prop `initialScrollY` or `initialScrollX` should be a percent number like `10%` or an exact number that greater than or equal to 0 like `100`.'); } // validate deprecated vBar/hBar vRail/hRail if (vBar || hBar || vRail || hRail) { warn('The options: vRail, hRail, vBar, hBar have been deprecated since v4.7.0,' + 'please use corresponing rail/bar instead!'); } if (_extraValidate) { _extraValidate = [].concat(_extraValidate); _extraValidate.forEach(function (hasError) { if (hasError(ops)) { renderError = true; } }); } return renderError; } var _extraValidate = null; var extendOpts = function extendOpts(extraOpts, extraValidate) { extraOpts = [].concat(extraOpts); extraOpts.forEach(function (opts) { mergeObject(opts, baseConfig); }); _extraValidate = extraValidate; }; // all modes // do nothing // some small changes. var smallChangeArray = ['mergedOptions.vuescroll.pullRefresh.tips', 'mergedOptions.vuescroll.pushLoad.tips', 'mergedOptions.vuescroll.scroller.disable', 'mergedOptions.rail', 'mergedOptions.bar']; // refresh/load dom ref/key... var scrollMap = { vertical: { size: 'height', opsSize: 'width', posName: 'top', opposName: 'bottom', sidePosName: 'right', page: 'pageY', scroll: 'scrollTop', scrollSize: 'scrollHeight', offset: 'offsetHeight', client: 'clientY', axis: 'Y', scrollButton: { start: 'top', end: 'bottom' } }, horizontal: { size: 'width', opsSize: 'height', posName: 'left', opposName: 'right', sidePosName: 'bottom', page: 'pageX', scroll: 'scrollLeft', scrollSize: 'scrollWidth', offset: 'offsetWidth', client: 'clientX', axis: 'X', scrollButton: { start: 'left', end: 'right' } } }; function requestAnimationFrame(global) { // Check for request animation Frame support var requestFrame = global.requestAnimationFrame || global.webkitRequestAnimationFrame || global.mozRequestAnimationFrame || global.oRequestAnimationFrame; var isNative = !!requestFrame; if (requestFrame && !/requestAnimationFrame\(\)\s*\{\s*\[native code\]\s*\}/i.test(requestFrame.toString())) { isNative = false; } if (isNative) { return function (callback, root) { requestFrame(callback, root); }; } var TARGET_FPS = 60; var requests = {}; var rafHandle = 1; var intervalHandle = null; var lastActive = +new Date(); return function (callback) { var callbackHandle = rafHandle++; // Store callback requests[callbackHandle] = callback; // Create timeout at first request if (intervalHandle === null) { intervalHandle = setInterval(function () { var time = +new Date(); var currentRequests = requests; // Reset data structure before executing callbacks requests = {}; for (var key in currentRequests) { if (currentRequests.hasOwnProperty(key)) { currentRequests[key](time); lastActive = time; } } // Disable the timeout when nothing happens for a certain // period of time if (time - lastActive > 2500) { clearInterval(intervalHandle); intervalHandle = null; } }, 1000 / TARGET_FPS); } return callbackHandle; }; } var colorCache = {}; var rgbReg = /rgb\(/; var extractRgbColor = /rgb\((.*)\)/; // Transform a common color int oa `rgbA` color function getRgbAColor(color, opacity) { var id = color + '&' + opacity; if (colorCache[id]) { return colorCache[id]; } var div = document.createElement('div'); div.style.background = color; document.body.appendChild(div); var computedColor = window.getComputedStyle(div).backgroundColor; document.body.removeChild(div); /* istanbul ignore if */ if (!rgbReg.test(computedColor)) { return color; } return colorCache[id] = 'rgba(' + extractRgbColor.exec(computedColor)[1] + ', ' + opacity + ')'; } var bar = { name: 'bar', props: { ops: Object, state: Object, hideBar: Boolean, otherBarHide: Boolean, type: String }, computed: { bar: function bar() { return scrollMap[this.type]; }, barSize: function barSize() { return Math.max(this.state.size, this.ops.bar.minSize); }, barRatio: function barRatio() { return (1 - this.barSize) / (1 - this.state.size); } }, render: function render(h) { var _style, _style2, _barStyle; var vm = this; /** Get rgbA format background color */ var railBackgroundColor = getRgbAColor(vm.ops.rail.background, vm.ops.rail.opacity); if (!this.touchManager) { this.touchManager = new touchManager(); } /** Rail Data */ var railSize = vm.ops.rail.size; var endPos = vm.otherBarHide ? 0 : railSize; var touchObj = vm.touchManager.getTouchObject(); var rail = { class: '__rail-is-' + vm.type, style: (_style = { position: 'absolute', 'z-index': '1', borderRadius: vm.ops.rail.specifyBorderRadius || railSize, background: railBackgroundColor, border: vm.ops.rail.border }, defineProperty(_style, vm.bar.opsSize, railSize), defineProperty(_style, vm.bar.posName, vm.ops.rail['gutterOfEnds'] || 0), defineProperty(_style, vm.bar.opposName, vm.ops.rail['gutterOfEnds'] || endPos), defineProperty(_style, vm.bar.sidePosName, vm.ops.rail['gutterOfSide']), _style) }; if (touchObj) { var _rail$on; rail.on = (_rail$on = {}, defineProperty(_rail$on, touchObj.touchenter, function () { vm.setRailHover(); }), defineProperty(_rail$on, touchObj.touchleave, function () { vm.setRailLeave(); }), _rail$on); } // left space for scroll button var buttonSize = vm.ops.scrollButton.enable ? railSize : 0; var barWrapper = { class: '__bar-wrap-is-' + vm.type, style: (_style2 = { position: 'absolute', borderRadius: vm.ops.rail.specifyBorderRadius || railSize }, defineProperty(_style2, vm.bar.posName, buttonSize), defineProperty(_style2, vm.bar.opposName, buttonSize), _style2), on: {} }; var scrollDistance = vm.state.posValue * vm.state.size; var pos = scrollDistance * vm.barRatio / vm.barSize; var opacity = vm.state.opacity; var parent = getRealParent(this); // set class hook parent.setClassHook(this.type == 'vertical' ? 'vBarVisible' : 'hBarVisible', !!opacity); /** Scrollbar style */ var barStyle = (_barStyle = { cursor: 'pointer', position: 'absolute', margin: 'auto', transition: 'opacity 0.5s', 'user-select': 'none', 'border-radius': 'inherit' }, defineProperty(_barStyle, vm.bar.size, vm.barSize * 100 + '%'), defineProperty(_barStyle, 'background', vm.ops.bar.background), defineProperty(_barStyle, vm.bar.opsSize, vm.ops.bar.size), defineProperty(_barStyle, 'opacity', opacity), defineProperty(_barStyle, 'transform', 'translate' + scrollMap[vm.type].axis + '(' + pos + '%)'), _barStyle); var bar = { style: barStyle, class: '__bar-is-' + vm.type, ref: 'thumb', on: {} }; if (vm.type == 'vertical') { barWrapper.style.width = '100%'; // Let bar to be on the center. bar.style.left = 0; bar.style.right = 0; } else { barWrapper.style.height = '100%'; bar.style.top = 0; bar.style.bottom = 0; } /* istanbul ignore next */ { var _touchObj = this.touchManager.getTouchObject(); bar.on[_touchObj.touchstart] = this.createBarEvent(); barWrapper.on[_touchObj.touchstart] = this.createTrackEvent(); } return h( 'div', rail, [this.createScrollbarButton(h, 'start'), this.hideBar ? null : h( 'div', barWrapper, [h('div', bar)] ), this.createScrollbarButton(h, 'end')] ); }, data: function data() { return { isBarDragging: false }; }, methods: { setRailHover: function setRailHover() { var parent = getRealParent(this); var state = parent.vuescroll.state; if (!state.isRailHover) { state.isRailHover = true; parent.showBar(); } }, setRailLeave: function setRailLeave() { var parent = getRealParent(this); var state = parent.vuescroll.state; state.isRailHover = false; parent.hideBar(); }, setBarDrag: function setBarDrag(val) /* istanbul ignore next */{ this.$emit('setBarDrag', this.isBarDragging = val); var parent = getRealParent(this); // set class hook parent.setClassHook(this.type == 'vertical' ? 'vBarDragging' : 'hBarDragging', !!val); }, createBarEvent: function createBarEvent() { var ctx = this; var parent = getRealParent(ctx); var touchObj = ctx.touchManager.getTouchObject(); function mousedown(e) /* istanbul ignore next */{ var event = ctx.touchManager.getEventObject(e); if (!event) return; e.stopImmediatePropagation(); e.preventDefault(); event = event[0]; document.onselectstart = function () { return false; }; ctx.axisStartPos = event[ctx.bar.client] - ctx.$refs['thumb'].getBoundingClientRect()[ctx.bar.posName]; // Tell parent that the mouse has been down. ctx.setBarDrag(true); eventCenter(document, touchObj.touchmove, mousemove); eventCenter(document, touchObj.touchend, mouseup); } function mousemove(e) /* istanbul ignore next */{ if (!ctx.axisStartPos) { return; } var event = ctx.touchManager.getEventObject(e); if (!event) return; event = event[0]; var thubmParent = ctx.$refs.thumb.parentNode; var delta = event[ctx.bar.client] - thubmParent.getBoundingClientRect()[ctx.bar.posName]; delta = delta / ctx.barRatio; var percent = (delta - ctx.axisStartPos) / thubmParent[ctx.bar.offset]; parent.scrollTo(defineProperty({}, ctx.bar.axis.toLowerCase(), parent.scrollPanelElm[ctx.bar.scrollSize] * percent), false); } function mouseup() /* istanbul ignore next */{ ctx.setBarDrag(false); parent.hideBar(); document.onselectstart = null; ctx.axisStartPos = 0; eventCenter(document, touchObj.touchmove, mousemove, false, 'off'); eventCenter(document, touchObj.touchend, mouseup, false, 'off'); } return mousedown; }, createTrackEvent: function createTrackEvent() { var ctx = this; return function handleClickTrack(e) { var parent = getRealParent(ctx); var _ctx$bar = ctx.bar, client = _ctx$bar.client, offset = _ctx$bar.offset, posName = _ctx$bar.posName, axis = _ctx$bar.axis; var thumb = ctx.$refs['thumb']; e.preventDefault(); e.stopImmediatePropagation(); /* istanbul ignore if */ if (!thumb) return; var barOffset = thumb[offset]; var event = ctx.touchManager.getEventObject(e)[0]; var percent = (event[client] - e.currentTarget.getBoundingClientRect()[posName] - barOffset / 2) / (e.currentTarget[offset] - barOffset); parent.scrollTo(defineProperty({}, axis.toLowerCase(), percent * 100 + '%')); }; }, // Scrollbuton relative things... createScrollbarButton: function createScrollbarButton(h, type /* start or end */) { var _style3; var barContext = this; if (!barContext.ops.scrollButton.enable) { return null; } var size = barContext.ops.rail.size; var _barContext$ops$scrol = barContext.ops.scrollButton, opacity = _barContext$ops$scrol.opacity, background = _barContext$ops$scrol.background; var borderColor = getRgbAColor(background, opacity); var wrapperProps = { class: ['__bar-button', '__bar-button-is-' + barContext.type + '-' + type], style: (_style3 = {}, defineProperty(_style3, barContext.bar.scrollButton[type], 0), defineProperty(_style3, 'width', size), defineProperty(_style3, 'height', size), defineProperty(_style3, 'position', 'absolute'), defineProperty(_style3, 'cursor', 'pointer'), defineProperty(_style3, 'display', 'table'), _style3), ref: type }; var innerProps = { class: '__bar-button-inner', style: { border: 'calc(' + size + ' / 2.5) solid transparent', width: '0', height: '0', margin: 'auto', position: 'absolute', top: '0', bottom: '0', right: '0', left: '0' }, on: {} }; if (barContext.type == 'vertical') { if (type == 'start') { innerProps.style['border-bottom-color'] = borderColor; innerProps.style['transform'] = 'translateY(-25%)'; } else { innerProps.style['border-top-color'] = borderColor; innerProps.style['transform'] = 'translateY(25%)'; } } else { if (type == 'start') { innerProps.style['border-right-color'] = borderColor; innerProps.style['transform'] = 'translateX(-25%)'; } else { innerProps.style['border-left-color'] = borderColor; innerProps.style['transform'] = 'translateX(25%)'; } } /* istanbul ignore next */ { var touchObj = this.touchManager.getTouchObject(); innerProps.on[touchObj.touchstart] = this.createScrollButtonEvent(type, touchObj); } return h( 'div', wrapperProps, [h('div', innerProps)] ); }, createScrollButtonEvent: function createScrollButtonEvent(type, touchObj) { var ctx = this; var parent = getRealParent(ctx); var _ctx$ops$scrollButton = ctx.ops.scrollButton, step = _ctx$ops$scrollButton.step, mousedownStep = _ctx$ops$scrollButton.mousedownStep; var stepWithDirection = type == 'start' ? -step : step; var mousedownStepWithDirection = type == 'start' ? -mousedownStep : mousedownStep; var ref = requestAnimationFrame(window); // bar props: type var barType = ctx.type; var isMouseDown = false; var isMouseout = true; var timeoutId = void 0; function start(e) { /* istanbul ignore if */ if (3 == e.which) { return; } // set class hook parent.setClassHook('cliking' + barType + type + 'Button', true); e.stopImmediatePropagation(); e.preventDefault(); isMouseout = false; parent.scrollBy(defineProperty({}, 'd' + ctx.bar.axis.toLowerCase(), stepWithDirection)); eventCenter(document, touchObj.touchend, endPress, false); if (touchObj.touchstart == 'mousedown') { var elm = ctx.$refs[type]; eventCenter(elm, 'mouseenter', enter, false); eventCenter(elm, 'mouseleave', leave, false); } clearTimeout(timeoutId); timeoutId = setTimeout(function () /* istanbul ignore next */{ isMouseDown = true; ref(pressing, window); }, 500); } function pressing() /* istanbul ignore next */{ if (isMouseDown && !isMouseout) { parent.scrollBy(defineProperty({}, 'd' + ctx.bar.axis.toLowerCase(), mousedownStepWithDirection), false); ref(pressing, window); } } function endPress() { clearTimeout(timeoutId); isMouseDown = false; eventCenter(document, touchObj.touchend, endPress, false, 'off'); if (touchObj.touchstart == 'mousedown') { var elm = ctx.$refs[type]; eventCenter(elm, 'mouseenter', enter, false, 'off'); eventCenter(elm, 'mouseleave', leave, false, 'off'); } parent.setClassHook('cliking' + barType + type + 'Button', false); } function enter() /* istanbul ignore next */{ isMouseout = false; pressing(); } function leave() /* istanbul ignore next */{ isMouseout = true; } return start; } } }; function getBarData(vm, type) { var axis = scrollMap[type].axis; /** type.charAt(0) = vBar/hBar */ var barType = type.charAt(0) + 'Bar'; var hideBar = !vm.bar[barType].state.size || !vm.mergedOptions.scrollPanel['scrolling' + axis] || vm.refreshLoad && type !== 'vertical' || vm.mergedOptions.bar.disable; var keepShowRail = vm.mergedOptions.rail.keepShow; if (hideBar && !keepShowRail) { return null; } return { hideBar: hideBar, props: { type: type, ops: { bar: vm.mergedOptions.bar, rail: vm.mergedOptions.rail, scrollButton: vm.mergedOptions.scrollButton }, state: vm.bar[barType].state, hideBar: hideBar }, on: { setBarDrag: vm.setBarDrag }, ref: type + 'Bar', key: type }; } /** * create bars * * @param {any} size * @param {any} type */ function createBar(h, vm) { var verticalBarProps = getBarData(vm, 'vertical'); var horizontalBarProps = getBarData(vm, 'horizontal'); // set class hooks vm.setClassHook('hasVBar', !!(verticalBarProps && !verticalBarProps.hideBar)); vm.setClassHook('hasHBar', !!(horizontalBarProps && !horizontalBarProps.hideBar)); return [verticalBarProps ? h('bar', _extends({}, verticalBarProps, { props: _extends({ otherBarHide: !horizontalBarProps }, verticalBarProps.props) })) : null, horizontalBarProps ? h('bar', _extends({}, horizontalBarProps, { props: _extends({ otherBarHide: !verticalBarProps }, horizontalBarProps.props) })) : null]; } /** * This is like a HOC, It extracts the common parts of the * native-mode, slide-mode and mix-mode. * Each mode must implement the following methods: * 1. refreshInternalStatus : use to refresh the component * 2. destroy : Destroy some registryed events before component destroy. * 3. updateBarStateAndEmitEvent: use to update bar states and emit events. */ var createComponent = function createComponent(_ref) { var _render = _ref.render, components = _ref.components, mixins = _ref.mixins; return { name: 'vueScroll', props: { ops: { type: Object } }, components: components, mixins: [api].concat(toConsumableArray([].concat(mixins))), created: function created() { var _this = this; /** * Begin to merge options */ var _gfc = mergeObject(this.$vuescrollConfig || {}, {}); var ops = mergeObject(baseConfig, _gfc); this.$options.propsData.ops = this.$options.propsData.ops || {}; Object.keys(this.$options.propsData.ops).forEach(function (key) { { defineReactive(_this.mergedOptions, key, _this.$options.propsData.ops); } }); // from ops to mergedOptions mergeObject(ops, this.mergedOptions); this._isVuescrollRoot = true; this.renderError = validateOps(this.mergedOptions); }, render: function render(h) { var vm = this; if (vm.renderError) { return h('div', [[vm.$slots['default']]]); } if (!vm.touchManager) vm.touchManager = new touchManager(); // vuescroll data var data = { style: { height: vm.vuescroll.state.height, width: vm.vuescroll.state.width, padding: 0, position: 'relative', overflow: 'hidden' }, class: _extends({ __vuescroll: true }, vm.classHooks) }; var touchObj = vm.touchManager.getTouchObject(); if (touchObj) { var _data$on; data.on = (_data$on = {}, defineProperty(_data$on, touchObj.touchenter, function () { vm.vuescroll.state.pointerLeave = false; vm.updateBarStateAndEmitEvent(); vm.setClassHook('mouseEnter', true); }), defineProperty(_data$on, touchObj.touchleave, function () { vm.vuescroll.state.pointerLeave = true; vm.hideBar(); vm.setClassHook('mouseEnter', false); }), defineProperty(_data$on, touchObj.touchmove, function () /* istanbul ignore next */{ vm.vuescroll.state.pointerLeave = false; vm.updateBarStateAndEmitEvent(); }), _data$on); } var ch = [_render(h, vm)].concat(toConsumableArray(createBar(h, vm))); var _customContainer = this.$slots['scroll-container']; if (_customContainer) { return insertChildrenIntoSlot(h, _customContainer, ch, data); } return h( 'div', data, [ch] ); }, mounted: function mounted() { var _this2 = this; if (!this.renderError) { this.initVariables(); this.initWatchOpsChange(); // Call external merged Api this.refreshInternalStatus(); this.updatedCbs.push(function () { _this2.scrollToAnchor(); // need to reflow to deal with the // latest thing. _this2.updateBarStateAndEmitEvent(); }); } }, updated: function updated() { var _this3 = this; this.updatedCbs.forEach(function (cb) { cb.call(_this3); }); // Clear this.updatedCbs = []; }, beforeDestroy: function beforeDestroy() { if (this.destroy) { this.destroy(); } }, /** ------------------------------- Computed ----------------------------- */ computed: { scrollPanelElm: function scrollPanelElm() { return this.$refs['scrollPanel']._isVue ? this.$refs['scrollPanel'].$el : this.$refs['scrollPanel']; } }, data: function data() { return { vuescroll: { state: { isDragging: false, pointerLeave: true, isRailHover: false, /** Default sizeStrategies */ height: '100%', width: '100%', // current size strategy currentSizeStrategy: 'percent', currentScrollState: null, currentScrollInfo: null } }, bar: { vBar: { state: { posValue: 0, size: 0, opacity: 0 } }, hBar: { state: { posValue: 0, size: 0, opacity: 0 } } }, mergedOptions: { vuescroll: {}, scrollPanel: {}, scrollContent: {}, rail: {}, bar: {} }, updatedCbs: [], renderError: false, classHooks: { hasVBar: false, hasHBar: false, vBarVisible: false, hBarVisible: false, vBarDragging: false, hBarDragging: false, clikingVerticalStartButton: false, clikingVerticalEndButton: false, clikingHorizontalStartButton: false, clikingHorizontalEndButton: false, mouseEnter: false } }; }, /** ------------------------------- Methods -------------------------------- */ methods: { /** ------------------------ Handlers --------------------------- */ scrollingComplete: function scrollingComplete() { this.updateBarStateAndEmitEvent('handle-scroll-complete'); }, setBarDrag: function setBarDrag(val) { /* istanbul ignore next */ this.vuescroll.state.isDragging = val; }, setClassHook: function setClassHook(name, value) { this.classHooks[name] = value; }, /** ------------------------ Some Helpers --------------------------- */ /* * To have a good ux, instead of hiding bar immediately, we hide bar * after some seconds by using this simple debounce-hidebar method. */ showAndDefferedHideBar: function showAndDefferedHideBar(forceHideBar) { var _this4 = this; this.showBar(); if (this.timeoutId) { clearTimeout(this.timeoutId); this.timeoutId = 0; } this.timeoutId = setTimeout(function () { _this4.timeoutId = 0; _this4.hideBar(forceHideBar); }, this.mergedOptions.bar.showDelay); }, showBar: function showBar() { var opacity = this.mergedOptions.bar.opacity; this.bar.vBar.state.opacity = opacity; this.bar.hBar.state.opacity = opacity; }, hideBar: function hideBar(forceHideBar) { var _vuescroll$state = this.vuescroll.state, isDragging = _vuescroll$state.isDragging, isRailHover = _vuescroll$state.isRailHover; /* istanbul ignore next */ if (isDragging || isRailHover) { return; } if (forceHideBar && !this.mergedOptions.bar.keepShow) { this.bar.hBar.state.opacity = 0; this.bar.vBar.state.opacity = 0; } // add isDragging condition // to prevent from hiding bar while dragging the bar if (!this.mergedOptions.bar.keepShow && !this.vuescroll.state.isDragging) { this.bar.vBar.state.opacity = 0; this.bar.hBar.state.opacity = 0; } }, useNumbericSize: function useNumbericSize() { this.vuescroll.state.currentSizeStrategy = 'number'; var _mergedOptions$scroll = this.mergedOptions.scrollPanel, maxHeight = _mergedOptions$scroll.maxHeight, maxWidth = _mergedOptions$scroll.maxWidth; var _$el$parentNode = this.$el.parentNode, parentClientHeight = _$el$parentNode.clientHeight, parentClientWidth = _$el$parentNode.clientWidth; var _scrollPanelElm = this.scrollPanelElm, scrollHeight = _scrollPanelElm.scrollHeight, scrollWidth = _scrollPanelElm.scrollWidth; var width = void 0; var height = void 0; if (maxHeight || maxWidth) { height = scrollHeight <= maxHeight ? undefined : maxHeight; width = scrollWidth <= maxWidth ? undefined : maxWidth; } else { height = parentClientHeight; width = parentClientWidth; } this.vuescroll.state.height = height ? height + 'px' : undefined; this.vuescroll.state.width = width ? width + 'px' : undefined; }, usePercentSize: function usePercentSize() { this.vuescroll.state.currentSizeStrategy = 'percent'; this.vuescroll.state.height = '100%'; this.vuescroll.state.width = '100%'; }, // Set its size to be equal to its parentNode setVsSize: function setVsSize() { var sizeStrategy = this.mergedOptions.vuescroll.sizeStrategy; var _mergedOptions$scroll2 = this.mergedOptions.scrollPanel, maxHeight = _mergedOptions$scroll2.maxHeight, maxWidth = _mergedOptions$scroll2.maxWidth; var _scrollPanelElm2 = this.scrollPanelElm, clientHeight = _scrollPanelElm2.clientHeight, clientWidth = _scrollPanelElm2.clientWidth; if (sizeStrategy == 'number' || maxHeight && clientHeight > maxHeight || maxWidth && clientWidth > maxWidth) { this.useNumbericSize(); } else if (sizeStrategy == 'percent' && clientHeight != maxHeight && clientWidth != maxWidth) { this.usePercentSize(); } }, /** ------------------------ Init --------------------------- */ initWatchOpsChange: function initWatchOpsChange() { var _this5 = this; var watchOpts = { deep: true, sync: true }; this.$watch('mergedOptions', function () { setTimeout(function () { if (_this5.isSmallChangeThisTick) { _this5.isSmallChangeThisTick = false; _this5.updateBarStateAndEmitEvent('options-change'); return; } _this5.refreshInternalStatus(); }, 0); }, watchOpts); /** * We also watch `small` changes, and when small changes happen, we send * a signal to vuescroll, to tell it: * 1. we don't need to registry resize * 2. we don't need to registry scroller. */ smallChangeArray.forEach(function (opts) { _this5.$watch(opts, function () { _this5.isSmallChangeThisTick = true; }, watchOpts); }); }, // scrollTo hash-anchor while mounted component have mounted. scrollToAnchor: function scrollToAnchor() /* istanbul ignore next */{ var validateHashSelector = function validateHashSelector(hash) { return (/^#[a-zA-Z_]\d*$/.test(hash) ); }; var hash = window.location.hash; if (!hash || (hash = hash.slice(hash.lastIndexOf('#'))) && !validateHashSelector(hash)) { return; } var elm = document.querySelector(hash); if (!isChildInParent(elm, this.$el) || this.mergedOptions.scrollPanel.initialScrollY || this.mergedOptions.scrollPanel.initialScrollX) { return; } this.scrollIntoView(elm); } /** ------------------------ Registry Resize --------------------------- */ } }; }; // begin importing var scrollPanel = { name: 'scrollPanel', props: { ops: { type: Object, required: true } }, methods: { // trigger scrollPanel options initialScrollX, // initialScrollY updateInitialScroll: function updateInitialScroll() { var x = 0; var y = 0; var parent = getRealParent(this); if (this.ops.initialScrollX) { x = this.ops.initialScrollX; } if (this.ops.initialScrollY) { y = this.ops.initialScrollY; } if (x || y) { parent.scrollTo({ x: x, y: y }); } } }, mounted: function mounted() { var _this = this; setTimeout(function () { if (!_this._isDestroyed) { _this.updateInitialScroll(); } }, 0); }, render: function render(h) { // eslint-disable-line var data = { class: ['__panel'], style: { position: 'relative', boxSizing: 'border-box' } }; var parent = getRealParent(this); var _customPanel = parent.$slots['scroll-panel']; if (_customPanel) { return insertChildrenIntoSlot(h, _customPanel, this.$slots.default, data); } return h( 'div', data, [[this.$slots.default]] ); } }; /** * Init following things * 1. Component * 2. Render * 3. Config */ function _install(core, render) { var _components; var extraConfigs = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : []; var extraValidators = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : []; var components = (_components = {}, defineProperty(_components, scrollPanel.name, scrollPanel), defineProperty(_components, bar.name, bar), _components); var opts = {}; opts.components = components; opts.render = render; opts.mixins = core; var comp = createComponent(opts); // Init Config extendOpts(extraConfigs, extraValidators); return comp; } /** * Get the children of parent those are in viewport */ function getCurrentViewportDom(parent, container) { var children = parent.children; var domFragment = []; var isCurrentview = function isCurrentview(dom) { var _dom$getBoundingClien = dom.getBoundingClientRect(), left = _dom$getBoundingClien.left, top = _dom$getBoundingClien.top, width = _dom$getBoundingClien.width, height = _dom$getBoundingClien.height; var _container$getBoundin = container.getBoundingClientRect(), parentLeft = _container$getBoundin.left, parentTop = _container$getBoundin.top, parentHeight = _container$getBoundin.height, parentWidth = _container$getBoundin.width; if (left - parentLeft + width > 0 && left - parentLeft < parentWidth && top - parentTop + height > 0 && top - parentTop < parentHeight) { return true; } return false; }; for (var i = 0; i < children.length; i++) { var dom = children.item(i); if (isCurrentview(dom) && !dom.isResizeElm) { domFragment.push(dom); } } return domFragment; } /** * Compatible to scroller's animation function */ function createEasingFunction(easing, easingPattern) { return function (time) { return easingPattern(easing, time); }; } /** * Calculate the easing pattern * @link https://github.com/cferdinandi/smooth-scroll/blob/master/src/js/smooth-scroll.js * modified by wangyi7099 * @param {String} type Easing pattern * @param {Number} time Time animation should take to complete * @returns {Number} */ function easingPattern(easing, time) { var pattern = null; /* istanbul ignore next */ { // Default Easing Patterns if (easing === 'easeInQuad') pattern = time * time; // accelerating from zero velocity if (easing === 'easeOutQuad') pattern = time * (2 - time); // decelerating to zero velocity if (easing === 'easeInOutQuad') pattern = time < 0.5 ? 2 * time * time : -1 + (4 - 2 * time) * time; // acceleration until halfway, then deceleration if (easing === 'easeInCubic') pattern = time * time * time; // accelerating from zero velocity if (easing === 'easeOutCubic') pattern = --time * time * time + 1; // decelerating to zero velocity if (easing === 'easeInOutCubic') pattern = time < 0.5 ? 4 * time * time * time : (time - 1) * (2 * time - 2) * (2 * time - 2) + 1; // acceleration until halfway, then deceleration if (easing === 'easeInQuart') pattern = time * time * time * time; // accelerating from zero velocity if (easing === 'easeOutQuart') pattern = 1 - --time * time * time * time; // decelerating to zero velocity if (easing === 'easeInOutQuart') pattern = time < 0.5 ? 8 * time * time * time * time : 1 - 8 * --time * time * time * time; // acceleration until halfway, then deceleration if (easing === 'easeInQuint') pattern = time * time * time * time * time; // accelerating from zero velocity if (easing === 'easeOutQuint') pattern = 1 + --time * time * time * time * time; // decelerating to zero velocity if (easing === 'easeInOutQuint') pattern = time < 0.5 ? 16 * time * time * time * time * time : 1 + 16 * --time * time * time * time * time; // acceleration until halfway, then deceleration } return pattern || time; // no easing, no acceleration } function noop() { return true; } /* istanbul ignore next */ var now = Date.now || function () { return new Date().getTime(); }; var ScrollControl = function () { function ScrollControl() { classCallCheck(this, ScrollControl); this.init(); this.isRunning = false; } createClass(ScrollControl, [{ key: 'pause', value: function pause() { /* istanbul ignore if */ if (!this.isRunning) return; this.isPaused = true; } }, { key: 'stop', value: function stop() { this.isStopped = true; } }, { key: 'continue', value: function _continue() { /* istanbul ignore if */ if (!this.isPaused) return; this.isPaused = false; this.ts = now() - this.percent * this.spd; this.execScroll(); } }, { key: 'startScroll', value: function startScroll(st, ed, spd) { var stepCb = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : noop; var completeCb = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : noop; var vertifyCb = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : noop; var easingMethod = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : noop; var df = ed - st; var dir = df > 0 ? -1 : 1; var nt = now(); if (!this.isRunning) { this.init(); } if (dir != this.dir || nt - this.ts > 200) { this.ts = nt; this.dir = dir; this.st = st; this.ed = ed; this.df = df; } /* istanbul ignore next */else { this.df += df; } this.spd = spd; this.completeCb = completeCb; this.vertifyCb = vertifyCb; this.stepCb = stepCb; this.easingMethod = easingMethod; if (!this.isRunning) this.execScroll(); } }, { key: 'execScroll', value: function execScroll() { var _this = this; if (!this.df) return; var percent = this.percent || 0; this.percent = 0; this.isRunning = true; var loop = function loop() { /* istanbul ignore if */ if (!_this.isRunning || !_this.vertifyCb(percent) || _this.isStopped) { _this.isRunning = false; return; } percent = (now() - _this.ts) / _this.spd; if (_this.isPaused) { _this.percent = percent; _this.isRunning = false; return; } if (percent < 1) { var value = _this.st + _this.df * _this.easingMethod(percent); _this.stepCb(value); _this.ref(loop); } else { // trigger complete _this.stepCb(_this.st + _this.df); _this.completeCb(); _this.isRunning = false; } }; this.ref(loop); } }, { key: 'init', value: function init() { this.st = 0; this.ed = 0; this.df = 0; this.spd = 0; this.ts = 0; this.dir = 0; this.ref = requestAnimationFrame(window); this.isPaused = false; this.isStopped = false; } }]); return ScrollControl; }(); function scrollTo(elm, x, y) { var speed = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : 300; var easing = arguments[4]; var scrollingComplete = arguments[5]; var scrollLeft = void 0, scrollTop = void 0, scrollHeight = void 0, scrollWidth = void 0, clientWidth = void 0, clientHeight = void 0; var _elm = elm, nodeType = _elm.nodeType; var scrollX = new ScrollControl(); var scrollY = new ScrollControl(); if (!nodeType) { warn('You must pass a dom for the first param, ' + 'for window scrolling, ' + 'you can pass document as the first param.'); return; } if (nodeType == 9) { // document elm = elm.scrollingElement; } var _elm2 = elm; scrollLeft = _elm2.scrollLeft; scrollTop = _elm2.scrollTop; scrollHeight = _elm2.scrollHeight; scrollWidth = _elm2.scrollWidth; clientWidth = _elm2.clientWidth; clientHeight = _elm2.clientHeight; if (typeof x === 'undefined') { x = scrollLeft; } else { x = getNumericValue(x, scrollWidth - clientWidth); } if (typeof y === 'undefined') { y = scrollTop; } else { y = getNumericValue(y, scrollHeight - clientHeight); } var easingMethod = createEasingFunction(easing, easingPattern); scrollX.startScroll(scrollLeft, x, speed, function (dx) { elm.scrollLeft = dx; }, scrollingComplete, undefined, easingMethod); scrollY.startScroll(scrollTop, y, speed, function (dy) { elm.scrollTop = dy; }, scrollingComplete, undefined, easingMethod); } var api$1 = { mounted: function mounted() { // registry scroll this.scrollX = new ScrollControl(); this.scrollY = new ScrollControl(); }, methods: { nativeStop: function nativeStop() { this.scrollX.stop(); this.scrollY.stop(); }, nativePause: function nativePause() { this.scrollX.pause(); this.scrollY.pause(); }, nativeContinue: function nativeContinue() { this.scrollX.continue(); this.scrollY.continue(); }, nativeScrollTo: function nativeScrollTo(x, y, speed, easing) { if (speed === false) { } else if (typeof speed === 'undefined') { speed = this.mergedOptions.scrollPanel.speed; } var elm = this.scrollPanelElm; var scrollTop = elm.scrollTop, scrollLeft = elm.scrollLeft, scrollWidth = elm.scrollWidth, clientWidth = elm.clientWidth, scrollHeight = elm.scrollHeight, clientHeight = elm.clientHeight; if (typeof x === 'undefined') { x = scrollLeft; } else { x = getNumericValue(x, scrollWidth - clientWidth); } if (typeof y === 'undefined') { y = scrollTop; } else { y = getNumericValue(y, scrollHeight - clientHeight); } if (speed) { easing = easing || this.mergedOptions.scrollPanel.easing; var easingMethod = createEasingFunction(easing, easingPattern); if (x != scrollLeft) { this.scrollX.startScroll(scrollLeft, x, speed, function (x) { elm.scrollLeft = x; }, this.scrollingComplete.bind(this), undefined, easingMethod); } if (y != scrollTop) { this.scrollY.startScroll(scrollTop, y, speed, function (y) { elm.scrollTop = y; }, this.scrollingComplete.bind(this), undefined, easingMethod); } } else { elm.scrollTop = y; elm.scrollLeft = x; } }, getCurrentviewDomNative: function getCurrentviewDomNative() { var parent = this.scrollContentElm; var domFragment = getCurrentViewportDom(parent, this.$el); return domFragment; } } }; function getPanelData(context) { // scrollPanel data start var data = { ref: 'scrollPanel', style: { height: '100%', overflowY: 'scroll', overflowX: 'scroll' }, class: [], nativeOn: { '&scroll': context.handleScroll }, props: { ops: context.mergedOptions.scrollPanel } }; context.scrollYEnable = true; context.scrollXEnable = true; data.nativeOn.DOMMouseScroll = data.nativeOn.mousewheel = context.onMouseWheel; var _context$mergedOption = context.mergedOptions.scrollPanel, scrollingY = _context$mergedOption.scrollingY, scrollingX = _context$mergedOption.scrollingX; if (!context.bar.hBar.state.size || !scrollingX) { context.scrollXEnable = false; data.style.overflowX = 'hidden'; } if (!context.bar.vBar.state.size || !scrollingY) { context.scrollYEnable = false; data.style.overflowY = 'hidden'; } var gutter = getGutter(); /* istanbul ignore if */ if (!gutter) { createHideBarStyle(); data.class.push('__hidebar'); if (isIos()) { data.style['-webkit-overflow-scrolling'] = 'touch'; } } else { // hide system bar by use a negative value px // gutter should be 0 when manually disable scrollingX #14 if (context.bar.vBar.state.size && context.mergedOptions.scrollPanel.scrollingY) { if (context.mergedOptions.scrollPanel.verticalNativeBarPos == 'right') { data.style.marginRight = '-' + gutter + 'px'; } /* istanbul ignore next */else { data.style.marginLeft = '-' + gutter + 'px'; } } if (context.bar.hBar.state.size && context.mergedOptions.scrollPanel.scrollingX) { data.style.height = 'calc(100% + ' + gutter + 'px)'; } } // clear legency styles of slide mode... data.style.transformOrigin = ''; data.style.transform = ''; return data; } /** * create a scrollPanel * * @param {any} size * @param {any} context * @returns */ function createPanel(h, context) { var data = {}; data = getPanelData(context); return h( 'scrollPanel', data, [getPanelChildren(h, context)] ); } function getPanelChildren(h, context) { var viewStyle = { position: 'relative', 'box-sizing': 'border-box', 'min-width': '100%', 'min-height': '100%' }; var data = { style: viewStyle, ref: 'scrollContent', class: '__view' }; var _customContent = context.$slots['scroll-content']; if (context.mergedOptions.scrollPanel.scrollingX) { viewStyle.width = getComplitableStyle('width', 'fit-content'); } else { data.style['width'] = '100%'; } if (context.mergedOptions.scrollPanel.padding) { data.style.paddingRight = context.mergedOptions.rail.size; } if (_customContent) { return insertChildrenIntoSlot(h, _customContent, context.$slots.default, data); } return h( 'div', data, [context.$slots.default] ); } // detect content size change function installResizeDetection(element, callback) { return injectObject(element, callback); } function injectObject(element, callback) { if (element.hasResized) { return; } var OBJECT_STYLE = 'display: block; position: absolute; top: 0; left: 0; width: 100%; height: 100%; border: none; padding: 0; margin: 0; opacity: 0; z-index: -1000; pointer-events: none;'; // define a wrap due to ie's zIndex bug var objWrap = document.createElement('div'); objWrap.style.cssText = OBJECT_STYLE; var object = document.createElement('object'); object.style.cssText = OBJECT_STYLE; object.type = 'text/html'; object.tabIndex = -1; object.onload = function () { eventCenter(object.contentDocument.defaultView, 'resize', callback); }; // https://github.com/wnr/element-resize-detector/blob/aafe9f7ea11d1eebdab722c7c5b86634e734b9b8/src/detection-strategy/object.js#L159 if (!isIE()) { object.data = 'about:blank'; } objWrap.isResizeElm = true; objWrap.appendChild(object); element.appendChild(objWrap); if (isIE()) { object.data = 'about:blank'; } return function destroy() { if (object.contentDocument) { eventCenter(object.contentDocument.defaultView, 'resize', callback, 'off'); } element.removeChild(objWrap); element.hasResized = false; }; } /** * These mixes is exclusive for native mode */ var update = { methods: { updateNativeModeBarState: function updateNativeModeBarState() { var container = this.scrollPanelElm; var isPercent = this.vuescroll.state.currentSizeStrategy == 'percent'; var _vuescroll$state = this.vuescroll.state, width = _vuescroll$state.width, height = _vuescroll$state.height; var clientWidth = isPercent || !width ? container.clientWidth : width.slice(0, -2); // xxxpx ==> xxx var clientHeight = isPercent || !height ? container.clientHeight : height.slice(0, -2); var heightPercentage = clientHeight / container.scrollHeight; var widthPercentage = clientWidth / container.scrollWidth; this.bar.vBar.state.posValue = container.scrollTop * 100 / clientHeight; this.bar.hBar.state.posValue = container.scrollLeft * 100 / clientWidth; this.bar.vBar.state.size = heightPercentage < 1 ? heightPercentage : 0; this.bar.hBar.state.size = widthPercentage < 1 ? widthPercentage : 0; }, getNativePosition: function getNativePosition() { return { scrollTop: this.scrollPanelElm.scrollTop, scrollLeft: this.scrollPanelElm.scrollLeft }; }, css: function css(dom, style) /* istanbul ignore next */{ return window.getComputedStyle(dom)[style]; }, checkScrollable: function checkScrollable(e, dir, delta) /* istanbul ignore next */{ var scrollable = false; // check mouse point scrollable. var dom = e.target ? e.target : e; while (dom && dom.nodeType == 1 && dom !== this.scrollPanelElm.parentNode && !/^BODY|HTML/.test(dom.nodeName)) { var ov = (dir == 'dy' ? this.css(dom, 'overflowY') : this.css(dom, 'overflowX')) || this.css(dom, 'overflow') || ''; if (/scroll|auto/.test(ov)) { var _getScrollProcess = this.getScrollProcess(dom), v = _getScrollProcess.v, h = _getScrollProcess.h; if (dir == 'dx' && (delta < 0 && h > 0 || delta > 0 && h < 1) || dir == 'dy' && (delta < 0 && v > 0 || delta > 0 && v < 1)) { scrollable = dom == this.scrollPanelElm; break; } } dom = dom.parentNode ? dom.parentNode : false; } return scrollable; }, onMouseWheel: function onMouseWheel(event) /* istanbul ignore next */{ var duration = this.mergedOptions.vuescroll.wheelScrollDuration; var isReverse = this.mergedOptions.vuescroll.wheelDirectionReverse; var delta = 0; var dir = void 0; if (event.wheelDelta) { if (event.deltaY) { dir = 'dy'; delta = event.deltaY; } else if (event.deltaX) { delta = event.deltaX; dir = 'dx'; } else { delta = -1 * event.wheelDelta / 2; } } else if (event.detail) { // horizontal scroll if (event.axis == 1) { dir = 'dx'; } else if (event.axis == 2) { // vertical scroll dir = 'dy'; } delta = event.detail * 16; } if (event.shiftKey) { dir = 'dx'; } else { dir = 'dy'; } if (isReverse) { dir = dir == 'dx' ? 'dy' : 'dx'; } if (this.checkScrollable(event, dir, delta)) { event.stopPropagation(); event.preventDefault(); this.scrollBy(defineProperty({}, dir, delta), duration); } } }, computed: { scrollContentElm: function scrollContentElm() { return this.$refs['scrollContent']._isVue ? this.$refs['scrollContent'].$el : this.$refs['scrollContent']; } } }; var mixins = [api$1, update]; var core = { mixins: mixins, methods: { destroy: function destroy() { /* istanbul ignore next */ if (this.destroyResize) { this.destroyResize(); } }, getCurrentviewDom: function getCurrentviewDom() { return this.getCurrentviewDomNative(); }, internalScrollTo: function internalScrollTo(destX, destY, animate, easing) { this.nativeScrollTo(destX, destY, animate, easing); }, internalStop: function internalStop() { this.nativeStop(); }, internalPause: function internalPause() { this.nativePause(); }, internalContinue: function internalContinue() { this.nativeContinue(); }, handleScroll: function handleScroll(nativeEvent) { this.updateBarStateAndEmitEvent('handle-scroll', nativeEvent); }, updateBarStateAndEmitEvent: function updateBarStateAndEmitEvent(eventType) { var nativeEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; this.updateNativeModeBarState(); if (eventType) { this.emitEvent(eventType, nativeEvent); } if (this.mergedOptions.bar.onlyShowBarOnScroll) { if (eventType == 'handle-scroll' || eventType == 'handle-resize' || eventType == 'refresh-status' || eventType == 'window-resize' || eventType == 'options-change') { this.showAndDefferedHideBar(true /* forceHideBar: true */); } } else { this.showAndDefferedHideBar(); } }, getScrollProcess: function getScrollProcess(elm) { var _ref = elm || this.scrollPanelElm, scrollHeight = _ref.scrollHeight, scrollWidth = _ref.scrollWidth, clientHeight = _ref.clientHeight, clientWidth = _ref.clientWidth, scrollTop = _ref.scrollTop, scrollLeft = _ref.scrollLeft; var v = Math.min(scrollTop / (scrollHeight - clientHeight || 1), 1); var h = Math.min(scrollLeft / (scrollWidth - clientWidth || 1), 1); return { v: v, h: h }; }, emitEvent: function emitEvent(eventType) { var nativeEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null; var _scrollPanelElm = this.scrollPanelElm, scrollTop = _scrollPanelElm.scrollTop, scrollLeft = _scrollPanelElm.scrollLeft; var vertical = { type: 'vertical' }; var horizontal = { type: 'horizontal' }; var _getScrollProcess = this.getScrollProcess(), v = _getScrollProcess.v, h = _getScrollProcess.h; vertical.process = v; horizontal.process = h; vertical['barSize'] = this.bar.vBar.state.size; horizontal['barSize'] = this.bar.hBar.state.size; vertical['scrollTop'] = scrollTop; horizontal['scrollLeft'] = scrollLeft; this.$emit(eventType, vertical, horizontal, nativeEvent); }, initVariables: function initVariables() { this.$el._isVuescroll = true; }, refreshInternalStatus: function refreshInternalStatus() { // 1.set vuescroll height or width according to // sizeStrategy this.setVsSize(); // 2. registry resize event this.registryResize(); // 3. update scrollbar's height/width this.updateBarStateAndEmitEvent('refresh-status'); }, registryResize: function registryResize() { var _this = this; var resizeEnable = this.mergedOptions.vuescroll.detectResize; /* istanbul ignore next */ if (this.destroyResize && resizeEnable) { return; } if (this.destroyResize) { this.destroyResize(); } if (!resizeEnable) { return; } var contentElm = this.scrollContentElm; var vm = this; var handleWindowResize = function handleWindowResize() /* istanbul ignore next */{ vm.updateBarStateAndEmitEvent('window-resize'); }; var handleDomResize = function handleDomResize() { var currentSize = {}; currentSize['width'] = _this.scrollPanelElm.scrollWidth; currentSize['height'] = _this.scrollPanelElm.scrollHeight; _this.updateBarStateAndEmitEvent('handle-resize', currentSize); // Since content sie changes, we should tell parent to set // correct size to fit content's size _this.setVsSize(); }; window.addEventListener('resize', handleWindowResize, false); var destroyDomResize = installResizeDetection(contentElm, handleDomResize); var destroyWindowResize = function destroyWindowResize() { window.removeEventListener('resize', handleWindowResize, false); }; this.destroyResize = function () { destroyWindowResize(); destroyDomResize(); _this.destroyResize = null; }; }, getPosition: function getPosition() { return this.getNativePosition(); } } }; var config = { vuescroll: { wheelScrollDuration: 0, wheelDirectionReverse: false } }; var component = _install(core, createPanel, [config]); function install(Vue$$1) { var opts = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; Vue$$1.component(opts.name || component.name, component); Vue$$1.prototype.$vuescrollConfig = opts.ops || {}; } var Vuescroll = _extends({ install: install, version: '4.16.1', refreshAll: refreshAll, scrollTo: scrollTo }, component); /* istanbul ignore if */ if (typeof window !== 'undefined' && window.Vue) { window.Vue.use(Vuescroll); } return Vuescroll; })));