cube-ui
Version:
A fantastic mobile ui lib implement by Vue
1,789 lines (1,531 loc) • 96.2 kB
JavaScript
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else if(typeof exports === 'object')
exports["better-scroll"] = factory();
else
root["cube"] = root["cube"] || {}, root["cube"]["better-scroll"] = factory();
})(typeof self !== 'undefined' ? self : this, function() {
return /******/ (function(modules) { // webpackBootstrap
/******/ // The module cache
/******/ var installedModules = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/
/******/ // Check if module is in cache
/******/ if(installedModules[moduleId]) {
/******/ return installedModules[moduleId].exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = installedModules[moduleId] = {
/******/ i: moduleId,
/******/ l: false,
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ modules[moduleId].call(module.exports, module, module.exports, __webpack_require__);
/******/
/******/ // Flag the module as loaded
/******/ module.l = true;
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = modules;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = installedModules;
/******/
/******/ // define getter function for harmony exports
/******/ __webpack_require__.d = function(exports, name, getter) {
/******/ if(!__webpack_require__.o(exports, name)) {
/******/ Object.defineProperty(exports, name, {
/******/ configurable: false,
/******/ enumerable: true,
/******/ get: getter
/******/ });
/******/ }
/******/ };
/******/
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function getDefault() { return module['default']; } :
/******/ function getModuleExports() { return module; };
/******/ __webpack_require__.d(getter, 'a', getter);
/******/ return getter;
/******/ };
/******/
/******/ // Object.prototype.hasOwnProperty.call
/******/ __webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };
/******/
/******/ // __webpack_public_path__
/******/ __webpack_require__.p = "./";
/******/
/******/ // Load entry module and return exports
/******/ return __webpack_require__(__webpack_require__.s = 282);
/******/ })
/************************************************************************/
/******/ ({
/***/ 282:
/***/ (function(module, exports, __webpack_require__) {
var __WEBPACK_AMD_DEFINE_FACTORY__, __WEBPACK_AMD_DEFINE_ARRAY__, __WEBPACK_AMD_DEFINE_RESULT__;(function (global, factory) {
if (true) {
!(__WEBPACK_AMD_DEFINE_ARRAY__ = [module, exports, __webpack_require__(90)], __WEBPACK_AMD_DEFINE_FACTORY__ = (factory),
__WEBPACK_AMD_DEFINE_RESULT__ = (typeof __WEBPACK_AMD_DEFINE_FACTORY__ === 'function' ?
(__WEBPACK_AMD_DEFINE_FACTORY__.apply(exports, __WEBPACK_AMD_DEFINE_ARRAY__)) : __WEBPACK_AMD_DEFINE_FACTORY__),
__WEBPACK_AMD_DEFINE_RESULT__ !== undefined && (module.exports = __WEBPACK_AMD_DEFINE_RESULT__));
} else if (typeof exports !== "undefined") {
factory(module, exports, require('better-scroll'));
} else {
var mod = {
exports: {}
};
factory(mod, mod.exports, global.betterScroll);
global.index = mod.exports;
}
})(this, function (module, exports, _betterScroll) {
'use strict';
Object.defineProperty(exports, "__esModule", {
value: true
});
var _betterScroll2 = _interopRequireDefault(_betterScroll);
function _interopRequireDefault(obj) {
return obj && obj.__esModule ? obj : {
default: obj
};
}
exports.default = _betterScroll2.default;
module.exports = exports['default'];
});
/***/ }),
/***/ 90:
/***/ (function(module, __webpack_exports__, __webpack_require__) {
"use strict";
Object.defineProperty(__webpack_exports__, "__esModule", { value: true });
/*!
* better-normal-scroll v1.12.6
* (c) 2016-2018 ustbhuangyi
* Released under the MIT License.
*/
var slicedToArray = function () {
function sliceIterator(arr, i) {
var _arr = [];
var _n = true;
var _d = false;
var _e = undefined;
try {
for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {
_arr.push(_s.value);
if (i && _arr.length === i) break;
}
} catch (err) {
_d = true;
_e = err;
} finally {
try {
if (!_n && _i["return"]) _i["return"]();
} finally {
if (_d) throw _e;
}
}
return _arr;
}
return function (arr, i) {
if (Array.isArray(arr)) {
return arr;
} else if (Symbol.iterator in Object(arr)) {
return sliceIterator(arr, i);
} else {
throw new TypeError("Invalid attempt to destructure non-iterable instance");
}
};
}();
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 eventMixin(BScroll) {
BScroll.prototype.on = function (type, fn) {
var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this;
if (!this._events[type]) {
this._events[type] = [];
}
this._events[type].push([fn, context]);
};
BScroll.prototype.once = function (type, fn) {
var context = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : this;
function magic() {
this.off(type, magic);
fn.apply(context, arguments);
}
// To expose the corresponding function method in order to execute the off method
magic.fn = fn;
this.on(type, magic);
};
BScroll.prototype.off = function (type, fn) {
var _events = this._events[type];
if (!_events) {
return;
}
var count = _events.length;
while (count--) {
if (_events[count][0] === fn || _events[count][0] && _events[count][0].fn === fn) {
_events[count][0] = undefined;
}
}
};
BScroll.prototype.trigger = function (type) {
var events = this._events[type];
if (!events) {
return;
}
var len = events.length;
var eventsCopy = [].concat(toConsumableArray(events));
for (var i = 0; i < len; i++) {
var event = eventsCopy[i];
var _event = slicedToArray(event, 2),
fn = _event[0],
context = _event[1];
if (fn) {
fn.apply(context, [].slice.call(arguments, 1));
}
}
};
}
// ssr support
var inBrowser = typeof window !== 'undefined';
var ua = inBrowser && navigator.userAgent.toLowerCase();
var isWeChatDevTools = ua && /wechatdevtools/.test(ua);
var isAndroid = ua && ua.indexOf('android') > 0;
function getNow() {
return window.performance && window.performance.now ? window.performance.now() + window.performance.timing.navigationStart : +new Date();
}
function extend(target) {
for (var _len = arguments.length, rest = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
rest[_key - 1] = arguments[_key];
}
for (var i = 0; i < rest.length; i++) {
var source = rest[i];
for (var key in source) {
target[key] = source[key];
}
}
return target;
}
function isUndef(v) {
return v === undefined || v === null;
}
function getDistance(x, y) {
return Math.sqrt(x * x + y * y);
}
var elementStyle = inBrowser && document.createElement('div').style;
var vendor = function () {
if (!inBrowser) {
return false;
}
var transformNames = {
webkit: 'webkitTransform',
Moz: 'MozTransform',
O: 'OTransform',
ms: 'msTransform',
standard: 'transform'
};
for (var key in transformNames) {
if (elementStyle[transformNames[key]] !== undefined) {
return key;
}
}
return false;
}();
function prefixStyle(style) {
if (vendor === false) {
return false;
}
if (vendor === 'standard') {
if (style === 'transitionEnd') {
return 'transitionend';
}
return style;
}
return vendor + style.charAt(0).toUpperCase() + style.substr(1);
}
function addEvent(el, type, fn, capture) {
el.addEventListener(type, fn, { passive: false, capture: !!capture });
}
function removeEvent(el, type, fn, capture) {
el.removeEventListener(type, fn, { passive: false, capture: !!capture });
}
function offset(el) {
var left = 0;
var top = 0;
while (el) {
left -= el.offsetLeft;
top -= el.offsetTop;
el = el.offsetParent;
}
return {
left: left,
top: top
};
}
function offsetToBody(el) {
var rect = el.getBoundingClientRect();
return {
left: -(rect.left + window.pageXOffset),
top: -(rect.top + window.pageYOffset)
};
}
var transform = prefixStyle('transform');
var hasPerspective = inBrowser && prefixStyle('perspective') in elementStyle;
// fix issue #361
var hasTouch = inBrowser && ('ontouchstart' in window || isWeChatDevTools);
var hasTransform = transform !== false;
var hasTransition = inBrowser && prefixStyle('transition') in elementStyle;
var style = {
transform: transform,
transitionTimingFunction: prefixStyle('transitionTimingFunction'),
transitionDuration: prefixStyle('transitionDuration'),
transitionDelay: prefixStyle('transitionDelay'),
transformOrigin: prefixStyle('transformOrigin'),
transitionEnd: prefixStyle('transitionEnd')
};
var TOUCH_EVENT = 1;
var MOUSE_EVENT = 2;
var eventType = {
touchstart: TOUCH_EVENT,
touchmove: TOUCH_EVENT,
touchend: TOUCH_EVENT,
mousedown: MOUSE_EVENT,
mousemove: MOUSE_EVENT,
mouseup: MOUSE_EVENT
};
function getRect(el) {
if (el instanceof window.SVGElement) {
var rect = el.getBoundingClientRect();
return {
top: rect.top,
left: rect.left,
width: rect.width,
height: rect.height
};
} else {
return {
top: el.offsetTop,
left: el.offsetLeft,
width: el.offsetWidth,
height: el.offsetHeight
};
}
}
function preventDefaultException(el, exceptions) {
for (var i in exceptions) {
if (exceptions[i].test(el[i])) {
return true;
}
}
return false;
}
function tap(e, eventName) {
var ev = document.createEvent('Event');
ev.initEvent(eventName, true, true);
ev.pageX = e.pageX;
ev.pageY = e.pageY;
e.target.dispatchEvent(ev);
}
function click(e) {
var event = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'click';
var eventSource = void 0;
if (e.type === 'mouseup' || e.type === 'mousecancel') {
eventSource = e;
} else if (e.type === 'touchend' || e.type === 'touchcancel') {
eventSource = e.changedTouches[0];
}
var posSrc = {};
if (eventSource) {
posSrc.screenX = eventSource.screenX || 0;
posSrc.screenY = eventSource.screenY || 0;
posSrc.clientX = eventSource.clientX || 0;
posSrc.clientY = eventSource.clientY || 0;
}
var ev = void 0;
var bubbles = true;
var cancelable = true;
if (typeof MouseEvent !== 'undefined') {
try {
ev = new MouseEvent(event, extend({
bubbles: bubbles,
cancelable: cancelable
}, posSrc));
} catch (e) {
createEvent();
}
} else {
createEvent();
}
function createEvent() {
ev = document.createEvent('Event');
ev.initEvent(event, bubbles, cancelable);
extend(ev, posSrc);
}
// forwardedTouchEvent set to true in case of the conflict with fastclick
ev.forwardedTouchEvent = true;
ev._constructed = true;
e.target.dispatchEvent(ev);
}
function dblclick(e) {
click(e, 'dblclick');
}
function prepend(el, target) {
if (target.firstChild) {
before(el, target.firstChild);
} else {
target.appendChild(el);
}
}
function before(el, target) {
target.parentNode.insertBefore(el, target);
}
function removeChild(el, child) {
el.removeChild(child);
}
var DEFAULT_OPTIONS = {
startX: 0,
startY: 0,
scrollX: false,
scrollY: true,
freeScroll: false,
directionLockThreshold: 5,
eventPassthrough: '',
click: false,
tap: false,
/**
* support any side
* bounce: {
* top: true,
* bottom: true,
* left: true,
* right: true
* }
*/
bounce: true,
bounceTime: 800,
momentum: true,
momentumLimitTime: 300,
momentumLimitDistance: 15,
swipeTime: 2500,
swipeBounceTime: 500,
deceleration: 0.0015,
flickLimitTime: 200,
flickLimitDistance: 100,
resizePolling: 60,
probeType: 0,
preventDefault: true,
preventDefaultException: {
tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT)$/
},
HWCompositing: true,
useTransition: true,
useTransform: true,
bindToWrapper: false,
disableMouse: hasTouch,
disableTouch: !hasTouch,
observeDOM: true,
autoBlur: true,
/**
* for picker
* wheel: {
* selectedIndex: 0,
* rotate: 25,
* adjustTime: 400
* wheelWrapperClass: 'wheel-scroll',
* wheelItemClass: 'wheel-item'
* }
*/
wheel: false,
/**
* for slide
* snap: {
* loop: false,
* el: domEl,
* threshold: 0.1,
* stepX: 100,
* stepY: 100,
* speed: 400,
* easing: {
* style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
* fn: function (t) {
* return t * (2 - t)
* }
* }
* listenFlick: true
* }
*/
snap: false,
/**
* for scrollbar
* scrollbar: {
* fade: true,
* interactive: false
* }
*/
scrollbar: false,
/**
* for pull down and refresh
* pullDownRefresh: {
* threshold: 50,
* stop: 20
* }
*/
pullDownRefresh: false,
/**
* for pull up and load
* pullUpLoad: {
* threshold: 50
* }
*/
pullUpLoad: false,
/**
* for mouse wheel
* mouseWheel: {
* speed: 20,
* invert: false,
* easeTime: 300
* }
*/
mouseWheel: false,
stopPropagation: false,
/**
* for zoom
* zoom: {
* start: 1,
* min: 1,
* max: 4
* }
*/
zoom: false,
/**
* for infinity
* infinity: {
* render(item, div) {
* },
* createTombstone() {
* },
* fetch(count) {
* }
* }
*/
infinity: false,
/**
* for double click
* dblclick: {
* delay: 300
* }
*/
dblclick: false
};
function initMixin(BScroll) {
BScroll.prototype._init = function (el, options) {
this._handleOptions(options);
// init private custom events
this._events = {};
this.x = 0;
this.y = 0;
this.directionX = 0;
this.directionY = 0;
this.setScale(1);
this._addDOMEvents();
this._initExtFeatures();
this._watchTransition();
if (this.options.observeDOM) {
this._initDOMObserver();
}
if (this.options.autoBlur) {
this._handleAutoBlur();
}
this.refresh();
if (!this.options.snap) {
this.scrollTo(this.options.startX, this.options.startY);
}
this.enable();
};
BScroll.prototype.setScale = function (scale) {
this.lastScale = isUndef(this.scale) ? scale : this.scale;
this.scale = scale;
};
BScroll.prototype._handleOptions = function (options) {
this.options = extend({}, DEFAULT_OPTIONS, options);
this.translateZ = this.options.HWCompositing && hasPerspective ? ' translateZ(0)' : '';
this.options.useTransition = this.options.useTransition && hasTransition;
this.options.useTransform = this.options.useTransform && hasTransform;
this.options.preventDefault = !this.options.eventPassthrough && this.options.preventDefault;
// If you want eventPassthrough I have to lock one of the axes
this.options.scrollX = this.options.eventPassthrough === 'horizontal' ? false : this.options.scrollX;
this.options.scrollY = this.options.eventPassthrough === 'vertical' ? false : this.options.scrollY;
// With eventPassthrough we also need lockDirection mechanism
this.options.freeScroll = this.options.freeScroll && !this.options.eventPassthrough;
this.options.directionLockThreshold = this.options.eventPassthrough ? 0 : this.options.directionLockThreshold;
if (this.options.tap === true) {
this.options.tap = 'tap';
}
};
BScroll.prototype._addDOMEvents = function () {
var eventOperation = addEvent;
this._handleDOMEvents(eventOperation);
};
BScroll.prototype._removeDOMEvents = function () {
var eventOperation = removeEvent;
this._handleDOMEvents(eventOperation);
};
BScroll.prototype._handleDOMEvents = function (eventOperation) {
var target = this.options.bindToWrapper ? this.wrapper : window;
eventOperation(window, 'orientationchange', this);
eventOperation(window, 'resize', this);
if (this.options.click) {
eventOperation(this.wrapper, 'click', this, true);
}
if (!this.options.disableMouse) {
eventOperation(this.wrapper, 'mousedown', this);
eventOperation(target, 'mousemove', this);
eventOperation(target, 'mousecancel', this);
eventOperation(target, 'mouseup', this);
}
if (hasTouch && !this.options.disableTouch) {
eventOperation(this.wrapper, 'touchstart', this);
eventOperation(target, 'touchmove', this);
eventOperation(target, 'touchcancel', this);
eventOperation(target, 'touchend', this);
}
eventOperation(this.scroller, style.transitionEnd, this);
};
BScroll.prototype._initExtFeatures = function () {
if (this.options.snap) {
this._initSnap();
}
if (this.options.scrollbar) {
this._initScrollbar();
}
if (this.options.pullUpLoad) {
this._initPullUp();
}
if (this.options.pullDownRefresh) {
this._initPullDown();
}
if (this.options.wheel) {
this._initWheel();
}
if (this.options.mouseWheel) {
this._initMouseWheel();
}
if (this.options.zoom) {
this._initZoom();
}
if (this.options.infinity) {
this._initInfinite();
}
};
BScroll.prototype._watchTransition = function () {
if (typeof Object.defineProperty !== 'function') {
return;
}
var me = this;
var isInTransition = false;
var key = this.useTransition ? 'isInTransition' : 'isAnimating';
Object.defineProperty(this, key, {
get: function get() {
return isInTransition;
},
set: function set(newVal) {
isInTransition = newVal;
// fix issue #359
var el = me.scroller.children.length ? me.scroller.children : [me.scroller];
var pointerEvents = isInTransition && !me.pulling ? 'none' : 'auto';
for (var i = 0; i < el.length; i++) {
el[i].style.pointerEvents = pointerEvents;
}
}
});
};
BScroll.prototype._handleAutoBlur = function () {
this.on('scrollStart', function () {
var activeElement = document.activeElement;
if (activeElement && (activeElement.tagName === 'INPUT' || activeElement.tagName === 'TEXTAREA')) {
activeElement.blur();
}
});
};
BScroll.prototype._initDOMObserver = function () {
var _this = this;
if (typeof MutationObserver !== 'undefined') {
var timer = void 0;
var observer = new MutationObserver(function (mutations) {
// don't do any refresh during the transition, or outside of the boundaries
if (_this._shouldNotRefresh()) {
return;
}
var immediateRefresh = false;
var deferredRefresh = false;
for (var i = 0; i < mutations.length; i++) {
var mutation = mutations[i];
if (mutation.type !== 'attributes') {
immediateRefresh = true;
break;
} else {
if (mutation.target !== _this.scroller) {
deferredRefresh = true;
break;
}
}
}
if (immediateRefresh) {
_this.refresh();
} else if (deferredRefresh) {
// attributes changes too often
clearTimeout(timer);
timer = setTimeout(function () {
if (!_this._shouldNotRefresh()) {
_this.refresh();
}
}, 60);
}
});
var config = {
attributes: true,
childList: true,
subtree: true
};
observer.observe(this.scroller, config);
this.on('destroy', function () {
observer.disconnect();
});
} else {
this._checkDOMUpdate();
}
};
BScroll.prototype._shouldNotRefresh = function () {
var outsideBoundaries = this.x > this.minScrollX || this.x < this.maxScrollX || this.y > this.minScrollY || this.y < this.maxScrollY;
return this.isInTransition || this.stopFromTransition || outsideBoundaries;
};
BScroll.prototype._checkDOMUpdate = function () {
var scrollerRect = getRect(this.scroller);
var oldWidth = scrollerRect.width;
var oldHeight = scrollerRect.height;
function check() {
if (this.destroyed) {
return;
}
scrollerRect = getRect(this.scroller);
var newWidth = scrollerRect.width;
var newHeight = scrollerRect.height;
if (oldWidth !== newWidth || oldHeight !== newHeight) {
this.refresh();
}
oldWidth = newWidth;
oldHeight = newHeight;
next.call(this);
}
function next() {
var _this2 = this;
setTimeout(function () {
check.call(_this2);
}, 1000);
}
next.call(this);
};
BScroll.prototype.handleEvent = function (e) {
switch (e.type) {
case 'touchstart':
case 'mousedown':
this._start(e);
if (this.options.zoom && e.touches && e.touches.length > 1) {
this._zoomStart(e);
}
break;
case 'touchmove':
case 'mousemove':
if (this.options.zoom && e.touches && e.touches.length > 1) {
this._zoom(e);
} else {
this._move(e);
}
break;
case 'touchend':
case 'mouseup':
case 'touchcancel':
case 'mousecancel':
if (this.scaled) {
this._zoomEnd(e);
} else {
this._end(e);
}
break;
case 'orientationchange':
case 'resize':
this._resize();
break;
case 'transitionend':
case 'webkitTransitionEnd':
case 'oTransitionEnd':
case 'MSTransitionEnd':
this._transitionEnd(e);
break;
case 'click':
if (this.enabled && !e._constructed) {
if (!preventDefaultException(e.target, this.options.preventDefaultException)) {
e.preventDefault();
e.stopPropagation();
}
}
break;
case 'wheel':
case 'DOMMouseScroll':
case 'mousewheel':
this._onMouseWheel(e);
break;
}
};
BScroll.prototype.refresh = function () {
var isWrapperStatic = window.getComputedStyle(this.wrapper, null).position === 'static';
var wrapperRect = getRect(this.wrapper);
this.wrapperWidth = wrapperRect.width;
this.wrapperHeight = wrapperRect.height;
var scrollerRect = getRect(this.scroller);
this.scrollerWidth = Math.round(scrollerRect.width * this.scale);
this.scrollerHeight = Math.round(scrollerRect.height * this.scale);
this.relativeX = scrollerRect.left;
this.relativeY = scrollerRect.top;
if (isWrapperStatic) {
this.relativeX -= wrapperRect.left;
this.relativeY -= wrapperRect.top;
}
this.minScrollX = 0;
this.minScrollY = 0;
var wheel = this.options.wheel;
if (wheel) {
this.items = this.scroller.children;
this.options.itemHeight = this.itemHeight = this.items.length ? this.scrollerHeight / this.items.length : 0;
if (this.selectedIndex === undefined) {
this.selectedIndex = wheel.selectedIndex || 0;
}
this.options.startY = -this.selectedIndex * this.itemHeight;
this.maxScrollX = 0;
this.maxScrollY = -this.itemHeight * (this.items.length - 1);
} else {
this.maxScrollX = this.wrapperWidth - this.scrollerWidth;
if (!this.options.infinity) {
this.maxScrollY = this.wrapperHeight - this.scrollerHeight;
}
if (this.maxScrollX < 0) {
this.maxScrollX -= this.relativeX;
this.minScrollX = -this.relativeX;
} else if (this.scale > 1) {
this.maxScrollX = this.maxScrollX / 2 - this.relativeX;
this.minScrollX = this.maxScrollX;
}
if (this.maxScrollY < 0) {
this.maxScrollY -= this.relativeY;
this.minScrollY = -this.relativeY;
} else if (this.scale > 1) {
this.maxScrollY = this.maxScrollY / 2 - this.relativeY;
this.minScrollY = this.maxScrollY;
}
}
this.hasHorizontalScroll = this.options.scrollX && this.maxScrollX < this.minScrollX;
this.hasVerticalScroll = this.options.scrollY && this.maxScrollY < this.minScrollY;
if (!this.hasHorizontalScroll) {
this.maxScrollX = this.minScrollX;
this.scrollerWidth = this.wrapperWidth;
}
if (!this.hasVerticalScroll) {
this.maxScrollY = this.minScrollY;
this.scrollerHeight = this.wrapperHeight;
}
this.endTime = 0;
this.directionX = 0;
this.directionY = 0;
this.wrapperOffset = offset(this.wrapper);
this.trigger('refresh');
!this.scaled && this.resetPosition();
};
BScroll.prototype.enable = function () {
this.enabled = true;
};
BScroll.prototype.disable = function () {
this.enabled = false;
};
}
var ease = {
// easeOutQuint
swipe: {
style: 'cubic-bezier(0.23, 1, 0.32, 1)',
fn: function fn(t) {
return 1 + --t * t * t * t * t;
}
},
// easeOutQuard
swipeBounce: {
style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
fn: function fn(t) {
return t * (2 - t);
}
},
// easeOutQuart
bounce: {
style: 'cubic-bezier(0.165, 0.84, 0.44, 1)',
fn: function fn(t) {
return 1 - --t * t * t * t;
}
}
};
function momentum(current, start, time, lowerMargin, upperMargin, wrapperSize, options) {
var distance = current - start;
var speed = Math.abs(distance) / time;
var deceleration = options.deceleration,
itemHeight = options.itemHeight,
swipeBounceTime = options.swipeBounceTime,
wheel = options.wheel,
swipeTime = options.swipeTime;
var duration = swipeTime;
var rate = wheel ? 4 : 15;
var destination = current + speed / deceleration * (distance < 0 ? -1 : 1);
if (wheel && itemHeight) {
destination = Math.round(destination / itemHeight) * itemHeight;
}
if (destination < lowerMargin) {
destination = wrapperSize ? Math.max(lowerMargin - wrapperSize / 4, lowerMargin - wrapperSize / rate * speed) : lowerMargin;
duration = swipeBounceTime;
} else if (destination > upperMargin) {
destination = wrapperSize ? Math.min(upperMargin + wrapperSize / 4, upperMargin + wrapperSize / rate * speed) : upperMargin;
duration = swipeBounceTime;
}
return {
destination: Math.round(destination),
duration: duration
};
}
var DEFAULT_INTERVAL = 100 / 60;
function noop() {}
var requestAnimationFrame = function () {
if (!inBrowser) {
/* istanbul ignore if */
return noop;
}
return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame ||
// if all else fails, use setTimeout
function (callback) {
return window.setTimeout(callback, (callback.interval || DEFAULT_INTERVAL) / 2); // make interval as precise as possible.
};
}();
var cancelAnimationFrame = function () {
if (!inBrowser) {
/* istanbul ignore if */
return noop;
}
return window.cancelAnimationFrame || window.webkitCancelAnimationFrame || window.mozCancelAnimationFrame || window.oCancelAnimationFrame || function (id) {
window.clearTimeout(id);
};
}();
var DIRECTION_UP = 1;
var DIRECTION_DOWN = -1;
var DIRECTION_LEFT = 1;
var DIRECTION_RIGHT = -1;
var PROBE_DEBOUNCE = 1;
var PROBE_REALTIME = 3;
function warn(msg) {
console.error('[BScroll warn]: ' + msg);
}
function assert(condition, msg) {
if (!condition) {
throw new Error('[BScroll] ' + msg);
}
}
function coreMixin(BScroll) {
BScroll.prototype._start = function (e) {
var _eventType = eventType[e.type];
if (_eventType !== TOUCH_EVENT) {
if (e.button !== 0) {
return;
}
}
if (!this.enabled || this.destroyed || this.initiated && this.initiated !== _eventType) {
return;
}
this.initiated = _eventType;
if (this.options.preventDefault && !preventDefaultException(e.target, this.options.preventDefaultException)) {
e.preventDefault();
}
if (this.options.stopPropagation) {
e.stopPropagation();
}
this.moved = false;
this.distX = 0;
this.distY = 0;
this.directionX = 0;
this.directionY = 0;
this.movingDirectionX = 0;
this.movingDirectionY = 0;
this.directionLocked = 0;
this._transitionTime();
this.startTime = getNow();
if (this.options.wheel) {
this.target = e.target;
}
this.stop();
var point = e.touches ? e.touches[0] : e;
this.startX = this.x;
this.startY = this.y;
this.absStartX = this.x;
this.absStartY = this.y;
this.pointX = point.pageX;
this.pointY = point.pageY;
this.trigger('beforeScrollStart');
};
BScroll.prototype._move = function (e) {
if (!this.enabled || this.destroyed || eventType[e.type] !== this.initiated) {
return;
}
if (this.options.preventDefault) {
e.preventDefault();
}
if (this.options.stopPropagation) {
e.stopPropagation();
}
var point = e.touches ? e.touches[0] : e;
var deltaX = point.pageX - this.pointX;
var deltaY = point.pageY - this.pointY;
this.pointX = point.pageX;
this.pointY = point.pageY;
this.distX += deltaX;
this.distY += deltaY;
var absDistX = Math.abs(this.distX);
var absDistY = Math.abs(this.distY);
var timestamp = getNow();
// We need to move at least momentumLimitDistance pixels for the scrolling to initiate
if (timestamp - this.endTime > this.options.momentumLimitTime && absDistY < this.options.momentumLimitDistance && absDistX < this.options.momentumLimitDistance) {
return;
}
// If you are scrolling in one direction lock the other
if (!this.directionLocked && !this.options.freeScroll) {
if (absDistX > absDistY + this.options.directionLockThreshold) {
this.directionLocked = 'h'; // lock horizontally
} else if (absDistY >= absDistX + this.options.directionLockThreshold) {
this.directionLocked = 'v'; // lock vertically
} else {
this.directionLocked = 'n'; // no lock
}
}
if (this.directionLocked === 'h') {
if (this.options.eventPassthrough === 'vertical') {
e.preventDefault();
} else if (this.options.eventPassthrough === 'horizontal') {
this.initiated = false;
return;
}
deltaY = 0;
} else if (this.directionLocked === 'v') {
if (this.options.eventPassthrough === 'horizontal') {
e.preventDefault();
} else if (this.options.eventPassthrough === 'vertical') {
this.initiated = false;
return;
}
deltaX = 0;
}
deltaX = this.hasHorizontalScroll ? deltaX : 0;
deltaY = this.hasVerticalScroll ? deltaY : 0;
this.movingDirectionX = deltaX > 0 ? DIRECTION_RIGHT : deltaX < 0 ? DIRECTION_LEFT : 0;
this.movingDirectionY = deltaY > 0 ? DIRECTION_DOWN : deltaY < 0 ? DIRECTION_UP : 0;
var newX = this.x + deltaX;
var newY = this.y + deltaY;
var top = false;
var bottom = false;
var left = false;
var right = false;
// Slow down or stop if outside of the boundaries
var bounce = this.options.bounce;
if (bounce !== false) {
top = bounce.top === undefined ? true : bounce.top;
bottom = bounce.bottom === undefined ? true : bounce.bottom;
left = bounce.left === undefined ? true : bounce.left;
right = bounce.right === undefined ? true : bounce.right;
}
if (newX > this.minScrollX || newX < this.maxScrollX) {
if (newX > this.minScrollX && left || newX < this.maxScrollX && right) {
newX = this.x + deltaX / 3;
} else {
newX = newX > this.minScrollX ? this.minScrollX : this.maxScrollX;
}
}
if (newY > this.minScrollY || newY < this.maxScrollY) {
if (newY > this.minScrollY && top || newY < this.maxScrollY && bottom) {
newY = this.y + deltaY / 3;
} else {
newY = newY > this.minScrollY ? this.minScrollY : this.maxScrollY;
}
}
if (!this.moved) {
this.moved = true;
this.trigger('scrollStart');
}
this._translate(newX, newY);
if (timestamp - this.startTime > this.options.momentumLimitTime) {
this.startTime = timestamp;
this.startX = this.x;
this.startY = this.y;
if (this.options.probeType === PROBE_DEBOUNCE) {
this.trigger('scroll', {
x: this.x,
y: this.y
});
}
}
if (this.options.probeType > PROBE_DEBOUNCE) {
this.trigger('scroll', {
x: this.x,
y: this.y
});
}
var scrollLeft = document.documentElement.scrollLeft || window.pageXOffset || document.body.scrollLeft;
var scrollTop = document.documentElement.scrollTop || window.pageYOffset || document.body.scrollTop;
var pX = this.pointX - scrollLeft;
var pY = this.pointY - scrollTop;
if (pX > document.documentElement.clientWidth - this.options.momentumLimitDistance || pX < this.options.momentumLimitDistance || pY < this.options.momentumLimitDistance || pY > document.documentElement.clientHeight - this.options.momentumLimitDistance) {
this._end(e);
}
};
BScroll.prototype._end = function (e) {
if (!this.enabled || this.destroyed || eventType[e.type] !== this.initiated) {
return;
}
this.initiated = false;
if (this.options.preventDefault && !preventDefaultException(e.target, this.options.preventDefaultException)) {
e.preventDefault();
}
if (this.options.stopPropagation) {
e.stopPropagation();
}
this.trigger('touchEnd', {
x: this.x,
y: this.y
});
this.isInTransition = false;
// ensures that the last position is rounded
var newX = Math.round(this.x);
var newY = Math.round(this.y);
var deltaX = newX - this.absStartX;
var deltaY = newY - this.absStartY;
this.directionX = deltaX > 0 ? DIRECTION_RIGHT : deltaX < 0 ? DIRECTION_LEFT : 0;
this.directionY = deltaY > 0 ? DIRECTION_DOWN : deltaY < 0 ? DIRECTION_UP : 0;
// if configure pull down refresh, check it first
if (this.options.pullDownRefresh && this._checkPullDown()) {
return;
}
// check if it is a click operation
if (this._checkClick(e)) {
this.trigger('scrollCancel');
return;
}
// reset if we are outside of the boundaries
if (this.resetPosition(this.options.bounceTime, ease.bounce)) {
return;
}
this._translate(newX, newY);
this.endTime = getNow();
var duration = this.endTime - this.startTime;
var absDistX = Math.abs(newX - this.startX);
var absDistY = Math.abs(newY - this.startY);
// flick
if (this._events.flick && duration < this.options.flickLimitTime && absDistX < this.options.flickLimitDistance && absDistY < this.options.flickLimitDistance) {
this.trigger('flick');
return;
}
var time = 0;
// start momentum animation if needed
if (this.options.momentum && duration < this.options.momentumLimitTime && (absDistY > this.options.momentumLimitDistance || absDistX > this.options.momentumLimitDistance)) {
var top = false;
var bottom = false;
var left = false;
var right = false;
var bounce = this.options.bounce;
if (bounce !== false) {
top = bounce.top === undefined ? true : bounce.top;
bottom = bounce.bottom === undefined ? true : bounce.bottom;
left = bounce.left === undefined ? true : bounce.left;
right = bounce.right === undefined ? true : bounce.right;
}
var wrapperWidth = this.directionX === DIRECTION_RIGHT && left || this.directionX === DIRECTION_LEFT && right ? this.wrapperWidth : 0;
var wrapperHeight = this.directionY === DIRECTION_DOWN && top || this.directionY === DIRECTION_UP && bottom ? this.wrapperHeight : 0;
var momentumX = this.hasHorizontalScroll ? momentum(this.x, this.startX, duration, this.maxScrollX, this.minScrollX, wrapperWidth, this.options) : { destination: newX, duration: 0 };
var momentumY = this.hasVerticalScroll ? momentum(this.y, this.startY, duration, this.maxScrollY, this.minScrollY, wrapperHeight, this.options) : { destination: newY, duration: 0 };
newX = momentumX.destination;
newY = momentumY.destination;
time = Math.max(momentumX.duration, momentumY.duration);
this.isInTransition = true;
} else {
if (this.options.wheel) {
newY = Math.round(newY / this.itemHeight) * this.itemHeight;
time = this.options.wheel.adjustTime || 400;
}
}
var easing = ease.swipe;
if (this.options.snap) {
var snap = this._nearestSnap(newX, newY);
this.currentPage = snap;
time = this.options.snapSpeed || Math.max(Math.max(Math.min(Math.abs(newX - snap.x), 1000), Math.min(Math.abs(newY - snap.y), 1000)), 300);
newX = snap.x;
newY = snap.y;
this.directionX = 0;
this.directionY = 0;
easing = this.options.snap.easing || ease.bounce;
}
if (newX !== this.x || newY !== this.y) {
// change easing function when scroller goes out of the boundaries
if (newX > this.minScrollX || newX < this.maxScrollX || newY > this.minScrollY || newY < this.maxScrollY) {
easing = ease.swipeBounce;
}
this.scrollTo(newX, newY, time, easing);
return;
}
if (this.options.wheel) {
this.selectedIndex = Math.round(Math.abs(this.y / this.itemHeight));
}
this.trigger('scrollEnd', {
x: this.x,
y: this.y
});
};
BScroll.prototype._checkClick = function (e) {
// when in the process of pulling down, it should not prevent click
var preventClick = this.stopFromTransition && !this.pulling;
this.stopFromTransition = false;
// we scrolled less than 15 pixels
if (!this.moved) {
if (this.options.wheel) {
if (this.target && this.target.classList.contains(this.options.wheel.wheelWrapperClass)) {
var index = Math.abs(Math.round(this.y / this.itemHeight));
var _offset = Math.round((this.pointY + offsetToBody(this.wrapper).top - this.wrapperHeight / 2) / this.itemHeight);
this.target = this.items[index + _offset];
}
this.scrollToElement(this.target, this.options.wheel.adjustTime || 400, true, true, ease.swipe);
return true;
} else {
if (!preventClick) {
var _dblclick = this.options.dblclick;
var dblclickTrigged = false;
if (_dblclick && this.lastClickTime) {
var _dblclick$delay = _dblclick.delay,
delay = _dblclick$delay === undefined ? 300 : _dblclick$delay;
if (getNow() - this.lastClickTime < delay) {
dblclickTrigged = true;
dblclick(e);
}
}
if (this.options.tap) {
tap(e, this.options.tap);
}
if (this.options.click && !preventDefaultException(e.target, this.options.preventDefaultException)) {
click(e);
}
this.lastClickTime = dblclickTrigged ? null : getNow();
return true;
}
return false;
}
}
return false;
};
BScroll.prototype._resize = function () {
var _this = this;
if (!this.enabled) {
return;
}
// fix a scroll problem under Android condition
if (isAndroid) {
this.wrapper.scrollTop = 0;
}
clearTimeout(this.resizeTimeout);
this.resizeTimeout = setTimeout(function () {
_this.refresh();
}, this.options.resizePolling);
};
BScroll.prototype._startProbe = function () {
cancelAnimationFrame(this.probeTimer);
this.probeTimer = requestAnimationFrame(probe);
var me = this;
function probe() {
var pos = me.getComputedPosition();
me.trigger('scroll', pos);
if (!me.isInTransition) {
me.trigger('scrollEnd', pos);
return;
}
me.probeTimer = requestAnimationFrame(probe);
}
};
BScroll.prototype._transitionTime = function () {
var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
this.scrollerStyle[style.transitionDuration] = time + 'ms';
if (this.options.wheel) {
for (var i = 0; i < this.items.length; i++) {
this.items[i].style[style.transitionDuration] = time + 'ms';
}
}
if (this.indicators) {
for (var _i = 0; _i < this.indicators.length; _i++) {
this.indicators[_i].transitionTime(time);
}
}
};
BScroll.prototype._transitionTimingFunction = function (easing) {
this.scrollerStyle[style.transitionTimingFunction] = easing;
if (this.options.wheel) {
for (var i = 0; i < this.items.length; i++) {
this.items[i].style[style.transitionTimingFunction] = easing;
}
}
if (this.indicators) {
for (var _i2 = 0; _i2 < this.indicators.length; _i2++) {
this.indicators[_i2].transitionTimingFunction(easing);
}
}
};
BScroll.prototype._transitionEnd = function (e) {
if (e.target !== this.scroller || !this.isInTransition) {
return;
}
this._transitionTime();
var needReset = !this.pulling || this.movingDirectionY === DIRECTION_UP;
if (needReset && !this.resetPosition(this.options.bounceTime, ease.bounce)) {
this.isInTransition = false;
if (this.options.probeType !== PROBE_REALTIME) {
this.trigger('scrollEnd', {
x: this.x,
y: this.y
});
}
}
};
BScroll.prototype._translate = function (x, y, scale) {
assert(!isUndef(x) && !isUndef(y), 'Translate x or y is null or undefined.');
if (isUndef(scale)) {
scale = this.scale;
}
if (this.options.useTransform) {
this.scrollerStyle[style.transform] = 'translate(' + x + 'px,' + y + 'px) scale(' + scale + ')' + this.translateZ;
} else {
x = Math.round(x);
y = Math.round(y);
this.scrollerStyle.left = x + 'px';
this.scrollerStyle.top = y + 'px';
}
if (this.options.wheel) {
var _options$wheel$rotate = this.options.wheel.rotate,
rotate = _options$wheel$rotate === undefined ? 25 : _options$wheel$rotate;
for (var i = 0; i < this.items.length; i++) {
var deg = rotate * (y / this.itemHeight + i);
this.items[i].style[style.transform] = 'rotateX(' + deg + 'deg)';
}
}
this.x = x;
this.y = y;
this.setScale(scale);
if (this.indicators) {
for (var _i3 = 0; _i3 < this.indicators.length; _i3++) {
this.indicators[_i3].updatePosition();
}
}
};
BScroll.prototype._animate = function (destX, destY, duration, easingFn) {
var me = this;
var startX = this.x;
var startY = this.y;
var startScale = this.lastScale;
var destScale = this.scale;
var startTime = getNow();
var destTime = startTime + duration;
function step() {
var now = getNow();
if (now >= destTime) {
me.isAnimating = false;
me._translate(destX, destY, destScale);
me.trigger('scroll', {
x: me.x,
y: me.y
});
if (!me.pulling && !me.resetPosition(me.options.bounceTime)) {
me.trigger('scrollEnd', {
x: me.x,
y: me.y
});
}
return;
}
now = (now - startTime) / duration;
var easing = easingFn(now);
var newX = (destX - startX) * easing + startX;
var newY = (destY - startY) * easing + startY;
var newScale = (destScale - startScale) * easing + startScale;
me._translate(newX, newY, newScale);
if (me.isAnimating) {
me.animateTimer = requestAnimationFrame(step);
}
if (me.options.probeType === PROBE_REALTIME) {
me.trigger('scroll', {
x: me.x,
y: me.y
});
}
}
this.isAnimating = true;
cancelAnimationFrame(this.animateTimer);
step();
};
BScroll.prototype.scrollBy = function (x, y) {
var time = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var easing = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ease.bounce;
x = this.x + x;
y = this.y + y;
this.scrollTo(x, y, time, easing);
};
BScroll.prototype.scrollTo = function (x, y) {
var time = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : 0;
var easing = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ease.bounce;
this.isInTransition = this.options.useTransition && time > 0 && (x !== this.x || y !== this.y);
if (!time || this.options.useTransition) {
this._transitionTimingFunction(easing.style);
this._transitionTime(time);
this._translate(x, y);
if (time && this.options.probeType === PROBE_REALTIME) {
this._startProbe();
}
if (!time && (x !== this.x || y !== this.y)) {
this.trigger('scroll', {
x: x,
y: y
});
// force reflow to put everything in position
this._reflow = document.body.offsetHeight;
if (!this.resetPosition(this.options.bounceTime, ease.bounce)) {
this.trigger('scrollEnd', {
x: x,
y: y
});
}
}
if (this.options.wheel) {
if (y > this.minScrollY) {
this.selectedIndex = 0;
} else if (y < this.maxScrollY) {
this.selectedIndex = this.items.length - 1;
} else {
this.selectedIndex = Math.round(Math.abs(y / this.itemHeight));
}
}
} else {
this._animate(x, y, time, easing.fn);
}
};
BScroll.prototype.scrollToElement = function (el, time, offsetX, offsetY, easing) {
if (!el) {
return;
}
el = el.nodeType ? el : this.scroller.querySelector(el);
if (this.options.wheel && !el.classList.contains(this.options.wheel.wheelItemClass)) {
return;
}
var pos = offset(el);
pos.left -= this.wrapperOffset.left;
pos.top -= this.wrapperOffset.top;
// if offsetX/Y are true we center the element to the screen
if (offsetX === true) {
offsetX = Math.round(el.offsetWidth / 2 - this.wrapper.offsetWidth / 2);
}
if (offsetY === true) {
offsetY = Math.round(el.offsetHeight / 2 - this.wrapper.offsetHeight / 2);
}
pos.left -= offsetX || 0;
pos.top -= offsetY || 0;
pos.left = pos.left > this.minScrollX ? this.minScrollX : pos.left < this.maxScrollX ? this.maxScrollX : pos.left;
pos.top = pos.top > this.minScrollY ? this.minScrollY : pos.top < this.maxScrollY ? this.maxScrollY : pos.top;
if (this.options.wheel) {
pos.top = Math.round(pos.top / this.itemHeight) * this.itemHeight;
}
this.scrollTo(pos.left, pos.top, time, easing);
};
BScroll.prototype.resetPosition = function () {
var time = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 0;
var easeing = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : ease.bounce;
var x = this.x;
var roundX = Math.round(x);
if (!this.hasHorizontalScroll || roundX > this.minScrollX) {
x = this.minScrollX;
} else if (roundX < this.maxScrollX) {
x = this.maxScrollX;
}
var y = this.y;
var roundY = Math.round(y);
if (!this.hasVerticalScroll || roundY > this.minScrollY) {
y = this.minScrollY;
} else if (roundY < this.maxScrollY) {
y = this.maxScrollY;
}
if (x === this.x && y === this.y) {
return false;
}
this.scrollTo(x, y, time, easeing);
return true;
};
BScroll.prototype.getComputedPosition = function () {
var matrix = window.getComputedStyle(this.scroller, null);
var x = void 0;
var y = void 0;
if (this.options.useTransform) {
matrix = matrix[style.transform].split(')')[0].split(', ');
x = +(matrix[12] || matrix[4]);
y = +(matrix[13] || matrix[5]);
} else {
x = +matrix.left.replace(/[^-\d.]/g, '');
y = +matrix.top.replace(/[^-\d.]/g, '');
}
return {
x: x,
y: y
};
};
BScroll.prototype.stop = function () {
if (this.options.useTransition && this.isInTransition) {
this.isInTransition = false;
cancelAnimationFrame(this.probeTimer);
var pos = this.getComputedPosition();
this._translate(pos.x, pos.y);
if (this.options.wheel) {
this.target = this.items[Math.round(-pos.y / this.itemHeight)];
} else {
this.trigger('scrollEnd', {
x: this.x,
y: this.y
});
}
this.stopFromTransition = true;
} else if (!this.options.useTransition && this.isAnimating) {
this.isAnimating = false;
cancelAnimationFrame(this.animateTimer);
this.trigger('scrollEnd', {
x: this.x,
y: this.y
});
this.stopFromTransition = true;
}
};
BScroll.prototype.destroy = fun