123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555 |
- /*!
- * better-scroll / nested-scroll
- * (c) 2016-2021 ustbhuangyi
- * Released under the MIT License.
- */
- (function (global, factory) {
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
- typeof define === 'function' && define.amd ? define(['exports'], factory) :
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global.NestedScroll = {}));
- }(this, (function (exports) { 'use strict';
- /*! *****************************************************************************
- Copyright (c) Microsoft Corporation.
- Permission to use, copy, modify, and/or distribute this software for any
- purpose with or without fee is hereby granted.
- THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
- REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
- AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
- INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
- LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
- OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
- PERFORMANCE OF THIS SOFTWARE.
- ***************************************************************************** */
- function __spreadArrays() {
- for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
- for (var r = Array(s), k = 0, i = 0; i < il; i++)
- for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
- r[k] = a[j];
- return r;
- }
- function warn(msg) {
- console.error("[BScroll warn]: " + msg);
- }
- // ssr support
- var inBrowser = typeof window !== 'undefined';
- var ua = inBrowser && navigator.userAgent.toLowerCase();
- !!(ua && /wechatdevtools/.test(ua));
- ua && ua.indexOf('android') > 0;
- /* istanbul ignore next */
- ((function () {
- if (typeof ua === 'string') {
- var regex = /os (\d\d?_\d(_\d)?)/;
- var matches = regex.exec(ua);
- if (!matches)
- return false;
- var parts = matches[1].split('_').map(function (item) {
- return parseInt(item, 10);
- });
- // ios version >= 13.4 issue 982
- return !!(parts[0] === 13 && parts[1] >= 4);
- }
- return false;
- }))();
- /* istanbul ignore next */
- var supportsPassive = false;
- /* istanbul ignore next */
- if (inBrowser) {
- var EventName = 'test-passive';
- try {
- var opts = {};
- Object.defineProperty(opts, 'passive', {
- get: function () {
- supportsPassive = true;
- },
- }); // https://github.com/facebook/flow/issues/285
- window.addEventListener(EventName, function () { }, opts);
- }
- catch (e) { }
- }
- var extend = function (target, source) {
- for (var key in source) {
- target[key] = source[key];
- }
- return target;
- };
- function findIndex(ary, fn) {
- if (ary.findIndex) {
- return ary.findIndex(fn);
- }
- var index = -1;
- ary.some(function (item, i, ary) {
- var ret = fn(item, i, ary);
- if (ret) {
- index = i;
- return ret;
- }
- });
- return index;
- }
- var elementStyle = (inBrowser &&
- document.createElement('div').style);
- var vendor = (function () {
- /* istanbul ignore if */
- if (!inBrowser) {
- return false;
- }
- var transformNames = [
- {
- key: 'standard',
- value: 'transform',
- },
- {
- key: 'webkit',
- value: 'webkitTransform',
- },
- {
- key: 'Moz',
- value: 'MozTransform',
- },
- {
- key: 'O',
- value: 'OTransform',
- },
- {
- key: 'ms',
- value: 'msTransform',
- },
- ];
- for (var _i = 0, transformNames_1 = transformNames; _i < transformNames_1.length; _i++) {
- var obj = transformNames_1[_i];
- if (elementStyle[obj.value] !== undefined) {
- return obj.key;
- }
- }
- /* istanbul ignore next */
- return false;
- })();
- /* istanbul ignore next */
- function prefixStyle(style) {
- if (vendor === false) {
- return style;
- }
- if (vendor === 'standard') {
- if (style === 'transitionEnd') {
- return 'transitionend';
- }
- return style;
- }
- return vendor + style.charAt(0).toUpperCase() + style.substr(1);
- }
- vendor && vendor !== 'standard' ? '-' + vendor.toLowerCase() + '-' : '';
- var transform = prefixStyle('transform');
- var transition = prefixStyle('transition');
- inBrowser && prefixStyle('perspective') in elementStyle;
- ({
- transform: transform,
- transition: transition,
- transitionTimingFunction: prefixStyle('transitionTimingFunction'),
- transitionDuration: prefixStyle('transitionDuration'),
- transitionDelay: prefixStyle('transitionDelay'),
- transformOrigin: prefixStyle('transformOrigin'),
- transitionEnd: prefixStyle('transitionEnd'),
- transitionProperty: prefixStyle('transitionProperty'),
- });
- var BScrollFamily = /** @class */ (function () {
- function BScrollFamily(scroll) {
- this.ancestors = [];
- this.descendants = [];
- this.hooksManager = [];
- this.analyzed = false;
- this.selfScroll = scroll;
- }
- BScrollFamily.create = function (scroll) {
- return new BScrollFamily(scroll);
- };
- BScrollFamily.prototype.hasAncestors = function (bscrollFamily) {
- var index = findIndex(this.ancestors, function (_a) {
- var item = _a[0];
- return item === bscrollFamily;
- });
- return index > -1;
- };
- BScrollFamily.prototype.hasDescendants = function (bscrollFamily) {
- var index = findIndex(this.descendants, function (_a) {
- var item = _a[0];
- return item === bscrollFamily;
- });
- return index > -1;
- };
- BScrollFamily.prototype.addAncestor = function (bscrollFamily, distance) {
- var ancestors = this.ancestors;
- ancestors.push([bscrollFamily, distance]);
- // by ascend
- ancestors.sort(function (a, b) {
- return a[1] - b[1];
- });
- };
- BScrollFamily.prototype.addDescendant = function (bscrollFamily, distance) {
- var descendants = this.descendants;
- descendants.push([bscrollFamily, distance]);
- // by ascend
- descendants.sort(function (a, b) {
- return a[1] - b[1];
- });
- };
- BScrollFamily.prototype.removeAncestor = function (bscrollFamily) {
- var ancestors = this.ancestors;
- if (ancestors.length) {
- var index = findIndex(this.ancestors, function (_a) {
- var item = _a[0];
- return item === bscrollFamily;
- });
- if (index > -1) {
- return ancestors.splice(index, 1);
- }
- }
- };
- BScrollFamily.prototype.removeDescendant = function (bscrollFamily) {
- var descendants = this.descendants;
- if (descendants.length) {
- var index = findIndex(this.descendants, function (_a) {
- var item = _a[0];
- return item === bscrollFamily;
- });
- if (index > -1) {
- return descendants.splice(index, 1);
- }
- }
- };
- BScrollFamily.prototype.registerHooks = function (hook, eventType, handler) {
- hook.on(eventType, handler);
- this.hooksManager.push([hook, eventType, handler]);
- };
- BScrollFamily.prototype.setAnalyzed = function (flag) {
- if (flag === void 0) { flag = false; }
- this.analyzed = flag;
- };
- BScrollFamily.prototype.purge = function () {
- var _this = this;
- // remove self from graph
- this.ancestors.forEach(function (_a) {
- var bscrollFamily = _a[0];
- bscrollFamily.removeDescendant(_this);
- });
- this.descendants.forEach(function (_a) {
- var bscrollFamily = _a[0];
- bscrollFamily.removeAncestor(_this);
- });
- // remove all hook handlers
- this.hooksManager.forEach(function (_a) {
- var hooks = _a[0], eventType = _a[1], handler = _a[2];
- hooks.off(eventType, handler);
- });
- this.hooksManager = [];
- };
- return BScrollFamily;
- }());
- var sourcePrefix = 'plugins.nestedScroll';
- var propertiesMap = [
- {
- key: 'purgeNestedScroll',
- name: 'purgeNestedScroll',
- },
- ];
- var propertiesConfig = propertiesMap.map(function (item) {
- return {
- key: item.key,
- sourceKey: sourcePrefix + "." + item.name,
- };
- });
- var DEFAUL_GROUP_ID = 'INTERNAL_NESTED_SCROLL';
- var forceScrollStopHandler = function (scrolls) {
- scrolls.forEach(function (scroll) {
- if (scroll.pending) {
- scroll.stop();
- scroll.resetPosition();
- }
- });
- };
- var enableScrollHander = function (scrolls) {
- scrolls.forEach(function (scroll) {
- scroll.enable();
- });
- };
- var disableScrollHander = function (scrolls, currentScroll) {
- scrolls.forEach(function (scroll) {
- if (scroll.hasHorizontalScroll === currentScroll.hasHorizontalScroll ||
- scroll.hasVerticalScroll === currentScroll.hasVerticalScroll) {
- scroll.disable();
- }
- });
- };
- var syncTouchstartData = function (scrolls) {
- scrolls.forEach(function (scroll) {
- var _a = scroll.scroller, actions = _a.actions, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
- // prevent click triggering many times
- actions.fingerMoved = true;
- actions.contentMoved = false;
- actions.directionLockAction.reset();
- scrollBehaviorX.start();
- scrollBehaviorY.start();
- scrollBehaviorX.resetStartPos();
- scrollBehaviorY.resetStartPos();
- actions.startTime = +new Date();
- });
- };
- var isOutOfBoundary = function (scroll) {
- var hasHorizontalScroll = scroll.hasHorizontalScroll, hasVerticalScroll = scroll.hasVerticalScroll, x = scroll.x, y = scroll.y, minScrollX = scroll.minScrollX, maxScrollX = scroll.maxScrollX, minScrollY = scroll.minScrollY, maxScrollY = scroll.maxScrollY, movingDirectionX = scroll.movingDirectionX, movingDirectionY = scroll.movingDirectionY;
- var ret = false;
- var outOfLeftBoundary = x >= minScrollX && movingDirectionX === -1 /* Negative */;
- var outOfRightBoundary = x <= maxScrollX && movingDirectionX === 1 /* Positive */;
- var outOfTopBoundary = y >= minScrollY && movingDirectionY === -1 /* Negative */;
- var outOfBottomBoundary = y <= maxScrollY && movingDirectionY === 1 /* Positive */;
- if (hasVerticalScroll) {
- ret = outOfTopBoundary || outOfBottomBoundary;
- }
- else if (hasHorizontalScroll) {
- ret = outOfLeftBoundary || outOfRightBoundary;
- }
- return ret;
- };
- var isResettingPosition = function (scroll) {
- var hasHorizontalScroll = scroll.hasHorizontalScroll, hasVerticalScroll = scroll.hasVerticalScroll, x = scroll.x, y = scroll.y, minScrollX = scroll.minScrollX, maxScrollX = scroll.maxScrollX, minScrollY = scroll.minScrollY, maxScrollY = scroll.maxScrollY;
- var ret = false;
- var outOfLeftBoundary = x > minScrollX;
- var outOfRightBoundary = x < maxScrollX;
- var outOfTopBoundary = y > minScrollY;
- var outOfBottomBoundary = y < maxScrollY;
- if (hasVerticalScroll) {
- ret = outOfTopBoundary || outOfBottomBoundary;
- }
- else if (hasHorizontalScroll) {
- ret = outOfLeftBoundary || outOfRightBoundary;
- }
- return ret;
- };
- var resetPositionHandler = function (scroll) {
- scroll.scroller.reflow();
- scroll.resetPosition(0 /* Immediately */);
- };
- var calculateDistance = function (childNode, parentNode) {
- var distance = 0;
- var parent = childNode.parentNode;
- while (parent && parent !== parentNode) {
- distance++;
- parent = parent.parentNode;
- }
- return distance;
- };
- var NestedScroll = /** @class */ (function () {
- function NestedScroll(scroll) {
- var groupId = this.handleOptions(scroll);
- var instance = NestedScroll.instancesMap[groupId];
- if (!instance) {
- instance = NestedScroll.instancesMap[groupId] = this;
- instance.store = [];
- instance.hooksFn = [];
- }
- instance.init(scroll);
- return instance;
- }
- NestedScroll.getAllNestedScrolls = function () {
- var instancesMap = NestedScroll.instancesMap;
- return Object.keys(instancesMap).map(function (key) { return instancesMap[key]; });
- };
- NestedScroll.purgeAllNestedScrolls = function () {
- var nestedScrolls = NestedScroll.getAllNestedScrolls();
- nestedScrolls.forEach(function (ns) { return ns.purgeNestedScroll(); });
- };
- NestedScroll.prototype.handleOptions = function (scroll) {
- var userOptions = (scroll.options.nestedScroll === true
- ? {}
- : scroll.options.nestedScroll);
- var defaultOptions = {
- groupId: DEFAUL_GROUP_ID,
- };
- this.options = extend(defaultOptions, userOptions);
- var groupIdType = typeof this.options.groupId;
- if (groupIdType !== 'string' && groupIdType !== 'number') {
- warn('groupId must be string or number for NestedScroll plugin');
- }
- return this.options.groupId;
- };
- NestedScroll.prototype.init = function (scroll) {
- scroll.proxy(propertiesConfig);
- this.addBScroll(scroll);
- this.buildBScrollGraph();
- this.analyzeBScrollGraph();
- this.ensureEventInvokeSequence();
- this.handleHooks(scroll);
- };
- NestedScroll.prototype.handleHooks = function (scroll) {
- var _this = this;
- this.registerHooks(scroll.hooks, scroll.hooks.eventTypes.destroy, function () {
- _this.deleteScroll(scroll);
- });
- };
- NestedScroll.prototype.deleteScroll = function (scroll) {
- var wrapper = scroll.wrapper;
- wrapper.isBScrollContainer = undefined;
- var store = this.store;
- var hooksFn = this.hooksFn;
- var i = findIndex(store, function (bscrollFamily) {
- return bscrollFamily.selfScroll === scroll;
- });
- if (i > -1) {
- var bscrollFamily = store[i];
- bscrollFamily.purge();
- store.splice(i, 1);
- }
- var k = findIndex(hooksFn, function (_a) {
- var hooks = _a[0];
- return hooks === scroll.hooks;
- });
- if (k > -1) {
- var _a = hooksFn[k], hooks = _a[0], eventType = _a[1], handler = _a[2];
- hooks.off(eventType, handler);
- hooksFn.splice(k, 1);
- }
- };
- NestedScroll.prototype.addBScroll = function (scroll) {
- this.store.push(BScrollFamily.create(scroll));
- };
- NestedScroll.prototype.buildBScrollGraph = function () {
- var store = this.store;
- var bf1;
- var bf2;
- var wrapper1;
- var wrapper2;
- var len = this.store.length;
- // build graph
- for (var i = 0; i < len; i++) {
- bf1 = store[i];
- wrapper1 = bf1.selfScroll.wrapper;
- for (var j = 0; j < len; j++) {
- bf2 = store[j];
- wrapper2 = bf2.selfScroll.wrapper;
- // same bs
- if (bf1 === bf2)
- continue;
- if (!wrapper1.contains(wrapper2))
- continue;
- // bs1 contains bs2
- var distance = calculateDistance(wrapper2, wrapper1);
- if (!bf1.hasDescendants(bf2)) {
- bf1.addDescendant(bf2, distance);
- }
- if (!bf2.hasAncestors(bf1)) {
- bf2.addAncestor(bf1, distance);
- }
- }
- }
- };
- NestedScroll.prototype.analyzeBScrollGraph = function () {
- this.store.forEach(function (bscrollFamily) {
- if (bscrollFamily.analyzed) {
- return;
- }
- var ancestors = bscrollFamily.ancestors, descendants = bscrollFamily.descendants, currentScroll = bscrollFamily.selfScroll;
- var beforeScrollStartHandler = function () {
- // always get the latest scroll
- var ancestorScrolls = ancestors.map(function (_a) {
- var bscrollFamily = _a[0];
- return bscrollFamily.selfScroll;
- });
- var descendantScrolls = descendants.map(function (_a) {
- var bscrollFamily = _a[0];
- return bscrollFamily.selfScroll;
- });
- forceScrollStopHandler(__spreadArrays(ancestorScrolls, descendantScrolls));
- if (isResettingPosition(currentScroll)) {
- resetPositionHandler(currentScroll);
- }
- syncTouchstartData(ancestorScrolls);
- disableScrollHander(ancestorScrolls, currentScroll);
- };
- var touchEndHandler = function () {
- var ancestorScrolls = ancestors.map(function (_a) {
- var bscrollFamily = _a[0];
- return bscrollFamily.selfScroll;
- });
- var descendantScrolls = descendants.map(function (_a) {
- var bscrollFamily = _a[0];
- return bscrollFamily.selfScroll;
- });
- enableScrollHander(__spreadArrays(ancestorScrolls, descendantScrolls));
- };
- bscrollFamily.registerHooks(currentScroll, currentScroll.eventTypes.beforeScrollStart, beforeScrollStartHandler);
- bscrollFamily.registerHooks(currentScroll, currentScroll.eventTypes.touchEnd, touchEndHandler);
- var selfActionsHooks = currentScroll.scroller.actions.hooks;
- bscrollFamily.registerHooks(selfActionsHooks, selfActionsHooks.eventTypes.detectMovingDirection, function () {
- var ancestorScrolls = ancestors.map(function (_a) {
- var bscrollFamily = _a[0];
- return bscrollFamily.selfScroll;
- });
- var parentScroll = ancestorScrolls[0];
- var otherAncestorScrolls = ancestorScrolls.slice(1);
- var contentMoved = currentScroll.scroller.actions.contentMoved;
- var isTopScroll = ancestorScrolls.length === 0;
- if (contentMoved) {
- disableScrollHander(ancestorScrolls, currentScroll);
- }
- else if (!isTopScroll) {
- if (isOutOfBoundary(currentScroll)) {
- disableScrollHander([currentScroll], currentScroll);
- if (parentScroll) {
- enableScrollHander([parentScroll]);
- }
- disableScrollHander(otherAncestorScrolls, currentScroll);
- return true;
- }
- }
- });
- bscrollFamily.setAnalyzed(true);
- });
- };
- // make sure touchmove|touchend invoke from child to parent
- NestedScroll.prototype.ensureEventInvokeSequence = function () {
- var copied = this.store.slice();
- var sequencedScroll = copied.sort(function (a, b) {
- return a.descendants.length - b.descendants.length;
- });
- sequencedScroll.forEach(function (bscrollFamily) {
- var scroll = bscrollFamily.selfScroll;
- scroll.scroller.actionsHandler.rebindDOMEvents();
- });
- };
- NestedScroll.prototype.registerHooks = function (hooks, name, handler) {
- hooks.on(name, handler, this);
- this.hooksFn.push([hooks, name, handler]);
- };
- NestedScroll.prototype.purgeNestedScroll = function () {
- var groupId = this.options.groupId;
- this.store.forEach(function (bscrollFamily) {
- bscrollFamily.purge();
- });
- this.store = [];
- this.hooksFn.forEach(function (_a) {
- var hooks = _a[0], eventType = _a[1], handler = _a[2];
- hooks.off(eventType, handler);
- });
- this.hooksFn = [];
- delete NestedScroll.instancesMap[groupId];
- };
- NestedScroll.pluginName = 'nestedScroll';
- NestedScroll.instancesMap = {};
- return NestedScroll;
- }());
- exports.DEFAUL_GROUP_ID = DEFAUL_GROUP_ID;
- exports.default = NestedScroll;
- Object.defineProperty(exports, '__esModule', { value: true });
- })));
|