UNPKG

255 kBJavaScriptView Raw
1/*!
2 * better-scroll / better-scroll
3 * (c) 2016-2022 ustbhuangyi
4 * Released under the MIT License.
5 */
6/*! *****************************************************************************
7Copyright (c) Microsoft Corporation.
8
9Permission to use, copy, modify, and/or distribute this software for any
10purpose with or without fee is hereby granted.
11
12THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
13REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
14AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
15INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
16LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
17OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
18PERFORMANCE OF THIS SOFTWARE.
19***************************************************************************** */
20/* global Reflect, Promise */
21
22var extendStatics = function(d, b) {
23 extendStatics = Object.setPrototypeOf ||
24 ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
25 function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; };
26 return extendStatics(d, b);
27};
28
29function __extends(d, b) {
30 extendStatics(d, b);
31 function __() { this.constructor = d; }
32 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
33}
34
35var __assign = function() {
36 __assign = Object.assign || function __assign(t) {
37 for (var s, i = 1, n = arguments.length; i < n; i++) {
38 s = arguments[i];
39 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
40 }
41 return t;
42 };
43 return __assign.apply(this, arguments);
44};
45
46function __awaiter(thisArg, _arguments, P, generator) {
47 function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
48 return new (P || (P = Promise))(function (resolve, reject) {
49 function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
50 function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
51 function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
52 step((generator = generator.apply(thisArg, _arguments || [])).next());
53 });
54}
55
56function __generator(thisArg, body) {
57 var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
58 return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
59 function verb(n) { return function (v) { return step([n, v]); }; }
60 function step(op) {
61 if (f) throw new TypeError("Generator is already executing.");
62 while (_) try {
63 if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
64 if (y = 0, t) op = [op[0] & 2, t.value];
65 switch (op[0]) {
66 case 0: case 1: t = op; break;
67 case 4: _.label++; return { value: op[1], done: false };
68 case 5: _.label++; y = op[1]; op = [0]; continue;
69 case 7: op = _.ops.pop(); _.trys.pop(); continue;
70 default:
71 if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
72 if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
73 if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
74 if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
75 if (t[2]) _.ops.pop();
76 _.trys.pop(); continue;
77 }
78 op = body.call(thisArg, _);
79 } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
80 if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
81 }
82}
83
84function __spreadArrays() {
85 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
86 for (var r = Array(s), k = 0, i = 0; i < il; i++)
87 for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
88 r[k] = a[j];
89 return r;
90}
91
92var propertiesConfig$7 = [
93 {
94 sourceKey: 'scroller.scrollBehaviorX.currentPos',
95 key: 'x'
96 },
97 {
98 sourceKey: 'scroller.scrollBehaviorY.currentPos',
99 key: 'y'
100 },
101 {
102 sourceKey: 'scroller.scrollBehaviorX.hasScroll',
103 key: 'hasHorizontalScroll'
104 },
105 {
106 sourceKey: 'scroller.scrollBehaviorY.hasScroll',
107 key: 'hasVerticalScroll'
108 },
109 {
110 sourceKey: 'scroller.scrollBehaviorX.contentSize',
111 key: 'scrollerWidth'
112 },
113 {
114 sourceKey: 'scroller.scrollBehaviorY.contentSize',
115 key: 'scrollerHeight'
116 },
117 {
118 sourceKey: 'scroller.scrollBehaviorX.maxScrollPos',
119 key: 'maxScrollX'
120 },
121 {
122 sourceKey: 'scroller.scrollBehaviorY.maxScrollPos',
123 key: 'maxScrollY'
124 },
125 {
126 sourceKey: 'scroller.scrollBehaviorX.minScrollPos',
127 key: 'minScrollX'
128 },
129 {
130 sourceKey: 'scroller.scrollBehaviorY.minScrollPos',
131 key: 'minScrollY'
132 },
133 {
134 sourceKey: 'scroller.scrollBehaviorX.movingDirection',
135 key: 'movingDirectionX'
136 },
137 {
138 sourceKey: 'scroller.scrollBehaviorY.movingDirection',
139 key: 'movingDirectionY'
140 },
141 {
142 sourceKey: 'scroller.scrollBehaviorX.direction',
143 key: 'directionX'
144 },
145 {
146 sourceKey: 'scroller.scrollBehaviorY.direction',
147 key: 'directionY'
148 },
149 {
150 sourceKey: 'scroller.actions.enabled',
151 key: 'enabled'
152 },
153 {
154 sourceKey: 'scroller.animater.pending',
155 key: 'pending'
156 },
157 {
158 sourceKey: 'scroller.animater.stop',
159 key: 'stop'
160 },
161 {
162 sourceKey: 'scroller.scrollTo',
163 key: 'scrollTo'
164 },
165 {
166 sourceKey: 'scroller.scrollBy',
167 key: 'scrollBy'
168 },
169 {
170 sourceKey: 'scroller.scrollToElement',
171 key: 'scrollToElement'
172 },
173 {
174 sourceKey: 'scroller.resetPosition',
175 key: 'resetPosition'
176 }
177];
178
179function warn(msg) {
180 console.error("[BScroll warn]: " + msg);
181}
182function assert(condition, msg) {
183 if (!condition) {
184 throw new Error('[BScroll] ' + msg);
185 }
186}
187
188// ssr support
189var inBrowser = typeof window !== 'undefined';
190var ua = inBrowser && navigator.userAgent.toLowerCase();
191var isWeChatDevTools = !!(ua && /wechatdevtools/.test(ua));
192var isAndroid = ua && ua.indexOf('android') > 0;
193/* istanbul ignore next */
194var isIOSBadVersion = (function () {
195 if (typeof ua === 'string') {
196 var regex = /os (\d\d?_\d(_\d)?)/;
197 var matches = regex.exec(ua);
198 if (!matches)
199 return false;
200 var parts = matches[1].split('_').map(function (item) {
201 return parseInt(item, 10);
202 });
203 // ios version >= 13.4 issue 982
204 return !!(parts[0] === 13 && parts[1] >= 4);
205 }
206 return false;
207})();
208/* istanbul ignore next */
209var supportsPassive = false;
210/* istanbul ignore next */
211if (inBrowser) {
212 var EventName = 'test-passive';
213 try {
214 var opts = {};
215 Object.defineProperty(opts, 'passive', {
216 get: function () {
217 supportsPassive = true;
218 },
219 }); // https://github.com/facebook/flow/issues/285
220 window.addEventListener(EventName, function () { }, opts);
221 }
222 catch (e) { }
223}
224
225function getNow() {
226 return window.performance &&
227 window.performance.now &&
228 window.performance.timing
229 ? window.performance.now() + window.performance.timing.navigationStart
230 : +new Date();
231}
232var extend = function (target, source) {
233 for (var key in source) {
234 target[key] = source[key];
235 }
236 return target;
237};
238function isUndef(v) {
239 return v === undefined || v === null;
240}
241function getDistance(x, y) {
242 return Math.sqrt(x * x + y * y);
243}
244function between(x, min, max) {
245 if (x < min) {
246 return min;
247 }
248 if (x > max) {
249 return max;
250 }
251 return x;
252}
253function findIndex(ary, fn) {
254 if (ary.findIndex) {
255 return ary.findIndex(fn);
256 }
257 var index = -1;
258 ary.some(function (item, i, ary) {
259 var ret = fn(item, i, ary);
260 if (ret) {
261 index = i;
262 return ret;
263 }
264 });
265 return index;
266}
267
268var elementStyle = (inBrowser &&
269 document.createElement('div').style);
270var vendor = (function () {
271 /* istanbul ignore if */
272 if (!inBrowser) {
273 return false;
274 }
275 var transformNames = [
276 {
277 key: 'standard',
278 value: 'transform',
279 },
280 {
281 key: 'webkit',
282 value: 'webkitTransform',
283 },
284 {
285 key: 'Moz',
286 value: 'MozTransform',
287 },
288 {
289 key: 'O',
290 value: 'OTransform',
291 },
292 {
293 key: 'ms',
294 value: 'msTransform',
295 },
296 ];
297 for (var _i = 0, transformNames_1 = transformNames; _i < transformNames_1.length; _i++) {
298 var obj = transformNames_1[_i];
299 if (elementStyle[obj.value] !== undefined) {
300 return obj.key;
301 }
302 }
303 /* istanbul ignore next */
304 return false;
305})();
306/* istanbul ignore next */
307function prefixStyle(style) {
308 if (vendor === false) {
309 return style;
310 }
311 if (vendor === 'standard') {
312 if (style === 'transitionEnd') {
313 return 'transitionend';
314 }
315 return style;
316 }
317 return vendor + style.charAt(0).toUpperCase() + style.substr(1);
318}
319function getElement(el) {
320 return (typeof el === 'string' ? document.querySelector(el) : el);
321}
322function addEvent(el, type, fn, capture) {
323 var useCapture = supportsPassive
324 ? {
325 passive: false,
326 capture: !!capture,
327 }
328 : !!capture;
329 el.addEventListener(type, fn, useCapture);
330}
331function removeEvent(el, type, fn, capture) {
332 el.removeEventListener(type, fn, {
333 capture: !!capture,
334 });
335}
336function maybePrevent(e) {
337 if (e.cancelable) {
338 e.preventDefault();
339 }
340}
341function offset(el) {
342 var left = 0;
343 var top = 0;
344 while (el) {
345 left -= el.offsetLeft;
346 top -= el.offsetTop;
347 el = el.offsetParent;
348 }
349 return {
350 left: left,
351 top: top,
352 };
353}
354function offsetToBody(el) {
355 var rect = el.getBoundingClientRect();
356 return {
357 left: -(rect.left + window.pageXOffset),
358 top: -(rect.top + window.pageYOffset),
359 };
360}
361var cssVendor = vendor && vendor !== 'standard' ? '-' + vendor.toLowerCase() + '-' : '';
362var transform = prefixStyle('transform');
363var transition = prefixStyle('transition');
364var hasPerspective = inBrowser && prefixStyle('perspective') in elementStyle;
365// fix issue #361
366var hasTouch = inBrowser && ('ontouchstart' in window || isWeChatDevTools);
367var hasTransition = inBrowser && transition in elementStyle;
368var style = {
369 transform: transform,
370 transition: transition,
371 transitionTimingFunction: prefixStyle('transitionTimingFunction'),
372 transitionDuration: prefixStyle('transitionDuration'),
373 transitionDelay: prefixStyle('transitionDelay'),
374 transformOrigin: prefixStyle('transformOrigin'),
375 transitionEnd: prefixStyle('transitionEnd'),
376 transitionProperty: prefixStyle('transitionProperty'),
377};
378var eventTypeMap = {
379 touchstart: 1,
380 touchmove: 1,
381 touchend: 1,
382 touchcancel: 1,
383 mousedown: 2,
384 mousemove: 2,
385 mouseup: 2,
386};
387function getRect(el) {
388 /* istanbul ignore if */
389 if (el instanceof window.SVGElement) {
390 var rect = el.getBoundingClientRect();
391 return {
392 top: rect.top,
393 left: rect.left,
394 width: rect.width,
395 height: rect.height,
396 };
397 }
398 else {
399 return {
400 top: el.offsetTop,
401 left: el.offsetLeft,
402 width: el.offsetWidth,
403 height: el.offsetHeight,
404 };
405 }
406}
407function preventDefaultExceptionFn(el, exceptions) {
408 for (var i in exceptions) {
409 if (exceptions[i].test(el[i])) {
410 return true;
411 }
412 }
413 return false;
414}
415var tagExceptionFn = preventDefaultExceptionFn;
416function tap(e, eventName) {
417 var ev = document.createEvent('Event');
418 ev.initEvent(eventName, true, true);
419 ev.pageX = e.pageX;
420 ev.pageY = e.pageY;
421 e.target.dispatchEvent(ev);
422}
423function click(e, event) {
424 if (event === void 0) { event = 'click'; }
425 var eventSource;
426 if (e.type === 'mouseup') {
427 eventSource = e;
428 }
429 else if (e.type === 'touchend' || e.type === 'touchcancel') {
430 eventSource = e.changedTouches[0];
431 }
432 var posSrc = {};
433 if (eventSource) {
434 posSrc.screenX = eventSource.screenX || 0;
435 posSrc.screenY = eventSource.screenY || 0;
436 posSrc.clientX = eventSource.clientX || 0;
437 posSrc.clientY = eventSource.clientY || 0;
438 }
439 var ev;
440 var bubbles = true;
441 var cancelable = true;
442 var ctrlKey = e.ctrlKey, shiftKey = e.shiftKey, altKey = e.altKey, metaKey = e.metaKey;
443 var pressedKeysMap = {
444 ctrlKey: ctrlKey,
445 shiftKey: shiftKey,
446 altKey: altKey,
447 metaKey: metaKey,
448 };
449 if (typeof MouseEvent !== 'undefined') {
450 try {
451 ev = new MouseEvent(event, extend(__assign({ bubbles: bubbles,
452 cancelable: cancelable }, pressedKeysMap), posSrc));
453 }
454 catch (e) {
455 /* istanbul ignore next */
456 createEvent();
457 }
458 }
459 else {
460 createEvent();
461 }
462 function createEvent() {
463 ev = document.createEvent('Event');
464 ev.initEvent(event, bubbles, cancelable);
465 extend(ev, posSrc);
466 }
467 // forwardedTouchEvent set to true in case of the conflict with fastclick
468 ev.forwardedTouchEvent = true;
469 ev._constructed = true;
470 e.target.dispatchEvent(ev);
471}
472function dblclick(e) {
473 click(e, 'dblclick');
474}
475function prepend(el, target) {
476 var firstChild = target.firstChild;
477 if (firstChild) {
478 before(el, firstChild);
479 }
480 else {
481 target.appendChild(el);
482 }
483}
484function before(el, target) {
485 var parentNode = target.parentNode;
486 parentNode.insertBefore(el, target);
487}
488function removeChild(el, child) {
489 el.removeChild(child);
490}
491function hasClass(el, className) {
492 var reg = new RegExp('(^|\\s)' + className + '(\\s|$)');
493 return reg.test(el.className);
494}
495function HTMLCollectionToArray(el) {
496 return Array.prototype.slice.call(el, 0);
497}
498function getClientSize(el) {
499 return {
500 width: el.clientWidth,
501 height: el.clientHeight,
502 };
503}
504
505var ease = {
506 // easeOutQuint
507 swipe: {
508 style: 'cubic-bezier(0.23, 1, 0.32, 1)',
509 fn: function (t) {
510 return 1 + --t * t * t * t * t;
511 }
512 },
513 // easeOutQuard
514 swipeBounce: {
515 style: 'cubic-bezier(0.25, 0.46, 0.45, 0.94)',
516 fn: function (t) {
517 return t * (2 - t);
518 }
519 },
520 // easeOutQuart
521 bounce: {
522 style: 'cubic-bezier(0.165, 0.84, 0.44, 1)',
523 fn: function (t) {
524 return 1 - --t * t * t * t;
525 }
526 }
527};
528
529var DEFAULT_INTERVAL = 1000 / 60;
530var windowCompat = inBrowser && window;
531/* istanbul ignore next */
532function noop$1() { }
533var requestAnimationFrame = (function () {
534 /* istanbul ignore if */
535 if (!inBrowser) {
536 return noop$1;
537 }
538 return (windowCompat.requestAnimationFrame ||
539 windowCompat.webkitRequestAnimationFrame ||
540 windowCompat.mozRequestAnimationFrame ||
541 windowCompat.oRequestAnimationFrame ||
542 // if all else fails, use setTimeout
543 function (callback) {
544 return window.setTimeout(callback, callback.interval || DEFAULT_INTERVAL); // make interval as precise as possible.
545 });
546})();
547var cancelAnimationFrame = (function () {
548 /* istanbul ignore if */
549 if (!inBrowser) {
550 return noop$1;
551 }
552 return (windowCompat.cancelAnimationFrame ||
553 windowCompat.webkitCancelAnimationFrame ||
554 windowCompat.mozCancelAnimationFrame ||
555 windowCompat.oCancelAnimationFrame ||
556 function (id) {
557 window.clearTimeout(id);
558 });
559})();
560
561/* istanbul ignore next */
562var noop = function (val) { };
563var sharedPropertyDefinition = {
564 enumerable: true,
565 configurable: true,
566 get: noop,
567 set: noop,
568};
569var getProperty = function (obj, key) {
570 var keys = key.split('.');
571 for (var i = 0; i < keys.length - 1; i++) {
572 obj = obj[keys[i]];
573 if (typeof obj !== 'object' || !obj)
574 return;
575 }
576 var lastKey = keys.pop();
577 if (typeof obj[lastKey] === 'function') {
578 return function () {
579 return obj[lastKey].apply(obj, arguments);
580 };
581 }
582 else {
583 return obj[lastKey];
584 }
585};
586var setProperty = function (obj, key, value) {
587 var keys = key.split('.');
588 var temp;
589 for (var i = 0; i < keys.length - 1; i++) {
590 temp = keys[i];
591 if (!obj[temp])
592 obj[temp] = {};
593 obj = obj[temp];
594 }
595 obj[keys.pop()] = value;
596};
597function propertiesProxy(target, sourceKey, key) {
598 sharedPropertyDefinition.get = function proxyGetter() {
599 return getProperty(this, sourceKey);
600 };
601 sharedPropertyDefinition.set = function proxySetter(val) {
602 setProperty(this, sourceKey, val);
603 };
604 Object.defineProperty(target, key, sharedPropertyDefinition);
605}
606
607var EventEmitter = /** @class */ (function () {
608 function EventEmitter(names) {
609 this.events = {};
610 this.eventTypes = {};
611 this.registerType(names);
612 }
613 EventEmitter.prototype.on = function (type, fn, context) {
614 if (context === void 0) { context = this; }
615 this.hasType(type);
616 if (!this.events[type]) {
617 this.events[type] = [];
618 }
619 this.events[type].push([fn, context]);
620 return this;
621 };
622 EventEmitter.prototype.once = function (type, fn, context) {
623 var _this = this;
624 if (context === void 0) { context = this; }
625 this.hasType(type);
626 var magic = function () {
627 var args = [];
628 for (var _i = 0; _i < arguments.length; _i++) {
629 args[_i] = arguments[_i];
630 }
631 _this.off(type, magic);
632 var ret = fn.apply(context, args);
633 if (ret === true) {
634 return ret;
635 }
636 };
637 magic.fn = fn;
638 this.on(type, magic);
639 return this;
640 };
641 EventEmitter.prototype.off = function (type, fn) {
642 if (!type && !fn) {
643 this.events = {};
644 return this;
645 }
646 if (type) {
647 this.hasType(type);
648 if (!fn) {
649 this.events[type] = [];
650 return this;
651 }
652 var events = this.events[type];
653 if (!events) {
654 return this;
655 }
656 var count = events.length;
657 while (count--) {
658 if (events[count][0] === fn ||
659 (events[count][0] && events[count][0].fn === fn)) {
660 events.splice(count, 1);
661 }
662 }
663 return this;
664 }
665 };
666 EventEmitter.prototype.trigger = function (type) {
667 var args = [];
668 for (var _i = 1; _i < arguments.length; _i++) {
669 args[_i - 1] = arguments[_i];
670 }
671 this.hasType(type);
672 var events = this.events[type];
673 if (!events) {
674 return;
675 }
676 var len = events.length;
677 var eventsCopy = __spreadArrays(events);
678 var ret;
679 for (var i = 0; i < len; i++) {
680 var event_1 = eventsCopy[i];
681 var fn = event_1[0], context = event_1[1];
682 if (fn) {
683 ret = fn.apply(context, args);
684 if (ret === true) {
685 return ret;
686 }
687 }
688 }
689 };
690 EventEmitter.prototype.registerType = function (names) {
691 var _this = this;
692 names.forEach(function (type) {
693 _this.eventTypes[type] = type;
694 });
695 };
696 EventEmitter.prototype.destroy = function () {
697 this.events = {};
698 this.eventTypes = {};
699 };
700 EventEmitter.prototype.hasType = function (type) {
701 var types = this.eventTypes;
702 var isType = types[type] === type;
703 if (!isType) {
704 warn("EventEmitter has used unknown event type: \"" + type + "\", should be oneof [" +
705 ("" + Object.keys(types).map(function (_) { return JSON.stringify(_); })) +
706 "]");
707 }
708 };
709 return EventEmitter;
710}());
711var EventRegister = /** @class */ (function () {
712 function EventRegister(wrapper, events) {
713 this.wrapper = wrapper;
714 this.events = events;
715 this.addDOMEvents();
716 }
717 EventRegister.prototype.destroy = function () {
718 this.removeDOMEvents();
719 this.events = [];
720 };
721 EventRegister.prototype.addDOMEvents = function () {
722 this.handleDOMEvents(addEvent);
723 };
724 EventRegister.prototype.removeDOMEvents = function () {
725 this.handleDOMEvents(removeEvent);
726 };
727 EventRegister.prototype.handleDOMEvents = function (eventOperation) {
728 var _this = this;
729 var wrapper = this.wrapper;
730 this.events.forEach(function (event) {
731 eventOperation(wrapper, event.name, _this, !!event.capture);
732 });
733 };
734 EventRegister.prototype.handleEvent = function (e) {
735 var eventType = e.type;
736 this.events.some(function (event) {
737 if (event.name === eventType) {
738 event.handler(e);
739 return true;
740 }
741 return false;
742 });
743 };
744 return EventRegister;
745}());
746
747var CustomOptions = /** @class */ (function () {
748 function CustomOptions() {
749 }
750 return CustomOptions;
751}());
752var OptionsConstructor = /** @class */ (function (_super) {
753 __extends(OptionsConstructor, _super);
754 function OptionsConstructor() {
755 var _this = _super.call(this) || this;
756 _this.startX = 0;
757 _this.startY = 0;
758 _this.scrollX = false;
759 _this.scrollY = true;
760 _this.freeScroll = false;
761 _this.directionLockThreshold = 0;
762 _this.eventPassthrough = "" /* None */;
763 _this.click = false;
764 _this.dblclick = false;
765 _this.tap = '';
766 _this.bounce = {
767 top: true,
768 bottom: true,
769 left: true,
770 right: true,
771 };
772 _this.bounceTime = 800;
773 _this.momentum = true;
774 _this.momentumLimitTime = 300;
775 _this.momentumLimitDistance = 15;
776 _this.swipeTime = 2500;
777 _this.swipeBounceTime = 500;
778 _this.deceleration = 0.0015;
779 _this.flickLimitTime = 200;
780 _this.flickLimitDistance = 100;
781 _this.resizePolling = 60;
782 _this.probeType = 0 /* Default */;
783 _this.stopPropagation = false;
784 _this.preventDefault = true;
785 _this.preventDefaultException = {
786 tagName: /^(INPUT|TEXTAREA|BUTTON|SELECT|AUDIO)$/,
787 };
788 _this.tagException = {
789 tagName: /^TEXTAREA$/,
790 };
791 _this.HWCompositing = true;
792 _this.useTransition = true;
793 _this.bindToWrapper = false;
794 _this.bindToTarget = false;
795 _this.disableMouse = hasTouch;
796 _this.disableTouch = !hasTouch;
797 _this.autoBlur = true;
798 _this.autoEndDistance = 5;
799 _this.outOfBoundaryDampingFactor = 1 / 3;
800 _this.specifiedIndexAsContent = 0;
801 _this.quadrant = 1 /* First */;
802 return _this;
803 }
804 OptionsConstructor.prototype.merge = function (options) {
805 if (!options)
806 return this;
807 for (var key in options) {
808 if (key === 'bounce') {
809 this.bounce = this.resolveBounce(options[key]);
810 continue;
811 }
812 this[key] = options[key];
813 }
814 return this;
815 };
816 OptionsConstructor.prototype.process = function () {
817 this.translateZ =
818 this.HWCompositing && hasPerspective ? ' translateZ(1px)' : '';
819 this.useTransition = this.useTransition && hasTransition;
820 this.preventDefault = !this.eventPassthrough && this.preventDefault;
821 // If you want eventPassthrough I have to lock one of the axes
822 this.scrollX =
823 this.eventPassthrough === "horizontal" /* Horizontal */
824 ? false
825 : this.scrollX;
826 this.scrollY =
827 this.eventPassthrough === "vertical" /* Vertical */ ? false : this.scrollY;
828 // With eventPassthrough we also need lockDirection mechanism
829 this.freeScroll = this.freeScroll && !this.eventPassthrough;
830 // force true when freeScroll is true
831 this.scrollX = this.freeScroll ? true : this.scrollX;
832 this.scrollY = this.freeScroll ? true : this.scrollY;
833 this.directionLockThreshold = this.eventPassthrough
834 ? 0
835 : this.directionLockThreshold;
836 return this;
837 };
838 OptionsConstructor.prototype.resolveBounce = function (bounceOptions) {
839 var DEFAULT_BOUNCE = {
840 top: true,
841 right: true,
842 bottom: true,
843 left: true,
844 };
845 var NEGATED_BOUNCE = {
846 top: false,
847 right: false,
848 bottom: false,
849 left: false,
850 };
851 var ret;
852 if (typeof bounceOptions === 'object') {
853 ret = extend(DEFAULT_BOUNCE, bounceOptions);
854 }
855 else {
856 ret = bounceOptions ? DEFAULT_BOUNCE : NEGATED_BOUNCE;
857 }
858 return ret;
859 };
860 return OptionsConstructor;
861}(CustomOptions));
862
863var ActionsHandler = /** @class */ (function () {
864 function ActionsHandler(wrapper, options) {
865 this.wrapper = wrapper;
866 this.options = options;
867 this.hooks = new EventEmitter([
868 'beforeStart',
869 'start',
870 'move',
871 'end',
872 'click',
873 ]);
874 this.handleDOMEvents();
875 }
876 ActionsHandler.prototype.handleDOMEvents = function () {
877 var _a = this.options, bindToWrapper = _a.bindToWrapper, disableMouse = _a.disableMouse, disableTouch = _a.disableTouch, click = _a.click;
878 var wrapper = this.wrapper;
879 var target = bindToWrapper ? wrapper : window;
880 var wrapperEvents = [];
881 var targetEvents = [];
882 var shouldRegisterTouch = !disableTouch;
883 var shouldRegisterMouse = !disableMouse;
884 if (click) {
885 wrapperEvents.push({
886 name: 'click',
887 handler: this.click.bind(this),
888 capture: true,
889 });
890 }
891 if (shouldRegisterTouch) {
892 wrapperEvents.push({
893 name: 'touchstart',
894 handler: this.start.bind(this),
895 });
896 targetEvents.push({
897 name: 'touchmove',
898 handler: this.move.bind(this),
899 }, {
900 name: 'touchend',
901 handler: this.end.bind(this),
902 }, {
903 name: 'touchcancel',
904 handler: this.end.bind(this),
905 });
906 }
907 if (shouldRegisterMouse) {
908 wrapperEvents.push({
909 name: 'mousedown',
910 handler: this.start.bind(this),
911 });
912 targetEvents.push({
913 name: 'mousemove',
914 handler: this.move.bind(this),
915 }, {
916 name: 'mouseup',
917 handler: this.end.bind(this),
918 });
919 }
920 this.wrapperEventRegister = new EventRegister(wrapper, wrapperEvents);
921 this.targetEventRegister = new EventRegister(target, targetEvents);
922 };
923 ActionsHandler.prototype.beforeHandler = function (e, type) {
924 var _a = this.options, preventDefault = _a.preventDefault, stopPropagation = _a.stopPropagation, preventDefaultException = _a.preventDefaultException;
925 var preventDefaultConditions = {
926 start: function () {
927 return (preventDefault &&
928 !preventDefaultExceptionFn(e.target, preventDefaultException));
929 },
930 end: function () {
931 return (preventDefault &&
932 !preventDefaultExceptionFn(e.target, preventDefaultException));
933 },
934 move: function () {
935 return preventDefault;
936 },
937 };
938 if (preventDefaultConditions[type]()) {
939 e.preventDefault();
940 }
941 if (stopPropagation) {
942 e.stopPropagation();
943 }
944 };
945 ActionsHandler.prototype.setInitiated = function (type) {
946 if (type === void 0) { type = 0; }
947 this.initiated = type;
948 };
949 ActionsHandler.prototype.start = function (e) {
950 var _eventType = eventTypeMap[e.type];
951 if (this.initiated && this.initiated !== _eventType) {
952 return;
953 }
954 this.setInitiated(_eventType);
955 // if textarea or other html tags in options.tagException is manipulated
956 // do not make bs scroll
957 if (tagExceptionFn(e.target, this.options.tagException)) {
958 this.setInitiated();
959 return;
960 }
961 // only allow mouse left button
962 if (_eventType === 2 /* Mouse */ && e.button !== 0 /* Left */)
963 return;
964 if (this.hooks.trigger(this.hooks.eventTypes.beforeStart, e)) {
965 return;
966 }
967 this.beforeHandler(e, 'start');
968 var point = (e.touches ? e.touches[0] : e);
969 this.pointX = point.pageX;
970 this.pointY = point.pageY;
971 this.hooks.trigger(this.hooks.eventTypes.start, e);
972 };
973 ActionsHandler.prototype.move = function (e) {
974 if (eventTypeMap[e.type] !== this.initiated) {
975 return;
976 }
977 this.beforeHandler(e, 'move');
978 var point = (e.touches ? e.touches[0] : e);
979 var deltaX = point.pageX - this.pointX;
980 var deltaY = point.pageY - this.pointY;
981 this.pointX = point.pageX;
982 this.pointY = point.pageY;
983 if (this.hooks.trigger(this.hooks.eventTypes.move, {
984 deltaX: deltaX,
985 deltaY: deltaY,
986 e: e,
987 })) {
988 return;
989 }
990 // auto end when out of viewport
991 var scrollLeft = document.documentElement.scrollLeft ||
992 window.pageXOffset ||
993 document.body.scrollLeft;
994 var scrollTop = document.documentElement.scrollTop ||
995 window.pageYOffset ||
996 document.body.scrollTop;
997 var pX = this.pointX - scrollLeft;
998 var pY = this.pointY - scrollTop;
999 var autoEndDistance = this.options.autoEndDistance;
1000 if (pX > document.documentElement.clientWidth - autoEndDistance ||
1001 pY > document.documentElement.clientHeight - autoEndDistance ||
1002 pX < autoEndDistance ||
1003 pY < autoEndDistance) {
1004 this.end(e);
1005 }
1006 };
1007 ActionsHandler.prototype.end = function (e) {
1008 if (eventTypeMap[e.type] !== this.initiated) {
1009 return;
1010 }
1011 this.setInitiated();
1012 this.beforeHandler(e, 'end');
1013 this.hooks.trigger(this.hooks.eventTypes.end, e);
1014 };
1015 ActionsHandler.prototype.click = function (e) {
1016 this.hooks.trigger(this.hooks.eventTypes.click, e);
1017 };
1018 ActionsHandler.prototype.setContent = function (content) {
1019 if (content !== this.wrapper) {
1020 this.wrapper = content;
1021 this.rebindDOMEvents();
1022 }
1023 };
1024 ActionsHandler.prototype.rebindDOMEvents = function () {
1025 this.wrapperEventRegister.destroy();
1026 this.targetEventRegister.destroy();
1027 this.handleDOMEvents();
1028 };
1029 ActionsHandler.prototype.destroy = function () {
1030 this.wrapperEventRegister.destroy();
1031 this.targetEventRegister.destroy();
1032 this.hooks.destroy();
1033 };
1034 return ActionsHandler;
1035}());
1036
1037var translaterMetaData = {
1038 x: ['translateX', 'px'],
1039 y: ['translateY', 'px'],
1040};
1041var Translater = /** @class */ (function () {
1042 function Translater(content) {
1043 this.setContent(content);
1044 this.hooks = new EventEmitter(['beforeTranslate', 'translate']);
1045 }
1046 Translater.prototype.getComputedPosition = function () {
1047 var cssStyle = window.getComputedStyle(this.content, null);
1048 var matrix = cssStyle[style.transform].split(')')[0].split(', ');
1049 var x = +(matrix[12] || matrix[4]) || 0;
1050 var y = +(matrix[13] || matrix[5]) || 0;
1051 return {
1052 x: x,
1053 y: y,
1054 };
1055 };
1056 Translater.prototype.translate = function (point) {
1057 var transformStyle = [];
1058 Object.keys(point).forEach(function (key) {
1059 if (!translaterMetaData[key]) {
1060 return;
1061 }
1062 var transformFnName = translaterMetaData[key][0];
1063 if (transformFnName) {
1064 var transformFnArgUnit = translaterMetaData[key][1];
1065 var transformFnArg = point[key];
1066 transformStyle.push(transformFnName + "(" + transformFnArg + transformFnArgUnit + ")");
1067 }
1068 });
1069 this.hooks.trigger(this.hooks.eventTypes.beforeTranslate, transformStyle, point);
1070 this.style[style.transform] = transformStyle.join(' ');
1071 this.hooks.trigger(this.hooks.eventTypes.translate, point);
1072 };
1073 Translater.prototype.setContent = function (content) {
1074 if (this.content !== content) {
1075 this.content = content;
1076 this.style = content.style;
1077 }
1078 };
1079 Translater.prototype.destroy = function () {
1080 this.hooks.destroy();
1081 };
1082 return Translater;
1083}());
1084
1085var Base = /** @class */ (function () {
1086 function Base(content, translater, options) {
1087 this.translater = translater;
1088 this.options = options;
1089 this.timer = 0;
1090 this.hooks = new EventEmitter([
1091 'move',
1092 'end',
1093 'beforeForceStop',
1094 'forceStop',
1095 'callStop',
1096 'time',
1097 'timeFunction',
1098 ]);
1099 this.setContent(content);
1100 }
1101 Base.prototype.translate = function (endPoint) {
1102 this.translater.translate(endPoint);
1103 };
1104 Base.prototype.setPending = function (pending) {
1105 this.pending = pending;
1106 };
1107 Base.prototype.setForceStopped = function (forceStopped) {
1108 this.forceStopped = forceStopped;
1109 };
1110 Base.prototype.setCallStop = function (called) {
1111 this.callStopWhenPending = called;
1112 };
1113 Base.prototype.setContent = function (content) {
1114 if (this.content !== content) {
1115 this.content = content;
1116 this.style = content.style;
1117 this.stop();
1118 }
1119 };
1120 Base.prototype.clearTimer = function () {
1121 if (this.timer) {
1122 cancelAnimationFrame(this.timer);
1123 this.timer = 0;
1124 }
1125 };
1126 Base.prototype.destroy = function () {
1127 this.hooks.destroy();
1128 cancelAnimationFrame(this.timer);
1129 };
1130 return Base;
1131}());
1132
1133// iOS 13.6 - 14.x, window.getComputedStyle sometimes will get wrong transform value
1134// when bs use transition mode
1135// eg: translateY -100px -> -200px, when the last frame which is about to scroll to -200px
1136// window.getComputedStyle(this.content) will calculate transformY to be -100px(startPoint)
1137// it is weird
1138// so we should validate position caculated by 'window.getComputedStyle'
1139var isValidPostion = function (startPoint, endPoint, currentPos, prePos) {
1140 var computeDirection = function (endValue, startValue) {
1141 var delta = endValue - startValue;
1142 var direction = delta > 0
1143 ? -1 /* Negative */
1144 : delta < 0
1145 ? 1 /* Positive */
1146 : 0 /* Default */;
1147 return direction;
1148 };
1149 var directionX = computeDirection(endPoint.x, startPoint.x);
1150 var directionY = computeDirection(endPoint.y, startPoint.y);
1151 var deltaX = currentPos.x - prePos.x;
1152 var deltaY = currentPos.y - prePos.y;
1153 return directionX * deltaX <= 0 && directionY * deltaY <= 0;
1154};
1155
1156var Transition = /** @class */ (function (_super) {
1157 __extends(Transition, _super);
1158 function Transition() {
1159 return _super !== null && _super.apply(this, arguments) || this;
1160 }
1161 Transition.prototype.startProbe = function (startPoint, endPoint) {
1162 var _this = this;
1163 var prePos = startPoint;
1164 var probe = function () {
1165 var pos = _this.translater.getComputedPosition();
1166 if (isValidPostion(startPoint, endPoint, pos, prePos)) {
1167 _this.hooks.trigger(_this.hooks.eventTypes.move, pos);
1168 }
1169 // call bs.stop() should not dispatch end hook again.
1170 // forceStop hook will do this.
1171 /* istanbul ignore if */
1172 if (!_this.pending) {
1173 if (_this.callStopWhenPending) {
1174 _this.callStopWhenPending = false;
1175 }
1176 else {
1177 // transition ends should dispatch end hook.
1178 _this.hooks.trigger(_this.hooks.eventTypes.end, pos);
1179 }
1180 }
1181 prePos = pos;
1182 if (_this.pending) {
1183 _this.timer = requestAnimationFrame(probe);
1184 }
1185 };
1186 // when manually call bs.stop(), then bs.scrollTo()
1187 // we should reset callStopWhenPending to dispatch end hook
1188 if (this.callStopWhenPending) {
1189 this.setCallStop(false);
1190 }
1191 cancelAnimationFrame(this.timer);
1192 probe();
1193 };
1194 Transition.prototype.transitionTime = function (time) {
1195 if (time === void 0) { time = 0; }
1196 this.style[style.transitionDuration] = time + 'ms';
1197 this.hooks.trigger(this.hooks.eventTypes.time, time);
1198 };
1199 Transition.prototype.transitionTimingFunction = function (easing) {
1200 this.style[style.transitionTimingFunction] = easing;
1201 this.hooks.trigger(this.hooks.eventTypes.timeFunction, easing);
1202 };
1203 Transition.prototype.transitionProperty = function () {
1204 this.style[style.transitionProperty] = style.transform;
1205 };
1206 Transition.prototype.move = function (startPoint, endPoint, time, easingFn) {
1207 this.setPending(time > 0);
1208 this.transitionTimingFunction(easingFn);
1209 this.transitionProperty();
1210 this.transitionTime(time);
1211 this.translate(endPoint);
1212 var isRealtimeProbeType = this.options.probeType === 3 /* Realtime */;
1213 if (time && isRealtimeProbeType) {
1214 this.startProbe(startPoint, endPoint);
1215 }
1216 // if we change content's transformY in a tick
1217 // such as: 0 -> 50px -> 0
1218 // transitionend will not be triggered
1219 // so we forceupdate by reflow
1220 if (!time) {
1221 this._reflow = this.content.offsetHeight;
1222 if (isRealtimeProbeType) {
1223 this.hooks.trigger(this.hooks.eventTypes.move, endPoint);
1224 }
1225 this.hooks.trigger(this.hooks.eventTypes.end, endPoint);
1226 }
1227 };
1228 Transition.prototype.doStop = function () {
1229 var pending = this.pending;
1230 this.setForceStopped(false);
1231 this.setCallStop(false);
1232 // still in transition
1233 if (pending) {
1234 this.setPending(false);
1235 cancelAnimationFrame(this.timer);
1236 var _a = this.translater.getComputedPosition(), x = _a.x, y = _a.y;
1237 this.transitionTime();
1238 this.translate({ x: x, y: y });
1239 this.setForceStopped(true);
1240 this.setCallStop(true);
1241 this.hooks.trigger(this.hooks.eventTypes.forceStop, { x: x, y: y });
1242 }
1243 return pending;
1244 };
1245 Transition.prototype.stop = function () {
1246 var stopFromTransition = this.doStop();
1247 if (stopFromTransition) {
1248 this.hooks.trigger(this.hooks.eventTypes.callStop);
1249 }
1250 };
1251 return Transition;
1252}(Base));
1253
1254var Animation = /** @class */ (function (_super) {
1255 __extends(Animation, _super);
1256 function Animation() {
1257 return _super !== null && _super.apply(this, arguments) || this;
1258 }
1259 Animation.prototype.move = function (startPoint, endPoint, time, easingFn) {
1260 // time is 0
1261 if (!time) {
1262 this.translate(endPoint);
1263 if (this.options.probeType === 3 /* Realtime */) {
1264 this.hooks.trigger(this.hooks.eventTypes.move, endPoint);
1265 }
1266 this.hooks.trigger(this.hooks.eventTypes.end, endPoint);
1267 return;
1268 }
1269 this.animate(startPoint, endPoint, time, easingFn);
1270 };
1271 Animation.prototype.animate = function (startPoint, endPoint, duration, easingFn) {
1272 var _this = this;
1273 var startTime = getNow();
1274 var destTime = startTime + duration;
1275 var isRealtimeProbeType = this.options.probeType === 3 /* Realtime */;
1276 var step = function () {
1277 var now = getNow();
1278 // js animation end
1279 if (now >= destTime) {
1280 _this.translate(endPoint);
1281 if (isRealtimeProbeType) {
1282 _this.hooks.trigger(_this.hooks.eventTypes.move, endPoint);
1283 }
1284 _this.hooks.trigger(_this.hooks.eventTypes.end, endPoint);
1285 return;
1286 }
1287 now = (now - startTime) / duration;
1288 var easing = easingFn(now);
1289 var newPoint = {};
1290 Object.keys(endPoint).forEach(function (key) {
1291 var startValue = startPoint[key];
1292 var endValue = endPoint[key];
1293 newPoint[key] = (endValue - startValue) * easing + startValue;
1294 });
1295 _this.translate(newPoint);
1296 if (isRealtimeProbeType) {
1297 _this.hooks.trigger(_this.hooks.eventTypes.move, newPoint);
1298 }
1299 if (_this.pending) {
1300 _this.timer = requestAnimationFrame(step);
1301 }
1302 // call bs.stop() should not dispatch end hook again.
1303 // forceStop hook will do this.
1304 /* istanbul ignore if */
1305 if (!_this.pending) {
1306 if (_this.callStopWhenPending) {
1307 _this.callStopWhenPending = false;
1308 }
1309 else {
1310 // raf ends should dispatch end hook.
1311 _this.hooks.trigger(_this.hooks.eventTypes.end, endPoint);
1312 }
1313 }
1314 };
1315 this.setPending(true);
1316 // when manually call bs.stop(), then bs.scrollTo()
1317 // we should reset callStopWhenPending to dispatch end hook
1318 if (this.callStopWhenPending) {
1319 this.setCallStop(false);
1320 }
1321 cancelAnimationFrame(this.timer);
1322 step();
1323 };
1324 Animation.prototype.doStop = function () {
1325 var pending = this.pending;
1326 this.setForceStopped(false);
1327 this.setCallStop(false);
1328 // still in requestFrameAnimation
1329 if (pending) {
1330 this.setPending(false);
1331 cancelAnimationFrame(this.timer);
1332 var pos = this.translater.getComputedPosition();
1333 this.setForceStopped(true);
1334 this.setCallStop(true);
1335 this.hooks.trigger(this.hooks.eventTypes.forceStop, pos);
1336 }
1337 return pending;
1338 };
1339 Animation.prototype.stop = function () {
1340 var stopFromAnimation = this.doStop();
1341 if (stopFromAnimation) {
1342 this.hooks.trigger(this.hooks.eventTypes.callStop);
1343 }
1344 };
1345 return Animation;
1346}(Base));
1347
1348function createAnimater(element, translater, options) {
1349 var useTransition = options.useTransition;
1350 var animaterOptions = {};
1351 Object.defineProperty(animaterOptions, 'probeType', {
1352 enumerable: true,
1353 configurable: false,
1354 get: function () {
1355 return options.probeType;
1356 },
1357 });
1358 if (useTransition) {
1359 return new Transition(element, translater, animaterOptions);
1360 }
1361 else {
1362 return new Animation(element, translater, animaterOptions);
1363 }
1364}
1365
1366var Behavior = /** @class */ (function () {
1367 function Behavior(wrapper, content, options) {
1368 this.wrapper = wrapper;
1369 this.options = options;
1370 this.hooks = new EventEmitter([
1371 'beforeComputeBoundary',
1372 'computeBoundary',
1373 'momentum',
1374 'end',
1375 'ignoreHasScroll'
1376 ]);
1377 this.refresh(content);
1378 }
1379 Behavior.prototype.start = function () {
1380 this.dist = 0;
1381 this.setMovingDirection(0 /* Default */);
1382 this.setDirection(0 /* Default */);
1383 };
1384 Behavior.prototype.move = function (delta) {
1385 delta = this.hasScroll ? delta : 0;
1386 this.setMovingDirection(delta);
1387 return this.performDampingAlgorithm(delta, this.options.outOfBoundaryDampingFactor);
1388 };
1389 Behavior.prototype.setMovingDirection = function (delta) {
1390 this.movingDirection =
1391 delta > 0
1392 ? -1 /* Negative */
1393 : delta < 0
1394 ? 1 /* Positive */
1395 : 0 /* Default */;
1396 };
1397 Behavior.prototype.setDirection = function (delta) {
1398 this.direction =
1399 delta > 0
1400 ? -1 /* Negative */
1401 : delta < 0
1402 ? 1 /* Positive */
1403 : 0 /* Default */;
1404 };
1405 Behavior.prototype.performDampingAlgorithm = function (delta, dampingFactor) {
1406 var newPos = this.currentPos + delta;
1407 // Slow down or stop if outside of the boundaries
1408 if (newPos > this.minScrollPos || newPos < this.maxScrollPos) {
1409 if ((newPos > this.minScrollPos && this.options.bounces[0]) ||
1410 (newPos < this.maxScrollPos && this.options.bounces[1])) {
1411 newPos = this.currentPos + delta * dampingFactor;
1412 }
1413 else {
1414 newPos =
1415 newPos > this.minScrollPos ? this.minScrollPos : this.maxScrollPos;
1416 }
1417 }
1418 return newPos;
1419 };
1420 Behavior.prototype.end = function (duration) {
1421 var momentumInfo = {
1422 duration: 0
1423 };
1424 var absDist = Math.abs(this.currentPos - this.startPos);
1425 // start momentum animation if needed
1426 if (this.options.momentum &&
1427 duration < this.options.momentumLimitTime &&
1428 absDist > this.options.momentumLimitDistance) {
1429 var wrapperSize = (this.direction === -1 /* Negative */ && this.options.bounces[0]) ||
1430 (this.direction === 1 /* Positive */ && this.options.bounces[1])
1431 ? this.wrapperSize
1432 : 0;
1433 momentumInfo = this.hasScroll
1434 ? this.momentum(this.currentPos, this.startPos, duration, this.maxScrollPos, this.minScrollPos, wrapperSize, this.options)
1435 : { destination: this.currentPos, duration: 0 };
1436 }
1437 else {
1438 this.hooks.trigger(this.hooks.eventTypes.end, momentumInfo);
1439 }
1440 return momentumInfo;
1441 };
1442 Behavior.prototype.momentum = function (current, start, time, lowerMargin, upperMargin, wrapperSize, options) {
1443 if (options === void 0) { options = this.options; }
1444 var distance = current - start;
1445 var speed = Math.abs(distance) / time;
1446 var deceleration = options.deceleration, swipeBounceTime = options.swipeBounceTime, swipeTime = options.swipeTime;
1447 var duration = Math.min(swipeTime, (speed * 2) / deceleration);
1448 var momentumData = {
1449 destination: current + ((speed * speed) / deceleration) * (distance < 0 ? -1 : 1),
1450 duration: duration,
1451 rate: 15
1452 };
1453 this.hooks.trigger(this.hooks.eventTypes.momentum, momentumData, distance);
1454 if (momentumData.destination < lowerMargin) {
1455 momentumData.destination = wrapperSize
1456 ? Math.max(lowerMargin - wrapperSize / 4, lowerMargin - (wrapperSize / momentumData.rate) * speed)
1457 : lowerMargin;
1458 momentumData.duration = swipeBounceTime;
1459 }
1460 else if (momentumData.destination > upperMargin) {
1461 momentumData.destination = wrapperSize
1462 ? Math.min(upperMargin + wrapperSize / 4, upperMargin + (wrapperSize / momentumData.rate) * speed)
1463 : upperMargin;
1464 momentumData.duration = swipeBounceTime;
1465 }
1466 momentumData.destination = Math.round(momentumData.destination);
1467 return momentumData;
1468 };
1469 Behavior.prototype.updateDirection = function () {
1470 var absDist = this.currentPos - this.absStartPos;
1471 this.setDirection(absDist);
1472 };
1473 Behavior.prototype.refresh = function (content) {
1474 var _a = this.options.rect, size = _a.size, position = _a.position;
1475 var isWrapperStatic = window.getComputedStyle(this.wrapper, null).position === 'static';
1476 // Force reflow
1477 var wrapperRect = getRect(this.wrapper);
1478 // use client is more fair than offset
1479 this.wrapperSize = this.wrapper[size === 'width' ? 'clientWidth' : 'clientHeight'];
1480 this.setContent(content);
1481 var contentRect = getRect(this.content);
1482 this.contentSize = contentRect[size];
1483 this.relativeOffset = contentRect[position];
1484 /* istanbul ignore if */
1485 if (isWrapperStatic) {
1486 this.relativeOffset -= wrapperRect[position];
1487 }
1488 this.computeBoundary();
1489 this.setDirection(0 /* Default */);
1490 };
1491 Behavior.prototype.setContent = function (content) {
1492 if (content !== this.content) {
1493 this.content = content;
1494 this.resetState();
1495 }
1496 };
1497 Behavior.prototype.resetState = function () {
1498 this.currentPos = 0;
1499 this.startPos = 0;
1500 this.dist = 0;
1501 this.setDirection(0 /* Default */);
1502 this.setMovingDirection(0 /* Default */);
1503 this.resetStartPos();
1504 };
1505 Behavior.prototype.computeBoundary = function () {
1506 this.hooks.trigger(this.hooks.eventTypes.beforeComputeBoundary);
1507 var boundary = {
1508 minScrollPos: 0,
1509 maxScrollPos: this.wrapperSize - this.contentSize
1510 };
1511 if (boundary.maxScrollPos < 0) {
1512 boundary.maxScrollPos -= this.relativeOffset;
1513 if (this.options.specifiedIndexAsContent === 0) {
1514 boundary.minScrollPos = -this.relativeOffset;
1515 }
1516 }
1517 this.hooks.trigger(this.hooks.eventTypes.computeBoundary, boundary);
1518 this.minScrollPos = boundary.minScrollPos;
1519 this.maxScrollPos = boundary.maxScrollPos;
1520 this.hasScroll =
1521 this.options.scrollable && this.maxScrollPos < this.minScrollPos;
1522 if (!this.hasScroll && this.minScrollPos < this.maxScrollPos) {
1523 this.maxScrollPos = this.minScrollPos;
1524 this.contentSize = this.wrapperSize;
1525 }
1526 };
1527 Behavior.prototype.updatePosition = function (pos) {
1528 this.currentPos = pos;
1529 };
1530 Behavior.prototype.getCurrentPos = function () {
1531 return this.currentPos;
1532 };
1533 Behavior.prototype.checkInBoundary = function () {
1534 var position = this.adjustPosition(this.currentPos);
1535 var inBoundary = position === this.getCurrentPos();
1536 return {
1537 position: position,
1538 inBoundary: inBoundary
1539 };
1540 };
1541 // adjust position when out of boundary
1542 Behavior.prototype.adjustPosition = function (pos) {
1543 if (!this.hasScroll &&
1544 !this.hooks.trigger(this.hooks.eventTypes.ignoreHasScroll)) {
1545 pos = this.minScrollPos;
1546 }
1547 else if (pos > this.minScrollPos) {
1548 pos = this.minScrollPos;
1549 }
1550 else if (pos < this.maxScrollPos) {
1551 pos = this.maxScrollPos;
1552 }
1553 return pos;
1554 };
1555 Behavior.prototype.updateStartPos = function () {
1556 this.startPos = this.currentPos;
1557 };
1558 Behavior.prototype.updateAbsStartPos = function () {
1559 this.absStartPos = this.currentPos;
1560 };
1561 Behavior.prototype.resetStartPos = function () {
1562 this.updateStartPos();
1563 this.updateAbsStartPos();
1564 };
1565 Behavior.prototype.getAbsDist = function (delta) {
1566 this.dist += delta;
1567 return Math.abs(this.dist);
1568 };
1569 Behavior.prototype.destroy = function () {
1570 this.hooks.destroy();
1571 };
1572 return Behavior;
1573}());
1574
1575var _a, _b, _c, _d;
1576var PassthroughHandlers = (_a = {},
1577 _a["yes" /* Yes */] = function (e) {
1578 return true;
1579 },
1580 _a["no" /* No */] = function (e) {
1581 maybePrevent(e);
1582 return false;
1583 },
1584 _a);
1585var DirectionMap = (_b = {},
1586 _b["horizontal" /* Horizontal */] = (_c = {},
1587 _c["yes" /* Yes */] = "horizontal" /* Horizontal */,
1588 _c["no" /* No */] = "vertical" /* Vertical */,
1589 _c),
1590 _b["vertical" /* Vertical */] = (_d = {},
1591 _d["yes" /* Yes */] = "vertical" /* Vertical */,
1592 _d["no" /* No */] = "horizontal" /* Horizontal */,
1593 _d),
1594 _b);
1595var DirectionLockAction = /** @class */ (function () {
1596 function DirectionLockAction(directionLockThreshold, freeScroll, eventPassthrough) {
1597 this.directionLockThreshold = directionLockThreshold;
1598 this.freeScroll = freeScroll;
1599 this.eventPassthrough = eventPassthrough;
1600 this.reset();
1601 }
1602 DirectionLockAction.prototype.reset = function () {
1603 this.directionLocked = "" /* Default */;
1604 };
1605 DirectionLockAction.prototype.checkMovingDirection = function (absDistX, absDistY, e) {
1606 this.computeDirectionLock(absDistX, absDistY);
1607 return this.handleEventPassthrough(e);
1608 };
1609 DirectionLockAction.prototype.adjustDelta = function (deltaX, deltaY) {
1610 if (this.directionLocked === "horizontal" /* Horizontal */) {
1611 deltaY = 0;
1612 }
1613 else if (this.directionLocked === "vertical" /* Vertical */) {
1614 deltaX = 0;
1615 }
1616 return {
1617 deltaX: deltaX,
1618 deltaY: deltaY,
1619 };
1620 };
1621 DirectionLockAction.prototype.computeDirectionLock = function (absDistX, absDistY) {
1622 // If you are scrolling in one direction, lock it
1623 if (this.directionLocked === "" /* Default */ && !this.freeScroll) {
1624 if (absDistX > absDistY + this.directionLockThreshold) {
1625 this.directionLocked = "horizontal" /* Horizontal */; // lock horizontally
1626 }
1627 else if (absDistY >= absDistX + this.directionLockThreshold) {
1628 this.directionLocked = "vertical" /* Vertical */; // lock vertically
1629 }
1630 else {
1631 this.directionLocked = "none" /* None */; // no lock
1632 }
1633 }
1634 };
1635 DirectionLockAction.prototype.handleEventPassthrough = function (e) {
1636 var handleMap = DirectionMap[this.directionLocked];
1637 if (handleMap) {
1638 if (this.eventPassthrough === handleMap["yes" /* Yes */]) {
1639 return PassthroughHandlers["yes" /* Yes */](e);
1640 }
1641 else if (this.eventPassthrough === handleMap["no" /* No */]) {
1642 return PassthroughHandlers["no" /* No */](e);
1643 }
1644 }
1645 return false;
1646 };
1647 return DirectionLockAction;
1648}());
1649
1650var applyQuadrantTransformation = function (deltaX, deltaY, quadrant) {
1651 if (quadrant === 2 /* Second */) {
1652 return [deltaY, -deltaX];
1653 }
1654 else if (quadrant === 3 /* Third */) {
1655 return [-deltaX, -deltaY];
1656 }
1657 else if (quadrant === 4 /* Forth */) {
1658 return [-deltaY, deltaX];
1659 }
1660 else {
1661 return [deltaX, deltaY];
1662 }
1663};
1664var ScrollerActions = /** @class */ (function () {
1665 function ScrollerActions(scrollBehaviorX, scrollBehaviorY, actionsHandler, animater, options) {
1666 this.hooks = new EventEmitter([
1667 'start',
1668 'beforeMove',
1669 'scrollStart',
1670 'scroll',
1671 'beforeEnd',
1672 'end',
1673 'scrollEnd',
1674 'contentNotMoved',
1675 'detectMovingDirection',
1676 'coordinateTransformation',
1677 ]);
1678 this.scrollBehaviorX = scrollBehaviorX;
1679 this.scrollBehaviorY = scrollBehaviorY;
1680 this.actionsHandler = actionsHandler;
1681 this.animater = animater;
1682 this.options = options;
1683 this.directionLockAction = new DirectionLockAction(options.directionLockThreshold, options.freeScroll, options.eventPassthrough);
1684 this.enabled = true;
1685 this.bindActionsHandler();
1686 }
1687 ScrollerActions.prototype.bindActionsHandler = function () {
1688 var _this = this;
1689 // [mouse|touch]start event
1690 this.actionsHandler.hooks.on(this.actionsHandler.hooks.eventTypes.start, function (e) {
1691 if (!_this.enabled)
1692 return true;
1693 return _this.handleStart(e);
1694 });
1695 // [mouse|touch]move event
1696 this.actionsHandler.hooks.on(this.actionsHandler.hooks.eventTypes.move, function (_a) {
1697 var deltaX = _a.deltaX, deltaY = _a.deltaY, e = _a.e;
1698 if (!_this.enabled)
1699 return true;
1700 var _b = applyQuadrantTransformation(deltaX, deltaY, _this.options.quadrant), transformateDeltaX = _b[0], transformateDeltaY = _b[1];
1701 var transformateDeltaData = {
1702 deltaX: transformateDeltaX,
1703 deltaY: transformateDeltaY,
1704 };
1705 _this.hooks.trigger(_this.hooks.eventTypes.coordinateTransformation, transformateDeltaData);
1706 return _this.handleMove(transformateDeltaData.deltaX, transformateDeltaData.deltaY, e);
1707 });
1708 // [mouse|touch]end event
1709 this.actionsHandler.hooks.on(this.actionsHandler.hooks.eventTypes.end, function (e) {
1710 if (!_this.enabled)
1711 return true;
1712 return _this.handleEnd(e);
1713 });
1714 // click
1715 this.actionsHandler.hooks.on(this.actionsHandler.hooks.eventTypes.click, function (e) {
1716 // handle native click event
1717 if (_this.enabled && !e._constructed) {
1718 _this.handleClick(e);
1719 }
1720 });
1721 };
1722 ScrollerActions.prototype.handleStart = function (e) {
1723 var timestamp = getNow();
1724 this.fingerMoved = false;
1725 this.contentMoved = false;
1726 this.startTime = timestamp;
1727 this.directionLockAction.reset();
1728 this.scrollBehaviorX.start();
1729 this.scrollBehaviorY.start();
1730 // force stopping last transition or animation
1731 this.animater.doStop();
1732 this.scrollBehaviorX.resetStartPos();
1733 this.scrollBehaviorY.resetStartPos();
1734 this.hooks.trigger(this.hooks.eventTypes.start, e);
1735 };
1736 ScrollerActions.prototype.handleMove = function (deltaX, deltaY, e) {
1737 if (this.hooks.trigger(this.hooks.eventTypes.beforeMove, e)) {
1738 return;
1739 }
1740 var absDistX = this.scrollBehaviorX.getAbsDist(deltaX);
1741 var absDistY = this.scrollBehaviorY.getAbsDist(deltaY);
1742 var timestamp = getNow();
1743 // We need to move at least momentumLimitDistance pixels
1744 // for the scrolling to initiate
1745 if (this.checkMomentum(absDistX, absDistY, timestamp)) {
1746 return true;
1747 }
1748 if (this.directionLockAction.checkMovingDirection(absDistX, absDistY, e)) {
1749 this.actionsHandler.setInitiated();
1750 return true;
1751 }
1752 var delta = this.directionLockAction.adjustDelta(deltaX, deltaY);
1753 var prevX = this.scrollBehaviorX.getCurrentPos();
1754 var newX = this.scrollBehaviorX.move(delta.deltaX);
1755 var prevY = this.scrollBehaviorY.getCurrentPos();
1756 var newY = this.scrollBehaviorY.move(delta.deltaY);
1757 if (this.hooks.trigger(this.hooks.eventTypes.detectMovingDirection)) {
1758 return;
1759 }
1760 if (!this.fingerMoved) {
1761 this.fingerMoved = true;
1762 }
1763 var positionChanged = newX !== prevX || newY !== prevY;
1764 if (!this.contentMoved && !positionChanged) {
1765 this.hooks.trigger(this.hooks.eventTypes.contentNotMoved);
1766 }
1767 if (!this.contentMoved && positionChanged) {
1768 this.contentMoved = true;
1769 this.hooks.trigger(this.hooks.eventTypes.scrollStart);
1770 }
1771 if (this.contentMoved && positionChanged) {
1772 this.animater.translate({
1773 x: newX,
1774 y: newY,
1775 });
1776 this.dispatchScroll(timestamp);
1777 }
1778 };
1779 ScrollerActions.prototype.dispatchScroll = function (timestamp) {
1780 // dispatch scroll in interval time
1781 if (timestamp - this.startTime > this.options.momentumLimitTime) {
1782 // refresh time and starting position to initiate a momentum
1783 this.startTime = timestamp;
1784 this.scrollBehaviorX.updateStartPos();
1785 this.scrollBehaviorY.updateStartPos();
1786 if (this.options.probeType === 1 /* Throttle */) {
1787 this.hooks.trigger(this.hooks.eventTypes.scroll, this.getCurrentPos());
1788 }
1789 }
1790 // dispatch scroll all the time
1791 if (this.options.probeType > 1 /* Throttle */) {
1792 this.hooks.trigger(this.hooks.eventTypes.scroll, this.getCurrentPos());
1793 }
1794 };
1795 ScrollerActions.prototype.checkMomentum = function (absDistX, absDistY, timestamp) {
1796 return (timestamp - this.endTime > this.options.momentumLimitTime &&
1797 absDistY < this.options.momentumLimitDistance &&
1798 absDistX < this.options.momentumLimitDistance);
1799 };
1800 ScrollerActions.prototype.handleEnd = function (e) {
1801 if (this.hooks.trigger(this.hooks.eventTypes.beforeEnd, e)) {
1802 return;
1803 }
1804 var currentPos = this.getCurrentPos();
1805 this.scrollBehaviorX.updateDirection();
1806 this.scrollBehaviorY.updateDirection();
1807 if (this.hooks.trigger(this.hooks.eventTypes.end, e, currentPos)) {
1808 return true;
1809 }
1810 currentPos = this.ensureIntegerPos(currentPos);
1811 this.animater.translate(currentPos);
1812 this.endTime = getNow();
1813 var duration = this.endTime - this.startTime;
1814 this.hooks.trigger(this.hooks.eventTypes.scrollEnd, currentPos, duration);
1815 };
1816 ScrollerActions.prototype.ensureIntegerPos = function (currentPos) {
1817 this.ensuringInteger = true;
1818 var x = currentPos.x, y = currentPos.y;
1819 var _a = this.scrollBehaviorX, minScrollPosX = _a.minScrollPos, maxScrollPosX = _a.maxScrollPos;
1820 var _b = this.scrollBehaviorY, minScrollPosY = _b.minScrollPos, maxScrollPosY = _b.maxScrollPos;
1821 x = x > 0 ? Math.ceil(x) : Math.floor(x);
1822 y = y > 0 ? Math.ceil(y) : Math.floor(y);
1823 x = between(x, maxScrollPosX, minScrollPosX);
1824 y = between(y, maxScrollPosY, minScrollPosY);
1825 return { x: x, y: y };
1826 };
1827 ScrollerActions.prototype.handleClick = function (e) {
1828 if (!preventDefaultExceptionFn(e.target, this.options.preventDefaultException)) {
1829 maybePrevent(e);
1830 e.stopPropagation();
1831 }
1832 };
1833 ScrollerActions.prototype.getCurrentPos = function () {
1834 return {
1835 x: this.scrollBehaviorX.getCurrentPos(),
1836 y: this.scrollBehaviorY.getCurrentPos(),
1837 };
1838 };
1839 ScrollerActions.prototype.refresh = function () {
1840 this.endTime = 0;
1841 };
1842 ScrollerActions.prototype.destroy = function () {
1843 this.hooks.destroy();
1844 };
1845 return ScrollerActions;
1846}());
1847
1848function createActionsHandlerOptions(bsOptions) {
1849 var options = [
1850 'click',
1851 'bindToWrapper',
1852 'disableMouse',
1853 'disableTouch',
1854 'preventDefault',
1855 'stopPropagation',
1856 'tagException',
1857 'preventDefaultException',
1858 'autoEndDistance',
1859 ].reduce(function (prev, cur) {
1860 prev[cur] = bsOptions[cur];
1861 return prev;
1862 }, {});
1863 return options;
1864}
1865function createBehaviorOptions(bsOptions, extraProp, bounces, rect) {
1866 var options = [
1867 'momentum',
1868 'momentumLimitTime',
1869 'momentumLimitDistance',
1870 'deceleration',
1871 'swipeBounceTime',
1872 'swipeTime',
1873 'outOfBoundaryDampingFactor',
1874 'specifiedIndexAsContent',
1875 ].reduce(function (prev, cur) {
1876 prev[cur] = bsOptions[cur];
1877 return prev;
1878 }, {});
1879 // add extra property
1880 options.scrollable = !!bsOptions[extraProp];
1881 options.bounces = bounces;
1882 options.rect = rect;
1883 return options;
1884}
1885
1886function bubbling(source, target, events) {
1887 events.forEach(function (event) {
1888 var sourceEvent;
1889 var targetEvent;
1890 if (typeof event === 'string') {
1891 sourceEvent = targetEvent = event;
1892 }
1893 else {
1894 sourceEvent = event.source;
1895 targetEvent = event.target;
1896 }
1897 source.on(sourceEvent, function () {
1898 var args = [];
1899 for (var _i = 0; _i < arguments.length; _i++) {
1900 args[_i] = arguments[_i];
1901 }
1902 return target.trigger.apply(target, __spreadArrays([targetEvent], args));
1903 });
1904 });
1905}
1906
1907function isSamePoint(startPoint, endPoint) {
1908 // keys of startPoint and endPoint should be equal
1909 var keys = Object.keys(startPoint);
1910 for (var _i = 0, keys_1 = keys; _i < keys_1.length; _i++) {
1911 var key = keys_1[_i];
1912 if (startPoint[key] !== endPoint[key])
1913 return false;
1914 }
1915 return true;
1916}
1917
1918var MIN_SCROLL_DISTANCE = 1;
1919var Scroller = /** @class */ (function () {
1920 function Scroller(wrapper, content, options) {
1921 this.wrapper = wrapper;
1922 this.content = content;
1923 this.resizeTimeout = 0;
1924 this.hooks = new EventEmitter([
1925 'beforeStart',
1926 'beforeMove',
1927 'beforeScrollStart',
1928 'scrollStart',
1929 'scroll',
1930 'beforeEnd',
1931 'scrollEnd',
1932 'resize',
1933 'touchEnd',
1934 'end',
1935 'flick',
1936 'scrollCancel',
1937 'momentum',
1938 'scrollTo',
1939 'minDistanceScroll',
1940 'scrollToElement',
1941 'beforeRefresh',
1942 ]);
1943 this.options = options;
1944 var _a = this.options.bounce, left = _a.left, right = _a.right, top = _a.top, bottom = _a.bottom;
1945 // direction X
1946 this.scrollBehaviorX = new Behavior(wrapper, content, createBehaviorOptions(options, 'scrollX', [left, right], {
1947 size: 'width',
1948 position: 'left',
1949 }));
1950 // direction Y
1951 this.scrollBehaviorY = new Behavior(wrapper, content, createBehaviorOptions(options, 'scrollY', [top, bottom], {
1952 size: 'height',
1953 position: 'top',
1954 }));
1955 this.translater = new Translater(this.content);
1956 this.animater = createAnimater(this.content, this.translater, this.options);
1957 this.actionsHandler = new ActionsHandler(this.options.bindToTarget ? this.content : wrapper, createActionsHandlerOptions(this.options));
1958 this.actions = new ScrollerActions(this.scrollBehaviorX, this.scrollBehaviorY, this.actionsHandler, this.animater, this.options);
1959 var resizeHandler = this.resize.bind(this);
1960 this.resizeRegister = new EventRegister(window, [
1961 {
1962 name: 'orientationchange',
1963 handler: resizeHandler,
1964 },
1965 {
1966 name: 'resize',
1967 handler: resizeHandler,
1968 },
1969 ]);
1970 this.registerTransitionEnd();
1971 this.init();
1972 }
1973 Scroller.prototype.init = function () {
1974 var _this = this;
1975 this.bindTranslater();
1976 this.bindAnimater();
1977 this.bindActions();
1978 // enable pointer events when scrolling ends
1979 this.hooks.on(this.hooks.eventTypes.scrollEnd, function () {
1980 _this.togglePointerEvents(true);
1981 });
1982 };
1983 Scroller.prototype.registerTransitionEnd = function () {
1984 this.transitionEndRegister = new EventRegister(this.content, [
1985 {
1986 name: style.transitionEnd,
1987 handler: this.transitionEnd.bind(this),
1988 },
1989 ]);
1990 };
1991 Scroller.prototype.bindTranslater = function () {
1992 var _this = this;
1993 var hooks = this.translater.hooks;
1994 hooks.on(hooks.eventTypes.beforeTranslate, function (transformStyle) {
1995 if (_this.options.translateZ) {
1996 transformStyle.push(_this.options.translateZ);
1997 }
1998 });
1999 // disable pointer events when scrolling
2000 hooks.on(hooks.eventTypes.translate, function (pos) {
2001 var prevPos = _this.getCurrentPos();
2002 _this.updatePositions(pos);
2003 // scrollEnd will dispatch when scroll is force stopping in touchstart handler
2004 // so in touchend handler, don't toggle pointer-events
2005 if (_this.actions.ensuringInteger === true) {
2006 _this.actions.ensuringInteger = false;
2007 return;
2008 }
2009 // a valid translate
2010 if (pos.x !== prevPos.x || pos.y !== prevPos.y) {
2011 _this.togglePointerEvents(false);
2012 }
2013 });
2014 };
2015 Scroller.prototype.bindAnimater = function () {
2016 var _this = this;
2017 // reset position
2018 this.animater.hooks.on(this.animater.hooks.eventTypes.end, function (pos) {
2019 if (!_this.resetPosition(_this.options.bounceTime)) {
2020 _this.animater.setPending(false);
2021 _this.hooks.trigger(_this.hooks.eventTypes.scrollEnd, pos);
2022 }
2023 });
2024 bubbling(this.animater.hooks, this.hooks, [
2025 {
2026 source: this.animater.hooks.eventTypes.move,
2027 target: this.hooks.eventTypes.scroll,
2028 },
2029 {
2030 source: this.animater.hooks.eventTypes.forceStop,
2031 target: this.hooks.eventTypes.scrollEnd,
2032 },
2033 ]);
2034 };
2035 Scroller.prototype.bindActions = function () {
2036 var _this = this;
2037 var actions = this.actions;
2038 bubbling(actions.hooks, this.hooks, [
2039 {
2040 source: actions.hooks.eventTypes.start,
2041 target: this.hooks.eventTypes.beforeStart,
2042 },
2043 {
2044 source: actions.hooks.eventTypes.start,
2045 target: this.hooks.eventTypes.beforeScrollStart,
2046 },
2047 {
2048 source: actions.hooks.eventTypes.beforeMove,
2049 target: this.hooks.eventTypes.beforeMove,
2050 },
2051 {
2052 source: actions.hooks.eventTypes.scrollStart,
2053 target: this.hooks.eventTypes.scrollStart,
2054 },
2055 {
2056 source: actions.hooks.eventTypes.scroll,
2057 target: this.hooks.eventTypes.scroll,
2058 },
2059 {
2060 source: actions.hooks.eventTypes.beforeEnd,
2061 target: this.hooks.eventTypes.beforeEnd,
2062 },
2063 ]);
2064 actions.hooks.on(actions.hooks.eventTypes.end, function (e, pos) {
2065 _this.hooks.trigger(_this.hooks.eventTypes.touchEnd, pos);
2066 if (_this.hooks.trigger(_this.hooks.eventTypes.end, pos)) {
2067 return true;
2068 }
2069 // check if it is a click operation
2070 if (!actions.fingerMoved) {
2071 _this.hooks.trigger(_this.hooks.eventTypes.scrollCancel);
2072 if (_this.checkClick(e)) {
2073 return true;
2074 }
2075 }
2076 // reset if we are outside of the boundaries
2077 if (_this.resetPosition(_this.options.bounceTime, ease.bounce)) {
2078 _this.animater.setForceStopped(false);
2079 return true;
2080 }
2081 });
2082 actions.hooks.on(actions.hooks.eventTypes.scrollEnd, function (pos, duration) {
2083 var deltaX = Math.abs(pos.x - _this.scrollBehaviorX.startPos);
2084 var deltaY = Math.abs(pos.y - _this.scrollBehaviorY.startPos);
2085 if (_this.checkFlick(duration, deltaX, deltaY)) {
2086 _this.animater.setForceStopped(false);
2087 _this.hooks.trigger(_this.hooks.eventTypes.flick);
2088 return;
2089 }
2090 if (_this.momentum(pos, duration)) {
2091 _this.animater.setForceStopped(false);
2092 return;
2093 }
2094 if (actions.contentMoved) {
2095 _this.hooks.trigger(_this.hooks.eventTypes.scrollEnd, pos);
2096 }
2097 if (_this.animater.forceStopped) {
2098 _this.animater.setForceStopped(false);
2099 }
2100 });
2101 };
2102 Scroller.prototype.checkFlick = function (duration, deltaX, deltaY) {
2103 var flickMinMovingDistance = 1; // distinguish flick from click
2104 if (this.hooks.events.flick.length > 1 &&
2105 duration < this.options.flickLimitTime &&
2106 deltaX < this.options.flickLimitDistance &&
2107 deltaY < this.options.flickLimitDistance &&
2108 (deltaY > flickMinMovingDistance || deltaX > flickMinMovingDistance)) {
2109 return true;
2110 }
2111 };
2112 Scroller.prototype.momentum = function (pos, duration) {
2113 var meta = {
2114 time: 0,
2115 easing: ease.swiper,
2116 newX: pos.x,
2117 newY: pos.y,
2118 };
2119 // start momentum animation if needed
2120 var momentumX = this.scrollBehaviorX.end(duration);
2121 var momentumY = this.scrollBehaviorY.end(duration);
2122 meta.newX = isUndef(momentumX.destination)
2123 ? meta.newX
2124 : momentumX.destination;
2125 meta.newY = isUndef(momentumY.destination)
2126 ? meta.newY
2127 : momentumY.destination;
2128 meta.time = Math.max(momentumX.duration, momentumY.duration);
2129 this.hooks.trigger(this.hooks.eventTypes.momentum, meta, this);
2130 // when x or y changed, do momentum animation now!
2131 if (meta.newX !== pos.x || meta.newY !== pos.y) {
2132 // change easing function when scroller goes out of the boundaries
2133 if (meta.newX > this.scrollBehaviorX.minScrollPos ||
2134 meta.newX < this.scrollBehaviorX.maxScrollPos ||
2135 meta.newY > this.scrollBehaviorY.minScrollPos ||
2136 meta.newY < this.scrollBehaviorY.maxScrollPos) {
2137 meta.easing = ease.swipeBounce;
2138 }
2139 this.scrollTo(meta.newX, meta.newY, meta.time, meta.easing);
2140 return true;
2141 }
2142 };
2143 Scroller.prototype.checkClick = function (e) {
2144 var cancelable = {
2145 preventClick: this.animater.forceStopped,
2146 };
2147 // we scrolled less than momentumLimitDistance pixels
2148 if (this.hooks.trigger(this.hooks.eventTypes.checkClick)) {
2149 this.animater.setForceStopped(false);
2150 return true;
2151 }
2152 if (!cancelable.preventClick) {
2153 var _dblclick = this.options.dblclick;
2154 var dblclickTrigged = false;
2155 if (_dblclick && this.lastClickTime) {
2156 var _a = _dblclick.delay, delay = _a === void 0 ? 300 : _a;
2157 if (getNow() - this.lastClickTime < delay) {
2158 dblclickTrigged = true;
2159 dblclick(e);
2160 }
2161 }
2162 if (this.options.tap) {
2163 tap(e, this.options.tap);
2164 }
2165 if (this.options.click &&
2166 !preventDefaultExceptionFn(e.target, this.options.preventDefaultException)) {
2167 click(e);
2168 }
2169 this.lastClickTime = dblclickTrigged ? null : getNow();
2170 return true;
2171 }
2172 return false;
2173 };
2174 Scroller.prototype.resize = function () {
2175 var _this = this;
2176 if (!this.actions.enabled) {
2177 return;
2178 }
2179 // fix a scroll problem under Android condition
2180 /* istanbul ignore if */
2181 if (isAndroid) {
2182 this.wrapper.scrollTop = 0;
2183 }
2184 clearTimeout(this.resizeTimeout);
2185 this.resizeTimeout = window.setTimeout(function () {
2186 _this.hooks.trigger(_this.hooks.eventTypes.resize);
2187 }, this.options.resizePolling);
2188 };
2189 /* istanbul ignore next */
2190 Scroller.prototype.transitionEnd = function (e) {
2191 if (e.target !== this.content || !this.animater.pending) {
2192 return;
2193 }
2194 var animater = this.animater;
2195 animater.transitionTime();
2196 if (!this.resetPosition(this.options.bounceTime, ease.bounce)) {
2197 this.animater.setPending(false);
2198 if (this.options.probeType !== 3 /* Realtime */) {
2199 this.hooks.trigger(this.hooks.eventTypes.scrollEnd, this.getCurrentPos());
2200 }
2201 }
2202 };
2203 Scroller.prototype.togglePointerEvents = function (enabled) {
2204 if (enabled === void 0) { enabled = true; }
2205 var el = this.content.children.length
2206 ? this.content.children
2207 : [this.content];
2208 var pointerEvents = enabled ? 'auto' : 'none';
2209 for (var i = 0; i < el.length; i++) {
2210 var node = el[i];
2211 // ignore BetterScroll instance's wrapper DOM
2212 /* istanbul ignore if */
2213 if (node.isBScrollContainer) {
2214 continue;
2215 }
2216 node.style.pointerEvents = pointerEvents;
2217 }
2218 };
2219 Scroller.prototype.refresh = function (content) {
2220 var contentChanged = this.setContent(content);
2221 this.hooks.trigger(this.hooks.eventTypes.beforeRefresh);
2222 this.scrollBehaviorX.refresh(content);
2223 this.scrollBehaviorY.refresh(content);
2224 if (contentChanged) {
2225 this.translater.setContent(content);
2226 this.animater.setContent(content);
2227 this.transitionEndRegister.destroy();
2228 this.registerTransitionEnd();
2229 if (this.options.bindToTarget) {
2230 this.actionsHandler.setContent(content);
2231 }
2232 }
2233 this.actions.refresh();
2234 this.wrapperOffset = offset(this.wrapper);
2235 };
2236 Scroller.prototype.setContent = function (content) {
2237 var contentChanged = content !== this.content;
2238 if (contentChanged) {
2239 this.content = content;
2240 }
2241 return contentChanged;
2242 };
2243 Scroller.prototype.scrollBy = function (deltaX, deltaY, time, easing) {
2244 if (time === void 0) { time = 0; }
2245 var _a = this.getCurrentPos(), x = _a.x, y = _a.y;
2246 easing = !easing ? ease.bounce : easing;
2247 deltaX += x;
2248 deltaY += y;
2249 this.scrollTo(deltaX, deltaY, time, easing);
2250 };
2251 Scroller.prototype.scrollTo = function (x, y, time, easing, extraTransform) {
2252 if (time === void 0) { time = 0; }
2253 if (easing === void 0) { easing = ease.bounce; }
2254 if (extraTransform === void 0) { extraTransform = {
2255 start: {},
2256 end: {},
2257 }; }
2258 var easingFn = this.options.useTransition ? easing.style : easing.fn;
2259 var currentPos = this.getCurrentPos();
2260 var startPoint = __assign({ x: currentPos.x, y: currentPos.y }, extraTransform.start);
2261 var endPoint = __assign({ x: x,
2262 y: y }, extraTransform.end);
2263 this.hooks.trigger(this.hooks.eventTypes.scrollTo, endPoint);
2264 // it is an useless move
2265 if (isSamePoint(startPoint, endPoint))
2266 return;
2267 var deltaX = Math.abs(endPoint.x - startPoint.x);
2268 var deltaY = Math.abs(endPoint.y - startPoint.y);
2269 // considering of browser compatibility for decimal transform value
2270 // force translating immediately
2271 if (deltaX < MIN_SCROLL_DISTANCE && deltaY < MIN_SCROLL_DISTANCE) {
2272 time = 0;
2273 this.hooks.trigger(this.hooks.eventTypes.minDistanceScroll);
2274 }
2275 this.animater.move(startPoint, endPoint, time, easingFn);
2276 };
2277 Scroller.prototype.scrollToElement = function (el, time, offsetX, offsetY, easing) {
2278 var targetEle = getElement(el);
2279 var pos = offset(targetEle);
2280 var getOffset = function (offset, size, wrapperSize) {
2281 if (typeof offset === 'number') {
2282 return offset;
2283 }
2284 // if offsetX/Y are true we center the element to the screen
2285 return offset ? Math.round(size / 2 - wrapperSize / 2) : 0;
2286 };
2287 offsetX = getOffset(offsetX, targetEle.offsetWidth, this.wrapper.offsetWidth);
2288 offsetY = getOffset(offsetY, targetEle.offsetHeight, this.wrapper.offsetHeight);
2289 var getPos = function (pos, wrapperPos, offset, scrollBehavior) {
2290 pos -= wrapperPos;
2291 pos = scrollBehavior.adjustPosition(pos - offset);
2292 return pos;
2293 };
2294 pos.left = getPos(pos.left, this.wrapperOffset.left, offsetX, this.scrollBehaviorX);
2295 pos.top = getPos(pos.top, this.wrapperOffset.top, offsetY, this.scrollBehaviorY);
2296 if (this.hooks.trigger(this.hooks.eventTypes.scrollToElement, targetEle, pos)) {
2297 return;
2298 }
2299 this.scrollTo(pos.left, pos.top, time, easing);
2300 };
2301 Scroller.prototype.resetPosition = function (time, easing) {
2302 if (time === void 0) { time = 0; }
2303 if (easing === void 0) { easing = ease.bounce; }
2304 var _a = this.scrollBehaviorX.checkInBoundary(), x = _a.position, xInBoundary = _a.inBoundary;
2305 var _b = this.scrollBehaviorY.checkInBoundary(), y = _b.position, yInBoundary = _b.inBoundary;
2306 if (xInBoundary && yInBoundary) {
2307 return false;
2308 }
2309 /* istanbul ignore if */
2310 if (isIOSBadVersion) {
2311 // fix ios 13.4 bouncing
2312 // see it in issues 982
2313 this.reflow();
2314 }
2315 // out of boundary
2316 this.scrollTo(x, y, time, easing);
2317 return true;
2318 };
2319 /* istanbul ignore next */
2320 Scroller.prototype.reflow = function () {
2321 this._reflow = this.content.offsetHeight;
2322 };
2323 Scroller.prototype.updatePositions = function (pos) {
2324 this.scrollBehaviorX.updatePosition(pos.x);
2325 this.scrollBehaviorY.updatePosition(pos.y);
2326 };
2327 Scroller.prototype.getCurrentPos = function () {
2328 return this.actions.getCurrentPos();
2329 };
2330 Scroller.prototype.enable = function () {
2331 this.actions.enabled = true;
2332 };
2333 Scroller.prototype.disable = function () {
2334 cancelAnimationFrame(this.animater.timer);
2335 this.actions.enabled = false;
2336 };
2337 Scroller.prototype.destroy = function () {
2338 var _this = this;
2339 var keys = [
2340 'resizeRegister',
2341 'transitionEndRegister',
2342 'actionsHandler',
2343 'actions',
2344 'hooks',
2345 'animater',
2346 'translater',
2347 'scrollBehaviorX',
2348 'scrollBehaviorY',
2349 ];
2350 keys.forEach(function (key) { return _this[key].destroy(); });
2351 };
2352 return Scroller;
2353}());
2354
2355var BScrollConstructor = /** @class */ (function (_super) {
2356 __extends(BScrollConstructor, _super);
2357 function BScrollConstructor(el, options) {
2358 var _this = _super.call(this, [
2359 'refresh',
2360 'contentChanged',
2361 'enable',
2362 'disable',
2363 'beforeScrollStart',
2364 'scrollStart',
2365 'scroll',
2366 'scrollEnd',
2367 'scrollCancel',
2368 'touchEnd',
2369 'flick',
2370 'destroy'
2371 ]) || this;
2372 var wrapper = getElement(el);
2373 if (!wrapper) {
2374 warn('Can not resolve the wrapper DOM.');
2375 return _this;
2376 }
2377 _this.plugins = {};
2378 _this.options = new OptionsConstructor().merge(options).process();
2379 if (!_this.setContent(wrapper).valid) {
2380 return _this;
2381 }
2382 _this.hooks = new EventEmitter([
2383 'refresh',
2384 'enable',
2385 'disable',
2386 'destroy',
2387 'beforeInitialScrollTo',
2388 'contentChanged'
2389 ]);
2390 _this.init(wrapper);
2391 return _this;
2392 }
2393 BScrollConstructor.use = function (ctor) {
2394 var name = ctor.pluginName;
2395 var installed = BScrollConstructor.plugins.some(function (plugin) { return ctor === plugin.ctor; });
2396 if (installed)
2397 return BScrollConstructor;
2398 if (isUndef(name)) {
2399 warn("Plugin Class must specify plugin's name in static property by 'pluginName' field.");
2400 return BScrollConstructor;
2401 }
2402 BScrollConstructor.pluginsMap[name] = true;
2403 BScrollConstructor.plugins.push({
2404 name: name,
2405 applyOrder: ctor.applyOrder,
2406 ctor: ctor
2407 });
2408 return BScrollConstructor;
2409 };
2410 BScrollConstructor.prototype.setContent = function (wrapper) {
2411 var contentChanged = false;
2412 var valid = true;
2413 var content = wrapper.children[this.options.specifiedIndexAsContent];
2414 if (!content) {
2415 warn('The wrapper need at least one child element to be content element to scroll.');
2416 valid = false;
2417 }
2418 else {
2419 contentChanged = this.content !== content;
2420 if (contentChanged) {
2421 this.content = content;
2422 }
2423 }
2424 return {
2425 valid: valid,
2426 contentChanged: contentChanged
2427 };
2428 };
2429 BScrollConstructor.prototype.init = function (wrapper) {
2430 var _this = this;
2431 this.wrapper = wrapper;
2432 // mark wrapper to recognize bs instance by DOM attribute
2433 wrapper.isBScrollContainer = true;
2434 this.scroller = new Scroller(wrapper, this.content, this.options);
2435 this.scroller.hooks.on(this.scroller.hooks.eventTypes.resize, function () {
2436 _this.refresh();
2437 });
2438 this.eventBubbling();
2439 this.handleAutoBlur();
2440 this.enable();
2441 this.proxy(propertiesConfig$7);
2442 this.applyPlugins();
2443 // maybe boundary has changed, should refresh
2444 this.refreshWithoutReset(this.content);
2445 var _a = this.options, startX = _a.startX, startY = _a.startY;
2446 var position = {
2447 x: startX,
2448 y: startY
2449 };
2450 // maybe plugins want to control scroll position
2451 if (this.hooks.trigger(this.hooks.eventTypes.beforeInitialScrollTo, position)) {
2452 return;
2453 }
2454 this.scroller.scrollTo(position.x, position.y);
2455 };
2456 BScrollConstructor.prototype.applyPlugins = function () {
2457 var _this = this;
2458 var options = this.options;
2459 BScrollConstructor.plugins
2460 .sort(function (a, b) {
2461 var _a;
2462 var applyOrderMap = (_a = {},
2463 _a["pre" /* Pre */] = -1,
2464 _a["post" /* Post */] = 1,
2465 _a);
2466 var aOrder = a.applyOrder ? applyOrderMap[a.applyOrder] : 0;
2467 var bOrder = b.applyOrder ? applyOrderMap[b.applyOrder] : 0;
2468 return aOrder - bOrder;
2469 })
2470 .forEach(function (item) {
2471 var ctor = item.ctor;
2472 if (options[item.name] && typeof ctor === 'function') {
2473 _this.plugins[item.name] = new ctor(_this);
2474 }
2475 });
2476 };
2477 BScrollConstructor.prototype.handleAutoBlur = function () {
2478 /* istanbul ignore if */
2479 if (this.options.autoBlur) {
2480 this.on(this.eventTypes.beforeScrollStart, function () {
2481 var activeElement = document.activeElement;
2482 if (activeElement &&
2483 (activeElement.tagName === 'INPUT' ||
2484 activeElement.tagName === 'TEXTAREA')) {
2485 activeElement.blur();
2486 }
2487 });
2488 }
2489 };
2490 BScrollConstructor.prototype.eventBubbling = function () {
2491 bubbling(this.scroller.hooks, this, [
2492 this.eventTypes.beforeScrollStart,
2493 this.eventTypes.scrollStart,
2494 this.eventTypes.scroll,
2495 this.eventTypes.scrollEnd,
2496 this.eventTypes.scrollCancel,
2497 this.eventTypes.touchEnd,
2498 this.eventTypes.flick
2499 ]);
2500 };
2501 BScrollConstructor.prototype.refreshWithoutReset = function (content) {
2502 this.scroller.refresh(content);
2503 this.hooks.trigger(this.hooks.eventTypes.refresh, content);
2504 this.trigger(this.eventTypes.refresh, content);
2505 };
2506 BScrollConstructor.prototype.proxy = function (propertiesConfig) {
2507 var _this = this;
2508 propertiesConfig.forEach(function (_a) {
2509 var key = _a.key, sourceKey = _a.sourceKey;
2510 propertiesProxy(_this, sourceKey, key);
2511 });
2512 };
2513 BScrollConstructor.prototype.refresh = function () {
2514 var _a = this.setContent(this.wrapper), contentChanged = _a.contentChanged, valid = _a.valid;
2515 if (valid) {
2516 var content = this.content;
2517 this.refreshWithoutReset(content);
2518 if (contentChanged) {
2519 this.hooks.trigger(this.hooks.eventTypes.contentChanged, content);
2520 this.trigger(this.eventTypes.contentChanged, content);
2521 }
2522 this.scroller.resetPosition();
2523 }
2524 };
2525 BScrollConstructor.prototype.enable = function () {
2526 this.scroller.enable();
2527 this.hooks.trigger(this.hooks.eventTypes.enable);
2528 this.trigger(this.eventTypes.enable);
2529 };
2530 BScrollConstructor.prototype.disable = function () {
2531 this.scroller.disable();
2532 this.hooks.trigger(this.hooks.eventTypes.disable);
2533 this.trigger(this.eventTypes.disable);
2534 };
2535 BScrollConstructor.prototype.destroy = function () {
2536 this.hooks.trigger(this.hooks.eventTypes.destroy);
2537 this.trigger(this.eventTypes.destroy);
2538 this.scroller.destroy();
2539 };
2540 BScrollConstructor.prototype.eventRegister = function (names) {
2541 this.registerType(names);
2542 };
2543 BScrollConstructor.plugins = [];
2544 BScrollConstructor.pluginsMap = {};
2545 return BScrollConstructor;
2546}(EventEmitter));
2547function createBScroll(el, options) {
2548 var bs = new BScrollConstructor(el, options);
2549 return bs;
2550}
2551createBScroll.use = BScrollConstructor.use;
2552createBScroll.plugins = BScrollConstructor.plugins;
2553createBScroll.pluginsMap = BScrollConstructor.pluginsMap;
2554var BScroll = createBScroll;
2555
2556var MouseWheel = /** @class */ (function () {
2557 function MouseWheel(scroll) {
2558 this.scroll = scroll;
2559 this.wheelEndTimer = 0;
2560 this.wheelMoveTimer = 0;
2561 this.wheelStart = false;
2562 this.init();
2563 }
2564 MouseWheel.prototype.init = function () {
2565 this.handleBScroll();
2566 this.handleOptions();
2567 this.handleHooks();
2568 this.registerEvent();
2569 };
2570 MouseWheel.prototype.handleBScroll = function () {
2571 this.scroll.registerType([
2572 'alterOptions',
2573 'mousewheelStart',
2574 'mousewheelMove',
2575 'mousewheelEnd',
2576 ]);
2577 };
2578 MouseWheel.prototype.handleOptions = function () {
2579 var userOptions = (this.scroll.options.mouseWheel === true
2580 ? {}
2581 : this.scroll.options.mouseWheel);
2582 var defaultOptions = {
2583 speed: 20,
2584 invert: false,
2585 easeTime: 300,
2586 discreteTime: 400,
2587 throttleTime: 0,
2588 dampingFactor: 0.1,
2589 };
2590 this.mouseWheelOpt = extend(defaultOptions, userOptions);
2591 };
2592 MouseWheel.prototype.handleHooks = function () {
2593 this.hooksFn = [];
2594 this.registerHooks(this.scroll.hooks, 'destroy', this.destroy);
2595 };
2596 MouseWheel.prototype.registerEvent = function () {
2597 this.eventRegister = new EventRegister(this.scroll.scroller.wrapper, [
2598 {
2599 name: 'wheel',
2600 handler: this.wheelHandler.bind(this),
2601 },
2602 {
2603 name: 'mousewheel',
2604 handler: this.wheelHandler.bind(this),
2605 },
2606 {
2607 name: 'DOMMouseScroll',
2608 handler: this.wheelHandler.bind(this),
2609 },
2610 ]);
2611 };
2612 MouseWheel.prototype.registerHooks = function (hooks, name, handler) {
2613 hooks.on(name, handler, this);
2614 this.hooksFn.push([hooks, name, handler]);
2615 };
2616 MouseWheel.prototype.wheelHandler = function (e) {
2617 if (!this.scroll.enabled) {
2618 return;
2619 }
2620 this.beforeHandler(e);
2621 // start
2622 if (!this.wheelStart) {
2623 this.wheelStartHandler(e);
2624 this.wheelStart = true;
2625 }
2626 // move
2627 var delta = this.getWheelDelta(e);
2628 this.wheelMoveHandler(delta);
2629 // end
2630 this.wheelEndDetector(delta);
2631 };
2632 MouseWheel.prototype.wheelStartHandler = function (e) {
2633 this.cleanCache();
2634 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
2635 scrollBehaviorX.setMovingDirection(0 /* Default */);
2636 scrollBehaviorY.setMovingDirection(0 /* Default */);
2637 scrollBehaviorX.setDirection(0 /* Default */);
2638 scrollBehaviorY.setDirection(0 /* Default */);
2639 this.scroll.trigger(this.scroll.eventTypes.alterOptions, this.mouseWheelOpt);
2640 this.scroll.trigger(this.scroll.eventTypes.mousewheelStart);
2641 };
2642 MouseWheel.prototype.cleanCache = function () {
2643 this.deltaCache = [];
2644 };
2645 MouseWheel.prototype.wheelMoveHandler = function (delta) {
2646 var _this = this;
2647 var _a = this.mouseWheelOpt, throttleTime = _a.throttleTime, dampingFactor = _a.dampingFactor;
2648 if (throttleTime && this.wheelMoveTimer) {
2649 this.deltaCache.push(delta);
2650 }
2651 else {
2652 var cachedDelta = this.deltaCache.reduce(function (prev, current) {
2653 return {
2654 x: prev.x + current.x,
2655 y: prev.y + current.y,
2656 };
2657 }, { x: 0, y: 0 });
2658 this.cleanCache();
2659 var _b = this.scroll.scroller, scrollBehaviorX = _b.scrollBehaviorX, scrollBehaviorY = _b.scrollBehaviorY;
2660 scrollBehaviorX.setMovingDirection(-delta.directionX);
2661 scrollBehaviorY.setMovingDirection(-delta.directionY);
2662 scrollBehaviorX.setDirection(delta.x);
2663 scrollBehaviorY.setDirection(delta.y);
2664 // when out of boundary, perform a damping scroll
2665 var newX = scrollBehaviorX.performDampingAlgorithm(Math.round(delta.x) + cachedDelta.x, dampingFactor);
2666 var newY = scrollBehaviorY.performDampingAlgorithm(Math.round(delta.y) + cachedDelta.x, dampingFactor);
2667 if (!this.scroll.trigger(this.scroll.eventTypes.mousewheelMove, {
2668 x: newX,
2669 y: newY,
2670 })) {
2671 var easeTime = this.getEaseTime();
2672 if (newX !== this.scroll.x || newY !== this.scroll.y) {
2673 this.scroll.scrollTo(newX, newY, easeTime);
2674 }
2675 }
2676 if (throttleTime) {
2677 this.wheelMoveTimer = window.setTimeout(function () {
2678 _this.wheelMoveTimer = 0;
2679 }, throttleTime);
2680 }
2681 }
2682 };
2683 MouseWheel.prototype.wheelEndDetector = function (delta) {
2684 var _this = this;
2685 window.clearTimeout(this.wheelEndTimer);
2686 this.wheelEndTimer = window.setTimeout(function () {
2687 _this.wheelStart = false;
2688 window.clearTimeout(_this.wheelMoveTimer);
2689 _this.wheelMoveTimer = 0;
2690 _this.scroll.trigger(_this.scroll.eventTypes.mousewheelEnd, delta);
2691 }, this.mouseWheelOpt.discreteTime);
2692 };
2693 MouseWheel.prototype.getWheelDelta = function (e) {
2694 var _a = this.mouseWheelOpt, speed = _a.speed, invert = _a.invert;
2695 var wheelDeltaX = 0;
2696 var wheelDeltaY = 0;
2697 var direction = invert ? -1 /* Negative */ : 1 /* Positive */;
2698 switch (true) {
2699 case 'deltaX' in e:
2700 if (e.deltaMode === 1) {
2701 wheelDeltaX = -e.deltaX * speed;
2702 wheelDeltaY = -e.deltaY * speed;
2703 }
2704 else {
2705 wheelDeltaX = -e.deltaX;
2706 wheelDeltaY = -e.deltaY;
2707 }
2708 break;
2709 case 'wheelDeltaX' in e:
2710 wheelDeltaX = (e.wheelDeltaX / 120) * speed;
2711 wheelDeltaY = (e.wheelDeltaY / 120) * speed;
2712 break;
2713 case 'wheelDelta' in e:
2714 wheelDeltaX = wheelDeltaY = (e.wheelDelta / 120) * speed;
2715 break;
2716 case 'detail' in e:
2717 wheelDeltaX = wheelDeltaY = (-e.detail / 3) * speed;
2718 break;
2719 }
2720 wheelDeltaX *= direction;
2721 wheelDeltaY *= direction;
2722 if (!this.scroll.hasVerticalScroll) {
2723 if (Math.abs(wheelDeltaY) > Math.abs(wheelDeltaX)) {
2724 wheelDeltaX = wheelDeltaY;
2725 }
2726 wheelDeltaY = 0;
2727 }
2728 if (!this.scroll.hasHorizontalScroll) {
2729 wheelDeltaX = 0;
2730 }
2731 var directionX = wheelDeltaX > 0
2732 ? -1 /* Negative */
2733 : wheelDeltaX < 0
2734 ? 1 /* Positive */
2735 : 0 /* Default */;
2736 var directionY = wheelDeltaY > 0
2737 ? -1 /* Negative */
2738 : wheelDeltaY < 0
2739 ? 1 /* Positive */
2740 : 0 /* Default */;
2741 return {
2742 x: wheelDeltaX,
2743 y: wheelDeltaY,
2744 directionX: directionX,
2745 directionY: directionY,
2746 };
2747 };
2748 MouseWheel.prototype.beforeHandler = function (e) {
2749 var _a = this.scroll.options, preventDefault = _a.preventDefault, stopPropagation = _a.stopPropagation, preventDefaultException = _a.preventDefaultException;
2750 if (preventDefault &&
2751 !preventDefaultExceptionFn(e.target, preventDefaultException)) {
2752 maybePrevent(e);
2753 }
2754 if (stopPropagation) {
2755 e.stopPropagation();
2756 }
2757 };
2758 MouseWheel.prototype.getEaseTime = function () {
2759 var SAFE_EASETIME = 100;
2760 var easeTime = this.mouseWheelOpt.easeTime;
2761 // scrollEnd event will be triggered in every calling of scrollTo when easeTime is too small
2762 // easeTime needs to be greater than 100
2763 if (easeTime < SAFE_EASETIME) {
2764 warn("easeTime should be greater than 100." +
2765 "If mouseWheel easeTime is too small," +
2766 "scrollEnd will be triggered many times.");
2767 }
2768 return Math.max(easeTime, SAFE_EASETIME);
2769 };
2770 MouseWheel.prototype.destroy = function () {
2771 this.eventRegister.destroy();
2772 window.clearTimeout(this.wheelEndTimer);
2773 window.clearTimeout(this.wheelMoveTimer);
2774 this.hooksFn.forEach(function (item) {
2775 var hooks = item[0];
2776 var hooksName = item[1];
2777 var handlerFn = item[2];
2778 hooks.off(hooksName, handlerFn);
2779 });
2780 };
2781 MouseWheel.pluginName = 'mouseWheel';
2782 MouseWheel.applyOrder = "pre" /* Pre */;
2783 return MouseWheel;
2784}());
2785
2786var ObserveDOM = /** @class */ (function () {
2787 function ObserveDOM(scroll) {
2788 this.scroll = scroll;
2789 this.stopObserver = false;
2790 this.init();
2791 }
2792 ObserveDOM.prototype.init = function () {
2793 this.handleMutationObserver();
2794 this.handleHooks();
2795 };
2796 ObserveDOM.prototype.handleMutationObserver = function () {
2797 var _this = this;
2798 if (typeof MutationObserver !== 'undefined') {
2799 var timer_1 = 0;
2800 this.observer = new MutationObserver(function (mutations) {
2801 _this.mutationObserverHandler(mutations, timer_1);
2802 });
2803 this.startObserve(this.observer);
2804 }
2805 else {
2806 this.checkDOMUpdate();
2807 }
2808 };
2809 ObserveDOM.prototype.handleHooks = function () {
2810 var _this = this;
2811 this.hooksFn = [];
2812 this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.contentChanged, function () {
2813 _this.stopObserve();
2814 // launch a new mutationObserver
2815 _this.handleMutationObserver();
2816 });
2817 this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.enable, function () {
2818 if (_this.stopObserver) {
2819 _this.handleMutationObserver();
2820 }
2821 });
2822 this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.disable, function () {
2823 _this.stopObserve();
2824 });
2825 this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.destroy, function () {
2826 _this.destroy();
2827 });
2828 };
2829 ObserveDOM.prototype.mutationObserverHandler = function (mutations, timer) {
2830 var _this = this;
2831 if (this.shouldNotRefresh()) {
2832 return;
2833 }
2834 var immediateRefresh = false;
2835 var deferredRefresh = false;
2836 for (var i = 0; i < mutations.length; i++) {
2837 var mutation = mutations[i];
2838 if (mutation.type !== 'attributes') {
2839 immediateRefresh = true;
2840 break;
2841 }
2842 else {
2843 if (mutation.target !== this.scroll.scroller.content) {
2844 deferredRefresh = true;
2845 break;
2846 }
2847 }
2848 }
2849 if (immediateRefresh) {
2850 this.scroll.refresh();
2851 }
2852 else if (deferredRefresh) {
2853 // attributes changes too often
2854 clearTimeout(timer);
2855 timer = window.setTimeout(function () {
2856 if (!_this.shouldNotRefresh()) {
2857 _this.scroll.refresh();
2858 }
2859 }, 60);
2860 }
2861 };
2862 ObserveDOM.prototype.startObserve = function (observer) {
2863 var config = {
2864 attributes: true,
2865 childList: true,
2866 subtree: true,
2867 };
2868 observer.observe(this.scroll.scroller.content, config);
2869 };
2870 ObserveDOM.prototype.shouldNotRefresh = function () {
2871 var scroller = this.scroll.scroller;
2872 var scrollBehaviorX = scroller.scrollBehaviorX, scrollBehaviorY = scroller.scrollBehaviorY;
2873 var outsideBoundaries = scrollBehaviorX.currentPos > scrollBehaviorX.minScrollPos ||
2874 scrollBehaviorX.currentPos < scrollBehaviorX.maxScrollPos ||
2875 scrollBehaviorY.currentPos > scrollBehaviorY.minScrollPos ||
2876 scrollBehaviorY.currentPos < scrollBehaviorY.maxScrollPos;
2877 return scroller.animater.pending || outsideBoundaries;
2878 };
2879 ObserveDOM.prototype.checkDOMUpdate = function () {
2880 var _this = this;
2881 var content = this.scroll.scroller.content;
2882 var contentRect = getRect(content);
2883 var oldWidth = contentRect.width;
2884 var oldHeight = contentRect.height;
2885 var check = function () {
2886 if (_this.stopObserver) {
2887 return;
2888 }
2889 contentRect = getRect(content);
2890 var newWidth = contentRect.width;
2891 var newHeight = contentRect.height;
2892 if (oldWidth !== newWidth || oldHeight !== newHeight) {
2893 _this.scroll.refresh();
2894 }
2895 oldWidth = newWidth;
2896 oldHeight = newHeight;
2897 next();
2898 };
2899 var next = function () {
2900 setTimeout(function () {
2901 check();
2902 }, 1000);
2903 };
2904 next();
2905 };
2906 ObserveDOM.prototype.registerHooks = function (hooks, name, handler) {
2907 hooks.on(name, handler, this);
2908 this.hooksFn.push([hooks, name, handler]);
2909 };
2910 ObserveDOM.prototype.stopObserve = function () {
2911 this.stopObserver = true;
2912 if (this.observer) {
2913 this.observer.disconnect();
2914 }
2915 };
2916 ObserveDOM.prototype.destroy = function () {
2917 this.stopObserve();
2918 this.hooksFn.forEach(function (item) {
2919 var hooks = item[0];
2920 var hooksName = item[1];
2921 var handlerFn = item[2];
2922 hooks.off(hooksName, handlerFn);
2923 });
2924 this.hooksFn.length = 0;
2925 };
2926 ObserveDOM.pluginName = 'observeDOM';
2927 return ObserveDOM;
2928}());
2929
2930var sourcePrefix$6 = 'plugins.pullDownRefresh';
2931var propertiesMap$6 = [
2932 {
2933 key: 'finishPullDown',
2934 name: 'finishPullDown'
2935 },
2936 {
2937 key: 'openPullDown',
2938 name: 'openPullDown'
2939 },
2940 {
2941 key: 'closePullDown',
2942 name: 'closePullDown'
2943 },
2944 {
2945 key: 'autoPullDownRefresh',
2946 name: 'autoPullDownRefresh'
2947 }
2948];
2949var propertiesConfig$6 = propertiesMap$6.map(function (item) {
2950 return {
2951 key: item.key,
2952 sourceKey: sourcePrefix$6 + "." + item.name
2953 };
2954});
2955
2956var PULLING_DOWN_EVENT = 'pullingDown';
2957var ENTER_THRESHOLD_EVENT = 'enterThreshold';
2958var LEAVE_THRESHOLD_EVENT = 'leaveThreshold';
2959var PullDown = /** @class */ (function () {
2960 function PullDown(scroll) {
2961 this.scroll = scroll;
2962 this.pulling = 0 /* DEFAULT */;
2963 this.thresholdBoundary = 0 /* DEFAULT */;
2964 this.init();
2965 }
2966 PullDown.prototype.setPulling = function (status) {
2967 this.pulling = status;
2968 };
2969 PullDown.prototype.setThresholdBoundary = function (boundary) {
2970 this.thresholdBoundary = boundary;
2971 };
2972 PullDown.prototype.init = function () {
2973 this.handleBScroll();
2974 this.handleOptions(this.scroll.options.pullDownRefresh);
2975 this.handleHooks();
2976 this.watch();
2977 };
2978 PullDown.prototype.handleBScroll = function () {
2979 this.scroll.registerType([
2980 PULLING_DOWN_EVENT,
2981 ENTER_THRESHOLD_EVENT,
2982 LEAVE_THRESHOLD_EVENT,
2983 ]);
2984 this.scroll.proxy(propertiesConfig$6);
2985 };
2986 PullDown.prototype.handleOptions = function (userOptions) {
2987 if (userOptions === void 0) { userOptions = {}; }
2988 userOptions = (userOptions === true ? {} : userOptions);
2989 var defaultOptions = {
2990 threshold: 90,
2991 stop: 40,
2992 };
2993 this.options = extend(defaultOptions, userOptions);
2994 this.scroll.options.probeType = 3 /* Realtime */;
2995 };
2996 PullDown.prototype.handleHooks = function () {
2997 var _this = this;
2998 this.hooksFn = [];
2999 var scroller = this.scroll.scroller;
3000 var scrollBehaviorY = scroller.scrollBehaviorY;
3001 this.currentMinScrollY = this.cachedOriginanMinScrollY =
3002 scrollBehaviorY.minScrollPos;
3003 this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.contentChanged, function () {
3004 _this.finishPullDown();
3005 });
3006 this.registerHooks(scrollBehaviorY.hooks, scrollBehaviorY.hooks.eventTypes.computeBoundary, function (boundary) {
3007 // content is smaller than wrapper
3008 if (boundary.maxScrollPos > 0) {
3009 // allow scrolling when content is not full of wrapper
3010 boundary.maxScrollPos = -1;
3011 }
3012 boundary.minScrollPos = _this.currentMinScrollY;
3013 });
3014 // integrate with mousewheel
3015 if (this.hasMouseWheelPlugin()) {
3016 this.registerHooks(this.scroll, this.scroll.eventTypes.alterOptions, function (mouseWheelOptions) {
3017 var SANE_DISCRETE_TIME = 300;
3018 var SANE_EASE_TIME = 350;
3019 mouseWheelOptions.discreteTime = SANE_DISCRETE_TIME;
3020 // easeTime > discreteTime ensure goInto checkPullDown function
3021 mouseWheelOptions.easeTime = SANE_EASE_TIME;
3022 });
3023 this.registerHooks(this.scroll, this.scroll.eventTypes.mousewheelEnd, function () {
3024 // mouseWheel need trigger checkPullDown manually
3025 scroller.hooks.trigger(scroller.hooks.eventTypes.end);
3026 });
3027 }
3028 };
3029 PullDown.prototype.registerHooks = function (hooks, name, handler) {
3030 hooks.on(name, handler, this);
3031 this.hooksFn.push([hooks, name, handler]);
3032 };
3033 PullDown.prototype.hasMouseWheelPlugin = function () {
3034 return !!this.scroll.eventTypes.alterOptions;
3035 };
3036 PullDown.prototype.watch = function () {
3037 var scroller = this.scroll.scroller;
3038 this.watching = true;
3039 this.registerHooks(scroller.hooks, scroller.hooks.eventTypes.end, this.checkPullDown);
3040 this.registerHooks(this.scroll, this.scroll.eventTypes.scrollStart, this.resetStateBeforeScrollStart);
3041 this.registerHooks(this.scroll, this.scroll.eventTypes.scroll, this.checkLocationOfThresholdBoundary);
3042 if (this.hasMouseWheelPlugin()) {
3043 this.registerHooks(this.scroll, this.scroll.eventTypes.mousewheelStart, this.resetStateBeforeScrollStart);
3044 }
3045 };
3046 PullDown.prototype.resetStateBeforeScrollStart = function () {
3047 // current fetching pulldownRefresh has ended
3048 if (!this.isFetchingStatus()) {
3049 this.setPulling(1 /* MOVING */);
3050 this.setThresholdBoundary(0 /* DEFAULT */);
3051 }
3052 };
3053 PullDown.prototype.checkLocationOfThresholdBoundary = function () {
3054 // pulldownRefresh is in the phase of Moving
3055 if (this.pulling === 1 /* MOVING */) {
3056 var scroll_1 = this.scroll;
3057 // enter threshold boundary
3058 var enteredThresholdBoundary = this.thresholdBoundary !== 1 /* INSIDE */ &&
3059 this.locateInsideThresholdBoundary();
3060 // leave threshold boundary
3061 var leftThresholdBoundary = this.thresholdBoundary !== 2 /* OUTSIDE */ &&
3062 !this.locateInsideThresholdBoundary();
3063 if (enteredThresholdBoundary) {
3064 this.setThresholdBoundary(1 /* INSIDE */);
3065 scroll_1.trigger(ENTER_THRESHOLD_EVENT);
3066 }
3067 if (leftThresholdBoundary) {
3068 this.setThresholdBoundary(2 /* OUTSIDE */);
3069 scroll_1.trigger(LEAVE_THRESHOLD_EVENT);
3070 }
3071 }
3072 };
3073 PullDown.prototype.locateInsideThresholdBoundary = function () {
3074 return this.scroll.y <= this.options.threshold;
3075 };
3076 PullDown.prototype.unwatch = function () {
3077 var scroll = this.scroll;
3078 var scroller = scroll.scroller;
3079 this.watching = false;
3080 scroller.hooks.off(scroller.hooks.eventTypes.end, this.checkPullDown);
3081 scroll.off(scroll.eventTypes.scrollStart, this.resetStateBeforeScrollStart);
3082 scroll.off(scroll.eventTypes.scroll, this.checkLocationOfThresholdBoundary);
3083 if (this.hasMouseWheelPlugin()) {
3084 scroll.off(scroll.eventTypes.mousewheelStart, this.resetStateBeforeScrollStart);
3085 }
3086 };
3087 PullDown.prototype.checkPullDown = function () {
3088 var _a = this.options, threshold = _a.threshold, stop = _a.stop;
3089 // check if a real pull down action
3090 if (this.scroll.y < threshold) {
3091 return false;
3092 }
3093 if (this.pulling === 1 /* MOVING */) {
3094 this.modifyBehaviorYBoundary(stop);
3095 this.setPulling(2 /* FETCHING */);
3096 this.scroll.trigger(PULLING_DOWN_EVENT);
3097 }
3098 this.scroll.scrollTo(this.scroll.x, stop, this.scroll.options.bounceTime, ease.bounce);
3099 return this.isFetchingStatus();
3100 };
3101 PullDown.prototype.isFetchingStatus = function () {
3102 return this.pulling === 2 /* FETCHING */;
3103 };
3104 PullDown.prototype.modifyBehaviorYBoundary = function (stopDistance) {
3105 var scrollBehaviorY = this.scroll.scroller.scrollBehaviorY;
3106 // manually modify minScrollPos for a hang animation
3107 // to prevent from resetPosition
3108 this.cachedOriginanMinScrollY = scrollBehaviorY.minScrollPos;
3109 this.currentMinScrollY = stopDistance;
3110 scrollBehaviorY.computeBoundary();
3111 };
3112 PullDown.prototype.finishPullDown = function () {
3113 if (this.isFetchingStatus()) {
3114 var scrollBehaviorY = this.scroll.scroller.scrollBehaviorY;
3115 // restore minScrollY since the hang animation has ended
3116 this.currentMinScrollY = this.cachedOriginanMinScrollY;
3117 scrollBehaviorY.computeBoundary();
3118 this.setPulling(0 /* DEFAULT */);
3119 this.scroll.resetPosition(this.scroll.options.bounceTime, ease.bounce);
3120 }
3121 };
3122 // allow 'true' type is compat for beta version implements
3123 PullDown.prototype.openPullDown = function (config) {
3124 if (config === void 0) { config = {}; }
3125 this.handleOptions(config);
3126 if (!this.watching) {
3127 this.watch();
3128 }
3129 };
3130 PullDown.prototype.closePullDown = function () {
3131 this.unwatch();
3132 };
3133 PullDown.prototype.autoPullDownRefresh = function () {
3134 var _a = this.options, threshold = _a.threshold, stop = _a.stop;
3135 if (this.isFetchingStatus() || !this.watching) {
3136 return;
3137 }
3138 this.modifyBehaviorYBoundary(stop);
3139 this.scroll.trigger(this.scroll.eventTypes.scrollStart);
3140 this.scroll.scrollTo(this.scroll.x, threshold);
3141 this.setPulling(2 /* FETCHING */);
3142 this.scroll.trigger(PULLING_DOWN_EVENT);
3143 this.scroll.scrollTo(this.scroll.x, stop, this.scroll.options.bounceTime, ease.bounce);
3144 };
3145 PullDown.pluginName = 'pullDownRefresh';
3146 return PullDown;
3147}());
3148
3149var sourcePrefix$5 = 'plugins.pullUpLoad';
3150var propertiesMap$5 = [
3151 {
3152 key: 'finishPullUp',
3153 name: 'finishPullUp'
3154 },
3155 {
3156 key: 'openPullUp',
3157 name: 'openPullUp'
3158 },
3159 {
3160 key: 'closePullUp',
3161 name: 'closePullUp'
3162 },
3163 {
3164 key: 'autoPullUpLoad',
3165 name: 'autoPullUpLoad'
3166 }
3167];
3168var propertiesConfig$5 = propertiesMap$5.map(function (item) {
3169 return {
3170 key: item.key,
3171 sourceKey: sourcePrefix$5 + "." + item.name
3172 };
3173});
3174
3175var PULL_UP_HOOKS_NAME = 'pullingUp';
3176var PullUp = /** @class */ (function () {
3177 function PullUp(scroll) {
3178 this.scroll = scroll;
3179 this.pulling = false;
3180 this.watching = false;
3181 this.init();
3182 }
3183 PullUp.prototype.init = function () {
3184 this.handleBScroll();
3185 this.handleOptions(this.scroll.options.pullUpLoad);
3186 this.handleHooks();
3187 this.watch();
3188 };
3189 PullUp.prototype.handleBScroll = function () {
3190 this.scroll.registerType([PULL_UP_HOOKS_NAME]);
3191 this.scroll.proxy(propertiesConfig$5);
3192 };
3193 PullUp.prototype.handleOptions = function (userOptions) {
3194 if (userOptions === void 0) { userOptions = {}; }
3195 userOptions = (userOptions === true ? {} : userOptions);
3196 var defaultOptions = {
3197 threshold: 0,
3198 };
3199 this.options = extend(defaultOptions, userOptions);
3200 this.scroll.options.probeType = 3 /* Realtime */;
3201 };
3202 PullUp.prototype.handleHooks = function () {
3203 var _this = this;
3204 this.hooksFn = [];
3205 var scrollBehaviorY = this.scroll.scroller.scrollBehaviorY;
3206 this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.contentChanged, function () {
3207 _this.finishPullUp();
3208 });
3209 this.registerHooks(scrollBehaviorY.hooks, scrollBehaviorY.hooks.eventTypes.computeBoundary, function (boundary) {
3210 // content is smaller than wrapper
3211 if (boundary.maxScrollPos > 0) {
3212 // allow scrolling when content is not full of wrapper
3213 boundary.maxScrollPos = -1;
3214 }
3215 });
3216 };
3217 PullUp.prototype.registerHooks = function (hooks, name, handler) {
3218 hooks.on(name, handler, this);
3219 this.hooksFn.push([hooks, name, handler]);
3220 };
3221 PullUp.prototype.watch = function () {
3222 if (this.watching) {
3223 return;
3224 }
3225 this.watching = true;
3226 this.registerHooks(this.scroll, this.scroll.eventTypes.scroll, this.checkPullUp);
3227 };
3228 PullUp.prototype.unwatch = function () {
3229 this.watching = false;
3230 this.scroll.off(this.scroll.eventTypes.scroll, this.checkPullUp);
3231 };
3232 PullUp.prototype.checkPullUp = function (pos) {
3233 var _this = this;
3234 var threshold = this.options.threshold;
3235 if (this.scroll.movingDirectionY === 1 /* Positive */ &&
3236 pos.y <= this.scroll.maxScrollY + threshold) {
3237 this.pulling = true;
3238 // must reset pulling after scrollEnd
3239 this.scroll.once(this.scroll.eventTypes.scrollEnd, function () {
3240 _this.pulling = false;
3241 });
3242 this.unwatch();
3243 this.scroll.trigger(PULL_UP_HOOKS_NAME);
3244 }
3245 };
3246 PullUp.prototype.finishPullUp = function () {
3247 var _this = this;
3248 // reset Direction, fix #936
3249 this.scroll.scroller.scrollBehaviorY.setMovingDirection(0 /* Default */);
3250 if (this.pulling) {
3251 this.scroll.once(this.scroll.eventTypes.scrollEnd, function () {
3252 _this.watch();
3253 });
3254 }
3255 else {
3256 this.watch();
3257 }
3258 };
3259 // allow 'true' type is compat for beta version implements
3260 PullUp.prototype.openPullUp = function (config) {
3261 if (config === void 0) { config = {}; }
3262 this.handleOptions(config);
3263 this.watch();
3264 };
3265 PullUp.prototype.closePullUp = function () {
3266 this.unwatch();
3267 };
3268 PullUp.prototype.autoPullUpLoad = function () {
3269 var threshold = this.options.threshold;
3270 var scrollBehaviorY = this.scroll.scroller.scrollBehaviorY;
3271 if (this.pulling || !this.watching) {
3272 return;
3273 }
3274 // simulate a pullUp action
3275 var NEGATIVE_VALUE = -1;
3276 var outOfBoundaryPos = scrollBehaviorY.maxScrollPos + threshold + NEGATIVE_VALUE;
3277 this.scroll.scroller.scrollBehaviorY.setMovingDirection(NEGATIVE_VALUE);
3278 this.scroll.scrollTo(this.scroll.x, outOfBoundaryPos, this.scroll.options.bounceTime);
3279 };
3280 PullUp.pluginName = 'pullUpLoad';
3281 return PullUp;
3282}());
3283
3284var EventHandler = /** @class */ (function () {
3285 function EventHandler(indicator, options) {
3286 this.indicator = indicator;
3287 this.options = options;
3288 this.hooks = new EventEmitter(['touchStart', 'touchMove', 'touchEnd']);
3289 this.registerEvents();
3290 }
3291 EventHandler.prototype.registerEvents = function () {
3292 var _a = this.options, disableMouse = _a.disableMouse, disableTouch = _a.disableTouch;
3293 var startEvents = [];
3294 var moveEvents = [];
3295 var endEvents = [];
3296 if (!disableMouse) {
3297 startEvents.push({
3298 name: 'mousedown',
3299 handler: this.start.bind(this),
3300 });
3301 moveEvents.push({
3302 name: 'mousemove',
3303 handler: this.move.bind(this),
3304 });
3305 endEvents.push({
3306 name: 'mouseup',
3307 handler: this.end.bind(this),
3308 });
3309 }
3310 if (!disableTouch) {
3311 startEvents.push({
3312 name: 'touchstart',
3313 handler: this.start.bind(this),
3314 });
3315 moveEvents.push({
3316 name: 'touchmove',
3317 handler: this.move.bind(this),
3318 });
3319 endEvents.push({
3320 name: 'touchend',
3321 handler: this.end.bind(this),
3322 }, {
3323 name: 'touchcancel',
3324 handler: this.end.bind(this),
3325 });
3326 }
3327 this.startEventRegister = new EventRegister(this.indicator.indicatorEl, startEvents);
3328 this.moveEventRegister = new EventRegister(window, moveEvents);
3329 this.endEventRegister = new EventRegister(window, endEvents);
3330 };
3331 EventHandler.prototype.BScrollIsDisabled = function () {
3332 return !this.indicator.scroll.enabled;
3333 };
3334 EventHandler.prototype.start = function (e) {
3335 if (this.BScrollIsDisabled()) {
3336 return;
3337 }
3338 var point = (e.touches ? e.touches[0] : e);
3339 maybePrevent(e);
3340 e.stopPropagation();
3341 this.initiated = true;
3342 this.lastPoint = point[this.indicator.keysMap.point];
3343 this.hooks.trigger(this.hooks.eventTypes.touchStart);
3344 };
3345 EventHandler.prototype.move = function (e) {
3346 if (!this.initiated) {
3347 return;
3348 }
3349 var point = (e.touches ? e.touches[0] : e);
3350 var pointPos = point[this.indicator.keysMap.point];
3351 maybePrevent(e);
3352 e.stopPropagation();
3353 var delta = pointPos - this.lastPoint;
3354 this.lastPoint = pointPos;
3355 this.hooks.trigger(this.hooks.eventTypes.touchMove, delta);
3356 };
3357 EventHandler.prototype.end = function (e) {
3358 if (!this.initiated) {
3359 return;
3360 }
3361 this.initiated = false;
3362 maybePrevent(e);
3363 e.stopPropagation();
3364 this.hooks.trigger(this.hooks.eventTypes.touchEnd);
3365 };
3366 EventHandler.prototype.destroy = function () {
3367 this.startEventRegister.destroy();
3368 this.moveEventRegister.destroy();
3369 this.endEventRegister.destroy();
3370 };
3371 return EventHandler;
3372}());
3373
3374var Indicator$1 = /** @class */ (function () {
3375 function Indicator(scroll, options) {
3376 this.scroll = scroll;
3377 this.options = options;
3378 this.hooksFn = [];
3379 this.wrapper = options.wrapper;
3380 this.direction = options.direction;
3381 this.indicatorEl = this.wrapper.children[0];
3382 this.keysMap = this.getKeysMap();
3383 this.handleFade();
3384 this.handleHooks();
3385 }
3386 Indicator.prototype.handleFade = function () {
3387 if (this.options.fade) {
3388 this.wrapper.style.opacity = '0';
3389 }
3390 };
3391 Indicator.prototype.handleHooks = function () {
3392 var _this = this;
3393 var _a = this.options, fade = _a.fade, interactive = _a.interactive, scrollbarTrackClickable = _a.scrollbarTrackClickable;
3394 var scroll = this.scroll;
3395 var scrollHooks = scroll.hooks;
3396 var translaterHooks = scroll.scroller.translater.hooks;
3397 var animaterHooks = scroll.scroller.animater.hooks;
3398 this.registerHooks(scrollHooks, scrollHooks.eventTypes.refresh, this.refresh);
3399 this.registerHooks(translaterHooks, translaterHooks.eventTypes.translate, function (pos) {
3400 var hasScrollKey = _this.keysMap.hasScroll;
3401 if (_this.scroll[hasScrollKey]) {
3402 _this.updatePosition(pos);
3403 }
3404 });
3405 this.registerHooks(animaterHooks, animaterHooks.eventTypes.time, this.transitionTime);
3406 this.registerHooks(animaterHooks, animaterHooks.eventTypes.timeFunction, this.transitionTimingFunction);
3407 if (fade) {
3408 this.registerHooks(scroll, scroll.eventTypes.scrollEnd, function () {
3409 _this.fade();
3410 });
3411 this.registerHooks(scroll, scroll.eventTypes.scrollStart, function () {
3412 _this.fade(true);
3413 });
3414 // for mousewheel event
3415 if (scroll.eventTypes.mousewheelStart &&
3416 scroll.eventTypes.mousewheelEnd) {
3417 this.registerHooks(scroll, scroll.eventTypes.mousewheelStart, function () {
3418 _this.fade(true);
3419 });
3420 this.registerHooks(scroll, scroll.eventTypes.mousewheelMove, function () {
3421 _this.fade(true);
3422 });
3423 this.registerHooks(scroll, scroll.eventTypes.mousewheelEnd, function () {
3424 _this.fade();
3425 });
3426 }
3427 }
3428 if (interactive) {
3429 var _b = this.scroll.options, disableMouse = _b.disableMouse, disableTouch = _b.disableTouch;
3430 this.eventHandler = new EventHandler(this, {
3431 disableMouse: disableMouse,
3432 disableTouch: disableTouch,
3433 });
3434 var eventHandlerHooks = this.eventHandler.hooks;
3435 this.registerHooks(eventHandlerHooks, eventHandlerHooks.eventTypes.touchStart, this.startHandler);
3436 this.registerHooks(eventHandlerHooks, eventHandlerHooks.eventTypes.touchMove, this.moveHandler);
3437 this.registerHooks(eventHandlerHooks, eventHandlerHooks.eventTypes.touchEnd, this.endHandler);
3438 }
3439 if (scrollbarTrackClickable) {
3440 this.bindClick();
3441 }
3442 };
3443 Indicator.prototype.registerHooks = function (hooks, name, handler) {
3444 hooks.on(name, handler, this);
3445 this.hooksFn.push([hooks, name, handler]);
3446 };
3447 Indicator.prototype.bindClick = function () {
3448 var wrapper = this.wrapper;
3449 this.clickEventRegister = new EventRegister(wrapper, [
3450 {
3451 name: 'click',
3452 handler: this.handleClick.bind(this),
3453 },
3454 ]);
3455 };
3456 Indicator.prototype.handleClick = function (e) {
3457 var newPos = this.calculateclickOffsetPos(e);
3458 var _a = this.scroll, x = _a.x, y = _a.y;
3459 x = this.direction === "horizontal" /* Horizontal */ ? newPos : x;
3460 y = this.direction === "vertical" /* Vertical */ ? newPos : y;
3461 this.scroll.scrollTo(x, y, this.options.scrollbarTrackOffsetTime);
3462 };
3463 Indicator.prototype.calculateclickOffsetPos = function (e) {
3464 var _a = this.keysMap, poinKey = _a.point, domRectKey = _a.domRect;
3465 var scrollbarTrackOffsetType = this.options.scrollbarTrackOffsetType;
3466 var clickPointOffset = e[poinKey] - this.wrapperRect[domRectKey];
3467 var scrollToWhere = clickPointOffset < this.currentPos ? -1 /* Up */ : 1 /* Down */;
3468 var delta = 0;
3469 var currentPos = this.currentPos;
3470 if (scrollbarTrackOffsetType === "step" /* Step */) {
3471 delta = this.scrollInfo.baseSize * scrollToWhere;
3472 }
3473 else {
3474 delta = 0;
3475 currentPos = clickPointOffset;
3476 }
3477 return this.newPos(currentPos, delta, this.scrollInfo);
3478 };
3479 Indicator.prototype.getKeysMap = function () {
3480 if (this.direction === "vertical" /* Vertical */) {
3481 return {
3482 hasScroll: 'hasVerticalScroll',
3483 size: 'height',
3484 wrapperSize: 'clientHeight',
3485 scrollerSize: 'scrollerHeight',
3486 maxScrollPos: 'maxScrollY',
3487 pos: 'y',
3488 point: 'pageY',
3489 translateProperty: 'translateY',
3490 domRect: 'top',
3491 };
3492 }
3493 return {
3494 hasScroll: 'hasHorizontalScroll',
3495 size: 'width',
3496 wrapperSize: 'clientWidth',
3497 scrollerSize: 'scrollerWidth',
3498 maxScrollPos: 'maxScrollX',
3499 pos: 'x',
3500 point: 'pageX',
3501 translateProperty: 'translateX',
3502 domRect: 'left',
3503 };
3504 };
3505 Indicator.prototype.fade = function (visible) {
3506 var _a = this.options, fadeInTime = _a.fadeInTime, fadeOutTime = _a.fadeOutTime;
3507 var time = visible ? fadeInTime : fadeOutTime;
3508 var wrapper = this.wrapper;
3509 wrapper.style[style.transitionDuration] = time + 'ms';
3510 wrapper.style.opacity = visible ? '1' : '0';
3511 };
3512 Indicator.prototype.refresh = function () {
3513 var hasScrollKey = this.keysMap.hasScroll;
3514 var scroll = this.scroll;
3515 var x = scroll.x, y = scroll.y;
3516 this.wrapperRect = this.wrapper.getBoundingClientRect();
3517 if (this.canScroll(scroll[hasScrollKey])) {
3518 var _a = this.keysMap, wrapperSizeKey = _a.wrapperSize, scrollerSizeKey = _a.scrollerSize, maxScrollPosKey = _a.maxScrollPos;
3519 this.scrollInfo = this.refreshScrollInfo(this.wrapper[wrapperSizeKey], scroll[scrollerSizeKey], scroll[maxScrollPosKey], this.indicatorEl[wrapperSizeKey]);
3520 this.updatePosition({
3521 x: x,
3522 y: y,
3523 });
3524 }
3525 };
3526 Indicator.prototype.transitionTime = function (time) {
3527 if (time === void 0) { time = 0; }
3528 this.indicatorEl.style[style.transitionDuration] = time + 'ms';
3529 };
3530 Indicator.prototype.transitionTimingFunction = function (easing) {
3531 this.indicatorEl.style[style.transitionTimingFunction] = easing;
3532 };
3533 Indicator.prototype.canScroll = function (hasScroll) {
3534 this.wrapper.style.display = hasScroll ? 'block' : 'none';
3535 return hasScroll;
3536 };
3537 Indicator.prototype.refreshScrollInfo = function (wrapperSize, scrollerSize, maxScrollPos, indicatorElSize) {
3538 var baseSize = Math.max(Math.round((wrapperSize * wrapperSize) / (scrollerSize || wrapperSize || 1)), this.options.minSize);
3539 if (this.options.isCustom) {
3540 baseSize = indicatorElSize;
3541 }
3542 var maxIndicatorScrollPos = wrapperSize - baseSize;
3543 // sizeRatio is negative
3544 var sizeRatio = maxIndicatorScrollPos / maxScrollPos;
3545 return {
3546 baseSize: baseSize,
3547 maxScrollPos: maxIndicatorScrollPos,
3548 minScrollPos: 0,
3549 sizeRatio: sizeRatio,
3550 };
3551 };
3552 Indicator.prototype.updatePosition = function (point) {
3553 var _a = this.caculatePosAndSize(point, this.scrollInfo), pos = _a.pos, size = _a.size;
3554 this.refreshStyle(size, pos);
3555 this.currentPos = pos;
3556 };
3557 Indicator.prototype.caculatePosAndSize = function (point, scrollInfo) {
3558 var posKey = this.keysMap.pos;
3559 var sizeRatio = scrollInfo.sizeRatio, baseSize = scrollInfo.baseSize, maxScrollPos = scrollInfo.maxScrollPos, minScrollPos = scrollInfo.minScrollPos;
3560 var minSize = this.options.minSize;
3561 var pos = Math.round(sizeRatio * point[posKey]);
3562 var size;
3563 // when out of boundary, slow down size reduction
3564 if (pos < minScrollPos) {
3565 size = Math.max(baseSize + pos * 3, minSize);
3566 pos = minScrollPos;
3567 }
3568 else if (pos > maxScrollPos) {
3569 size = Math.max(baseSize - (pos - maxScrollPos) * 3, minSize);
3570 pos = maxScrollPos + baseSize - size;
3571 }
3572 else {
3573 size = baseSize;
3574 }
3575 return {
3576 pos: pos,
3577 size: size,
3578 };
3579 };
3580 Indicator.prototype.refreshStyle = function (size, pos) {
3581 var _a = this.keysMap, translatePropertyKey = _a.translateProperty, sizeKey = _a.size;
3582 var translateZ = this.scroll.options.translateZ;
3583 this.indicatorEl.style[sizeKey] = size + "px";
3584 this.indicatorEl.style[style.transform] = translatePropertyKey + "(" + pos + "px)" + translateZ;
3585 };
3586 Indicator.prototype.startHandler = function () {
3587 this.moved = false;
3588 this.startTime = getNow();
3589 this.transitionTime();
3590 this.scroll.scroller.hooks.trigger(this.scroll.scroller.hooks.eventTypes.beforeScrollStart);
3591 };
3592 Indicator.prototype.moveHandler = function (delta) {
3593 if (!this.moved && !this.indicatorNotMoved(delta)) {
3594 this.moved = true;
3595 this.scroll.scroller.hooks.trigger(this.scroll.scroller.hooks.eventTypes.scrollStart);
3596 }
3597 if (this.moved) {
3598 var newPos = this.newPos(this.currentPos, delta, this.scrollInfo);
3599 this.syncBScroll(newPos);
3600 }
3601 };
3602 Indicator.prototype.endHandler = function () {
3603 if (this.moved) {
3604 var _a = this.scroll, x = _a.x, y = _a.y;
3605 this.scroll.scroller.hooks.trigger(this.scroll.scroller.hooks.eventTypes.scrollEnd, {
3606 x: x,
3607 y: y,
3608 });
3609 }
3610 };
3611 Indicator.prototype.indicatorNotMoved = function (delta) {
3612 var currentPos = this.currentPos;
3613 var _a = this.scrollInfo, maxScrollPos = _a.maxScrollPos, minScrollPos = _a.minScrollPos;
3614 var notMoved = (currentPos === minScrollPos && delta <= 0) ||
3615 (currentPos === maxScrollPos && delta >= 0);
3616 return notMoved;
3617 };
3618 Indicator.prototype.syncBScroll = function (newPos) {
3619 var timestamp = getNow();
3620 var _a = this.scroll, x = _a.x, y = _a.y, options = _a.options, scroller = _a.scroller, maxScrollY = _a.maxScrollY, minScrollY = _a.minScrollY, maxScrollX = _a.maxScrollX, minScrollX = _a.minScrollX;
3621 var probeType = options.probeType, momentumLimitTime = options.momentumLimitTime;
3622 var position = { x: x, y: y };
3623 if (this.direction === "vertical" /* Vertical */) {
3624 position.y = between(newPos, maxScrollY, minScrollY);
3625 }
3626 else {
3627 position.x = between(newPos, maxScrollX, minScrollX);
3628 }
3629 scroller.translater.translate(position);
3630 // dispatch scroll in interval time
3631 if (timestamp - this.startTime > momentumLimitTime) {
3632 this.startTime = timestamp;
3633 if (probeType === 1 /* Throttle */) {
3634 scroller.hooks.trigger(scroller.hooks.eventTypes.scroll, position);
3635 }
3636 }
3637 // dispatch scroll all the time
3638 if (probeType > 1 /* Throttle */) {
3639 scroller.hooks.trigger(scroller.hooks.eventTypes.scroll, position);
3640 }
3641 };
3642 Indicator.prototype.newPos = function (currentPos, delta, scrollInfo) {
3643 var maxScrollPos = scrollInfo.maxScrollPos, sizeRatio = scrollInfo.sizeRatio, minScrollPos = scrollInfo.minScrollPos;
3644 var newPos = currentPos + delta;
3645 newPos = between(newPos, minScrollPos, maxScrollPos);
3646 return Math.round(newPos / sizeRatio);
3647 };
3648 Indicator.prototype.destroy = function () {
3649 var _a = this.options, interactive = _a.interactive, scrollbarTrackClickable = _a.scrollbarTrackClickable, isCustom = _a.isCustom;
3650 if (interactive) {
3651 this.eventHandler.destroy();
3652 }
3653 if (scrollbarTrackClickable) {
3654 this.clickEventRegister.destroy();
3655 }
3656 if (!isCustom) {
3657 this.wrapper.parentNode.removeChild(this.wrapper);
3658 }
3659 this.hooksFn.forEach(function (item) {
3660 var hooks = item[0];
3661 var hooksName = item[1];
3662 var handlerFn = item[2];
3663 hooks.off(hooksName, handlerFn);
3664 });
3665 this.hooksFn.length = 0;
3666 };
3667 return Indicator;
3668}());
3669
3670var ScrollBar = /** @class */ (function () {
3671 function ScrollBar(scroll) {
3672 this.scroll = scroll;
3673 this.handleOptions();
3674 this.createIndicators();
3675 this.handleHooks();
3676 }
3677 ScrollBar.prototype.handleHooks = function () {
3678 var _this = this;
3679 var scroll = this.scroll;
3680 scroll.hooks.on(scroll.hooks.eventTypes.destroy, function () {
3681 for (var _i = 0, _a = _this.indicators; _i < _a.length; _i++) {
3682 var indicator = _a[_i];
3683 indicator.destroy();
3684 }
3685 });
3686 };
3687 ScrollBar.prototype.handleOptions = function () {
3688 var userOptions = (this.scroll.options.scrollbar === true
3689 ? {}
3690 : this.scroll.options.scrollbar);
3691 var defaultOptions = {
3692 fade: true,
3693 fadeInTime: 250,
3694 fadeOutTime: 500,
3695 interactive: false,
3696 customElements: [],
3697 minSize: 8,
3698 scrollbarTrackClickable: false,
3699 scrollbarTrackOffsetType: "step" /* Step */,
3700 scrollbarTrackOffsetTime: 300,
3701 };
3702 this.options = extend(defaultOptions, userOptions);
3703 };
3704 ScrollBar.prototype.createIndicators = function () {
3705 var indicatorOptions;
3706 var scroll = this.scroll;
3707 var indicators = [];
3708 var scrollDirectionConfigKeys = ['scrollX', 'scrollY'];
3709 var indicatorDirections = [
3710 "horizontal" /* Horizontal */,
3711 "vertical" /* Vertical */,
3712 ];
3713 var customScrollbarEls = this.options.customElements;
3714 for (var i = 0; i < scrollDirectionConfigKeys.length; i++) {
3715 var key = scrollDirectionConfigKeys[i];
3716 // wanna scroll in specified direction
3717 if (scroll.options[key]) {
3718 var customElement = customScrollbarEls.shift();
3719 var direction = indicatorDirections[i];
3720 var isCustom = false;
3721 var scrollbarWrapper = customElement
3722 ? customElement
3723 : this.createScrollbarElement(direction);
3724 // internal scrollbar
3725 if (scrollbarWrapper !== customElement) {
3726 scroll.wrapper.appendChild(scrollbarWrapper);
3727 }
3728 else {
3729 // custom scrollbar passed by users
3730 isCustom = true;
3731 }
3732 indicatorOptions = __assign(__assign({ wrapper: scrollbarWrapper, direction: direction }, this.options), { isCustom: isCustom });
3733 indicators.push(new Indicator$1(scroll, indicatorOptions));
3734 }
3735 }
3736 this.indicators = indicators;
3737 };
3738 ScrollBar.prototype.createScrollbarElement = function (direction, scrollbarTrackClickable) {
3739 if (scrollbarTrackClickable === void 0) { scrollbarTrackClickable = this.options.scrollbarTrackClickable; }
3740 var scrollbarWrapperEl = document.createElement('div');
3741 var scrollbarIndicatorEl = document.createElement('div');
3742 scrollbarWrapperEl.style.cssText =
3743 'position:absolute;z-index:9999;overflow:hidden;';
3744 scrollbarIndicatorEl.style.cssText =
3745 'box-sizing:border-box;position:absolute;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);border-radius:3px;';
3746 scrollbarIndicatorEl.className = 'bscroll-indicator';
3747 if (direction === "horizontal" /* Horizontal */) {
3748 scrollbarWrapperEl.style.cssText +=
3749 'height:7px;left:2px;right:2px;bottom:0;';
3750 scrollbarIndicatorEl.style.height = '100%';
3751 scrollbarWrapperEl.className = 'bscroll-horizontal-scrollbar';
3752 }
3753 else {
3754 scrollbarWrapperEl.style.cssText +=
3755 'width:7px;bottom:2px;top:2px;right:1px;';
3756 scrollbarIndicatorEl.style.width = '100%';
3757 scrollbarWrapperEl.className = 'bscroll-vertical-scrollbar';
3758 }
3759 if (!scrollbarTrackClickable) {
3760 scrollbarWrapperEl.style.cssText += 'pointer-events:none;';
3761 }
3762 scrollbarWrapperEl.appendChild(scrollbarIndicatorEl);
3763 return scrollbarWrapperEl;
3764 };
3765 ScrollBar.pluginName = 'scrollbar';
3766 return ScrollBar;
3767}());
3768
3769var PagesMatrix = /** @class */ (function () {
3770 function PagesMatrix(scroll) {
3771 this.scroll = scroll;
3772 this.init();
3773 }
3774 PagesMatrix.prototype.init = function () {
3775 var scroller = this.scroll.scroller;
3776 var scrollBehaviorX = scroller.scrollBehaviorX, scrollBehaviorY = scroller.scrollBehaviorY;
3777 this.wrapperWidth = scrollBehaviorX.wrapperSize;
3778 this.wrapperHeight = scrollBehaviorY.wrapperSize;
3779 this.scrollerHeight = scrollBehaviorY.contentSize;
3780 this.scrollerWidth = scrollBehaviorX.contentSize;
3781 this.pages = this.buildPagesMatrix(this.wrapperWidth, this.wrapperHeight);
3782 this.pageLengthOfX = this.pages ? this.pages.length : 0;
3783 this.pageLengthOfY = this.pages && this.pages[0] ? this.pages[0].length : 0;
3784 };
3785 PagesMatrix.prototype.getPageStats = function (pageX, pageY) {
3786 return this.pages[pageX][pageY];
3787 };
3788 PagesMatrix.prototype.getNearestPageIndex = function (x, y) {
3789 var pageX = 0;
3790 var pageY = 0;
3791 var l = this.pages.length;
3792 for (; pageX < l - 1; pageX++) {
3793 if (x >= this.pages[pageX][0].cx) {
3794 break;
3795 }
3796 }
3797 l = this.pages[pageX].length;
3798 for (; pageY < l - 1; pageY++) {
3799 if (y >= this.pages[0][pageY].cy) {
3800 break;
3801 }
3802 }
3803 return {
3804 pageX: pageX,
3805 pageY: pageY,
3806 };
3807 };
3808 // (n x 1) matrix for horizontal scroll or
3809 // (1 * n) matrix for vertical scroll
3810 PagesMatrix.prototype.buildPagesMatrix = function (stepX, stepY) {
3811 var pages = [];
3812 var x = 0;
3813 var y;
3814 var cx;
3815 var cy;
3816 var i = 0;
3817 var l;
3818 var maxScrollPosX = this.scroll.scroller.scrollBehaviorX.maxScrollPos;
3819 var maxScrollPosY = this.scroll.scroller.scrollBehaviorY.maxScrollPos;
3820 cx = Math.round(stepX / 2);
3821 cy = Math.round(stepY / 2);
3822 while (x > -this.scrollerWidth) {
3823 pages[i] = [];
3824 l = 0;
3825 y = 0;
3826 while (y > -this.scrollerHeight) {
3827 pages[i][l] = {
3828 x: Math.max(x, maxScrollPosX),
3829 y: Math.max(y, maxScrollPosY),
3830 width: stepX,
3831 height: stepY,
3832 cx: x - cx,
3833 cy: y - cy,
3834 };
3835 y -= stepY;
3836 l++;
3837 }
3838 x -= stepX;
3839 i++;
3840 }
3841 return pages;
3842 };
3843 return PagesMatrix;
3844}());
3845
3846var BASE_PAGE = {
3847 pageX: 0,
3848 pageY: 0,
3849 x: 0,
3850 y: 0,
3851};
3852
3853var SlidePages = /** @class */ (function () {
3854 function SlidePages(scroll, slideOptions) {
3855 this.scroll = scroll;
3856 this.slideOptions = slideOptions;
3857 this.slideX = false;
3858 this.slideY = false;
3859 this.currentPage = extend({}, BASE_PAGE);
3860 }
3861 SlidePages.prototype.refresh = function () {
3862 this.pagesMatrix = new PagesMatrix(this.scroll);
3863 this.checkSlideLoop();
3864 this.currentPage = this.getAdjustedCurrentPage();
3865 };
3866 SlidePages.prototype.getAdjustedCurrentPage = function () {
3867 var _a = this.currentPage, pageX = _a.pageX, pageY = _a.pageY;
3868 // page index should be handled
3869 // because page counts may reduce
3870 pageX = Math.min(pageX, this.pagesMatrix.pageLengthOfX - 1);
3871 pageY = Math.min(pageY, this.pagesMatrix.pageLengthOfY - 1);
3872 // loop scene should also be respected
3873 // because clonedNode will cause pageLength increasing
3874 if (this.loopX) {
3875 pageX = Math.min(pageX, this.pagesMatrix.pageLengthOfX - 2);
3876 }
3877 if (this.loopY) {
3878 pageY = Math.min(pageY, this.pagesMatrix.pageLengthOfY - 2);
3879 }
3880 var _b = this.pagesMatrix.getPageStats(pageX, pageY), x = _b.x, y = _b.y;
3881 return { pageX: pageX, pageY: pageY, x: x, y: y };
3882 };
3883 SlidePages.prototype.setCurrentPage = function (newPage) {
3884 this.currentPage = newPage;
3885 };
3886 SlidePages.prototype.getInternalPage = function (pageX, pageY) {
3887 if (pageX >= this.pagesMatrix.pageLengthOfX) {
3888 pageX = this.pagesMatrix.pageLengthOfX - 1;
3889 }
3890 else if (pageX < 0) {
3891 pageX = 0;
3892 }
3893 if (pageY >= this.pagesMatrix.pageLengthOfY) {
3894 pageY = this.pagesMatrix.pageLengthOfY - 1;
3895 }
3896 else if (pageY < 0) {
3897 pageY = 0;
3898 }
3899 var _a = this.pagesMatrix.getPageStats(pageX, pageY), x = _a.x, y = _a.y;
3900 return {
3901 pageX: pageX,
3902 pageY: pageY,
3903 x: x,
3904 y: y,
3905 };
3906 };
3907 SlidePages.prototype.getInitialPage = function (showFirstPage, firstInitialised) {
3908 if (showFirstPage === void 0) { showFirstPage = false; }
3909 if (firstInitialised === void 0) { firstInitialised = false; }
3910 var _a = this.slideOptions, startPageXIndex = _a.startPageXIndex, startPageYIndex = _a.startPageYIndex;
3911 var firstPageX = this.loopX ? 1 : 0;
3912 var firstPageY = this.loopY ? 1 : 0;
3913 var pageX = showFirstPage ? firstPageX : this.currentPage.pageX;
3914 var pageY = showFirstPage ? firstPageY : this.currentPage.pageY;
3915 if (firstInitialised) {
3916 pageX = this.loopX ? startPageXIndex + 1 : startPageXIndex;
3917 pageY = this.loopY ? startPageYIndex + 1 : startPageYIndex;
3918 }
3919 else {
3920 pageX = showFirstPage ? firstPageX : this.currentPage.pageX;
3921 pageY = showFirstPage ? firstPageY : this.currentPage.pageY;
3922 }
3923 var _b = this.pagesMatrix.getPageStats(pageX, pageY), x = _b.x, y = _b.y;
3924 return {
3925 pageX: pageX,
3926 pageY: pageY,
3927 x: x,
3928 y: y,
3929 };
3930 };
3931 SlidePages.prototype.getExposedPage = function (page) {
3932 var exposedPage = extend({}, page);
3933 // only pageX or pageY need fix
3934 if (this.loopX) {
3935 exposedPage.pageX = this.fixedPage(exposedPage.pageX, this.pagesMatrix.pageLengthOfX - 2);
3936 }
3937 if (this.loopY) {
3938 exposedPage.pageY = this.fixedPage(exposedPage.pageY, this.pagesMatrix.pageLengthOfY - 2);
3939 }
3940 return exposedPage;
3941 };
3942 SlidePages.prototype.getExposedPageByPageIndex = function (pageIndexX, pageIndexY) {
3943 var page = {
3944 pageX: pageIndexX,
3945 pageY: pageIndexY,
3946 };
3947 if (this.loopX) {
3948 page.pageX = pageIndexX + 1;
3949 }
3950 if (this.loopY) {
3951 page.pageY = pageIndexY + 1;
3952 }
3953 var _a = this.pagesMatrix.getPageStats(page.pageX, page.pageY), x = _a.x, y = _a.y;
3954 return {
3955 x: x,
3956 y: y,
3957 pageX: pageIndexX,
3958 pageY: pageIndexY,
3959 };
3960 };
3961 SlidePages.prototype.getWillChangedPage = function (page) {
3962 page = extend({}, page);
3963 // Page need fix
3964 if (this.loopX) {
3965 page.pageX = this.fixedPage(page.pageX, this.pagesMatrix.pageLengthOfX - 2);
3966 page.x = this.pagesMatrix.getPageStats(page.pageX + 1, 0).x;
3967 }
3968 if (this.loopY) {
3969 page.pageY = this.fixedPage(page.pageY, this.pagesMatrix.pageLengthOfY - 2);
3970 page.y = this.pagesMatrix.getPageStats(0, page.pageY + 1).y;
3971 }
3972 return page;
3973 };
3974 SlidePages.prototype.fixedPage = function (page, realPageLen) {
3975 var pageIndex = [];
3976 for (var i = 0; i < realPageLen; i++) {
3977 pageIndex.push(i);
3978 }
3979 pageIndex.unshift(realPageLen - 1);
3980 pageIndex.push(0);
3981 return pageIndex[page];
3982 };
3983 SlidePages.prototype.getPageStats = function () {
3984 return this.pagesMatrix.getPageStats(this.currentPage.pageX, this.currentPage.pageY);
3985 };
3986 SlidePages.prototype.getValidPageIndex = function (x, y) {
3987 var lastX = this.pagesMatrix.pageLengthOfX - 1;
3988 var lastY = this.pagesMatrix.pageLengthOfY - 1;
3989 var firstX = 0;
3990 var firstY = 0;
3991 if (this.loopX) {
3992 x += 1;
3993 firstX = firstX + 1;
3994 lastX = lastX - 1;
3995 }
3996 if (this.loopY) {
3997 y += 1;
3998 firstY = firstY + 1;
3999 lastY = lastY - 1;
4000 }
4001 x = between(x, firstX, lastX);
4002 y = between(y, firstY, lastY);
4003 return {
4004 pageX: x,
4005 pageY: y,
4006 };
4007 };
4008 SlidePages.prototype.nextPageIndex = function () {
4009 return this.getPageIndexByDirection("positive" /* Positive */);
4010 };
4011 SlidePages.prototype.prevPageIndex = function () {
4012 return this.getPageIndexByDirection("negative" /* Negative */);
4013 };
4014 SlidePages.prototype.getNearestPage = function (x, y) {
4015 var pageIndex = this.pagesMatrix.getNearestPageIndex(x, y);
4016 var pageX = pageIndex.pageX, pageY = pageIndex.pageY;
4017 var newX = this.pagesMatrix.getPageStats(pageX, 0).x;
4018 var newY = this.pagesMatrix.getPageStats(0, pageY).y;
4019 return {
4020 x: newX,
4021 y: newY,
4022 pageX: pageX,
4023 pageY: pageY,
4024 };
4025 };
4026 SlidePages.prototype.getPageByDirection = function (page, directionX, directionY) {
4027 var pageX = page.pageX, pageY = page.pageY;
4028 if (pageX === this.currentPage.pageX) {
4029 pageX = between(pageX + directionX, 0, this.pagesMatrix.pageLengthOfX - 1);
4030 }
4031 if (pageY === this.currentPage.pageY) {
4032 pageY = between(pageY + directionY, 0, this.pagesMatrix.pageLengthOfY - 1);
4033 }
4034 var x = this.pagesMatrix.getPageStats(pageX, 0).x;
4035 var y = this.pagesMatrix.getPageStats(0, pageY).y;
4036 return {
4037 x: x,
4038 y: y,
4039 pageX: pageX,
4040 pageY: pageY,
4041 };
4042 };
4043 SlidePages.prototype.resetLoopPage = function () {
4044 if (this.loopX) {
4045 if (this.currentPage.pageX === 0) {
4046 return {
4047 pageX: this.pagesMatrix.pageLengthOfX - 2,
4048 pageY: this.currentPage.pageY,
4049 };
4050 }
4051 if (this.currentPage.pageX === this.pagesMatrix.pageLengthOfX - 1) {
4052 return {
4053 pageX: 1,
4054 pageY: this.currentPage.pageY,
4055 };
4056 }
4057 }
4058 if (this.loopY) {
4059 if (this.currentPage.pageY === 0) {
4060 return {
4061 pageX: this.currentPage.pageX,
4062 pageY: this.pagesMatrix.pageLengthOfY - 2,
4063 };
4064 }
4065 if (this.currentPage.pageY === this.pagesMatrix.pageLengthOfY - 1) {
4066 return {
4067 pageX: this.currentPage.pageX,
4068 pageY: 1,
4069 };
4070 }
4071 }
4072 };
4073 SlidePages.prototype.getPageIndexByDirection = function (direction) {
4074 var x = this.currentPage.pageX;
4075 var y = this.currentPage.pageY;
4076 if (this.slideX) {
4077 x = direction === "negative" /* Negative */ ? x - 1 : x + 1;
4078 }
4079 if (this.slideY) {
4080 y = direction === "negative" /* Negative */ ? y - 1 : y + 1;
4081 }
4082 return {
4083 pageX: x,
4084 pageY: y,
4085 };
4086 };
4087 SlidePages.prototype.checkSlideLoop = function () {
4088 this.wannaLoop = this.slideOptions.loop;
4089 if (this.pagesMatrix.pageLengthOfX > 1) {
4090 this.slideX = true;
4091 }
4092 else {
4093 this.slideX = false;
4094 }
4095 if (this.pagesMatrix.pages[0] && this.pagesMatrix.pageLengthOfY > 1) {
4096 this.slideY = true;
4097 }
4098 else {
4099 this.slideY = false;
4100 }
4101 this.loopX = this.wannaLoop && this.slideX;
4102 this.loopY = this.wannaLoop && this.slideY;
4103 if (this.slideX && this.slideY) {
4104 warn('slide does not support two direction at the same time.');
4105 }
4106 };
4107 return SlidePages;
4108}());
4109
4110var sourcePrefix$4 = 'plugins.slide';
4111var propertiesMap$4 = [
4112 {
4113 key: 'next',
4114 name: 'next',
4115 },
4116 {
4117 key: 'prev',
4118 name: 'prev',
4119 },
4120 {
4121 key: 'goToPage',
4122 name: 'goToPage',
4123 },
4124 {
4125 key: 'getCurrentPage',
4126 name: 'getCurrentPage',
4127 },
4128 {
4129 key: 'startPlay',
4130 name: 'startPlay',
4131 },
4132 {
4133 key: 'pausePlay',
4134 name: 'pausePlay',
4135 },
4136];
4137var propertiesConfig$4 = propertiesMap$4.map(function (item) {
4138 return {
4139 key: item.key,
4140 sourceKey: sourcePrefix$4 + "." + item.name,
4141 };
4142});
4143
4144var samePage = function (p1, p2) {
4145 return p1.pageX === p2.pageX && p1.pageY === p2.pageY;
4146};
4147var Slide = /** @class */ (function () {
4148 function Slide(scroll) {
4149 this.scroll = scroll;
4150 this.cachedClonedPageDOM = [];
4151 this.resetLooping = false;
4152 this.autoplayTimer = 0;
4153 if (!this.satisfyInitialization()) {
4154 return;
4155 }
4156 this.init();
4157 }
4158 Slide.prototype.satisfyInitialization = function () {
4159 if (this.scroll.scroller.content.children.length <= 0) {
4160 warn("slide need at least one slide page to be initialised." +
4161 "please check your DOM layout.");
4162 return false;
4163 }
4164 return true;
4165 };
4166 Slide.prototype.init = function () {
4167 this.willChangeToPage = extend({}, BASE_PAGE);
4168 this.handleBScroll();
4169 this.handleOptions();
4170 this.handleHooks();
4171 this.createPages();
4172 };
4173 Slide.prototype.createPages = function () {
4174 this.pages = new SlidePages(this.scroll, this.options);
4175 };
4176 Slide.prototype.handleBScroll = function () {
4177 this.scroll.registerType(['slideWillChange', 'slidePageChanged']);
4178 this.scroll.proxy(propertiesConfig$4);
4179 };
4180 Slide.prototype.handleOptions = function () {
4181 var userOptions = (this.scroll.options.slide === true
4182 ? {}
4183 : this.scroll.options.slide);
4184 var defaultOptions = {
4185 loop: true,
4186 threshold: 0.1,
4187 speed: 400,
4188 easing: ease.bounce,
4189 listenFlick: true,
4190 autoplay: true,
4191 interval: 3000,
4192 startPageXIndex: 0,
4193 startPageYIndex: 0,
4194 };
4195 this.options = extend(defaultOptions, userOptions);
4196 };
4197 Slide.prototype.handleLoop = function (prevSlideContent) {
4198 var loop = this.options.loop;
4199 var slideContent = this.scroll.scroller.content;
4200 var currentSlidePagesLength = slideContent.children.length;
4201 // only should respect loop scene
4202 if (loop) {
4203 if (slideContent !== prevSlideContent) {
4204 this.resetLoopChangedStatus();
4205 this.removeClonedSlidePage(prevSlideContent);
4206 currentSlidePagesLength > 1 &&
4207 this.cloneFirstAndLastSlidePage(slideContent);
4208 }
4209 else {
4210 // many pages reduce to one page
4211 if (currentSlidePagesLength === 3 && this.initialised) {
4212 this.removeClonedSlidePage(slideContent);
4213 this.moreToOnePageInLoop = true;
4214 this.oneToMorePagesInLoop = false;
4215 }
4216 else if (currentSlidePagesLength > 1) {
4217 // one page increases to many page
4218 if (this.initialised && this.cachedClonedPageDOM.length === 0) {
4219 this.oneToMorePagesInLoop = true;
4220 this.moreToOnePageInLoop = false;
4221 }
4222 else {
4223 this.removeClonedSlidePage(slideContent);
4224 this.resetLoopChangedStatus();
4225 }
4226 this.cloneFirstAndLastSlidePage(slideContent);
4227 }
4228 else {
4229 this.resetLoopChangedStatus();
4230 }
4231 }
4232 }
4233 };
4234 Slide.prototype.resetLoopChangedStatus = function () {
4235 this.moreToOnePageInLoop = false;
4236 this.oneToMorePagesInLoop = false;
4237 };
4238 Slide.prototype.handleHooks = function () {
4239 var _this = this;
4240 var scrollHooks = this.scroll.hooks;
4241 var scrollerHooks = this.scroll.scroller.hooks;
4242 var listenFlick = this.options.listenFlick;
4243 this.prevContent = this.scroll.scroller.content;
4244 this.hooksFn = [];
4245 // scroll
4246 this.registerHooks(this.scroll, this.scroll.eventTypes.beforeScrollStart, this.pausePlay);
4247 this.registerHooks(this.scroll, this.scroll.eventTypes.scrollEnd, this.modifyCurrentPage);
4248 this.registerHooks(this.scroll, this.scroll.eventTypes.scrollEnd, this.startPlay);
4249 // for mousewheel event
4250 if (this.scroll.eventTypes.mousewheelMove) {
4251 this.registerHooks(this.scroll, this.scroll.eventTypes.mousewheelMove, function () {
4252 // prevent default action of mousewheelMove
4253 return true;
4254 });
4255 this.registerHooks(this.scroll, this.scroll.eventTypes.mousewheelEnd, function (delta) {
4256 if (delta.directionX === 1 /* Positive */ ||
4257 delta.directionY === 1 /* Positive */) {
4258 _this.next();
4259 }
4260 if (delta.directionX === -1 /* Negative */ ||
4261 delta.directionY === -1 /* Negative */) {
4262 _this.prev();
4263 }
4264 });
4265 }
4266 // scrollHooks
4267 this.registerHooks(scrollHooks, scrollHooks.eventTypes.refresh, this.refreshHandler);
4268 this.registerHooks(scrollHooks, scrollHooks.eventTypes.destroy, this.destroy);
4269 // scroller
4270 this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.beforeRefresh, function () {
4271 _this.handleLoop(_this.prevContent);
4272 _this.setSlideInlineStyle();
4273 });
4274 this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.momentum, this.modifyScrollMetaHandler);
4275 this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.scroll, this.scrollHandler);
4276 // a click operation will clearTimer, so restart a new one
4277 this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.checkClick, this.startPlay);
4278 if (listenFlick) {
4279 this.registerHooks(scrollerHooks, scrollerHooks.eventTypes.flick, this.flickHandler);
4280 }
4281 };
4282 Slide.prototype.startPlay = function () {
4283 var _this = this;
4284 var _a = this.options, interval = _a.interval, autoplay = _a.autoplay;
4285 if (autoplay) {
4286 clearTimeout(this.autoplayTimer);
4287 this.autoplayTimer = window.setTimeout(function () {
4288 _this.next();
4289 }, interval);
4290 }
4291 };
4292 Slide.prototype.pausePlay = function () {
4293 if (this.options.autoplay) {
4294 clearTimeout(this.autoplayTimer);
4295 }
4296 };
4297 Slide.prototype.setSlideInlineStyle = function () {
4298 var styleConfigurations = [
4299 {
4300 direction: 'scrollX',
4301 sizeType: 'offsetWidth',
4302 styleType: 'width',
4303 },
4304 {
4305 direction: 'scrollY',
4306 sizeType: 'offsetHeight',
4307 styleType: 'height',
4308 },
4309 ];
4310 var _a = this.scroll.scroller, slideContent = _a.content, slideWrapper = _a.wrapper;
4311 var scrollOptions = this.scroll.options;
4312 styleConfigurations.forEach(function (_a) {
4313 var direction = _a.direction, sizeType = _a.sizeType, styleType = _a.styleType;
4314 // wanna scroll in this direction
4315 if (scrollOptions[direction]) {
4316 var size = slideWrapper[sizeType];
4317 var children = slideContent.children;
4318 var length_1 = children.length;
4319 for (var i = 0; i < length_1; i++) {
4320 var slidePageDOM = children[i];
4321 slidePageDOM.style[styleType] = size + 'px';
4322 }
4323 slideContent.style[styleType] = size * length_1 + 'px';
4324 }
4325 });
4326 };
4327 Slide.prototype.next = function (time, easing) {
4328 var _a = this.pages.nextPageIndex(), pageX = _a.pageX, pageY = _a.pageY;
4329 this.goTo(pageX, pageY, time, easing);
4330 };
4331 Slide.prototype.prev = function (time, easing) {
4332 var _a = this.pages.prevPageIndex(), pageX = _a.pageX, pageY = _a.pageY;
4333 this.goTo(pageX, pageY, time, easing);
4334 };
4335 Slide.prototype.goToPage = function (pageX, pageY, time, easing) {
4336 var pageIndex = this.pages.getValidPageIndex(pageX, pageY);
4337 this.goTo(pageIndex.pageX, pageIndex.pageY, time, easing);
4338 };
4339 Slide.prototype.getCurrentPage = function () {
4340 return this.exposedPage || this.pages.getInitialPage(false, true);
4341 };
4342 Slide.prototype.setCurrentPage = function (page) {
4343 this.pages.setCurrentPage(page);
4344 this.exposedPage = this.pages.getExposedPage(page);
4345 };
4346 Slide.prototype.nearestPage = function (x, y) {
4347 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
4348 var maxScrollPosX = scrollBehaviorX.maxScrollPos, minScrollPosX = scrollBehaviorX.minScrollPos;
4349 var maxScrollPosY = scrollBehaviorY.maxScrollPos, minScrollPosY = scrollBehaviorY.minScrollPos;
4350 return this.pages.getNearestPage(between(x, maxScrollPosX, minScrollPosX), between(y, maxScrollPosY, minScrollPosY));
4351 };
4352 Slide.prototype.satisfyThreshold = function (x, y) {
4353 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
4354 var satisfied = true;
4355 if (Math.abs(x - scrollBehaviorX.absStartPos) <= this.thresholdX &&
4356 Math.abs(y - scrollBehaviorY.absStartPos) <= this.thresholdY) {
4357 satisfied = false;
4358 }
4359 return satisfied;
4360 };
4361 Slide.prototype.refreshHandler = function (content) {
4362 var _this = this;
4363 if (!this.satisfyInitialization()) {
4364 return;
4365 }
4366 this.pages.refresh();
4367 this.computeThreshold();
4368 var contentChanged = (this.contentChanged = this.prevContent !== content);
4369 if (contentChanged) {
4370 this.prevContent = content;
4371 }
4372 var initPage = this.pages.getInitialPage(this.oneToMorePagesInLoop || this.moreToOnePageInLoop, contentChanged || !this.initialised);
4373 if (this.initialised) {
4374 this.goTo(initPage.pageX, initPage.pageY, 0);
4375 }
4376 else {
4377 this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.beforeInitialScrollTo, function (position) {
4378 _this.initialised = true;
4379 position.x = initPage.x;
4380 position.y = initPage.y;
4381 });
4382 }
4383 this.startPlay();
4384 };
4385 Slide.prototype.computeThreshold = function () {
4386 var threshold = this.options.threshold;
4387 // Integer
4388 if (threshold % 1 === 0) {
4389 this.thresholdX = threshold;
4390 this.thresholdY = threshold;
4391 }
4392 else {
4393 // decimal
4394 var _a = this.pages.getPageStats(), width = _a.width, height = _a.height;
4395 this.thresholdX = Math.round(width * threshold);
4396 this.thresholdY = Math.round(height * threshold);
4397 }
4398 };
4399 Slide.prototype.cloneFirstAndLastSlidePage = function (slideContent) {
4400 var children = slideContent.children;
4401 var preprendDOM = children[children.length - 1].cloneNode(true);
4402 var appendDOM = children[0].cloneNode(true);
4403 prepend(preprendDOM, slideContent);
4404 slideContent.appendChild(appendDOM);
4405 this.cachedClonedPageDOM = [preprendDOM, appendDOM];
4406 };
4407 Slide.prototype.removeClonedSlidePage = function (slideContent) {
4408 // maybe slideContent has removed from DOM Tree
4409 var slidePages = (slideContent && slideContent.children) || [];
4410 if (slidePages.length) {
4411 this.cachedClonedPageDOM.forEach(function (el) {
4412 removeChild(slideContent, el);
4413 });
4414 }
4415 this.cachedClonedPageDOM = [];
4416 };
4417 Slide.prototype.modifyCurrentPage = function (point) {
4418 var _a = this.getCurrentPage(), prevExposedPageX = _a.pageX, prevExposedPageY = _a.pageY;
4419 var newPage = this.nearestPage(point.x, point.y);
4420 this.setCurrentPage(newPage);
4421 /* istanbul ignore if */
4422 if (this.contentChanged) {
4423 this.contentChanged = false;
4424 return true;
4425 }
4426 var _b = this.getCurrentPage(), currentExposedPageX = _b.pageX, currentExposedPageY = _b.pageY;
4427 this.pageWillChangeTo(newPage);
4428 // loop is true, and one page becomes many pages when call bs.refresh
4429 if (this.oneToMorePagesInLoop) {
4430 this.oneToMorePagesInLoop = false;
4431 return true;
4432 }
4433 // loop is true, and many page becomes one page when call bs.refresh
4434 // if prevPage > 0, dispatch slidePageChanged and scrollEnd events
4435 /* istanbul ignore if */
4436 if (this.moreToOnePageInLoop &&
4437 prevExposedPageX === 0 &&
4438 prevExposedPageY === 0) {
4439 this.moreToOnePageInLoop = false;
4440 return true;
4441 }
4442 if (prevExposedPageX !== currentExposedPageX ||
4443 prevExposedPageY !== currentExposedPageY) {
4444 // only trust pageX & pageY when loop is true
4445 var page = this.pages.getExposedPageByPageIndex(currentExposedPageX, currentExposedPageY);
4446 this.scroll.trigger(this.scroll.eventTypes.slidePageChanged, page);
4447 }
4448 // triggered by resetLoop
4449 if (this.resetLooping) {
4450 this.resetLooping = false;
4451 return;
4452 }
4453 var changePage = this.pages.resetLoopPage();
4454 if (changePage) {
4455 this.resetLooping = true;
4456 this.goTo(changePage.pageX, changePage.pageY, 0);
4457 // stop user's scrollEnd
4458 // since it is a seamless scroll
4459 return true;
4460 }
4461 };
4462 Slide.prototype.goTo = function (pageX, pageY, time, easing) {
4463 var newPage = this.pages.getInternalPage(pageX, pageY);
4464 var scrollEasing = easing || this.options.easing || ease.bounce;
4465 var x = newPage.x, y = newPage.y;
4466 var deltaX = x - this.scroll.scroller.scrollBehaviorX.currentPos;
4467 var deltaY = y - this.scroll.scroller.scrollBehaviorY.currentPos;
4468 /* istanbul ignore if */
4469 if (!deltaX && !deltaY) {
4470 this.scroll.scroller.togglePointerEvents(true);
4471 return;
4472 }
4473 time = time === undefined ? this.getEaseTime(deltaX, deltaY) : time;
4474 this.scroll.scroller.scrollTo(x, y, time, scrollEasing);
4475 };
4476 Slide.prototype.flickHandler = function () {
4477 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
4478 var currentPosX = scrollBehaviorX.currentPos, startPosX = scrollBehaviorX.startPos, directionX = scrollBehaviorX.direction;
4479 var currentPosY = scrollBehaviorY.currentPos, startPosY = scrollBehaviorY.startPos, directionY = scrollBehaviorY.direction;
4480 var _b = this.pages.currentPage, pageX = _b.pageX, pageY = _b.pageY;
4481 var time = this.getEaseTime(currentPosX - startPosX, currentPosY - startPosY);
4482 this.goTo(pageX + directionX, pageY + directionY, time);
4483 };
4484 Slide.prototype.getEaseTime = function (deltaX, deltaY) {
4485 return (this.options.speed ||
4486 Math.max(Math.max(Math.min(Math.abs(deltaX), 1000), Math.min(Math.abs(deltaY), 1000)), 300));
4487 };
4488 Slide.prototype.modifyScrollMetaHandler = function (scrollMeta) {
4489 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY, animater = _a.animater;
4490 var newX = scrollMeta.newX;
4491 var newY = scrollMeta.newY;
4492 var newPage = this.satisfyThreshold(newX, newY) || animater.forceStopped
4493 ? this.pages.getPageByDirection(this.nearestPage(newX, newY), scrollBehaviorX.direction, scrollBehaviorY.direction)
4494 : this.pages.currentPage;
4495 scrollMeta.time = this.getEaseTime(scrollMeta.newX - newPage.x, scrollMeta.newY - newPage.y);
4496 scrollMeta.newX = newPage.x;
4497 scrollMeta.newY = newPage.y;
4498 scrollMeta.easing = this.options.easing || ease.bounce;
4499 };
4500 Slide.prototype.scrollHandler = function (_a) {
4501 var x = _a.x, y = _a.y;
4502 if (this.satisfyThreshold(x, y)) {
4503 var newPage = this.nearestPage(x, y);
4504 this.pageWillChangeTo(newPage);
4505 }
4506 };
4507 Slide.prototype.pageWillChangeTo = function (newPage) {
4508 var changeToPage = this.pages.getWillChangedPage(newPage);
4509 if (!samePage(this.willChangeToPage, changeToPage)) {
4510 this.willChangeToPage = changeToPage;
4511 this.scroll.trigger(this.scroll.eventTypes.slideWillChange, this.willChangeToPage);
4512 }
4513 };
4514 Slide.prototype.registerHooks = function (hooks, name, handler) {
4515 hooks.on(name, handler, this);
4516 this.hooksFn.push([hooks, name, handler]);
4517 };
4518 Slide.prototype.destroy = function () {
4519 var slideContent = this.scroll.scroller.content;
4520 var _a = this.options, loop = _a.loop, autoplay = _a.autoplay;
4521 if (loop) {
4522 this.removeClonedSlidePage(slideContent);
4523 }
4524 if (autoplay) {
4525 clearTimeout(this.autoplayTimer);
4526 }
4527 this.hooksFn.forEach(function (item) {
4528 var hooks = item[0];
4529 var hooksName = item[1];
4530 var handlerFn = item[2];
4531 if (hooks.eventTypes[hooksName]) {
4532 hooks.off(hooksName, handlerFn);
4533 }
4534 });
4535 this.hooksFn.length = 0;
4536 };
4537 Slide.pluginName = 'slide';
4538 return Slide;
4539}());
4540
4541var sourcePrefix$3 = 'plugins.wheel';
4542var propertiesMap$3 = [
4543 {
4544 key: 'wheelTo',
4545 name: 'wheelTo',
4546 },
4547 {
4548 key: 'getSelectedIndex',
4549 name: 'getSelectedIndex',
4550 },
4551 {
4552 key: 'restorePosition',
4553 name: 'restorePosition',
4554 },
4555];
4556var propertiesConfig$3 = propertiesMap$3.map(function (item) {
4557 return {
4558 key: item.key,
4559 sourceKey: sourcePrefix$3 + "." + item.name,
4560 };
4561});
4562
4563var WHEEL_INDEX_CHANGED_EVENT_NAME = 'wheelIndexChanged';
4564var CONSTANTS = {
4565 rate: 4
4566};
4567var Wheel = /** @class */ (function () {
4568 function Wheel(scroll) {
4569 this.scroll = scroll;
4570 this.init();
4571 }
4572 Wheel.prototype.init = function () {
4573 this.handleBScroll();
4574 this.handleOptions();
4575 this.handleHooks();
4576 // init boundary for Wheel
4577 this.refreshBoundary();
4578 this.setSelectedIndex(this.options.selectedIndex);
4579 };
4580 Wheel.prototype.handleBScroll = function () {
4581 this.scroll.proxy(propertiesConfig$3);
4582 this.scroll.registerType([WHEEL_INDEX_CHANGED_EVENT_NAME]);
4583 };
4584 Wheel.prototype.handleOptions = function () {
4585 var userOptions = (this.scroll.options.wheel === true
4586 ? {}
4587 : this.scroll.options.wheel);
4588 var defaultOptions = {
4589 wheelWrapperClass: 'wheel-scroll',
4590 wheelItemClass: 'wheel-item',
4591 rotate: 25,
4592 adjustTime: 400,
4593 selectedIndex: 0,
4594 wheelDisabledItemClass: 'wheel-disabled-item'
4595 };
4596 this.options = extend(defaultOptions, userOptions);
4597 };
4598 Wheel.prototype.handleHooks = function () {
4599 var _this = this;
4600 var scroll = this.scroll;
4601 var scroller = this.scroll.scroller;
4602 var actionsHandler = scroller.actionsHandler, scrollBehaviorX = scroller.scrollBehaviorX, scrollBehaviorY = scroller.scrollBehaviorY, animater = scroller.animater;
4603 var prevContent = scroller.content;
4604 // BScroll
4605 scroll.on(scroll.eventTypes.scrollEnd, function (position) {
4606 var index = _this.findNearestValidWheel(position.y).index;
4607 if (scroller.animater.forceStopped && !_this.isAdjustingPosition) {
4608 _this.target = _this.items[index];
4609 // since stopped from an animation.
4610 // prevent user's scrollEnd callback triggered twice
4611 return true;
4612 }
4613 else {
4614 _this.setSelectedIndex(index);
4615 if (_this.isAdjustingPosition) {
4616 _this.isAdjustingPosition = false;
4617 }
4618 }
4619 });
4620 // BScroll.hooks
4621 this.scroll.hooks.on(this.scroll.hooks.eventTypes.refresh, function (content) {
4622 if (content !== prevContent) {
4623 prevContent = content;
4624 _this.setSelectedIndex(_this.options.selectedIndex, true);
4625 }
4626 // rotate all wheel-items
4627 // because position may not change
4628 _this.rotateX(_this.scroll.y);
4629 // check we are stop at a disable item or not
4630 _this.wheelTo(_this.selectedIndex, 0);
4631 });
4632 this.scroll.hooks.on(this.scroll.hooks.eventTypes.beforeInitialScrollTo, function (position) {
4633 // selectedIndex has higher priority than bs.options.startY
4634 position.x = 0;
4635 position.y = -(_this.selectedIndex * _this.itemHeight);
4636 });
4637 // Scroller
4638 scroller.hooks.on(scroller.hooks.eventTypes.checkClick, function () {
4639 var index = HTMLCollectionToArray(_this.items).indexOf(_this.target);
4640 if (index === -1)
4641 return true;
4642 _this.wheelTo(index, _this.options.adjustTime, ease.swipe);
4643 return true;
4644 });
4645 scroller.hooks.on(scroller.hooks.eventTypes.scrollTo, function (endPoint) {
4646 endPoint.y = _this.findNearestValidWheel(endPoint.y).y;
4647 });
4648 // when content is scrolling
4649 // click wheel-item DOM repeatedly and crazily will cause scrollEnd not triggered
4650 // so reset forceStopped
4651 scroller.hooks.on(scroller.hooks.eventTypes.minDistanceScroll, function () {
4652 var animater = scroller.animater;
4653 if (animater.forceStopped === true) {
4654 animater.forceStopped = false;
4655 }
4656 });
4657 scroller.hooks.on(scroller.hooks.eventTypes.scrollToElement, function (el, pos) {
4658 if (!hasClass(el, _this.options.wheelItemClass)) {
4659 return true;
4660 }
4661 else {
4662 pos.top = _this.findNearestValidWheel(pos.top).y;
4663 }
4664 });
4665 // ActionsHandler
4666 actionsHandler.hooks.on(actionsHandler.hooks.eventTypes.beforeStart, function (e) {
4667 _this.target = e.target;
4668 });
4669 // ScrollBehaviorX
4670 // Wheel has no x direction now
4671 scrollBehaviorX.hooks.on(scrollBehaviorX.hooks.eventTypes.computeBoundary, function (boundary) {
4672 boundary.maxScrollPos = 0;
4673 boundary.minScrollPos = 0;
4674 });
4675 // ScrollBehaviorY
4676 scrollBehaviorY.hooks.on(scrollBehaviorY.hooks.eventTypes.computeBoundary, function (boundary) {
4677 _this.items = _this.scroll.scroller.content.children;
4678 _this.checkWheelAllDisabled();
4679 _this.itemHeight =
4680 _this.items.length > 0
4681 ? scrollBehaviorY.contentSize / _this.items.length
4682 : 0;
4683 boundary.maxScrollPos = -_this.itemHeight * (_this.items.length - 1);
4684 boundary.minScrollPos = 0;
4685 });
4686 scrollBehaviorY.hooks.on(scrollBehaviorY.hooks.eventTypes.momentum, function (momentumInfo) {
4687 momentumInfo.rate = CONSTANTS.rate;
4688 momentumInfo.destination = _this.findNearestValidWheel(momentumInfo.destination).y;
4689 });
4690 scrollBehaviorY.hooks.on(scrollBehaviorY.hooks.eventTypes.end, function (momentumInfo) {
4691 var validWheel = _this.findNearestValidWheel(scrollBehaviorY.currentPos);
4692 momentumInfo.destination = validWheel.y;
4693 momentumInfo.duration = _this.options.adjustTime;
4694 });
4695 // Animater
4696 animater.hooks.on(animater.hooks.eventTypes.time, function (time) {
4697 _this.transitionDuration(time);
4698 });
4699 animater.hooks.on(animater.hooks.eventTypes.timeFunction, function (easing) {
4700 _this.timeFunction(easing);
4701 });
4702 // bs.stop() to make wheel stop at a correct position when pending
4703 animater.hooks.on(animater.hooks.eventTypes.callStop, function () {
4704 var index = _this.findNearestValidWheel(_this.scroll.y).index;
4705 _this.isAdjustingPosition = true;
4706 _this.wheelTo(index, 0);
4707 });
4708 // Translater
4709 animater.translater.hooks.on(animater.translater.hooks.eventTypes.translate, function (endPoint) {
4710 _this.rotateX(endPoint.y);
4711 });
4712 };
4713 Wheel.prototype.refreshBoundary = function () {
4714 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY, content = _a.content;
4715 scrollBehaviorX.refresh(content);
4716 scrollBehaviorY.refresh(content);
4717 };
4718 Wheel.prototype.setSelectedIndex = function (index, contentChanged) {
4719 if (contentChanged === void 0) { contentChanged = false; }
4720 var prevSelectedIndex = this.selectedIndex;
4721 this.selectedIndex = index;
4722 // if content DOM changed, should not trigger event
4723 if (prevSelectedIndex !== index && !contentChanged) {
4724 this.scroll.trigger(WHEEL_INDEX_CHANGED_EVENT_NAME, index);
4725 }
4726 };
4727 Wheel.prototype.getSelectedIndex = function () {
4728 return this.selectedIndex;
4729 };
4730 Wheel.prototype.wheelTo = function (index, time, ease) {
4731 if (index === void 0) { index = 0; }
4732 if (time === void 0) { time = 0; }
4733 var y = -index * this.itemHeight;
4734 this.scroll.scrollTo(0, y, time, ease);
4735 };
4736 Wheel.prototype.restorePosition = function () {
4737 // bs is scrolling
4738 var isPending = this.scroll.pending;
4739 if (isPending) {
4740 var selectedIndex = this.getSelectedIndex();
4741 this.scroll.scroller.animater.clearTimer();
4742 this.wheelTo(selectedIndex, 0);
4743 }
4744 };
4745 Wheel.prototype.transitionDuration = function (time) {
4746 for (var i = 0; i < this.items.length; i++) {
4747 this.items[i].style[style.transitionDuration] =
4748 time + 'ms';
4749 }
4750 };
4751 Wheel.prototype.timeFunction = function (easing) {
4752 for (var i = 0; i < this.items.length; i++) {
4753 this.items[i].style[style.transitionTimingFunction] = easing;
4754 }
4755 };
4756 Wheel.prototype.rotateX = function (y) {
4757 var _a = this.options.rotate, rotate = _a === void 0 ? 25 : _a;
4758 for (var i = 0; i < this.items.length; i++) {
4759 var deg = rotate * (y / this.itemHeight + i);
4760 // Too small value is invalid in some phones, issue 1026
4761 var SafeDeg = deg.toFixed(3);
4762 this.items[i].style[style.transform] = "rotateX(" + SafeDeg + "deg)";
4763 }
4764 };
4765 Wheel.prototype.findNearestValidWheel = function (y) {
4766 y = y > 0 ? 0 : y < this.scroll.maxScrollY ? this.scroll.maxScrollY : y;
4767 var currentIndex = Math.abs(Math.round(-y / this.itemHeight));
4768 var cacheIndex = currentIndex;
4769 var items = this.items;
4770 var wheelDisabledItemClassName = this.options
4771 .wheelDisabledItemClass;
4772 // implement web native select element
4773 // first, check whether there is a enable item whose index is smaller than currentIndex
4774 // then, check whether there is a enable item whose index is bigger than currentIndex
4775 // otherwise, there are all disabled items, just keep currentIndex unchange
4776 while (currentIndex >= 0) {
4777 if (!hasClass(items[currentIndex], wheelDisabledItemClassName)) {
4778 break;
4779 }
4780 currentIndex--;
4781 }
4782 if (currentIndex < 0) {
4783 currentIndex = cacheIndex;
4784 while (currentIndex <= items.length - 1) {
4785 if (!hasClass(items[currentIndex], wheelDisabledItemClassName)) {
4786 break;
4787 }
4788 currentIndex++;
4789 }
4790 }
4791 // keep it unchange when all the items are disabled
4792 if (currentIndex === items.length) {
4793 currentIndex = cacheIndex;
4794 }
4795 // when all the items are disabled, selectedIndex should always be -1
4796 return {
4797 index: this.wheelItemsAllDisabled ? -1 : currentIndex,
4798 y: -currentIndex * this.itemHeight
4799 };
4800 };
4801 Wheel.prototype.checkWheelAllDisabled = function () {
4802 var wheelDisabledItemClassName = this.options.wheelDisabledItemClass;
4803 var items = this.items;
4804 this.wheelItemsAllDisabled = true;
4805 for (var i = 0; i < items.length; i++) {
4806 if (!hasClass(items[i], wheelDisabledItemClassName)) {
4807 this.wheelItemsAllDisabled = false;
4808 break;
4809 }
4810 }
4811 };
4812 Wheel.pluginName = 'wheel';
4813 return Wheel;
4814}());
4815
4816var sourcePrefix$2 = 'plugins.zoom';
4817var propertiesMap$2 = [
4818 {
4819 key: 'zoomTo',
4820 name: 'zoomTo'
4821 }
4822];
4823var propertiesConfig$2 = propertiesMap$2.map(function (item) {
4824 return {
4825 key: item.key,
4826 sourceKey: sourcePrefix$2 + "." + item.name
4827 };
4828});
4829
4830var TWO_FINGERS = 2;
4831var RAW_SCALE = 1;
4832var Zoom = /** @class */ (function () {
4833 function Zoom(scroll) {
4834 this.scroll = scroll;
4835 this.scale = RAW_SCALE;
4836 this.prevScale = 1;
4837 this.init();
4838 }
4839 Zoom.prototype.init = function () {
4840 this.handleBScroll();
4841 this.handleOptions();
4842 this.handleHooks();
4843 this.tryInitialZoomTo(this.zoomOpt);
4844 };
4845 Zoom.prototype.zoomTo = function (scale, x, y, bounceTime) {
4846 var _a = this.resolveOrigin(x, y), originX = _a.originX, originY = _a.originY;
4847 var origin = {
4848 x: originX,
4849 y: originY,
4850 baseScale: this.scale,
4851 };
4852 this._doZoomTo(scale, origin, bounceTime, true);
4853 };
4854 Zoom.prototype.handleBScroll = function () {
4855 this.scroll.proxy(propertiesConfig$2);
4856 this.scroll.registerType([
4857 'beforeZoomStart',
4858 'zoomStart',
4859 'zooming',
4860 'zoomEnd',
4861 ]);
4862 };
4863 Zoom.prototype.handleOptions = function () {
4864 var userOptions = (this.scroll.options.zoom === true
4865 ? {}
4866 : this.scroll.options.zoom);
4867 var defaultOptions = {
4868 start: 1,
4869 min: 1,
4870 max: 4,
4871 initialOrigin: [0, 0],
4872 minimalZoomDistance: 5,
4873 bounceTime: 800,
4874 };
4875 this.zoomOpt = extend(defaultOptions, userOptions);
4876 };
4877 Zoom.prototype.handleHooks = function () {
4878 var _this = this;
4879 var scroll = this.scroll;
4880 var scroller = this.scroll.scroller;
4881 this.wrapper = this.scroll.scroller.wrapper;
4882 this.setTransformOrigin(this.scroll.scroller.content);
4883 var scrollBehaviorX = scroller.scrollBehaviorX;
4884 var scrollBehaviorY = scroller.scrollBehaviorY;
4885 this.hooksFn = [];
4886 // BScroll
4887 this.registerHooks(scroll.hooks, scroll.hooks.eventTypes.contentChanged, function (content) {
4888 _this.setTransformOrigin(content);
4889 _this.scale = RAW_SCALE;
4890 _this.tryInitialZoomTo(_this.zoomOpt);
4891 });
4892 this.registerHooks(scroll.hooks, scroll.hooks.eventTypes.beforeInitialScrollTo, function () {
4893 // if perform a zoom action, we should prevent initial scroll when initialised
4894 if (_this.zoomOpt.start !== RAW_SCALE) {
4895 return true;
4896 }
4897 });
4898 // enlarge boundary
4899 this.registerHooks(scrollBehaviorX.hooks, scrollBehaviorX.hooks.eventTypes.beforeComputeBoundary, function () {
4900 // content may change, don't cache it's size
4901 var contentSize = getRect(_this.scroll.scroller.content);
4902 scrollBehaviorX.contentSize = Math.floor(contentSize.width * _this.scale);
4903 });
4904 this.registerHooks(scrollBehaviorY.hooks, scrollBehaviorY.hooks.eventTypes.beforeComputeBoundary, function () {
4905 // content may change, don't cache it's size
4906 var contentSize = getRect(_this.scroll.scroller.content);
4907 scrollBehaviorY.contentSize = Math.floor(contentSize.height * _this.scale);
4908 });
4909 // touch event
4910 this.registerHooks(scroller.actions.hooks, scroller.actions.hooks.eventTypes.start, function (e) {
4911 var numberOfFingers = (e.touches && e.touches.length) || 0;
4912 _this.fingersOperation(numberOfFingers);
4913 if (numberOfFingers === TWO_FINGERS) {
4914 _this.zoomStart(e);
4915 }
4916 });
4917 this.registerHooks(scroller.actions.hooks, scroller.actions.hooks.eventTypes.beforeMove, function (e) {
4918 var numberOfFingers = (e.touches && e.touches.length) || 0;
4919 _this.fingersOperation(numberOfFingers);
4920 if (numberOfFingers === TWO_FINGERS) {
4921 _this.zoom(e);
4922 return true;
4923 }
4924 });
4925 this.registerHooks(scroller.actions.hooks, scroller.actions.hooks.eventTypes.beforeEnd, function (e) {
4926 var numberOfFingers = _this.fingersOperation();
4927 if (numberOfFingers === TWO_FINGERS) {
4928 _this.zoomEnd();
4929 return true;
4930 }
4931 });
4932 this.registerHooks(scroller.translater.hooks, scroller.translater.hooks.eventTypes.beforeTranslate, function (transformStyle, point) {
4933 var scale = point.scale ? point.scale : _this.prevScale;
4934 _this.prevScale = scale;
4935 transformStyle.push("scale(" + scale + ")");
4936 });
4937 this.registerHooks(scroller.hooks, scroller.hooks.eventTypes.scrollEnd, function () {
4938 if (_this.fingersOperation() === TWO_FINGERS) {
4939 _this.scroll.trigger(_this.scroll.eventTypes.zoomEnd, {
4940 scale: _this.scale,
4941 });
4942 }
4943 });
4944 this.registerHooks(this.scroll.hooks, 'destroy', this.destroy);
4945 };
4946 Zoom.prototype.setTransformOrigin = function (content) {
4947 content.style[style.transformOrigin] = '0 0';
4948 };
4949 Zoom.prototype.tryInitialZoomTo = function (options) {
4950 var start = options.start, initialOrigin = options.initialOrigin;
4951 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
4952 if (start !== RAW_SCALE) {
4953 // Movable plugin may wanna modify minScrollPos or maxScrollPos
4954 // so we force Movable to caculate them
4955 this.resetBoundaries([scrollBehaviorX, scrollBehaviorY]);
4956 this.zoomTo(start, initialOrigin[0], initialOrigin[1], 0);
4957 }
4958 };
4959 // getter or setter operation
4960 Zoom.prototype.fingersOperation = function (amounts) {
4961 if (typeof amounts === 'number') {
4962 this.numberOfFingers = amounts;
4963 }
4964 else {
4965 return this.numberOfFingers;
4966 }
4967 };
4968 Zoom.prototype._doZoomTo = function (scale, origin, time, useCurrentPos) {
4969 var _this = this;
4970 if (time === void 0) { time = this.zoomOpt.bounceTime; }
4971 if (useCurrentPos === void 0) { useCurrentPos = false; }
4972 var _a = this.zoomOpt, min = _a.min, max = _a.max;
4973 var fromScale = this.scale;
4974 var toScale = between(scale, min, max);
4975 (function () {
4976 if (time === 0) {
4977 _this.scroll.trigger(_this.scroll.eventTypes.zooming, {
4978 scale: toScale,
4979 });
4980 return;
4981 }
4982 if (time > 0) {
4983 var timer_1;
4984 var startTime_1 = getNow();
4985 var endTime_1 = startTime_1 + time;
4986 var scheduler_1 = function () {
4987 var now = getNow();
4988 if (now >= endTime_1) {
4989 _this.scroll.trigger(_this.scroll.eventTypes.zooming, {
4990 scale: toScale,
4991 });
4992 cancelAnimationFrame(timer_1);
4993 return;
4994 }
4995 var ratio = ease.bounce.fn((now - startTime_1) / time);
4996 var currentScale = ratio * (toScale - fromScale) + fromScale;
4997 _this.scroll.trigger(_this.scroll.eventTypes.zooming, {
4998 scale: currentScale,
4999 });
5000 timer_1 = requestAnimationFrame(scheduler_1);
5001 };
5002 // start scheduler job
5003 scheduler_1();
5004 }
5005 })();
5006 // suppose you are zooming by two fingers
5007 this.fingersOperation(2);
5008 this._zoomTo(toScale, fromScale, origin, time, useCurrentPos);
5009 };
5010 Zoom.prototype._zoomTo = function (toScale, fromScale, origin, time, useCurrentPos) {
5011 if (useCurrentPos === void 0) { useCurrentPos = false; }
5012 var ratio = toScale / origin.baseScale;
5013 this.setScale(toScale);
5014 var scroller = this.scroll.scroller;
5015 var scrollBehaviorX = scroller.scrollBehaviorX, scrollBehaviorY = scroller.scrollBehaviorY;
5016 this.resetBoundaries([scrollBehaviorX, scrollBehaviorY]);
5017 // position is restrained in boundary
5018 var newX = this.getNewPos(origin.x, ratio, scrollBehaviorX, true, useCurrentPos);
5019 var newY = this.getNewPos(origin.y, ratio, scrollBehaviorY, true, useCurrentPos);
5020 if (scrollBehaviorX.currentPos !== Math.round(newX) ||
5021 scrollBehaviorY.currentPos !== Math.round(newY) ||
5022 toScale !== fromScale) {
5023 scroller.scrollTo(newX, newY, time, ease.bounce, {
5024 start: {
5025 scale: fromScale,
5026 },
5027 end: {
5028 scale: toScale,
5029 },
5030 });
5031 }
5032 };
5033 Zoom.prototype.resolveOrigin = function (x, y) {
5034 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
5035 var resolveFormula = {
5036 left: function () {
5037 return 0;
5038 },
5039 top: function () {
5040 return 0;
5041 },
5042 right: function () {
5043 return scrollBehaviorX.contentSize;
5044 },
5045 bottom: function () {
5046 return scrollBehaviorY.contentSize;
5047 },
5048 center: function (index) {
5049 var baseSize = index === 0
5050 ? scrollBehaviorX.contentSize
5051 : scrollBehaviorY.contentSize;
5052 return baseSize / 2;
5053 },
5054 };
5055 return {
5056 originX: typeof x === 'number' ? x : resolveFormula[x](0),
5057 originY: typeof y === 'number' ? y : resolveFormula[y](1),
5058 };
5059 };
5060 Zoom.prototype.zoomStart = function (e) {
5061 var firstFinger = e.touches[0];
5062 var secondFinger = e.touches[1];
5063 this.startDistance = this.getFingerDistance(e);
5064 this.startScale = this.scale;
5065 var _a = offsetToBody(this.wrapper), left = _a.left, top = _a.top;
5066 this.origin = {
5067 x: Math.abs(firstFinger.pageX + secondFinger.pageX) / 2 +
5068 left -
5069 this.scroll.x,
5070 y: Math.abs(firstFinger.pageY + secondFinger.pageY) / 2 +
5071 top -
5072 this.scroll.y,
5073 baseScale: this.startScale,
5074 };
5075 this.scroll.trigger(this.scroll.eventTypes.beforeZoomStart);
5076 };
5077 Zoom.prototype.zoom = function (e) {
5078 var currentDistance = this.getFingerDistance(e);
5079 // at least minimalZoomDistance pixels for the zoom to initiate
5080 if (!this.zoomed &&
5081 Math.abs(currentDistance - this.startDistance) <
5082 this.zoomOpt.minimalZoomDistance) {
5083 return;
5084 }
5085 // when out of boundary , perform a damping algorithm
5086 var endScale = this.dampingScale((currentDistance / this.startDistance) * this.startScale);
5087 var ratio = endScale / this.startScale;
5088 this.setScale(endScale);
5089 if (!this.zoomed) {
5090 this.zoomed = true;
5091 this.scroll.trigger(this.scroll.eventTypes.zoomStart);
5092 }
5093 var scroller = this.scroll.scroller;
5094 var scrollBehaviorX = scroller.scrollBehaviorX, scrollBehaviorY = scroller.scrollBehaviorY;
5095 var x = this.getNewPos(this.origin.x, ratio, scrollBehaviorX, false, false);
5096 var y = this.getNewPos(this.origin.y, ratio, scrollBehaviorY, false, false);
5097 this.scroll.trigger(this.scroll.eventTypes.zooming, {
5098 scale: this.scale,
5099 });
5100 scroller.translater.translate({ x: x, y: y, scale: endScale });
5101 };
5102 Zoom.prototype.zoomEnd = function () {
5103 if (!this.zoomed)
5104 return;
5105 // if out of boundary, do rebound!
5106 if (this.shouldRebound()) {
5107 this._doZoomTo(this.scale, this.origin, this.zoomOpt.bounceTime);
5108 return;
5109 }
5110 this.scroll.trigger(this.scroll.eventTypes.zoomEnd, { scale: this.scale });
5111 };
5112 Zoom.prototype.getFingerDistance = function (e) {
5113 var firstFinger = e.touches[0];
5114 var secondFinger = e.touches[1];
5115 var deltaX = Math.abs(firstFinger.pageX - secondFinger.pageX);
5116 var deltaY = Math.abs(firstFinger.pageY - secondFinger.pageY);
5117 return getDistance(deltaX, deltaY);
5118 };
5119 Zoom.prototype.shouldRebound = function () {
5120 var _a = this.zoomOpt, min = _a.min, max = _a.max;
5121 var currentScale = this.scale;
5122 // scale exceeded!
5123 if (currentScale !== between(currentScale, min, max)) {
5124 return true;
5125 }
5126 var _b = this.scroll.scroller, scrollBehaviorX = _b.scrollBehaviorX, scrollBehaviorY = _b.scrollBehaviorY;
5127 // enlarge boundaries manually when zoom is end
5128 this.resetBoundaries([scrollBehaviorX, scrollBehaviorY]);
5129 var xInBoundary = scrollBehaviorX.checkInBoundary().inBoundary;
5130 var yInBoundary = scrollBehaviorX.checkInBoundary().inBoundary;
5131 return !(xInBoundary && yInBoundary);
5132 };
5133 Zoom.prototype.dampingScale = function (scale) {
5134 var _a = this.zoomOpt, min = _a.min, max = _a.max;
5135 if (scale < min) {
5136 scale = 0.5 * min * Math.pow(2.0, scale / min);
5137 }
5138 else if (scale > max) {
5139 scale = 2.0 * max * Math.pow(0.5, max / scale);
5140 }
5141 return scale;
5142 };
5143 Zoom.prototype.setScale = function (scale) {
5144 this.scale = scale;
5145 };
5146 Zoom.prototype.resetBoundaries = function (scrollBehaviorPairs) {
5147 scrollBehaviorPairs.forEach(function (behavior) { return behavior.computeBoundary(); });
5148 };
5149 Zoom.prototype.getNewPos = function (origin, lastScale, scrollBehavior, shouldInBoundary, useCurrentPos) {
5150 if (useCurrentPos === void 0) { useCurrentPos = false; }
5151 var newPos = origin -
5152 origin * lastScale +
5153 (useCurrentPos ? scrollBehavior.currentPos : scrollBehavior.startPos);
5154 if (shouldInBoundary) {
5155 newPos = between(newPos, scrollBehavior.maxScrollPos, scrollBehavior.minScrollPos);
5156 }
5157 // maxScrollPos or minScrollPos maybe a negative or positive digital
5158 return newPos > 0 ? Math.floor(newPos) : Math.ceil(newPos);
5159 };
5160 Zoom.prototype.registerHooks = function (hooks, name, handler) {
5161 hooks.on(name, handler, this);
5162 this.hooksFn.push([hooks, name, handler]);
5163 };
5164 Zoom.prototype.destroy = function () {
5165 this.hooksFn.forEach(function (item) {
5166 var hooks = item[0];
5167 var hooksName = item[1];
5168 var handlerFn = item[2];
5169 hooks.off(hooksName, handlerFn);
5170 });
5171 this.hooksFn.length = 0;
5172 };
5173 Zoom.pluginName = 'zoom';
5174 return Zoom;
5175}());
5176
5177var BScrollFamily = /** @class */ (function () {
5178 function BScrollFamily(scroll) {
5179 this.ancestors = [];
5180 this.descendants = [];
5181 this.hooksManager = [];
5182 this.analyzed = false;
5183 this.selfScroll = scroll;
5184 }
5185 BScrollFamily.create = function (scroll) {
5186 return new BScrollFamily(scroll);
5187 };
5188 BScrollFamily.prototype.hasAncestors = function (bscrollFamily) {
5189 var index = findIndex(this.ancestors, function (_a) {
5190 var item = _a[0];
5191 return item === bscrollFamily;
5192 });
5193 return index > -1;
5194 };
5195 BScrollFamily.prototype.hasDescendants = function (bscrollFamily) {
5196 var index = findIndex(this.descendants, function (_a) {
5197 var item = _a[0];
5198 return item === bscrollFamily;
5199 });
5200 return index > -1;
5201 };
5202 BScrollFamily.prototype.addAncestor = function (bscrollFamily, distance) {
5203 var ancestors = this.ancestors;
5204 ancestors.push([bscrollFamily, distance]);
5205 // by ascend
5206 ancestors.sort(function (a, b) {
5207 return a[1] - b[1];
5208 });
5209 };
5210 BScrollFamily.prototype.addDescendant = function (bscrollFamily, distance) {
5211 var descendants = this.descendants;
5212 descendants.push([bscrollFamily, distance]);
5213 // by ascend
5214 descendants.sort(function (a, b) {
5215 return a[1] - b[1];
5216 });
5217 };
5218 BScrollFamily.prototype.removeAncestor = function (bscrollFamily) {
5219 var ancestors = this.ancestors;
5220 if (ancestors.length) {
5221 var index = findIndex(this.ancestors, function (_a) {
5222 var item = _a[0];
5223 return item === bscrollFamily;
5224 });
5225 if (index > -1) {
5226 return ancestors.splice(index, 1);
5227 }
5228 }
5229 };
5230 BScrollFamily.prototype.removeDescendant = function (bscrollFamily) {
5231 var descendants = this.descendants;
5232 if (descendants.length) {
5233 var index = findIndex(this.descendants, function (_a) {
5234 var item = _a[0];
5235 return item === bscrollFamily;
5236 });
5237 if (index > -1) {
5238 return descendants.splice(index, 1);
5239 }
5240 }
5241 };
5242 BScrollFamily.prototype.registerHooks = function (hook, eventType, handler) {
5243 hook.on(eventType, handler);
5244 this.hooksManager.push([hook, eventType, handler]);
5245 };
5246 BScrollFamily.prototype.setAnalyzed = function (flag) {
5247 if (flag === void 0) { flag = false; }
5248 this.analyzed = flag;
5249 };
5250 BScrollFamily.prototype.purge = function () {
5251 var _this = this;
5252 // remove self from graph
5253 this.ancestors.forEach(function (_a) {
5254 var bscrollFamily = _a[0];
5255 bscrollFamily.removeDescendant(_this);
5256 });
5257 this.descendants.forEach(function (_a) {
5258 var bscrollFamily = _a[0];
5259 bscrollFamily.removeAncestor(_this);
5260 });
5261 // remove all hook handlers
5262 this.hooksManager.forEach(function (_a) {
5263 var hooks = _a[0], eventType = _a[1], handler = _a[2];
5264 hooks.off(eventType, handler);
5265 });
5266 this.hooksManager = [];
5267 };
5268 return BScrollFamily;
5269}());
5270
5271var sourcePrefix$1 = 'plugins.nestedScroll';
5272var propertiesMap$1 = [
5273 {
5274 key: 'purgeNestedScroll',
5275 name: 'purgeNestedScroll',
5276 },
5277];
5278var propertiesConfig$1 = propertiesMap$1.map(function (item) {
5279 return {
5280 key: item.key,
5281 sourceKey: sourcePrefix$1 + "." + item.name,
5282 };
5283});
5284
5285var DEFAUL_GROUP_ID = 'INTERNAL_NESTED_SCROLL';
5286var forceScrollStopHandler = function (scrolls) {
5287 scrolls.forEach(function (scroll) {
5288 if (scroll.pending) {
5289 scroll.stop();
5290 scroll.resetPosition();
5291 }
5292 });
5293};
5294var enableScrollHander = function (scrolls) {
5295 scrolls.forEach(function (scroll) {
5296 scroll.enable();
5297 });
5298};
5299var disableScrollHander = function (scrolls, currentScroll) {
5300 scrolls.forEach(function (scroll) {
5301 if (scroll.hasHorizontalScroll === currentScroll.hasHorizontalScroll ||
5302 scroll.hasVerticalScroll === currentScroll.hasVerticalScroll) {
5303 scroll.disable();
5304 }
5305 });
5306};
5307var syncTouchstartData = function (scrolls) {
5308 scrolls.forEach(function (scroll) {
5309 var _a = scroll.scroller, actions = _a.actions, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
5310 // prevent click triggering many times
5311 actions.fingerMoved = true;
5312 actions.contentMoved = false;
5313 actions.directionLockAction.reset();
5314 scrollBehaviorX.start();
5315 scrollBehaviorY.start();
5316 scrollBehaviorX.resetStartPos();
5317 scrollBehaviorY.resetStartPos();
5318 actions.startTime = +new Date();
5319 });
5320};
5321var isOutOfBoundary = function (scroll) {
5322 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;
5323 var ret = false;
5324 var outOfLeftBoundary = x >= minScrollX && movingDirectionX === -1 /* Negative */;
5325 var outOfRightBoundary = x <= maxScrollX && movingDirectionX === 1 /* Positive */;
5326 var outOfTopBoundary = y >= minScrollY && movingDirectionY === -1 /* Negative */;
5327 var outOfBottomBoundary = y <= maxScrollY && movingDirectionY === 1 /* Positive */;
5328 if (hasVerticalScroll) {
5329 ret = outOfTopBoundary || outOfBottomBoundary;
5330 }
5331 else if (hasHorizontalScroll) {
5332 ret = outOfLeftBoundary || outOfRightBoundary;
5333 }
5334 return ret;
5335};
5336var isResettingPosition = function (scroll) {
5337 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;
5338 var ret = false;
5339 var outOfLeftBoundary = x > minScrollX;
5340 var outOfRightBoundary = x < maxScrollX;
5341 var outOfTopBoundary = y > minScrollY;
5342 var outOfBottomBoundary = y < maxScrollY;
5343 if (hasVerticalScroll) {
5344 ret = outOfTopBoundary || outOfBottomBoundary;
5345 }
5346 else if (hasHorizontalScroll) {
5347 ret = outOfLeftBoundary || outOfRightBoundary;
5348 }
5349 return ret;
5350};
5351var resetPositionHandler = function (scroll) {
5352 scroll.scroller.reflow();
5353 scroll.resetPosition(0 /* Immediately */);
5354};
5355var calculateDistance = function (childNode, parentNode) {
5356 var distance = 0;
5357 var parent = childNode.parentNode;
5358 while (parent && parent !== parentNode) {
5359 distance++;
5360 parent = parent.parentNode;
5361 }
5362 return distance;
5363};
5364var NestedScroll = /** @class */ (function () {
5365 function NestedScroll(scroll) {
5366 var groupId = this.handleOptions(scroll);
5367 var instance = NestedScroll.instancesMap[groupId];
5368 if (!instance) {
5369 instance = NestedScroll.instancesMap[groupId] = this;
5370 instance.store = [];
5371 instance.hooksFn = [];
5372 }
5373 instance.init(scroll);
5374 return instance;
5375 }
5376 NestedScroll.getAllNestedScrolls = function () {
5377 var instancesMap = NestedScroll.instancesMap;
5378 return Object.keys(instancesMap).map(function (key) { return instancesMap[key]; });
5379 };
5380 NestedScroll.purgeAllNestedScrolls = function () {
5381 var nestedScrolls = NestedScroll.getAllNestedScrolls();
5382 nestedScrolls.forEach(function (ns) { return ns.purgeNestedScroll(); });
5383 };
5384 NestedScroll.prototype.handleOptions = function (scroll) {
5385 var userOptions = (scroll.options.nestedScroll === true
5386 ? {}
5387 : scroll.options.nestedScroll);
5388 var defaultOptions = {
5389 groupId: DEFAUL_GROUP_ID,
5390 };
5391 this.options = extend(defaultOptions, userOptions);
5392 var groupIdType = typeof this.options.groupId;
5393 if (groupIdType !== 'string' && groupIdType !== 'number') {
5394 warn('groupId must be string or number for NestedScroll plugin');
5395 }
5396 return this.options.groupId;
5397 };
5398 NestedScroll.prototype.init = function (scroll) {
5399 scroll.proxy(propertiesConfig$1);
5400 this.addBScroll(scroll);
5401 this.buildBScrollGraph();
5402 this.analyzeBScrollGraph();
5403 this.ensureEventInvokeSequence();
5404 this.handleHooks(scroll);
5405 };
5406 NestedScroll.prototype.handleHooks = function (scroll) {
5407 var _this = this;
5408 this.registerHooks(scroll.hooks, scroll.hooks.eventTypes.destroy, function () {
5409 _this.deleteScroll(scroll);
5410 });
5411 };
5412 NestedScroll.prototype.deleteScroll = function (scroll) {
5413 var wrapper = scroll.wrapper;
5414 wrapper.isBScrollContainer = undefined;
5415 var store = this.store;
5416 var hooksFn = this.hooksFn;
5417 var i = findIndex(store, function (bscrollFamily) {
5418 return bscrollFamily.selfScroll === scroll;
5419 });
5420 if (i > -1) {
5421 var bscrollFamily = store[i];
5422 bscrollFamily.purge();
5423 store.splice(i, 1);
5424 }
5425 var k = findIndex(hooksFn, function (_a) {
5426 var hooks = _a[0];
5427 return hooks === scroll.hooks;
5428 });
5429 if (k > -1) {
5430 var _a = hooksFn[k], hooks = _a[0], eventType = _a[1], handler = _a[2];
5431 hooks.off(eventType, handler);
5432 hooksFn.splice(k, 1);
5433 }
5434 };
5435 NestedScroll.prototype.addBScroll = function (scroll) {
5436 this.store.push(BScrollFamily.create(scroll));
5437 };
5438 NestedScroll.prototype.buildBScrollGraph = function () {
5439 var store = this.store;
5440 var bf1;
5441 var bf2;
5442 var wrapper1;
5443 var wrapper2;
5444 var len = this.store.length;
5445 // build graph
5446 for (var i = 0; i < len; i++) {
5447 bf1 = store[i];
5448 wrapper1 = bf1.selfScroll.wrapper;
5449 for (var j = 0; j < len; j++) {
5450 bf2 = store[j];
5451 wrapper2 = bf2.selfScroll.wrapper;
5452 // same bs
5453 if (bf1 === bf2)
5454 continue;
5455 if (!wrapper1.contains(wrapper2))
5456 continue;
5457 // bs1 contains bs2
5458 var distance = calculateDistance(wrapper2, wrapper1);
5459 if (!bf1.hasDescendants(bf2)) {
5460 bf1.addDescendant(bf2, distance);
5461 }
5462 if (!bf2.hasAncestors(bf1)) {
5463 bf2.addAncestor(bf1, distance);
5464 }
5465 }
5466 }
5467 };
5468 NestedScroll.prototype.analyzeBScrollGraph = function () {
5469 this.store.forEach(function (bscrollFamily) {
5470 if (bscrollFamily.analyzed) {
5471 return;
5472 }
5473 var ancestors = bscrollFamily.ancestors, descendants = bscrollFamily.descendants, currentScroll = bscrollFamily.selfScroll;
5474 var beforeScrollStartHandler = function () {
5475 // always get the latest scroll
5476 var ancestorScrolls = ancestors.map(function (_a) {
5477 var bscrollFamily = _a[0];
5478 return bscrollFamily.selfScroll;
5479 });
5480 var descendantScrolls = descendants.map(function (_a) {
5481 var bscrollFamily = _a[0];
5482 return bscrollFamily.selfScroll;
5483 });
5484 forceScrollStopHandler(__spreadArrays(ancestorScrolls, descendantScrolls));
5485 if (isResettingPosition(currentScroll)) {
5486 resetPositionHandler(currentScroll);
5487 }
5488 syncTouchstartData(ancestorScrolls);
5489 disableScrollHander(ancestorScrolls, currentScroll);
5490 };
5491 var touchEndHandler = function () {
5492 var ancestorScrolls = ancestors.map(function (_a) {
5493 var bscrollFamily = _a[0];
5494 return bscrollFamily.selfScroll;
5495 });
5496 var descendantScrolls = descendants.map(function (_a) {
5497 var bscrollFamily = _a[0];
5498 return bscrollFamily.selfScroll;
5499 });
5500 enableScrollHander(__spreadArrays(ancestorScrolls, descendantScrolls));
5501 };
5502 bscrollFamily.registerHooks(currentScroll, currentScroll.eventTypes.beforeScrollStart, beforeScrollStartHandler);
5503 bscrollFamily.registerHooks(currentScroll, currentScroll.eventTypes.touchEnd, touchEndHandler);
5504 var selfActionsHooks = currentScroll.scroller.actions.hooks;
5505 bscrollFamily.registerHooks(selfActionsHooks, selfActionsHooks.eventTypes.detectMovingDirection, function () {
5506 var ancestorScrolls = ancestors.map(function (_a) {
5507 var bscrollFamily = _a[0];
5508 return bscrollFamily.selfScroll;
5509 });
5510 var parentScroll = ancestorScrolls[0];
5511 var otherAncestorScrolls = ancestorScrolls.slice(1);
5512 var contentMoved = currentScroll.scroller.actions.contentMoved;
5513 var isTopScroll = ancestorScrolls.length === 0;
5514 if (contentMoved) {
5515 disableScrollHander(ancestorScrolls, currentScroll);
5516 }
5517 else if (!isTopScroll) {
5518 if (isOutOfBoundary(currentScroll)) {
5519 disableScrollHander([currentScroll], currentScroll);
5520 if (parentScroll) {
5521 enableScrollHander([parentScroll]);
5522 }
5523 disableScrollHander(otherAncestorScrolls, currentScroll);
5524 return true;
5525 }
5526 }
5527 });
5528 bscrollFamily.setAnalyzed(true);
5529 });
5530 };
5531 // make sure touchmove|touchend invoke from child to parent
5532 NestedScroll.prototype.ensureEventInvokeSequence = function () {
5533 var copied = this.store.slice();
5534 var sequencedScroll = copied.sort(function (a, b) {
5535 return a.descendants.length - b.descendants.length;
5536 });
5537 sequencedScroll.forEach(function (bscrollFamily) {
5538 var scroll = bscrollFamily.selfScroll;
5539 scroll.scroller.actionsHandler.rebindDOMEvents();
5540 });
5541 };
5542 NestedScroll.prototype.registerHooks = function (hooks, name, handler) {
5543 hooks.on(name, handler, this);
5544 this.hooksFn.push([hooks, name, handler]);
5545 };
5546 NestedScroll.prototype.purgeNestedScroll = function () {
5547 var groupId = this.options.groupId;
5548 this.store.forEach(function (bscrollFamily) {
5549 bscrollFamily.purge();
5550 });
5551 this.store = [];
5552 this.hooksFn.forEach(function (_a) {
5553 var hooks = _a[0], eventType = _a[1], handler = _a[2];
5554 hooks.off(eventType, handler);
5555 });
5556 this.hooksFn = [];
5557 delete NestedScroll.instancesMap[groupId];
5558 };
5559 NestedScroll.pluginName = 'nestedScroll';
5560 NestedScroll.instancesMap = {};
5561 return NestedScroll;
5562}());
5563
5564var PRE_NUM = 10;
5565var POST_NUM = 30;
5566var IndexCalculator = /** @class */ (function () {
5567 function IndexCalculator(wrapperHeight, tombstoneHeight) {
5568 this.wrapperHeight = wrapperHeight;
5569 this.tombstoneHeight = tombstoneHeight;
5570 this.lastDirection = 1 /* DOWN */;
5571 this.lastPos = 0;
5572 }
5573 IndexCalculator.prototype.calculate = function (pos, list) {
5574 var offset = pos - this.lastPos;
5575 this.lastPos = pos;
5576 var direction = this.getDirection(offset);
5577 // important! start index is much more important than end index.
5578 var start = this.calculateIndex(0, pos, list);
5579 var end = this.calculateIndex(start, pos + this.wrapperHeight, list);
5580 if (direction === 1 /* DOWN */) {
5581 start -= PRE_NUM;
5582 end += POST_NUM;
5583 }
5584 else {
5585 start -= POST_NUM;
5586 end += PRE_NUM;
5587 }
5588 if (start < 0) {
5589 start = 0;
5590 }
5591 return {
5592 start: start,
5593 end: end,
5594 };
5595 };
5596 IndexCalculator.prototype.getDirection = function (offset) {
5597 var direction;
5598 if (offset > 0) {
5599 direction = 1 /* DOWN */;
5600 }
5601 else if (offset < 0) {
5602 direction = 0 /* UP */;
5603 }
5604 else {
5605 return this.lastDirection;
5606 }
5607 this.lastDirection = direction;
5608 return direction;
5609 };
5610 IndexCalculator.prototype.calculateIndex = function (start, offset, list) {
5611 if (offset <= 0) {
5612 return start;
5613 }
5614 var i = start;
5615 var startPos = list[i] && list[i].pos !== -1 ? list[i].pos : 0;
5616 var lastPos = startPos;
5617 var tombstone = 0;
5618 while (i < list.length && list[i].pos < offset) {
5619 lastPos = list[i].pos;
5620 i++;
5621 }
5622 if (i === list.length) {
5623 tombstone = Math.floor((offset - lastPos) / this.tombstoneHeight);
5624 }
5625 i += tombstone;
5626 return i;
5627 };
5628 IndexCalculator.prototype.resetState = function () {
5629 this.lastDirection = 1 /* DOWN */;
5630 this.lastPos = 0;
5631 };
5632 return IndexCalculator;
5633}());
5634
5635var ListItem = /** @class */ (function () {
5636 function ListItem() {
5637 this.data = null;
5638 this.dom = null;
5639 this.tombstone = null;
5640 this.width = 0;
5641 this.height = 0;
5642 this.pos = 0;
5643 }
5644 return ListItem;
5645}());
5646var DataManager = /** @class */ (function () {
5647 function DataManager(list, fetchFn, onFetchFinish) {
5648 this.fetchFn = fetchFn;
5649 this.onFetchFinish = onFetchFinish;
5650 this.loadedNum = 0;
5651 this.fetching = false;
5652 this.hasMore = true;
5653 this.list = list || [];
5654 }
5655 DataManager.prototype.update = function (end) {
5656 return __awaiter(this, void 0, void 0, function () {
5657 var len;
5658 return __generator(this, function (_a) {
5659 if (!this.hasMore) {
5660 end = Math.min(end, this.list.length);
5661 }
5662 // add data placeholder
5663 if (end > this.list.length) {
5664 len = end - this.list.length;
5665 this.addEmptyData(len);
5666 }
5667 // tslint:disable-next-line: no-floating-promises
5668 return [2 /*return*/, this.checkToFetch(end)];
5669 });
5670 });
5671 };
5672 DataManager.prototype.add = function (data) {
5673 for (var i = 0; i < data.length; i++) {
5674 if (!this.list[this.loadedNum]) {
5675 this.list[this.loadedNum] = { data: data[i] };
5676 }
5677 else {
5678 this.list[this.loadedNum] = __assign(__assign({}, this.list[this.loadedNum]), { data: data[i] });
5679 }
5680 this.loadedNum++;
5681 }
5682 return this.list;
5683 };
5684 DataManager.prototype.addEmptyData = function (len) {
5685 for (var i = 0; i < len; i++) {
5686 this.list.push(new ListItem());
5687 }
5688 return this.list;
5689 };
5690 DataManager.prototype.fetch = function (len) {
5691 return __awaiter(this, void 0, void 0, function () {
5692 var data;
5693 return __generator(this, function (_a) {
5694 switch (_a.label) {
5695 case 0:
5696 if (this.fetching) {
5697 return [2 /*return*/, []];
5698 }
5699 this.fetching = true;
5700 return [4 /*yield*/, this.fetchFn(len)];
5701 case 1:
5702 data = _a.sent();
5703 this.fetching = false;
5704 return [2 /*return*/, data];
5705 }
5706 });
5707 });
5708 };
5709 DataManager.prototype.checkToFetch = function (end) {
5710 return __awaiter(this, void 0, void 0, function () {
5711 var min, newData, currentEnd;
5712 return __generator(this, function (_a) {
5713 switch (_a.label) {
5714 case 0:
5715 if (!this.hasMore) {
5716 return [2 /*return*/];
5717 }
5718 if (end <= this.loadedNum) {
5719 return [2 /*return*/];
5720 }
5721 min = end - this.loadedNum;
5722 return [4 /*yield*/, this.fetch(min)];
5723 case 1:
5724 newData = _a.sent();
5725 if (newData instanceof Array && newData.length) {
5726 this.add(newData);
5727 currentEnd = this.onFetchFinish(this.list, true);
5728 return [2 /*return*/, this.checkToFetch(currentEnd)];
5729 }
5730 else if (typeof newData === 'boolean' && newData === false) {
5731 this.hasMore = false;
5732 this.list.splice(this.loadedNum);
5733 this.onFetchFinish(this.list, false);
5734 }
5735 return [2 /*return*/];
5736 }
5737 });
5738 });
5739 };
5740 DataManager.prototype.getList = function () {
5741 return this.list;
5742 };
5743 DataManager.prototype.resetState = function () {
5744 this.loadedNum = 0;
5745 this.fetching = false;
5746 this.hasMore = true;
5747 this.list = [];
5748 };
5749 return DataManager;
5750}());
5751
5752var Tombstone = /** @class */ (function () {
5753 function Tombstone(create) {
5754 this.create = create;
5755 this.cached = [];
5756 this.width = 0;
5757 this.height = 0;
5758 this.initialed = false;
5759 this.getSize();
5760 }
5761 Tombstone.isTombstone = function (el) {
5762 if (el && el.classList) {
5763 return el.classList.contains('tombstone');
5764 }
5765 return false;
5766 };
5767 Tombstone.prototype.getSize = function () {
5768 if (!this.initialed) {
5769 var tombstone = this.create();
5770 tombstone.style.position = 'absolute';
5771 document.body.appendChild(tombstone);
5772 tombstone.style.display = '';
5773 this.height = tombstone.offsetHeight;
5774 this.width = tombstone.offsetWidth;
5775 document.body.removeChild(tombstone);
5776 this.cached.push(tombstone);
5777 }
5778 };
5779 Tombstone.prototype.getOne = function () {
5780 var tombstone = this.cached.pop();
5781 if (tombstone) {
5782 var tombstoneStyle = tombstone.style;
5783 tombstoneStyle.display = '';
5784 tombstoneStyle.opacity = '1';
5785 tombstoneStyle[style.transform] = '';
5786 tombstoneStyle[style.transition] = '';
5787 return tombstone;
5788 }
5789 return this.create();
5790 };
5791 Tombstone.prototype.recycle = function (tombstones) {
5792 for (var _i = 0, tombstones_1 = tombstones; _i < tombstones_1.length; _i++) {
5793 var tombstone = tombstones_1[_i];
5794 tombstone.style.display = 'none';
5795 this.cached.push(tombstone);
5796 }
5797 return this.cached;
5798 };
5799 Tombstone.prototype.recycleOne = function (tombstone) {
5800 this.cached.push(tombstone);
5801 return this.cached;
5802 };
5803 return Tombstone;
5804}());
5805
5806var ANIMATION_DURATION_MS = 200;
5807var DomManager = /** @class */ (function () {
5808 function DomManager(content, renderFn, tombstone) {
5809 this.renderFn = renderFn;
5810 this.tombstone = tombstone;
5811 this.unusedDom = [];
5812 this.timers = [];
5813 this.setContent(content);
5814 }
5815 DomManager.prototype.update = function (list, start, end) {
5816 if (start >= list.length) {
5817 start = list.length - 1;
5818 }
5819 if (end > list.length) {
5820 end = list.length;
5821 }
5822 this.collectUnusedDom(list, start, end);
5823 this.createDom(list, start, end);
5824 this.cacheHeight(list, start, end);
5825 var _a = this.positionDom(list, start, end), startPos = _a.startPos, startDelta = _a.startDelta, endPos = _a.endPos;
5826 return {
5827 start: start,
5828 startPos: startPos,
5829 startDelta: startDelta,
5830 end: end,
5831 endPos: endPos,
5832 };
5833 };
5834 DomManager.prototype.collectUnusedDom = function (list, start, end) {
5835 // TODO optimise
5836 for (var i = 0; i < list.length; i++) {
5837 if (i === start) {
5838 i = end - 1;
5839 continue;
5840 }
5841 if (list[i].dom) {
5842 var dom = list[i].dom;
5843 if (Tombstone.isTombstone(dom)) {
5844 this.tombstone.recycleOne(dom);
5845 dom.style.display = 'none';
5846 }
5847 else {
5848 this.unusedDom.push(dom);
5849 }
5850 list[i].dom = null;
5851 }
5852 }
5853 return list;
5854 };
5855 DomManager.prototype.createDom = function (list, start, end) {
5856 for (var i = start; i < end; i++) {
5857 var dom = list[i].dom;
5858 var data = list[i].data;
5859 if (dom) {
5860 if (Tombstone.isTombstone(dom) && data) {
5861 list[i].tombstone = dom;
5862 list[i].dom = null;
5863 }
5864 else {
5865 continue;
5866 }
5867 }
5868 dom = data
5869 ? this.renderFn(data, this.unusedDom.pop())
5870 : this.tombstone.getOne();
5871 dom.style.position = 'absolute';
5872 list[i].dom = dom;
5873 list[i].pos = -1;
5874 this.content.appendChild(dom);
5875 }
5876 };
5877 DomManager.prototype.cacheHeight = function (list, start, end) {
5878 for (var i = start; i < end; i++) {
5879 if (list[i].data && !list[i].height) {
5880 list[i].height = list[i].dom.offsetHeight;
5881 }
5882 }
5883 };
5884 DomManager.prototype.positionDom = function (list, start, end) {
5885 var _this = this;
5886 var tombstoneEles = [];
5887 var _a = this.getStartPos(list, start, end), startPos = _a.start, startDelta = _a.delta;
5888 var pos = startPos;
5889 for (var i = start; i < end; i++) {
5890 var tombstone = list[i].tombstone;
5891 if (tombstone) {
5892 var tombstoneStyle = tombstone.style;
5893 tombstoneStyle[style.transition] = cssVendor + "transform " + ANIMATION_DURATION_MS + "ms, opacity " + ANIMATION_DURATION_MS + "ms";
5894 tombstoneStyle[style.transform] = "translateY(" + pos + "px)";
5895 tombstoneStyle.opacity = '0';
5896 list[i].tombstone = null;
5897 tombstoneEles.push(tombstone);
5898 }
5899 if (list[i].dom && list[i].pos !== pos) {
5900 list[i].dom.style[style.transform] = "translateY(" + pos + "px)";
5901 list[i].pos = pos;
5902 }
5903 pos += list[i].height || this.tombstone.height;
5904 }
5905 var timerId = window.setTimeout(function () {
5906 _this.tombstone.recycle(tombstoneEles);
5907 }, ANIMATION_DURATION_MS);
5908 this.timers.push(timerId);
5909 return {
5910 startPos: startPos,
5911 startDelta: startDelta,
5912 endPos: pos,
5913 };
5914 };
5915 DomManager.prototype.getStartPos = function (list, start, end) {
5916 if (list[start] && list[start].pos !== -1) {
5917 return {
5918 start: list[start].pos,
5919 delta: 0,
5920 };
5921 }
5922 // TODO optimise
5923 var pos = list[0].pos === -1 ? 0 : list[0].pos;
5924 for (var i_1 = 0; i_1 < start; i_1++) {
5925 pos += list[i_1].height || this.tombstone.height;
5926 }
5927 var originPos = pos;
5928 var i;
5929 for (i = start; i < end; i++) {
5930 if (!Tombstone.isTombstone(list[i].dom) && list[i].pos !== -1) {
5931 pos = list[i].pos;
5932 break;
5933 }
5934 }
5935 var x = i;
5936 if (x < end) {
5937 while (x > start) {
5938 pos -= list[x - 1].height;
5939 x--;
5940 }
5941 }
5942 var delta = originPos - pos;
5943 return {
5944 start: pos,
5945 delta: delta,
5946 };
5947 };
5948 DomManager.prototype.removeTombstone = function () {
5949 var tombstones = this.content.querySelectorAll('.tombstone');
5950 for (var i = tombstones.length - 1; i >= 0; i--) {
5951 this.content.removeChild(tombstones[i]);
5952 }
5953 };
5954 DomManager.prototype.setContent = function (content) {
5955 if (content !== this.content) {
5956 this.content = content;
5957 }
5958 };
5959 DomManager.prototype.destroy = function () {
5960 this.removeTombstone();
5961 this.timers.forEach(function (id) {
5962 clearTimeout(id);
5963 });
5964 };
5965 DomManager.prototype.resetState = function () {
5966 this.destroy();
5967 this.timers = [];
5968 this.unusedDom = [];
5969 };
5970 return DomManager;
5971}());
5972
5973var EXTRA_SCROLL_Y = -2000;
5974var InfinityScroll = /** @class */ (function () {
5975 function InfinityScroll(scroll) {
5976 this.scroll = scroll;
5977 this.start = 0;
5978 this.end = 0;
5979 this.init();
5980 }
5981 InfinityScroll.prototype.init = function () {
5982 var _this = this;
5983 this.handleOptions();
5984 var _a = this.options, fetchFn = _a.fetch, renderFn = _a.render, createTombstoneFn = _a.createTombstone;
5985 this.tombstone = new Tombstone(createTombstoneFn);
5986 this.indexCalculator = new IndexCalculator(this.scroll.scroller.scrollBehaviorY.wrapperSize, this.tombstone.height);
5987 this.domManager = new DomManager(this.scroll.scroller.content, renderFn, this.tombstone);
5988 this.dataManager = new DataManager([], fetchFn, this.onFetchFinish.bind(this));
5989 this.scroll.on(this.scroll.eventTypes.destroy, this.destroy, this);
5990 this.scroll.on(this.scroll.eventTypes.scroll, this.update, this);
5991 this.scroll.on(this.scroll.eventTypes.contentChanged, function (content) {
5992 _this.domManager.setContent(content);
5993 _this.indexCalculator.resetState();
5994 _this.domManager.resetState();
5995 _this.dataManager.resetState();
5996 _this.update({ y: 0 });
5997 });
5998 var scrollBehaviorY = this.scroll.scroller.scrollBehaviorY;
5999 scrollBehaviorY.hooks.on(scrollBehaviorY.hooks.eventTypes.computeBoundary, this.modifyBoundary, this);
6000 this.update({ y: 0 });
6001 };
6002 InfinityScroll.prototype.modifyBoundary = function (boundary) {
6003 // manually set position to allow scroll
6004 boundary.maxScrollPos = EXTRA_SCROLL_Y;
6005 };
6006 InfinityScroll.prototype.handleOptions = function () {
6007 // narrow down type to an object
6008 var infinityOptions = this.scroll.options.infinity;
6009 if (infinityOptions) {
6010 if (typeof infinityOptions.fetch !== 'function') {
6011 warn('Infinity plugin need fetch Function to new data.');
6012 }
6013 if (typeof infinityOptions.render !== 'function') {
6014 warn('Infinity plugin need render Function to render each item.');
6015 }
6016 if (typeof infinityOptions.render !== 'function') {
6017 warn('Infinity plugin need createTombstone Function to create tombstone.');
6018 }
6019 this.options = infinityOptions;
6020 }
6021 this.scroll.options.probeType = 3 /* Realtime */;
6022 };
6023 InfinityScroll.prototype.update = function (pos) {
6024 var position = Math.round(-pos.y);
6025 // important! calculate start/end index to render
6026 var _a = this.indexCalculator.calculate(position, this.dataManager.getList()), start = _a.start, end = _a.end;
6027 this.start = start;
6028 this.end = end;
6029 // tslint:disable-next-line: no-floating-promises
6030 this.dataManager.update(end);
6031 this.updateDom(this.dataManager.getList());
6032 };
6033 InfinityScroll.prototype.onFetchFinish = function (list, hasMore) {
6034 var end = this.updateDom(list).end;
6035 if (!hasMore) {
6036 this.domManager.removeTombstone();
6037 this.scroll.scroller.animater.stop();
6038 this.scroll.resetPosition();
6039 }
6040 // tslint:disable-next-line: no-floating-promises
6041 return end;
6042 };
6043 InfinityScroll.prototype.updateDom = function (list) {
6044 var _a = this.domManager.update(list, this.start, this.end), end = _a.end, startPos = _a.startPos, endPos = _a.endPos, startDelta = _a.startDelta;
6045 if (startDelta) {
6046 this.scroll.minScrollY = startDelta;
6047 }
6048 if (endPos > this.scroll.maxScrollY) {
6049 this.scroll.maxScrollY = -(endPos - this.scroll.scroller.scrollBehaviorY.wrapperSize);
6050 }
6051 return {
6052 end: end,
6053 startPos: startPos,
6054 endPos: endPos,
6055 };
6056 };
6057 InfinityScroll.prototype.destroy = function () {
6058 var _a = this.scroll.scroller, content = _a.content, scrollBehaviorY = _a.scrollBehaviorY;
6059 while (content.firstChild) {
6060 content.removeChild(content.firstChild);
6061 }
6062 this.domManager.destroy();
6063 this.scroll.off('scroll', this.update);
6064 this.scroll.off('destroy', this.destroy);
6065 scrollBehaviorY.hooks.off(scrollBehaviorY.hooks.eventTypes.computeBoundary);
6066 };
6067 InfinityScroll.pluginName = 'infinity';
6068 return InfinityScroll;
6069}());
6070
6071var sourcePrefix = 'plugins.movable';
6072var propertiesMap = [
6073 {
6074 key: 'putAt',
6075 name: 'putAt',
6076 },
6077];
6078var propertiesConfig = propertiesMap.map(function (item) {
6079 return {
6080 key: item.key,
6081 sourceKey: sourcePrefix + "." + item.name,
6082 };
6083});
6084
6085var Movable = /** @class */ (function () {
6086 function Movable(scroll) {
6087 this.scroll = scroll;
6088 this.handleBScroll();
6089 this.handleHooks();
6090 }
6091 Movable.prototype.handleBScroll = function () {
6092 this.scroll.proxy(propertiesConfig);
6093 };
6094 Movable.prototype.handleHooks = function () {
6095 var _this = this;
6096 this.hooksFn = [];
6097 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
6098 var computeBoundary = function (boundary, behavior) {
6099 if (boundary.maxScrollPos > 0) {
6100 // content is smaller than wrapper
6101 boundary.minScrollPos = behavior.wrapperSize - behavior.contentSize;
6102 boundary.maxScrollPos = 0;
6103 }
6104 };
6105 this.registerHooks(scrollBehaviorX.hooks, scrollBehaviorX.hooks.eventTypes.ignoreHasScroll, function () { return true; });
6106 this.registerHooks(scrollBehaviorX.hooks, scrollBehaviorX.hooks.eventTypes.computeBoundary, function (boundary) {
6107 computeBoundary(boundary, scrollBehaviorX);
6108 });
6109 this.registerHooks(scrollBehaviorY.hooks, scrollBehaviorY.hooks.eventTypes.ignoreHasScroll, function () { return true; });
6110 this.registerHooks(scrollBehaviorY.hooks, scrollBehaviorY.hooks.eventTypes.computeBoundary, function (boundary) {
6111 computeBoundary(boundary, scrollBehaviorY);
6112 });
6113 this.registerHooks(this.scroll.hooks, this.scroll.hooks.eventTypes.destroy, function () {
6114 _this.destroy();
6115 });
6116 };
6117 Movable.prototype.putAt = function (x, y, time, easing) {
6118 if (time === void 0) { time = this.scroll.options.bounceTime; }
6119 if (easing === void 0) { easing = ease.bounce; }
6120 var position = this.resolvePostion(x, y);
6121 this.scroll.scrollTo(position.x, position.y, time, easing);
6122 };
6123 Movable.prototype.resolvePostion = function (x, y) {
6124 var _a = this.scroll.scroller, scrollBehaviorX = _a.scrollBehaviorX, scrollBehaviorY = _a.scrollBehaviorY;
6125 var resolveFormula = {
6126 left: function () {
6127 return 0;
6128 },
6129 top: function () {
6130 return 0;
6131 },
6132 right: function () {
6133 return scrollBehaviorX.minScrollPos;
6134 },
6135 bottom: function () {
6136 return scrollBehaviorY.minScrollPos;
6137 },
6138 center: function (index) {
6139 var baseSize = index === 0
6140 ? scrollBehaviorX.minScrollPos
6141 : scrollBehaviorY.minScrollPos;
6142 return baseSize / 2;
6143 },
6144 };
6145 return {
6146 x: typeof x === 'number' ? x : resolveFormula[x](0),
6147 y: typeof y === 'number' ? y : resolveFormula[y](1),
6148 };
6149 };
6150 Movable.prototype.destroy = function () {
6151 this.hooksFn.forEach(function (item) {
6152 var hooks = item[0];
6153 var hooksName = item[1];
6154 var handlerFn = item[2];
6155 hooks.off(hooksName, handlerFn);
6156 });
6157 this.hooksFn.length = 0;
6158 };
6159 Movable.prototype.registerHooks = function (hooks, name, handler) {
6160 hooks.on(name, handler, this);
6161 this.hooksFn.push([hooks, name, handler]);
6162 };
6163 Movable.pluginName = 'movable';
6164 Movable.applyOrder = "pre" /* Pre */;
6165 return Movable;
6166}());
6167
6168var isImageTag = function (el) {
6169 return el.tagName.toLowerCase() === 'img';
6170};
6171var ObserveImage = /** @class */ (function () {
6172 function ObserveImage(scroll) {
6173 this.scroll = scroll;
6174 this.refreshTimer = 0;
6175 this.init();
6176 }
6177 ObserveImage.prototype.init = function () {
6178 this.handleOptions(this.scroll.options.observeImage);
6179 this.bindEventsToWrapper();
6180 };
6181 ObserveImage.prototype.handleOptions = function (userOptions) {
6182 if (userOptions === void 0) { userOptions = {}; }
6183 userOptions = (userOptions === true ? {} : userOptions);
6184 var defaultOptions = {
6185 debounceTime: 100,
6186 };
6187 this.options = extend(defaultOptions, userOptions);
6188 };
6189 ObserveImage.prototype.bindEventsToWrapper = function () {
6190 var wrapper = this.scroll.scroller.wrapper;
6191 this.imageLoadEventRegister = new EventRegister(wrapper, [
6192 {
6193 name: 'load',
6194 handler: this.load.bind(this),
6195 capture: true,
6196 },
6197 ]);
6198 this.imageErrorEventRegister = new EventRegister(wrapper, [
6199 {
6200 name: 'error',
6201 handler: this.load.bind(this),
6202 capture: true,
6203 },
6204 ]);
6205 };
6206 ObserveImage.prototype.load = function (e) {
6207 var _this = this;
6208 var target = e.target;
6209 var debounceTime = this.options.debounceTime;
6210 if (target && isImageTag(target)) {
6211 if (debounceTime === 0) {
6212 this.scroll.refresh();
6213 }
6214 else {
6215 clearTimeout(this.refreshTimer);
6216 this.refreshTimer = window.setTimeout(function () {
6217 _this.scroll.refresh();
6218 }, this.options.debounceTime);
6219 }
6220 }
6221 };
6222 ObserveImage.pluginName = 'observeImage';
6223 return ObserveImage;
6224}());
6225
6226var resolveRatioOption = function (ratioConfig) {
6227 var ret = {
6228 ratioX: 0,
6229 ratioY: 0,
6230 };
6231 /* istanbul ignore if */
6232 if (!ratioConfig) {
6233 return ret;
6234 }
6235 if (typeof ratioConfig === 'number') {
6236 ret.ratioX = ret.ratioY = ratioConfig;
6237 }
6238 else if (typeof ratioConfig === 'object' && ratioConfig) {
6239 ret.ratioX = ratioConfig.x || 0;
6240 ret.ratioY = ratioConfig.y || 0;
6241 }
6242 return ret;
6243};
6244var handleBubbleAndCancelable = function (e) {
6245 maybePrevent(e);
6246 e.stopPropagation();
6247};
6248var Indicator = /** @class */ (function () {
6249 function Indicator(scroll, options) {
6250 this.scroll = scroll;
6251 this.options = options;
6252 this.currentPos = {
6253 x: 0,
6254 y: 0,
6255 };
6256 this.hooksFn = [];
6257 this.handleDOM();
6258 this.handleHooks();
6259 this.handleInteractive();
6260 }
6261 Indicator.prototype.handleDOM = function () {
6262 var _a = this.options, relationElement = _a.relationElement, _b = _a.relationElementHandleElementIndex, relationElementHandleElementIndex = _b === void 0 ? 0 : _b;
6263 this.wrapper = relationElement;
6264 this.indicatorEl = this.wrapper.children[relationElementHandleElementIndex];
6265 };
6266 Indicator.prototype.handleHooks = function () {
6267 var _this = this;
6268 var scroll = this.scroll;
6269 var scrollHooks = scroll.hooks;
6270 var translaterHooks = scroll.scroller.translater.hooks;
6271 var animaterHooks = scroll.scroller.animater.hooks;
6272 this.registerHooks(scrollHooks, scrollHooks.eventTypes.refresh, this.refresh);
6273 this.registerHooks(translaterHooks, translaterHooks.eventTypes.translate, function (pos) {
6274 _this.updatePosition(pos);
6275 });
6276 this.registerHooks(animaterHooks, animaterHooks.eventTypes.time, this.transitionTime);
6277 this.registerHooks(animaterHooks, animaterHooks.eventTypes.timeFunction, this.transitionTimingFunction);
6278 };
6279 Indicator.prototype.transitionTime = function (time) {
6280 if (time === void 0) { time = 0; }
6281 this.indicatorEl.style[style.transitionDuration] = time + 'ms';
6282 };
6283 Indicator.prototype.transitionTimingFunction = function (easing) {
6284 this.indicatorEl.style[style.transitionTimingFunction] = easing;
6285 };
6286 Indicator.prototype.handleInteractive = function () {
6287 if (this.options.interactive !== false) {
6288 this.registerEvents();
6289 }
6290 };
6291 Indicator.prototype.registerHooks = function (hooks, name, handler) {
6292 hooks.on(name, handler, this);
6293 this.hooksFn.push([hooks, name, handler]);
6294 };
6295 Indicator.prototype.registerEvents = function () {
6296 var _a = this.scroll.options, disableMouse = _a.disableMouse, disableTouch = _a.disableTouch;
6297 var startEvents = [];
6298 var moveEvents = [];
6299 var endEvents = [];
6300 if (!disableMouse) {
6301 startEvents.push({
6302 name: 'mousedown',
6303 handler: this.start.bind(this),
6304 });
6305 moveEvents.push({
6306 name: 'mousemove',
6307 handler: this.move.bind(this),
6308 });
6309 endEvents.push({
6310 name: 'mouseup',
6311 handler: this.end.bind(this),
6312 });
6313 }
6314 if (!disableTouch) {
6315 startEvents.push({
6316 name: 'touchstart',
6317 handler: this.start.bind(this),
6318 });
6319 moveEvents.push({
6320 name: 'touchmove',
6321 handler: this.move.bind(this),
6322 });
6323 endEvents.push({
6324 name: 'touchend',
6325 handler: this.end.bind(this),
6326 }, {
6327 name: 'touchcancel',
6328 handler: this.end.bind(this),
6329 });
6330 }
6331 this.startEventRegister = new EventRegister(this.indicatorEl, startEvents);
6332 this.moveEventRegister = new EventRegister(window, moveEvents);
6333 this.endEventRegister = new EventRegister(window, endEvents);
6334 };
6335 Indicator.prototype.refresh = function () {
6336 var _a = this.scroll, x = _a.x, y = _a.y, hasHorizontalScroll = _a.hasHorizontalScroll, hasVerticalScroll = _a.hasVerticalScroll, maxBScrollX = _a.maxScrollX, maxBScrollY = _a.maxScrollY;
6337 var _b = resolveRatioOption(this.options.ratio), ratioX = _b.ratioX, ratioY = _b.ratioY;
6338 var _c = getClientSize(this.wrapper), wrapperWidth = _c.width, wrapperHeight = _c.height;
6339 var _d = getRect(this.indicatorEl), indicatorWidth = _d.width, indicatorHeight = _d.height;
6340 if (hasHorizontalScroll) {
6341 this.maxScrollX = wrapperWidth - indicatorWidth;
6342 this.translateXSign =
6343 this.maxScrollX > 0 ? -1 /* Positive */ : 1 /* NotPositive */;
6344 this.minScrollX = 0;
6345 // ensure positive
6346 this.ratioX = ratioX ? ratioX : Math.abs(this.maxScrollX / maxBScrollX);
6347 }
6348 if (hasVerticalScroll) {
6349 this.maxScrollY = wrapperHeight - indicatorHeight;
6350 this.translateYSign =
6351 this.maxScrollY > 0 ? -1 /* Positive */ : 1 /* NotPositive */;
6352 this.minScrollY = 0;
6353 this.ratioY = ratioY ? ratioY : Math.abs(this.maxScrollY / maxBScrollY);
6354 }
6355 this.updatePosition({
6356 x: x,
6357 y: y,
6358 });
6359 };
6360 Indicator.prototype.start = function (e) {
6361 if (this.BScrollIsDisabled()) {
6362 return;
6363 }
6364 var point = (e.touches ? e.touches[0] : e);
6365 handleBubbleAndCancelable(e);
6366 this.initiated = true;
6367 this.moved = false;
6368 this.lastPointX = point.pageX;
6369 this.lastPointY = point.pageY;
6370 this.startTime = getNow();
6371 this.scroll.scroller.hooks.trigger(this.scroll.scroller.hooks.eventTypes.beforeScrollStart);
6372 };
6373 Indicator.prototype.BScrollIsDisabled = function () {
6374 return !this.scroll.enabled;
6375 };
6376 Indicator.prototype.move = function (e) {
6377 if (!this.initiated) {
6378 return;
6379 }
6380 var point = (e.touches ? e.touches[0] : e);
6381 var pointX = point.pageX;
6382 var pointY = point.pageY;
6383 handleBubbleAndCancelable(e);
6384 var deltaX = pointX - this.lastPointX;
6385 var deltaY = pointY - this.lastPointY;
6386 this.lastPointX = pointX;
6387 this.lastPointY = pointY;
6388 if (!this.moved && !this.indicatorNotMoved(deltaX, deltaY)) {
6389 this.moved = true;
6390 this.scroll.scroller.hooks.trigger(this.scroll.scroller.hooks.eventTypes.scrollStart);
6391 }
6392 if (this.moved) {
6393 var newPos = this.getBScrollPosByRatio(this.currentPos, deltaX, deltaY);
6394 this.syncBScroll(newPos);
6395 }
6396 };
6397 Indicator.prototype.end = function (e) {
6398 if (!this.initiated) {
6399 return;
6400 }
6401 this.initiated = false;
6402 handleBubbleAndCancelable(e);
6403 if (this.moved) {
6404 var _a = this.scroll, x = _a.x, y = _a.y;
6405 this.scroll.scroller.hooks.trigger(this.scroll.scroller.hooks.eventTypes.scrollEnd, {
6406 x: x,
6407 y: y,
6408 });
6409 }
6410 };
6411 Indicator.prototype.getBScrollPosByRatio = function (currentPos, deltaX, deltaY) {
6412 var currentX = currentPos.x, currentY = currentPos.y;
6413 var _a = this.scroll, hasHorizontalScroll = _a.hasHorizontalScroll, hasVerticalScroll = _a.hasVerticalScroll, BScrollMinScrollX = _a.minScrollX, BScrollMaxScrollX = _a.maxScrollX, BScrollMinScrollY = _a.minScrollY, BScrollMaxScrollY = _a.maxScrollY;
6414 var _b = this.scroll, x = _b.x, y = _b.y;
6415 if (hasHorizontalScroll) {
6416 var newPosX = between(currentX + deltaX, Math.min(this.minScrollX, this.maxScrollX), Math.max(this.minScrollX, this.maxScrollX));
6417 var roundX = Math.round((newPosX / this.ratioX) * this.translateXSign);
6418 x = between(roundX, BScrollMaxScrollX, BScrollMinScrollX);
6419 }
6420 if (hasVerticalScroll) {
6421 var newPosY = between(currentY + deltaY, Math.min(this.minScrollY, this.maxScrollY), Math.max(this.minScrollY, this.maxScrollY));
6422 var roundY = Math.round((newPosY / this.ratioY) * this.translateYSign);
6423 y = between(roundY, BScrollMaxScrollY, BScrollMinScrollY);
6424 }
6425 return { x: x, y: y };
6426 };
6427 Indicator.prototype.indicatorNotMoved = function (deltaX, deltaY) {
6428 var _a = this.currentPos, x = _a.x, y = _a.y;
6429 var xNotMoved = (x === this.minScrollX && deltaX <= 0) ||
6430 (x === this.maxScrollX && deltaX >= 0);
6431 var yNotMoved = (y === this.minScrollY && deltaY <= 0) ||
6432 (y === this.maxScrollY && deltaY >= 0);
6433 return xNotMoved && yNotMoved;
6434 };
6435 Indicator.prototype.syncBScroll = function (newPos) {
6436 var timestamp = getNow();
6437 var _a = this.scroll, options = _a.options, scroller = _a.scroller;
6438 var probeType = options.probeType, momentumLimitTime = options.momentumLimitTime;
6439 scroller.translater.translate(newPos);
6440 // dispatch scroll in interval time
6441 if (timestamp - this.startTime > momentumLimitTime) {
6442 this.startTime = timestamp;
6443 if (probeType === 1 /* Throttle */) {
6444 scroller.hooks.trigger(scroller.hooks.eventTypes.scroll, newPos);
6445 }
6446 }
6447 // dispatch scroll all the time
6448 if (probeType > 1 /* Throttle */) {
6449 scroller.hooks.trigger(scroller.hooks.eventTypes.scroll, newPos);
6450 }
6451 };
6452 Indicator.prototype.updatePosition = function (BScrollPos) {
6453 var newIndicatorPos = this.getIndicatorPosByRatio(BScrollPos);
6454 this.applyTransformProperty(newIndicatorPos);
6455 this.currentPos = __assign({}, newIndicatorPos);
6456 };
6457 Indicator.prototype.applyTransformProperty = function (pos) {
6458 var translateZ = this.scroll.options.translateZ;
6459 var transformProperties = [
6460 "translateX(" + pos.x + "px)",
6461 "translateY(" + pos.y + "px)",
6462 "" + translateZ,
6463 ];
6464 this.indicatorEl.style[style.transform] =
6465 transformProperties.join(' ');
6466 };
6467 Indicator.prototype.getIndicatorPosByRatio = function (BScrollPos) {
6468 var x = BScrollPos.x, y = BScrollPos.y;
6469 var _a = this.scroll, hasHorizontalScroll = _a.hasHorizontalScroll, hasVerticalScroll = _a.hasVerticalScroll;
6470 var position = __assign({}, this.currentPos);
6471 if (hasHorizontalScroll) {
6472 var roundX = Math.round(this.ratioX * x * this.translateXSign);
6473 // maybe maxScrollX is negative
6474 position.x = between(roundX, Math.min(this.minScrollX, this.maxScrollX), Math.max(this.minScrollX, this.maxScrollX));
6475 }
6476 if (hasVerticalScroll) {
6477 var roundY = Math.round(this.ratioY * y * this.translateYSign);
6478 // maybe maxScrollY is negative
6479 position.y = between(roundY, Math.min(this.minScrollY, this.maxScrollY), Math.max(this.minScrollY, this.maxScrollY));
6480 }
6481 return position;
6482 };
6483 Indicator.prototype.destroy = function () {
6484 if (this.options.interactive !== false) {
6485 this.startEventRegister.destroy();
6486 this.moveEventRegister.destroy();
6487 this.endEventRegister.destroy();
6488 }
6489 this.hooksFn.forEach(function (item) {
6490 var hooks = item[0];
6491 var hooksName = item[1];
6492 var handlerFn = item[2];
6493 hooks.off(hooksName, handlerFn);
6494 });
6495 this.hooksFn.length = 0;
6496 };
6497 return Indicator;
6498}());
6499
6500var Indicators = /** @class */ (function () {
6501 function Indicators(scroll) {
6502 this.scroll = scroll;
6503 this.options = [];
6504 this.indicators = [];
6505 this.handleOptions();
6506 this.handleHooks();
6507 }
6508 Indicators.prototype.handleOptions = function () {
6509 var UserIndicatorsOptions = this.scroll.options.indicators;
6510 assert(Array.isArray(UserIndicatorsOptions), "'indicators' must be an array.");
6511 for (var _i = 0, UserIndicatorsOptions_1 = UserIndicatorsOptions; _i < UserIndicatorsOptions_1.length; _i++) {
6512 var indicatorOptions = UserIndicatorsOptions_1[_i];
6513 assert(!!indicatorOptions.relationElement, "'relationElement' must be a HTMLElement.");
6514 this.createIndicators(indicatorOptions);
6515 }
6516 };
6517 Indicators.prototype.createIndicators = function (options) {
6518 this.indicators.push(new Indicator(this.scroll, options));
6519 };
6520 Indicators.prototype.handleHooks = function () {
6521 var _this = this;
6522 var scrollHooks = this.scroll.hooks;
6523 scrollHooks.on(scrollHooks.eventTypes.destroy, function () {
6524 for (var _i = 0, _a = _this.indicators; _i < _a.length; _i++) {
6525 var indicator = _a[_i];
6526 indicator.destroy();
6527 }
6528 _this.indicators = [];
6529 });
6530 };
6531 Indicators.pluginName = 'indicators';
6532 return Indicators;
6533}());
6534
6535BScroll.use(MouseWheel)
6536 .use(ObserveDOM)
6537 .use(PullDown)
6538 .use(PullUp)
6539 .use(ScrollBar)
6540 .use(Slide)
6541 .use(Wheel)
6542 .use(Zoom)
6543 .use(NestedScroll)
6544 .use(InfinityScroll)
6545 .use(Movable)
6546 .use(ObserveImage)
6547 .use(Indicators);
6548
6549export { Behavior, CustomOptions, Indicators, InfinityScroll, MouseWheel, Movable, NestedScroll, ObserveDOM as ObserveDom, ObserveImage, PullDown as PullDownRefresh, PullUp as PullUpLoad, ScrollBar, Slide, Wheel, Zoom, createBScroll, BScroll as default };