text: /*
      * Vuescroll v4.14.4
      * (c) 2018-2019 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
    });
  }
  
  
  
  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 error = function error(msg) {
    console.error('[vuescroll] ' + msg);
  };
  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.
  
  
  // create slide mode style
  function createSlideModeStyle() {
    var cssText = '\n    @-webkit-keyframes loading-rotate {\n      to {\n        -webkit-transform: rotate(1turn);\n        transform: rotate(1turn);\n      }\n    }\n\n    @keyframes loading-rotate {\n      to {\n        -webkit-transform: rotate(1turn);\n        transform: rotate(1turn);\n      }\n    }\n\n    @-webkit-keyframes loading-wipe {\n      0% {\n        stroke-dasharray: 1, 200;\n        stroke-dashoffset: 0;\n      }\n      50% {\n        stroke-dasharray: 90, 150;\n        stroke-dashoffset: -40px;\n      }\n      to {\n        stroke-dasharray: 90, 150;\n        stroke-dashoffset: -120px;\n      }\n    }\n\n    @keyframes loading-wipe {\n      0% {\n        stroke-dasharray: 1, 200;\n        stroke-dashoffset: 0;\n      }\n      50% {\n        stroke-dasharray: 90, 150;\n        stroke-dashoffset: -40px;\n      }\n      to {\n        stroke-dasharray: 90, 150;\n        stroke-dashoffset: -120px;\n      }\n    }\n\n    .__vuescroll .__refresh,\n    .__vuescroll .__load {\n      position: absolute;\n      width: 100%;\n      color: black;\n      height: 50px;\n      line-height: 50px;\n      text-align: center;\n      font-size: 16px;\n    }\n    .__vuescroll .__refresh svg,\n    .__vuescroll .__load svg {\n      margin-right: 10px;\n      width: 25px;\n      height: 25px;\n      vertical-align: sub;\n    }\n    .__vuescroll .__refresh svg.active,\n    .__vuescroll .__load svg.active {\n      transition: all 0.2s;\n    }\n    .__vuescroll .__refresh svg.active.deactive,\n    .__vuescroll .__load svg.active.deactive {\n      transform: rotateZ(180deg);\n    }\n    .__vuescroll .__refresh svg path,\n    .__vuescroll .__refresh svg rect,\n    .__vuescroll .__load svg path,\n    .__vuescroll .__load svg rect {\n      fill: #20a0ff;\n    }\n    .__vuescroll .__refresh svg.start,\n    .__vuescroll .__load svg.start {\n      stroke: #343640;\n      stroke-width: 4;\n      stroke-linecap: round;\n      -webkit-animation: loading-rotate 2s linear infinite;\n      animation: loading-rotate 2s linear infinite;\n    }\n    .__vuescroll .__refresh svg.start .bg-path,\n    .__vuescroll .__load svg.start .bg-path {\n      stroke: #f2f2f2;\n      fill: none;\n    }\n    .__vuescroll .__refresh svg.start .active-path,\n    .__vuescroll .__load svg.start .active-path {\n      stroke: #20a0ff;\n      fill: none;\n      stroke-dasharray: 90, 150;\n      stroke-dashoffset: 0;\n      -webkit-animation: loading-wipe 1.5s ease-in-out infinite;\n      animation: loading-wipe 1.5s ease-in-out infinite;\n    }\n  ';
  
    createStyle('vuescroll-silde-mode-style', cssText);
  }
  
  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'
    },
  
    //
    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
  var NOOP$1 = function NOOP() {};
  // 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 __REFRESH_DOM_NAME = 'refreshDom';
  var __LOAD_DOM_NAME = 'loadDom';
  
  // 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;
    };
  }
  
  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 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)
      };
  
      // 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: {
      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() {
        // remove registryed resize event
        if (this.destroyParentDomResize) {
          this.destroyParentDomResize();
          this.destroyParentDomResize = null;
        }
  
        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,
              /** Default sizeStrategies */
              height: '100%',
              width: '100%',
              // current size strategy
              currentSizeStrategy: 'percent'
            }
          },
          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) {
          // when in non-native mode dragging content
          // in slide mode, just return
          /* istanbul ignore next */
          if (this.vuescroll.state.isDragging) {
            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.vuescroll.state.pointerLeave) {
            this.bar.vBar.state.opacity = 0;
            this.bar.hBar.state.opacity = 0;
          }
        },
        useNumbericSize: function useNumbericSize() {
          var _this5 = this;
  
          this.usePercentSize();
          setTimeout(function () {
            _this5.vuescroll.state.currentSizeStrategy = 'number';
  
            var el = _this5.$el.parentNode || _this5.$el;
            _this5.vuescroll.state.height = el.offsetHeight + 'px';
            _this5.vuescroll.state.width = el.offsetWidth + 'px';
  
            _this5.updateBarStateAndEmitEvent('handle-resize');
          }, 0);
        },
        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() {
          if (this.destroyParentDomResize) {
            this.destroyParentDomResize();
            this.destroyParentDomResize = null;
          }
  
          if (this.mergedOptions.vuescroll.sizeStrategy == 'number') {
            this.useNumbericSize();
            this.registryParentResize();
          } else if (this.mergedOptions.vuescroll.sizeStrategy == 'percent') {
            this.usePercentSize();
          }
        },
  
  
        /** ------------------------ Init --------------------------- */
        initWatchOpsChange: function initWatchOpsChange() {
          var _this6 = this;
  
          var watchOpts = {
            deep: true,
            sync: true
          };
          this.$watch('mergedOptions', function () {
            setTimeout(function () {
              if (_this6.isSmallChangeThisTick) {
                _this6.isSmallChangeThisTick = false;
                _this6.updateBarStateAndEmitEvent('options-change');
                return;
              }
              _this6.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) {
            _this6.$watch(opts, function () {
              _this6.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 --------------------------- */
  
        registryParentResize: function registryParentResize() {
          var resizeEnable = this.mergedOptions.vuescroll.detectResize;
          this.destroyParentDomResize = resizeEnable ? installResizeDetection(this.$el.parentNode, this.useNumbericSize) : function () {};
        }
      }
    };
  };
  
  // 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: '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;
  
        this.ref = requestAnimationFrame(window);
  
        if (!this.isRunning) this.execScroll();
      }
    }, {
      key: 'execScroll',
      value: function execScroll() {
        var _this = this;
  
        var percent = 0;
        this.isRunning = true;
  
        var loop = function loop() {
          /* istanbul ignore if */
          if (!_this.isRunning || !_this.vertifyCb(percent)) {
            _this.isRunning = false;
            return;
          }
  
          percent = (now() - _this.ts) / _this.spd;
          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;
      }
    }]);
    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);
  }
  
  function getPanelData(context) {
    // scrollPanel data start
    var data = {
      ref: 'scrollPanel',
      style: {
        'user-select': 'none',
        '-webkit-user-select': 'none',
        'min-width': '100%',
        'min-height': '100%'
      },
      class: [],
      props: {
        ops: context.mergedOptions.scrollPanel
      }
    };
  
    data.class.push('__slide');
    /* istanbul ignore if */
    if (isIos()) {
      data.style = defineProperty({}, '-webkit-overflow-scrolling', 'touch');
    }
  
    if (context.mergedOptions.vuescroll.renderMethod == 'transform') {
      data.style['transform-origin'] = 'left top 0px';
    }
  
    var _context$mergedOption = context.mergedOptions.scrollPanel,
        scrollingX = _context$mergedOption.scrollingX,
        scrollingY = _context$mergedOption.scrollingY,
        padding = _context$mergedOption.padding;
  
  
    if (scrollingX && !context.refreshLoad) {
      var width = getComplitableStyle('width', 'fit-content');
      if (width) {
        data.style['width'] = width;
      } /* istanbul ignore next */else {
          data['display'] = 'inline-block';
        }
    }
  
    /* istanbul ignore if */
    if (!scrollingX) {
      data.class.push('x-hidden');
    }
    /* istanbul ignore if */
    if (!scrollingY) {
      data.class.push('y-hidden');
    }
  
    if (padding) {
      data.style.paddingRight = context.mergedOptions.rail.size;
    }
  
    return data;
  }
  
  function getPanelChildren(h, context) {
    var renderChildren = getVnodeInfo(context.$slots['scroll-panel']).ch || context.$slots.default;
    var finalChildren = [];
  
    /* istanbul ignore if */
    if (!renderChildren) {
      context.$slots.default = renderChildren = [];
    }
  
    // handle refresh
    if (context.mergedOptions.vuescroll.pullRefresh.enable) {
      finalChildren.push(h(
        'div',
        {
          'class': '__refresh',
          style: { visibility: context.refrehDomVisiable ? '' : 'hidden' },
          ref: __REFRESH_DOM_NAME,
          key: __REFRESH_DOM_NAME
        },
        [createTipDom(h, context, 'refresh', context.pullRefreshTip)]
      ));
    }
  
    finalChildren.push(renderChildren);
  
    // handle load
    if (context.mergedOptions.vuescroll.pushLoad.enable) {
      finalChildren.push(h(
        'div',
        {
          ref: __LOAD_DOM_NAME,
          key: __LOAD_DOM_NAME,
          'class': '__load',
          style: { visibility: context.loadDomVisiable ? '' : 'hidden' }
        },
        [createTipDom(h, context, 'load', context.pushLoadTip)]
      ));
    }
  
    return finalChildren;
  }
  
  // Create load or refresh tip dom of each stages
  function createTipDom(h, context, type, tip) {
    var stage = context.vuescroll.state[type + 'Stage'];
    var dom = null;
    // Return user specified animation dom
    /* istanbul ignore if */
    if (dom = context.$slots[type + '-' + stage]) {
      return dom;
    }
  
    switch (stage) {
      // The dom will show at deactive stage
      case 'deactive':
      case 'active':
        {
          var className = 'active';
          if (stage == 'deactive') {
            className += ' deactive';
          }
  
          dom = h(
            'svg',
            {
              'class': className,
              attrs: { version: '1.1',
                xmlns: 'http://www.w3.org/2000/svg',
                xmlnsXlink: 'http://www.w3.org/1999/xlink',
                x: '0px',
                y: '0px',
                viewBox: '0 0 1000 1000',
                'enable-background': 'new 0 0 1000 1000',
                xmlSpace: 'preserve'
              }
            },
            [h('metadata', [' Svg Vector Icons : http://www.sfont.cn ']), h('g', [h(
              'g',
              {
                attrs: { transform: 'matrix(1 0 0 -1 0 1008)' }
              },
              [h('path', {
                attrs: { d: 'M10,543l490,455l490-455L885,438L570,735.5V18H430v717.5L115,438L10,543z' }
              })]
            )])]
          );
        }
        break;
      case 'start':
        dom = h(
          'svg',
          {
            attrs: { viewBox: '0 0 50 50' },
            'class': 'start' },
          [h('circle', {
            attrs: { stroke: 'true', cx: '25', cy: '25', r: '20' },
            'class': 'bg-path' }), h('circle', {
            attrs: { cx: '25', cy: '25', r: '20' },
            'class': 'active-path' })]
        );
        break;
      case 'beforeDeactive':
        dom = h(
          'svg',
          {
            attrs: {
              viewBox: '0 0 1024 1024',
              version: '1.1',
              xmlns: 'http://www.w3.org/2000/svg',
              'p-id': '3562'
            }
          },
          [h('path', {
            attrs: {
              d: 'M512 0C229.706831 0 0 229.667446 0 512s229.667446 512 512 512c282.293169 0 512-229.667446 512-512S794.332554 0 512 0z m282.994215 353.406031L433.2544 715.145846a31.484062 31.484062 0 0 1-22.275938 9.231754h-0.4096a31.586462 31.586462 0 0 1-22.449231-9.814646L228.430769 546.327631a31.507692 31.507692 0 0 1 45.701908-43.386093l137.4208 144.785724L750.442338 308.854154a31.507692 31.507692 0 1 1 44.551877 44.551877z',
              fill: '',
              'p-id': '3563'
            }
          })]
        );
        break;
    }
    return [dom, tip];
  }
  
  /**
   * create a scrollPanel
   *
   * @param {any} size
   * @param {any} context
   * @returns
   */
  function createPanel(h, context) {
    var data = getPanelData(context);
  
    return h(
      'scrollPanel',
      data,
      [getPanelChildren(h, context)]
    );
  }
  
  var api$2 = {
    methods: {
      slideScrollTo: function slideScrollTo(x, y, speed, easing) {
        var _getPosition = this.getPosition(),
            scrollLeft = _getPosition.scrollLeft,
            scrollTop = _getPosition.scrollTop;
  
        x = getNumericValue(x || scrollLeft, this.scroller.__maxScrollLeft);
        y = getNumericValue(y || scrollTop, this.scroller.__maxScrollTop);
  
        this.scroller.scrollTo(x, y, speed > 0, undefined, false, speed, easing);
      },
      zoomBy: function zoomBy(factor, animate, originLeft, originTop, callback) {
        if (!this.scroller) {
          warn('zoomBy and zoomTo are only for slide mode!');
          return;
        }
        this.scroller.zoomBy(factor, animate, originLeft, originTop, callback);
      },
      zoomTo: function zoomTo(level) {
        var animate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
        var originLeft = arguments[2];
        var originTop = arguments[3];
        var callback = arguments[4];
  
        if (!this.scroller) {
          warn('zoomBy and zoomTo are only for slide mode!');
          return;
        }
        this.scroller.zoomTo(level, animate, originLeft, originTop, callback);
      },
      getCurrentPage: function getCurrentPage() {
        if (!this.scroller || !this.mergedOptions.vuescroll.paging) {
          warn('getCurrentPage and goToPage are only for slide mode and paging is enble!');
          return;
        }
        return this.scroller.getCurrentPage();
      },
      goToPage: function goToPage(dest) {
        var animate = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : false;
  
        if (!this.scroller || !this.mergedOptions.vuescroll.paging) {
          warn('getCurrentPage and goToPage are only for slide mode and paging is enble!');
          return;
        }
        this.scroller.goToPage(dest, animate);
      },
      triggerRefreshOrLoad: function triggerRefreshOrLoad(type) {
        if (!this.scroller) {
          warn('You can only use triggerRefreshOrLoad in slide mode!');
          return;
        }
  
        var isRefresh = this.mergedOptions.vuescroll.pullRefresh.enable;
        var isLoad = this.mergedOptions.vuescroll.pushLoad.enable;
  
        if (type == 'refresh' && !isRefresh) {
          warn('refresh must be enabled!');
          return;
        } else if (type == 'load' && !isLoad) {
          warn('load must be enabled and content\'s height > container\'s height!');
          return;
        } else if (type !== 'refresh' && type !== 'load') {
          warn('param must be one of load and refresh!');
          return;
        }
  
        /* istanbul ignore if */
        if (this.vuescroll.state[type + 'Stage'] == 'start') {
          return;
        }
  
        this.scroller.triggerRefreshOrLoad(type);
        return true;
      },
      getCurrentviewDomSlide: function getCurrentviewDomSlide() {
        var parent = this.scrollPanelElm;
        var domFragment = getCurrentViewportDom(parent, this.$el);
        return domFragment;
      }
    }
  };
  
  /*
   * Scroller
   * http://github.com/zynga/scroller
   *
   * Copyright 2011, Zynga Inc.
   * Licensed under the MIT License.
   * https://raw.github.com/zynga/scroller/master/MIT-LICENSE.txt
   *
   * Based on the work of: Unify Project (unify-project.org)
   * http://unify-project.org
   * Copyright 2011, Deutsche Telekom AG
   * License: MIT + Apache (V2)
   */
  
  /**
   * Generic animation class with support for dropped frames both optional easing and duration.
   *
   * Optional duration is useful when the lifetime is defined by another condition than time
   * e.g. speed of an animating object, etc.
   *
   * Dropped frame logic allows to keep using the same updater logic independent from the actual
   * rendering. This eases a lot of cases where it might be pretty complex to break down a state
   * based on the pure time difference.
   */
  var time = Date.now || function () {
    return +new Date();
  };
  var desiredFrames = 60;
  var millisecondsPerSecond = 1000;
  var running = {};
  var counter = 1;
  
  var core = { effect: {} };
  var global$1 = null;
  
  if (typeof window !== 'undefined') {
    global$1 = window;
  } else {
    global$1 = {};
  }
  
  core.effect.Animate = {
    /**
     * A requestAnimationFrame wrapper / polyfill.
     *
     * @param callback {Function} The callback to be invoked before the next repaint.
     * @param root {HTMLElement} The root element for the repaint
     */
    requestAnimationFrame: requestAnimationFrame(global$1),
    /**
     * Stops the given animation.
     *
     * @param id {Integer} Unique animation ID
     * @return {Boolean} Whether the animation was stopped (aka, was running before)
     */
    stop: function stop(id) {
      var cleared = running[id] != null;
      if (cleared) {
        running[id] = null;
      }
  
      return cleared;
    },
  
    /**
     * Whether the given animation is still running.
     *
     * @param id {Integer} Unique animation ID
     * @return {Boolean} Whether the animation is still running
     */
    isRunning: function isRunning(id) {
      return running[id] != null;
    },
  
    /**
     * Start the animation.
     *
     * @param stepCallback {Function} Pointer to function which is executed on every step.
     *   Signature of the method should be `function(percent, now, virtual) { return continueWithAnimation; }`
     * @param verifyCallback {Function} Executed before every animation step.
     *   Signature of the method should be `function() { return continueWithAnimation; }`
     * @param completedCallback {Function}
     *   Signature of the method should be `function(droppedFrames, finishedAnimation) {}`
     * @param duration {Integer} Milliseconds to run the animation
     * @param easingMethod {Function} Pointer to easing function
     *   Signature of the method should be `function(percent) { return modifiedValue; }`
     * @param root {Element ? document.body} Render root, when available. Used for internal
     *   usage of requestAnimationFrame.
     * @return {Integer} Identifier of animation. Can be used to stop it any time.
     */
    start: function start(stepCallback, verifyCallback, completedCallback, duration, easingMethod, root) {
      var start = time();
      var lastFrame = start;
      var percent = 0;
      var dropCounter = 0;
      var id = counter++;
  
      if (!root) {
        root = document.body;
      }
  
      // Compacting running db automatically every few new animations
      if (id % 20 === 0) {
        var newRunning = {};
        for (var usedId in running) {
          newRunning[usedId] = true;
        }
        running = newRunning;
      }
  
      // This is the internal step method which is called every few milliseconds
      var step = function step(virtual) {
        // Normalize virtual value
        var render = virtual !== true;
  
        // Get current time
        var now = time();
  
        // Verification is executed before next animation step
        if (!running[id] || verifyCallback && !verifyCallback(id)) {
          running[id] = null;
          completedCallback && completedCallback(desiredFrames - dropCounter / ((now - start) / millisecondsPerSecond), id, false);
          return;
        }
  
        // For the current rendering to apply let's update omitted steps in memory.
        // This is important to bring internal state variables up-to-date with progress in time.
        if (render) {
          var droppedFrames = Math.round((now - lastFrame) / (millisecondsPerSecond / desiredFrames)) - 1;
          for (var j = 0; j < Math.min(droppedFrames, 4); j++) {
            step(true);
            dropCounter++;
          }
        }
  
        if (!running[id]) {
          return;
        }
  
        // Compute percent value
        if (duration) {
          percent = (now - start) / duration;
          if (percent > 1) {
            percent = 1;
          }
        }
  
        // Execute step callback, then...
        var value = easingMethod ? easingMethod(percent) : percent;
        if ((stepCallback(value, now, render) === false || percent === 1) && render) {
          running[id] = null;
          completedCallback && completedCallback(desiredFrames - dropCounter / ((now - start) / millisecondsPerSecond), id, percent === 1 || duration == null);
        } else if (render) {
          lastFrame = now;
          core.effect.Animate.requestAnimationFrame(step, root);
        }
      };
  
      // Mark as running
      running[id] = true;
  
      // Init first step
      core.effect.Animate.requestAnimationFrame(step, root);
  
      // Return unique animation ID
      return id;
    }
  };
  
  /*
   * Scroller
   * http://github.com/zynga/scroller
   *
   * modified by wangyi7099
   *
   * Copyright 2011, Zynga Inc.
   * Licensed under the MIT License.
   * https://raw.github.com/zynga/scroller/master/MIT-LICENSE.txt
   *
   * Based on the work of: Unify Project (unify-project.org)
   * http://unify-project.org
   * Copyright 2011, Deutsche Telekom AG
   * License: MIT + Apache (V2)
   */
  var animatingMethod = null;
  
  var noAnimatingMethod = null;
  
  function Scroller(callback, options) {
    this.__callback = callback;
  
    this.options = {
      /** Enable scrolling on x-axis */
      scrollingX: true,
  
      /** Enable scrolling on y-axis */
      scrollingY: true,
  
      /** Enable animations for deceleration, snap back, zooming and scrolling */
      animating: true,
  
      /** duration for animations triggered by scrollTo/zoomTo */
      animationDuration: 250,
  
      /** Enable bouncing (content can be slowly moved outside and jumps back after releasing) */
      bouncing: {
        top: 100,
        bottom: 100,
        left: 100,
        right: 100
      },
  
      /** Enable locking to the main axis if user moves only slightly on one of them at start */
      locking: true,
  
      /** Enable pagination mode (switching between full page content panes) */
      paging: false,
  
      /** Enable snapping of content to a configured pixel grid */
      snapping: false,
  
      /** Enable zooming of content via API, fingers and mouse wheel */
      zooming: false,
  
      /** Minimum zoom level */
      minZoom: 0.5,
  
      /** Maximum zoom level */
      maxZoom: 3,
  
      /** Multiply or decrease scrolling speed **/
      speedMultiplier: 1,
  
      /** Callback that is fired on the later of touch end or deceleration end,
      provided that another scrolling action has not begun. Used to know
      when to fade out a scrollbar. */
      scrollingComplete: NOOP$1,
  
      animatingEasing: 'easeOutCubic',
  
      noAnimatingEasing: 'easeInOutCubic',
  
      /** This configures the amount of change applied to deceleration when reaching boundaries  **/
      penetrationDeceleration: 0.03,
  
      /** This configures the amount of change applied to acceleration when reaching boundaries  **/
      penetrationAcceleration: 0.08
    };
  
    for (var key in options) {
      this.options[key] = options[key];
    }
  
    animatingMethod = createEasingFunction(this.options.animatingEasing, easingPattern);
    noAnimatingMethod = createEasingFunction(this.options.noAnimatingEasing, easingPattern);
  }
  
  var members = {
    /*
    ---------------------------------------------------------------------------
    INTERNAL FIELDS :: STATUS
    ---------------------------------------------------------------------------
    */
  
    /** {Boolean} Whether only a single finger is used in touch handling */
    __isSingleTouch: false,
  
    /** {Boolean} Whether a touch event sequence is in progress */
    __isTracking: false,
  
    /** {Boolean} Whether a deceleration animation went to completion. */
    __didDecelerationComplete: false,
  
    /**
     * {Boolean} Whether a gesture zoom/rotate event is in progress. Activates when
     * a gesturestart event happens. This has higher priority than dragging.
     */
    __isGesturing: false,
  
    /**
     * {Boolean} Whether the user has moved by such a distance that we have enabled
     * dragging mode. Hint: It's only enabled after some pixels of movement to
     * not interrupt with clicks etc.
     */
    __isDragging: false,
  
    /**
     * {Boolean} Not touching and dragging anymore, and smoothly animating the
     * touch sequence using deceleration.
     */
    __isDecelerating: false,
  
    /**
     * {Boolean} Smoothly animating the currently configured change
     */
    __isAnimating: false,
  
    /*
    ---------------------------------------------------------------------------
    INTERNAL FIELDS :: DIMENSIONS
    ---------------------------------------------------------------------------
    */
  
    /** {Integer} Available outer left position (from document perspective) */
    __clientLeft: 0,
  
    /** {Integer} Available outer top position (from document perspective) */
    __clientTop: 0,
  
    /** {Integer} Available outer width */
    __clientWidth: 0,
  
    /** {Integer} Available outer height */
    __clientHeight: 0,
  
    /** {Integer} Outer width of content */
    __contentWidth: 0,
  
    /** {Integer} Outer height of content */
    __contentHeight: 0,
  
    /** {Integer} Snapping width for content */
    __snapWidth: 100,
  
    /** {Integer} Snapping height for content */
    __snapHeight: 100,
  
    /** {Integer} Height to assign to refresh area */
    __refreshHeight: null,
    /** {Integer} Height to assign to refresh area */
    __loadHeight: null,
    /** {Boolean} Whether the refresh process is enabled when the event is released now */
    __refreshActive: false,
  
    /** {Function} Callback to execute on activation. This is for signalling the user about a refresh is about to happen when he release */
    __refreshActivate: null,
  
    __refreshBeforeDeactivate: null,
  
    /** {Function} Callback to execute on deactivation. This is for signalling the user about the refresh being cancelled */
    __refreshDeactivate: null,
  
    /** {Function} Callback to execute to start the actual refresh. Call {@link #refreshFinish} when done */
    __refreshStart: null,
  
    __loadActive: null,
  
    __loadActivate: null,
  
    __loadBeforeDeactivate: null,
  
    __loadDeactivate: null,
  
    __loadStart: null,
    /** {Number} Zoom level */
    __zoomLevel: 1,
  
    /** {Number} Scroll position on x-axis */
    __scrollLeft: 0,
  
    /** {Number} Scroll position on y-axis */
    __scrollTop: 0,
  
    /** {Integer} Maximum allowed scroll position on x-axis */
    __maxScrollLeft: 0,
  
    /** {Integer} Maximum allowed scroll position on y-axis */
    __maxScrollTop: 0,
  
    /* {Number} Scheduled left position (final position when animating) */
    __scheduledLeft: 0,
  
    /* {Number} Scheduled top position (final position when animating) */
    __scheduledTop: 0,
  
    /* {Number} Scheduled zoom level (final scale when animating) */
    __scheduledZoom: 0,
  
    /**
     * current page
     */
    __currentPageX: null,
  
    __currentPageY: null,
  
    /**
     * total page
     */
    __totalXPage: null,
  
    __totalYPage: null,
    /*
    ---------------------------------------------------------------------------
    INTERNAL FIELDS :: LAST POSITIONS
    ---------------------------------------------------------------------------
    */
    /** whether the scroller is disabled or not */
    __disable: false,
    /** {Number} Left position of finger at start */
    __lastTouchLeft: null,
  
    /** {Number} Top position of finger at start */
    __lastTouchTop: null,
  
    /** {Date} Timestamp of last move of finger. Used to limit tracking range for deceleration speed. */
    __lastTouchMove: null,
  
    /** {Array} List of positions, uses three indexes for each state: left, top, timestamp */
    __positions: null,
  
    /*
    ---------------------------------------------------------------------------
    INTERNAL FIELDS :: DECELERATION SUPPORT
    ---------------------------------------------------------------------------
    */
  
    /** {Integer} Minimum left scroll position during deceleration */
    __minDecelerationScrollLeft: null,
  
    /** {Integer} Minimum top scroll position during deceleration */
    __minDecelerationScrollTop: null,
  
    /** {Integer} Maximum left scroll position during deceleration */
    __maxDecelerationScrollLeft: null,
  
    /** {Integer} Maximum top scroll position during deceleration */
    __maxDecelerationScrollTop: null,
  
    /** {Number} Current factor to modify horizontal scroll position with on every step */
    __decelerationVelocityX: null,
  
    /** {Number} Current factor to modify vertical scroll position with on every step */
    __decelerationVelocityY: null,
  
    /*
    ---------------------------------------------------------------------------
    PUBLIC API
    ---------------------------------------------------------------------------
    */
  
    /**
     * Configures the dimensions of the client (outer) and content (inner) elements.
     * Requires the available space for the outer element and the outer size of the inner element.
     * All values which are falsy (null or zero etc.) are ignored and the old value is kept.
     *
     * @param clientWidth {Integer ? null} Inner width of outer element
     * @param clientHeight {Integer ? null} Inner height of outer element
     * @param contentWidth {Integer ? null} Outer width of inner element
     * @param contentHeight {Integer ? null} Outer height of inner element
     */
    setDimensions: function setDimensions(clientWidth, clientHeight, contentWidth, contentHeight, animate) {
      var noScroll = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : false;
  
      var self = this;
  
      // Only update values which are defined
      if (clientWidth === +clientWidth) {
        self.__clientWidth = clientWidth;
      }
  
      if (clientHeight === +clientHeight) {
        self.__clientHeight = clientHeight;
      }
  
      if (contentWidth === +contentWidth) {
        self.__contentWidth = contentWidth;
      }
  
      if (contentHeight === +contentHeight) {
        self.__contentHeight = contentHeight;
      }
  
      // Refresh maximums
      self.__computeScrollMax();
  
      if (!noScroll) {
        // Refresh scroll position
        self.scrollTo(self.__scrollLeft, self.__scrollTop, animate);
      }
    },
  
    /**
     * Sets the client coordinates in relation to the document.
     *
     * @param left {Integer ? 0} Left position of outer element
     * @param top {Integer ? 0} Top position of outer element
     */
    setPosition: function setPosition(left, top) {
      var self = this;
  
      self.__clientLeft = left || 0;
      self.__clientTop = top || 0;
    },
  
    /**
     * Configures the snapping (when snapping is active)
     *
     * @param width {Integer} Snapping width
     * @param height {Integer} Snapping height
     */
    setSnapSize: function setSnapSize(width, height) {
      var self = this;
  
      self.__snapWidth = width;
      self.__snapHeight = height;
    },
  
    /**
     * Activates pull-to-refresh. A special zone on the top of the list to start a list refresh whenever
     * the user event is released during visibility of this zone. This was introduced by some apps on iOS like
     * the official Twitter client.
     *
     * @param height {Integer} Height of pull-to-refresh zone on top of rendered list
     * @param activateCallback {Function} Callback to execute on activation. This is for signalling the user about a refresh is about to happen when he release.
     * @param deactivateCallback {Function} Callback to execute on deactivation. This is for signalling the user about the refresh being cancelled.
     * @param startCallback {Function} Callback to execute to start the real async refresh action. Call {@link #finishPullToRefresh} after finish of refresh.
     */
    activatePullToRefresh: function activatePullToRefresh(height, _ref) {
      var activateCallback = _ref.activateCallback,
          deactivateCallback = _ref.deactivateCallback,
          startCallback = _ref.startCallback,
          beforeDeactivateCallback = _ref.beforeDeactivateCallback,
          beforeDeactiveEnd = _ref.beforeDeactiveEnd;
  
      var self = this;
  
      self.__refreshHeight = height;
      self.__refreshActivate = activateCallback;
      self.__refreshBeforeDeactivate = beforeDeactivateCallback;
      self.__refreshBeforeDeactiveEnd = beforeDeactiveEnd;
      self.__refreshDeactivate = deactivateCallback;
      self.__refreshStart = startCallback;
    },
    activatePushToLoad: function activatePushToLoad(height, _ref2) {
      var activateCallback = _ref2.activateCallback,
          deactivateCallback = _ref2.deactivateCallback,
          startCallback = _ref2.startCallback,
          beforeDeactivateCallback = _ref2.beforeDeactivateCallback,
          beforeDeactiveEnd = _ref2.beforeDeactiveEnd;
  
      var self = this;
  
      self.__loadHeight = height;
      self.__loadActivate = activateCallback;
      self.__loadBeforeDeactivate = beforeDeactivateCallback;
      self.__loadBeforeDeactiveEnd = beforeDeactiveEnd;
      self.__loadDeactivate = deactivateCallback;
      self.__loadStart = startCallback;
    },
  
    /**
     * Starts pull-to-refresh manually.
     */
    triggerRefreshOrLoad: function triggerRefreshOrLoad() {
      var type = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'refresh';
  
      var wasDecelerating = this.__isDecelerating;
      if (wasDecelerating) {
        core.effect.Animate.stop(wasDecelerating);
        this.__isDecelerating = false;
      }
      // Use publish instead of scrollTo to allow scrolling to out of boundary position
      // We don't need to normalize scrollLeft, zoomLevel, etc. here because we only y-scrolling when pull-to-refresh is enabled
      if (type == 'refresh') {
        if (this.__refreshActive || this.__refreshBeforeDeactiveStarted) return;
  
        this.__publish(this.__scrollLeft, -this.__refreshHeight, this.__zoomLevel, true);
        if (this.__refreshStart) {
          this.__refreshStart();
          this.__refreshActive = true;
        }
      } else if (type == 'load') {
        if (this.__loadActive || this.__loadBeforeDeactiveStarted) return;
  
        this.__publish(this.__scrollLeft, this.__maxScrollTop + this.__loadHeight, this.__zoomLevel, true);
        if (this.__loadStart) {
          this.__loadStart();
          this.__loadActive = true;
        }
      }
    },
  
    /**
     * Signalizes that pull-to-refresh is finished.
     */
    finishRefreshOrLoad: function finishRefreshOrLoad() {
      var self = this;
  
      if (self.__refreshActive) {
        self.__refreshActive = false;
        var endRefreshActive = function endRefreshActive() {
          if (self.__refreshBeforeDeactiveEnd) {
            self.__refreshBeforeDeactiveEnd();
          }
          self.__refreshBeforeDeactiveStarted = true;
          self.scrollTo(self.__scrollLeft, self.__scrollTop, true);
        };
  
        if (self.__refreshBeforeDeactivate) {
          self.__refreshBeforeDeactivate(endRefreshActive);
        } else {
          endRefreshActive();
        }
      }
  
      if (self.__loadActive) {
        self.__loadActive = false;
        var endLoadActive = function endLoadActive() {
          if (self.__loadBeforeDeactiveEnd) {
            self.__loadBeforeDeactiveEnd();
          }
          self.__loadBeforeDeactiveStarted = true;
          self.scrollTo(self.__scrollLeft, self.__scrollTop, true);
        };
  
        if (self.__loadBeforeDeactivate) {
          self.__loadBeforeDeactivate(endLoadActive);
        } else {
          endLoadActive();
        }
      }
    },
  
    /**
     * Returns the scroll position and zooming values
     *
     * @return {Map} `left` and `top` scroll position and `zoom` level
     */
    getValues: function getValues() {
      var self = this;
  
      return {
        left: self.__scrollLeft,
        top: self.__scrollTop,
        zoom: self.__zoomLevel
      };
    },
  
    /**
     * Returns the maximum scroll values
     *
     * @return {Map} `left` and `top` maximum scroll values
     */
    getScrollMax: function getScrollMax() {
      var self = this;
  
      return {
        left: self.__maxScrollLeft,
        top: self.__maxScrollTop
      };
    },
  
    /**
     * Zooms to the given level. Supports optional animation. Zooms
     * the center when no coordinates are given.
     *
     * @param level {Number} Level to zoom to
     * @param animate {Boolean ? false} Whether to use animation
     * @param originLeft {Number ? null} Zoom in at given left coordinate
     * @param originTop {Number ? null} Zoom in at given top coordinate
     * @param callback {Function ? null} A callback that gets fired when the zoom is complete.
     */
    zoomTo: function zoomTo(level, animate, originLeft, originTop, callback) {
      var self = this;
  
      if (!self.options.zooming) {
        throw new Error('Zooming is not enabled!');
      }
  
      // Add callback if exists
      if (callback) {
        self.__zoomComplete = callback;
      }
  
      // Stop deceleration
      if (self.__isDecelerating) {
        core.effect.Animate.stop(self.__isDecelerating);
        self.__isDecelerating = false;
      }
  
      var oldLevel = self.__zoomLevel;
  
      // Normalize input origin to center of viewport if not defined
      if (originLeft == null) {
        originLeft = self.__clientWidth / 2;
      }
  
      if (originTop == null) {
        originTop = self.__clientHeight / 2;
      }
  
      // Limit level according to configuration
      level = Math.max(Math.min(level, self.options.maxZoom), self.options.minZoom);
  
      // Recompute maximum values while temporary tweaking maximum scroll ranges
      self.__computeScrollMax(level);
  
      // Recompute left and top coordinates based on new zoom level
      var left = (originLeft + self.__scrollLeft) * level / oldLevel - originLeft;
      var top = (originTop + self.__scrollTop) * level / oldLevel - originTop;
  
      // Limit x-axis
      if (left > self.__maxScrollLeft) {
        left = self.__maxScrollLeft;
      } else if (left < 0) {
        left = 0;
      }
  
      // Limit y-axis
      if (top > self.__maxScrollTop) {
        top = self.__maxScrollTop;
      } else if (top < 0) {
        top = 0;
      }
  
      // Push values out
      self.__publish(left, top, level, animate);
    },
  
    /**
     * Zooms the content by the given factor.
     *
     * @param factor {Number} Zoom by given factor
     * @param animate {Boolean ? false} Whether to use animation
     * @param originLeft {Number ? 0} Zoom in at given left coordinate
     * @param originTop {Number ? 0} Zoom in at given top coordinate
     * @param callback {Function ? null} A callback that gets fired when the zoom is complete.
     */
    zoomBy: function zoomBy(factor, animate, originLeft, originTop, callback) {
      var self = this;
  
      self.zoomTo(self.__zoomLevel * factor, animate, originLeft, originTop, callback);
    },
  
    /**
     * Scrolls to the given position. Respect limitations and snapping automatically.
     *
     * @param left {Number?null} Horizontal scroll position, keeps current if value is <code>null</code>
     * @param top {Number?null} Vertical scroll position, keeps current if value is <code>null</code>
     * @param animate {Boolean?false} Whether the scrolling should happen using an animation
     * @param zoom {Number?null} Zoom level to go to
     */
    scrollTo: function scrollTo(left, top, animate, zoom, force, speed, easing) {
      var self = this;
  
      // Stop deceleration
      if (self.__isDecelerating) {
        core.effect.Animate.stop(self.__isDecelerating);
        self.__isDecelerating = false;
      }
  
      // Correct coordinates based on new zoom level
      if (zoom != null && zoom !== self.__zoomLevel) {
        if (!self.options.zooming) {
          throw new Error('Zooming is not enabled!');
        }
  
        left *= zoom;
        top *= zoom;
  
        // Recompute maximum values while temporary tweaking maximum scroll ranges
        self.__computeScrollMax(zoom);
      } else {
        // Keep zoom when not defined
        zoom = self.__zoomLevel;
      }
  
      if (!self.options.scrollingX && !force) {
        left = self.__scrollLeft;
      } else {
        if (self.options.paging) {
          left = Math.round(left / self.__clientWidth) * self.__clientWidth;
        } else if (self.options.snapping) {
          left = Math.round(left / self.__snapWidth) * self.__snapWidth;
        }
      }
  
      if (!self.options.scrollingY && !force) {
        top = self.__scrollTop;
      } else {
        if (self.options.paging) {
          top = Math.round(top / self.__clientHeight) * self.__clientHeight;
        } else if (self.options.snapping) {
          top = Math.round(top / self.__snapHeight) * self.__snapHeight;
        }
      }
  
      if (!force) {
        // Limit for allowed ranges
        left = Math.max(Math.min(self.__maxScrollLeft, left), 0);
        top = Math.max(Math.min(self.__maxScrollTop, top), 0);
      }
  
      // Don't animate when no change detected, still call publish to make sure
      // that rendered position is really in-sync with internal data
      if (left === self.__scrollLeft && top === self.__scrollTop) {
        animate = false;
      }
  
      // Publish new values
      if (!self.__isTracking) {
        self.__publish(left, top, zoom, animate, speed, easing);
      }
    },
  
    /**
     * Scroll by the given offset
     *
     * @param left {Number ? 0} Scroll x-axis by given offset
     * @param top {Number ? 0} Scroll x-axis by given offset
     * @param animate {Boolean ? false} Whether to animate the given change
     */
    scrollBy: function scrollBy(left, top, animate) {
      var self = this;
  
      var startLeft = self.__isAnimating ? self.__scheduledLeft : self.__scrollLeft;
      var startTop = self.__isAnimating ? self.__scheduledTop : self.__scrollTop;
  
      self.scrollTo(startLeft + (left || 0), startTop + (top || 0), animate);
    },
    getCurrentPage: function getCurrentPage() {
      this.__computePage();
      return {
        x: this.__currentPageX,
        y: this.__currentPageY
      };
    },
    goToPage: function goToPage(_ref3, animate) {
      var x = _ref3.x,
          y = _ref3.y;
  
      if (isNaN(x)) {
        x = 1;
      }
      if (isNaN(y)) {
        y = 1;
      }
      this.scrollTo((x - 1) * this.__clientWidth, (y - 1) * this.__clientHeight, animate);
    },
  
  
    /*
    ---------------------------------------------------------------------------
    EVENT CALLBACKS
    ---------------------------------------------------------------------------
    */
  
    /**
     * Mouse wheel handler for zooming support
     */
    doMouseZoom: function doMouseZoom(wheelDelta, timeStamp, pageX, pageY) {
      var self = this;
      var change = wheelDelta > 0 ? 0.97 : 1.03;
  
      return self.zoomTo(self.__zoomLevel * change, false, pageX - self.__clientLeft, pageY - self.__clientTop);
    },
  
    /**
     * Touch start handler for scrolling support
     */
    doTouchStart: function doTouchStart(touches, timeStamp) {
      // Array-like check is enough here
      if (touches.length == null) {
        throw new Error('Invalid touch list: ' + touches);
      }
  
      if (timeStamp instanceof Date) {
        timeStamp = timeStamp.valueOf();
      }
      if (typeof timeStamp !== 'number') {
        throw new Error('Invalid timestamp value: ' + timeStamp);
      }
  
      var self = this;
  
      // Reset interruptedAnimation flag
      self.__interruptedAnimation = true;
  
      // Stop deceleration
      if (self.__isDecelerating) {
        core.effect.Animate.stop(self.__isDecelerating);
        self.__isDecelerating = false;
        self.__interruptedAnimation = true;
      }
  
      // Stop animation
      if (self.__isAnimating) {
        core.effect.Animate.stop(self.__isAnimating);
        self.__isAnimating = false;
        self.__interruptedAnimation = true;
      }
  
      // Use center point when dealing with two fingers
      var currentTouchLeft, currentTouchTop;
      var isSingleTouch = touches.length === 1;
      if (isSingleTouch) {
        currentTouchLeft = touches[0].pageX;
        currentTouchTop = touches[0].pageY;
      } else {
        currentTouchLeft = Math.abs(touches[0].pageX + touches[1].pageX) / 2;
        currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2;
      }
  
      // Store initial positions
      self.__initialTouchLeft = currentTouchLeft;
      self.__initialTouchTop = currentTouchTop;
  
      // Store current zoom level
      self.__zoomLevelStart = self.__zoomLevel;
  
      // Store initial touch positions
      self.__lastTouchLeft = currentTouchLeft;
      self.__lastTouchTop = currentTouchTop;
  
      // Store initial move time stamp
      self.__lastTouchMove = timeStamp;
  
      // Reset initial scale
      self.__lastScale = 1;
  
      // Reset locking flags
      self.__enableScrollX = !isSingleTouch && self.options.scrollingX;
      self.__enableScrollY = !isSingleTouch && self.options.scrollingY;
  
      // Reset tracking flag
      self.__isTracking = true;
  
      // Reset deceleration complete flag
      self.__didDecelerationComplete = false;
  
      // Dragging starts directly with two fingers, otherwise lazy with an offset
      self.__isDragging = !isSingleTouch;
  
      // Some features are  in multi touch scenarios
      self.__isSingleTouch = isSingleTouch;
  
      // Clearing data structure
      self.__positions = [];
    },
  
    /**
     * Touch move handler for scrolling support
     */
    doTouchMove: function doTouchMove(touches, timeStamp, scale) {
      // Array-like check is enough here
      if (touches.length == null) {
        throw new Error('Invalid touch list: ' + touches);
      }
  
      if (timeStamp instanceof Date) {
        timeStamp = timeStamp.valueOf();
      }
      if (typeof timeStamp !== 'number') {
        throw new Error('Invalid timestamp value: ' + timeStamp);
      }
  
      var self = this;
  
      // Ignore event when tracking is not enabled (event might be outside of element)
      if (!self.__isTracking) {
        return;
      }
  
      var currentTouchLeft, currentTouchTop;
  
      // Compute move based around of center of fingers
      if (touches.length === 2) {
        currentTouchLeft = Math.abs(touches[0].pageX + touches[1].pageX) / 2;
        currentTouchTop = Math.abs(touches[0].pageY + touches[1].pageY) / 2;
      } else {
        currentTouchLeft = touches[0].pageX;
        currentTouchTop = touches[0].pageY;
      }
  
      var positions = self.__positions;
  
      // Are we already is dragging mode?
      if (self.__isDragging) {
        // Compute move distance
        var moveX = currentTouchLeft - self.__lastTouchLeft;
        var moveY = currentTouchTop - self.__lastTouchTop;
  
        // Read previous scroll position and zooming
        var scrollLeft = self.__scrollLeft;
        var scrollTop = self.__scrollTop;
        var level = self.__zoomLevel;
  
        // Work with scaling
        if (scale != null && self.options.zooming) {
          var oldLevel = level;
  
          // Recompute level based on previous scale and new scale
          level = level / self.__lastScale * scale;
  
          // Limit level according to configuration
          level = Math.max(Math.min(level, self.options.maxZoom), self.options.minZoom);
  
          // Only do further compution when change happened
          if (oldLevel !== level) {
            // Compute relative event position to container
            var currentTouchLeftRel = currentTouchLeft - self.__clientLeft;
            var currentTouchTopRel = currentTouchTop - self.__clientTop;
  
            // Recompute left and top coordinates based on new zoom level
            scrollLeft = (currentTouchLeftRel + scrollLeft) * level / oldLevel - currentTouchLeftRel;
            scrollTop = (currentTouchTopRel + scrollTop) * level / oldLevel - currentTouchTopRel;
  
            // Recompute max scroll values
            self.__computeScrollMax(level);
          }
        }
  
        var bouncing = self.options.bouncing;
  
        if (self.__enableScrollX) {
          scrollLeft -= moveX * this.options.speedMultiplier;
          var maxScrollLeft = self.__maxScrollLeft;
  
          if (scrollLeft > maxScrollLeft || scrollLeft < 0) {
            scrollLeft += moveX / 2 * this.options.speedMultiplier;
  
            // fix scrollLeft
            scrollLeft = Math.min(Math.max(-bouncing.left, scrollLeft), maxScrollLeft + bouncing.right);
          }
        }
  
        // Compute new vertical scroll position
        if (self.__enableScrollY) {
          scrollTop -= moveY * this.options.speedMultiplier;
          var maxScrollTop = self.__maxScrollTop;
  
          if (scrollTop > maxScrollTop || scrollTop < 0) {
            scrollTop += moveY / 2 * this.options.speedMultiplier;
  
            // fix scrollTop
            scrollTop = Math.min(Math.max(-bouncing.top, scrollTop), maxScrollTop + bouncing.bottom);
  
            // Trigger pull to refresh or push to load
            if (!self.__enableScrollX && (self.__refreshHeight != null || self.__loadHeight != null)) {
              if (!self.__refreshActive && scrollTop <= -self.__refreshHeight) {
                self.__refreshActive = true;
                if (self.__refreshActivate) {
                  self.__refreshActivate();
                }
              } else if (self.__refreshActive && scrollTop > -self.__refreshHeight) {
                self.__refreshActive = false;
                if (self.__refreshDeactivate) {
                  self.__refreshDeactivate();
                }
              }
              // handle for push-load
              else if (!self.__loadActive && scrollTop >= self.__maxScrollTop + self.__loadHeight && self.__loadHeight > 0) {
                  self.__loadActive = true;
                  if (self.__loadActivate) {
                    self.__loadActivate();
                  }
                } else if (self.__loadActive && scrollTop < self.__maxScrollTop + self.__loadHeight) {
                  self.__loadActive = false;
                  if (self.__loadDeactivate) {
                    self.__loadDeactivate();
                  }
                }
            }
          }
        }
  
        // Keep list from growing infinitely (holding min 10, max 20 measure points)
        if (positions.length > 60) {
          positions.splice(0, 30);
        }
  
        // Track scroll movement for decleration
        positions.push(scrollLeft, scrollTop, timeStamp);
  
        // Sync scroll position
        self.__publish(scrollLeft, scrollTop, level);
  
        // Otherwise figure out whether we are switching into dragging mode now.
      } else {
        var minimumTrackingForScroll = self.options.locking ? 3 : 0;
        var minimumTrackingForDrag = 5;
  
        var distanceX = Math.abs(currentTouchLeft - self.__initialTouchLeft);
        var distanceY = Math.abs(currentTouchTop - self.__initialTouchTop);
  
        self.__enableScrollX = self.options.scrollingX && distanceX >= minimumTrackingForScroll;
        self.__enableScrollY = self.options.scrollingY && distanceY >= minimumTrackingForScroll;
  
        positions.push(self.__scrollLeft, self.__scrollTop, timeStamp);
  
        self.__isDragging = (self.__enableScrollX || self.__enableScrollY) && (distanceX >= minimumTrackingForDrag || distanceY >= minimumTrackingForDrag);
        if (self.__isDragging) {
          self.__interruptedAnimation = false;
        }
      }
  
      // Update last touch positions and time stamp for next event
      self.__lastTouchLeft = currentTouchLeft;
      self.__lastTouchTop = currentTouchTop;
      self.__lastTouchMove = timeStamp;
      self.__lastScale = scale;
    },
  
    /**
     * Touch end handler for scrolling support
     */
    doTouchEnd: function doTouchEnd(timeStamp) {
      if (timeStamp instanceof Date) {
        timeStamp = timeStamp.valueOf();
      }
      if (typeof timeStamp !== 'number') {
        throw new Error('Invalid timestamp value: ' + timeStamp);
      }
  
      var self = this;
  
      // Ignore event when tracking is not enabled (no touchstart event on element)
      // This is required as this listener ('touchmove') sits on the document and not on the element itself.
      if (!self.__isTracking) {
        return;
      }
  
      // Not touching anymore (when two finger hit the screen there are two touch end events)
      self.__isTracking = false;
  
      // Be sure to reset the dragging flag now. Here we also detect whether
      // the finger has moved fast enough to switch into a deceleration animation.
      if (self.__isDragging) {
        // Reset dragging flag
        self.__isDragging = false;
  
        // Start deceleration
        // Verify that the last move detected was in some relevant time frame
        if (self.__isSingleTouch && self.options.animating && timeStamp - self.__lastTouchMove <= 100) {
          // Then figure out what the scroll position was about 100ms ago
          var positions = self.__positions;
          var endPos = positions.length - 1;
          var startPos = endPos;
  
          // Move pointer to position measured 100ms ago
          for (var i = endPos; i > 0 && positions[i] > self.__lastTouchMove - 100; i -= 3) {
            startPos = i;
          }
  
          // If start and stop position is identical in a 100ms timeframe,
          // we cannot compute any useful deceleration.
          if (startPos !== endPos) {
            // Compute relative movement between these two points
            var timeOffset = positions[endPos] - positions[startPos];
            var movedLeft = self.__scrollLeft - positions[startPos - 2];
            var movedTop = self.__scrollTop - positions[startPos - 1];
  
            // Based on 50ms compute the movement to apply for each render step
            self.__decelerationVelocityX = movedLeft / timeOffset * (1000 / 60);
            self.__decelerationVelocityY = movedTop / timeOffset * (1000 / 60);
  
            // How much velocity is required to start the deceleration
            var minVelocityToStartDeceleration = self.options.paging || self.options.snapping ? 4 : 1;
  
            // Verify that we have enough velocity to start deceleration
            if (Math.abs(self.__decelerationVelocityX) > minVelocityToStartDeceleration || Math.abs(self.__decelerationVelocityY) > minVelocityToStartDeceleration) {
              // Deactivate pull-to-refresh when decelerating
              if (!self.__refreshActive && !self.__loadActive) {
                self.__startDeceleration(timeStamp);
              }
            } else {
              self.__scrollComplete();
            }
          } else {
            self.__scrollComplete();
          }
        } else if (timeStamp - self.__lastTouchMove > 100) {
          self.__scrollComplete();
        }
      }
  
      // If this was a slower move it is per default non decelerated, but this
      // still means that we want snap back to the bounds which is done here.
      // This is placed outside the condition above to improve edge case stability
      // e.g. touchend fired without enabled dragging. This should normally do not
      // have modified the scroll positions or even showed the scrollbars though.
      if (!self.__isDecelerating) {
        if (self.__refreshActive && self.__refreshStart) {
          // Use publish instead of scrollTo to allow scrolling to out of boundary position
          // We don't need to normalize scrollLeft, zoomLevel, etc. here because we only y-scrolling when pull-to-refresh is enabled
          self.__publish(self.__scrollLeft, -self.__refreshHeight, self.__zoomLevel, true);
  
          if (self.__refreshStart) {
            self.__refreshStart();
          }
        } else if (self.__loadActive && self.__loadStart) {
          // Use publish instead of scrollTo to allow scrolling to out of boundary position
          // We don't need to normalize scrollLeft, zoomLevel, etc. here because we only y-scrolling when pull-to-refresh is enabled
          self.__publish(self.__scrollLeft, self.__maxScrollTop + self.__loadHeight, self.__zoomLevel, true);
  
          if (self.__loadStart) {
            self.__loadStart();
          }
        } else {
          if (self.__interruptedAnimation || self.__isDragging) {
            self.__scrollComplete();
          }
          self.scrollTo(self.__scrollLeft, self.__scrollTop, true, self.__zoomLevel);
  
          // Directly signalize deactivation (nothing todo on refresh?)
          if (self.__refreshActive) {
            self.__refreshActive = false;
            if (self.__refreshDeactivate) {
              self.__refreshDeactivate();
            }
          } else if (self.__loadActive) {
            self.__loadActive = false;
            if (self.__loadDeactivate) {
              self.__loadDeactivate();
            }
          }
        }
      }
  
      // Fully cleanup list
      self.__positions.length = 0;
    },
  
    /** Handle for scroll/publish */
    onScroll: NOOP$1,
  
    stop: function stop() {
      var self = this;
  
      self.__disable = true;
    },
    start: function start() {
      var self = this;
  
      self.__disable = true;
    },
    /*
    ---------------------------------------------------------------------------
    PRIVATE API
    ---------------------------------------------------------------------------
    */
  
    /**
     * Applies the scroll position to the content element
     *
     * @param left {Number} Left scroll position
     * @param top {Number} Top scroll position
     * @param animate {Boolean?false} Whether animation should be used to move to the new coordinates
     */
    __publish: function __publish(left, top, zoom, animate, speed, easing) {
      var self = this;
      if (self.__disable) {
        return;
      }
      if (isNaN(left)) {
        left = this.__scrollLeft;
      }
      if (isNaN(top)) {
        top = this.__scrollTop;
      }
      // Remember whether we had an animation, then we try to continue based on the current "drive" of the animation
      var wasAnimating = self.__isAnimating;
      if (wasAnimating) {
        core.effect.Animate.stop(wasAnimating);
        self.__isAnimating = false;
      }
  
      if (animate && (self.options.animating || speed)) {
        // Keep scheduled positions for scrollBy/zoomBy functionality
        self.__scheduledLeft = left;
        self.__scheduledTop = top;
        self.__scheduledZoom = zoom;
  
        var oldLeft = self.__scrollLeft;
        var oldTop = self.__scrollTop;
        var oldZoom = self.__zoomLevel;
  
        var diffLeft = left - oldLeft;
        var diffTop = top - oldTop;
        var diffZoom = zoom - oldZoom;
  
        var step = function step(percent, now, render) {
          if (render) {
            self.__scrollLeft = oldLeft + diffLeft * percent;
            self.__scrollTop = oldTop + diffTop * percent;
            self.__zoomLevel = oldZoom + diffZoom * percent;
  
            // Push values out
            if (self.__callback) {
              self.__callback(self.__scrollLeft, self.__scrollTop, self.__zoomLevel);
              self.onScroll();
            }
          }
        };
  
        var verify = function verify(id) {
          return self.__isAnimating === id;
        };
  
        var completed = function completed(renderedFramesPerSecond, animationId, wasFinished) {
          if (animationId === self.__isAnimating) {
            self.__isAnimating = false;
          }
          if (self.__didDecelerationComplete || wasFinished) {
            self.__scrollComplete();
          }
  
          if (self.options.zooming) {
            self.__computeScrollMax();
            if (self.__zoomComplete) {
              self.__zoomComplete();
              self.__zoomComplete = null;
            }
          }
  
          if (self.__refreshBeforeDeactiveStarted) {
            self.__refreshBeforeDeactiveStarted = false;
            if (self.__refreshDeactivate) self.__refreshDeactivate();
          }
  
          if (self.__loadBeforeDeactiveStarted) {
            self.__loadBeforeDeactiveStarted = false;
            if (self.__loadDeactivate) self.__loadDeactivate();
          }
        };
  
        var easingFunction = animatingMethod;
        if (easing) {
          easingFunction = createEasingFunction(easing, easingPattern);
        }
  
        // When continuing based on previous animation we choose an ease-out animation instead of ease-in-out
        self.__isAnimating = core.effect.Animate.start(step, verify, completed, speed || self.options.animationDuration, wasAnimating ? easingFunction : noAnimatingMethod);
      } else {
        self.__scheduledLeft = self.__scrollLeft = left;
        self.__scheduledTop = self.__scrollTop = top;
        self.__scheduledZoom = self.__zoomLevel = zoom;
  
        // Push values out
        if (self.__callback) {
          self.__callback(left, top, zoom);
          self.onScroll();
        }
  
        // Fix max scroll ranges
        if (self.options.zooming) {
          self.__computeScrollMax();
          if (self.__zoomComplete) {
            self.__zoomComplete();
            self.__zoomComplete = null;
          }
        }
  
        if (self.__refreshBeforeDeactiveStarted) {
          self.__refreshBeforeDeactiveStarted = false;
          if (self.__refreshDeactivate) self.__refreshDeactivate();
        }
  
        if (self.__loadBeforeDeactiveStarted) {
          self.__loadBeforeDeactiveStarted = false;
          if (self.__loadDeactivate) self.__loadDeactivate();
        }
      }
    },
  
    /**
     * Recomputes scroll minimum values based on client dimensions and content dimensions.
     */
    __computeScrollMax: function __computeScrollMax(zoomLevel) {
      var self = this;
  
      if (zoomLevel == null) {
        zoomLevel = self.__zoomLevel;
      }
  
      self.__maxScrollLeft = Math.max(self.__contentWidth * zoomLevel - self.__clientWidth, 0);
      self.__maxScrollTop = Math.max(self.__contentHeight * zoomLevel - self.__clientHeight, 0);
    },
    /** compute current page total page */
    __computePage: function __computePage() {
      var self = this;
      var clientWidth = self.__clientWidth;
      var clientHeight = self.__clientHeight;
      var left = self.__scrollLeft;
      var top = self.__scrollTop;
      self.__totalXPage = Math.ceil(self.__contentWidth / clientWidth);
      self.__currentPageX = Math.ceil(left / clientWidth + 1);
      self.__totalYPage = Math.ceil(self.__contentHeight / clientHeight);
      self.__currentPageY = Math.ceil(top / clientHeight + 1);
    },
    /** complete scroll*/
    __scrollComplete: function __scrollComplete() {
      var self = this;
      self.options.scrollingComplete();
    },
    /*
    ---------------------------------------------------------------------------
    ANIMATION (DECELERATION) SUPPORT
    ---------------------------------------------------------------------------
    */
  
    /**
     * Called when a touch sequence end and the speed of the finger was high enough
     * to switch into deceleration mode.
     */
    __startDeceleration: function __startDeceleration() {
      var self = this;
  
      if (self.options.paging) {
        var scrollLeft = Math.max(Math.min(self.__scrollLeft, self.__maxScrollLeft), 0);
        var scrollTop = Math.max(Math.min(self.__scrollTop, self.__maxScrollTop), 0);
        var clientWidth = self.__clientWidth;
        var clientHeight = self.__clientHeight;
  
        // We limit deceleration not to the min/max values of the allowed range, but to the size of the visible client area.
        // Each page should have exactly the size of the client area.
        self.__minDecelerationScrollLeft = Math.floor(scrollLeft / clientWidth) * clientWidth;
        self.__minDecelerationScrollTop = Math.floor(scrollTop / clientHeight) * clientHeight;
        self.__maxDecelerationScrollLeft = Math.ceil(scrollLeft / clientWidth) * clientWidth;
        self.__maxDecelerationScrollTop = Math.ceil(scrollTop / clientHeight) * clientHeight;
      } else {
        self.__minDecelerationScrollLeft = 0;
        self.__minDecelerationScrollTop = 0;
        self.__maxDecelerationScrollLeft = self.__maxScrollLeft;
        self.__maxDecelerationScrollTop = self.__maxScrollTop;
      }
  
      // Wrap class method
      var step = function step(percent, now, render) {
        self.__stepThroughDeceleration(render);
      };
  
      // How much velocity is required to keep the deceleration running
      var minVelocityToKeepDecelerating = self.options.snapping ? 4 : 0.001;
  
      // Detect whether it's still worth to continue animating steps
      // If we are already slow enough to not being user perceivable anymore, we stop the whole process here.
      var verify = function verify() {
        var shouldContinue = Math.abs(self.__decelerationVelocityX) >= minVelocityToKeepDecelerating || Math.abs(self.__decelerationVelocityY) >= minVelocityToKeepDecelerating;
        if (!shouldContinue) {
          self.__didDecelerationComplete = true;
        }
        return shouldContinue;
      };
  
      var completed = function completed() {
        if (!self.__isDecelerating) {
          return;
        }
        self.__isDecelerating = false;
        if (self.__didDecelerationComplete) {
          self.__scrollComplete();
        }
  
        // Animate to grid when snapping is active, otherwise just fix out-of-boundary positions
        self.scrollTo(self.__scrollLeft, self.__scrollTop, self.options.snapping);
      };
  
      // Start animation and switch on flag
      self.__isDecelerating = core.effect.Animate.start(step, verify, completed);
    },
  
    /**
     * Called on every step of the animation
     *
     * @param inMemory {Boolean?false} Whether to not render the current step, but keep it in memory only. Used internally only!
     */
    __stepThroughDeceleration: function __stepThroughDeceleration(render) {
      var self = this;
      var bouncing = self.options.bouncing;
      var minLeft = self.__minDecelerationScrollLeft;
      var maxLeft = self.__maxDecelerationScrollLeft;
      var minTop = self.__minDecelerationScrollTop;
      var maxTop = self.__maxDecelerationScrollTop;
      // Add deceleration to scroll position
      var scrollLeft = self.__scrollLeft + self.__decelerationVelocityX;
      var scrollTop = self.__scrollTop + self.__decelerationVelocityY;
  
      var bounceX = scrollLeft < minLeft || scrollLeft > maxLeft;
      var bounceY = scrollTop < minTop || scrollTop > maxTop;
  
      // fix scrollLeft and scrollTop
      var fixedScrollLeft = Math.min(Math.max(minLeft - bouncing.left, scrollLeft), maxLeft + bouncing.right);
  
      var fixedScrollTop = Math.min(Math.max(minTop - bouncing.top, scrollTop), maxTop + bouncing.bottom);
  
      //
      // UPDATE SCROLL POSITION
      //
      if (render) {
        self.__publish(fixedScrollLeft, fixedScrollTop, self.__zoomLevel);
      } else {
        self.__scrollLeft = scrollLeft;
        self.__scrollTop = scrollTop;
      }
  
      //
      // SLOW DOWN
      //
  
      // Slow down velocity on every iteration
      if (!self.options.paging) {
        // This is the factor applied to every iteration of the animation
        // to slow down the process. This should emulate natural behavior where
        // objects slow down when the initiator of the movement is removed
        var frictionFactor = 0.95;
  
        self.__decelerationVelocityX *= frictionFactor;
        self.__decelerationVelocityY *= frictionFactor;
      }
  
      //
      // BOUNCING SUPPORT
      //
  
      var scrollOutsideX = 0;
      var scrollOutsideY = 0;
  
      // This configures the amount of change applied to deceleration/acceleration when reaching boundaries
      var penetrationDeceleration = self.options.penetrationDeceleration;
      var penetrationAcceleration = self.options.penetrationAcceleration;
  
      if (bounceX) {
        // Check limits
        if (scrollLeft < self.__minDecelerationScrollLeft) {
          scrollOutsideX = self.__minDecelerationScrollLeft - scrollLeft;
        } else if (scrollLeft > self.__maxDecelerationScrollLeft) {
          scrollOutsideX = self.__maxDecelerationScrollLeft - scrollLeft;
        }
      }
  
      if (bounceY) {
        if (scrollTop < self.__minDecelerationScrollTop) {
          scrollOutsideY = self.__minDecelerationScrollTop - scrollTop;
        } else if (scrollTop > self.__maxDecelerationScrollTop) {
          scrollOutsideY = self.__maxDecelerationScrollTop - scrollTop;
        }
      }
  
      if (scrollOutsideX !== 0) {
        if (scrollOutsideX * self.__decelerationVelocityX <= 0) {
          self.__decelerationVelocityX += scrollOutsideX * penetrationDeceleration;
          if (scrollOutsideX < 0 && -scrollOutsideX >= bouncing.right && self.__decelerationVelocityX > 0) {
            self.__decelerationVelocityX = -bouncing.right / 2;
          }
          if (scrollOutsideX > 0 && scrollOutsideX >= bouncing.left && self.__decelerationVelocityX < 0) {
            self.__decelerationVelocityX = bouncing.left / 2;
          }
        } else {
          self.__decelerationVelocityX = scrollOutsideX * penetrationAcceleration;
        }
      }
  
      if (scrollOutsideY !== 0) {
        if (scrollOutsideY * self.__decelerationVelocityY <= 0) {
          self.__decelerationVelocityY += scrollOutsideY * penetrationDeceleration;
          if (scrollOutsideY < 0 && -scrollOutsideY >= bouncing.bottom && self.__decelerationVelocityY > 0) {
            self.__decelerationVelocityY = -bouncing.bottom / 2;
          }
          if (scrollOutsideY > 0 && scrollOutsideY >= bouncing.top && self.__decelerationVelocityY < 0) {
            self.__decelerationVelocityY = bouncing.top / 2;
          }
        } else {
          self.__decelerationVelocityY = scrollOutsideY * penetrationAcceleration / 2;
        }
      }
    }
  };
  
  // Copy over members to prototype
  for (var key in members) {
    Scroller.prototype[key] = members[key];
  }
  
  /* DOM-based rendering (Uses 3D when available, falls back on margin when transform not available) */
  function render(content, global, suffix, type) {
    if (type == 'position') {
      return function (left, top) {
        content.style.left = -left + 'px';
        content.style.top = -top + 'px';
      };
    }
  
    var vendorPrefix = getPrefix(global);
  
    var helperElem = document.createElement('div');
    var undef;
  
    var perspectiveProperty = vendorPrefix + 'Perspective';
    var transformProperty = 'transform'; //vendorPrefix + 'Transform';
  
    if (helperElem.style[perspectiveProperty] !== undef) {
      return function (left, top, zoom) {
        content.style[transformProperty] = 'translate3d(' + -left + suffix + ',' + -top + suffix + ',0) scale(' + zoom + ')';
      };
    } else if (helperElem.style[transformProperty] !== undef) {
      return function (left, top, zoom) {
        content.style[transformProperty] = 'translate(' + -left + suffix + ',' + -top + suffix + ') scale(' + zoom + ')';
      };
    }
  }
  
  var touch = new touchManager();
  function listenContainer(container, scroller, eventCallback, zooming, preventDefault, preventDefaultOnMove) {
    var destroy = null;
    var mousedown = false;
    var touchObj = touch.getTouchObject();
  
    function touchstart(e) {
      var event = touch.getEventObject(e);
      // Don't react if initial down happens on a form element
      if (event[0] && event[0].target && event[0].target.tagName.match(/input|textarea|select/i) || scroller.__disable) {
        return;
      }
      eventCallback('mousedown');
      mousedown = true;
      scroller.doTouchStart(event, e.timeStamp);
  
      if (preventDefault) {
        e.preventDefault();
      }
      e.stopPropagation();
  
      // here , we want to manully prevent default, so we
      // set passive to false
      // see https://developer.mozilla.org/zh-CN/docs/Web/API/EventTarget/addEventListener
      document.addEventListener(touchObj.touchmove, touchmove, {
        passive: false
      });
    }
  
    function touchmove(e) {
      if (scroller.__disable || !mousedown) return;
  
      var event = touch.getEventObject(e);
      eventCallback('mousemove');
      scroller.doTouchMove(event, e.timeStamp, e.scale);
      if (preventDefaultOnMove) {
        e.preventDefault();
      }
    }
  
    function touchend(e) {
      eventCallback('mouseup');
      mousedown = false;
      scroller.doTouchEnd(e.timeStamp);
      document.removeEventListener(touchObj.touchmove, touchmove);
    }
    function touchcancel(e) {
      scroller.doTouchEnd(e.timeStamp);
    }
  
    function zoomHandle(e) {
      scroller.doMouseZoom(e.detail ? e.detail * -120 : e.wheelDelta, e.timeStamp, e.pageX, e.pageY);
    }
  
    container.addEventListener(touchObj.touchstart, touchstart, false);
  
    document.addEventListener(touchObj.touchend, touchend, false);
    document.addEventListener(touchObj.touchcancel, touchcancel, false);
  
    if (zooming && !touch.isTouch) {
      container.addEventListener(navigator.userAgent.indexOf('Firefox') > -1 ? 'DOMMouseScroll' : 'mousewheel', zoomHandle, false);
    }
  
    destroy = function destroy() {
      container.removeEventListener(touchObj.touchstart, touchstart, false);
  
      document.removeEventListener(touchObj.touchend, touchend, false);
      document.removeEventListener(touchObj.touchcancel, touchcancel, false);
  
      container.removeEventListener(navigator.userAgent.indexOf('Firefox') > -1 ? 'DOMMouseScroll' : 'mousewheel', zoomHandle, false);
    };
  
    // handle __publish event
    scroller.onScroll = function () {
      eventCallback('onscroll');
    };
    return destroy;
  }
  
  /**
   * These mixes is exclusive for slide mode
   */
  
  createSlideModeStyle();
  /**
   * @description refresh and load callback
   */
  function createStateCallbacks(type, stageType, vm, tipDom) {
    var listeners = vm.$listeners;
  
    var activateCallback = function activateCallback() {
      vm.vuescroll.state[stageType] = 'active';
      vm.$emit(type + '-activate', vm, tipDom);
    };
  
    var deactivateCallback = function deactivateCallback() {
      vm.vuescroll.state[stageType] = 'deactive';
      vm.$emit(type + '-deactivate', vm, tipDom);
    };
  
    var beforeDeactiveEnd = function beforeDeactiveEnd() {
      vm.vuescroll.state[stageType] = 'beforeDeactiveEnd';
      vm.$emit(type + '-before-deactivate-end', vm, tipDom);
    };
  
    var startCallback = function startCallback() {
      vm.vuescroll.state[stageType] = 'start';
      setTimeout(function () {
        vm.scroller.finishRefreshOrLoad();
      }, 2000); // Default start stage duration
    };
  
    // let beforeDeactivateCallback = done => {
    //   vm.vuescroll.state[stageType] = 'beforeDeactive';
    //   setTimeout(function() {
    //     done();
    //   }, 500); // Default before-deactivated stage duration
    // };
    var beforeDeactivateCallback = void 0;
  
    /* istanbul ignore if */
    if (listeners[type + '-before-deactivate']) {
      beforeDeactivateCallback = function beforeDeactivateCallback(done) {
        vm.vuescroll.state[stageType] = 'beforeDeactive';
        vm.$emit(type + '-before-deactivate', vm, tipDom, done.bind(vm.scroller));
      };
    }
  
    /* istanbul ignore if */
    if (listeners[type + '-start']) {
      startCallback = function startCallback() {
        vm.vuescroll.state[stageType] = 'start';
        vm.$emit(type + '-start', vm, tipDom, vm.scroller.finishRefreshOrLoad.bind(vm.scroller));
      };
    }
  
    return {
      activateCallback: activateCallback,
      deactivateCallback: deactivateCallback,
      startCallback: startCallback,
      beforeDeactivateCallback: beforeDeactivateCallback,
      beforeDeactiveEnd: beforeDeactiveEnd
    };
  }
  
  var update = {
    mounted: function mounted() {
      this.vsMounted = true;
    },
  
    computed: {
      pullRefreshTip: function pullRefreshTip() {
        return this.mergedOptions.vuescroll.pullRefresh.tips[this.vuescroll.state.refreshStage];
      },
      pushLoadTip: function pushLoadTip() {
        return this.mergedOptions.vuescroll.pushLoad.tips[this.vuescroll.state.loadStage];
      },
      refreshLoad: function refreshLoad() {
        return this.mergedOptions.vuescroll.pullRefresh.enable || this.mergedOptions.vuescroll.pushLoad.enable;
      },
      refrehDomVisiable: function refrehDomVisiable() {
        return this.vsMounted && this.outTheTopBoundary;
      },
      loadDomVisiable: function loadDomVisiable() {
        return this.vsMounted && this.outTheBottomBoundary;
      }
    },
    data: function data() {
      return {
        vuescroll: {
          state: {
            /** Default tips of refresh and load */
            refreshStage: 'deactive',
            loadStage: 'deactive'
          }
        },
        vsMounted: false,
        outTheTopBoundary: false,
        outTheBottomBoundary: false
      };
    },
  
    methods: {
      // Update:
      // 1. update height/width
      // 2. update refresh or load
      updateScroller: function updateScroller() {
        this.updateDimesion();
        this.registryRefreshLoad();
      },
      updateDimesion: function updateDimesion() {
        var clientWidth = this.$el.clientWidth;
        var clientHeight = this.$el.clientHeight;
        var contentWidth = this.scrollPanelElm.scrollWidth;
        var contentHeight = this.scrollPanelElm.scrollHeight;
        var refreshHeight = 0;
        var loadHeight = 0;
        // If the refresh option is true,let's  give a "margin-top" style to
        // the refresh-tip dom. let it to be invisible when doesn't trigger
        // refresh.
        if (this.mergedOptions.vuescroll.pullRefresh.enable) {
          if (this.vsMounted) {
            var refreshDom = this.$refs[__REFRESH_DOM_NAME].elm || this.$refs[__REFRESH_DOM_NAME];
            refreshHeight = refreshDom.offsetHeight;
            refreshDom.style.marginTop = -refreshHeight + 'px';
          }
        }
        if (this.mergedOptions.vuescroll.pushLoad.enable) {
          if (this.vsMounted) {
            var loadDom = this.$refs[__LOAD_DOM_NAME].elm || this.$refs[__LOAD_DOM_NAME];
            loadHeight = loadDom.offsetHeight;
            contentHeight -= loadHeight;
            loadDom.style.bottom = '-' + loadHeight + 'px';
          }
        }
        if (this.scroller) {
          this.scroller.setDimensions(clientWidth, clientHeight, contentWidth, contentHeight, false);
        }
      },
      registryRefreshLoad: function registryRefreshLoad() {
        // registry refresh
        if (this.mergedOptions.vuescroll.pullRefresh.enable) {
          this.registryEvent('refresh');
        }
        // registry load
        if (this.mergedOptions.vuescroll.pushLoad.enable) {
          this.registryEvent('load');
        }
      },
      registryScroller: function registryScroller() {
        var _this = this;
  
        var _ref = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : {},
            _ref$left = _ref.left,
            left = _ref$left === undefined ? 0 : _ref$left,
            _ref$top = _ref.top,
            top = _ref$top === undefined ? 0 : _ref$top,
            _ref$zoom = _ref.zoom,
            zoom = _ref$zoom === undefined ? 1 : _ref$zoom;
  
        var _mergedOptions$vuescr = this.mergedOptions.vuescroll.scroller,
            preventDefault = _mergedOptions$vuescr.preventDefault,
            preventDefaultOnMove = _mergedOptions$vuescr.preventDefaultOnMove;
        var _mergedOptions$vuescr2 = this.mergedOptions.vuescroll,
            paging = _mergedOptions$vuescr2.paging,
            snapping = _mergedOptions$vuescr2.snapping.enable,
            renderMethod = _mergedOptions$vuescr2.renderMethod,
            zooming = _mergedOptions$vuescr2.zooming;
        // disale zooming when refresh or load enabled
  
        zooming = !this.refreshLoad && !paging && !snapping && zooming;
        var _mergedOptions$scroll = this.mergedOptions.scrollPanel,
            scrollingY = _mergedOptions$scroll.scrollingY,
            scrollingX = _mergedOptions$scroll.scrollingX;
  
  
        var scrollingComplete = this.scrollingComplete.bind(this);
  
        // Initialize Scroller
        this.scroller = new Scroller(render(this.scrollPanelElm, window, 'px', renderMethod), _extends({}, this.mergedOptions.vuescroll.scroller, {
          zooming: zooming,
          scrollingY: scrollingY,
          scrollingX: scrollingX && !this.refreshLoad,
          animationDuration: this.mergedOptions.scrollPanel.speed,
          paging: paging,
          snapping: snapping,
          scrollingComplete: scrollingComplete
        }));
  
        this.scroller.__disable = this.mergedOptions.vuescroll.scroller.disable;
        this.scroller.__scrollLeft = left;
        this.scroller.__scrollTop = top;
        this.scroller.__zoomLevel = zoom;
  
        // Set snap
        if (snapping) {
          this.scroller.setSnapSize(this.mergedOptions.vuescroll.snapping.width, this.mergedOptions.vuescroll.snapping.height);
        }
        var rect = this.$el.getBoundingClientRect();
        this.scroller.setPosition(rect.left + this.$el.clientLeft, rect.top + this.$el.clientTop);
  
        // Get destroy callback
        var cb = listenContainer(this.$el, this.scroller, function (eventType) {
          // Thie is to dispatch the event from the scroller.
          // to let vuescroll refresh the dom
          switch (eventType) {
            case 'mousedown':
              _this.vuescroll.state.isDragging = true;
              break;
            case 'onscroll':
              {
                /**
                   * Trigger auto load
                   */
                var stage = _this.vuescroll.state['loadStage'];
                var _mergedOptions$vuescr3 = _this.mergedOptions.vuescroll.pushLoad,
                    enable = _mergedOptions$vuescr3.enable,
                    auto = _mergedOptions$vuescr3.auto,
                    autoLoadDistance = _mergedOptions$vuescr3.autoLoadDistance;
                var _scroller = _this.scroller,
                    __scrollTop = _scroller.__scrollTop,
                    __maxScrollTop = _scroller.__maxScrollTop;
  
                if (stage != 'start' && enable && auto && !_this.lockAutoLoad && // auto load debounce
                autoLoadDistance >= __maxScrollTop - __scrollTop && __scrollTop > 0) {
                  _this.lockAutoLoad = true;
                  _this.triggerRefreshOrLoad('load');
                }
  
                if (autoLoadDistance < __maxScrollTop - __scrollTop) {
                  _this.lockAutoLoad = false;
                }
  
                _this.handleScroll(false);
              }
  
              break;
            case 'mouseup':
              _this.vuescroll.state.isDragging = false;
              break;
          }
        }, zooming, preventDefault, preventDefaultOnMove);
  
        this.updateScroller();
  
        return cb;
      },
      updateSlideModeBarState: function updateSlideModeBarState() {
        // update slide mode scrollbars' state
        var heightPercentage = void 0,
            widthPercentage = void 0;
        var vuescroll = this.$el;
        var scroller = this.scroller;
  
        var outerLeft = 0;
        var outerTop = 0;
  
        var _$el = this.$el,
            clientWidth = _$el.clientWidth,
            clientHeight = _$el.clientHeight;
  
  
        var contentWidth = clientWidth + this.scroller.__maxScrollLeft;
        var contentHeight = clientHeight + this.scroller.__maxScrollTop;
  
        // We should add the the height or width that is
        // out of horizontal bountry  to the total length
  
        /* istanbul ignore if */
        if (scroller.__scrollLeft < 0) {
          outerLeft = -scroller.__scrollLeft;
        } /* istanbul ignore next */else if (scroller.__scrollLeft > scroller.__maxScrollLeft) {
            outerLeft = scroller.__scrollLeft - scroller.__maxScrollLeft;
          }
  
        // out of vertical bountry
        if (scroller.__scrollTop < 0) {
          outerTop = -scroller.__scrollTop;
          this.outTheBottomBoundary = false;
          this.outTheTopBoundary = true;
        } else if (scroller.__scrollTop > scroller.__maxScrollTop) {
          outerTop = scroller.__scrollTop - scroller.__maxScrollTop;
          this.outTheTopBoundary = false;
          this.outTheBottomBoundary = true;
        } else {
          this.outTheTopBoundary = this.outTheBottomBoundary = false;
        }
  
        heightPercentage = clientHeight / (contentHeight + outerTop);
        widthPercentage = clientWidth / (contentWidth + outerLeft);
  
        var scrollTop = Math.min(Math.max(0, scroller.__scrollTop), scroller.__maxScrollTop);
        var scrollLeft = Math.min(Math.max(0, scroller.__scrollLeft), scroller.__maxScrollLeft);
  
        this.bar.vBar.state.posValue = (scrollTop + outerTop) * 100 / vuescroll.clientHeight;
        this.bar.hBar.state.posValue = (scrollLeft + outerLeft) * 100 / vuescroll.clientWidth;
  
        /* istanbul ignore if */
        if (scroller.__scrollLeft < 0) {
          this.bar.hBar.state.posValue = 0;
        }
        if (scroller.__scrollTop < 0) {
          this.bar.vBar.state.posValue = 0;
        }
  
        this.bar.vBar.state.size = heightPercentage < 1 ? heightPercentage : 0;
        this.bar.hBar.state.size = widthPercentage < 1 ? widthPercentage : 0;
      },
      registryEvent: function registryEvent(type) {
        var domName = type == 'refresh' ? __REFRESH_DOM_NAME : __LOAD_DOM_NAME;
        var activateFunc = type == 'refresh' ? this.scroller.activatePullToRefresh : this.scroller.activatePushToLoad;
        var stageType = type == 'refresh' ? 'refreshStage' : 'loadStage';
        var tipDom = this.$refs[domName].elm || this.$refs[domName];
        var cbs = createStateCallbacks(type, stageType, this, tipDom);
        var height = tipDom.offsetHeight;
  
        activateFunc.bind(this.scroller)(height, cbs);
      },
      getSlidePosition: function getSlidePosition() {
        return {
          scrollLeft: this.scroller.__scrollLeft,
          scrollTop: this.scroller.__scrollTop
        };
      }
    }
  };
  
  var mixins = [api$2, update];
  
  var core$1 = {
    mixins: mixins,
    mounted: function mounted() {
      var _this = this;
  
      this.$nextTick(function () {
        if (!_this._isDestroyed && !_this.renderError) {
          _this.updatedCbs.push(function () {
            _this.updateScroller();
          });
  
          _this.$watch('mergedOptions.vuescroll.scroller.disable', {
            sync: true,
            handler: function handler(newVal) {
              if (this.scroller) {
                this.scroller.__disable = newVal;
              }
            }
          });
        }
      });
    },
  
    methods: {
      destroy: function destroy() {
        /* istanbul ignore next */
        if (this.destroyScroller) {
          this.scroller.stop();
          this.destroyScroller();
          this.destroyScroller = null;
        }
  
        /* istanbul ignore next */
        if (this.destroyResize) {
          this.destroyResize();
        }
      },
      getCurrentviewDom: function getCurrentviewDom() {
        return this.getCurrentviewDomSlide();
      },
      internalScrollTo: function internalScrollTo(destX, destY, speed, sasing) {
        this.slideScrollTo(destX, destY, speed, sasing);
      },
      handleScroll: function handleScroll(nativeEvent) {
        this.updateBarStateAndEmitEvent('handle-scroll', nativeEvent);
      },
      updateBarStateAndEmitEvent: function updateBarStateAndEmitEvent(eventType) {
        var nativeEvent = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : null;
  
        if (!this.scroller) {
          return;
        }
        this.updateSlideModeBarState();
        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() {
        var _scrollPanelElm = this.scrollPanelElm,
            scrollHeight = _scrollPanelElm.scrollHeight,
            scrollWidth = _scrollPanelElm.scrollWidth,
            clientHeight = _scrollPanelElm.clientHeight,
            clientWidth = _scrollPanelElm.clientWidth,
            scrollTop = _scrollPanelElm.scrollTop,
            scrollLeft = _scrollPanelElm.scrollLeft;
  
  
        scrollHeight = this.scroller.__contentHeight;
        scrollWidth = this.scroller.__contentWidth;
        scrollTop = this.scroller.__scrollTop;
        scrollLeft = this.scroller.__scrollLeft;
        clientHeight = this.$el.clientHeight;
        clientWidth = this.$el.clientWidth;
  
        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 _scrollPanelElm2 = this.scrollPanelElm,
            scrollTop = _scrollPanelElm2.scrollTop,
            scrollLeft = _scrollPanelElm2.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;
      },
      refreshMode: function refreshMode() {
        var initPos = void 0;
        if (this.scroller) {
          initPos = this.scroller.getValues();
        }
  
        if (this.destroyScroller) {
          this.scroller.stop();
          this.destroyScroller();
          this.destroyScroller = null;
        }
        this.destroyScroller = this.registryScroller(initPos);
      },
      refreshInternalStatus: function refreshInternalStatus() {
        // 1.set vuescroll height or width according to
        // sizeStrategy
        this.setVsSize();
        // 2. registry resize event
        this.registryResize();
        // 3. registry scroller if mode is 'slide'
        // or remove 'transform origin' is the mode is not `slide`
        this.refreshMode();
        // 4. update scrollbar's height/width
        this.updateBarStateAndEmitEvent('refresh-status');
      },
      registryResize: function registryResize() {
        var _this2 = 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.scrollPanelElm;
        var vm = this;
        var handleWindowResize = function handleWindowResize() /* istanbul ignore next */{
          vm.updateBarStateAndEmitEvent('window-resize');
          vm.updatedCbs.push(vm.updateScroller);
          vm.$forceUpdate();
        };
  
        var handleDomResize = function handleDomResize() {
          var currentSize = {};
          currentSize['width'] = _this2.scroller.__contentWidth;
          currentSize['height'] = _this2.scroller.__contentHeight;
          _this2.updateBarStateAndEmitEvent('handle-resize', currentSize);
          // update scroller should after rendering
          _this2.updatedCbs.push(_this2.updateScroller);
          _this2.$forceUpdate();
  
          // 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 = resizeEnable ? installResizeDetection(contentElm, handleDomResize) : NOOP;
        var destroyWindowResize = function destroyWindowResize() {
          window.removeEventListener('resize', handleWindowResize, false);
        };
  
        this.destroyResize = function () {
          destroyWindowResize();
          destroyDomResize();
  
          _this2.destroyResize = null;
        };
      },
      getPosition: function getPosition() {
        return this.getSlidePosition();
      }
    }
  };
  
  /**
   * The slide mode config
   */
  var config = {
    // vuescroll
    vuescroll: {
      // position or transform
      renderMethod: 'transform',
      // pullRefresh or pushLoad is only for the slide mode...
      pullRefresh: {
        enable: false,
        tips: {
          deactive: 'Pull to Refresh',
          active: 'Release to Refresh',
          start: 'Refreshing...',
          beforeDeactive: 'Refresh Successfully!'
        }
      },
      pushLoad: {
        enable: false,
        tips: {
          deactive: 'Push to Load',
          active: 'Release to Load',
          start: 'Loading...',
          beforeDeactive: 'Load Successfully!'
        },
        auto: false,
        autoLoadDistance: 0
      },
      paging: false,
      zooming: true,
      snapping: {
        enable: false,
        width: 100,
        height: 100
      },
      /* some scroller options */
      scroller: {
        /** Enable bouncing (content can be slowly moved outside and jumps back after releasing) */
        bouncing: {
          top: 100,
          bottom: 100,
          left: 100,
          right: 100
        },
        /** Enable locking to the main axis if user moves only slightly on one of them at start */
        locking: true,
        /** Minimum zoom level */
        minZoom: 0.5,
        /** Maximum zoom level */
        maxZoom: 3,
        /** Multiply or decrease scrolling speed **/
        speedMultiplier: 1,
        /** This configures the amount of change applied to deceleration when reaching boundaries  **/
        penetrationDeceleration: 0.03,
        /** This configures the amount of change applied to acceleration when reaching boundaries  **/
        penetrationAcceleration: 0.08,
        /** Whether call e.preventDefault event when sliding the content or not */
        preventDefault: false,
        /** Whether call preventDefault when (mouse/touch)move*/
        preventDefaultOnMove: true,
        disable: false
      }
    }
  };
  /**
   * validate the options
   * @export
   * @param {any} ops
   */
  function configValidator(ops) {
    var renderError = false;
    var vuescroll = ops.vuescroll;
  
    // validate pushLoad, pullReresh, snapping
  
    if (vuescroll.paging == vuescroll.snapping.enable && vuescroll.paging && (vuescroll.pullRefresh || vuescroll.pushLoad)) {
      error('paging, snapping, (pullRefresh with pushLoad) can only one of them to be true.');
    }
  
    return renderError;
  }
  
  var component = _install(core$1, createPanel, [config], [configValidator]);
  
  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.14.4',
    refreshAll: refreshAll,
    scrollTo: scrollTo
  }, component);
  
  /* istanbul ignore if */
  if (typeof window !== 'undefined' && window.Vue) {
    window.Vue.use(Vuescroll);
  }
  
  return Vuescroll;
  
  })));
  