UNPKG

389 kBJavaScriptView Raw
1/*
2Copyright (c) 2015-present NAVER Corp.
3name: @egjs/flicking
4license: MIT
5author: NAVER Corp.
6repository: https://github.com/naver/egjs-flicking
7version: 3.7.1
8*/
9(function (global, factory) {
10 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
11 typeof define === 'function' && define.amd ? define(factory) :
12 (global = global || self, (global.eg = global.eg || {}, global.eg.Flicking = factory()));
13}(this, (function () { 'use strict';
14
15 /*! *****************************************************************************
16 Copyright (c) Microsoft Corporation.
17
18 Permission to use, copy, modify, and/or distribute this software for any
19 purpose with or without fee is hereby granted.
20
21 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
22 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
23 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
24 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
25 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
26 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
27 PERFORMANCE OF THIS SOFTWARE.
28 ***************************************************************************** */
29
30 /* global Reflect, Promise */
31 var extendStatics = function (d, b) {
32 extendStatics = Object.setPrototypeOf || {
33 __proto__: []
34 } instanceof Array && function (d, b) {
35 d.__proto__ = b;
36 } || function (d, b) {
37 for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
38 };
39
40 return extendStatics(d, b);
41 };
42
43 function __extends(d, b) {
44 extendStatics(d, b);
45
46 function __() {
47 this.constructor = d;
48 }
49
50 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
51 }
52 function __spreadArrays() {
53 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
54
55 for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j];
56
57 return r;
58 }
59
60 /*
61 Copyright (c) NAVER Corp.
62 name: @egjs/component
63 license: MIT
64 author: NAVER Corp.
65 repository: https://github.com/naver/egjs-component
66 version: 2.2.2
67 */
68 /*! *****************************************************************************
69 Copyright (c) Microsoft Corporation.
70
71 Permission to use, copy, modify, and/or distribute this software for any
72 purpose with or without fee is hereby granted.
73
74 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
75 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
76 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
77 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
78 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
79 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
80 PERFORMANCE OF THIS SOFTWARE.
81 ***************************************************************************** */
82 function __values(o) {
83 var s = typeof Symbol === "function" && Symbol.iterator,
84 m = s && o[s],
85 i = 0;
86 if (m) return m.call(o);
87 if (o && typeof o.length === "number") return {
88 next: function () {
89 if (o && i >= o.length) o = void 0;
90 return {
91 value: o && o[i++],
92 done: !o
93 };
94 }
95 };
96 throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
97 }
98
99 /*
100 * Copyright (c) 2015 NAVER Corp.
101 * egjs projects are licensed under the MIT license
102 */
103
104 function isUndefined(value) {
105 return typeof value === "undefined";
106 }
107 /**
108 * A class used to manage events in a component
109 * @ko 컴포넌트의 이벤트을 관리할 수 있게 하는 클래스
110 * @alias eg.Component
111 */
112
113
114 var Component =
115 /*#__PURE__*/
116 function () {
117 /**
118 * @support {"ie": "7+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.1+ (except 3.x)"}
119 */
120 function Component() {
121 /**
122 * @deprecated
123 * @private
124 */
125 this.options = {};
126 this._eventHandler = {};
127 }
128 /**
129 * Triggers a custom event.
130 * @ko 커스텀 이벤트를 발생시킨다
131 * @param {string} eventName The name of the custom event to be triggered <ko>발생할 커스텀 이벤트의 이름</ko>
132 * @param {object} customEvent Event data to be sent when triggering a custom event <ko>커스텀 이벤트가 발생할 때 전달할 데이터</ko>
133 * @param {any[]} restParam Additional parameters when triggering a custom event <ko>커스텀 이벤트가 발생할 때 필요시 추가적으로 전달할 데이터</ko>
134 * @return Indicates whether the event has occurred. If the stop() method is called by a custom event handler, it will return false and prevent the event from occurring. <a href="https://github.com/naver/egjs-component/wiki/How-to-make-Component-event-design%3F">Ref</a> <ko>이벤트 발생 여부. 커스텀 이벤트 핸들러에서 stop() 메서드를 호출하면 'false'를 반환하고 이벤트 발생을 중단한다. <a href="https://github.com/naver/egjs-component/wiki/How-to-make-Component-event-design%3F">참고</a></ko>
135 * @example
136 * ```
137 * class Some extends eg.Component {
138 * some(){
139 * if(this.trigger("beforeHi")){ // When event call to stop return false.
140 * this.trigger("hi");// fire hi event.
141 * }
142 * }
143 * }
144 *
145 * const some = new Some();
146 * some.on("beforeHi", (e) => {
147 * if(condition){
148 * e.stop(); // When event call to stop, `hi` event not call.
149 * }
150 * });
151 * some.on("hi", (e) => {
152 * // `currentTarget` is component instance.
153 * console.log(some === e.currentTarget); // true
154 * });
155 * // If you want to more know event design. You can see article.
156 * // https://github.com/naver/egjs-component/wiki/How-to-make-Component-event-design%3F
157 * ```
158 */
159
160
161 var __proto = Component.prototype;
162
163 __proto.trigger = function (eventName) {
164 var _this = this;
165
166 var params = [];
167
168 for (var _i = 1; _i < arguments.length; _i++) {
169 params[_i - 1] = arguments[_i];
170 }
171
172 var handlerList = this._eventHandler[eventName] || [];
173 var hasHandlerList = handlerList.length > 0;
174
175 if (!hasHandlerList) {
176 return true;
177 }
178
179 var customEvent = params[0] || {};
180 var restParams = params.slice(1); // If detach method call in handler in first time then handler list calls.
181
182 handlerList = handlerList.concat();
183 var isCanceled = false; // This should be done like this to pass previous tests
184
185 customEvent.eventType = eventName;
186
187 customEvent.stop = function () {
188 isCanceled = true;
189 };
190
191 customEvent.currentTarget = this;
192 var arg = [customEvent];
193
194 if (restParams.length >= 1) {
195 arg = arg.concat(restParams);
196 }
197
198 handlerList.forEach(function (handler) {
199 handler.apply(_this, arg);
200 });
201 return !isCanceled;
202 };
203 /**
204 * Executed event just one time.
205 * @ko 이벤트가 한번만 실행된다.
206 * @param {string} eventName The name of the event to be attached <ko>등록할 이벤트의 이름</ko>
207 * @param {function} handlerToAttach The handler function of the event to be attached <ko>등록할 이벤트의 핸들러 함수</ko>
208 * @return An instance of a component itself<ko>컴포넌트 자신의 인스턴스</ko>
209 * @example
210 * ```
211 * class Some extends eg.Component {
212 * hi() {
213 * alert("hi");
214 * }
215 * thing() {
216 * this.once("hi", this.hi);
217 * }
218 *
219 * var some = new Some();
220 * some.thing();
221 * some.trigger("hi");
222 * // fire alert("hi");
223 * some.trigger("hi");
224 * // Nothing happens
225 * ```
226 */
227
228
229 __proto.once = function (eventName, handlerToAttach) {
230 var _this = this;
231
232 if (typeof eventName === "object" && isUndefined(handlerToAttach)) {
233 var eventHash = eventName;
234
235 for (var key in eventHash) {
236 this.once(key, eventHash[key]);
237 }
238
239 return this;
240 } else if (typeof eventName === "string" && typeof handlerToAttach === "function") {
241 var listener_1 = function () {
242 var args = [];
243
244 for (var _i = 0; _i < arguments.length; _i++) {
245 args[_i] = arguments[_i];
246 }
247
248 handlerToAttach.apply(_this, args);
249
250 _this.off(eventName, listener_1);
251 };
252
253 this.on(eventName, listener_1);
254 }
255
256 return this;
257 };
258 /**
259 * Checks whether an event has been attached to a component.
260 * @ko 컴포넌트에 이벤트가 등록됐는지 확인한다.
261 * @param {string} eventName The name of the event to be attached <ko>등록 여부를 확인할 이벤트의 이름</ko>
262 * @return {boolean} Indicates whether the event is attached. <ko>이벤트 등록 여부</ko>
263 * @example
264 * ```
265 * class Some extends eg.Component {
266 * some() {
267 * this.hasOn("hi");// check hi event.
268 * }
269 * }
270 * ```
271 */
272
273
274 __proto.hasOn = function (eventName) {
275 return !!this._eventHandler[eventName];
276 };
277 /**
278 * Attaches an event to a component.
279 * @ko 컴포넌트에 이벤트를 등록한다.
280 * @param {string} eventName The name of the event to be attached <ko>등록할 이벤트의 이름</ko>
281 * @param {function} handlerToAttach The handler function of the event to be attached <ko>등록할 이벤트의 핸들러 함수</ko>
282 * @return An instance of a component itself<ko>컴포넌트 자신의 인스턴스</ko>
283 * @example
284 * ```
285 * class Some extends eg.Component {
286 * hi() {
287 * console.log("hi");
288 * }
289 * some() {
290 * this.on("hi",this.hi); //attach event
291 * }
292 * }
293 * ```
294 */
295
296
297 __proto.on = function (eventName, handlerToAttach) {
298 if (typeof eventName === "object" && isUndefined(handlerToAttach)) {
299 var eventHash = eventName;
300
301 for (var name in eventHash) {
302 this.on(name, eventHash[name]);
303 }
304
305 return this;
306 } else if (typeof eventName === "string" && typeof handlerToAttach === "function") {
307 var handlerList = this._eventHandler[eventName];
308
309 if (isUndefined(handlerList)) {
310 this._eventHandler[eventName] = [];
311 handlerList = this._eventHandler[eventName];
312 }
313
314 handlerList.push(handlerToAttach);
315 }
316
317 return this;
318 };
319 /**
320 * Detaches an event from the component.
321 * @ko 컴포넌트에 등록된 이벤트를 해제한다
322 * @param {string} eventName The name of the event to be detached <ko>해제할 이벤트의 이름</ko>
323 * @param {function} handlerToDetach The handler function of the event to be detached <ko>해제할 이벤트의 핸들러 함수</ko>
324 * @return An instance of a component itself <ko>컴포넌트 자신의 인스턴스</ko>
325 * @example
326 * ```
327 * class Some extends eg.Component {
328 * hi() {
329 * console.log("hi");
330 * }
331 * some() {
332 * this.off("hi",this.hi); //detach event
333 * }
334 * }
335 * ```
336 */
337
338
339 __proto.off = function (eventName, handlerToDetach) {
340 var e_1, _a; // Detach all event handlers.
341
342
343 if (isUndefined(eventName)) {
344 this._eventHandler = {};
345 return this;
346 } // Detach all handlers for eventname or detach event handlers by object.
347
348
349 if (isUndefined(handlerToDetach)) {
350 if (typeof eventName === "string") {
351 delete this._eventHandler[eventName];
352 return this;
353 } else {
354 var eventHash = eventName;
355
356 for (var name in eventHash) {
357 this.off(name, eventHash[name]);
358 }
359
360 return this;
361 }
362 } // Detach single event handler
363
364
365 var handlerList = this._eventHandler[eventName];
366
367 if (handlerList) {
368 var idx = 0;
369
370 try {
371 for (var handlerList_1 = __values(handlerList), handlerList_1_1 = handlerList_1.next(); !handlerList_1_1.done; handlerList_1_1 = handlerList_1.next()) {
372 var handlerFunction = handlerList_1_1.value;
373
374 if (handlerFunction === handlerToDetach) {
375 handlerList.splice(idx, 1);
376 break;
377 }
378
379 idx++;
380 }
381 } catch (e_1_1) {
382 e_1 = {
383 error: e_1_1
384 };
385 } finally {
386 try {
387 if (handlerList_1_1 && !handlerList_1_1.done && (_a = handlerList_1.return)) _a.call(handlerList_1);
388 } finally {
389 if (e_1) throw e_1.error;
390 }
391 }
392 }
393
394 return this;
395 };
396 /**
397 * Version info string
398 * @ko 버전정보 문자열
399 * @name VERSION
400 * @static
401 * @example
402 * eg.Component.VERSION; // ex) 2.0.0
403 * @memberof eg.Component
404 */
405
406
407 Component.VERSION = "2.2.2";
408 return Component;
409 }();
410
411 /*
412 Copyright (c) 2020-present NAVER Corp.
413 name: @egjs/imready
414 license: MIT
415 author: NAVER Corp.
416 repository: https://github.com/naver/egjs-imready
417 version: 1.1.2
418 */
419
420 /*! *****************************************************************************
421 Copyright (c) Microsoft Corporation.
422
423 Permission to use, copy, modify, and/or distribute this software for any
424 purpose with or without fee is hereby granted.
425
426 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
427 REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
428 AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
429 INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
430 LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
431 OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
432 PERFORMANCE OF THIS SOFTWARE.
433 ***************************************************************************** */
434
435 /* global Reflect, Promise */
436 var extendStatics$1 = function (d, b) {
437 extendStatics$1 = Object.setPrototypeOf || {
438 __proto__: []
439 } instanceof Array && function (d, b) {
440 d.__proto__ = b;
441 } || function (d, b) {
442 for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p];
443 };
444
445 return extendStatics$1(d, b);
446 };
447
448 function __extends$1(d, b) {
449 extendStatics$1(d, b);
450
451 function __() {
452 this.constructor = d;
453 }
454
455 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
456 }
457 var __assign = function () {
458 __assign = Object.assign || function __assign(t) {
459 for (var s, i = 1, n = arguments.length; i < n; i++) {
460 s = arguments[i];
461
462 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
463 }
464
465 return t;
466 };
467
468 return __assign.apply(this, arguments);
469 };
470 function __spreadArrays$1() {
471 for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
472
473 for (var r = Array(s), k = 0, i = 0; i < il; i++) for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++) r[k] = a[j];
474
475 return r;
476 }
477
478 /*
479 egjs-imready
480 Copyright (c) 2020-present NAVER Corp.
481 MIT license
482 */
483 var isWindow = typeof window !== "undefined";
484 var ua = isWindow ? window.navigator.userAgent : "";
485 var SUPPORT_COMPUTEDSTYLE = isWindow ? !!("getComputedStyle" in window) : false;
486 var IS_IE = /MSIE|Trident|Windows Phone|Edge/.test(ua);
487 var SUPPORT_ADDEVENTLISTENER = isWindow ? !!("addEventListener" in document) : false;
488 var WIDTH = "width";
489 var HEIGHT = "height";
490
491 function getAttribute(el, name) {
492 return el.getAttribute(name) || "";
493 }
494 function toArray(arr) {
495 return [].slice.call(arr);
496 }
497 function hasSizeAttribute(target, prefix) {
498 if (prefix === void 0) {
499 prefix = "data-";
500 }
501
502 return !!target.getAttribute(prefix + "width");
503 }
504 function hasLoadingAttribute(target) {
505 return "loading" in target && target.getAttribute("loading") === "lazy";
506 }
507 function hasSkipAttribute(target, prefix) {
508 if (prefix === void 0) {
509 prefix = "data-";
510 }
511
512 return !!target.getAttribute(prefix + "skip");
513 }
514 function addEvent(element, type, handler) {
515 if (SUPPORT_ADDEVENTLISTENER) {
516 element.addEventListener(type, handler, false);
517 } else if (element.attachEvent) {
518 element.attachEvent("on" + type, handler);
519 } else {
520 element["on" + type] = handler;
521 }
522 }
523 function removeEvent(element, type, handler) {
524 if (element.removeEventListener) {
525 element.removeEventListener(type, handler, false);
526 } else if (element.detachEvent) {
527 element.detachEvent("on" + type, handler);
528 } else {
529 element["on" + type] = null;
530 }
531 }
532 function innerWidth(el) {
533 return getSize(el, "Width");
534 }
535 function innerHeight(el) {
536 return getSize(el, "Height");
537 }
538 function getStyles(el) {
539 return (SUPPORT_COMPUTEDSTYLE ? window.getComputedStyle(el) : el.currentStyle) || {};
540 }
541
542 function getSize(el, name) {
543 var size = el["client" + name] || el["offset" + name];
544 return parseFloat(size || getStyles(el)[name.toLowerCase()]) || 0;
545 }
546
547 function getContentElements(element, tags, prefix) {
548 var skipElements = toArray(element.querySelectorAll(__spreadArrays$1(["[" + prefix + "skip] [" + prefix + "width]"], tags.map(function (tag) {
549 return ["[" + prefix + "skip] " + tag, tag + "[" + prefix + "skip]", "[" + prefix + "width] " + tag].join(", ");
550 })).join(", ")));
551 return toArray(element.querySelectorAll("[" + prefix + "width], " + tags.join(", "))).filter(function (el) {
552 return skipElements.indexOf(el) === -1;
553 });
554 }
555
556 /*
557 egjs-imready
558 Copyright (c) 2020-present NAVER Corp.
559 MIT license
560 */
561 var elements = [];
562 function addAutoSizer(element, prefix) {
563 !elements.length && addEvent(window, "resize", resizeAllAutoSizers);
564 element.__PREFIX__ = prefix;
565 elements.push(element);
566 resize(element);
567 }
568 function removeAutoSizer(element, prefix) {
569 var index = elements.indexOf(element);
570
571 if (index < 0) {
572 return;
573 }
574
575 var fixed = getAttribute(element, prefix + "fixed");
576 delete element.__PREFIX__;
577 element.style[fixed === HEIGHT ? WIDTH : HEIGHT] = "";
578 elements.splice(index, 1);
579 !elements.length && removeEvent(window, "resize", resizeAllAutoSizers);
580 }
581
582 function resize(element, prefix) {
583 if (prefix === void 0) {
584 prefix = "data-";
585 }
586
587 var elementPrefix = element.__PREFIX__ || prefix;
588 var dataWidth = parseInt(getAttribute(element, "" + elementPrefix + WIDTH), 10) || 0;
589 var dataHeight = parseInt(getAttribute(element, "" + elementPrefix + HEIGHT), 10) || 0;
590 var fixed = getAttribute(element, elementPrefix + "fixed");
591
592 if (fixed === HEIGHT) {
593 var size = innerHeight(element) || dataHeight;
594 element.style[WIDTH] = dataWidth / dataHeight * size + "px";
595 } else {
596 var size = innerWidth(element) || dataWidth;
597 element.style[HEIGHT] = dataHeight / dataWidth * size + "px";
598 }
599 }
600
601 function resizeAllAutoSizers() {
602 elements.forEach(function (element) {
603 resize(element);
604 });
605 }
606
607 var Loader =
608 /*#__PURE__*/
609 function (_super) {
610 __extends$1(Loader, _super);
611
612 function Loader(element, options) {
613 if (options === void 0) {
614 options = {};
615 }
616
617 var _this = _super.call(this) || this;
618
619 _this.isReady = false;
620 _this.isPreReady = false;
621 _this.hasDataSize = false;
622 _this.hasLoading = false;
623 _this.isSkip = false;
624
625 _this.onCheck = function (e) {
626 _this.clear();
627
628 if (e && e.type === "error") {
629 _this.onError(_this.element);
630 } // I'm pre-ready and ready!
631
632
633 var withPreReady = !_this.hasDataSize && !_this.hasLoading;
634
635 _this.onReady(withPreReady);
636 };
637
638 _this.options = __assign({
639 prefix: "data-"
640 }, options);
641 _this.element = element;
642 _this.hasDataSize = hasSizeAttribute(element, _this.options.prefix);
643 _this.hasLoading = hasLoadingAttribute(element);
644 _this.isSkip = hasSkipAttribute(_this.element);
645 return _this;
646 }
647
648 var __proto = Loader.prototype;
649
650 __proto.check = function () {
651 if (this.isSkip || !this.checkElement()) {
652 // I'm Ready
653 this.onAlreadyReady(true);
654 return false;
655 }
656
657 if (this.hasDataSize) {
658 addAutoSizer(this.element, this.options.prefix);
659 }
660
661 if (this.hasDataSize || this.hasLoading) {
662 // I'm Pre Ready
663 this.onAlreadyPreReady();
664 } // Wati Pre Ready, Ready
665
666
667 return true;
668 };
669
670 __proto.addEvents = function () {
671 var _this = this;
672
673 var element = this.element;
674 this.constructor.EVENTS.forEach(function (name) {
675 addEvent(element, name, _this.onCheck);
676 });
677 };
678
679 __proto.clear = function () {
680 var _this = this;
681
682 var element = this.element;
683 this.constructor.EVENTS.forEach(function (name) {
684 removeEvent(element, name, _this.onCheck);
685 });
686 this.removeAutoSizer();
687 };
688
689 __proto.destroy = function () {
690 this.clear();
691 this.off();
692 };
693
694 __proto.removeAutoSizer = function () {
695 if (this.hasDataSize) {
696 // I'm already ready.
697 var prefix = this.options.prefix;
698 removeAutoSizer(this.element, prefix);
699 }
700 };
701
702 __proto.onError = function (target) {
703 this.trigger("error", {
704 element: this.element,
705 target: target
706 });
707 };
708
709 __proto.onPreReady = function () {
710 if (this.isPreReady) {
711 return;
712 }
713
714 this.isPreReady = true;
715 this.trigger("preReady", {
716 element: this.element,
717 hasLoading: this.hasLoading,
718 isSkip: this.isSkip
719 });
720 };
721
722 __proto.onReady = function (withPreReady) {
723 if (this.isReady) {
724 return;
725 }
726
727 if (withPreReady) {
728 this.isPreReady = true;
729 }
730
731 this.removeAutoSizer();
732 this.isReady = true;
733 this.trigger("ready", {
734 element: this.element,
735 withPreReady: withPreReady,
736 hasLoading: this.hasLoading,
737 isSkip: this.isSkip
738 });
739 };
740
741 __proto.onAlreadyError = function (target) {
742 var _this = this;
743
744 setTimeout(function () {
745 _this.onError(target);
746 });
747 };
748
749 __proto.onAlreadyPreReady = function () {
750 var _this = this;
751
752 setTimeout(function () {
753 _this.onPreReady();
754 });
755 };
756
757 __proto.onAlreadyReady = function (withPreReady) {
758 var _this = this;
759
760 setTimeout(function () {
761 _this.onReady(withPreReady);
762 });
763 };
764
765 Loader.EVENTS = [];
766 return Loader;
767 }(Component);
768
769 var ElementLoader =
770 /*#__PURE__*/
771 function (_super) {
772 __extends$1(ElementLoader, _super);
773
774 function ElementLoader() {
775 return _super !== null && _super.apply(this, arguments) || this;
776 }
777
778 var __proto = ElementLoader.prototype;
779
780 __proto.setHasLoading = function (hasLoading) {
781 this.hasLoading = hasLoading;
782 };
783
784 __proto.check = function () {
785 if (this.isSkip) {
786 // I'm Ready
787 this.onAlreadyReady(true);
788 return false;
789 }
790
791 if (this.hasDataSize) {
792 addAutoSizer(this.element, this.options.prefix);
793 this.onAlreadyPreReady();
794 } else {
795 // has not data size
796 this.trigger("requestChildren");
797 }
798
799 return true;
800 };
801
802 __proto.checkElement = function () {
803 return true;
804 };
805
806 __proto.destroy = function () {
807 this.clear();
808 this.trigger("requestDestroy");
809 this.off();
810 };
811
812 __proto.onAlreadyPreReady = function () {
813 // has data size
814 _super.prototype.onAlreadyPreReady.call(this);
815
816 this.trigger("reqeustReadyChildren");
817 };
818
819 ElementLoader.EVENTS = [];
820 return ElementLoader;
821 }(Loader);
822
823 /**
824 * @alias eg.ImReady
825 * @extends eg.Component
826 */
827
828 var ImReadyManager =
829 /*#__PURE__*/
830 function (_super) {
831 __extends$1(ImReadyManager, _super);
832 /**
833 * @param - ImReady's options
834 */
835
836
837 function ImReadyManager(options) {
838 if (options === void 0) {
839 options = {};
840 }
841
842 var _this = _super.call(this) || this;
843
844 _this.readyCount = 0;
845 _this.preReadyCount = 0;
846 _this.totalCount = 0;
847 _this.totalErrorCount = 0;
848 _this.isPreReadyOver = true;
849 _this.elementInfos = [];
850 _this.options = __assign({
851 loaders: {},
852 prefix: "data-"
853 }, options);
854 return _this;
855 }
856 /**
857 * Checks whether elements are in the ready state.
858 * @ko 엘리먼트가 준비 상태인지 체크한다.
859 * @elements - Elements to check ready status. <ko> 준비 상태를 체크할 엘리먼트들.</ko>
860 * @example
861 * ```html
862 * <div>
863 * <img src="./1.jpg" data-width="1280" data-height="853" style="width:100%"/>
864 * <img src="./2.jpg" data-width="1280" data-height="853"/>
865 * <img src="ERR" data-width="1280" data-height="853"/>
866 * </div>
867 * ```
868 * ## Javascript
869 * ```js
870 * import ImReady from "@egjs/imready";
871 *
872 * const im = new ImReady(); // umd: eg.ImReady
873 * im.check(document.querySelectorAll("img")).on({
874 * preReadyElement: e => {
875 * // 1, 3
876 * // 2, 3
877 * // 3, 3
878 * console.log(e.preReadyCount, e.totalCount),
879 * },
880 * });
881 * ```
882 */
883
884
885 var __proto = ImReadyManager.prototype;
886
887 __proto.check = function (elements) {
888 var _this = this;
889
890 var prefix = this.options.prefix;
891 this.clear();
892 this.elementInfos = toArray(elements).map(function (element, index) {
893 var loader = _this.getLoader(element, {
894 prefix: prefix
895 });
896
897 loader.check();
898 loader.on("error", function (e) {
899 _this.onError(index, e.target);
900 }).on("preReady", function (e) {
901 var info = _this.elementInfos[index];
902 info.hasLoading = e.hasLoading;
903 info.isSkip = e.isSkip;
904
905 var isPreReady = _this.checkPreReady(index);
906
907 _this.onPreReadyElement(index);
908
909 isPreReady && _this.onPreReady();
910 }).on("ready", function (_a) {
911 var withPreReady = _a.withPreReady,
912 hasLoading = _a.hasLoading,
913 isSkip = _a.isSkip;
914 var info = _this.elementInfos[index];
915 info.hasLoading = hasLoading;
916 info.isSkip = isSkip;
917
918 var isPreReady = withPreReady && _this.checkPreReady(index);
919
920 var isReady = _this.checkReady(index); // Pre-ready and ready occur simultaneously
921
922
923 withPreReady && _this.onPreReadyElement(index);
924
925 _this.onReadyElement(index);
926
927 isPreReady && _this.onPreReady();
928 isReady && _this.onReady();
929 });
930 return {
931 loader: loader,
932 element: element,
933 hasLoading: false,
934 hasError: false,
935 isPreReady: false,
936 isReady: false,
937 isSkip: false
938 };
939 });
940 var length = this.elementInfos.length;
941 this.totalCount = length;
942
943 if (!length) {
944 setTimeout(function () {
945 _this.onPreReady();
946
947 _this.onReady();
948 });
949 }
950
951 return this;
952 };
953 /**
954 * Gets the total count of elements to be checked.
955 * @ko 체크하는 element의 총 개수를 가져온다.
956 */
957
958
959 __proto.getTotalCount = function () {
960 return this.totalCount;
961 };
962 /**
963 * Whether the elements are all pre-ready. (all sizes are known)
964 * @ko 엘리먼트들이 모두 사전 준비가 됐는지 (사이즈를 전부 알 수 있는지) 여부.
965 */
966
967
968 __proto.isPreReady = function () {
969 return this.elementInfos.every(function (info) {
970 return info.isPreReady;
971 });
972 };
973 /**
974 * Whether the elements are all ready.
975 * @ko 엘리먼트들이 모두 준비가 됐는지 여부.
976 */
977
978
979 __proto.isReady = function () {
980 return this.elementInfos.every(function (info) {
981 return info.isReady;
982 });
983 };
984 /**
985 * Whether an error has occurred in the elements in the current state.
986 * @ko 현재 상태에서 엘리먼트들이 에러가 발생했는지 여부.
987 */
988
989
990 __proto.hasError = function () {
991 return this.totalErrorCount > 0;
992 };
993 /**
994 * Clears events of elements being checked.
995 * @ko 체크 중인 엘리먼트들의 이벤트를 해제 한다.
996 */
997
998
999 __proto.clear = function () {
1000 this.isPreReadyOver = false;
1001 this.totalCount = 0;
1002 this.preReadyCount = 0;
1003 this.readyCount = 0;
1004 this.totalErrorCount = 0;
1005 this.elementInfos.forEach(function (info) {
1006 if (!info.isReady && info.loader) {
1007 info.loader.destroy();
1008 }
1009 });
1010 this.elementInfos = [];
1011 };
1012 /**
1013 * Destory all events.
1014 * @ko 모든 이벤트를 해제 한다.
1015 */
1016
1017
1018 __proto.destroy = function () {
1019 this.clear();
1020 this.off();
1021 };
1022
1023 __proto.getLoader = function (element, options) {
1024 var _this = this;
1025
1026 var tagName = element.tagName.toLowerCase();
1027 var loaders = this.options.loaders;
1028 var tags = Object.keys(loaders);
1029
1030 if (loaders[tagName]) {
1031 return new loaders[tagName](element, options);
1032 }
1033
1034 var loader = new ElementLoader(element, options);
1035 var children = toArray(element.querySelectorAll(tags.join(", ")));
1036 loader.setHasLoading(children.some(function (el) {
1037 return hasLoadingAttribute(el);
1038 }));
1039 var withPreReady = false;
1040 var childrenImReady = this.clone().on("error", function (e) {
1041 loader.onError(e.target);
1042 }).on("ready", function () {
1043 loader.onReady(withPreReady);
1044 });
1045 loader.on("requestChildren", function () {
1046 // has not data size
1047 var contentElements = getContentElements(element, tags, _this.options.prefix);
1048 childrenImReady.check(contentElements).on("preReady", function (e) {
1049 withPreReady = e.isReady;
1050
1051 if (!withPreReady) {
1052 loader.onPreReady();
1053 }
1054 });
1055 }).on("reqeustReadyChildren", function () {
1056 // has data size
1057 // loader call preReady
1058 // check only video, image elements
1059 childrenImReady.check(children);
1060 }).on("requestDestroy", function () {
1061 childrenImReady.destroy();
1062 });
1063 return loader;
1064 };
1065
1066 __proto.clone = function () {
1067 return new ImReadyManager(__assign({}, this.options));
1068 };
1069
1070 __proto.checkPreReady = function (index) {
1071 this.elementInfos[index].isPreReady = true;
1072 ++this.preReadyCount;
1073
1074 if (this.preReadyCount < this.totalCount) {
1075 return false;
1076 }
1077
1078 return true;
1079 };
1080
1081 __proto.checkReady = function (index) {
1082 this.elementInfos[index].isReady = true;
1083 ++this.readyCount;
1084
1085 if (this.readyCount < this.totalCount) {
1086 return false;
1087 }
1088
1089 return true;
1090 };
1091
1092 __proto.onError = function (index, target) {
1093 var info = this.elementInfos[index];
1094 info.hasError = true;
1095 /**
1096 * An event occurs if the image, video fails to load.
1097 * @ko 이미지, 비디오가 로딩에 실패하면 이벤트가 발생한다.
1098 * @event eg.ImReady#error
1099 * @param {eg.ImReady.OnError} e - The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
1100 * @param {HTMLElement} [e.element] - The element with error images.<ko>오류난 이미지가 있는 엘리먼트</ko>
1101 * @param {number} [e.index] - The item's index with error images. <ko>오류난 이미지가 있는 엘리먼트의 인덱스</ko>
1102 * @param {HTMLElement} [e.target] - Error image target in element <ko>엘리먼트의 오류난 이미지 타겟</ko>
1103 * @param {number} [e.errorCount] - The number of elements with errors <ko>에러가 있는 엘리먼트들의 개수</ko>
1104 * @param {number} [e.totalErrorCount] - The total number of targets with errors <ko>에러가 있는 타겟들의 총 개수</ko>
1105 * @example
1106 * ```html
1107 * <div>
1108 * <img src="./1.jpg" data-width="1280" data-height="853" style="width:100%"/>
1109 * <img src="./2.jpg"/>
1110 * <img src="ERR"/>
1111 * </div>
1112 * ```
1113 * ## Javascript
1114 * ```js
1115 * import ImReady from "@egjs/imready";
1116 *
1117 * const im = new ImReady(); // umd: eg.ImReady
1118 * im.check([document.querySelector("div")]).on({
1119 * error: e => {
1120 * // <div>...</div>, 0, <img src="ERR"/>
1121 * console.log(e.element, e.index, e.target),
1122 * },
1123 * });
1124 * ```
1125 */
1126
1127 this.trigger("error", {
1128 element: info.element,
1129 index: index,
1130 target: target,
1131 errorCount: this.getErrorCount(),
1132 totalErrorCount: ++this.totalErrorCount
1133 });
1134 };
1135
1136 __proto.onPreReadyElement = function (index) {
1137 var info = this.elementInfos[index];
1138 /**
1139 * An event occurs when the element is pre-ready (when the loading attribute is applied or the size is known)
1140 * @ko 해당 엘리먼트가 사전 준비되었을 때(loading 속성이 적용되었거나 사이즈를 알 수 있을 때) 이벤트가 발생한다.
1141 * @event eg.ImReady#preReadyElement
1142 * @param {eg.ImReady.OnPreReadyElement} e - The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
1143 * @param {HTMLElement} [e.element] - The pre-ready element.<ko>사전 준비된 엘리먼트</ko>
1144 * @param {number} [e.index] - The index of the pre-ready element. <ko>사전 준비된 엘리먼트의 인덱스</ko>
1145 * @param {number} [e.preReadyCount] - Number of elements pre-ready <ko>사전 준비된 엘리먼트들의 개수</ko>
1146 * @param {number} [e.readyCount] - Number of elements ready <ko>준비된 엘리먼트들의 개수</ko>
1147 * @param {number} [e.totalCount] - Total number of elements <ko>엘리먼트들의 총 개수</ko>
1148 * @param {boolean} [e.isPreReady] - Whether all elements are pre-ready <ko>모든 엘리먼트가 사전 준비가 끝났는지 여부</ko>
1149 * @param {boolean} [e.isReady] - Whether all elements are ready <ko>모든 엘리먼트가 준비가 끝났는지 여부</ko>
1150 * @param {boolean} [e.hasLoading] - Whether the loading attribute has been applied <ko>loading 속성이 적용되었는지 여부</ko>
1151 * @param {boolean} [e.isSkip] - Whether the check is omitted due to skip attribute <ko>skip 속성으로 인하여 체크가 생략됐는지 여부</ko>
1152 * @example
1153 * ```html
1154 * <div>
1155 * <img src="./1.jpg" data-width="1280" data-height="853" style="width:100%"/>
1156 * <img src="./2.jpg" data-width="1280" data-height="853"/>
1157 * <img src="ERR" data-width="1280" data-height="853"/>
1158 * </div>
1159 * ```
1160 * ## Javascript
1161 * ```js
1162 * import ImReady from "@egjs/imready";
1163 *
1164 * const im = new ImReady(); // umd: eg.ImReady
1165 * im.check(document.querySelectorAll("img")).on({
1166 * preReadyElement: e => {
1167 * // 1, 3
1168 * // 2, 3
1169 * // 3, 3
1170 * console.log(e.preReadyCount, e.totalCount),
1171 * },
1172 * });
1173 * ```
1174 */
1175
1176 this.trigger("preReadyElement", {
1177 element: info.element,
1178 index: index,
1179 preReadyCount: this.preReadyCount,
1180 readyCount: this.readyCount,
1181 totalCount: this.totalCount,
1182 isPreReady: this.isPreReady(),
1183 isReady: this.isReady(),
1184 hasLoading: info.hasLoading,
1185 isSkip: info.isSkip
1186 });
1187 };
1188
1189 __proto.onPreReady = function () {
1190 this.isPreReadyOver = true;
1191 /**
1192 * An event occurs when all element are pre-ready (When all elements have the loading attribute applied or the size is known)
1193 * @ko 모든 엘리먼트들이 사전 준비된 경우 (모든 엘리먼트들이 loading 속성이 적용되었거나 사이즈를 알 수 있는 경우) 이벤트가 발생한다.
1194 * @event eg.ImReady#preReady
1195 * @param {eg.ImReady.OnPreReady} e - The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
1196 * @param {number} [e.readyCount] - Number of elements ready <ko>준비된 엘리먼트들의 개수</ko>
1197 * @param {number} [e.totalCount] - Total number of elements <ko>엘리먼트들의 총 개수</ko>
1198 * @param {boolean} [e.isReady] - Whether all elements are ready <ko>모든 엘리먼트가 준비가 끝났는지 여부</ko>
1199 * @param {boolean} [e.hasLoading] - Whether the loading attribute has been applied <ko>loading 속성이 적용되었는지 여부</ko>
1200 * @example
1201 * ```html
1202 * <div>
1203 * <img src="./1.jpg" data-width="1280" data-height="853" style="width:100%"/>
1204 * <img src="./2.jpg" data-width="1280" data-height="853"/>
1205 * <img src="ERR" data-width="1280" data-height="853"/>
1206 * </div>
1207 * ```
1208 * ## Javascript
1209 * ```js
1210 * import ImReady from "@egjs/imready";
1211 *
1212 * const im = new ImReady(); // umd: eg.ImReady
1213 * im.check(document.querySelectorAll("img")).on({
1214 * preReady: e => {
1215 * // 0, 3
1216 * console.log(e.readyCount, e.totalCount),
1217 * },
1218 * });
1219 * ```
1220 */
1221
1222 this.trigger("preReady", {
1223 readyCount: this.readyCount,
1224 totalCount: this.totalCount,
1225 isReady: this.isReady(),
1226 hasLoading: this.hasLoading()
1227 });
1228 };
1229
1230 __proto.onReadyElement = function (index) {
1231 var info = this.elementInfos[index];
1232 /**
1233 * An event occurs when the element is ready
1234 * @ko 해당 엘리먼트가 준비가 되었을 때 이벤트가 발생한다.
1235 * @event eg.ImReady#readyElement
1236 * @param {eg.ImReady.OnReadyElement} e - The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
1237 * @param {HTMLElement} [e.element] - The ready element.<ko>준비된 엘리먼트</ko>
1238 * @param {number} [e.index] - The index of the ready element. <ko>준비된 엘리먼트의 인덱스</ko>
1239 * @param {boolean} [e.hasError] - Whether there is an error in the element <ko>해당 엘리먼트에 에러가 있는지 여부</ko>
1240 * @param {number} [e.errorCount] - The number of elements with errors <ko>에러가 있는 엘리먼트들의 개수</ko>
1241 * @param {number} [e.totalErrorCount] - The total number of targets with errors <ko>에러가 있는 타겟들의 총 개수</ko>
1242 * @param {number} [e.preReadyCount] - Number of elements pre-ready <ko>사전 준비된 엘리먼트들의 개수</ko>
1243 * @param {number} [e.readyCount] - Number of elements ready <ko>준비된 엘리먼트들의 개수</ko>
1244 * @param {number} [e.totalCount] - Total number of elements <ko>엘리먼트들의 총 개수</ko>
1245 * @param {boolean} [e.isPreReady] - Whether all elements are pre-ready <ko>모든 엘리먼트가 사전 준비가 끝났는지 여부</ko>
1246 * @param {boolean} [e.isReady] - Whether all elements are ready <ko>모든 엘리먼트가 준비가 끝났는지 여부</ko>
1247 * @param {boolean} [e.hasLoading] - Whether the loading attribute has been applied <ko>loading 속성이 적용되었는지 여부</ko>
1248 * @param {boolean} [e.isPreReadyOver] - Whether pre-ready is over <ko>사전 준비가 끝났는지 여부</ko>
1249 * @param {boolean} [e.isSkip] - Whether the check is omitted due to skip attribute <ko>skip 속성으로 인하여 체크가 생략됐는지 여부</ko>
1250 * @example
1251 * ```html
1252 * <div>
1253 * <img src="./1.jpg" data-width="1280" data-height="853" style="width:100%"/>
1254 * <img src="./2.jpg" data-width="1280" data-height="853"/>
1255 * <img src="ERR" data-width="1280" data-height="853"/>
1256 * </div>
1257 * ```
1258 * ## Javascript
1259 * ```js
1260 * import ImReady from "@egjs/imready";
1261 *
1262 * const im = new ImReady(); // umd: eg.ImReady
1263 * im.check(document.querySelectorAll("img")).on({
1264 * readyElement: e => {
1265 * // 1, 0, false, 3
1266 * // 2, 1, false, 3
1267 * // 3, 2, true, 3
1268 * console.log(e.readyCount, e.index, e.hasError, e.totalCount),
1269 * },
1270 * });
1271 * ```
1272 */
1273
1274 this.trigger("readyElement", {
1275 index: index,
1276 element: info.element,
1277 hasError: info.hasError,
1278 errorCount: this.getErrorCount(),
1279 totalErrorCount: this.totalErrorCount,
1280 preReadyCount: this.preReadyCount,
1281 readyCount: this.readyCount,
1282 totalCount: this.totalCount,
1283 isPreReady: this.isPreReady(),
1284 isReady: this.isReady(),
1285 hasLoading: info.hasLoading,
1286 isPreReadyOver: this.isPreReadyOver,
1287 isSkip: info.isSkip
1288 });
1289 };
1290
1291 __proto.onReady = function () {
1292 /**
1293 * An event occurs when all element are ready
1294 * @ko 모든 엘리먼트들이 준비된 경우 이벤트가 발생한다.
1295 * @event eg.ImReady#ready
1296 * @param {eg.ImReady.OnReady} e - The object of data to be sent to an event <ko>이벤트에 전달되는 데이터 객체</ko>
1297 * @param {number} [e.errorCount] - The number of elements with errors <ko>에러가 있는 엘리먼트들의 개수</ko>
1298 * @param {number} [e.totalErrorCount] - The total number of targets with errors <ko>에러가 있는 타겟들의 총 개수</ko>
1299 * @param {number} [e.totalCount] - Total number of elements <ko>엘리먼트들의 총 개수</ko>
1300 * @example
1301 * ```html
1302 * <div>
1303 * <img src="./1.jpg" data-width="1280" data-height="853" style="width:100%"/>
1304 * <img src="./2.jpg" data-width="1280" data-height="853"/>
1305 * <img src="ERR" data-width="1280" data-height="853"/>
1306 * </div>
1307 * ```
1308 * ## Javascript
1309 * ```js
1310 * import ImReady from "@egjs/imready";
1311 *
1312 * const im = new ImReady(); // umd: eg.ImReady
1313 * im.check(document.querySelectorAll("img")).on({
1314 * preReady: e => {
1315 * // 0, 3
1316 * console.log(e.readyCount, e.totalCount),
1317 * },
1318 * ready: e => {
1319 * // 1, 3
1320 * console.log(e.errorCount, e.totalCount),
1321 * },
1322 * });
1323 * ```
1324 */
1325 this.trigger("ready", {
1326 errorCount: this.getErrorCount(),
1327 totalErrorCount: this.totalErrorCount,
1328 totalCount: this.totalCount
1329 });
1330 };
1331
1332 __proto.getErrorCount = function () {
1333 return this.elementInfos.filter(function (info) {
1334 return info.hasError;
1335 }).length;
1336 };
1337
1338 __proto.hasLoading = function () {
1339 return this.elementInfos.some(function (info) {
1340 return info.hasLoading;
1341 });
1342 };
1343
1344 return ImReadyManager;
1345 }(Component);
1346
1347 var ImageLoader =
1348 /*#__PURE__*/
1349 function (_super) {
1350 __extends$1(ImageLoader, _super);
1351
1352 function ImageLoader() {
1353 return _super !== null && _super.apply(this, arguments) || this;
1354 }
1355
1356 var __proto = ImageLoader.prototype;
1357
1358 __proto.checkElement = function () {
1359 var element = this.element;
1360 var src = element.getAttribute("src");
1361
1362 if (element.complete && src) {
1363 if (!element.naturalWidth) {
1364 this.onAlreadyError(element);
1365 }
1366
1367 return false;
1368 }
1369
1370 this.addEvents();
1371 IS_IE && element.setAttribute("src", src);
1372 return true;
1373 };
1374
1375 ImageLoader.EVENTS = ["load", "error"];
1376 return ImageLoader;
1377 }(Loader);
1378
1379 var VideoLoader =
1380 /*#__PURE__*/
1381 function (_super) {
1382 __extends$1(VideoLoader, _super);
1383
1384 function VideoLoader() {
1385 return _super !== null && _super.apply(this, arguments) || this;
1386 }
1387
1388 var __proto = VideoLoader.prototype;
1389
1390 __proto.checkElement = function () {
1391 var element = this.element; // HAVE_NOTHING: 0, no information whether or not the audio/video is ready
1392 // HAVE_METADATA: 1, HAVE_METADATA - metadata for the audio/video is ready
1393 // HAVE_CURRENT_DATA: 2, data for the current playback position is available, but not enough data to play next frame/millisecond
1394 // HAVE_FUTURE_DATA: 3, data for the current and at least the next frame is available
1395 // HAVE_ENOUGH_DATA: 4, enough data available to start playing
1396
1397 if (element.readyState >= 1) {
1398 return false;
1399 }
1400
1401 if (element.error) {
1402 this.onAlreadyError(element);
1403 return false;
1404 }
1405
1406 this.addEvents();
1407 return true;
1408 };
1409
1410 VideoLoader.EVENTS = ["loadedmetadata", "error"];
1411 return VideoLoader;
1412 }(Loader);
1413
1414 var ImReady =
1415 /*#__PURE__*/
1416 function (_super) {
1417 __extends$1(ImReady, _super);
1418
1419 function ImReady(options) {
1420 if (options === void 0) {
1421 options = {};
1422 }
1423
1424 return _super.call(this, __assign({
1425 loaders: {
1426 img: ImageLoader,
1427 video: VideoLoader
1428 }
1429 }, options)) || this;
1430 }
1431
1432 return ImReady;
1433 }(ImReadyManager);
1434
1435 /*! Hammer.JS - v2.0.17-rc - 2019-12-16
1436 * http://naver.github.io/egjs
1437 *
1438 * Forked By Naver egjs
1439 * Copyright (c) hammerjs
1440 * Licensed under the MIT license */
1441 function _extends() {
1442 _extends = Object.assign || function (target) {
1443 for (var i = 1; i < arguments.length; i++) {
1444 var source = arguments[i];
1445
1446 for (var key in source) {
1447 if (Object.prototype.hasOwnProperty.call(source, key)) {
1448 target[key] = source[key];
1449 }
1450 }
1451 }
1452
1453 return target;
1454 };
1455
1456 return _extends.apply(this, arguments);
1457 }
1458
1459 function _inheritsLoose(subClass, superClass) {
1460 subClass.prototype = Object.create(superClass.prototype);
1461 subClass.prototype.constructor = subClass;
1462 subClass.__proto__ = superClass;
1463 }
1464
1465 function _assertThisInitialized(self) {
1466 if (self === void 0) {
1467 throw new ReferenceError("this hasn't been initialised - super() hasn't been called");
1468 }
1469
1470 return self;
1471 }
1472
1473 /**
1474 * @private
1475 * extend object.
1476 * means that properties in dest will be overwritten by the ones in src.
1477 * @param {Object} target
1478 * @param {...Object} objects_to_assign
1479 * @returns {Object} target
1480 */
1481 var assign;
1482
1483 if (typeof Object.assign !== 'function') {
1484 assign = function assign(target) {
1485 if (target === undefined || target === null) {
1486 throw new TypeError('Cannot convert undefined or null to object');
1487 }
1488
1489 var output = Object(target);
1490
1491 for (var index = 1; index < arguments.length; index++) {
1492 var source = arguments[index];
1493
1494 if (source !== undefined && source !== null) {
1495 for (var nextKey in source) {
1496 if (source.hasOwnProperty(nextKey)) {
1497 output[nextKey] = source[nextKey];
1498 }
1499 }
1500 }
1501 }
1502
1503 return output;
1504 };
1505 } else {
1506 assign = Object.assign;
1507 }
1508
1509 var assign$1 = assign;
1510
1511 var VENDOR_PREFIXES = ['', 'webkit', 'Moz', 'MS', 'ms', 'o'];
1512 var TEST_ELEMENT = typeof document === "undefined" ? {
1513 style: {}
1514 } : document.createElement('div');
1515 var TYPE_FUNCTION = 'function';
1516 var round = Math.round,
1517 abs = Math.abs;
1518 var now = Date.now;
1519
1520 /**
1521 * @private
1522 * get the prefixed property
1523 * @param {Object} obj
1524 * @param {String} property
1525 * @returns {String|Undefined} prefixed
1526 */
1527
1528 function prefixed(obj, property) {
1529 var prefix;
1530 var prop;
1531 var camelProp = property[0].toUpperCase() + property.slice(1);
1532 var i = 0;
1533
1534 while (i < VENDOR_PREFIXES.length) {
1535 prefix = VENDOR_PREFIXES[i];
1536 prop = prefix ? prefix + camelProp : property;
1537
1538 if (prop in obj) {
1539 return prop;
1540 }
1541
1542 i++;
1543 }
1544
1545 return undefined;
1546 }
1547
1548 /* eslint-disable no-new-func, no-nested-ternary */
1549 var win;
1550
1551 if (typeof window === "undefined") {
1552 // window is undefined in node.js
1553 win = {};
1554 } else {
1555 win = window;
1556 }
1557
1558 var PREFIXED_TOUCH_ACTION = prefixed(TEST_ELEMENT.style, 'touchAction');
1559 var NATIVE_TOUCH_ACTION = PREFIXED_TOUCH_ACTION !== undefined;
1560 function getTouchActionProps() {
1561 if (!NATIVE_TOUCH_ACTION) {
1562 return false;
1563 }
1564
1565 var touchMap = {};
1566 var cssSupports = win.CSS && win.CSS.supports;
1567 ['auto', 'manipulation', 'pan-y', 'pan-x', 'pan-x pan-y', 'none'].forEach(function (val) {
1568 // If css.supports is not supported but there is native touch-action assume it supports
1569 // all values. This is the case for IE 10 and 11.
1570 return touchMap[val] = cssSupports ? win.CSS.supports('touch-action', val) : true;
1571 });
1572 return touchMap;
1573 }
1574
1575 var TOUCH_ACTION_COMPUTE = 'compute';
1576 var TOUCH_ACTION_AUTO = 'auto';
1577 var TOUCH_ACTION_MANIPULATION = 'manipulation'; // not implemented
1578
1579 var TOUCH_ACTION_NONE = 'none';
1580 var TOUCH_ACTION_PAN_X = 'pan-x';
1581 var TOUCH_ACTION_PAN_Y = 'pan-y';
1582 var TOUCH_ACTION_MAP = getTouchActionProps();
1583
1584 var MOBILE_REGEX = /mobile|tablet|ip(ad|hone|od)|android/i;
1585 var SUPPORT_TOUCH = 'ontouchstart' in win;
1586 var SUPPORT_POINTER_EVENTS = prefixed(win, 'PointerEvent') !== undefined;
1587 var SUPPORT_ONLY_TOUCH = SUPPORT_TOUCH && MOBILE_REGEX.test(navigator.userAgent);
1588 var INPUT_TYPE_TOUCH = 'touch';
1589 var INPUT_TYPE_PEN = 'pen';
1590 var INPUT_TYPE_MOUSE = 'mouse';
1591 var INPUT_TYPE_KINECT = 'kinect';
1592 var COMPUTE_INTERVAL = 25;
1593 var INPUT_START = 1;
1594 var INPUT_MOVE = 2;
1595 var INPUT_END = 4;
1596 var INPUT_CANCEL = 8;
1597 var DIRECTION_NONE = 1;
1598 var DIRECTION_LEFT = 2;
1599 var DIRECTION_RIGHT = 4;
1600 var DIRECTION_UP = 8;
1601 var DIRECTION_DOWN = 16;
1602 var DIRECTION_HORIZONTAL = DIRECTION_LEFT | DIRECTION_RIGHT;
1603 var DIRECTION_VERTICAL = DIRECTION_UP | DIRECTION_DOWN;
1604 var DIRECTION_ALL = DIRECTION_HORIZONTAL | DIRECTION_VERTICAL;
1605 var PROPS_XY = ['x', 'y'];
1606 var PROPS_CLIENT_XY = ['clientX', 'clientY'];
1607
1608 /**
1609 * @private
1610 * walk objects and arrays
1611 * @param {Object} obj
1612 * @param {Function} iterator
1613 * @param {Object} context
1614 */
1615 function each(obj, iterator, context) {
1616 var i;
1617
1618 if (!obj) {
1619 return;
1620 }
1621
1622 if (obj.forEach) {
1623 obj.forEach(iterator, context);
1624 } else if (obj.length !== undefined) {
1625 i = 0;
1626
1627 while (i < obj.length) {
1628 iterator.call(context, obj[i], i, obj);
1629 i++;
1630 }
1631 } else {
1632 for (i in obj) {
1633 obj.hasOwnProperty(i) && iterator.call(context, obj[i], i, obj);
1634 }
1635 }
1636 }
1637
1638 /**
1639 * @private
1640 * let a boolean value also be a function that must return a boolean
1641 * this first item in args will be used as the context
1642 * @param {Boolean|Function} val
1643 * @param {Array} [args]
1644 * @returns {Boolean}
1645 */
1646
1647 function boolOrFn(val, args) {
1648 if (typeof val === TYPE_FUNCTION) {
1649 return val.apply(args ? args[0] || undefined : undefined, args);
1650 }
1651
1652 return val;
1653 }
1654
1655 /**
1656 * @private
1657 * small indexOf wrapper
1658 * @param {String} str
1659 * @param {String} find
1660 * @returns {Boolean} found
1661 */
1662 function inStr(str, find) {
1663 return str.indexOf(find) > -1;
1664 }
1665
1666 /**
1667 * @private
1668 * when the touchActions are collected they are not a valid value, so we need to clean things up. *
1669 * @param {String} actions
1670 * @returns {*}
1671 */
1672
1673 function cleanTouchActions(actions) {
1674 // none
1675 if (inStr(actions, TOUCH_ACTION_NONE)) {
1676 return TOUCH_ACTION_NONE;
1677 }
1678
1679 var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X);
1680 var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y); // if both pan-x and pan-y are set (different recognizers
1681 // for different directions, e.g. horizontal pan but vertical swipe?)
1682 // we need none (as otherwise with pan-x pan-y combined none of these
1683 // recognizers will work, since the browser would handle all panning
1684
1685 if (hasPanX && hasPanY) {
1686 return TOUCH_ACTION_NONE;
1687 } // pan-x OR pan-y
1688
1689
1690 if (hasPanX || hasPanY) {
1691 return hasPanX ? TOUCH_ACTION_PAN_X : TOUCH_ACTION_PAN_Y;
1692 } // manipulation
1693
1694
1695 if (inStr(actions, TOUCH_ACTION_MANIPULATION)) {
1696 return TOUCH_ACTION_MANIPULATION;
1697 }
1698
1699 return TOUCH_ACTION_AUTO;
1700 }
1701
1702 /**
1703 * @private
1704 * Touch Action
1705 * sets the touchAction property or uses the js alternative
1706 * @param {Manager} manager
1707 * @param {String} value
1708 * @constructor
1709 */
1710
1711 var TouchAction =
1712 /*#__PURE__*/
1713 function () {
1714 function TouchAction(manager, value) {
1715 this.manager = manager;
1716 this.set(value);
1717 }
1718 /**
1719 * @private
1720 * set the touchAction value on the element or enable the polyfill
1721 * @param {String} value
1722 */
1723
1724
1725 var _proto = TouchAction.prototype;
1726
1727 _proto.set = function set(value) {
1728 // find out the touch-action by the event handlers
1729 if (value === TOUCH_ACTION_COMPUTE) {
1730 value = this.compute();
1731 }
1732
1733 if (NATIVE_TOUCH_ACTION && this.manager.element.style && TOUCH_ACTION_MAP[value]) {
1734 this.manager.element.style[PREFIXED_TOUCH_ACTION] = value;
1735 }
1736
1737 this.actions = value.toLowerCase().trim();
1738 };
1739 /**
1740 * @private
1741 * just re-set the touchAction value
1742 */
1743
1744
1745 _proto.update = function update() {
1746 this.set(this.manager.options.touchAction);
1747 };
1748 /**
1749 * @private
1750 * compute the value for the touchAction property based on the recognizer's settings
1751 * @returns {String} value
1752 */
1753
1754
1755 _proto.compute = function compute() {
1756 var actions = [];
1757 each(this.manager.recognizers, function (recognizer) {
1758 if (boolOrFn(recognizer.options.enable, [recognizer])) {
1759 actions = actions.concat(recognizer.getTouchAction());
1760 }
1761 });
1762 return cleanTouchActions(actions.join(' '));
1763 };
1764 /**
1765 * @private
1766 * this method is called on each input cycle and provides the preventing of the browser behavior
1767 * @param {Object} input
1768 */
1769
1770
1771 _proto.preventDefaults = function preventDefaults(input) {
1772 var srcEvent = input.srcEvent;
1773 var direction = input.offsetDirection; // if the touch action did prevented once this session
1774
1775 if (this.manager.session.prevented) {
1776 srcEvent.preventDefault();
1777 return;
1778 }
1779
1780 var actions = this.actions;
1781 var hasNone = inStr(actions, TOUCH_ACTION_NONE) && !TOUCH_ACTION_MAP[TOUCH_ACTION_NONE];
1782 var hasPanY = inStr(actions, TOUCH_ACTION_PAN_Y) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_Y];
1783 var hasPanX = inStr(actions, TOUCH_ACTION_PAN_X) && !TOUCH_ACTION_MAP[TOUCH_ACTION_PAN_X];
1784
1785 if (hasNone) {
1786 // do not prevent defaults if this is a tap gesture
1787 var isTapPointer = input.pointers.length === 1;
1788 var isTapMovement = input.distance < 2;
1789 var isTapTouchTime = input.deltaTime < 250;
1790
1791 if (isTapPointer && isTapMovement && isTapTouchTime) {
1792 return;
1793 }
1794 }
1795
1796 if (hasPanX && hasPanY) {
1797 // `pan-x pan-y` means browser handles all scrolling/panning, do not prevent
1798 return;
1799 }
1800
1801 if (hasNone || hasPanY && direction & DIRECTION_HORIZONTAL || hasPanX && direction & DIRECTION_VERTICAL) {
1802 return this.preventSrc(srcEvent);
1803 }
1804 };
1805 /**
1806 * @private
1807 * call preventDefault to prevent the browser's default behavior (scrolling in most cases)
1808 * @param {Object} srcEvent
1809 */
1810
1811
1812 _proto.preventSrc = function preventSrc(srcEvent) {
1813 this.manager.session.prevented = true;
1814 srcEvent.preventDefault();
1815 };
1816
1817 return TouchAction;
1818 }();
1819
1820 /**
1821 * @private
1822 * find if a node is in the given parent
1823 * @method hasParent
1824 * @param {HTMLElement} node
1825 * @param {HTMLElement} parent
1826 * @return {Boolean} found
1827 */
1828 function hasParent(node, parent) {
1829 while (node) {
1830 if (node === parent) {
1831 return true;
1832 }
1833
1834 node = node.parentNode;
1835 }
1836
1837 return false;
1838 }
1839
1840 /**
1841 * @private
1842 * get the center of all the pointers
1843 * @param {Array} pointers
1844 * @return {Object} center contains `x` and `y` properties
1845 */
1846
1847 function getCenter(pointers) {
1848 var pointersLength = pointers.length; // no need to loop when only one touch
1849
1850 if (pointersLength === 1) {
1851 return {
1852 x: round(pointers[0].clientX),
1853 y: round(pointers[0].clientY)
1854 };
1855 }
1856
1857 var x = 0;
1858 var y = 0;
1859 var i = 0;
1860
1861 while (i < pointersLength) {
1862 x += pointers[i].clientX;
1863 y += pointers[i].clientY;
1864 i++;
1865 }
1866
1867 return {
1868 x: round(x / pointersLength),
1869 y: round(y / pointersLength)
1870 };
1871 }
1872
1873 /**
1874 * @private
1875 * create a simple clone from the input used for storage of firstInput and firstMultiple
1876 * @param {Object} input
1877 * @returns {Object} clonedInputData
1878 */
1879
1880 function simpleCloneInputData(input) {
1881 // make a simple copy of the pointers because we will get a reference if we don't
1882 // we only need clientXY for the calculations
1883 var pointers = [];
1884 var i = 0;
1885
1886 while (i < input.pointers.length) {
1887 pointers[i] = {
1888 clientX: round(input.pointers[i].clientX),
1889 clientY: round(input.pointers[i].clientY)
1890 };
1891 i++;
1892 }
1893
1894 return {
1895 timeStamp: now(),
1896 pointers: pointers,
1897 center: getCenter(pointers),
1898 deltaX: input.deltaX,
1899 deltaY: input.deltaY
1900 };
1901 }
1902
1903 /**
1904 * @private
1905 * calculate the absolute distance between two points
1906 * @param {Object} p1 {x, y}
1907 * @param {Object} p2 {x, y}
1908 * @param {Array} [props] containing x and y keys
1909 * @return {Number} distance
1910 */
1911
1912 function getDistance(p1, p2, props) {
1913 if (!props) {
1914 props = PROPS_XY;
1915 }
1916
1917 var x = p2[props[0]] - p1[props[0]];
1918 var y = p2[props[1]] - p1[props[1]];
1919 return Math.sqrt(x * x + y * y);
1920 }
1921
1922 /**
1923 * @private
1924 * calculate the angle between two coordinates
1925 * @param {Object} p1
1926 * @param {Object} p2
1927 * @param {Array} [props] containing x and y keys
1928 * @return {Number} angle
1929 */
1930
1931 function getAngle(p1, p2, props) {
1932 if (!props) {
1933 props = PROPS_XY;
1934 }
1935
1936 var x = p2[props[0]] - p1[props[0]];
1937 var y = p2[props[1]] - p1[props[1]];
1938 return Math.atan2(y, x) * 180 / Math.PI;
1939 }
1940
1941 /**
1942 * @private
1943 * get the direction between two points
1944 * @param {Number} x
1945 * @param {Number} y
1946 * @return {Number} direction
1947 */
1948
1949 function getDirection(x, y) {
1950 if (x === y) {
1951 return DIRECTION_NONE;
1952 }
1953
1954 if (abs(x) >= abs(y)) {
1955 return x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
1956 }
1957
1958 return y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
1959 }
1960
1961 function computeDeltaXY(session, input) {
1962 var center = input.center; // let { offsetDelta:offset = {}, prevDelta = {}, prevInput = {} } = session;
1963 // jscs throwing error on defalut destructured values and without defaults tests fail
1964
1965 var offset = session.offsetDelta || {};
1966 var prevDelta = session.prevDelta || {};
1967 var prevInput = session.prevInput || {};
1968
1969 if (input.eventType === INPUT_START || prevInput.eventType === INPUT_END) {
1970 prevDelta = session.prevDelta = {
1971 x: prevInput.deltaX || 0,
1972 y: prevInput.deltaY || 0
1973 };
1974 offset = session.offsetDelta = {
1975 x: center.x,
1976 y: center.y
1977 };
1978 }
1979
1980 input.deltaX = prevDelta.x + (center.x - offset.x);
1981 input.deltaY = prevDelta.y + (center.y - offset.y);
1982 }
1983
1984 /**
1985 * @private
1986 * calculate the velocity between two points. unit is in px per ms.
1987 * @param {Number} deltaTime
1988 * @param {Number} x
1989 * @param {Number} y
1990 * @return {Object} velocity `x` and `y`
1991 */
1992 function getVelocity(deltaTime, x, y) {
1993 return {
1994 x: x / deltaTime || 0,
1995 y: y / deltaTime || 0
1996 };
1997 }
1998
1999 /**
2000 * @private
2001 * calculate the scale factor between two pointersets
2002 * no scale is 1, and goes down to 0 when pinched together, and bigger when pinched out
2003 * @param {Array} start array of pointers
2004 * @param {Array} end array of pointers
2005 * @return {Number} scale
2006 */
2007
2008 function getScale(start, end) {
2009 return getDistance(end[0], end[1], PROPS_CLIENT_XY) / getDistance(start[0], start[1], PROPS_CLIENT_XY);
2010 }
2011
2012 /**
2013 * @private
2014 * calculate the rotation degrees between two pointersets
2015 * @param {Array} start array of pointers
2016 * @param {Array} end array of pointers
2017 * @return {Number} rotation
2018 */
2019
2020 function getRotation(start, end) {
2021 return getAngle(end[1], end[0], PROPS_CLIENT_XY) + getAngle(start[1], start[0], PROPS_CLIENT_XY);
2022 }
2023
2024 /**
2025 * @private
2026 * velocity is calculated every x ms
2027 * @param {Object} session
2028 * @param {Object} input
2029 */
2030
2031 function computeIntervalInputData(session, input) {
2032 var last = session.lastInterval || input;
2033 var deltaTime = input.timeStamp - last.timeStamp;
2034 var velocity;
2035 var velocityX;
2036 var velocityY;
2037 var direction;
2038
2039 if (input.eventType !== INPUT_CANCEL && (deltaTime > COMPUTE_INTERVAL || last.velocity === undefined)) {
2040 var deltaX = input.deltaX - last.deltaX;
2041 var deltaY = input.deltaY - last.deltaY;
2042 var v = getVelocity(deltaTime, deltaX, deltaY);
2043 velocityX = v.x;
2044 velocityY = v.y;
2045 velocity = abs(v.x) > abs(v.y) ? v.x : v.y;
2046 direction = getDirection(deltaX, deltaY);
2047 session.lastInterval = input;
2048 } else {
2049 // use latest velocity info if it doesn't overtake a minimum period
2050 velocity = last.velocity;
2051 velocityX = last.velocityX;
2052 velocityY = last.velocityY;
2053 direction = last.direction;
2054 }
2055
2056 input.velocity = velocity;
2057 input.velocityX = velocityX;
2058 input.velocityY = velocityY;
2059 input.direction = direction;
2060 }
2061
2062 /**
2063 * @private
2064 * extend the data with some usable properties like scale, rotate, velocity etc
2065 * @param {Object} manager
2066 * @param {Object} input
2067 */
2068
2069 function computeInputData(manager, input) {
2070 var session = manager.session;
2071 var pointers = input.pointers;
2072 var pointersLength = pointers.length; // store the first input to calculate the distance and direction
2073
2074 if (!session.firstInput) {
2075 session.firstInput = simpleCloneInputData(input);
2076 } // to compute scale and rotation we need to store the multiple touches
2077
2078
2079 if (pointersLength > 1 && !session.firstMultiple) {
2080 session.firstMultiple = simpleCloneInputData(input);
2081 } else if (pointersLength === 1) {
2082 session.firstMultiple = false;
2083 }
2084
2085 var firstInput = session.firstInput,
2086 firstMultiple = session.firstMultiple;
2087 var offsetCenter = firstMultiple ? firstMultiple.center : firstInput.center;
2088 var center = input.center = getCenter(pointers);
2089 input.timeStamp = now();
2090 input.deltaTime = input.timeStamp - firstInput.timeStamp;
2091 input.angle = getAngle(offsetCenter, center);
2092 input.distance = getDistance(offsetCenter, center);
2093 computeDeltaXY(session, input);
2094 input.offsetDirection = getDirection(input.deltaX, input.deltaY);
2095 var overallVelocity = getVelocity(input.deltaTime, input.deltaX, input.deltaY);
2096 input.overallVelocityX = overallVelocity.x;
2097 input.overallVelocityY = overallVelocity.y;
2098 input.overallVelocity = abs(overallVelocity.x) > abs(overallVelocity.y) ? overallVelocity.x : overallVelocity.y;
2099 input.scale = firstMultiple ? getScale(firstMultiple.pointers, pointers) : 1;
2100 input.rotation = firstMultiple ? getRotation(firstMultiple.pointers, pointers) : 0;
2101 input.maxPointers = !session.prevInput ? input.pointers.length : input.pointers.length > session.prevInput.maxPointers ? input.pointers.length : session.prevInput.maxPointers;
2102 computeIntervalInputData(session, input); // find the correct target
2103
2104 var target = manager.element;
2105 var srcEvent = input.srcEvent;
2106 var srcEventTarget;
2107
2108 if (srcEvent.composedPath) {
2109 srcEventTarget = srcEvent.composedPath()[0];
2110 } else if (srcEvent.path) {
2111 srcEventTarget = srcEvent.path[0];
2112 } else {
2113 srcEventTarget = srcEvent.target;
2114 }
2115
2116 if (hasParent(srcEventTarget, target)) {
2117 target = srcEventTarget;
2118 }
2119
2120 input.target = target;
2121 }
2122
2123 /**
2124 * @private
2125 * handle input events
2126 * @param {Manager} manager
2127 * @param {String} eventType
2128 * @param {Object} input
2129 */
2130
2131 function inputHandler(manager, eventType, input) {
2132 var pointersLen = input.pointers.length;
2133 var changedPointersLen = input.changedPointers.length;
2134 var isFirst = eventType & INPUT_START && pointersLen - changedPointersLen === 0;
2135 var isFinal = eventType & (INPUT_END | INPUT_CANCEL) && pointersLen - changedPointersLen === 0;
2136 input.isFirst = !!isFirst;
2137 input.isFinal = !!isFinal;
2138
2139 if (isFirst) {
2140 manager.session = {};
2141 } // source event is the normalized value of the domEvents
2142 // like 'touchstart, mouseup, pointerdown'
2143
2144
2145 input.eventType = eventType; // compute scale, rotation etc
2146
2147 computeInputData(manager, input); // emit secret event
2148
2149 manager.emit('hammer.input', input);
2150 manager.recognize(input);
2151 manager.session.prevInput = input;
2152 }
2153
2154 /**
2155 * @private
2156 * split string on whitespace
2157 * @param {String} str
2158 * @returns {Array} words
2159 */
2160 function splitStr(str) {
2161 return str.trim().split(/\s+/g);
2162 }
2163
2164 /**
2165 * @private
2166 * addEventListener with multiple events at once
2167 * @param {EventTarget} target
2168 * @param {String} types
2169 * @param {Function} handler
2170 */
2171
2172 function addEventListeners(target, types, handler) {
2173 each(splitStr(types), function (type) {
2174 target.addEventListener(type, handler, false);
2175 });
2176 }
2177
2178 /**
2179 * @private
2180 * removeEventListener with multiple events at once
2181 * @param {EventTarget} target
2182 * @param {String} types
2183 * @param {Function} handler
2184 */
2185
2186 function removeEventListeners(target, types, handler) {
2187 each(splitStr(types), function (type) {
2188 target.removeEventListener(type, handler, false);
2189 });
2190 }
2191
2192 /**
2193 * @private
2194 * get the window object of an element
2195 * @param {HTMLElement} element
2196 * @returns {DocumentView|Window}
2197 */
2198 function getWindowForElement(element) {
2199 var doc = element.ownerDocument || element;
2200 return doc.defaultView || doc.parentWindow || window;
2201 }
2202
2203 /**
2204 * @private
2205 * create new input type manager
2206 * @param {Manager} manager
2207 * @param {Function} callback
2208 * @returns {Input}
2209 * @constructor
2210 */
2211
2212 var Input =
2213 /*#__PURE__*/
2214 function () {
2215 function Input(manager, callback) {
2216 var self = this;
2217 this.manager = manager;
2218 this.callback = callback;
2219 this.element = manager.element;
2220 this.target = manager.options.inputTarget; // smaller wrapper around the handler, for the scope and the enabled state of the manager,
2221 // so when disabled the input events are completely bypassed.
2222
2223 this.domHandler = function (ev) {
2224 if (boolOrFn(manager.options.enable, [manager])) {
2225 self.handler(ev);
2226 }
2227 };
2228
2229 this.init();
2230 }
2231 /**
2232 * @private
2233 * should handle the inputEvent data and trigger the callback
2234 * @virtual
2235 */
2236
2237
2238 var _proto = Input.prototype;
2239
2240 _proto.handler = function handler() {};
2241 /**
2242 * @private
2243 * bind the events
2244 */
2245
2246
2247 _proto.init = function init() {
2248 this.evEl && addEventListeners(this.element, this.evEl, this.domHandler);
2249 this.evTarget && addEventListeners(this.target, this.evTarget, this.domHandler);
2250 this.evWin && addEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
2251 };
2252 /**
2253 * @private
2254 * unbind the events
2255 */
2256
2257
2258 _proto.destroy = function destroy() {
2259 this.evEl && removeEventListeners(this.element, this.evEl, this.domHandler);
2260 this.evTarget && removeEventListeners(this.target, this.evTarget, this.domHandler);
2261 this.evWin && removeEventListeners(getWindowForElement(this.element), this.evWin, this.domHandler);
2262 };
2263
2264 return Input;
2265 }();
2266
2267 /**
2268 * @private
2269 * find if a array contains the object using indexOf or a simple polyFill
2270 * @param {Array} src
2271 * @param {String} find
2272 * @param {String} [findByKey]
2273 * @return {Boolean|Number} false when not found, or the index
2274 */
2275 function inArray(src, find, findByKey) {
2276 if (src.indexOf && !findByKey) {
2277 return src.indexOf(find);
2278 } else {
2279 var i = 0;
2280
2281 while (i < src.length) {
2282 if (findByKey && src[i][findByKey] == find || !findByKey && src[i] === find) {
2283 // do not use === here, test fails
2284 return i;
2285 }
2286
2287 i++;
2288 }
2289
2290 return -1;
2291 }
2292 }
2293
2294 var POINTER_INPUT_MAP = {
2295 pointerdown: INPUT_START,
2296 pointermove: INPUT_MOVE,
2297 pointerup: INPUT_END,
2298 pointercancel: INPUT_CANCEL,
2299 pointerout: INPUT_CANCEL
2300 }; // in IE10 the pointer types is defined as an enum
2301
2302 var IE10_POINTER_TYPE_ENUM = {
2303 2: INPUT_TYPE_TOUCH,
2304 3: INPUT_TYPE_PEN,
2305 4: INPUT_TYPE_MOUSE,
2306 5: INPUT_TYPE_KINECT // see https://twitter.com/jacobrossi/status/480596438489890816
2307
2308 };
2309 var POINTER_ELEMENT_EVENTS = 'pointerdown';
2310 var POINTER_WINDOW_EVENTS = 'pointermove pointerup pointercancel'; // IE10 has prefixed support, and case-sensitive
2311
2312 if (win.MSPointerEvent && !win.PointerEvent) {
2313 POINTER_ELEMENT_EVENTS = 'MSPointerDown';
2314 POINTER_WINDOW_EVENTS = 'MSPointerMove MSPointerUp MSPointerCancel';
2315 }
2316 /**
2317 * @private
2318 * Pointer events input
2319 * @constructor
2320 * @extends Input
2321 */
2322
2323
2324 var PointerEventInput =
2325 /*#__PURE__*/
2326 function (_Input) {
2327 _inheritsLoose(PointerEventInput, _Input);
2328
2329 function PointerEventInput() {
2330 var _this;
2331
2332 var proto = PointerEventInput.prototype;
2333 proto.evEl = POINTER_ELEMENT_EVENTS;
2334 proto.evWin = POINTER_WINDOW_EVENTS;
2335 _this = _Input.apply(this, arguments) || this;
2336 _this.store = _this.manager.session.pointerEvents = [];
2337 return _this;
2338 }
2339 /**
2340 * @private
2341 * handle mouse events
2342 * @param {Object} ev
2343 */
2344
2345
2346 var _proto = PointerEventInput.prototype;
2347
2348 _proto.handler = function handler(ev) {
2349 var store = this.store;
2350 var removePointer = false;
2351 var eventTypeNormalized = ev.type.toLowerCase().replace('ms', '');
2352 var eventType = POINTER_INPUT_MAP[eventTypeNormalized];
2353 var pointerType = IE10_POINTER_TYPE_ENUM[ev.pointerType] || ev.pointerType;
2354 var isTouch = pointerType === INPUT_TYPE_TOUCH; // get index of the event in the store
2355
2356 var storeIndex = inArray(store, ev.pointerId, 'pointerId'); // start and mouse must be down
2357
2358 if (eventType & INPUT_START && (ev.button === 0 || isTouch)) {
2359 if (storeIndex < 0) {
2360 store.push(ev);
2361 storeIndex = store.length - 1;
2362 }
2363 } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
2364 removePointer = true;
2365 } // it not found, so the pointer hasn't been down (so it's probably a hover)
2366
2367
2368 if (storeIndex < 0) {
2369 return;
2370 } // update the event in the store
2371
2372
2373 store[storeIndex] = ev;
2374 this.callback(this.manager, eventType, {
2375 pointers: store,
2376 changedPointers: [ev],
2377 pointerType: pointerType,
2378 srcEvent: ev
2379 });
2380
2381 if (removePointer) {
2382 // remove from the store
2383 store.splice(storeIndex, 1);
2384 }
2385 };
2386
2387 return PointerEventInput;
2388 }(Input);
2389
2390 /**
2391 * @private
2392 * convert array-like objects to real arrays
2393 * @param {Object} obj
2394 * @returns {Array}
2395 */
2396 function toArray$1(obj) {
2397 return Array.prototype.slice.call(obj, 0);
2398 }
2399
2400 /**
2401 * @private
2402 * unique array with objects based on a key (like 'id') or just by the array's value
2403 * @param {Array} src [{id:1},{id:2},{id:1}]
2404 * @param {String} [key]
2405 * @param {Boolean} [sort=False]
2406 * @returns {Array} [{id:1},{id:2}]
2407 */
2408
2409 function uniqueArray(src, key, sort) {
2410 var results = [];
2411 var values = [];
2412 var i = 0;
2413
2414 while (i < src.length) {
2415 var val = key ? src[i][key] : src[i];
2416
2417 if (inArray(values, val) < 0) {
2418 results.push(src[i]);
2419 }
2420
2421 values[i] = val;
2422 i++;
2423 }
2424
2425 if (sort) {
2426 if (!key) {
2427 results = results.sort();
2428 } else {
2429 results = results.sort(function (a, b) {
2430 return a[key] > b[key];
2431 });
2432 }
2433 }
2434
2435 return results;
2436 }
2437
2438 var TOUCH_INPUT_MAP = {
2439 touchstart: INPUT_START,
2440 touchmove: INPUT_MOVE,
2441 touchend: INPUT_END,
2442 touchcancel: INPUT_CANCEL
2443 };
2444 var TOUCH_TARGET_EVENTS = 'touchstart touchmove touchend touchcancel';
2445 /**
2446 * @private
2447 * Multi-user touch events input
2448 * @constructor
2449 * @extends Input
2450 */
2451
2452 var TouchInput =
2453 /*#__PURE__*/
2454 function (_Input) {
2455 _inheritsLoose(TouchInput, _Input);
2456
2457 function TouchInput() {
2458 var _this;
2459
2460 TouchInput.prototype.evTarget = TOUCH_TARGET_EVENTS;
2461 _this = _Input.apply(this, arguments) || this;
2462 _this.targetIds = {}; // this.evTarget = TOUCH_TARGET_EVENTS;
2463
2464 return _this;
2465 }
2466
2467 var _proto = TouchInput.prototype;
2468
2469 _proto.handler = function handler(ev) {
2470 var type = TOUCH_INPUT_MAP[ev.type];
2471 var touches = getTouches.call(this, ev, type);
2472
2473 if (!touches) {
2474 return;
2475 }
2476
2477 this.callback(this.manager, type, {
2478 pointers: touches[0],
2479 changedPointers: touches[1],
2480 pointerType: INPUT_TYPE_TOUCH,
2481 srcEvent: ev
2482 });
2483 };
2484
2485 return TouchInput;
2486 }(Input);
2487
2488 function getTouches(ev, type) {
2489 var allTouches = toArray$1(ev.touches);
2490 var targetIds = this.targetIds; // when there is only one touch, the process can be simplified
2491
2492 if (type & (INPUT_START | INPUT_MOVE) && allTouches.length === 1) {
2493 targetIds[allTouches[0].identifier] = true;
2494 return [allTouches, allTouches];
2495 }
2496
2497 var i;
2498 var targetTouches;
2499 var changedTouches = toArray$1(ev.changedTouches);
2500 var changedTargetTouches = [];
2501 var target = this.target; // get target touches from touches
2502
2503 targetTouches = allTouches.filter(function (touch) {
2504 return hasParent(touch.target, target);
2505 }); // collect touches
2506
2507 if (type === INPUT_START) {
2508 i = 0;
2509
2510 while (i < targetTouches.length) {
2511 targetIds[targetTouches[i].identifier] = true;
2512 i++;
2513 }
2514 } // filter changed touches to only contain touches that exist in the collected target ids
2515
2516
2517 i = 0;
2518
2519 while (i < changedTouches.length) {
2520 if (targetIds[changedTouches[i].identifier]) {
2521 changedTargetTouches.push(changedTouches[i]);
2522 } // cleanup removed touches
2523
2524
2525 if (type & (INPUT_END | INPUT_CANCEL)) {
2526 delete targetIds[changedTouches[i].identifier];
2527 }
2528
2529 i++;
2530 }
2531
2532 if (!changedTargetTouches.length) {
2533 return;
2534 }
2535
2536 return [// merge targetTouches with changedTargetTouches so it contains ALL touches, including 'end' and 'cancel'
2537 uniqueArray(targetTouches.concat(changedTargetTouches), 'identifier', true), changedTargetTouches];
2538 }
2539
2540 var MOUSE_INPUT_MAP = {
2541 mousedown: INPUT_START,
2542 mousemove: INPUT_MOVE,
2543 mouseup: INPUT_END
2544 };
2545 var MOUSE_ELEMENT_EVENTS = 'mousedown';
2546 var MOUSE_WINDOW_EVENTS = 'mousemove mouseup';
2547 /**
2548 * @private
2549 * Mouse events input
2550 * @constructor
2551 * @extends Input
2552 */
2553
2554 var MouseInput =
2555 /*#__PURE__*/
2556 function (_Input) {
2557 _inheritsLoose(MouseInput, _Input);
2558
2559 function MouseInput() {
2560 var _this;
2561
2562 var proto = MouseInput.prototype;
2563 proto.evEl = MOUSE_ELEMENT_EVENTS;
2564 proto.evWin = MOUSE_WINDOW_EVENTS;
2565 _this = _Input.apply(this, arguments) || this;
2566 _this.pressed = false; // mousedown state
2567
2568 return _this;
2569 }
2570 /**
2571 * @private
2572 * handle mouse events
2573 * @param {Object} ev
2574 */
2575
2576
2577 var _proto = MouseInput.prototype;
2578
2579 _proto.handler = function handler(ev) {
2580 var eventType = MOUSE_INPUT_MAP[ev.type]; // on start we want to have the left mouse button down
2581
2582 if (eventType & INPUT_START && ev.button === 0) {
2583 this.pressed = true;
2584 }
2585
2586 if (eventType & INPUT_MOVE && ev.which !== 1) {
2587 eventType = INPUT_END;
2588 } // mouse must be down
2589
2590
2591 if (!this.pressed) {
2592 return;
2593 }
2594
2595 if (eventType & INPUT_END) {
2596 this.pressed = false;
2597 }
2598
2599 this.callback(this.manager, eventType, {
2600 pointers: [ev],
2601 changedPointers: [ev],
2602 pointerType: INPUT_TYPE_MOUSE,
2603 srcEvent: ev
2604 });
2605 };
2606
2607 return MouseInput;
2608 }(Input);
2609
2610 /**
2611 * @private
2612 * Combined touch and mouse input
2613 *
2614 * Touch has a higher priority then mouse, and while touching no mouse events are allowed.
2615 * This because touch devices also emit mouse events while doing a touch.
2616 *
2617 * @constructor
2618 * @extends Input
2619 */
2620
2621 var DEDUP_TIMEOUT = 2500;
2622 var DEDUP_DISTANCE = 25;
2623
2624 function setLastTouch(eventData) {
2625 var _eventData$changedPoi = eventData.changedPointers,
2626 touch = _eventData$changedPoi[0];
2627
2628 if (touch.identifier === this.primaryTouch) {
2629 var lastTouch = {
2630 x: touch.clientX,
2631 y: touch.clientY
2632 };
2633 var lts = this.lastTouches;
2634 this.lastTouches.push(lastTouch);
2635
2636 var removeLastTouch = function removeLastTouch() {
2637 var i = lts.indexOf(lastTouch);
2638
2639 if (i > -1) {
2640 lts.splice(i, 1);
2641 }
2642 };
2643
2644 setTimeout(removeLastTouch, DEDUP_TIMEOUT);
2645 }
2646 }
2647
2648 function recordTouches(eventType, eventData) {
2649 if (eventType & INPUT_START) {
2650 this.primaryTouch = eventData.changedPointers[0].identifier;
2651 setLastTouch.call(this, eventData);
2652 } else if (eventType & (INPUT_END | INPUT_CANCEL)) {
2653 setLastTouch.call(this, eventData);
2654 }
2655 }
2656
2657 function isSyntheticEvent(eventData) {
2658 var x = eventData.srcEvent.clientX;
2659 var y = eventData.srcEvent.clientY;
2660
2661 for (var i = 0; i < this.lastTouches.length; i++) {
2662 var t = this.lastTouches[i];
2663 var dx = Math.abs(x - t.x);
2664 var dy = Math.abs(y - t.y);
2665
2666 if (dx <= DEDUP_DISTANCE && dy <= DEDUP_DISTANCE) {
2667 return true;
2668 }
2669 }
2670
2671 return false;
2672 }
2673
2674 var TouchMouseInput =
2675 /*#__PURE__*/
2676 function () {
2677 var TouchMouseInput =
2678 /*#__PURE__*/
2679 function (_Input) {
2680 _inheritsLoose(TouchMouseInput, _Input);
2681
2682 function TouchMouseInput(_manager, callback) {
2683 var _this;
2684
2685 _this = _Input.call(this, _manager, callback) || this;
2686
2687 _this.handler = function (manager, inputEvent, inputData) {
2688 var isTouch = inputData.pointerType === INPUT_TYPE_TOUCH;
2689 var isMouse = inputData.pointerType === INPUT_TYPE_MOUSE;
2690
2691 if (isMouse && inputData.sourceCapabilities && inputData.sourceCapabilities.firesTouchEvents) {
2692 return;
2693 } // when we're in a touch event, record touches to de-dupe synthetic mouse event
2694
2695
2696 if (isTouch) {
2697 recordTouches.call(_assertThisInitialized(_assertThisInitialized(_this)), inputEvent, inputData);
2698 } else if (isMouse && isSyntheticEvent.call(_assertThisInitialized(_assertThisInitialized(_this)), inputData)) {
2699 return;
2700 }
2701
2702 _this.callback(manager, inputEvent, inputData);
2703 };
2704
2705 _this.touch = new TouchInput(_this.manager, _this.handler);
2706 _this.mouse = new MouseInput(_this.manager, _this.handler);
2707 _this.primaryTouch = null;
2708 _this.lastTouches = [];
2709 return _this;
2710 }
2711 /**
2712 * @private
2713 * handle mouse and touch events
2714 * @param {Hammer} manager
2715 * @param {String} inputEvent
2716 * @param {Object} inputData
2717 */
2718
2719
2720 var _proto = TouchMouseInput.prototype;
2721
2722 /**
2723 * @private
2724 * remove the event listeners
2725 */
2726 _proto.destroy = function destroy() {
2727 this.touch.destroy();
2728 this.mouse.destroy();
2729 };
2730
2731 return TouchMouseInput;
2732 }(Input);
2733
2734 return TouchMouseInput;
2735 }();
2736
2737 /**
2738 * @private
2739 * create new input type manager
2740 * called by the Manager constructor
2741 * @param {Hammer} manager
2742 * @returns {Input}
2743 */
2744
2745 function createInputInstance(manager) {
2746 var Type; // let inputClass = manager.options.inputClass;
2747
2748 var inputClass = manager.options.inputClass;
2749
2750 if (inputClass) {
2751 Type = inputClass;
2752 } else if (SUPPORT_POINTER_EVENTS) {
2753 Type = PointerEventInput;
2754 } else if (SUPPORT_ONLY_TOUCH) {
2755 Type = TouchInput;
2756 } else if (!SUPPORT_TOUCH) {
2757 Type = MouseInput;
2758 } else {
2759 Type = TouchMouseInput;
2760 }
2761
2762 return new Type(manager, inputHandler);
2763 }
2764
2765 /**
2766 * @private
2767 * if the argument is an array, we want to execute the fn on each entry
2768 * if it aint an array we don't want to do a thing.
2769 * this is used by all the methods that accept a single and array argument.
2770 * @param {*|Array} arg
2771 * @param {String} fn
2772 * @param {Object} [context]
2773 * @returns {Boolean}
2774 */
2775
2776 function invokeArrayArg(arg, fn, context) {
2777 if (Array.isArray(arg)) {
2778 each(arg, context[fn], context);
2779 return true;
2780 }
2781
2782 return false;
2783 }
2784
2785 var STATE_POSSIBLE = 1;
2786 var STATE_BEGAN = 2;
2787 var STATE_CHANGED = 4;
2788 var STATE_ENDED = 8;
2789 var STATE_RECOGNIZED = STATE_ENDED;
2790 var STATE_CANCELLED = 16;
2791 var STATE_FAILED = 32;
2792
2793 /**
2794 * @private
2795 * get a unique id
2796 * @returns {number} uniqueId
2797 */
2798 var _uniqueId = 1;
2799 function uniqueId() {
2800 return _uniqueId++;
2801 }
2802
2803 /**
2804 * @private
2805 * get a recognizer by name if it is bound to a manager
2806 * @param {Recognizer|String} otherRecognizer
2807 * @param {Recognizer} recognizer
2808 * @returns {Recognizer}
2809 */
2810 function getRecognizerByNameIfManager(otherRecognizer, recognizer) {
2811 var manager = recognizer.manager;
2812
2813 if (manager) {
2814 return manager.get(otherRecognizer);
2815 }
2816
2817 return otherRecognizer;
2818 }
2819
2820 /**
2821 * @private
2822 * get a usable string, used as event postfix
2823 * @param {constant} state
2824 * @returns {String} state
2825 */
2826
2827 function stateStr(state) {
2828 if (state & STATE_CANCELLED) {
2829 return 'cancel';
2830 } else if (state & STATE_ENDED) {
2831 return 'end';
2832 } else if (state & STATE_CHANGED) {
2833 return 'move';
2834 } else if (state & STATE_BEGAN) {
2835 return 'start';
2836 }
2837
2838 return '';
2839 }
2840
2841 /**
2842 * @private
2843 * Recognizer flow explained; *
2844 * All recognizers have the initial state of POSSIBLE when a input session starts.
2845 * The definition of a input session is from the first input until the last input, with all it's movement in it. *
2846 * Example session for mouse-input: mousedown -> mousemove -> mouseup
2847 *
2848 * On each recognizing cycle (see Manager.recognize) the .recognize() method is executed
2849 * which determines with state it should be.
2850 *
2851 * If the recognizer has the state FAILED, CANCELLED or RECOGNIZED (equals ENDED), it is reset to
2852 * POSSIBLE to give it another change on the next cycle.
2853 *
2854 * Possible
2855 * |
2856 * +-----+---------------+
2857 * | |
2858 * +-----+-----+ |
2859 * | | |
2860 * Failed Cancelled |
2861 * +-------+------+
2862 * | |
2863 * Recognized Began
2864 * |
2865 * Changed
2866 * |
2867 * Ended/Recognized
2868 */
2869
2870 /**
2871 * @private
2872 * Recognizer
2873 * Every recognizer needs to extend from this class.
2874 * @constructor
2875 * @param {Object} options
2876 */
2877
2878 var Recognizer =
2879 /*#__PURE__*/
2880 function () {
2881 function Recognizer(options) {
2882 if (options === void 0) {
2883 options = {};
2884 }
2885
2886 this.options = _extends({
2887 enable: true
2888 }, options);
2889 this.id = uniqueId();
2890 this.manager = null; // default is enable true
2891
2892 this.state = STATE_POSSIBLE;
2893 this.simultaneous = {};
2894 this.requireFail = [];
2895 }
2896 /**
2897 * @private
2898 * set options
2899 * @param {Object} options
2900 * @return {Recognizer}
2901 */
2902
2903
2904 var _proto = Recognizer.prototype;
2905
2906 _proto.set = function set(options) {
2907 assign$1(this.options, options); // also update the touchAction, in case something changed about the directions/enabled state
2908
2909 this.manager && this.manager.touchAction.update();
2910 return this;
2911 };
2912 /**
2913 * @private
2914 * recognize simultaneous with an other recognizer.
2915 * @param {Recognizer} otherRecognizer
2916 * @returns {Recognizer} this
2917 */
2918
2919
2920 _proto.recognizeWith = function recognizeWith(otherRecognizer) {
2921 if (invokeArrayArg(otherRecognizer, 'recognizeWith', this)) {
2922 return this;
2923 }
2924
2925 var simultaneous = this.simultaneous;
2926 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
2927
2928 if (!simultaneous[otherRecognizer.id]) {
2929 simultaneous[otherRecognizer.id] = otherRecognizer;
2930 otherRecognizer.recognizeWith(this);
2931 }
2932
2933 return this;
2934 };
2935 /**
2936 * @private
2937 * drop the simultaneous link. it doesnt remove the link on the other recognizer.
2938 * @param {Recognizer} otherRecognizer
2939 * @returns {Recognizer} this
2940 */
2941
2942
2943 _proto.dropRecognizeWith = function dropRecognizeWith(otherRecognizer) {
2944 if (invokeArrayArg(otherRecognizer, 'dropRecognizeWith', this)) {
2945 return this;
2946 }
2947
2948 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
2949 delete this.simultaneous[otherRecognizer.id];
2950 return this;
2951 };
2952 /**
2953 * @private
2954 * recognizer can only run when an other is failing
2955 * @param {Recognizer} otherRecognizer
2956 * @returns {Recognizer} this
2957 */
2958
2959
2960 _proto.requireFailure = function requireFailure(otherRecognizer) {
2961 if (invokeArrayArg(otherRecognizer, 'requireFailure', this)) {
2962 return this;
2963 }
2964
2965 var requireFail = this.requireFail;
2966 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
2967
2968 if (inArray(requireFail, otherRecognizer) === -1) {
2969 requireFail.push(otherRecognizer);
2970 otherRecognizer.requireFailure(this);
2971 }
2972
2973 return this;
2974 };
2975 /**
2976 * @private
2977 * drop the requireFailure link. it does not remove the link on the other recognizer.
2978 * @param {Recognizer} otherRecognizer
2979 * @returns {Recognizer} this
2980 */
2981
2982
2983 _proto.dropRequireFailure = function dropRequireFailure(otherRecognizer) {
2984 if (invokeArrayArg(otherRecognizer, 'dropRequireFailure', this)) {
2985 return this;
2986 }
2987
2988 otherRecognizer = getRecognizerByNameIfManager(otherRecognizer, this);
2989 var index = inArray(this.requireFail, otherRecognizer);
2990
2991 if (index > -1) {
2992 this.requireFail.splice(index, 1);
2993 }
2994
2995 return this;
2996 };
2997 /**
2998 * @private
2999 * has require failures boolean
3000 * @returns {boolean}
3001 */
3002
3003
3004 _proto.hasRequireFailures = function hasRequireFailures() {
3005 return this.requireFail.length > 0;
3006 };
3007 /**
3008 * @private
3009 * if the recognizer can recognize simultaneous with an other recognizer
3010 * @param {Recognizer} otherRecognizer
3011 * @returns {Boolean}
3012 */
3013
3014
3015 _proto.canRecognizeWith = function canRecognizeWith(otherRecognizer) {
3016 return !!this.simultaneous[otherRecognizer.id];
3017 };
3018 /**
3019 * @private
3020 * You should use `tryEmit` instead of `emit` directly to check
3021 * that all the needed recognizers has failed before emitting.
3022 * @param {Object} input
3023 */
3024
3025
3026 _proto.emit = function emit(input) {
3027 var self = this;
3028 var state = this.state;
3029
3030 function emit(event) {
3031 self.manager.emit(event, input);
3032 } // 'panstart' and 'panmove'
3033
3034
3035 if (state < STATE_ENDED) {
3036 emit(self.options.event + stateStr(state));
3037 }
3038
3039 emit(self.options.event); // simple 'eventName' events
3040
3041 if (input.additionalEvent) {
3042 // additional event(panleft, panright, pinchin, pinchout...)
3043 emit(input.additionalEvent);
3044 } // panend and pancancel
3045
3046
3047 if (state >= STATE_ENDED) {
3048 emit(self.options.event + stateStr(state));
3049 }
3050 };
3051 /**
3052 * @private
3053 * Check that all the require failure recognizers has failed,
3054 * if true, it emits a gesture event,
3055 * otherwise, setup the state to FAILED.
3056 * @param {Object} input
3057 */
3058
3059
3060 _proto.tryEmit = function tryEmit(input) {
3061 if (this.canEmit()) {
3062 return this.emit(input);
3063 } // it's failing anyway
3064
3065
3066 this.state = STATE_FAILED;
3067 };
3068 /**
3069 * @private
3070 * can we emit?
3071 * @returns {boolean}
3072 */
3073
3074
3075 _proto.canEmit = function canEmit() {
3076 var i = 0;
3077
3078 while (i < this.requireFail.length) {
3079 if (!(this.requireFail[i].state & (STATE_FAILED | STATE_POSSIBLE))) {
3080 return false;
3081 }
3082
3083 i++;
3084 }
3085
3086 return true;
3087 };
3088 /**
3089 * @private
3090 * update the recognizer
3091 * @param {Object} inputData
3092 */
3093
3094
3095 _proto.recognize = function recognize(inputData) {
3096 // make a new copy of the inputData
3097 // so we can change the inputData without messing up the other recognizers
3098 var inputDataClone = assign$1({}, inputData); // is is enabled and allow recognizing?
3099
3100 if (!boolOrFn(this.options.enable, [this, inputDataClone])) {
3101 this.reset();
3102 this.state = STATE_FAILED;
3103 return;
3104 } // reset when we've reached the end
3105
3106
3107 if (this.state & (STATE_RECOGNIZED | STATE_CANCELLED | STATE_FAILED)) {
3108 this.state = STATE_POSSIBLE;
3109 }
3110
3111 this.state = this.process(inputDataClone); // the recognizer has recognized a gesture
3112 // so trigger an event
3113
3114 if (this.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED | STATE_CANCELLED)) {
3115 this.tryEmit(inputDataClone);
3116 }
3117 };
3118 /**
3119 * @private
3120 * return the state of the recognizer
3121 * the actual recognizing happens in this method
3122 * @virtual
3123 * @param {Object} inputData
3124 * @returns {constant} STATE
3125 */
3126
3127 /* jshint ignore:start */
3128
3129
3130 _proto.process = function process(inputData) {};
3131 /* jshint ignore:end */
3132
3133 /**
3134 * @private
3135 * return the preferred touch-action
3136 * @virtual
3137 * @returns {Array}
3138 */
3139
3140
3141 _proto.getTouchAction = function getTouchAction() {};
3142 /**
3143 * @private
3144 * called when the gesture isn't allowed to recognize
3145 * like when another is being recognized or it is disabled
3146 * @virtual
3147 */
3148
3149
3150 _proto.reset = function reset() {};
3151
3152 return Recognizer;
3153 }();
3154
3155 /**
3156 * @private
3157 * This recognizer is just used as a base for the simple attribute recognizers.
3158 * @constructor
3159 * @extends Recognizer
3160 */
3161
3162 var AttrRecognizer =
3163 /*#__PURE__*/
3164 function (_Recognizer) {
3165 _inheritsLoose(AttrRecognizer, _Recognizer);
3166
3167 function AttrRecognizer(options) {
3168 if (options === void 0) {
3169 options = {};
3170 }
3171
3172 return _Recognizer.call(this, _extends({
3173 pointers: 1
3174 }, options)) || this;
3175 }
3176 /**
3177 * @private
3178 * Used to check if it the recognizer receives valid input, like input.distance > 10.
3179 * @memberof AttrRecognizer
3180 * @param {Object} input
3181 * @returns {Boolean} recognized
3182 */
3183
3184
3185 var _proto = AttrRecognizer.prototype;
3186
3187 _proto.attrTest = function attrTest(input) {
3188 var optionPointers = this.options.pointers;
3189 return optionPointers === 0 || input.pointers.length === optionPointers;
3190 };
3191 /**
3192 * @private
3193 * Process the input and return the state for the recognizer
3194 * @memberof AttrRecognizer
3195 * @param {Object} input
3196 * @returns {*} State
3197 */
3198
3199
3200 _proto.process = function process(input) {
3201 var state = this.state;
3202 var eventType = input.eventType;
3203 var isRecognized = state & (STATE_BEGAN | STATE_CHANGED);
3204 var isValid = this.attrTest(input); // on cancel input and we've recognized before, return STATE_CANCELLED
3205
3206 if (isRecognized && (eventType & INPUT_CANCEL || !isValid)) {
3207 return state | STATE_CANCELLED;
3208 } else if (isRecognized || isValid) {
3209 if (eventType & INPUT_END) {
3210 return state | STATE_ENDED;
3211 } else if (!(state & STATE_BEGAN)) {
3212 return STATE_BEGAN;
3213 }
3214
3215 return state | STATE_CHANGED;
3216 }
3217
3218 return STATE_FAILED;
3219 };
3220
3221 return AttrRecognizer;
3222 }(Recognizer);
3223
3224 /**
3225 * @private
3226 * direction cons to string
3227 * @param {constant} direction
3228 * @returns {String}
3229 */
3230
3231 function directionStr(direction) {
3232 if (direction === DIRECTION_DOWN) {
3233 return 'down';
3234 } else if (direction === DIRECTION_UP) {
3235 return 'up';
3236 } else if (direction === DIRECTION_LEFT) {
3237 return 'left';
3238 } else if (direction === DIRECTION_RIGHT) {
3239 return 'right';
3240 }
3241
3242 return '';
3243 }
3244
3245 /**
3246 * @private
3247 * Pan
3248 * Recognized when the pointer is down and moved in the allowed direction.
3249 * @constructor
3250 * @extends AttrRecognizer
3251 */
3252
3253 var PanRecognizer =
3254 /*#__PURE__*/
3255 function (_AttrRecognizer) {
3256 _inheritsLoose(PanRecognizer, _AttrRecognizer);
3257
3258 function PanRecognizer(options) {
3259 var _this;
3260
3261 if (options === void 0) {
3262 options = {};
3263 }
3264
3265 _this = _AttrRecognizer.call(this, _extends({
3266 event: 'pan',
3267 threshold: 10,
3268 pointers: 1,
3269 direction: DIRECTION_ALL
3270 }, options)) || this;
3271 _this.pX = null;
3272 _this.pY = null;
3273 return _this;
3274 }
3275
3276 var _proto = PanRecognizer.prototype;
3277
3278 _proto.getTouchAction = function getTouchAction() {
3279 var direction = this.options.direction;
3280 var actions = [];
3281
3282 if (direction & DIRECTION_HORIZONTAL) {
3283 actions.push(TOUCH_ACTION_PAN_Y);
3284 }
3285
3286 if (direction & DIRECTION_VERTICAL) {
3287 actions.push(TOUCH_ACTION_PAN_X);
3288 }
3289
3290 return actions;
3291 };
3292
3293 _proto.directionTest = function directionTest(input) {
3294 var options = this.options;
3295 var hasMoved = true;
3296 var distance = input.distance;
3297 var direction = input.direction;
3298 var x = input.deltaX;
3299 var y = input.deltaY; // lock to axis?
3300
3301 if (!(direction & options.direction)) {
3302 if (options.direction & DIRECTION_HORIZONTAL) {
3303 direction = x === 0 ? DIRECTION_NONE : x < 0 ? DIRECTION_LEFT : DIRECTION_RIGHT;
3304 hasMoved = x !== this.pX;
3305 distance = Math.abs(input.deltaX);
3306 } else {
3307 direction = y === 0 ? DIRECTION_NONE : y < 0 ? DIRECTION_UP : DIRECTION_DOWN;
3308 hasMoved = y !== this.pY;
3309 distance = Math.abs(input.deltaY);
3310 }
3311 }
3312
3313 input.direction = direction;
3314 return hasMoved && distance > options.threshold && direction & options.direction;
3315 };
3316
3317 _proto.attrTest = function attrTest(input) {
3318 return AttrRecognizer.prototype.attrTest.call(this, input) && ( // replace with a super call
3319 this.state & STATE_BEGAN || !(this.state & STATE_BEGAN) && this.directionTest(input));
3320 };
3321
3322 _proto.emit = function emit(input) {
3323 this.pX = input.deltaX;
3324 this.pY = input.deltaY;
3325 var direction = directionStr(input.direction);
3326
3327 if (direction) {
3328 input.additionalEvent = this.options.event + direction;
3329 }
3330
3331 _AttrRecognizer.prototype.emit.call(this, input);
3332 };
3333
3334 return PanRecognizer;
3335 }(AttrRecognizer);
3336
3337 var defaults = {
3338 /**
3339 * @private
3340 * set if DOM events are being triggered.
3341 * But this is slower and unused by simple implementations, so disabled by default.
3342 * @type {Boolean}
3343 * @default false
3344 */
3345 domEvents: false,
3346
3347 /**
3348 * @private
3349 * The value for the touchAction property/fallback.
3350 * When set to `compute` it will magically set the correct value based on the added recognizers.
3351 * @type {String}
3352 * @default compute
3353 */
3354 touchAction: TOUCH_ACTION_COMPUTE,
3355
3356 /**
3357 * @private
3358 * @type {Boolean}
3359 * @default true
3360 */
3361 enable: true,
3362
3363 /**
3364 * @private
3365 * EXPERIMENTAL FEATURE -- can be removed/changed
3366 * Change the parent input target element.
3367 * If Null, then it is being set the to main element.
3368 * @type {Null|EventTarget}
3369 * @default null
3370 */
3371 inputTarget: null,
3372
3373 /**
3374 * @private
3375 * force an input class
3376 * @type {Null|Function}
3377 * @default null
3378 */
3379 inputClass: null,
3380
3381 /**
3382 * @private
3383 * Some CSS properties can be used to improve the working of Hammer.
3384 * Add them to this method and they will be set when creating a new Manager.
3385 * @namespace
3386 */
3387 cssProps: {
3388 /**
3389 * @private
3390 * Disables text selection to improve the dragging gesture. Mainly for desktop browsers.
3391 * @type {String}
3392 * @default 'none'
3393 */
3394 userSelect: "none",
3395
3396 /**
3397 * @private
3398 * Disable the Windows Phone grippers when pressing an element.
3399 * @type {String}
3400 * @default 'none'
3401 */
3402 touchSelect: "none",
3403
3404 /**
3405 * @private
3406 * Disables the default callout shown when you touch and hold a touch target.
3407 * On iOS, when you touch and hold a touch target such as a link, Safari displays
3408 * a callout containing information about the link. This property allows you to disable that callout.
3409 * @type {String}
3410 * @default 'none'
3411 */
3412 touchCallout: "none",
3413
3414 /**
3415 * @private
3416 * Specifies whether zooming is enabled. Used by IE10>
3417 * @type {String}
3418 * @default 'none'
3419 */
3420 contentZooming: "none",
3421
3422 /**
3423 * @private
3424 * Specifies that an entire element should be draggable instead of its contents. Mainly for desktop browsers.
3425 * @type {String}
3426 * @default 'none'
3427 */
3428 userDrag: "none",
3429
3430 /**
3431 * @private
3432 * Overrides the highlight color shown when the user taps a link or a JavaScript
3433 * clickable element in iOS. This property obeys the alpha value, if specified.
3434 * @type {String}
3435 * @default 'rgba(0,0,0,0)'
3436 */
3437 tapHighlightColor: "rgba(0,0,0,0)"
3438 }
3439 };
3440
3441 var STOP = 1;
3442 var FORCED_STOP = 2;
3443 /**
3444 * @private
3445 * add/remove the css properties as defined in manager.options.cssProps
3446 * @param {Manager} manager
3447 * @param {Boolean} add
3448 */
3449
3450 function toggleCssProps(manager, add) {
3451 var element = manager.element;
3452
3453 if (!element.style) {
3454 return;
3455 }
3456
3457 var prop;
3458 each(manager.options.cssProps, function (value, name) {
3459 prop = prefixed(element.style, name);
3460
3461 if (add) {
3462 manager.oldCssProps[prop] = element.style[prop];
3463 element.style[prop] = value;
3464 } else {
3465 element.style[prop] = manager.oldCssProps[prop] || "";
3466 }
3467 });
3468
3469 if (!add) {
3470 manager.oldCssProps = {};
3471 }
3472 }
3473 /**
3474 * @private
3475 * trigger dom event
3476 * @param {String} event
3477 * @param {Object} data
3478 */
3479
3480
3481 function triggerDomEvent(event, data) {
3482 var gestureEvent = document.createEvent("Event");
3483 gestureEvent.initEvent(event, true, true);
3484 gestureEvent.gesture = data;
3485 data.target.dispatchEvent(gestureEvent);
3486 }
3487 /**
3488 * @private
3489 * Manager
3490 * @param {HTMLElement} element
3491 * @param {Object} [options]
3492 * @constructor
3493 */
3494
3495
3496 var Manager =
3497 /*#__PURE__*/
3498 function () {
3499 function Manager(element, options) {
3500 var _this = this;
3501
3502 this.options = assign$1({}, defaults, options || {});
3503 this.options.inputTarget = this.options.inputTarget || element;
3504 this.handlers = {};
3505 this.session = {};
3506 this.recognizers = [];
3507 this.oldCssProps = {};
3508 this.element = element;
3509 this.input = createInputInstance(this);
3510 this.touchAction = new TouchAction(this, this.options.touchAction);
3511 toggleCssProps(this, true);
3512 each(this.options.recognizers, function (item) {
3513 var recognizer = _this.add(new item[0](item[1]));
3514
3515 item[2] && recognizer.recognizeWith(item[2]);
3516 item[3] && recognizer.requireFailure(item[3]);
3517 }, this);
3518 }
3519 /**
3520 * @private
3521 * set options
3522 * @param {Object} options
3523 * @returns {Manager}
3524 */
3525
3526
3527 var _proto = Manager.prototype;
3528
3529 _proto.set = function set(options) {
3530 assign$1(this.options, options); // Options that need a little more setup
3531
3532 if (options.touchAction) {
3533 this.touchAction.update();
3534 }
3535
3536 if (options.inputTarget) {
3537 // Clean up existing event listeners and reinitialize
3538 this.input.destroy();
3539 this.input.target = options.inputTarget;
3540 this.input.init();
3541 }
3542
3543 return this;
3544 };
3545 /**
3546 * @private
3547 * stop recognizing for this session.
3548 * This session will be discarded, when a new [input]start event is fired.
3549 * When forced, the recognizer cycle is stopped immediately.
3550 * @param {Boolean} [force]
3551 */
3552
3553
3554 _proto.stop = function stop(force) {
3555 this.session.stopped = force ? FORCED_STOP : STOP;
3556 };
3557 /**
3558 * @private
3559 * run the recognizers!
3560 * called by the inputHandler function on every movement of the pointers (touches)
3561 * it walks through all the recognizers and tries to detect the gesture that is being made
3562 * @param {Object} inputData
3563 */
3564
3565
3566 _proto.recognize = function recognize(inputData) {
3567 var session = this.session;
3568
3569 if (session.stopped) {
3570 return;
3571 } // run the touch-action polyfill
3572
3573
3574 this.touchAction.preventDefaults(inputData);
3575 var recognizer;
3576 var recognizers = this.recognizers; // this holds the recognizer that is being recognized.
3577 // so the recognizer's state needs to be BEGAN, CHANGED, ENDED or RECOGNIZED
3578 // if no recognizer is detecting a thing, it is set to `null`
3579
3580 var curRecognizer = session.curRecognizer; // reset when the last recognizer is recognized
3581 // or when we're in a new session
3582
3583 if (!curRecognizer || curRecognizer && curRecognizer.state & STATE_RECOGNIZED) {
3584 session.curRecognizer = null;
3585 curRecognizer = null;
3586 }
3587
3588 var i = 0;
3589
3590 while (i < recognizers.length) {
3591 recognizer = recognizers[i]; // find out if we are allowed try to recognize the input for this one.
3592 // 1. allow if the session is NOT forced stopped (see the .stop() method)
3593 // 2. allow if we still haven't recognized a gesture in this session, or the this recognizer is the one
3594 // that is being recognized.
3595 // 3. allow if the recognizer is allowed to run simultaneous with the current recognized recognizer.
3596 // this can be setup with the `recognizeWith()` method on the recognizer.
3597
3598 if (session.stopped !== FORCED_STOP && ( // 1
3599 !curRecognizer || recognizer === curRecognizer || // 2
3600 recognizer.canRecognizeWith(curRecognizer))) {
3601 // 3
3602 recognizer.recognize(inputData);
3603 } else {
3604 recognizer.reset();
3605 } // if the recognizer has been recognizing the input as a valid gesture, we want to store this one as the
3606 // current active recognizer. but only if we don't already have an active recognizer
3607
3608
3609 if (!curRecognizer && recognizer.state & (STATE_BEGAN | STATE_CHANGED | STATE_ENDED)) {
3610 session.curRecognizer = recognizer;
3611 curRecognizer = recognizer;
3612 }
3613
3614 i++;
3615 }
3616 };
3617 /**
3618 * @private
3619 * get a recognizer by its event name.
3620 * @param {Recognizer|String} recognizer
3621 * @returns {Recognizer|Null}
3622 */
3623
3624
3625 _proto.get = function get(recognizer) {
3626 if (recognizer instanceof Recognizer) {
3627 return recognizer;
3628 }
3629
3630 var recognizers = this.recognizers;
3631
3632 for (var i = 0; i < recognizers.length; i++) {
3633 if (recognizers[i].options.event === recognizer) {
3634 return recognizers[i];
3635 }
3636 }
3637
3638 return null;
3639 };
3640 /**
3641 * @private add a recognizer to the manager
3642 * existing recognizers with the same event name will be removed
3643 * @param {Recognizer} recognizer
3644 * @returns {Recognizer|Manager}
3645 */
3646
3647
3648 _proto.add = function add(recognizer) {
3649 if (invokeArrayArg(recognizer, "add", this)) {
3650 return this;
3651 } // remove existing
3652
3653
3654 var existing = this.get(recognizer.options.event);
3655
3656 if (existing) {
3657 this.remove(existing);
3658 }
3659
3660 this.recognizers.push(recognizer);
3661 recognizer.manager = this;
3662 this.touchAction.update();
3663 return recognizer;
3664 };
3665 /**
3666 * @private
3667 * remove a recognizer by name or instance
3668 * @param {Recognizer|String} recognizer
3669 * @returns {Manager}
3670 */
3671
3672
3673 _proto.remove = function remove(recognizer) {
3674 if (invokeArrayArg(recognizer, "remove", this)) {
3675 return this;
3676 }
3677
3678 var targetRecognizer = this.get(recognizer); // let's make sure this recognizer exists
3679
3680 if (recognizer) {
3681 var recognizers = this.recognizers;
3682 var index = inArray(recognizers, targetRecognizer);
3683
3684 if (index !== -1) {
3685 recognizers.splice(index, 1);
3686 this.touchAction.update();
3687 }
3688 }
3689
3690 return this;
3691 };
3692 /**
3693 * @private
3694 * bind event
3695 * @param {String} events
3696 * @param {Function} handler
3697 * @returns {EventEmitter} this
3698 */
3699
3700
3701 _proto.on = function on(events, handler) {
3702 if (events === undefined || handler === undefined) {
3703 return this;
3704 }
3705
3706 var handlers = this.handlers;
3707 each(splitStr(events), function (event) {
3708 handlers[event] = handlers[event] || [];
3709 handlers[event].push(handler);
3710 });
3711 return this;
3712 };
3713 /**
3714 * @private unbind event, leave emit blank to remove all handlers
3715 * @param {String} events
3716 * @param {Function} [handler]
3717 * @returns {EventEmitter} this
3718 */
3719
3720
3721 _proto.off = function off(events, handler) {
3722 if (events === undefined) {
3723 return this;
3724 }
3725
3726 var handlers = this.handlers;
3727 each(splitStr(events), function (event) {
3728 if (!handler) {
3729 delete handlers[event];
3730 } else {
3731 handlers[event] && handlers[event].splice(inArray(handlers[event], handler), 1);
3732 }
3733 });
3734 return this;
3735 };
3736 /**
3737 * @private emit event to the listeners
3738 * @param {String} event
3739 * @param {Object} data
3740 */
3741
3742
3743 _proto.emit = function emit(event, data) {
3744 // we also want to trigger dom events
3745 if (this.options.domEvents) {
3746 triggerDomEvent(event, data);
3747 } // no handlers, so skip it all
3748
3749
3750 var handlers = this.handlers[event] && this.handlers[event].slice();
3751
3752 if (!handlers || !handlers.length) {
3753 return;
3754 }
3755
3756 data.type = event;
3757
3758 data.preventDefault = function () {
3759 data.srcEvent.preventDefault();
3760 };
3761
3762 var i = 0;
3763
3764 while (i < handlers.length) {
3765 handlers[i](data);
3766 i++;
3767 }
3768 };
3769 /**
3770 * @private
3771 * destroy the manager and unbinds all events
3772 * it doesn't unbind dom events, that is the user own responsibility
3773 */
3774
3775
3776 _proto.destroy = function destroy() {
3777 this.element && toggleCssProps(this, false);
3778 this.handlers = {};
3779 this.session = {};
3780 this.input.destroy();
3781 this.element = null;
3782 };
3783
3784 return Manager;
3785 }();
3786
3787 /*
3788 Copyright (c) 2015 NAVER Corp.
3789 name: @egjs/agent
3790 license: MIT
3791 author: NAVER Corp.
3792 repository: git+https://github.com/naver/agent.git
3793 version: 2.2.1
3794 */
3795 function some(arr, callback) {
3796 var length = arr.length;
3797
3798 for (var i = 0; i < length; ++i) {
3799 if (callback(arr[i], i)) {
3800 return true;
3801 }
3802 }
3803
3804 return false;
3805 }
3806 function find(arr, callback) {
3807 var length = arr.length;
3808
3809 for (var i = 0; i < length; ++i) {
3810 if (callback(arr[i], i)) {
3811 return arr[i];
3812 }
3813 }
3814
3815 return null;
3816 }
3817 function getUserAgent(agent) {
3818 var userAgent = agent;
3819
3820 if (typeof userAgent === "undefined") {
3821 if (typeof navigator === "undefined" || !navigator) {
3822 return "";
3823 }
3824
3825 userAgent = navigator.userAgent || "";
3826 }
3827
3828 return userAgent.toLowerCase();
3829 }
3830 function execRegExp(pattern, text) {
3831 try {
3832 return new RegExp(pattern, "g").exec(text);
3833 } catch (e) {
3834 return null;
3835 }
3836 }
3837 function hasUserAgentData() {
3838 if (typeof navigator === "undefined" || !navigator || !navigator.userAgentData) {
3839 return false;
3840 }
3841
3842 var userAgentData = navigator.userAgentData;
3843 var brands = userAgentData.brands || userAgentData.uaList;
3844 return !!(brands && brands.length);
3845 }
3846 function findVersion(versionTest, userAgent) {
3847 var result = execRegExp("(" + versionTest + ")((?:\\/|\\s|:)([0-9|\\.|_]+))?", userAgent);
3848 return result ? result[3] : "";
3849 }
3850 function convertVersion(text) {
3851 return text.replace(/_/g, ".");
3852 }
3853 function findPreset(presets, userAgent) {
3854 var userPreset = null;
3855 var version = "-1";
3856 some(presets, function (preset) {
3857 var result = execRegExp("(" + preset.test + ")((?:\\/|\\s|:)([0-9|\\.|_]+))?", userAgent);
3858
3859 if (!result || preset.brand) {
3860 return false;
3861 }
3862
3863 userPreset = preset;
3864 version = result[3] || "-1";
3865
3866 if (preset.versionAlias) {
3867 version = preset.versionAlias;
3868 } else if (preset.versionTest) {
3869 version = findVersion(preset.versionTest.toLowerCase(), userAgent) || version;
3870 }
3871
3872 version = convertVersion(version);
3873 return true;
3874 });
3875 return {
3876 preset: userPreset,
3877 version: version
3878 };
3879 }
3880 function findBrand(brands, preset) {
3881 return find(brands, function (_a) {
3882 var brand = _a.brand;
3883 return execRegExp("" + preset.test, brand.toLowerCase());
3884 });
3885 }
3886
3887 var BROWSER_PRESETS = [{
3888 test: "phantomjs",
3889 id: "phantomjs"
3890 }, {
3891 test: "whale",
3892 id: "whale"
3893 }, {
3894 test: "edgios|edge|edg",
3895 id: "edge"
3896 }, {
3897 test: "msie|trident|windows phone",
3898 id: "ie",
3899 versionTest: "iemobile|msie|rv"
3900 }, {
3901 test: "miuibrowser",
3902 id: "miui browser"
3903 }, {
3904 test: "samsungbrowser",
3905 id: "samsung internet"
3906 }, {
3907 test: "samsung",
3908 id: "samsung internet",
3909 versionTest: "version"
3910 }, {
3911 test: "chrome|crios",
3912 id: "chrome"
3913 }, {
3914 test: "firefox|fxios",
3915 id: "firefox"
3916 }, {
3917 test: "android",
3918 id: "android browser",
3919 versionTest: "version"
3920 }, {
3921 test: "safari|iphone|ipad|ipod",
3922 id: "safari",
3923 versionTest: "version"
3924 }]; // chromium's engine(blink) is based on applewebkit 537.36.
3925
3926 var CHROMIUM_PRESETS = [{
3927 test: "(?=.*applewebkit/(53[0-7]|5[0-2]|[0-4]))(?=.*\\schrome)",
3928 id: "chrome"
3929 }, {
3930 test: "chromium",
3931 id: "chrome"
3932 }, {
3933 test: "whale",
3934 id: "chrome",
3935 brand: true
3936 }];
3937 var WEBKIT_PRESETS = [{
3938 test: "applewebkit",
3939 id: "webkit"
3940 }];
3941 var WEBVIEW_PRESETS = [{
3942 test: "(?=(iphone|ipad))(?!(.*version))",
3943 id: "webview"
3944 }, {
3945 test: "(?=(android|iphone|ipad))(?=.*(naver|daum|; wv))",
3946 id: "webview"
3947 }, {
3948 // test webview
3949 test: "webview",
3950 id: "webview"
3951 }];
3952 var OS_PRESETS = [{
3953 test: "windows phone",
3954 id: "windows phone"
3955 }, {
3956 test: "windows 2000",
3957 id: "window",
3958 versionAlias: "5.0"
3959 }, {
3960 test: "windows nt",
3961 id: "window"
3962 }, {
3963 test: "iphone|ipad|ipod",
3964 id: "ios",
3965 versionTest: "iphone os|cpu os"
3966 }, {
3967 test: "mac os x",
3968 id: "mac"
3969 }, {
3970 test: "android",
3971 id: "android"
3972 }, {
3973 test: "tizen",
3974 id: "tizen"
3975 }, {
3976 test: "webos|web0s",
3977 id: "webos"
3978 }];
3979
3980 function parseUserAgentData(osData) {
3981 var userAgentData = navigator.userAgentData;
3982 var brands = (userAgentData.uaList || userAgentData.brands).slice();
3983 var isMobile = userAgentData.mobile || false;
3984 var firstBrand = brands[0];
3985 var browser = {
3986 name: firstBrand.brand,
3987 version: firstBrand.version,
3988 majorVersion: -1,
3989 webkit: false,
3990 webview: some(WEBVIEW_PRESETS, function (preset) {
3991 return findBrand(brands, preset);
3992 }),
3993 chromium: some(CHROMIUM_PRESETS, function (preset) {
3994 return findBrand(brands, preset);
3995 })
3996 };
3997 var os = {
3998 name: "unknown",
3999 version: "-1",
4000 majorVersion: -1
4001 };
4002 browser.webkit = !browser.chromium && some(WEBKIT_PRESETS, function (preset) {
4003 return findBrand(brands, preset);
4004 });
4005
4006 if (osData) {
4007 var platform_1 = osData.platform.toLowerCase();
4008 var result = find(OS_PRESETS, function (preset) {
4009 return new RegExp("" + preset.test, "g").exec(platform_1);
4010 });
4011 os.name = result ? result.id : platform_1;
4012 os.version = osData.platformVersion;
4013 }
4014
4015 some(BROWSER_PRESETS, function (preset) {
4016 var result = findBrand(brands, preset);
4017
4018 if (!result) {
4019 return false;
4020 }
4021
4022 browser.name = preset.id;
4023 browser.version = osData ? osData.uaFullVersion : result.version;
4024 return true;
4025 });
4026
4027 if (navigator.platform === "Linux armv8l") {
4028 os.name = "android";
4029 } else if (browser.webkit) {
4030 os.name = isMobile ? "ios" : "mac";
4031 }
4032
4033 if (os.name === "ios" && browser.webview) {
4034 browser.version = "-1";
4035 }
4036
4037 os.version = convertVersion(os.version);
4038 browser.version = convertVersion(browser.version);
4039 os.majorVersion = parseInt(os.version, 10);
4040 browser.majorVersion = parseInt(browser.version, 10);
4041 return {
4042 browser: browser,
4043 os: os,
4044 isMobile: isMobile,
4045 isHints: true
4046 };
4047 }
4048
4049 function parseUserAgent(userAgent) {
4050 var nextAgent = getUserAgent(userAgent);
4051 var isMobile = !!/mobi/g.exec(nextAgent);
4052 var browser = {
4053 name: "unknown",
4054 version: "-1",
4055 majorVersion: -1,
4056 webview: !!findPreset(WEBVIEW_PRESETS, nextAgent).preset,
4057 chromium: !!findPreset(CHROMIUM_PRESETS, nextAgent).preset,
4058 webkit: false
4059 };
4060 var os = {
4061 name: "unknown",
4062 version: "-1",
4063 majorVersion: -1
4064 };
4065
4066 var _a = findPreset(BROWSER_PRESETS, nextAgent),
4067 browserPreset = _a.preset,
4068 browserVersion = _a.version;
4069
4070 var _b = findPreset(OS_PRESETS, nextAgent),
4071 osPreset = _b.preset,
4072 osVersion = _b.version;
4073
4074 browser.webkit = !browser.chromium && !!findPreset(WEBKIT_PRESETS, nextAgent).preset;
4075
4076 if (osPreset) {
4077 os.name = osPreset.id;
4078 os.version = osVersion;
4079 os.majorVersion = parseInt(osVersion, 10);
4080 }
4081
4082 if (browserPreset) {
4083 browser.name = browserPreset.id;
4084 browser.version = browserVersion;
4085
4086 if (browser.webview && os.name === "ios" && browser.name !== "safari") {
4087 browser.webview = false;
4088 }
4089 }
4090
4091 browser.majorVersion = parseInt(browser.version, 10);
4092 return {
4093 browser: browser,
4094 os: os,
4095 isMobile: isMobile,
4096 isHints: false
4097 };
4098 }
4099 /**
4100 * Extracts browser and operating system information from the user agent string.
4101 * @ko 유저 에이전트 문자열에서 브라우저와 운영체제 정보를 추출한다.
4102 * @function eg.agent#agent
4103 * @param - user agent string to parse <ko>파싱할 유저에이전트 문자열</ko>
4104 * @return - agent Info <ko> 에이전트 정보 </ko>
4105 * @example
4106 import agent from "@egjs/agent";
4107 // eg.agent();
4108 const { os, browser, isMobile } = agent();
4109 */
4110
4111 function agent(userAgent) {
4112 if (typeof userAgent === "undefined" && hasUserAgentData()) {
4113 return parseUserAgentData();
4114 } else {
4115 return parseUserAgent(userAgent);
4116 }
4117 }
4118
4119 /*
4120 Copyright (c) 2017 NAVER Corp.
4121 @egjs/axes project is licensed under the MIT license
4122
4123 @egjs/axes JavaScript library
4124 https://github.com/naver/egjs-axes
4125
4126 @version 2.7.0
4127 */
4128
4129 /*! *****************************************************************************
4130 Copyright (c) Microsoft Corporation. All rights reserved.
4131 Licensed under the Apache License, Version 2.0 (the "License"); you may not use
4132 this file except in compliance with the License. You may obtain a copy of the
4133 License at http://www.apache.org/licenses/LICENSE-2.0
4134
4135 THIS CODE IS PROVIDED ON AN *AS IS* BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
4136 KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION ANY IMPLIED
4137 WARRANTIES OR CONDITIONS OF TITLE, FITNESS FOR A PARTICULAR PURPOSE,
4138 MERCHANTABLITY OR NON-INFRINGEMENT.
4139
4140 See the Apache Version 2.0 License for specific language governing permissions
4141 and limitations under the License.
4142 ***************************************************************************** */
4143
4144 /* global Reflect, Promise */
4145 var extendStatics$2 = function (d, b) {
4146 extendStatics$2 = Object.setPrototypeOf || {
4147 __proto__: []
4148 } instanceof Array && function (d, b) {
4149 d.__proto__ = b;
4150 } || function (d, b) {
4151 for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
4152 };
4153
4154 return extendStatics$2(d, b);
4155 };
4156
4157 function __extends$2(d, b) {
4158 extendStatics$2(d, b);
4159
4160 function __() {
4161 this.constructor = d;
4162 }
4163
4164 d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
4165 }
4166 var __assign$1 = function () {
4167 __assign$1 = Object.assign || function __assign(t) {
4168 for (var s, i = 1, n = arguments.length; i < n; i++) {
4169 s = arguments[i];
4170
4171 for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p)) t[p] = s[p];
4172 }
4173
4174 return t;
4175 };
4176
4177 return __assign$1.apply(this, arguments);
4178 };
4179
4180 function getInsidePosition(destPos, range, circular, bounce) {
4181 var toDestPos = destPos;
4182 var targetRange = [circular[0] ? range[0] : bounce ? range[0] - bounce[0] : range[0], circular[1] ? range[1] : bounce ? range[1] + bounce[1] : range[1]];
4183 toDestPos = Math.max(targetRange[0], toDestPos);
4184 toDestPos = Math.min(targetRange[1], toDestPos);
4185 return toDestPos;
4186 } // determine outside
4187
4188 function isOutside(pos, range) {
4189 return pos < range[0] || pos > range[1];
4190 }
4191 function getDuration(distance, deceleration) {
4192 var duration = Math.sqrt(distance / deceleration * 2); // when duration is under 100, then value is zero
4193
4194 return duration < 100 ? 0 : duration;
4195 }
4196 function isCircularable(destPos, range, circular) {
4197 return circular[1] && destPos > range[1] || circular[0] && destPos < range[0];
4198 }
4199 function getCirculatedPos(pos, range, circular) {
4200 var toPos = pos;
4201 var min = range[0];
4202 var max = range[1];
4203 var length = max - min;
4204
4205 if (circular[1] && pos > max) {
4206 // right
4207 toPos = (toPos - max) % length + min;
4208 }
4209
4210 if (circular[0] && pos < min) {
4211 // left
4212 toPos = (toPos - min) % length + max;
4213 }
4214
4215 return toPos;
4216 }
4217
4218 /* eslint-disable no-new-func, no-nested-ternary */
4219 var win$1;
4220
4221 if (typeof window === "undefined") {
4222 // window is undefined in node.js
4223 win$1 = {
4224 navigator: {
4225 userAgent: ""
4226 }
4227 };
4228 } else {
4229 win$1 = window;
4230 }
4231
4232 function toArray$2(nodes) {
4233 // const el = Array.prototype.slice.call(nodes);
4234 // for IE8
4235 var el = [];
4236
4237 for (var i = 0, len = nodes.length; i < len; i++) {
4238 el.push(nodes[i]);
4239 }
4240
4241 return el;
4242 }
4243 function $(param, multi) {
4244 if (multi === void 0) {
4245 multi = false;
4246 }
4247
4248 var el;
4249
4250 if (typeof param === "string") {
4251 // String (HTML, Selector)
4252 // check if string is HTML tag format
4253 var match = param.match(/^<([a-z]+)\s*([^>]*)>/); // creating element
4254
4255 if (match) {
4256 // HTML
4257 var dummy = document.createElement("div");
4258 dummy.innerHTML = param;
4259 el = toArray$2(dummy.childNodes);
4260 } else {
4261 // Selector
4262 el = toArray$2(document.querySelectorAll(param));
4263 }
4264
4265 if (!multi) {
4266 el = el.length >= 1 ? el[0] : undefined;
4267 }
4268 } else if (param === win$1) {
4269 // window
4270 el = param;
4271 } else if (param.nodeName && (param.nodeType === 1 || param.nodeType === 9)) {
4272 // HTMLElement, Document
4273 el = param;
4274 } else if ("jQuery" in win$1 && param instanceof jQuery || param.constructor.prototype.jquery) {
4275 // jQuery
4276 el = multi ? param.toArray() : param.get(0);
4277 } else if (Array.isArray(param)) {
4278 el = param.map(function (v) {
4279 return $(v);
4280 });
4281
4282 if (!multi) {
4283 el = el.length >= 1 ? el[0] : undefined;
4284 }
4285 }
4286
4287 return el;
4288 }
4289 var raf = win$1.requestAnimationFrame || win$1.webkitRequestAnimationFrame;
4290 var caf = win$1.cancelAnimationFrame || win$1.webkitCancelAnimationFrame;
4291
4292 if (raf && !caf) {
4293 var keyInfo_1 = {};
4294 var oldraf_1 = raf;
4295
4296 raf = function (callback) {
4297 function wrapCallback(timestamp) {
4298 if (keyInfo_1[key]) {
4299 callback(timestamp);
4300 }
4301 }
4302
4303 var key = oldraf_1(wrapCallback);
4304 keyInfo_1[key] = true;
4305 return key;
4306 };
4307
4308 caf = function (key) {
4309 delete keyInfo_1[key];
4310 };
4311 } else if (!(raf && caf)) {
4312 raf = function (callback) {
4313 return win$1.setTimeout(function () {
4314 callback(win$1.performance && win$1.performance.now && win$1.performance.now() || new Date().getTime());
4315 }, 16);
4316 };
4317
4318 caf = win$1.clearTimeout;
4319 }
4320 /**
4321 * A polyfill for the window.requestAnimationFrame() method.
4322 * @see https://developer.mozilla.org/en-US/docs/Web/API/window/requestAnimationFrame
4323 * @private
4324 */
4325
4326
4327 function requestAnimationFrame(fp) {
4328 return raf(fp);
4329 }
4330 /**
4331 * A polyfill for the window.cancelAnimationFrame() method. It cancels an animation executed through a call to the requestAnimationFrame() method.
4332 * @param {Number} key − The ID value returned through a call to the requestAnimationFrame() method. <ko>requestAnimationFrame() 메서드가 반환한 아이디 값</ko>
4333 * @see https://developer.mozilla.org/en-US/docs/Web/API/Window/cancelAnimationFrame
4334 * @private
4335 */
4336
4337 function cancelAnimationFrame(key) {
4338 caf(key);
4339 }
4340 function map(obj, callback) {
4341 var tranformed = {};
4342
4343 for (var k in obj) {
4344 k && (tranformed[k] = callback(obj[k], k));
4345 }
4346
4347 return tranformed;
4348 }
4349 function filter(obj, callback) {
4350 var filtered = {};
4351
4352 for (var k in obj) {
4353 k && callback(obj[k], k) && (filtered[k] = obj[k]);
4354 }
4355
4356 return filtered;
4357 }
4358 function every(obj, callback) {
4359 for (var k in obj) {
4360 if (k && !callback(obj[k], k)) {
4361 return false;
4362 }
4363 }
4364
4365 return true;
4366 }
4367 function equal(target, base) {
4368 return every(target, function (v, k) {
4369 return v === base[k];
4370 });
4371 }
4372 var roundNumFunc = {};
4373 function roundNumber(num, roundUnit) {
4374 // Cache for performance
4375 if (!roundNumFunc[roundUnit]) {
4376 roundNumFunc[roundUnit] = getRoundFunc(roundUnit);
4377 }
4378
4379 return roundNumFunc[roundUnit](num);
4380 }
4381 function roundNumbers(num, roundUnit) {
4382 if (!num || !roundUnit) {
4383 return num;
4384 }
4385
4386 var isNumber = typeof roundUnit === "number";
4387 return map(num, function (value, key) {
4388 return roundNumber(value, isNumber ? roundUnit : roundUnit[key]);
4389 });
4390 }
4391 function getDecimalPlace(val) {
4392 if (!isFinite(val)) {
4393 return 0;
4394 }
4395
4396 var v = val + "";
4397
4398 if (v.indexOf("e") >= 0) {
4399 // Exponential Format
4400 // 1e-10, 1e-12
4401 var p = 0;
4402 var e = 1;
4403
4404 while (Math.round(val * e) / e !== val) {
4405 e *= 10;
4406 p++;
4407 }
4408
4409 return p;
4410 } // In general, following has performance benefit.
4411 // https://jsperf.com/precision-calculation
4412
4413
4414 return v.indexOf(".") >= 0 ? v.length - v.indexOf(".") - 1 : 0;
4415 }
4416 function inversePow(n) {
4417 // replace Math.pow(10, -n) to solve floating point issue.
4418 // eg. Math.pow(10, -4) => 0.00009999999999999999
4419 return 1 / Math.pow(10, n);
4420 }
4421 function getRoundFunc(v) {
4422 var p = v < 1 ? Math.pow(10, getDecimalPlace(v)) : 1;
4423 return function (n) {
4424 if (v === 0) {
4425 return 0;
4426 }
4427
4428 return Math.round(Math.round(n / v) * v * p) / p;
4429 };
4430 }
4431
4432 function minMax(value, min, max) {
4433 return Math.max(Math.min(value, max), min);
4434 }
4435
4436 var AnimationManager =
4437 /*#__PURE__*/
4438 function () {
4439 function AnimationManager(_a) {
4440 var options = _a.options,
4441 itm = _a.itm,
4442 em = _a.em,
4443 axm = _a.axm;
4444 this.options = options;
4445 this.itm = itm;
4446 this.em = em;
4447 this.axm = axm;
4448 this.animationEnd = this.animationEnd.bind(this);
4449 }
4450
4451 var __proto = AnimationManager.prototype;
4452
4453 __proto.getDuration = function (depaPos, destPos, wishDuration) {
4454 var _this = this;
4455
4456 var duration;
4457
4458 if (typeof wishDuration !== "undefined") {
4459 duration = wishDuration;
4460 } else {
4461 var durations_1 = map(destPos, function (v, k) {
4462 return getDuration(Math.abs(v - depaPos[k]), _this.options.deceleration);
4463 });
4464 duration = Object.keys(durations_1).reduce(function (max, v) {
4465 return Math.max(max, durations_1[v]);
4466 }, -Infinity);
4467 }
4468
4469 return minMax(duration, this.options.minimumDuration, this.options.maximumDuration);
4470 };
4471
4472 __proto.createAnimationParam = function (pos, duration, option) {
4473 var depaPos = this.axm.get();
4474 var destPos = pos;
4475 var inputEvent = option && option.event || null;
4476 return {
4477 depaPos: depaPos,
4478 destPos: destPos,
4479 duration: minMax(duration, this.options.minimumDuration, this.options.maximumDuration),
4480 delta: this.axm.getDelta(depaPos, destPos),
4481 inputEvent: inputEvent,
4482 input: option && option.input || null,
4483 isTrusted: !!inputEvent,
4484 done: this.animationEnd
4485 };
4486 };
4487
4488 __proto.grab = function (axes, option) {
4489 if (this._animateParam && axes.length) {
4490 var orgPos_1 = this.axm.get(axes);
4491 var pos = this.axm.map(orgPos_1, function (v, opt) {
4492 return getCirculatedPos(v, opt.range, opt.circular);
4493 });
4494
4495 if (!every(pos, function (v, k) {
4496 return orgPos_1[k] === v;
4497 })) {
4498 this.em.triggerChange(pos, false, orgPos_1, option, !!option);
4499 }
4500
4501 this._animateParam = null;
4502 this._raf && cancelAnimationFrame(this._raf);
4503 this._raf = null;
4504 this.em.triggerAnimationEnd(!!(option && option.event));
4505 }
4506 };
4507
4508 __proto.getEventInfo = function () {
4509 if (this._animateParam && this._animateParam.input && this._animateParam.inputEvent) {
4510 return {
4511 input: this._animateParam.input,
4512 event: this._animateParam.inputEvent
4513 };
4514 } else {
4515 return null;
4516 }
4517 };
4518
4519 __proto.restore = function (option) {
4520 var pos = this.axm.get();
4521 var destPos = this.axm.map(pos, function (v, opt) {
4522 return Math.min(opt.range[1], Math.max(opt.range[0], v));
4523 });
4524 this.animateTo(destPos, this.getDuration(pos, destPos), option);
4525 };
4526
4527 __proto.animationEnd = function () {
4528 var beforeParam = this.getEventInfo();
4529 this._animateParam = null; // for Circular
4530
4531 var circularTargets = this.axm.filter(this.axm.get(), function (v, opt) {
4532 return isCircularable(v, opt.range, opt.circular);
4533 });
4534 Object.keys(circularTargets).length > 0 && this.setTo(this.axm.map(circularTargets, function (v, opt) {
4535 return getCirculatedPos(v, opt.range, opt.circular);
4536 }));
4537 this.itm.setInterrupt(false);
4538 this.em.triggerAnimationEnd(!!beforeParam);
4539
4540 if (this.axm.isOutside()) {
4541 this.restore(beforeParam);
4542 } else {
4543 this.finish(!!beforeParam);
4544 }
4545 };
4546
4547 __proto.finish = function (isTrusted) {
4548 this._animateParam = null;
4549 this.itm.setInterrupt(false);
4550 this.em.triggerFinish(isTrusted);
4551 };
4552
4553 __proto.animateLoop = function (param, complete) {
4554 if (param.duration) {
4555 this._animateParam = __assign$1({}, param);
4556 var info_1 = this._animateParam;
4557 var self_1 = this;
4558 var destPos_1 = info_1.destPos;
4559 var prevPos_1 = info_1.depaPos;
4560 var prevEasingPer_1 = 0;
4561 var directions_1 = map(prevPos_1, function (value, key) {
4562 return value <= destPos_1[key] ? 1 : -1;
4563 });
4564 var originalIntendedPos_1 = map(destPos_1, function (v) {
4565 return v;
4566 });
4567 var prevTime_1 = new Date().getTime();
4568 info_1.startTime = prevTime_1;
4569
4570 (function loop() {
4571 self_1._raf = null;
4572 var currentTime = new Date().getTime();
4573 var ratio = (currentTime - info_1.startTime) / param.duration;
4574 var easingPer = self_1.easing(ratio);
4575 var toPos = self_1.axm.map(prevPos_1, function (pos, options, key) {
4576 var nextPos = ratio >= 1 ? destPos_1[key] : pos + info_1.delta[key] * (easingPer - prevEasingPer_1); // Subtract distance from distance already moved.
4577 // Recalculate the remaining distance.
4578 // Fix the bouncing phenomenon by changing the range.
4579
4580 var circulatedPos = getCirculatedPos(nextPos, options.range, options.circular);
4581
4582 if (nextPos !== circulatedPos) {
4583 // circular
4584 var rangeOffset = directions_1[key] * (options.range[1] - options.range[0]);
4585 destPos_1[key] -= rangeOffset;
4586 prevPos_1[key] -= rangeOffset;
4587 }
4588
4589 return circulatedPos;
4590 });
4591 var isCanceled = !self_1.em.triggerChange(toPos, false, prevPos_1);
4592 prevPos_1 = toPos;
4593 prevTime_1 = currentTime;
4594 prevEasingPer_1 = easingPer;
4595
4596 if (easingPer >= 1) {
4597 destPos_1 = self_1.getFinalPos(destPos_1, originalIntendedPos_1);
4598
4599 if (!equal(destPos_1, self_1.axm.get(Object.keys(destPos_1)))) {
4600 self_1.em.triggerChange(destPos_1, true, prevPos_1);
4601 }
4602
4603 complete();
4604 return;
4605 } else if (isCanceled) {
4606 self_1.finish(false);
4607 } else {
4608 // animationEnd
4609 self_1._raf = requestAnimationFrame(loop);
4610 }
4611 })();
4612 } else {
4613 this.em.triggerChange(param.destPos, true);
4614 complete();
4615 }
4616 };
4617 /**
4618 * Get estimated final value.
4619 *
4620 * If destPos is within the 'error range' of the original intended position, the initial intended position is returned.
4621 * - eg. original intended pos: 100, destPos: 100.0000000004 ==> return 100;
4622 * If dest Pos is outside the 'range of error' compared to the originally intended pos, it is returned rounded based on the originally intended pos.
4623 * - eg. original intended pos: 100.123 destPos: 50.12345 => return 50.123
4624 *
4625 * @param originalIntendedPos
4626 * @param destPos
4627 */
4628
4629
4630 __proto.getFinalPos = function (destPos, originalIntendedPos) {
4631 var _this = this; // compare destPos and originalIntendedPos
4632
4633
4634 var ERROR_LIMIT = 0.000001;
4635 var finalPos = map(destPos, function (value, key) {
4636 if (value >= originalIntendedPos[key] - ERROR_LIMIT && value <= originalIntendedPos[key] + ERROR_LIMIT) {
4637 // In error range, return original intended
4638 return originalIntendedPos[key];
4639 } else {
4640 // Out of error range, return rounded pos.
4641 var roundUnit = _this.getRoundUnit(value, key);
4642
4643 var result = roundNumber(value, roundUnit);
4644 return result;
4645 }
4646 });
4647 return finalPos;
4648 };
4649
4650 __proto.getRoundUnit = function (val, key) {
4651 var roundUnit = this.options.round; // manual mode
4652
4653 var minRoundUnit = null; // auto mode
4654 // auto mode
4655
4656 if (!roundUnit) {
4657 // Get minimum round unit
4658 var options = this.axm.getAxisOptions(key);
4659 minRoundUnit = inversePow(Math.max(getDecimalPlace(options.range[0]), getDecimalPlace(options.range[1]), getDecimalPlace(val)));
4660 }
4661
4662 return minRoundUnit || roundUnit;
4663 };
4664
4665 __proto.getUserControll = function (param) {
4666 var userWish = param.setTo();
4667 userWish.destPos = this.axm.get(userWish.destPos);
4668 userWish.duration = minMax(userWish.duration, this.options.minimumDuration, this.options.maximumDuration);
4669 return userWish;
4670 };
4671
4672 __proto.animateTo = function (destPos, duration, option) {
4673 var _this = this;
4674
4675 var param = this.createAnimationParam(destPos, duration, option);
4676
4677 var depaPos = __assign$1({}, param.depaPos);
4678
4679 var retTrigger = this.em.triggerAnimationStart(param); // to control
4680
4681 var userWish = this.getUserControll(param); // You can't stop the 'animationStart' event when 'circular' is true.
4682
4683 if (!retTrigger && this.axm.every(userWish.destPos, function (v, opt) {
4684 return isCircularable(v, opt.range, opt.circular);
4685 })) {
4686 console.warn("You can't stop the 'animation' event when 'circular' is true.");
4687 }
4688
4689 if (retTrigger && !equal(userWish.destPos, depaPos)) {
4690 var inputEvent = option && option.event || null;
4691 this.animateLoop({
4692 depaPos: depaPos,
4693 destPos: userWish.destPos,
4694 duration: userWish.duration,
4695 delta: this.axm.getDelta(depaPos, userWish.destPos),
4696 isTrusted: !!inputEvent,
4697 inputEvent: inputEvent,
4698 input: option && option.input || null
4699 }, function () {
4700 return _this.animationEnd();
4701 });
4702 }
4703 };
4704
4705 __proto.easing = function (p) {
4706 return p > 1 ? 1 : this.options.easing(p);
4707 };
4708
4709 __proto.setTo = function (pos, duration) {
4710 if (duration === void 0) {
4711 duration = 0;
4712 }
4713
4714 var axes = Object.keys(pos);
4715 this.grab(axes);
4716 var orgPos = this.axm.get(axes);
4717
4718 if (equal(pos, orgPos)) {
4719 return this;
4720 }
4721
4722 this.itm.setInterrupt(true);
4723 var movedPos = filter(pos, function (v, k) {
4724 return orgPos[k] !== v;
4725 });
4726
4727 if (!Object.keys(movedPos).length) {
4728 return this;
4729 }
4730
4731 movedPos = this.axm.map(movedPos, function (v, opt) {
4732 var range = opt.range,
4733 circular = opt.circular;
4734
4735 if (circular && (circular[0] || circular[1])) {
4736 return v;
4737 } else {
4738 return getInsidePosition(v, range, circular);
4739 }
4740 });
4741
4742 if (equal(movedPos, orgPos)) {
4743 return this;
4744 }
4745
4746 if (duration > 0) {
4747 this.animateTo(movedPos, duration);
4748 } else {
4749 this.em.triggerChange(movedPos);
4750 this.finish(false);
4751 }
4752
4753 return this;
4754 };
4755
4756 __proto.setBy = function (pos, duration) {
4757 if (duration === void 0) {
4758 duration = 0;
4759 }
4760
4761 return this.setTo(map(this.axm.get(Object.keys(pos)), function (v, k) {
4762 return v + pos[k];
4763 }), duration);
4764 };
4765
4766 return AnimationManager;
4767 }();
4768
4769 var EventManager =
4770 /*#__PURE__*/
4771 function () {
4772 function EventManager(axes) {
4773 this.axes = axes;
4774 }
4775 /**
4776 * This event is fired when a user holds an element on the screen of the device.
4777 * @ko 사용자가 기기의 화면에 손을 대고 있을 때 발생하는 이벤트
4778 * @name eg.Axes#hold
4779 * @event
4780 * @type {object} The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
4781 * @property {Object.<string, number>} pos coordinate <ko>좌표 정보</ko>
4782 * @property {Object} input The instance of inputType where the event occurred<ko>이벤트가 발생한 inputType 인스턴스</ko>
4783 * @property {Object} inputEvent The event object received from inputType <ko>inputType으로 부터 받은 이벤트 객체</ko>
4784 * @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
4785 *
4786 * @example
4787 * const axes = new eg.Axes({
4788 * "x": {
4789 * range: [0, 100]
4790 * },
4791 * "zoom": {
4792 * range: [50, 30]
4793 * }
4794 * }).on("hold", function(event) {
4795 * // event.pos
4796 * // event.input
4797 * // event.inputEvent
4798 * // isTrusted
4799 * });
4800 */
4801
4802
4803 var __proto = EventManager.prototype;
4804
4805 __proto.triggerHold = function (pos, option) {
4806 var roundPos = this.getRoundPos(pos).roundPos;
4807 this.axes.trigger("hold", {
4808 pos: roundPos,
4809 input: option.input || null,
4810 inputEvent: option.event || null,
4811 isTrusted: true
4812 });
4813 };
4814 /**
4815 * Specifies the coordinates to move after the 'change' event. It works when the holding value of the change event is true.
4816 * @ko 'change' 이벤트 이후 이동할 좌표를 지정한다. change이벤트의 holding 값이 true일 경우에 동작한다
4817 * @name set
4818 * @function
4819 * @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
4820 * @example
4821 * const axes = new eg.Axes({
4822 * "x": {
4823 * range: [0, 100]
4824 * },
4825 * "zoom": {
4826 * range: [50, 30]
4827 * }
4828 * }).on("change", function(event) {
4829 * event.holding && event.set({x: 10});
4830 * });
4831 */
4832
4833 /** Specifies the animation coordinates to move after the 'release' or 'animationStart' events.
4834 * @ko 'release' 또는 'animationStart' 이벤트 이후 이동할 좌표를 지정한다.
4835 * @name setTo
4836 * @function
4837 * @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
4838 * @param {Number} [duration] Duration of the animation (unit: ms) <ko>애니메이션 진행 시간(단위: ms)</ko>
4839 * @example
4840 * const axes = new eg.Axes({
4841 * "x": {
4842 * range: [0, 100]
4843 * },
4844 * "zoom": {
4845 * range: [50, 30]
4846 * }
4847 * }).on("animationStart", function(event) {
4848 * event.setTo({x: 10}, 2000);
4849 * });
4850 */
4851
4852 /**
4853 * This event is fired when a user release an element on the screen of the device.
4854 * @ko 사용자가 기기의 화면에서 손을 뗐을 때 발생하는 이벤트
4855 * @name eg.Axes#release
4856 * @event
4857 * @type {object} The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
4858 * @property {Object.<string, number>} depaPos The coordinates when releasing an element<ko>손을 뗐을 때의 좌표 </ko>
4859 * @property {Object.<string, number>} destPos The coordinates to move to after releasing an element<ko>손을 뗀 뒤에 이동할 좌표</ko>
4860 * @property {Object.<string, number>} delta The movement variation of coordinate <ko>좌표의 변화량</ko>
4861 * @property {Object} inputEvent The event object received from inputType <ko>inputType으로 부터 받은 이벤트 객체</ko>
4862 * @property {Object} input The instance of inputType where the event occurred<ko>이벤트가 발생한 inputType 인스턴스</ko>
4863 * @property {setTo} setTo Specifies the animation coordinates to move after the event <ko>이벤트 이후 이동할 애니메이션 좌표를 지정한다</ko>
4864 * @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
4865 *
4866 * @example
4867 * const axes = new eg.Axes({
4868 * "x": {
4869 * range: [0, 100]
4870 * },
4871 * "zoom": {
4872 * range: [50, 30]
4873 * }
4874 * }).on("release", function(event) {
4875 * // event.depaPos
4876 * // event.destPos
4877 * // event.delta
4878 * // event.input
4879 * // event.inputEvent
4880 * // event.setTo
4881 * // event.isTrusted
4882 *
4883 * // if you want to change the animation coordinates to move after the 'release' event.
4884 * event.setTo({x: 10}, 2000);
4885 * });
4886 */
4887
4888
4889 __proto.triggerRelease = function (param) {
4890 var _a = this.getRoundPos(param.destPos, param.depaPos),
4891 roundPos = _a.roundPos,
4892 roundDepa = _a.roundDepa;
4893
4894 param.destPos = roundPos;
4895 param.depaPos = roundDepa;
4896 param.setTo = this.createUserControll(param.destPos, param.duration);
4897 this.axes.trigger("release", param);
4898 };
4899 /**
4900 * This event is fired when coordinate changes.
4901 * @ko 좌표가 변경됐을 때 발생하는 이벤트
4902 * @name eg.Axes#change
4903 * @event
4904 * @type {object} The object of data to be sent when the event is fired <ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
4905 * @property {Object.<string, number>} pos The coordinate <ko>좌표</ko>
4906 * @property {Object.<string, number>} delta The movement variation of coordinate <ko>좌표의 변화량</ko>
4907 * @property {Boolean} holding Indicates whether a user holds an element on the screen of the device.<ko>사용자가 기기의 화면을 누르고 있는지 여부</ko>
4908 * @property {Object} input The instance of inputType where the event occurred. If the value is changed by animation, it returns 'null'.<ko>이벤트가 발생한 inputType 인스턴스. 애니메이션에 의해 값이 변경될 경우에는 'null'을 반환한다.</ko>
4909 * @property {Object} inputEvent The event object received from inputType. If the value is changed by animation, it returns 'null'.<ko>inputType으로 부터 받은 이벤트 객체. 애니메이션에 의해 값이 변경될 경우에는 'null'을 반환한다.</ko>
4910 * @property {set} set Specifies the coordinates to move after the event. It works when the holding value is true <ko>이벤트 이후 이동할 좌표를 지정한다. holding 값이 true일 경우에 동작한다.</ko>
4911 * @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
4912 *
4913 * @example
4914 * const axes = new eg.Axes({
4915 * "x": {
4916 * range: [0, 100]
4917 * },
4918 * "zoom": {
4919 * range: [50, 30]
4920 * }
4921 * }).on("change", function(event) {
4922 * // event.pos
4923 * // event.delta
4924 * // event.input
4925 * // event.inputEvent
4926 * // event.holding
4927 * // event.set
4928 * // event.isTrusted
4929 *
4930 * // if you want to change the coordinates to move after the 'change' event.
4931 * // it works when the holding value of the change event is true.
4932 * event.holding && event.set({x: 10});
4933 * });
4934 */
4935
4936
4937 __proto.triggerChange = function (pos, isAccurate, depaPos, option, holding) {
4938 if (holding === void 0) {
4939 holding = false;
4940 }
4941
4942 var am = this.am;
4943 var axm = am.axm;
4944 var eventInfo = am.getEventInfo();
4945
4946 var _a = this.getRoundPos(pos, depaPos),
4947 roundPos = _a.roundPos,
4948 roundDepa = _a.roundDepa;
4949
4950 var moveTo = axm.moveTo(roundPos, roundDepa);
4951 var inputEvent = option && option.event || eventInfo && eventInfo.event || null;
4952 var param = {
4953 pos: moveTo.pos,
4954 delta: moveTo.delta,
4955 holding: holding,
4956 inputEvent: inputEvent,
4957 isTrusted: !!inputEvent,
4958 input: option && option.input || eventInfo && eventInfo.input || null,
4959 set: inputEvent ? this.createUserControll(moveTo.pos) : function () {}
4960 };
4961 var result = this.axes.trigger("change", param);
4962 inputEvent && axm.set(param.set()["destPos"]);
4963 return result;
4964 };
4965 /**
4966 * This event is fired when animation starts.
4967 * @ko 에니메이션이 시작할 때 발생한다.
4968 * @name eg.Axes#animationStart
4969 * @event
4970 * @type {object} The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
4971 * @property {Object.<string, number>} depaPos The coordinates when animation starts<ko>애니메이션이 시작 되었을 때의 좌표 </ko>
4972 * @property {Object.<string, number>} destPos The coordinates to move to. If you change this value, you can run the animation<ko>이동할 좌표. 이값을 변경하여 애니메이션을 동작시킬수 있다</ko>
4973 * @property {Object.<string, number>} delta The movement variation of coordinate <ko>좌표의 변화량</ko>
4974 * @property {Number} duration Duration of the animation (unit: ms). If you change this value, you can control the animation duration time.<ko>애니메이션 진행 시간(단위: ms). 이값을 변경하여 애니메이션의 이동시간을 조절할 수 있다.</ko>
4975 * @property {Object} input The instance of inputType where the event occurred. If the value is changed by animation, it returns 'null'.<ko>이벤트가 발생한 inputType 인스턴스. 애니메이션에 의해 값이 변경될 경우에는 'null'을 반환한다.</ko>
4976 * @property {Object} inputEvent The event object received from inputType <ko>inputType으로 부터 받은 이벤트 객체</ko>
4977 * @property {setTo} setTo Specifies the animation coordinates to move after the event <ko>이벤트 이후 이동할 애니메이션 좌표를 지정한다</ko>
4978 * @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
4979 *
4980 * @example
4981 * const axes = new eg.Axes({
4982 * "x": {
4983 * range: [0, 100]
4984 * },
4985 * "zoom": {
4986 * range: [50, 30]
4987 * }
4988 * }).on("release", function(event) {
4989 * // event.depaPos
4990 * // event.destPos
4991 * // event.delta
4992 * // event.input
4993 * // event.inputEvent
4994 * // event.setTo
4995 * // event.isTrusted
4996 *
4997 * // if you want to change the animation coordinates to move after the 'animationStart' event.
4998 * event.setTo({x: 10}, 2000);
4999 * });
5000 */
5001
5002
5003 __proto.triggerAnimationStart = function (param) {
5004 var _a = this.getRoundPos(param.destPos, param.depaPos),
5005 roundPos = _a.roundPos,
5006 roundDepa = _a.roundDepa;
5007
5008 param.destPos = roundPos;
5009 param.depaPos = roundDepa;
5010 param.setTo = this.createUserControll(param.destPos, param.duration);
5011 return this.axes.trigger("animationStart", param);
5012 };
5013 /**
5014 * This event is fired when animation ends.
5015 * @ko 에니메이션이 끝났을 때 발생한다.
5016 * @name eg.Axes#animationEnd
5017 * @event
5018 * @type {object} The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
5019 * @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
5020 *
5021 * @example
5022 * const axes = new eg.Axes({
5023 * "x": {
5024 * range: [0, 100]
5025 * },
5026 * "zoom": {
5027 * range: [50, 30]
5028 * }
5029 * }).on("animationEnd", function(event) {
5030 * // event.isTrusted
5031 * });
5032 */
5033
5034
5035 __proto.triggerAnimationEnd = function (isTrusted) {
5036 if (isTrusted === void 0) {
5037 isTrusted = false;
5038 }
5039
5040 this.axes.trigger("animationEnd", {
5041 isTrusted: isTrusted
5042 });
5043 };
5044 /**
5045 * This event is fired when all actions have been completed.
5046 * @ko 에니메이션이 끝났을 때 발생한다.
5047 * @name eg.Axes#finish
5048 * @event
5049 * @type {object} The object of data to be sent when the event is fired<ko>이벤트가 발생할 때 전달되는 데이터 객체</ko>
5050 * @property {Boolean} isTrusted Returns true if an event was generated by the user action, or false if it was caused by a script or API call <ko>사용자의 액션에 의해 이벤트가 발생하였으면 true, 스크립트나 API호출에 의해 발생하였을 경우에는 false를 반환한다.</ko>
5051 *
5052 * @example
5053 * const axes = new eg.Axes({
5054 * "x": {
5055 * range: [0, 100]
5056 * },
5057 * "zoom": {
5058 * range: [50, 30]
5059 * }
5060 * }).on("finish", function(event) {
5061 * // event.isTrusted
5062 * });
5063 */
5064
5065
5066 __proto.triggerFinish = function (isTrusted) {
5067 if (isTrusted === void 0) {
5068 isTrusted = false;
5069 }
5070
5071 this.axes.trigger("finish", {
5072 isTrusted: isTrusted
5073 });
5074 };
5075
5076 __proto.createUserControll = function (pos, duration) {
5077 if (duration === void 0) {
5078 duration = 0;
5079 } // to controll
5080
5081
5082 var userControl = {
5083 destPos: __assign$1({}, pos),
5084 duration: duration
5085 };
5086 return function (toPos, userDuration) {
5087 toPos && (userControl.destPos = __assign$1({}, toPos));
5088 userDuration !== undefined && (userControl.duration = userDuration);
5089 return userControl;
5090 };
5091 };
5092
5093 __proto.setAnimationManager = function (am) {
5094 this.am = am;
5095 };
5096
5097 __proto.destroy = function () {
5098 this.axes.off();
5099 };
5100
5101 __proto.getRoundPos = function (pos, depaPos) {
5102 // round value if round exist
5103 var roundUnit = this.axes.options.round; // if (round == null) {
5104 // return {pos, depaPos}; // undefined, undefined
5105 // }
5106
5107 return {
5108 roundPos: roundNumbers(pos, roundUnit),
5109 roundDepa: roundNumbers(depaPos, roundUnit)
5110 };
5111 };
5112
5113 return EventManager;
5114 }();
5115
5116 var InterruptManager =
5117 /*#__PURE__*/
5118 function () {
5119 function InterruptManager(options) {
5120 this.options = options;
5121 this._prevented = false; // check whether the animation event was prevented
5122 }
5123
5124 var __proto = InterruptManager.prototype;
5125
5126 __proto.isInterrupting = function () {
5127 // when interruptable is 'true', return value is always 'true'.
5128 return this.options.interruptable || this._prevented;
5129 };
5130
5131 __proto.isInterrupted = function () {
5132 return !this.options.interruptable && this._prevented;
5133 };
5134
5135 __proto.setInterrupt = function (prevented) {
5136 !this.options.interruptable && (this._prevented = prevented);
5137 };
5138
5139 return InterruptManager;
5140 }();
5141
5142 var AxisManager =
5143 /*#__PURE__*/
5144 function () {
5145 function AxisManager(axis, options) {
5146 var _this = this;
5147
5148 this.axis = axis;
5149 this.options = options;
5150
5151 this._complementOptions();
5152
5153 this._pos = Object.keys(this.axis).reduce(function (acc, v) {
5154 acc[v] = _this.axis[v].range[0];
5155 return acc;
5156 }, {});
5157 }
5158 /**
5159 * set up 'css' expression
5160 * @private
5161 */
5162
5163
5164 var __proto = AxisManager.prototype;
5165
5166 __proto._complementOptions = function () {
5167 var _this = this;
5168
5169 Object.keys(this.axis).forEach(function (axis) {
5170 _this.axis[axis] = __assign$1({
5171 range: [0, 100],
5172 bounce: [0, 0],
5173 circular: [false, false]
5174 }, _this.axis[axis]);
5175 ["bounce", "circular"].forEach(function (v) {
5176 var axisOption = _this.axis;
5177 var key = axisOption[axis][v];
5178
5179 if (/string|number|boolean/.test(typeof key)) {
5180 axisOption[axis][v] = [key, key];
5181 }
5182 });
5183 });
5184 };
5185
5186 __proto.getDelta = function (depaPos, destPos) {
5187 var fullDepaPos = this.get(depaPos);
5188 return map(this.get(destPos), function (v, k) {
5189 return v - fullDepaPos[k];
5190 });
5191 };
5192
5193 __proto.get = function (axes) {
5194 var _this = this;
5195
5196 if (axes && Array.isArray(axes)) {
5197 return axes.reduce(function (acc, v) {
5198 if (v && v in _this._pos) {
5199 acc[v] = _this._pos[v];
5200 }
5201
5202 return acc;
5203 }, {});
5204 } else {
5205 return __assign$1({}, this._pos, axes || {});
5206 }
5207 };
5208
5209 __proto.moveTo = function (pos, depaPos) {
5210 if (depaPos === void 0) {
5211 depaPos = this._pos;
5212 }
5213
5214 var delta = map(this._pos, function (v, key) {
5215 return key in pos && key in depaPos ? pos[key] - depaPos[key] : 0;
5216 });
5217 this.set(this.map(pos, function (v, opt) {
5218 return opt ? getCirculatedPos(v, opt.range, opt.circular) : 0;
5219 }));
5220 return {
5221 pos: __assign$1({}, this._pos),
5222 delta: delta
5223 };
5224 };
5225
5226 __proto.set = function (pos) {
5227 for (var k in pos) {
5228 if (k && k in this._pos) {
5229 this._pos[k] = pos[k];
5230 }
5231 }
5232 };
5233
5234 __proto.every = function (pos, callback) {
5235 var axisOptions = this.axis;
5236 return every(pos, function (value, key) {
5237 return callback(value, axisOptions[key], key);
5238 });
5239 };
5240
5241 __proto.filter = function (pos, callback) {
5242 var axisOptions = this.axis;
5243 return filter(pos, function (value, key) {
5244 return callback(value, axisOptions[key], key);
5245 });
5246 };
5247
5248 __proto.map = function (pos, callback) {
5249 var axisOptions = this.axis;
5250 return map(pos, function (value, key) {
5251 return callback(value, axisOptions[key], key);
5252 });
5253 };
5254
5255 __proto.isOutside = function (axes) {
5256 return !this.every(axes ? this.get(axes) : this._pos, function (v, opt) {
5257 return !isOutside(v, opt.range);
5258 });
5259 };
5260
5261 __proto.getAxisOptions = function (key) {
5262 return this.axis[key];
5263 };
5264
5265 return AxisManager;
5266 }();
5267
5268 var InputObserver =
5269 /*#__PURE__*/
5270 function () {
5271 function InputObserver(_a) {
5272 var options = _a.options,
5273 itm = _a.itm,
5274 em = _a.em,
5275 axm = _a.axm,
5276 am = _a.am;
5277 this.isOutside = false;
5278 this.moveDistance = null;
5279 this.isStopped = false;
5280 this.options = options;
5281 this.itm = itm;
5282 this.em = em;
5283 this.axm = axm;
5284 this.am = am;
5285 } // when move pointer is held in outside
5286
5287
5288 var __proto = InputObserver.prototype;
5289
5290 __proto.atOutside = function (pos) {
5291 var _this = this;
5292
5293 if (this.isOutside) {
5294 return this.axm.map(pos, function (v, opt) {
5295 var tn = opt.range[0] - opt.bounce[0];
5296 var tx = opt.range[1] + opt.bounce[1];
5297 return v > tx ? tx : v < tn ? tn : v;
5298 });
5299 } else {
5300 // when start pointer is held in inside
5301 // get a initialization slope value to prevent smooth animation.
5302 var initSlope_1 = this.am.easing(0.00001) / 0.00001;
5303 return this.axm.map(pos, function (v, opt) {
5304 var min = opt.range[0];
5305 var max = opt.range[1];
5306 var out = opt.bounce;
5307 var circular = opt.circular;
5308
5309 if (circular && (circular[0] || circular[1])) {
5310 return v;
5311 } else if (v < min) {
5312 // left
5313 return min - _this.am.easing((min - v) / (out[0] * initSlope_1)) * out[0];
5314 } else if (v > max) {
5315 // right
5316 return max + _this.am.easing((v - max) / (out[1] * initSlope_1)) * out[1];
5317 }
5318
5319 return v;
5320 });
5321 }
5322 };
5323
5324 __proto.get = function (input) {
5325 return this.axm.get(input.axes);
5326 };
5327
5328 __proto.hold = function (input, event) {
5329 if (this.itm.isInterrupted() || !input.axes.length) {
5330 return;
5331 }
5332
5333 var changeOption = {
5334 input: input,
5335 event: event
5336 };
5337 this.isStopped = false;
5338 this.itm.setInterrupt(true);
5339 this.am.grab(input.axes, changeOption);
5340 !this.moveDistance && this.em.triggerHold(this.axm.get(), changeOption);
5341 this.isOutside = this.axm.isOutside(input.axes);
5342 this.moveDistance = this.axm.get(input.axes);
5343 };
5344
5345 __proto.change = function (input, event, offset) {
5346 if (this.isStopped || !this.itm.isInterrupting() || this.axm.every(offset, function (v) {
5347 return v === 0;
5348 })) {
5349 return;
5350 }
5351
5352 var depaPos = this.moveDistance || this.axm.get(input.axes);
5353 var destPos; // for outside logic
5354
5355 destPos = map(depaPos, function (v, k) {
5356 return v + (offset[k] || 0);
5357 });
5358 this.moveDistance && (this.moveDistance = destPos); // from outside to inside
5359
5360 if (this.isOutside && this.axm.every(depaPos, function (v, opt) {
5361 return !isOutside(v, opt.range);
5362 })) {
5363 this.isOutside = false;
5364 }
5365
5366 depaPos = this.atOutside(depaPos);
5367 destPos = this.atOutside(destPos);
5368 var isCanceled = !this.em.triggerChange(destPos, false, depaPos, {
5369 input: input,
5370 event: event
5371 }, true);
5372
5373 if (isCanceled) {
5374 this.isStopped = true;
5375 this.moveDistance = null;
5376 this.am.finish(false);
5377 }
5378 };
5379
5380 __proto.release = function (input, event, offset, inputDuration) {
5381 if (this.isStopped || !this.itm.isInterrupting() || !this.moveDistance) {
5382 return;
5383 }
5384
5385 var pos = this.axm.get(input.axes);
5386 var depaPos = this.axm.get();
5387 var destPos = this.axm.get(this.axm.map(offset, function (v, opt, k) {
5388 if (opt.circular && (opt.circular[0] || opt.circular[1])) {
5389 return pos[k] + v;
5390 } else {
5391 return getInsidePosition(pos[k] + v, opt.range, opt.circular, opt.bounce);
5392 }
5393 }));
5394 var duration = this.am.getDuration(destPos, pos, inputDuration);
5395
5396 if (duration === 0) {
5397 destPos = __assign$1({}, depaPos);
5398 } // prepare params
5399
5400
5401 var param = {
5402 depaPos: depaPos,
5403 destPos: destPos,
5404 duration: duration,
5405 delta: this.axm.getDelta(depaPos, destPos),
5406 inputEvent: event,
5407 input: input,
5408 isTrusted: true
5409 };
5410 this.em.triggerRelease(param);
5411 this.moveDistance = null; // to contol
5412
5413 var userWish = this.am.getUserControll(param);
5414 var isEqual = equal(userWish.destPos, depaPos);
5415 var changeOption = {
5416 input: input,
5417 event: event
5418 };
5419
5420 if (isEqual || userWish.duration === 0) {
5421 !isEqual && this.em.triggerChange(userWish.destPos, false, depaPos, changeOption, true);
5422 this.itm.setInterrupt(false);
5423
5424 if (this.axm.isOutside()) {
5425 this.am.restore(changeOption);
5426 } else {
5427 this.em.triggerFinish(true);
5428 }
5429 } else {
5430 this.am.animateTo(userWish.destPos, userWish.duration, changeOption);
5431 }
5432 };
5433
5434 return InputObserver;
5435 }();
5436
5437 // export const DIRECTION_NONE = 1;
5438 var IOS_EDGE_THRESHOLD = 30;
5439 var IS_IOS_SAFARI = "ontouchstart" in win$1 && agent(win$1.navigator.userAgent).browser.name.indexOf("safari") > -1;
5440 var TRANSFORM = function () {
5441 if (typeof document === "undefined") {
5442 return "";
5443 }
5444
5445 var bodyStyle = (document.head || document.getElementsByTagName("head")[0]).style;
5446 var target = ["transform", "webkitTransform", "msTransform", "mozTransform"];
5447
5448 for (var i = 0, len = target.length; i < len; i++) {
5449 if (target[i] in bodyStyle) {
5450 return target[i];
5451 }
5452 }
5453
5454 return "";
5455 }();
5456
5457 /**
5458 * @typedef {Object} AxisOption The Axis information. The key of the axis specifies the name to use as the logical virtual coordinate system.
5459 * @ko 축 정보. 축의 키는 논리적인 가상 좌표계로 사용할 이름을 지정한다.
5460 * @property {Number[]} [range] The coordinate of range <ko>좌표 범위</ko>
5461 * @property {Number} [range.0=0] The coordinate of the minimum <ko>최소 좌표</ko>
5462 * @property {Number} [range.1=0] The coordinate of the maximum <ko>최대 좌표</ko>
5463 * @property {Number[]} [bounce] The size of bouncing area. The coordinates can exceed the coordinate area as much as the bouncing area based on user action. If the coordinates does not exceed the bouncing area when an element is dragged, the coordinates where bouncing effects are applied are retuned back into the coordinate area<ko>바운스 영역의 크기. 사용자의 동작에 따라 좌표가 좌표 영역을 넘어 바운스 영역의 크기만큼 더 이동할 수 있다. 사용자가 끌어다 놓는 동작을 했을 때 좌표가 바운스 영역에 있으면, 바운스 효과가 적용된 좌표가 다시 좌표 영역 안으로 들어온다</ko>
5464 * @property {Number} [bounce.0=0] The size of coordinate of the minimum area <ko>최소 좌표 바운스 영역의 크기</ko>
5465 * @property {Number} [bounce.1=0] The size of coordinate of the maximum area <ko>최대 좌표 바운스 영역의 크기</ko>
5466 * @property {Boolean[]} [circular] Indicates whether a circular element is available. If it is set to "true" and an element is dragged outside the coordinate area, the element will appear on the other side.<ko>순환 여부. 'true'로 설정한 방향의 좌표 영역 밖으로 엘리먼트가 이동하면 반대 방향에서 엘리먼트가 나타난다</ko>
5467 * @property {Boolean} [circular.0=false] Indicates whether to circulate to the coordinate of the minimum <ko>최소 좌표 방향의 순환 여부</ko>
5468 * @property {Boolean} [circular.1=false] Indicates whether to circulate to the coordinate of the maximum <ko>최대 좌표 방향의 순환 여부</ko>
5469 **/
5470
5471 /**
5472 * @typedef {Object} AxesOption The option object of the eg.Axes module
5473 * @ko eg.Axes 모듈의 옵션 객체
5474 * @property {Function} [easing=easing.easeOutCubic] The easing function to apply to an animation <ko>애니메이션에 적용할 easing 함수</ko>
5475 * @property {Number} [maximumDuration=Infinity] Maximum duration of the animation <ko>가속도에 의해 애니메이션이 동작할 때의 최대 좌표 이동 시간</ko>
5476 * @property {Number} [minimumDuration=0] Minimum duration of the animation <ko>가속도에 의해 애니메이션이 동작할 때의 최소 좌표 이동 시간</ko>
5477 * @property {Number} [deceleration=0.0006] Deceleration of the animation where acceleration is manually enabled by user. A higher value indicates shorter running time. <ko>사용자의 동작으로 가속도가 적용된 애니메이션의 감속도. 값이 높을수록 애니메이션 실행 시간이 짧아진다</ko>
5478 * @property {Boolean} [interruptable=true] Indicates whether an animation is interruptible.<br>- true: It can be paused or stopped by user action or the API.<br>- false: It cannot be paused or stopped by user action or the API while it is running.<ko>진행 중인 애니메이션 중지 가능 여부.<br>- true: 사용자의 동작이나 API로 애니메이션을 중지할 수 있다.<br>- false: 애니메이션이 진행 중일 때는 사용자의 동작이나 API가 적용되지 않는다</ko>
5479 * @property {Number} [round = null] Rounding unit. For example, 0.1 rounds to 0.1 decimal point(6.1234 => 6.1), 5 rounds to 5 (93 => 95) <br>[Details](https://github.com/naver/egjs-axes/wiki/round-option)<ko>반올림 단위. 예를 들어 0.1 은 소숫점 0.1 까지 반올림(6.1234 => 6.1), 5 는 5 단위로 반올림(93 => 95).<br>[상세내용](https://github.com/naver/egjs-axes/wiki/round-option)</ko>
5480 **/
5481
5482 /**
5483 * @class eg.Axes
5484 * @classdesc A module used to change the information of user action entered by various input devices such as touch screen or mouse into the logical virtual coordinates. You can easily create a UI that responds to user actions.
5485 * @ko 터치 입력 장치나 마우스와 같은 다양한 입력 장치를 통해 전달 받은 사용자의 동작을 논리적인 가상 좌표로 변경하는 모듈이다. 사용자 동작에 반응하는 UI를 손쉽게 만들수 있다.
5486 * @extends eg.Component
5487 *
5488 * @param {Object.<string, AxisOption>} axis Axis information managed by eg.Axes. The key of the axis specifies the name to use as the logical virtual coordinate system. <ko>eg.Axes가 관리하는 축 정보. 축의 키는 논리적인 가상 좌표계로 사용할 이름을 지정한다.</ko>
5489 * @param {AxesOption} [options] The option object of the eg.Axes module<ko>eg.Axes 모듈의 옵션 객체</ko>
5490 * @param {Object.<string, number>} [startPos] The coordinates to be moved when creating an instance. not triggering change event.<ko>인스턴스 생성시 이동할 좌표, change 이벤트는 발생하지 않음.</ko>
5491 *
5492 * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest", "edge" : "latest", "ios" : "7+", "an" : "2.3+ (except 3.x)"}
5493 * @example
5494 *
5495 * // 1. Initialize eg.Axes
5496 * const axes = new eg.Axes({
5497 * something1: {
5498 * range: [0, 150],
5499 * bounce: 50
5500 * },
5501 * something2: {
5502 * range: [0, 200],
5503 * bounce: 100
5504 * },
5505 * somethingN: {
5506 * range: [1, 10],
5507 * }
5508 * }, {
5509 * deceleration : 0.0024
5510 * });
5511 *
5512 * // 2. attach event handler
5513 * axes.on({
5514 * "hold" : function(evt) {
5515 * },
5516 * "release" : function(evt) {
5517 * },
5518 * "animationStart" : function(evt) {
5519 * },
5520 * "animationEnd" : function(evt) {
5521 * },
5522 * "change" : function(evt) {
5523 * }
5524 * });
5525 *
5526 * // 3. Initialize inputTypes
5527 * const panInputArea = new eg.Axes.PanInput("#area", {
5528 * scale: [0.5, 1]
5529 * });
5530 * const panInputHmove = new eg.Axes.PanInput("#hmove");
5531 * const panInputVmove = new eg.Axes.PanInput("#vmove");
5532 * const pinchInputArea = new eg.Axes.PinchInput("#area", {
5533 * scale: 1.5
5534 * });
5535 *
5536 * // 4. Connect eg.Axes and InputTypes
5537 * // [PanInput] When the mouse or touchscreen is down and moved.
5538 * // Connect the 'something2' axis to the mouse or touchscreen x position and
5539 * // connect the 'somethingN' axis to the mouse or touchscreen y position.
5540 * axes.connect(["something2", "somethingN"], panInputArea); // or axes.connect("something2 somethingN", panInputArea);
5541 *
5542 * // Connect only one 'something1' axis to the mouse or touchscreen x position.
5543 * axes.connect(["something1"], panInputHmove); // or axes.connect("something1", panInputHmove);
5544 *
5545 * // Connect only one 'something2' axis to the mouse or touchscreen y position.
5546 * axes.connect(["", "something2"], panInputVmove); // or axes.connect(" something2", panInputVmove);
5547 *
5548 * // [PinchInput] Connect 'something2' axis when two pointers are moving toward (zoom-in) or away from each other (zoom-out).
5549 * axes.connect("something2", pinchInputArea);
5550 */
5551
5552 var Axes =
5553 /*#__PURE__*/
5554 function (_super) {
5555 __extends$2(Axes, _super);
5556
5557 function Axes(axis, options, startPos) {
5558 if (axis === void 0) {
5559 axis = {};
5560 }
5561
5562 if (options === void 0) {
5563 options = {};
5564 }
5565
5566 var _this = _super.call(this) || this;
5567
5568 _this.axis = axis;
5569 _this._inputs = [];
5570 _this.options = __assign$1({
5571 easing: function easeOutCubic(x) {
5572 return 1 - Math.pow(1 - x, 3);
5573 },
5574 interruptable: true,
5575 maximumDuration: Infinity,
5576 minimumDuration: 0,
5577 deceleration: 0.0006,
5578 round: null
5579 }, options);
5580 _this.itm = new InterruptManager(_this.options);
5581 _this.axm = new AxisManager(_this.axis, _this.options);
5582 _this.em = new EventManager(_this);
5583 _this.am = new AnimationManager(_this);
5584 _this.io = new InputObserver(_this);
5585
5586 _this.em.setAnimationManager(_this.am);
5587
5588 startPos && _this.em.triggerChange(startPos);
5589 return _this;
5590 }
5591 /**
5592 * Connect the axis of eg.Axes to the inputType.
5593 * @ko eg.Axes의 축과 inputType을 연결한다
5594 * @method eg.Axes#connect
5595 * @param {(String[]|String)} axes The name of the axis to associate with inputType <ko>inputType과 연결할 축의 이름</ko>
5596 * @param {Object} inputType The inputType instance to associate with the axis of eg.Axes <ko>eg.Axes의 축과 연결할 inputType 인스턴스<ko>
5597 * @return {eg.Axes} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
5598 * @example
5599 * const axes = new eg.Axes({
5600 * "x": {
5601 * range: [0, 100]
5602 * },
5603 * "xOther": {
5604 * range: [-100, 100]
5605 * }
5606 * });
5607 *
5608 * axes.connect("x", new eg.Axes.PanInput("#area1"))
5609 * .connect("x xOther", new eg.Axes.PanInput("#area2"))
5610 * .connect(" xOther", new eg.Axes.PanInput("#area3"))
5611 * .connect(["x"], new eg.Axes.PanInput("#area4"))
5612 * .connect(["xOther", "x"], new eg.Axes.PanInput("#area5"))
5613 * .connect(["", "xOther"], new eg.Axes.PanInput("#area6"));
5614 */
5615
5616
5617 var __proto = Axes.prototype;
5618
5619 __proto.connect = function (axes, inputType) {
5620 var mapped;
5621
5622 if (typeof axes === "string") {
5623 mapped = axes.split(" ");
5624 } else {
5625 mapped = axes.concat();
5626 } // check same instance
5627
5628
5629 if (~this._inputs.indexOf(inputType)) {
5630 this.disconnect(inputType);
5631 } // check same element in hammer type for share
5632
5633
5634 if ("hammer" in inputType) {
5635 var targets = this._inputs.filter(function (v) {
5636 return v.hammer && v.element === inputType.element;
5637 });
5638
5639 if (targets.length) {
5640 inputType.hammer = targets[0].hammer;
5641 }
5642 }
5643
5644 inputType.mapAxes(mapped);
5645 inputType.connect(this.io);
5646
5647 this._inputs.push(inputType);
5648
5649 return this;
5650 };
5651 /**
5652 * Disconnect the axis of eg.Axes from the inputType.
5653 * @ko eg.Axes의 축과 inputType의 연결을 끊는다.
5654 * @method eg.Axes#disconnect
5655 * @param {Object} [inputType] An inputType instance associated with the axis of eg.Axes <ko>eg.Axes의 축과 연결한 inputType 인스턴스<ko>
5656 * @return {eg.Axes} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
5657 * @example
5658 * const axes = new eg.Axes({
5659 * "x": {
5660 * range: [0, 100]
5661 * },
5662 * "xOther": {
5663 * range: [-100, 100]
5664 * }
5665 * });
5666 *
5667 * const input1 = new eg.Axes.PanInput("#area1");
5668 * const input2 = new eg.Axes.PanInput("#area2");
5669 * const input3 = new eg.Axes.PanInput("#area3");
5670 *
5671 * axes.connect("x", input1);
5672 * .connect("x xOther", input2)
5673 * .connect(["xOther", "x"], input3);
5674 *
5675 * axes.disconnect(input1); // disconnects input1
5676 * axes.disconnect(); // disconnects all of them
5677 */
5678
5679
5680 __proto.disconnect = function (inputType) {
5681 if (inputType) {
5682 var index = this._inputs.indexOf(inputType);
5683
5684 if (index >= 0) {
5685 this._inputs[index].disconnect();
5686
5687 this._inputs.splice(index, 1);
5688 }
5689 } else {
5690 this._inputs.forEach(function (v) {
5691 return v.disconnect();
5692 });
5693
5694 this._inputs = [];
5695 }
5696
5697 return this;
5698 };
5699 /**
5700 * Returns the current position of the coordinates.
5701 * @ko 좌표의 현재 위치를 반환한다
5702 * @method eg.Axes#get
5703 * @param {Object} [axes] The names of the axis <ko>축 이름들</ko>
5704 * @return {Object.<string, number>} Axis coordinate information <ko>축 좌표 정보</ko>
5705 * @example
5706 * const axes = new eg.Axes({
5707 * "x": {
5708 * range: [0, 100]
5709 * },
5710 * "xOther": {
5711 * range: [-100, 100]
5712 * },
5713 * "zoom": {
5714 * range: [50, 30]
5715 * }
5716 * });
5717 *
5718 * axes.get(); // {"x": 0, "xOther": -100, "zoom": 50}
5719 * axes.get(["x", "zoom"]); // {"x": 0, "zoom": 50}
5720 */
5721
5722
5723 __proto.get = function (axes) {
5724 return this.axm.get(axes);
5725 };
5726 /**
5727 * Moves an axis to specific coordinates.
5728 * @ko 좌표를 이동한다.
5729 * @method eg.Axes#setTo
5730 * @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
5731 * @param {Number} [duration=0] Duration of the animation (unit: ms) <ko>애니메이션 진행 시간(단위: ms)</ko>
5732 * @return {eg.Axes} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
5733 * @example
5734 * const axes = new eg.Axes({
5735 * "x": {
5736 * range: [0, 100]
5737 * },
5738 * "xOther": {
5739 * range: [-100, 100]
5740 * },
5741 * "zoom": {
5742 * range: [50, 30]
5743 * }
5744 * });
5745 *
5746 * axes.setTo({"x": 30, "zoom": 60});
5747 * axes.get(); // {"x": 30, "xOther": -100, "zoom": 60}
5748 *
5749 * axes.setTo({"x": 100, "xOther": 60}, 1000); // animatation
5750 *
5751 * // after 1000 ms
5752 * axes.get(); // {"x": 100, "xOther": 60, "zoom": 60}
5753 */
5754
5755
5756 __proto.setTo = function (pos, duration) {
5757 if (duration === void 0) {
5758 duration = 0;
5759 }
5760
5761 this.am.setTo(pos, duration);
5762 return this;
5763 };
5764 /**
5765 * Moves an axis from the current coordinates to specific coordinates.
5766 * @ko 현재 좌표를 기준으로 좌표를 이동한다.
5767 * @method eg.Axes#setBy
5768 * @param {Object.<string, number>} pos The coordinate to move to <ko>이동할 좌표</ko>
5769 * @param {Number} [duration=0] Duration of the animation (unit: ms) <ko>애니메이션 진행 시간(단위: ms)</ko>
5770 * @return {eg.Axes} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
5771 * @example
5772 * const axes = new eg.Axes({
5773 * "x": {
5774 * range: [0, 100]
5775 * },
5776 * "xOther": {
5777 * range: [-100, 100]
5778 * },
5779 * "zoom": {
5780 * range: [50, 30]
5781 * }
5782 * });
5783 *
5784 * axes.setBy({"x": 30, "zoom": 10});
5785 * axes.get(); // {"x": 30, "xOther": -100, "zoom": 60}
5786 *
5787 * axes.setBy({"x": 70, "xOther": 60}, 1000); // animatation
5788 *
5789 * // after 1000 ms
5790 * axes.get(); // {"x": 100, "xOther": -40, "zoom": 60}
5791 */
5792
5793
5794 __proto.setBy = function (pos, duration) {
5795 if (duration === void 0) {
5796 duration = 0;
5797 }
5798
5799 this.am.setBy(pos, duration);
5800 return this;
5801 };
5802 /**
5803 * Returns whether there is a coordinate in the bounce area of ​​the target axis.
5804 * @ko 대상 축 중 bounce영역에 좌표가 존재하는지를 반환한다
5805 * @method eg.Axes#isBounceArea
5806 * @param {Object} [axes] The names of the axis <ko>축 이름들</ko>
5807 * @return {Boolen} Whether the bounce area exists. <ko>bounce 영역 존재 여부</ko>
5808 * @example
5809 * const axes = new eg.Axes({
5810 * "x": {
5811 * range: [0, 100]
5812 * },
5813 * "xOther": {
5814 * range: [-100, 100]
5815 * },
5816 * "zoom": {
5817 * range: [50, 30]
5818 * }
5819 * });
5820 *
5821 * axes.isBounceArea(["x"]);
5822 * axes.isBounceArea(["x", "zoom"]);
5823 * axes.isBounceArea();
5824 */
5825
5826
5827 __proto.isBounceArea = function (axes) {
5828 return this.axm.isOutside(axes);
5829 };
5830 /**
5831 * Destroys properties, and events used in a module and disconnect all connections to inputTypes.
5832 * @ko 모듈에 사용한 속성, 이벤트를 해제한다. 모든 inputType과의 연결을 끊는다.
5833 * @method eg.Axes#destroy
5834 */
5835
5836
5837 __proto.destroy = function () {
5838 this.disconnect();
5839 this.em.destroy();
5840 };
5841 /**
5842 * Version info string
5843 * @ko 버전정보 문자열
5844 * @name VERSION
5845 * @static
5846 * @type {String}
5847 * @example
5848 * eg.Axes.VERSION; // ex) 3.3.3
5849 * @memberof eg.Axes
5850 */
5851
5852
5853 Axes.VERSION = "2.7.0";
5854 /**
5855 * @name eg.Axes.TRANSFORM
5856 * @desc Returns the transform attribute with CSS vendor prefixes.
5857 * @ko CSS vendor prefixes를 붙인 transform 속성을 반환한다.
5858 *
5859 * @constant
5860 * @type {String}
5861 * @example
5862 * eg.Axes.TRANSFORM; // "transform" or "webkitTransform"
5863 */
5864
5865 Axes.TRANSFORM = TRANSFORM;
5866 /**
5867 * @name eg.Axes.DIRECTION_NONE
5868 * @constant
5869 * @type {Number}
5870 */
5871
5872 Axes.DIRECTION_NONE = DIRECTION_NONE;
5873 /**
5874 * @name eg.Axes.DIRECTION_LEFT
5875 * @constant
5876 * @type {Number}
5877 */
5878
5879 Axes.DIRECTION_LEFT = DIRECTION_LEFT;
5880 /**
5881 * @name eg.Axes.DIRECTION_RIGHT
5882 * @constant
5883 * @type {Number}
5884 */
5885
5886 Axes.DIRECTION_RIGHT = DIRECTION_RIGHT;
5887 /**
5888 * @name eg.Axes.DIRECTION_UP
5889 * @constant
5890 * @type {Number}
5891 */
5892
5893 Axes.DIRECTION_UP = DIRECTION_UP;
5894 /**
5895 * @name eg.Axes.DIRECTION_DOWN
5896 * @constant
5897 * @type {Number}
5898 */
5899
5900 Axes.DIRECTION_DOWN = DIRECTION_DOWN;
5901 /**
5902 * @name eg.Axes.DIRECTION_HORIZONTAL
5903 * @constant
5904 * @type {Number}
5905 */
5906
5907 Axes.DIRECTION_HORIZONTAL = DIRECTION_HORIZONTAL;
5908 /**
5909 * @name eg.Axes.DIRECTION_VERTICAL
5910 * @constant
5911 * @type {Number}
5912 */
5913
5914 Axes.DIRECTION_VERTICAL = DIRECTION_VERTICAL;
5915 /**
5916 * @name eg.Axes.DIRECTION_ALL
5917 * @constant
5918 * @type {Number}
5919 */
5920
5921 Axes.DIRECTION_ALL = DIRECTION_ALL;
5922 return Axes;
5923 }(Component);
5924
5925 var SUPPORT_POINTER_EVENTS$1 = "PointerEvent" in win$1 || "MSPointerEvent" in win$1;
5926 var SUPPORT_TOUCH$1 = ("ontouchstart" in win$1);
5927 var UNIQUEKEY = "_EGJS_AXES_INPUTTYPE_";
5928 function toAxis(source, offset) {
5929 return offset.reduce(function (acc, v, i) {
5930 if (source[i]) {
5931 acc[source[i]] = v;
5932 }
5933
5934 return acc;
5935 }, {});
5936 }
5937 function createHammer(element, options) {
5938 try {
5939 // create Hammer
5940 return new Manager(element, __assign$1({}, options));
5941 } catch (e) {
5942 return null;
5943 }
5944 }
5945 function convertInputType(inputType) {
5946 if (inputType === void 0) {
5947 inputType = [];
5948 }
5949
5950 var hasTouch = false;
5951 var hasMouse = false;
5952 var hasPointer = false;
5953 inputType.forEach(function (v) {
5954 switch (v) {
5955 case "mouse":
5956 hasMouse = true;
5957 break;
5958
5959 case "touch":
5960 hasTouch = SUPPORT_TOUCH$1;
5961 break;
5962
5963 case "pointer":
5964 hasPointer = SUPPORT_POINTER_EVENTS$1;
5965 // no default
5966 }
5967 });
5968
5969 if (hasPointer) {
5970 return PointerEventInput;
5971 } else if (hasTouch && hasMouse) {
5972 return TouchMouseInput;
5973 } else if (hasTouch) {
5974 return TouchInput;
5975 } else if (hasMouse) {
5976 return MouseInput;
5977 }
5978
5979 return null;
5980 }
5981
5982 function getDirectionByAngle(angle, thresholdAngle) {
5983 if (thresholdAngle < 0 || thresholdAngle > 90) {
5984 return DIRECTION_NONE;
5985 }
5986
5987 var toAngle = Math.abs(angle);
5988 return toAngle > thresholdAngle && toAngle < 180 - thresholdAngle ? DIRECTION_VERTICAL : DIRECTION_HORIZONTAL;
5989 }
5990 function getNextOffset(speeds, deceleration) {
5991 var normalSpeed = Math.sqrt(speeds[0] * speeds[0] + speeds[1] * speeds[1]);
5992 var duration = Math.abs(normalSpeed / -deceleration);
5993 return [speeds[0] / 2 * duration, speeds[1] / 2 * duration];
5994 }
5995 function useDirection(checkType, direction, userDirection) {
5996 if (userDirection) {
5997 return !!(direction === DIRECTION_ALL || direction & checkType && userDirection & checkType);
5998 } else {
5999 return !!(direction & checkType);
6000 }
6001 }
6002 /**
6003 * @typedef {Object} PanInputOption The option object of the eg.Axes.PanInput module.
6004 * @ko eg.Axes.PanInput 모듈의 옵션 객체
6005 * @property {String[]} [inputType=["touch","mouse", "pointer"]] Types of input devices.<br>- touch: Touch screen<br>- mouse: Mouse <ko>입력 장치 종류.<br>- touch: 터치 입력 장치<br>- mouse: 마우스</ko>
6006 * @property {Number[]} [scale] Coordinate scale that a user can move<ko>사용자의 동작으로 이동하는 좌표의 배율</ko>
6007 * @property {Number} [scale.0=1] horizontal axis scale <ko>수평축 배율</ko>
6008 * @property {Number} [scale.1=1] vertical axis scale <ko>수직축 배율</ko>
6009 * @property {Number} [thresholdAngle=45] The threshold value that determines whether user action is horizontal or vertical (0~90) <ko>사용자의 동작이 가로 방향인지 세로 방향인지 판단하는 기준 각도(0~90)</ko>
6010 * @property {Number} [threshold=0] Minimal pan distance required before recognizing <ko>사용자의 Pan 동작을 인식하기 위해산 최소한의 거리</ko>
6011 * @property {Number} [iOSEdgeSwipeThreshold=30] Area (px) that can go to the next page when swiping the right edge in iOS safari <ko>iOS Safari에서 오른쪽 엣지를 스와이프 하는 경우 다음 페이지로 넘어갈 수 있는 영역(px)</ko>
6012 * @property {Object} [hammerManagerOptions={cssProps: {userSelect: "none",touchSelect: "none",touchCallout: "none",userDrag: "none"}] Options of Hammer.Manager <ko>Hammer.Manager의 옵션</ko>
6013 **/
6014
6015 /**
6016 * @class eg.Axes.PanInput
6017 * @classdesc A module that passes the amount of change to eg.Axes when the mouse or touchscreen is down and moved. use less than two axes.
6018 * @ko 마우스나 터치 스크린을 누르고 움직일때의 변화량을 eg.Axes에 전달하는 모듈. 두개 이하의 축을 사용한다.
6019 *
6020 * @example
6021 * const pan = new eg.Axes.PanInput("#area", {
6022 * inputType: ["touch"],
6023 * scale: [1, 1.3],
6024 * });
6025 *
6026 * // Connect the 'something2' axis to the mouse or touchscreen x position when the mouse or touchscreen is down and moved.
6027 * // Connect the 'somethingN' axis to the mouse or touchscreen y position when the mouse or touchscreen is down and moved.
6028 * axes.connect(["something2", "somethingN"], pan); // or axes.connect("something2 somethingN", pan);
6029 *
6030 * // Connect only one 'something1' axis to the mouse or touchscreen x position when the mouse or touchscreen is down and moved.
6031 * axes.connect(["something1"], pan); // or axes.connect("something1", pan);
6032 *
6033 * // Connect only one 'something2' axis to the mouse or touchscreen y position when the mouse or touchscreen is down and moved.
6034 * axes.connect(["", "something2"], pan); // or axes.connect(" something2", pan);
6035 *
6036 * @param {HTMLElement|String|jQuery} element An element to use the eg.Axes.PanInput module <ko>eg.Axes.PanInput 모듈을 사용할 엘리먼트</ko>
6037 * @param {PanInputOption} [options] The option object of the eg.Axes.PanInput module<ko>eg.Axes.PanInput 모듈의 옵션 객체</ko>
6038 */
6039
6040 var PanInput =
6041 /*#__PURE__*/
6042 function () {
6043 function PanInput(el, options) {
6044 this.axes = [];
6045 this.hammer = null;
6046 this.element = null;
6047 this.panRecognizer = null;
6048 this.isRightEdge = false;
6049 this.rightEdgeTimer = 0;
6050 this.panFlag = false;
6051 /**
6052 * Hammer helps you add support for touch gestures to your page
6053 *
6054 * @external Hammer
6055 * @see {@link http://hammerjs.github.io|Hammer.JS}
6056 * @see {@link http://hammerjs.github.io/jsdoc/Hammer.html|Hammer.JS API documents}
6057 * @see Hammer.JS applies specific CSS properties by {@link http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html|default} when creating an instance. The eg.Axes module removes all default CSS properties provided by Hammer.JS
6058 */
6059
6060 if (typeof Manager === "undefined") {
6061 throw new Error("The Hammerjs must be loaded before eg.Axes.PanInput.\nhttp://hammerjs.github.io/");
6062 }
6063
6064 this.element = $(el);
6065 this.options = __assign$1({
6066 inputType: ["touch", "mouse", "pointer"],
6067 scale: [1, 1],
6068 thresholdAngle: 45,
6069 threshold: 0,
6070 iOSEdgeSwipeThreshold: IOS_EDGE_THRESHOLD,
6071 hammerManagerOptions: {
6072 // css properties were removed due to usablility issue
6073 // http://hammerjs.github.io/jsdoc/Hammer.defaults.cssProps.html
6074 cssProps: {
6075 userSelect: "none",
6076 touchSelect: "none",
6077 touchCallout: "none",
6078 userDrag: "none"
6079 }
6080 }
6081 }, options);
6082 this.onHammerInput = this.onHammerInput.bind(this);
6083 this.onPanmove = this.onPanmove.bind(this);
6084 this.onPanend = this.onPanend.bind(this);
6085 }
6086
6087 var __proto = PanInput.prototype;
6088
6089 __proto.mapAxes = function (axes) {
6090 var useHorizontal = !!axes[0];
6091 var useVertical = !!axes[1];
6092
6093 if (useHorizontal && useVertical) {
6094 this._direction = DIRECTION_ALL;
6095 } else if (useHorizontal) {
6096 this._direction = DIRECTION_HORIZONTAL;
6097 } else if (useVertical) {
6098 this._direction = DIRECTION_VERTICAL;
6099 } else {
6100 this._direction = DIRECTION_NONE;
6101 }
6102
6103 this.axes = axes;
6104 };
6105
6106 __proto.connect = function (observer) {
6107 var hammerOption = {
6108 direction: this._direction,
6109 threshold: this.options.threshold
6110 };
6111
6112 if (this.hammer) {
6113 // for sharing hammer instance.
6114 // hammer remove previous PanRecognizer.
6115 this.removeRecognizer();
6116 this.dettachEvent();
6117 } else {
6118 var keyValue = this.element[UNIQUEKEY];
6119
6120 if (!keyValue) {
6121 keyValue = String(Math.round(Math.random() * new Date().getTime()));
6122 }
6123
6124 var inputClass = convertInputType(this.options.inputType);
6125
6126 if (!inputClass) {
6127 throw new Error("Wrong inputType parameter!");
6128 }
6129
6130 this.hammer = createHammer(this.element, __assign$1({
6131 inputClass: inputClass
6132 }, this.options.hammerManagerOptions));
6133 this.element[UNIQUEKEY] = keyValue;
6134 }
6135
6136 this.panRecognizer = new PanRecognizer(hammerOption);
6137 this.hammer.add(this.panRecognizer);
6138 this.attachEvent(observer);
6139 return this;
6140 };
6141
6142 __proto.disconnect = function () {
6143 this.removeRecognizer();
6144
6145 if (this.hammer) {
6146 this.dettachEvent();
6147 }
6148
6149 this._direction = DIRECTION_NONE;
6150 return this;
6151 };
6152 /**
6153 * Destroys elements, properties, and events used in a module.
6154 * @ko 모듈에 사용한 엘리먼트와 속성, 이벤트를 해제한다.
6155 * @method eg.Axes.PanInput#destroy
6156 */
6157
6158
6159 __proto.destroy = function () {
6160 this.disconnect();
6161
6162 if (this.hammer && this.hammer.recognizers.length === 0) {
6163 this.hammer.destroy();
6164 }
6165
6166 delete this.element[UNIQUEKEY];
6167 this.element = null;
6168 this.hammer = null;
6169 };
6170 /**
6171 * Enables input devices
6172 * @ko 입력 장치를 사용할 수 있게 한다
6173 * @method eg.Axes.PanInput#enable
6174 * @return {eg.Axes.PanInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
6175 */
6176
6177
6178 __proto.enable = function () {
6179 this.hammer && (this.hammer.get("pan").options.enable = true);
6180 return this;
6181 };
6182 /**
6183 * Disables input devices
6184 * @ko 입력 장치를 사용할 수 없게 한다.
6185 * @method eg.Axes.PanInput#disable
6186 * @return {eg.Axes.PanInput} An instance of a module itself <ko>모듈 자신의 인스턴스</ko>
6187 */
6188
6189
6190 __proto.disable = function () {
6191 this.hammer && (this.hammer.get("pan").options.enable = false);
6192 return this;
6193 };
6194 /**
6195 * Returns whether to use an input device
6196 * @ko 입력 장치를 사용 여부를 반환한다.
6197 * @method eg.Axes.PanInput#isEnable
6198 * @return {Boolean} Whether to use an input device <ko>입력장치 사용여부</ko>
6199 */
6200
6201
6202 __proto.isEnable = function () {
6203 return !!(this.hammer && this.hammer.get("pan").options.enable);
6204 };
6205
6206 __proto.removeRecognizer = function () {
6207 if (this.hammer && this.panRecognizer) {
6208 this.hammer.remove(this.panRecognizer);
6209 this.panRecognizer = null;
6210 }
6211 };
6212
6213 __proto.onHammerInput = function (event) {
6214 if (this.isEnable()) {
6215 if (event.isFirst) {
6216 this.panFlag = false;
6217
6218 if (event.srcEvent.cancelable !== false) {
6219 var edgeThreshold = this.options.iOSEdgeSwipeThreshold;
6220 this.observer.hold(this, event);
6221 this.isRightEdge = IS_IOS_SAFARI && event.center.x > window.innerWidth - edgeThreshold;
6222 this.panFlag = true;
6223 }
6224 } else if (event.isFinal) {
6225 this.onPanend(event);
6226 }
6227 }
6228 };
6229
6230 __proto.onPanmove = function (event) {
6231 var _this = this;
6232
6233 if (!this.panFlag) {
6234 return;
6235 }
6236
6237 var userDirection = getDirectionByAngle(event.angle, this.options.thresholdAngle); // not support offset properties in Hammerjs - start
6238
6239 var prevInput = this.hammer.session.prevInput;
6240
6241 if (prevInput && IS_IOS_SAFARI) {
6242 var swipeLeftToRight = event.center.x < 0;
6243
6244 if (swipeLeftToRight) {
6245 // iOS swipe left => right
6246 this.onPanend(__assign$1({}, prevInput, {
6247 velocityX: 0,
6248 velocityY: 0,
6249 offsetX: 0,
6250 offsetY: 0
6251 }));
6252 return;
6253 } else if (this.isRightEdge) {
6254 clearTimeout(this.rightEdgeTimer); // - is right to left
6255
6256 var edgeThreshold = this.options.iOSEdgeSwipeThreshold;
6257 var swipeRightToLeft = event.deltaX < -edgeThreshold;
6258
6259 if (swipeRightToLeft) {
6260 this.isRightEdge = false;
6261 } else {
6262 // iOS swipe right => left
6263 this.rightEdgeTimer = window.setTimeout(function () {
6264 _this.onPanend(__assign$1({}, prevInput, {
6265 velocityX: 0,
6266 velocityY: 0,
6267 offsetX: 0,
6268 offsetY: 0
6269 }));
6270 }, 100);
6271 }
6272 }
6273 }
6274 /* eslint-disable no-param-reassign */
6275
6276
6277 if (prevInput) {
6278 event.offsetX = event.deltaX - prevInput.deltaX;
6279 event.offsetY = event.deltaY - prevInput.deltaY;
6280 } else {
6281 event.offsetX = 0;
6282 event.offsetY = 0;
6283 }
6284
6285 var offset = this.getOffset([event.offsetX, event.offsetY], [useDirection(DIRECTION_HORIZONTAL, this._direction, userDirection), useDirection(DIRECTION_VERTICAL, this._direction, userDirection)]);
6286 var prevent = offset.some(function (v) {
6287 return v !== 0;
6288 });
6289
6290 if (prevent) {
6291 var srcEvent = event.srcEvent;
6292
6293 if (srcEvent.cancelable !== false) {
6294 srcEvent.preventDefault();
6295 }
6296
6297 srcEvent.stopPropagation();
6298 }
6299
6300 event.preventSystemEvent = prevent;
6301 prevent && this.observer.change(this, event, toAxis(this.axes, offset));
6302 };
6303
6304 __proto.onPanend = function (event) {
6305 if (!this.panFlag) {
6306 return;
6307 }
6308
6309 clearTimeout(this.rightEdgeTimer);
6310 this.panFlag = false;
6311 var offset = this.getOffset([Math.abs(event.velocityX) * (event.deltaX < 0 ? -1 : 1), Math.abs(event.velocityY) * (event.deltaY < 0 ? -1 : 1)], [useDirection(DIRECTION_HORIZONTAL, this._direction), useDirection(DIRECTION_VERTICAL, this._direction)]);
6312 offset = getNextOffset(offset, this.observer.options.deceleration);
6313 this.observer.release(this, event, toAxis(this.axes, offset));
6314 };
6315
6316 __proto.attachEvent = function (observer) {
6317 this.observer = observer;
6318 this.hammer.on("hammer.input", this.onHammerInput).on("panstart panmove", this.onPanmove);
6319 };
6320
6321 __proto.dettachEvent = function () {
6322 this.hammer.off("hammer.input", this.onHammerInput).off("panstart panmove", this.onPanmove);
6323 this.observer = null;
6324 };
6325
6326 __proto.getOffset = function (properties, direction) {
6327 var offset = [0, 0];
6328 var scale = this.options.scale;
6329
6330 if (direction[0]) {
6331 offset[0] = properties[0] * scale[0];
6332 }
6333
6334 if (direction[1]) {
6335 offset[1] = properties[1] * scale[1];
6336 }
6337
6338 return offset;
6339 };
6340
6341 return PanInput;
6342 }();
6343
6344 /**
6345 * Copyright (c) 2015 NAVER Corp.
6346 * egjs projects are licensed under the MIT license
6347 */
6348 var MOVE_TYPE = {
6349 SNAP: "snap",
6350 FREE_SCROLL: "freeScroll"
6351 };
6352 var DEFAULT_MOVE_TYPE_OPTIONS = {
6353 snap: {
6354 type: "snap",
6355 count: 1
6356 },
6357 freeScroll: {
6358 type: "freeScroll"
6359 }
6360 };
6361 var isBrowser = typeof document !== "undefined";
6362 /**
6363 * Default options for creating Flicking.
6364 * @ko 플리킹을 만들 때 사용하는 기본 옵션들
6365 * @private
6366 * @memberof eg.Flicking
6367 */
6368
6369 var DEFAULT_OPTIONS = {
6370 classPrefix: "eg-flick",
6371 deceleration: 0.0075,
6372 horizontal: true,
6373 circular: false,
6374 infinite: false,
6375 infiniteThreshold: 0,
6376 lastIndex: Infinity,
6377 threshold: 40,
6378 duration: 100,
6379 panelEffect: function (x) {
6380 return 1 - Math.pow(1 - x, 3);
6381 },
6382 defaultIndex: 0,
6383 inputType: ["touch", "mouse"],
6384 thresholdAngle: 45,
6385 bounce: 10,
6386 autoResize: false,
6387 adaptive: false,
6388 zIndex: 2000,
6389 bound: false,
6390 overflow: false,
6391 hanger: "50%",
6392 anchor: "50%",
6393 gap: 0,
6394 moveType: DEFAULT_MOVE_TYPE_OPTIONS.snap,
6395 useOffset: false,
6396 isEqualSize: false,
6397 isConstantSize: false,
6398 renderOnlyVisible: false,
6399 renderExternal: false,
6400 resizeOnContentsReady: false,
6401 iOSEdgeSwipeThreshold: 30,
6402 collectStatistics: true
6403 };
6404 var DEFAULT_VIEWPORT_CSS = {
6405 position: "relative",
6406 zIndex: DEFAULT_OPTIONS.zIndex,
6407 overflow: "hidden"
6408 };
6409 var DEFAULT_CAMERA_CSS = {
6410 width: "100%",
6411 height: "100%",
6412 willChange: "transform"
6413 };
6414 var DEFAULT_PANEL_CSS = {
6415 position: "absolute"
6416 };
6417 var EVENTS = {
6418 HOLD_START: "holdStart",
6419 HOLD_END: "holdEnd",
6420 MOVE_START: "moveStart",
6421 MOVE: "move",
6422 MOVE_END: "moveEnd",
6423 CHANGE: "change",
6424 RESTORE: "restore",
6425 SELECT: "select",
6426 NEED_PANEL: "needPanel",
6427 VISIBLE_CHANGE: "visibleChange",
6428 CONTENT_ERROR: "contentError"
6429 };
6430 var AXES_EVENTS = {
6431 HOLD: "hold",
6432 CHANGE: "change",
6433 RELEASE: "release",
6434 ANIMATION_END: "animationEnd",
6435 FINISH: "finish"
6436 };
6437 var STATE_TYPE = {
6438 IDLE: 0,
6439 HOLDING: 1,
6440 DRAGGING: 2,
6441 ANIMATING: 3,
6442 DISABLED: 4
6443 };
6444 var DIRECTION = {
6445 PREV: "PREV",
6446 NEXT: "NEXT"
6447 };
6448 var FLICKING_METHODS = {
6449 prev: true,
6450 next: true,
6451 moveTo: true,
6452 getIndex: true,
6453 getAllPanels: true,
6454 getCurrentPanel: true,
6455 getElement: true,
6456 getSize: true,
6457 getPanel: true,
6458 getPanelCount: true,
6459 getStatus: true,
6460 getVisiblePanels: true,
6461 enableInput: true,
6462 disableInput: true,
6463 destroy: true,
6464 resize: true,
6465 setStatus: true,
6466 isPlaying: true
6467 }; // Check whether browser supports transform: translate3d
6468 // https://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
6469
6470 var checkTranslateSupport = function () {
6471 var transforms = {
6472 webkitTransform: "-webkit-transform",
6473 msTransform: "-ms-transform",
6474 MozTransform: "-moz-transform",
6475 OTransform: "-o-transform",
6476 transform: "transform"
6477 };
6478
6479 if (!isBrowser) {
6480 return {
6481 name: transforms.transform,
6482 has3d: true
6483 };
6484 }
6485
6486 var supportedStyle = document.documentElement.style;
6487 var transformName = "";
6488
6489 for (var prefixedTransform in transforms) {
6490 if (prefixedTransform in supportedStyle) {
6491 transformName = prefixedTransform;
6492 }
6493 }
6494
6495 if (!transformName) {
6496 throw new Error("Browser doesn't support CSS3 2D Transforms.");
6497 }
6498
6499 var el = document.createElement("div");
6500 document.documentElement.insertBefore(el, null);
6501 el.style[transformName] = "translate3d(1px, 1px, 1px)";
6502 var styleVal = window.getComputedStyle(el).getPropertyValue(transforms[transformName]);
6503 el.parentElement.removeChild(el);
6504 var transformInfo = {
6505 name: transformName,
6506 has3d: styleVal.length > 0 && styleVal !== "none"
6507 };
6508
6509 checkTranslateSupport = function () {
6510 return transformInfo;
6511 };
6512
6513 return transformInfo;
6514 };
6515 var TRANSFORM$1 = checkTranslateSupport();
6516
6517 /**
6518 * Copyright (c) 2015 NAVER Corp.
6519 * egjs projects are licensed under the MIT license
6520 */
6521 function merge(target) {
6522 var srcs = [];
6523
6524 for (var _i = 1; _i < arguments.length; _i++) {
6525 srcs[_i - 1] = arguments[_i];
6526 }
6527
6528 srcs.forEach(function (source) {
6529 Object.keys(source).forEach(function (key) {
6530 var value = source[key];
6531 target[key] = value;
6532 });
6533 });
6534 return target;
6535 }
6536 function parseElement(element) {
6537 if (!Array.isArray(element)) {
6538 element = [element];
6539 }
6540
6541 var elements = [];
6542 element.forEach(function (el) {
6543 if (isString(el)) {
6544 var tempDiv = document.createElement("div");
6545 tempDiv.innerHTML = el;
6546 elements.push.apply(elements, toArray$3(tempDiv.children));
6547
6548 while (tempDiv.firstChild) {
6549 tempDiv.removeChild(tempDiv.firstChild);
6550 }
6551 } else {
6552 elements.push(el);
6553 }
6554 });
6555 return elements;
6556 }
6557 function isString(value) {
6558 return typeof value === "string";
6559 } // Get class list of element as string array
6560
6561 function addClass(element, className) {
6562 if (element.classList) {
6563 element.classList.add(className);
6564 } else {
6565 if (!hasClass(element, className)) {
6566 element.className = (element.className + " " + className).replace(/\s{2,}/g, " ");
6567 }
6568 }
6569 }
6570 function hasClass(element, className) {
6571 if (element.classList) {
6572 return element.classList.contains(className);
6573 } else {
6574 return element.className.split(" ").indexOf(className) >= 0;
6575 }
6576 }
6577 function applyCSS(element, cssObj) {
6578 Object.keys(cssObj).forEach(function (property) {
6579 element.style[property] = cssObj[property];
6580 });
6581 }
6582 function clamp(val, min, max) {
6583 return Math.max(Math.min(val, max), min);
6584 } // Min: inclusive, Max: exclusive
6585
6586 function isBetween(val, min, max) {
6587 return val >= min && val <= max;
6588 }
6589 function toArray$3(iterable) {
6590 return [].slice.call(iterable);
6591 }
6592 function isArray(arr) {
6593 return arr && arr.constructor === Array;
6594 }
6595 function parseArithmeticExpression(cssValue, base, defaultVal) {
6596 // Set base / 2 to default value, if it's undefined
6597 var defaultValue = defaultVal != null ? defaultVal : base / 2;
6598 var cssRegex = /(?:(\+|\-)\s*)?(\d+(?:\.\d+)?(%|px)?)/g;
6599
6600 if (typeof cssValue === "number") {
6601 return clamp(cssValue, 0, base);
6602 }
6603
6604 var idx = 0;
6605 var calculatedValue = 0;
6606 var matchResult = cssRegex.exec(cssValue);
6607
6608 while (matchResult != null) {
6609 var sign = matchResult[1];
6610 var value = matchResult[2];
6611 var unit = matchResult[3];
6612 var parsedValue = parseFloat(value);
6613
6614 if (idx <= 0) {
6615 sign = sign || "+";
6616 } // Return default value for values not in good form
6617
6618
6619 if (!sign) {
6620 return defaultValue;
6621 }
6622
6623 if (unit === "%") {
6624 parsedValue = parsedValue / 100 * base;
6625 }
6626
6627 calculatedValue += sign === "+" ? parsedValue : -parsedValue; // Match next occurrence
6628
6629 ++idx;
6630 matchResult = cssRegex.exec(cssValue);
6631 } // None-matched
6632
6633
6634 if (idx === 0) {
6635 return defaultValue;
6636 } // Clamp between 0 ~ base
6637
6638
6639 return clamp(calculatedValue, 0, base);
6640 }
6641 function getProgress(pos, range) {
6642 // start, anchor, end
6643 // -1 , 0 , 1
6644 var min = range[0],
6645 center = range[1],
6646 max = range[2];
6647
6648 if (pos > center && max - center) {
6649 // 0 ~ 1
6650 return (pos - center) / (max - center);
6651 } else if (pos < center && center - min) {
6652 // -1 ~ 0
6653 return (pos - center) / (center - min);
6654 } else if (pos !== center && max - min) {
6655 return (pos - min) / (max - min);
6656 }
6657
6658 return 0;
6659 }
6660 function findIndex(iterable, callback) {
6661 for (var i = 0; i < iterable.length; i += 1) {
6662 var element = iterable[i];
6663
6664 if (element && callback(element)) {
6665 return i;
6666 }
6667 }
6668
6669 return -1;
6670 } // return [0, 1, ...., max - 1]
6671
6672 function counter(max) {
6673 var counterArray = [];
6674
6675 for (var i = 0; i < max; i += 1) {
6676 counterArray[i] = i;
6677 }
6678
6679 return counterArray;
6680 } // Circulate number between range [min, max]
6681
6682 /*
6683 * "indexed" means min and max is not same, so if it's true "min - 1" should be max
6684 * While if it's false, "min - 1" should be "max - 1"
6685 * use `indexed: true` when it should be used for circulating integers like index
6686 * or `indexed: false` when it should be used for something like positions.
6687 */
6688
6689 function circulate(value, min, max, indexed) {
6690 var size = indexed ? max - min + 1 : max - min;
6691
6692 if (value < min) {
6693 var offset = indexed ? (min - value - 1) % size : (min - value) % size;
6694 value = max - offset;
6695 } else if (value > max) {
6696 var offset = indexed ? (value - max - 1) % size : (value - max) % size;
6697 value = min + offset;
6698 }
6699
6700 return value;
6701 }
6702 function restoreStyle(element, originalStyle) {
6703 originalStyle.className ? element.setAttribute("class", originalStyle.className) : element.removeAttribute("class");
6704 originalStyle.style ? element.setAttribute("style", originalStyle.style) : element.removeAttribute("style");
6705 }
6706 /**
6707 * Decorator that makes the method of flicking available in the framework.
6708 * @ko 프레임워크에서 플리킹의 메소드를 사용할 수 있게 하는 데코레이터.
6709 * @memberof eg.Flicking
6710 * @private
6711 * @example
6712 * ```js
6713 * import Flicking, { withFlickingMethods } from "@egjs/flicking";
6714 *
6715 * class Flicking extends React.Component<Partial<FlickingProps & FlickingOptions>> {
6716 * &#64;withFlickingMethods
6717 * private flicking: Flicking;
6718 * }
6719 * ```
6720 */
6721
6722 function withFlickingMethods(prototype, flickingName) {
6723 Object.keys(FLICKING_METHODS).forEach(function (name) {
6724 if (prototype[name]) {
6725 return;
6726 }
6727
6728 prototype[name] = function () {
6729 var _a;
6730
6731 var args = [];
6732
6733 for (var _i = 0; _i < arguments.length; _i++) {
6734 args[_i] = arguments[_i];
6735 }
6736
6737 var result = (_a = this[flickingName])[name].apply(_a, args); // fix `this` type to return your own `flicking` instance to the instance using the decorator.
6738
6739
6740 if (result === this[flickingName]) {
6741 return this;
6742 } else {
6743 return result;
6744 }
6745 };
6746 });
6747 }
6748 function getBbox(element, useOffset) {
6749 var bbox;
6750
6751 if (useOffset) {
6752 bbox = {
6753 x: 0,
6754 y: 0,
6755 width: element.offsetWidth,
6756 height: element.offsetHeight
6757 };
6758 } else {
6759 var clientRect = element.getBoundingClientRect();
6760 bbox = {
6761 x: clientRect.left,
6762 y: clientRect.top,
6763 width: clientRect.width,
6764 height: clientRect.height
6765 };
6766 }
6767
6768 return bbox;
6769 }
6770
6771 /**
6772 * Copyright (c) 2015 NAVER Corp.
6773 * egjs projects are licensed under the MIT license
6774 */
6775
6776 var Panel =
6777 /*#__PURE__*/
6778 function () {
6779 function Panel(element, index, viewport) {
6780 this.viewport = viewport;
6781 this.prevSibling = null;
6782 this.nextSibling = null;
6783 this.clonedPanels = [];
6784 this.state = {
6785 index: index,
6786 position: 0,
6787 relativeAnchorPosition: 0,
6788 size: 0,
6789 isClone: false,
6790 isVirtual: false,
6791 cloneIndex: -1,
6792 originalStyle: {
6793 className: "",
6794 style: ""
6795 },
6796 cachedBbox: null
6797 };
6798 this.setElement(element);
6799 }
6800
6801 var __proto = Panel.prototype;
6802
6803 __proto.resize = function (givenBbox) {
6804 var state = this.state;
6805 var options = this.viewport.options;
6806 var bbox = givenBbox ? givenBbox : this.getBbox();
6807 this.state.cachedBbox = bbox;
6808 var prevSize = state.size;
6809 state.size = options.horizontal ? bbox.width : bbox.height;
6810
6811 if (prevSize !== state.size) {
6812 state.relativeAnchorPosition = parseArithmeticExpression(options.anchor, state.size);
6813 }
6814
6815 if (!state.isClone) {
6816 this.clonedPanels.forEach(function (panel) {
6817 var cloneState = panel.state;
6818 cloneState.size = state.size;
6819 cloneState.cachedBbox = state.cachedBbox;
6820 cloneState.relativeAnchorPosition = state.relativeAnchorPosition;
6821 });
6822 }
6823 };
6824
6825 __proto.unCacheBbox = function () {
6826 this.state.cachedBbox = null;
6827 };
6828
6829 __proto.getProgress = function () {
6830 var viewport = this.viewport;
6831 var options = viewport.options;
6832 var panelCount = viewport.panelManager.getPanelCount();
6833 var scrollAreaSize = viewport.getScrollAreaSize();
6834 var relativeIndex = (options.circular ? Math.floor(this.getPosition() / scrollAreaSize) * panelCount : 0) + this.getIndex();
6835 var progress = relativeIndex - viewport.getCurrentProgress();
6836 return progress;
6837 };
6838
6839 __proto.getOutsetProgress = function () {
6840 var viewport = this.viewport;
6841 var outsetRange = [-this.getSize(), viewport.getRelativeHangerPosition() - this.getRelativeAnchorPosition(), viewport.getSize()];
6842 var relativePanelPosition = this.getPosition() - viewport.getCameraPosition();
6843 var outsetProgress = getProgress(relativePanelPosition, outsetRange);
6844 return outsetProgress;
6845 };
6846
6847 __proto.getVisibleRatio = function () {
6848 var viewport = this.viewport;
6849 var panelSize = this.getSize();
6850 var relativePanelPosition = this.getPosition() - viewport.getCameraPosition();
6851 var rightRelativePanelPosition = relativePanelPosition + panelSize;
6852 var visibleSize = Math.min(viewport.getSize(), rightRelativePanelPosition) - Math.max(relativePanelPosition, 0);
6853 var visibleRatio = visibleSize >= 0 ? visibleSize / panelSize : 0;
6854 return visibleRatio;
6855 };
6856
6857 __proto.focus = function (duration) {
6858 var viewport = this.viewport;
6859 var currentPanel = viewport.getCurrentPanel();
6860 var hangerPosition = viewport.getHangerPosition();
6861 var anchorPosition = this.getAnchorPosition();
6862
6863 if (hangerPosition === anchorPosition || !currentPanel) {
6864 return;
6865 }
6866
6867 var currentPosition = currentPanel.getPosition();
6868 var eventType = currentPosition === this.getPosition() ? "" : EVENTS.CHANGE;
6869 viewport.moveTo(this, viewport.findEstimatedPosition(this), eventType, null, duration);
6870 };
6871
6872 __proto.update = function (updateFunction, shouldResize) {
6873 if (updateFunction === void 0) {
6874 updateFunction = null;
6875 }
6876
6877 if (shouldResize === void 0) {
6878 shouldResize = true;
6879 }
6880
6881 var identicalPanels = this.getIdenticalPanels();
6882
6883 if (updateFunction) {
6884 identicalPanels.forEach(function (eachPanel) {
6885 updateFunction(eachPanel.getElement());
6886 });
6887 }
6888
6889 if (shouldResize) {
6890 identicalPanels.forEach(function (eachPanel) {
6891 eachPanel.unCacheBbox();
6892 });
6893 this.viewport.addVisiblePanel(this);
6894 this.viewport.resize();
6895 }
6896 };
6897
6898 __proto.prev = function () {
6899 var viewport = this.viewport;
6900 var options = viewport.options;
6901 var prevSibling = this.prevSibling;
6902
6903 if (!prevSibling) {
6904 return null;
6905 }
6906
6907 var currentIndex = this.getIndex();
6908 var currentPosition = this.getPosition();
6909 var prevPanelIndex = prevSibling.getIndex();
6910 var prevPanelPosition = prevSibling.getPosition();
6911 var prevPanelSize = prevSibling.getSize();
6912 var hasEmptyPanelBetween = currentIndex - prevPanelIndex > 1;
6913 var notYetMinPanel = options.infinite && currentIndex > 0 && prevPanelIndex > currentIndex;
6914
6915 if (hasEmptyPanelBetween || notYetMinPanel) {
6916 // Empty panel exists between
6917 return null;
6918 }
6919
6920 var newPosition = currentPosition - prevPanelSize - options.gap;
6921 var prevPanel = prevSibling;
6922
6923 if (prevPanelPosition !== newPosition) {
6924 prevPanel = prevSibling.clone(prevSibling.getCloneIndex(), true);
6925 prevPanel.setPosition(newPosition);
6926 }
6927
6928 return prevPanel;
6929 };
6930
6931 __proto.next = function () {
6932 var viewport = this.viewport;
6933 var options = viewport.options;
6934 var nextSibling = this.nextSibling;
6935 var lastIndex = viewport.panelManager.getLastIndex();
6936
6937 if (!nextSibling) {
6938 return null;
6939 }
6940
6941 var currentIndex = this.getIndex();
6942 var currentPosition = this.getPosition();
6943 var nextPanelIndex = nextSibling.getIndex();
6944 var nextPanelPosition = nextSibling.getPosition();
6945 var hasEmptyPanelBetween = nextPanelIndex - currentIndex > 1;
6946 var notYetMaxPanel = options.infinite && currentIndex < lastIndex && nextPanelIndex < currentIndex;
6947
6948 if (hasEmptyPanelBetween || notYetMaxPanel) {
6949 return null;
6950 }
6951
6952 var newPosition = currentPosition + this.getSize() + options.gap;
6953 var nextPanel = nextSibling;
6954
6955 if (nextPanelPosition !== newPosition) {
6956 nextPanel = nextSibling.clone(nextSibling.getCloneIndex(), true);
6957 nextPanel.setPosition(newPosition);
6958 }
6959
6960 return nextPanel;
6961 };
6962
6963 __proto.insertBefore = function (element) {
6964 var viewport = this.viewport;
6965 var parsedElements = parseElement(element);
6966 var firstPanel = viewport.panelManager.firstPanel();
6967 var prevSibling = this.prevSibling; // Finding correct inserting index
6968 // While it should insert removing empty spaces,
6969 // It also should have to be bigger than prevSibling' s index
6970
6971 var targetIndex = prevSibling && firstPanel.getIndex() !== this.getIndex() ? Math.max(prevSibling.getIndex() + 1, this.getIndex() - parsedElements.length) : Math.max(this.getIndex() - parsedElements.length, 0);
6972 return viewport.insert(targetIndex, parsedElements);
6973 };
6974
6975 __proto.insertAfter = function (element) {
6976 return this.viewport.insert(this.getIndex() + 1, element);
6977 };
6978
6979 __proto.remove = function () {
6980 this.viewport.remove(this.getIndex());
6981 return this;
6982 };
6983
6984 __proto.destroy = function (option) {
6985 if (!option.preserveUI) {
6986 var originalStyle = this.state.originalStyle;
6987 restoreStyle(this.element, originalStyle);
6988 } // release resources
6989
6990
6991 for (var x in this) {
6992 this[x] = null;
6993 }
6994 };
6995
6996 __proto.getElement = function () {
6997 return this.element;
6998 };
6999
7000 __proto.getAnchorPosition = function () {
7001 return this.state.position + this.state.relativeAnchorPosition;
7002 };
7003
7004 __proto.getRelativeAnchorPosition = function () {
7005 return this.state.relativeAnchorPosition;
7006 };
7007
7008 __proto.getIndex = function () {
7009 return this.state.index;
7010 };
7011
7012 __proto.getPosition = function () {
7013 return this.state.position;
7014 };
7015
7016 __proto.getSize = function () {
7017 return this.state.size;
7018 };
7019
7020 __proto.getBbox = function () {
7021 var state = this.state;
7022 var viewport = this.viewport;
7023 var element = this.element;
7024 var options = viewport.options;
7025
7026 if (!element) {
7027 state.cachedBbox = {
7028 x: 0,
7029 y: 0,
7030 width: 0,
7031 height: 0
7032 };
7033 } else if (!state.cachedBbox) {
7034 var wasVisible = Boolean(element.parentNode);
7035 var cameraElement = viewport.getCameraElement();
7036
7037 if (!wasVisible) {
7038 cameraElement.appendChild(element);
7039 viewport.addVisiblePanel(this);
7040 }
7041
7042 state.cachedBbox = getBbox(element, options.useOffset);
7043
7044 if (!wasVisible && viewport.options.renderExternal) {
7045 cameraElement.removeChild(element);
7046 }
7047 }
7048
7049 return state.cachedBbox;
7050 };
7051
7052 __proto.isClone = function () {
7053 return this.state.isClone;
7054 };
7055
7056 __proto.getOverlappedClass = function (classes) {
7057 var element = this.element;
7058
7059 for (var _i = 0, classes_1 = classes; _i < classes_1.length; _i++) {
7060 var className = classes_1[_i];
7061
7062 if (hasClass(element, className)) {
7063 return className;
7064 }
7065 }
7066 };
7067
7068 __proto.getCloneIndex = function () {
7069 return this.state.cloneIndex;
7070 };
7071
7072 __proto.getClonedPanels = function () {
7073 var state = this.state;
7074 return state.isClone ? this.original.getClonedPanels() : this.clonedPanels;
7075 };
7076
7077 __proto.getIdenticalPanels = function () {
7078 var state = this.state;
7079 return state.isClone ? this.original.getIdenticalPanels() : __spreadArrays([this], this.clonedPanels);
7080 };
7081
7082 __proto.getOriginalPanel = function () {
7083 return this.state.isClone ? this.original : this;
7084 };
7085
7086 __proto.setIndex = function (index) {
7087 var state = this.state;
7088 state.index = index;
7089 this.clonedPanels.forEach(function (panel) {
7090 return panel.state.index = index;
7091 });
7092 };
7093
7094 __proto.setPosition = function (pos) {
7095 this.state.position = pos;
7096 return this;
7097 };
7098
7099 __proto.setPositionCSS = function (offset) {
7100 if (offset === void 0) {
7101 offset = 0;
7102 }
7103
7104 if (!this.element) {
7105 return;
7106 }
7107
7108 var state = this.state;
7109 var pos = state.position;
7110 var options = this.viewport.options;
7111 var elementStyle = this.element.style;
7112 var currentElementStyle = options.horizontal ? elementStyle.left : elementStyle.top;
7113 var styleToApply = pos - offset + "px";
7114
7115 if (!state.isVirtual && currentElementStyle !== styleToApply) {
7116 options.horizontal ? elementStyle.left = styleToApply : elementStyle.top = styleToApply;
7117 }
7118 };
7119
7120 __proto.clone = function (cloneIndex, isVirtual, element) {
7121 if (isVirtual === void 0) {
7122 isVirtual = false;
7123 }
7124
7125 var state = this.state;
7126 var viewport = this.viewport;
7127 var cloneElement = element;
7128
7129 if (!cloneElement && this.element) {
7130 cloneElement = isVirtual ? this.element : this.element.cloneNode(true);
7131 }
7132
7133 var clonedPanel = new Panel(cloneElement, state.index, viewport);
7134 var clonedState = clonedPanel.state;
7135 clonedPanel.original = state.isClone ? this.original : this;
7136 clonedState.isClone = true;
7137 clonedState.isVirtual = isVirtual;
7138 clonedState.cloneIndex = cloneIndex; // Inherit some state values
7139
7140 clonedState.size = state.size;
7141 clonedState.relativeAnchorPosition = state.relativeAnchorPosition;
7142 clonedState.originalStyle = state.originalStyle;
7143 clonedState.cachedBbox = state.cachedBbox;
7144
7145 if (!isVirtual) {
7146 this.clonedPanels.push(clonedPanel);
7147 } else {
7148 clonedPanel.prevSibling = this.prevSibling;
7149 clonedPanel.nextSibling = this.nextSibling;
7150 }
7151
7152 return clonedPanel;
7153 };
7154
7155 __proto.removeElement = function () {
7156 if (!this.viewport.options.renderExternal) {
7157 var element = this.element;
7158 element.parentNode && element.parentNode.removeChild(element);
7159 } // Do the same thing for clones
7160
7161
7162 if (!this.state.isClone) {
7163 this.removeClonedPanelsAfter(0);
7164 }
7165 };
7166
7167 __proto.removeClonedPanelsAfter = function (start) {
7168 var options = this.viewport.options;
7169 var removingPanels = this.clonedPanels.splice(start);
7170
7171 if (!options.renderExternal) {
7172 removingPanels.forEach(function (panel) {
7173 panel.removeElement();
7174 });
7175 }
7176 };
7177
7178 __proto.setElement = function (element) {
7179 if (!element) {
7180 return;
7181 }
7182
7183 var currentElement = this.element;
7184
7185 if (element !== currentElement) {
7186 var options = this.viewport.options;
7187
7188 if (currentElement) {
7189 if (options.horizontal) {
7190 element.style.left = currentElement.style.left;
7191 } else {
7192 element.style.top = currentElement.style.top;
7193 }
7194 } else {
7195 var originalStyle = this.state.originalStyle;
7196 originalStyle.className = element.getAttribute("class");
7197 originalStyle.style = element.getAttribute("style");
7198 }
7199
7200 this.element = element;
7201
7202 if (options.classPrefix) {
7203 addClass(element, options.classPrefix + "-panel");
7204 } // Update size info after applying panel css
7205
7206
7207 applyCSS(this.element, DEFAULT_PANEL_CSS);
7208 }
7209 };
7210
7211 return Panel;
7212 }();
7213
7214 /**
7215 * Copyright (c) 2015 NAVER Corp.
7216 * egjs projects are licensed under the MIT license
7217 */
7218
7219 var PanelManager =
7220 /*#__PURE__*/
7221 function () {
7222 function PanelManager(cameraElement, options) {
7223 this.cameraElement = cameraElement;
7224 this.panels = [];
7225 this.clones = [];
7226 this.range = {
7227 min: -1,
7228 max: -1
7229 };
7230 this.length = 0;
7231 this.cloneCount = 0;
7232 this.options = options;
7233 this.lastIndex = options.lastIndex;
7234 }
7235
7236 var __proto = PanelManager.prototype;
7237
7238 __proto.firstPanel = function () {
7239 return this.panels[this.range.min];
7240 };
7241
7242 __proto.lastPanel = function () {
7243 return this.panels[this.range.max];
7244 };
7245
7246 __proto.allPanels = function () {
7247 return __spreadArrays(this.panels, this.clones.reduce(function (allClones, clones) {
7248 return __spreadArrays(allClones, clones);
7249 }, []));
7250 };
7251
7252 __proto.originalPanels = function () {
7253 return this.panels;
7254 };
7255
7256 __proto.clonedPanels = function () {
7257 return this.clones;
7258 };
7259
7260 __proto.replacePanels = function (newPanels, newClones) {
7261 this.panels = newPanels;
7262 this.clones = newClones;
7263 this.range = {
7264 min: findIndex(newPanels, function (panel) {
7265 return Boolean(panel);
7266 }),
7267 max: newPanels.length - 1
7268 };
7269 this.length = newPanels.filter(function (panel) {
7270 return Boolean(panel);
7271 }).length;
7272 };
7273
7274 __proto.has = function (index) {
7275 return !!this.panels[index];
7276 };
7277
7278 __proto.get = function (index) {
7279 return this.panels[index];
7280 };
7281
7282 __proto.getPanelCount = function () {
7283 return this.length;
7284 };
7285
7286 __proto.getLastIndex = function () {
7287 return this.lastIndex;
7288 };
7289
7290 __proto.getRange = function () {
7291 return this.range;
7292 };
7293
7294 __proto.getCloneCount = function () {
7295 return this.cloneCount;
7296 };
7297
7298 __proto.setLastIndex = function (lastIndex) {
7299 this.lastIndex = lastIndex;
7300 var firstPanel = this.firstPanel();
7301 var lastPanel = this.lastPanel();
7302
7303 if (!firstPanel || !lastPanel) {
7304 return; // no meaning of updating range & length
7305 } // Remove panels above new last index
7306
7307
7308 var range = this.range;
7309
7310 if (lastPanel.getIndex() > lastIndex) {
7311 var removingPanels = this.panels.splice(lastIndex + 1);
7312 this.length -= removingPanels.length;
7313 var firstRemovedPanel = removingPanels.filter(function (panel) {
7314 return !!panel;
7315 })[0];
7316 var possibleLastPanel = firstRemovedPanel.prevSibling;
7317
7318 if (possibleLastPanel) {
7319 range.max = possibleLastPanel.getIndex();
7320 } else {
7321 range.min = -1;
7322 range.max = -1;
7323 }
7324
7325 if (this.shouldRender()) {
7326 removingPanels.forEach(function (panel) {
7327 return panel.removeElement();
7328 });
7329 }
7330 }
7331 };
7332
7333 __proto.setCloneCount = function (cloneCount) {
7334 this.cloneCount = cloneCount;
7335 }; // Insert at index
7336 // Returns pushed elements from index, inserting at 'empty' position doesn't push elements behind it
7337
7338
7339 __proto.insert = function (index, newPanels) {
7340 var panels = this.panels;
7341 var range = this.range;
7342 var isCircular = this.options.circular;
7343 var lastIndex = this.lastIndex; // Find first panel that index is greater than inserting index
7344
7345 var nextSibling = this.findFirstPanelFrom(index); // if it's null, element will be inserted at last position
7346 // https://developer.mozilla.org/ko/docs/Web/API/Node/insertBefore#Syntax
7347
7348 var firstPanel = this.firstPanel();
7349 var siblingElement = nextSibling ? nextSibling.getElement() : isCircular && firstPanel ? firstPanel.getClonedPanels()[0].getElement() : null; // Insert panels before sibling element
7350
7351 this.insertNewPanels(newPanels, siblingElement);
7352 var pushedIndex = newPanels.length; // Like when setting index 50 while visible panels are 0, 1, 2
7353
7354 if (index > range.max) {
7355 newPanels.forEach(function (panel, offset) {
7356 panels[index + offset] = panel;
7357 });
7358 } else {
7359 var panelsAfterIndex = panels.slice(index, index + newPanels.length); // Find empty from beginning
7360
7361 var emptyPanelCount = findIndex(panelsAfterIndex, function (panel) {
7362 return !!panel;
7363 });
7364
7365 if (emptyPanelCount < 0) {
7366 // All empty
7367 emptyPanelCount = panelsAfterIndex.length;
7368 }
7369
7370 pushedIndex = newPanels.length - emptyPanelCount; // Insert removing empty panels
7371
7372 panels.splice.apply(panels, __spreadArrays([index, emptyPanelCount], newPanels)); // Remove panels after last index
7373
7374 if (panels.length > lastIndex + 1) {
7375 var removedPanels = panels.splice(lastIndex + 1).filter(function (panel) {
7376 return Boolean(panel);
7377 });
7378 this.length -= removedPanels.length; // Find first
7379
7380 var newLastIndex = lastIndex - findIndex(this.panels.concat().reverse(), function (panel) {
7381 return !!panel;
7382 }); // Can be filled with empty after newLastIndex
7383
7384 this.panels.splice(newLastIndex + 1);
7385 this.range.max = newLastIndex;
7386
7387 if (this.shouldRender()) {
7388 removedPanels.forEach(function (panel) {
7389 return panel.removeElement();
7390 });
7391 }
7392 }
7393 } // Update index of previous panels
7394
7395
7396 if (pushedIndex > 0) {
7397 panels.slice(index + newPanels.length).forEach(function (panel) {
7398 panel.setIndex(panel.getIndex() + pushedIndex);
7399 });
7400 } // Update state
7401
7402
7403 this.length += newPanels.length;
7404 this.updateIndex(index);
7405
7406 if (isCircular) {
7407 this.addNewClones(index, newPanels, newPanels.length - pushedIndex, nextSibling);
7408 var clones = this.clones;
7409 var panelCount_1 = this.panels.length;
7410
7411 if (clones[0] && clones[0].length > lastIndex + 1) {
7412 clones.forEach(function (cloneSet) {
7413 cloneSet.splice(panelCount_1);
7414 });
7415 }
7416 }
7417
7418 return pushedIndex;
7419 };
7420
7421 __proto.replace = function (index, newPanels) {
7422 var panels = this.panels;
7423 var range = this.range;
7424 var options = this.options;
7425 var isCircular = options.circular; // Find first panel that index is greater than inserting index
7426
7427 var nextSibling = this.findFirstPanelFrom(index + newPanels.length); // if it's null, element will be inserted at last position
7428 // https://developer.mozilla.org/ko/docs/Web/API/Node/insertBefore#Syntax
7429
7430 var firstPanel = this.firstPanel();
7431 var siblingElement = nextSibling ? nextSibling.getElement() : isCircular && firstPanel ? firstPanel.getClonedPanels()[0].getElement() : null; // Insert panels before sibling element
7432
7433 this.insertNewPanels(newPanels, siblingElement);
7434
7435 if (index > range.max) {
7436 // Temporarily insert null at index to use splice()
7437 panels[index] = null;
7438 }
7439
7440 var replacedPanels = panels.splice.apply(panels, __spreadArrays([index, newPanels.length], newPanels));
7441 var wasNonEmptyCount = replacedPanels.filter(function (panel) {
7442 return Boolean(panel);
7443 }).length; // Suppose inserting [1, 2, 3] at 0 position when there were [empty, 1]
7444 // So length should be increased by 3(inserting panels) - 1(non-empty panels)
7445
7446 this.length += newPanels.length - wasNonEmptyCount;
7447 this.updateIndex(index);
7448
7449 if (isCircular) {
7450 this.addNewClones(index, newPanels, newPanels.length, nextSibling);
7451 }
7452
7453 if (this.shouldRender()) {
7454 replacedPanels.forEach(function (panel) {
7455 return panel && panel.removeElement();
7456 });
7457 }
7458
7459 return replacedPanels;
7460 };
7461
7462 __proto.remove = function (index, deleteCount) {
7463 if (deleteCount === void 0) {
7464 deleteCount = 1;
7465 }
7466
7467 var isCircular = this.options.circular;
7468 var panels = this.panels;
7469 var clones = this.clones; // Delete count should be equal or larger than 0
7470
7471 deleteCount = Math.max(deleteCount, 0);
7472 var deletedPanels = panels.splice(index, deleteCount).filter(function (panel) {
7473 return !!panel;
7474 });
7475
7476 if (this.shouldRender()) {
7477 deletedPanels.forEach(function (panel) {
7478 return panel.removeElement();
7479 });
7480 }
7481
7482 if (isCircular) {
7483 clones.forEach(function (cloneSet) {
7484 cloneSet.splice(index, deleteCount);
7485 });
7486 } // Update indexes
7487
7488
7489 panels.slice(index).forEach(function (panel) {
7490 panel.setIndex(panel.getIndex() - deleteCount);
7491 }); // Check last panel is empty
7492
7493 var lastIndex = panels.length - 1;
7494
7495 if (!panels[lastIndex]) {
7496 var reversedPanels = panels.concat().reverse();
7497 var nonEmptyIndexFromLast = findIndex(reversedPanels, function (panel) {
7498 return !!panel;
7499 });
7500 lastIndex = nonEmptyIndexFromLast < 0 ? -1 // All empty
7501 : lastIndex - nonEmptyIndexFromLast; // Remove all empty panels from last
7502
7503 panels.splice(lastIndex + 1);
7504
7505 if (isCircular) {
7506 clones.forEach(function (cloneSet) {
7507 cloneSet.splice(lastIndex + 1);
7508 });
7509 }
7510 } // Update range & length
7511
7512
7513 this.range = {
7514 min: findIndex(panels, function (panel) {
7515 return !!panel;
7516 }),
7517 max: lastIndex
7518 };
7519 this.length -= deletedPanels.length;
7520
7521 if (this.length <= 0) {
7522 // Reset clones
7523 this.clones = [];
7524 this.cloneCount = 0;
7525 }
7526
7527 return deletedPanels;
7528 };
7529
7530 __proto.chainAllPanels = function () {
7531 var allPanels = this.allPanels().filter(function (panel) {
7532 return !!panel;
7533 });
7534 var allPanelsCount = allPanels.length;
7535
7536 if (allPanelsCount <= 1) {
7537 return;
7538 }
7539
7540 allPanels.slice(1, allPanels.length - 1).forEach(function (panel, idx) {
7541 var prevPanel = allPanels[idx];
7542 var nextPanel = allPanels[idx + 2];
7543 panel.prevSibling = prevPanel;
7544 panel.nextSibling = nextPanel;
7545 });
7546 var firstPanel = allPanels[0];
7547 var lastPanel = allPanels[allPanelsCount - 1];
7548 firstPanel.prevSibling = null;
7549 firstPanel.nextSibling = allPanels[1];
7550 lastPanel.prevSibling = allPanels[allPanelsCount - 2];
7551 lastPanel.nextSibling = null;
7552
7553 if (this.options.circular) {
7554 firstPanel.prevSibling = lastPanel;
7555 lastPanel.nextSibling = firstPanel;
7556 }
7557 };
7558
7559 __proto.insertClones = function (cloneIndex, index, clonedPanels, deleteCount) {
7560 if (deleteCount === void 0) {
7561 deleteCount = 0;
7562 }
7563
7564 var clones = this.clones;
7565 var lastIndex = this.lastIndex;
7566
7567 if (!clones[cloneIndex]) {
7568 var newClones_1 = [];
7569 clonedPanels.forEach(function (panel, offset) {
7570 newClones_1[index + offset] = panel;
7571 });
7572 clones[cloneIndex] = newClones_1;
7573 } else {
7574 var insertTarget_1 = clones[cloneIndex];
7575
7576 if (index >= insertTarget_1.length) {
7577 clonedPanels.forEach(function (panel, offset) {
7578 insertTarget_1[index + offset] = panel;
7579 });
7580 } else {
7581 insertTarget_1.splice.apply(insertTarget_1, __spreadArrays([index, deleteCount], clonedPanels)); // Remove panels after last index
7582
7583 if (clonedPanels.length > lastIndex + 1) {
7584 clonedPanels.splice(lastIndex + 1);
7585 }
7586 }
7587 }
7588 }; // clones are operating in set
7589
7590
7591 __proto.removeClonesAfter = function (cloneIndex) {
7592 var panels = this.panels;
7593 panels.forEach(function (panel) {
7594 panel.removeClonedPanelsAfter(cloneIndex);
7595 });
7596 this.clones.splice(cloneIndex);
7597 };
7598
7599 __proto.findPanelOf = function (element) {
7600 var allPanels = this.allPanels();
7601
7602 for (var _i = 0, allPanels_1 = allPanels; _i < allPanels_1.length; _i++) {
7603 var panel = allPanels_1[_i];
7604
7605 if (!panel) {
7606 continue;
7607 }
7608
7609 var panelElement = panel.getElement();
7610
7611 if (panelElement.contains(element)) {
7612 return panel;
7613 }
7614 }
7615 };
7616
7617 __proto.findFirstPanelFrom = function (index) {
7618 for (var _i = 0, _a = this.panels.slice(index); _i < _a.length; _i++) {
7619 var panel = _a[_i];
7620
7621 if (panel && panel.getIndex() >= index && panel.getElement().parentNode) {
7622 return panel;
7623 }
7624 }
7625 };
7626
7627 __proto.addNewClones = function (index, originalPanels, deleteCount, nextSibling) {
7628 var _this = this;
7629
7630 var cameraElement = this.cameraElement;
7631 var cloneCount = this.getCloneCount();
7632 var lastPanel = this.lastPanel();
7633 var lastPanelClones = lastPanel ? lastPanel.getClonedPanels() : [];
7634 var nextSiblingClones = nextSibling ? nextSibling.getClonedPanels() : [];
7635
7636 var _loop_1 = function (cloneIndex) {
7637 var cloneNextSibling = nextSiblingClones[cloneIndex];
7638 var lastPanelSibling = lastPanelClones[cloneIndex];
7639 var cloneSiblingElement = cloneNextSibling ? cloneNextSibling.getElement() : lastPanelSibling ? lastPanelSibling.getElement().nextElementSibling : null;
7640 var newClones = originalPanels.map(function (panel) {
7641 var clone = panel.clone(cloneIndex);
7642
7643 if (_this.shouldRender()) {
7644 cameraElement.insertBefore(clone.getElement(), cloneSiblingElement);
7645 }
7646
7647 return clone;
7648 });
7649 this_1.insertClones(cloneIndex, index, newClones, deleteCount);
7650 };
7651
7652 var this_1 = this;
7653
7654 for (var _i = 0, _a = counter(cloneCount); _i < _a.length; _i++) {
7655 var cloneIndex = _a[_i];
7656
7657 _loop_1(cloneIndex);
7658 }
7659 };
7660
7661 __proto.updateIndex = function (insertingIndex) {
7662 var panels = this.panels;
7663 var range = this.range;
7664 var newLastIndex = panels.length - 1;
7665
7666 if (newLastIndex > range.max) {
7667 range.max = newLastIndex;
7668 }
7669
7670 if (insertingIndex < range.min || range.min < 0) {
7671 range.min = insertingIndex;
7672 }
7673 };
7674
7675 __proto.insertNewPanels = function (newPanels, siblingElement) {
7676 if (this.shouldRender()) {
7677 var fragment_1 = document.createDocumentFragment();
7678 newPanels.forEach(function (panel) {
7679 return fragment_1.appendChild(panel.getElement());
7680 });
7681 this.cameraElement.insertBefore(fragment_1, siblingElement);
7682 }
7683 };
7684
7685 __proto.shouldRender = function () {
7686 var options = this.options;
7687 return !options.renderExternal && !options.renderOnlyVisible;
7688 };
7689
7690 return PanelManager;
7691 }();
7692
7693 /**
7694 * Copyright (c) 2015 NAVER Corp.
7695 * egjs projects are licensed under the MIT license
7696 */
7697 var State =
7698 /*#__PURE__*/
7699 function () {
7700 function State() {
7701 this.delta = 0;
7702 this.direction = null;
7703 this.targetPanel = null;
7704 this.lastPosition = 0;
7705 }
7706
7707 var __proto = State.prototype;
7708
7709 __proto.onEnter = function (prevState) {
7710 this.delta = prevState.delta;
7711 this.direction = prevState.direction;
7712 this.targetPanel = prevState.targetPanel;
7713 this.lastPosition = prevState.lastPosition;
7714 };
7715
7716 __proto.onExit = function (nextState) {// DO NOTHING
7717 };
7718
7719 __proto.onHold = function (e, context) {// DO NOTHING
7720 };
7721
7722 __proto.onChange = function (e, context) {// DO NOTHING
7723 };
7724
7725 __proto.onRelease = function (e, context) {// DO NOTHING
7726 };
7727
7728 __proto.onAnimationEnd = function (e, context) {// DO NOTHING
7729 };
7730
7731 __proto.onFinish = function (e, context) {// DO NOTHING
7732 };
7733
7734 return State;
7735 }();
7736
7737 /**
7738 * Copyright (c) 2015 NAVER Corp.
7739 * egjs projects are licensed under the MIT license
7740 */
7741
7742 var IdleState =
7743 /*#__PURE__*/
7744 function (_super) {
7745 __extends(IdleState, _super);
7746
7747 function IdleState() {
7748 var _this = _super !== null && _super.apply(this, arguments) || this;
7749
7750 _this.type = STATE_TYPE.IDLE;
7751 _this.holding = false;
7752 _this.playing = false;
7753 return _this;
7754 }
7755
7756 var __proto = IdleState.prototype;
7757
7758 __proto.onEnter = function () {
7759 this.direction = null;
7760 this.targetPanel = null;
7761 this.delta = 0;
7762 this.lastPosition = 0;
7763 };
7764
7765 __proto.onHold = function (e, _a) {
7766 var flicking = _a.flicking,
7767 viewport = _a.viewport,
7768 triggerEvent = _a.triggerEvent,
7769 transitTo = _a.transitTo; // Shouldn't do any action until any panels on flicking area
7770
7771 if (flicking.getPanelCount() <= 0) {
7772 if (viewport.options.infinite) {
7773 viewport.moveCamera(viewport.getCameraPosition(), e);
7774 }
7775
7776 transitTo(STATE_TYPE.DISABLED);
7777 return;
7778 }
7779
7780 this.lastPosition = viewport.getCameraPosition();
7781 triggerEvent(EVENTS.HOLD_START, e, true).onSuccess(function () {
7782 transitTo(STATE_TYPE.HOLDING);
7783 }).onStopped(function () {
7784 transitTo(STATE_TYPE.DISABLED);
7785 });
7786 }; // By methods call
7787
7788
7789 __proto.onChange = function (e, context) {
7790 var triggerEvent = context.triggerEvent,
7791 transitTo = context.transitTo;
7792 triggerEvent(EVENTS.MOVE_START, e, false).onSuccess(function () {
7793 // Trigger AnimatingState's onChange, to trigger "move" event immediately
7794 transitTo(STATE_TYPE.ANIMATING).onChange(e, context);
7795 }).onStopped(function () {
7796 transitTo(STATE_TYPE.DISABLED);
7797 });
7798 };
7799
7800 return IdleState;
7801 }(State);
7802
7803 /**
7804 * Copyright (c) 2015 NAVER Corp.
7805 * egjs projects are licensed under the MIT license
7806 */
7807
7808 var HoldingState =
7809 /*#__PURE__*/
7810 function (_super) {
7811 __extends(HoldingState, _super);
7812
7813 function HoldingState() {
7814 var _this = _super !== null && _super.apply(this, arguments) || this;
7815
7816 _this.type = STATE_TYPE.HOLDING;
7817 _this.holding = true;
7818 _this.playing = true;
7819 _this.releaseEvent = null;
7820 return _this;
7821 }
7822
7823 var __proto = HoldingState.prototype;
7824
7825 __proto.onChange = function (e, context) {
7826 var flicking = context.flicking,
7827 triggerEvent = context.triggerEvent,
7828 transitTo = context.transitTo;
7829 var offset = flicking.options.horizontal ? e.inputEvent.offsetX : e.inputEvent.offsetY;
7830 this.direction = offset < 0 ? DIRECTION.NEXT : DIRECTION.PREV;
7831 triggerEvent(EVENTS.MOVE_START, e, true).onSuccess(function () {
7832 // Trigger DraggingState's onChange, to trigger "move" event immediately
7833 transitTo(STATE_TYPE.DRAGGING).onChange(e, context);
7834 }).onStopped(function () {
7835 transitTo(STATE_TYPE.DISABLED);
7836 });
7837 };
7838
7839 __proto.onRelease = function (e, context) {
7840 var viewport = context.viewport,
7841 triggerEvent = context.triggerEvent,
7842 transitTo = context.transitTo;
7843 triggerEvent(EVENTS.HOLD_END, e, true);
7844
7845 if (e.delta.flick !== 0) {
7846 // Sometimes "release" event on axes triggered before "change" event
7847 // Especially if user flicked panel fast in really short amount of time
7848 // if delta is not zero, that means above case happened.
7849 // Event flow should be HOLD_START -> MOVE_START -> MOVE -> HOLD_END
7850 // At least one move event should be included between holdStart and holdEnd
7851 e.setTo({
7852 flick: viewport.getCameraPosition()
7853 }, 0);
7854 transitTo(STATE_TYPE.IDLE);
7855 return;
7856 } // Can't handle select event here,
7857 // As "finish" axes event happens
7858
7859
7860 this.releaseEvent = e;
7861 };
7862
7863 __proto.onFinish = function (e, _a) {
7864 var viewport = _a.viewport,
7865 triggerEvent = _a.triggerEvent,
7866 transitTo = _a.transitTo; // Should transite to IDLE state before select event
7867 // As user expects hold is already finished
7868
7869 transitTo(STATE_TYPE.IDLE);
7870
7871 if (!this.releaseEvent) {
7872 return;
7873 } // Handle release event here
7874 // To prevent finish event called twice
7875
7876
7877 var releaseEvent = this.releaseEvent; // Static click
7878
7879 var srcEvent = releaseEvent.inputEvent.srcEvent;
7880 var clickedElement;
7881
7882 if (srcEvent.type === "touchend") {
7883 var touchEvent = srcEvent;
7884 var touch = touchEvent.changedTouches[0];
7885 clickedElement = document.elementFromPoint(touch.clientX, touch.clientY);
7886 } else {
7887 clickedElement = srcEvent.target;
7888 }
7889
7890 var clickedPanel = viewport.panelManager.findPanelOf(clickedElement);
7891 var cameraPosition = viewport.getCameraPosition();
7892
7893 if (clickedPanel) {
7894 var clickedPanelPosition = clickedPanel.getPosition();
7895 var direction = clickedPanelPosition > cameraPosition ? DIRECTION.NEXT : clickedPanelPosition < cameraPosition ? DIRECTION.PREV : null; // Don't provide axes event, to use axes instance instead
7896
7897 triggerEvent(EVENTS.SELECT, null, true, {
7898 direction: direction,
7899 index: clickedPanel.getIndex(),
7900 panel: clickedPanel
7901 });
7902 }
7903 };
7904
7905 return HoldingState;
7906 }(State);
7907
7908 /**
7909 * Copyright (c) 2015 NAVER Corp.
7910 * egjs projects are licensed under the MIT license
7911 */
7912
7913 var DraggingState =
7914 /*#__PURE__*/
7915 function (_super) {
7916 __extends(DraggingState, _super);
7917
7918 function DraggingState() {
7919 var _this = _super !== null && _super.apply(this, arguments) || this;
7920
7921 _this.type = STATE_TYPE.DRAGGING;
7922 _this.holding = true;
7923 _this.playing = true;
7924 return _this;
7925 }
7926
7927 var __proto = DraggingState.prototype;
7928
7929 __proto.onChange = function (e, _a) {
7930 var moveCamera = _a.moveCamera,
7931 transitTo = _a.transitTo;
7932
7933 if (!e.delta.flick) {
7934 return;
7935 }
7936
7937 moveCamera(e).onStopped(function () {
7938 transitTo(STATE_TYPE.DISABLED);
7939 });
7940 };
7941
7942 __proto.onRelease = function (e, context) {
7943 var flicking = context.flicking,
7944 viewport = context.viewport,
7945 triggerEvent = context.triggerEvent,
7946 transitTo = context.transitTo,
7947 stopCamera = context.stopCamera;
7948 var delta = this.delta;
7949 var absDelta = Math.abs(delta);
7950 var options = flicking.options;
7951 var horizontal = options.horizontal;
7952 var moveType = viewport.moveType;
7953 var inputEvent = e.inputEvent;
7954 var velocity = horizontal ? inputEvent.velocityX : inputEvent.velocityY;
7955 var inputDelta = horizontal ? inputEvent.deltaX : inputEvent.deltaY;
7956 var isNextDirection = Math.abs(velocity) > 1 ? velocity < 0 : absDelta > 0 ? delta > 0 : inputDelta < 0;
7957 var swipeDistance = viewport.options.bound ? Math.max(absDelta, Math.abs(inputDelta)) : absDelta;
7958 var swipeAngle = inputEvent.deltaX ? Math.abs(180 * Math.atan(inputEvent.deltaY / inputEvent.deltaX) / Math.PI) : 90;
7959 var belowAngleThreshold = horizontal ? swipeAngle <= options.thresholdAngle : swipeAngle > options.thresholdAngle;
7960 var overThreshold = swipeDistance >= options.threshold && belowAngleThreshold;
7961 var moveTypeContext = {
7962 viewport: viewport,
7963 axesEvent: e,
7964 state: this,
7965 swipeDistance: swipeDistance,
7966 isNextDirection: isNextDirection
7967 }; // Update last position to cope with Axes's animating behavior
7968 // Axes uses start position when animation start
7969
7970 triggerEvent(EVENTS.HOLD_END, e, true);
7971 var targetPanel = this.targetPanel;
7972
7973 if (!overThreshold && targetPanel) {
7974 // Interrupted while animating
7975 var interruptDestInfo = moveType.findPanelWhenInterrupted(moveTypeContext);
7976 viewport.moveTo(interruptDestInfo.panel, interruptDestInfo.destPos, interruptDestInfo.eventType, e, interruptDestInfo.duration);
7977 transitTo(STATE_TYPE.ANIMATING);
7978 return;
7979 }
7980
7981 var currentPanel = viewport.getCurrentPanel();
7982 var nearestPanel = viewport.getNearestPanel();
7983
7984 if (!currentPanel || !nearestPanel) {
7985 // There're no panels
7986 e.stop();
7987 transitTo(STATE_TYPE.IDLE);
7988 return;
7989 }
7990
7991 var destInfo = overThreshold ? moveType.findTargetPanel(moveTypeContext) : moveType.findRestorePanel(moveTypeContext);
7992 viewport.moveTo(destInfo.panel, destInfo.destPos, destInfo.eventType, e, destInfo.duration).onSuccess(function () {
7993 transitTo(STATE_TYPE.ANIMATING);
7994 }).onStopped(function () {
7995 transitTo(STATE_TYPE.DISABLED);
7996 stopCamera(e);
7997 });
7998 };
7999
8000 return DraggingState;
8001 }(State);
8002
8003 /**
8004 * Copyright (c) 2015 NAVER Corp.
8005 * egjs projects are licensed under the MIT license
8006 */
8007
8008 var AnimatingState =
8009 /*#__PURE__*/
8010 function (_super) {
8011 __extends(AnimatingState, _super);
8012
8013 function AnimatingState() {
8014 var _this = _super !== null && _super.apply(this, arguments) || this;
8015
8016 _this.type = STATE_TYPE.ANIMATING;
8017 _this.holding = false;
8018 _this.playing = true;
8019 return _this;
8020 }
8021
8022 var __proto = AnimatingState.prototype;
8023
8024 __proto.onHold = function (e, _a) {
8025 var viewport = _a.viewport,
8026 triggerEvent = _a.triggerEvent,
8027 transitTo = _a.transitTo;
8028 var options = viewport.options;
8029 var scrollArea = viewport.getScrollArea();
8030 var scrollAreaSize = viewport.getScrollAreaSize();
8031 var loopCount = Math.floor((this.lastPosition + this.delta - scrollArea.prev) / scrollAreaSize);
8032 var targetPanel = this.targetPanel;
8033
8034 if (options.circular && loopCount !== 0 && targetPanel) {
8035 var cloneCount = viewport.panelManager.getCloneCount();
8036 var originalTargetPosition = targetPanel.getPosition(); // cloneIndex is from -1 to cloneCount - 1
8037
8038 var newCloneIndex = circulate(targetPanel.getCloneIndex() - loopCount, -1, cloneCount - 1, true);
8039 var newTargetPosition = originalTargetPosition - loopCount * scrollAreaSize;
8040 var newTargetPanel = targetPanel.getIdenticalPanels()[newCloneIndex + 1].clone(newCloneIndex, true); // Set new target panel considering looped count
8041
8042 newTargetPanel.setPosition(newTargetPosition);
8043 this.targetPanel = newTargetPanel;
8044 } // Reset last position and delta
8045
8046
8047 this.delta = 0;
8048 this.lastPosition = viewport.getCameraPosition(); // Update current panel as current nearest panel
8049
8050 viewport.setCurrentPanel(viewport.getNearestPanel());
8051 triggerEvent(EVENTS.HOLD_START, e, true).onSuccess(function () {
8052 transitTo(STATE_TYPE.DRAGGING);
8053 }).onStopped(function () {
8054 transitTo(STATE_TYPE.DISABLED);
8055 });
8056 };
8057
8058 __proto.onChange = function (e, _a) {
8059 var moveCamera = _a.moveCamera,
8060 transitTo = _a.transitTo;
8061
8062 if (!e.delta.flick) {
8063 return;
8064 }
8065
8066 moveCamera(e).onStopped(function () {
8067 transitTo(STATE_TYPE.DISABLED);
8068 });
8069 };
8070
8071 __proto.onFinish = function (e, _a) {
8072 var flicking = _a.flicking,
8073 viewport = _a.viewport,
8074 triggerEvent = _a.triggerEvent,
8075 transitTo = _a.transitTo;
8076 var isTrusted = e && e.isTrusted;
8077 viewport.options.bound ? viewport.setCurrentPanel(this.targetPanel) : viewport.setCurrentPanel(viewport.getNearestPanel());
8078
8079 if (flicking.options.adaptive) {
8080 viewport.updateAdaptiveSize();
8081 }
8082
8083 transitTo(STATE_TYPE.IDLE);
8084 viewport.updateCameraPosition();
8085 triggerEvent(EVENTS.MOVE_END, e, isTrusted, {
8086 direction: this.direction
8087 });
8088 };
8089
8090 return AnimatingState;
8091 }(State);
8092
8093 /**
8094 * Copyright (c) 2015 NAVER Corp.
8095 * egjs projects are licensed under the MIT license
8096 */
8097
8098 var DisabledState =
8099 /*#__PURE__*/
8100 function (_super) {
8101 __extends(DisabledState, _super);
8102
8103 function DisabledState() {
8104 var _this = _super !== null && _super.apply(this, arguments) || this;
8105
8106 _this.type = STATE_TYPE.DISABLED;
8107 _this.holding = false;
8108 _this.playing = true;
8109 return _this;
8110 }
8111
8112 var __proto = DisabledState.prototype;
8113
8114 __proto.onAnimationEnd = function (e, _a) {
8115 var transitTo = _a.transitTo;
8116 transitTo(STATE_TYPE.IDLE);
8117 };
8118
8119 __proto.onChange = function (e, _a) {
8120 var viewport = _a.viewport,
8121 transitTo = _a.transitTo; // Can stop Axes's change event
8122
8123 e.stop(); // Should update axes position as it's already changed at this moment
8124
8125 viewport.updateAxesPosition(viewport.getCameraPosition());
8126 transitTo(STATE_TYPE.IDLE);
8127 };
8128
8129 __proto.onRelease = function (e, _a) {
8130 var transitTo = _a.transitTo; // This is needed when stopped hold start event
8131
8132 if (e.delta.flick === 0) {
8133 transitTo(STATE_TYPE.IDLE);
8134 }
8135 };
8136
8137 return DisabledState;
8138 }(State);
8139
8140 /**
8141 * Copyright (c) 2015 NAVER Corp.
8142 * egjs projects are licensed under the MIT license
8143 */
8144
8145 var StateMachine =
8146 /*#__PURE__*/
8147 function () {
8148 function StateMachine() {
8149 var _this = this;
8150
8151 this.state = new IdleState();
8152
8153 this.transitTo = function (nextStateType) {
8154 var currentState = _this.state;
8155
8156 if (currentState.type !== nextStateType) {
8157 var nextState = void 0;
8158
8159 switch (nextStateType) {
8160 case STATE_TYPE.IDLE:
8161 nextState = new IdleState();
8162 break;
8163
8164 case STATE_TYPE.HOLDING:
8165 nextState = new HoldingState();
8166 break;
8167
8168 case STATE_TYPE.DRAGGING:
8169 nextState = new DraggingState();
8170 break;
8171
8172 case STATE_TYPE.ANIMATING:
8173 nextState = new AnimatingState();
8174 break;
8175
8176 case STATE_TYPE.DISABLED:
8177 nextState = new DisabledState();
8178 break;
8179 }
8180
8181 currentState.onExit(nextState);
8182 nextState.onEnter(currentState);
8183 _this.state = nextState;
8184 }
8185
8186 return _this.state;
8187 };
8188 }
8189
8190 var __proto = StateMachine.prototype;
8191
8192 __proto.fire = function (eventType, e, context) {
8193 var currentState = this.state;
8194
8195 switch (eventType) {
8196 case AXES_EVENTS.HOLD:
8197 currentState.onHold(e, context);
8198 break;
8199
8200 case AXES_EVENTS.CHANGE:
8201 currentState.onChange(e, context);
8202 break;
8203
8204 case AXES_EVENTS.RELEASE:
8205 currentState.onRelease(e, context);
8206 break;
8207
8208 case AXES_EVENTS.ANIMATION_END:
8209 currentState.onAnimationEnd(e, context);
8210 break;
8211
8212 case AXES_EVENTS.FINISH:
8213 currentState.onFinish(e, context);
8214 break;
8215 }
8216 };
8217
8218 __proto.getState = function () {
8219 return this.state;
8220 };
8221
8222 return StateMachine;
8223 }();
8224
8225 /**
8226 * Copyright (c) 2015 NAVER Corp.
8227 * egjs projects are licensed under the MIT license
8228 */
8229
8230 var MoveType =
8231 /*#__PURE__*/
8232 function () {
8233 function MoveType() {}
8234
8235 var __proto = MoveType.prototype;
8236
8237 __proto.is = function (type) {
8238 return type === this.type;
8239 };
8240
8241 __proto.findRestorePanel = function (ctx) {
8242 var viewport = ctx.viewport;
8243 var options = viewport.options;
8244 var panel = options.circular ? this.findRestorePanelInCircularMode(ctx) : viewport.getCurrentPanel();
8245 return {
8246 panel: panel,
8247 destPos: viewport.findEstimatedPosition(panel),
8248 duration: options.duration,
8249 eventType: EVENTS.RESTORE
8250 };
8251 };
8252
8253 __proto.findPanelWhenInterrupted = function (ctx) {
8254 var state = ctx.state,
8255 viewport = ctx.viewport;
8256 var targetPanel = state.targetPanel;
8257 return {
8258 panel: targetPanel,
8259 destPos: viewport.findEstimatedPosition(targetPanel),
8260 duration: viewport.options.duration,
8261 eventType: ""
8262 };
8263 }; // Calculate minimum distance to "change" panel
8264
8265
8266 __proto.calcBrinkOfChange = function (ctx) {
8267 var viewport = ctx.viewport,
8268 isNextDirection = ctx.isNextDirection;
8269 var options = viewport.options;
8270 var currentPanel = viewport.getCurrentPanel();
8271 var halfGap = options.gap / 2;
8272 var relativeAnchorPosition = currentPanel.getRelativeAnchorPosition(); // Minimum distance needed to decide prev/next panel as nearest
8273
8274 /*
8275 * | Prev | Next |
8276 * |--------|--------------|
8277 * [][ |<-Anchor ][] <- Panel + Half-Gap
8278 */
8279
8280 var minimumDistanceToChange = isNextDirection ? currentPanel.getSize() - relativeAnchorPosition + halfGap : relativeAnchorPosition + halfGap;
8281 minimumDistanceToChange = Math.max(minimumDistanceToChange, options.threshold);
8282 return minimumDistanceToChange;
8283 };
8284
8285 __proto.findRestorePanelInCircularMode = function (ctx) {
8286 var viewport = ctx.viewport;
8287 var originalPanel = viewport.getCurrentPanel().getOriginalPanel();
8288 var hangerPosition = viewport.getHangerPosition();
8289 var firstClonedPanel = originalPanel.getIdenticalPanels()[1];
8290 var lapped = Math.abs(originalPanel.getAnchorPosition() - hangerPosition) > Math.abs(firstClonedPanel.getAnchorPosition() - hangerPosition);
8291 return !ctx.isNextDirection && lapped ? firstClonedPanel : originalPanel;
8292 };
8293
8294 return MoveType;
8295 }();
8296
8297 /**
8298 * Copyright (c) 2015 NAVER Corp.
8299 * egjs projects are licensed under the MIT license
8300 */
8301
8302 var Snap =
8303 /*#__PURE__*/
8304 function (_super) {
8305 __extends(Snap, _super);
8306
8307 function Snap(count) {
8308 var _this = _super.call(this) || this;
8309
8310 _this.type = MOVE_TYPE.SNAP;
8311 _this.count = count;
8312 return _this;
8313 }
8314
8315 var __proto = Snap.prototype;
8316
8317 __proto.findTargetPanel = function (ctx) {
8318 var viewport = ctx.viewport,
8319 axesEvent = ctx.axesEvent,
8320 swipeDistance = ctx.swipeDistance;
8321 var snapCount = this.count;
8322 var eventDelta = Math.abs(axesEvent.delta.flick);
8323 var currentPanel = viewport.getCurrentPanel();
8324 var nearestPanel = viewport.getNearestPanel();
8325 var minimumDistanceToChange = this.calcBrinkOfChange(ctx);
8326 var nearestIsCurrent = nearestPanel.getIndex() === currentPanel.getIndex(); // This can happen when bounce is 0
8327
8328 var shouldMoveWhenBounceIs0 = viewport.canSetBoundMode() && nearestIsCurrent;
8329 var shouldMoveToAdjacent = !viewport.isOutOfBound() && (swipeDistance <= minimumDistanceToChange || shouldMoveWhenBounceIs0);
8330
8331 if (snapCount > 1 && eventDelta > minimumDistanceToChange) {
8332 return this.findSnappedPanel(ctx);
8333 } else if (shouldMoveToAdjacent) {
8334 return this.findAdjacentPanel(ctx);
8335 } else {
8336 return {
8337 panel: nearestPanel,
8338 duration: viewport.options.duration,
8339 destPos: viewport.findEstimatedPosition(nearestPanel),
8340 // As swipeDistance holds mouse/touch position change regardless of bounce option value
8341 // swipDistance > minimumDistanceToChange can happen in bounce area
8342 // Second condition is for handling that.
8343 eventType: swipeDistance <= minimumDistanceToChange || viewport.isOutOfBound() && nearestIsCurrent ? EVENTS.RESTORE : EVENTS.CHANGE
8344 };
8345 }
8346 };
8347
8348 __proto.findSnappedPanel = function (ctx) {
8349 var axesEvent = ctx.axesEvent,
8350 viewport = ctx.viewport,
8351 state = ctx.state,
8352 isNextDirection = ctx.isNextDirection;
8353 var eventDelta = Math.abs(axesEvent.delta.flick);
8354 var minimumDistanceToChange = this.calcBrinkOfChange(ctx);
8355 var snapCount = this.count;
8356 var options = viewport.options;
8357 var scrollAreaSize = viewport.getScrollAreaSize();
8358 var halfGap = options.gap / 2;
8359 var estimatedHangerPos = axesEvent.destPos.flick + viewport.getRelativeHangerPosition();
8360 var panelToMove = viewport.getNearestPanel();
8361 var cycleIndex = panelToMove.getCloneIndex() + 1; // 0(original) or 1(clone)
8362
8363 var passedPanelCount = 0;
8364
8365 while (passedPanelCount < snapCount) {
8366 // Since panelToMove holds also cloned panels, we should use original panel's position
8367 var originalPanel = panelToMove.getOriginalPanel();
8368 var panelPosition = originalPanel.getPosition() + cycleIndex * scrollAreaSize;
8369 var panelSize = originalPanel.getSize();
8370 var panelNextPosition = panelPosition + panelSize + halfGap;
8371 var panelPrevPosition = panelPosition - halfGap; // Current panelToMove contains destPos
8372
8373 if (isNextDirection && panelNextPosition > estimatedHangerPos || !isNextDirection && panelPrevPosition < estimatedHangerPos) {
8374 break;
8375 }
8376
8377 var siblingPanel = isNextDirection ? panelToMove.nextSibling : panelToMove.prevSibling;
8378
8379 if (!siblingPanel) {
8380 break;
8381 }
8382
8383 var panelIndex = panelToMove.getIndex();
8384 var siblingIndex = siblingPanel.getIndex();
8385
8386 if (isNextDirection && siblingIndex <= panelIndex || !isNextDirection && siblingIndex >= panelIndex) {
8387 cycleIndex = isNextDirection ? cycleIndex + 1 : cycleIndex - 1;
8388 }
8389
8390 panelToMove = siblingPanel;
8391 passedPanelCount += 1;
8392 }
8393
8394 var originalPosition = panelToMove.getOriginalPanel().getPosition();
8395
8396 if (cycleIndex !== 0) {
8397 panelToMove = panelToMove.clone(panelToMove.getCloneIndex(), true);
8398 panelToMove.setPosition(originalPosition + cycleIndex * scrollAreaSize);
8399 }
8400
8401 var defaultDuration = viewport.options.duration;
8402 var duration = clamp(axesEvent.duration, defaultDuration, defaultDuration * passedPanelCount);
8403 return {
8404 panel: panelToMove,
8405 destPos: viewport.findEstimatedPosition(panelToMove),
8406 duration: duration,
8407 eventType: Math.max(eventDelta, state.delta) > minimumDistanceToChange ? EVENTS.CHANGE : EVENTS.RESTORE
8408 };
8409 };
8410
8411 __proto.findAdjacentPanel = function (ctx) {
8412 var viewport = ctx.viewport,
8413 isNextDirection = ctx.isNextDirection;
8414 var options = viewport.options;
8415 var currentIndex = viewport.getCurrentIndex();
8416 var currentPanel = viewport.panelManager.get(currentIndex);
8417 var hangerPosition = viewport.getHangerPosition();
8418 var scrollArea = viewport.getScrollArea();
8419 var firstClonedPanel = currentPanel.getIdenticalPanels()[1];
8420 var lapped = options.circular && Math.abs(currentPanel.getAnchorPosition() - hangerPosition) > Math.abs(firstClonedPanel.getAnchorPosition() - hangerPosition); // If lapped in circular mode, use first cloned panel as base panel
8421
8422 var basePanel = lapped ? firstClonedPanel : currentPanel;
8423 var basePosition = basePanel.getPosition();
8424 var adjacentPanel = isNextDirection ? basePanel.nextSibling : basePanel.prevSibling;
8425 var eventType = adjacentPanel ? EVENTS.CHANGE : EVENTS.RESTORE;
8426 var panelToMove = adjacentPanel ? adjacentPanel : basePanel;
8427 var targetRelativeAnchorPosition = panelToMove.getRelativeAnchorPosition();
8428 var estimatedPanelPosition = options.circular ? isNextDirection ? basePosition + basePanel.getSize() + targetRelativeAnchorPosition + options.gap : basePosition - (panelToMove.getSize() - targetRelativeAnchorPosition) - options.gap : panelToMove.getAnchorPosition();
8429 var estimatedPosition = estimatedPanelPosition - viewport.getRelativeHangerPosition();
8430 var destPos = viewport.canSetBoundMode() ? clamp(estimatedPosition, scrollArea.prev, scrollArea.next) : estimatedPosition;
8431 return {
8432 panel: panelToMove,
8433 destPos: destPos,
8434 duration: options.duration,
8435 eventType: eventType
8436 };
8437 };
8438
8439 return Snap;
8440 }(MoveType);
8441
8442 /**
8443 * Copyright (c) 2015 NAVER Corp.
8444 * egjs projects are licensed under the MIT license
8445 */
8446
8447 var FreeScroll =
8448 /*#__PURE__*/
8449 function (_super) {
8450 __extends(FreeScroll, _super);
8451
8452 function FreeScroll() {
8453 var _this = // Set snap count to Infinity
8454 _super.call(this, Infinity) || this;
8455
8456 _this.type = MOVE_TYPE.FREE_SCROLL;
8457 return _this;
8458 }
8459
8460 var __proto = FreeScroll.prototype;
8461
8462 __proto.findTargetPanel = function (ctx) {
8463 var axesEvent = ctx.axesEvent,
8464 state = ctx.state,
8465 viewport = ctx.viewport;
8466 var destPos = axesEvent.destPos.flick;
8467 var minimumDistanceToChange = this.calcBrinkOfChange(ctx);
8468 var scrollArea = viewport.getScrollArea();
8469 var currentPanel = viewport.getCurrentPanel();
8470 var options = viewport.options;
8471 var delta = Math.abs(axesEvent.delta.flick + state.delta);
8472
8473 if (delta > minimumDistanceToChange) {
8474 var destInfo = _super.prototype.findSnappedPanel.call(this, ctx);
8475
8476 destInfo.duration = axesEvent.duration;
8477 destInfo.destPos = destPos;
8478 destInfo.eventType = !options.circular && destInfo.panel === currentPanel ? "" : EVENTS.CHANGE;
8479 return destInfo;
8480 } else {
8481 var estimatedPosition = options.circular ? circulate(destPos, scrollArea.prev, scrollArea.next, false) : destPos;
8482 estimatedPosition = clamp(estimatedPosition, scrollArea.prev, scrollArea.next);
8483 estimatedPosition += viewport.getRelativeHangerPosition();
8484 var estimatedPanel = viewport.findNearestPanelAt(estimatedPosition);
8485 return {
8486 panel: estimatedPanel,
8487 destPos: destPos,
8488 duration: axesEvent.duration,
8489 eventType: ""
8490 };
8491 }
8492 };
8493
8494 __proto.findRestorePanel = function (ctx) {
8495 return this.findTargetPanel(ctx);
8496 };
8497
8498 __proto.findPanelWhenInterrupted = function (ctx) {
8499 var viewport = ctx.viewport;
8500 return {
8501 panel: viewport.getNearestPanel(),
8502 destPos: viewport.getCameraPosition(),
8503 duration: 0,
8504 eventType: ""
8505 };
8506 };
8507
8508 __proto.calcBrinkOfChange = function (ctx) {
8509 var viewport = ctx.viewport,
8510 isNextDirection = ctx.isNextDirection;
8511 var options = viewport.options;
8512 var currentPanel = viewport.getCurrentPanel();
8513 var halfGap = options.gap / 2;
8514 var lastPosition = viewport.stateMachine.getState().lastPosition;
8515 var currentPanelPosition = currentPanel.getPosition(); // As camera can stop anywhere in free scroll mode,
8516 // minimumDistanceToChange should be calculated differently.
8517 // Ref #191(https://github.com/naver/egjs-flicking/issues/191)
8518
8519 var lastHangerPosition = lastPosition + viewport.getRelativeHangerPosition();
8520 var scrollAreaSize = viewport.getScrollAreaSize();
8521 var minimumDistanceToChange = isNextDirection ? currentPanelPosition + currentPanel.getSize() - lastHangerPosition + halfGap : lastHangerPosition - currentPanelPosition + halfGap;
8522 minimumDistanceToChange = Math.abs(minimumDistanceToChange % scrollAreaSize);
8523 return Math.min(minimumDistanceToChange, scrollAreaSize - minimumDistanceToChange);
8524 };
8525
8526 return FreeScroll;
8527 }(Snap);
8528
8529 var Viewport =
8530 /*#__PURE__*/
8531 function () {
8532 function Viewport(flicking, options, triggerEvent) {
8533 var _this = this;
8534
8535 this.plugins = [];
8536
8537 this.stopCamera = function (axesEvent) {
8538 if (axesEvent && axesEvent.setTo) {
8539 axesEvent.setTo({
8540 flick: _this.state.position
8541 }, 0);
8542 }
8543
8544 _this.stateMachine.transitTo(STATE_TYPE.IDLE);
8545 };
8546
8547 this.flicking = flicking;
8548 this.triggerEvent = triggerEvent;
8549 this.state = {
8550 size: 0,
8551 position: 0,
8552 panelMaintainRatio: 0,
8553 relativeHangerPosition: 0,
8554 positionOffset: 0,
8555 scrollArea: {
8556 prev: 0,
8557 next: 0
8558 },
8559 translate: TRANSFORM$1,
8560 infiniteThreshold: 0,
8561 checkedIndexes: [],
8562 isAdaptiveCached: false,
8563 isViewportGiven: false,
8564 isCameraGiven: false,
8565 originalViewportStyle: {
8566 className: null,
8567 style: null
8568 },
8569 originalCameraStyle: {
8570 className: null,
8571 style: null
8572 },
8573 cachedBbox: null
8574 };
8575 this.options = options;
8576 this.stateMachine = new StateMachine();
8577 this.visiblePanels = [];
8578 this.panelBboxes = {};
8579 this.build();
8580 }
8581
8582 var __proto = Viewport.prototype;
8583
8584 __proto.moveTo = function (panel, destPos, eventType, axesEvent, duration) {
8585 var _this = this;
8586
8587 if (duration === void 0) {
8588 duration = this.options.duration;
8589 }
8590
8591 var state = this.state;
8592 var currentState = this.stateMachine.getState();
8593 var currentPosition = state.position;
8594 var isTrusted = axesEvent ? axesEvent.isTrusted : false;
8595 var direction = destPos === currentPosition ? null : destPos > currentPosition ? DIRECTION.NEXT : DIRECTION.PREV;
8596 var eventResult;
8597
8598 if (eventType === EVENTS.CHANGE) {
8599 eventResult = this.triggerEvent(EVENTS.CHANGE, axesEvent, isTrusted, {
8600 index: panel.getIndex(),
8601 panel: panel,
8602 direction: direction
8603 });
8604 } else if (eventType === EVENTS.RESTORE) {
8605 eventResult = this.triggerEvent(EVENTS.RESTORE, axesEvent, isTrusted);
8606 } else {
8607 eventResult = {
8608 onSuccess: function (callback) {
8609 callback();
8610 return this;
8611 },
8612 onStopped: function () {
8613 return this;
8614 }
8615 };
8616 }
8617
8618 eventResult.onSuccess(function () {
8619 currentState.delta = 0;
8620 currentState.lastPosition = _this.getCameraPosition();
8621 currentState.targetPanel = panel;
8622 currentState.direction = destPos === currentPosition ? null : destPos > currentPosition ? DIRECTION.NEXT : DIRECTION.PREV;
8623
8624 if (destPos === currentPosition) {
8625 // no move
8626 _this.nearestPanel = panel;
8627 _this.currentPanel = panel;
8628 }
8629
8630 if (axesEvent && axesEvent.setTo) {
8631 // freeScroll only occurs in release events
8632 axesEvent.setTo({
8633 flick: destPos
8634 }, duration);
8635 } else {
8636 _this.axes.setTo({
8637 flick: destPos
8638 }, duration);
8639 }
8640 });
8641 return eventResult;
8642 };
8643
8644 __proto.moveCamera = function (pos, axesEvent) {
8645 var state = this.state;
8646 var options = this.options;
8647 var transform = state.translate.name;
8648 var scrollArea = state.scrollArea; // Update position & nearestPanel
8649
8650 if (options.circular && !isBetween(pos, scrollArea.prev, scrollArea.next)) {
8651 pos = circulate(pos, scrollArea.prev, scrollArea.next, false);
8652 }
8653
8654 state.position = pos;
8655 this.nearestPanel = this.findNearestPanel();
8656 var nearestPanel = this.nearestPanel;
8657 var originalNearestPosition = nearestPanel ? nearestPanel.getPosition() : 0; // From 0(panel position) to 1(panel position + panel size)
8658 // When it's on gap area value will be (val > 1 || val < 0)
8659
8660 if (nearestPanel) {
8661 var hangerPosition = this.getHangerPosition();
8662 var panelPosition = nearestPanel.getPosition();
8663 var panelSize = nearestPanel.getSize();
8664 var halfGap = options.gap / 2; // As panel's range is from panel position - half gap ~ panel pos + panel size + half gap
8665
8666 state.panelMaintainRatio = (hangerPosition - panelPosition + halfGap) / (panelSize + 2 * halfGap);
8667 } else {
8668 state.panelMaintainRatio = 0;
8669 }
8670
8671 this.checkNeedPanel(axesEvent); // Possibly modified after need panel, if it's looped
8672
8673 var modifiedNearestPosition = nearestPanel ? nearestPanel.getPosition() : 0;
8674 pos += modifiedNearestPosition - originalNearestPosition;
8675 state.position = pos;
8676 this.updateVisiblePanels(); // Offset is needed to fix camera layer size in visible-only rendering mode
8677
8678 var posOffset = options.renderOnlyVisible ? state.positionOffset : 0;
8679 var moveVector = options.horizontal ? [-(pos - posOffset), 0] : [0, -(pos - posOffset)];
8680 var moveCoord = moveVector.map(function (coord) {
8681 return Math.round(coord) + "px";
8682 }).join(", ");
8683 this.cameraElement.style[transform] = state.translate.has3d ? "translate3d(" + moveCoord + ", 0px)" : "translate(" + moveCoord + ")";
8684 };
8685
8686 __proto.unCacheBbox = function () {
8687 var state = this.state;
8688 var options = this.options;
8689 state.cachedBbox = null;
8690 this.visiblePanels = [];
8691 var viewportElement = this.viewportElement;
8692
8693 if (!options.horizontal) {
8694 // Don't preserve previous width for adaptive resizing
8695 viewportElement.style.width = "";
8696 } else {
8697 viewportElement.style.height = "";
8698 }
8699
8700 state.isAdaptiveCached = false;
8701 this.panelBboxes = {};
8702 };
8703
8704 __proto.resize = function () {
8705 this.updateSize();
8706 this.updateOriginalPanelPositions();
8707 this.updateAdaptiveSize();
8708 this.updateScrollArea();
8709 this.updateClonePanels();
8710 this.updateVisiblePanelPositions();
8711 this.updateCameraPosition();
8712 this.updatePlugins();
8713 }; // Find nearest anchor from current hanger position
8714
8715
8716 __proto.findNearestPanel = function () {
8717 var state = this.state;
8718 var panelManager = this.panelManager;
8719 var hangerPosition = this.getHangerPosition();
8720
8721 if (this.isOutOfBound()) {
8722 var position = state.position;
8723 return position <= state.scrollArea.prev ? panelManager.firstPanel() : panelManager.lastPanel();
8724 }
8725
8726 return this.findNearestPanelAt(hangerPosition);
8727 };
8728
8729 __proto.findNearestPanelAt = function (position) {
8730 var panelManager = this.panelManager;
8731 var allPanels = panelManager.allPanels();
8732 var minimumDistance = Infinity;
8733 var nearestPanel;
8734
8735 for (var _i = 0, allPanels_1 = allPanels; _i < allPanels_1.length; _i++) {
8736 var panel = allPanels_1[_i];
8737
8738 if (!panel) {
8739 continue;
8740 }
8741
8742 var prevPosition = panel.getPosition();
8743 var nextPosition = prevPosition + panel.getSize(); // Use shortest distance from panel's range
8744
8745 var distance = isBetween(position, prevPosition, nextPosition) ? 0 : Math.min(Math.abs(prevPosition - position), Math.abs(nextPosition - position));
8746
8747 if (distance > minimumDistance) {
8748 break;
8749 } else if (distance === minimumDistance) {
8750 var minimumAnchorDistance = Math.abs(position - nearestPanel.getAnchorPosition());
8751 var anchorDistance = Math.abs(position - panel.getAnchorPosition());
8752
8753 if (anchorDistance > minimumAnchorDistance) {
8754 break;
8755 }
8756 }
8757
8758 minimumDistance = distance;
8759 nearestPanel = panel;
8760 }
8761
8762 return nearestPanel;
8763 };
8764
8765 __proto.findNearestIdenticalPanel = function (panel) {
8766 var nearest = panel;
8767 var shortestDistance = Infinity;
8768 var hangerPosition = this.getHangerPosition();
8769 var identicals = panel.getIdenticalPanels();
8770 identicals.forEach(function (identical) {
8771 var anchorPosition = identical.getAnchorPosition();
8772 var distance = Math.abs(anchorPosition - hangerPosition);
8773
8774 if (distance < shortestDistance) {
8775 nearest = identical;
8776 shortestDistance = distance;
8777 }
8778 });
8779 return nearest;
8780 }; // Find shortest camera position that distance is minimum
8781
8782
8783 __proto.findShortestPositionToPanel = function (panel) {
8784 var state = this.state;
8785 var options = this.options;
8786 var anchorPosition = panel.getAnchorPosition();
8787 var hangerPosition = this.getHangerPosition();
8788 var distance = Math.abs(hangerPosition - anchorPosition);
8789 var scrollAreaSize = state.scrollArea.next - state.scrollArea.prev;
8790
8791 if (!options.circular) {
8792 var position = anchorPosition - state.relativeHangerPosition;
8793 return this.canSetBoundMode() ? clamp(position, state.scrollArea.prev, state.scrollArea.next) : position;
8794 } else {
8795 // If going out of viewport border is more efficient way of moving, choose that position
8796 return distance <= scrollAreaSize - distance ? anchorPosition - state.relativeHangerPosition : anchorPosition > hangerPosition // PREV TO NEXT
8797 ? anchorPosition - state.relativeHangerPosition - scrollAreaSize // NEXT TO PREV
8798 : anchorPosition - state.relativeHangerPosition + scrollAreaSize;
8799 }
8800 };
8801
8802 __proto.findEstimatedPosition = function (panel) {
8803 var scrollArea = this.getScrollArea();
8804 var estimatedPosition = panel.getAnchorPosition() - this.getRelativeHangerPosition();
8805 estimatedPosition = this.canSetBoundMode() ? clamp(estimatedPosition, scrollArea.prev, scrollArea.next) : estimatedPosition;
8806 return estimatedPosition;
8807 };
8808
8809 __proto.addVisiblePanel = function (panel) {
8810 if (this.getVisibleIndexOf(panel) < 0) {
8811 this.visiblePanels.push(panel);
8812 }
8813 };
8814
8815 __proto.enable = function () {
8816 if (!this.panInput) {
8817 this.createPanInput();
8818 }
8819 };
8820
8821 __proto.disable = function () {
8822 if (this.panInput) {
8823 this.panInput.destroy();
8824 this.panInput = null;
8825 this.stateMachine.transitTo(STATE_TYPE.IDLE);
8826 }
8827 };
8828
8829 __proto.insert = function (index, element) {
8830 var _this = this;
8831
8832 var lastIndex = this.panelManager.getLastIndex(); // Index should not below 0
8833
8834 if (index < 0 || index > lastIndex) {
8835 return [];
8836 }
8837
8838 var state = this.state;
8839 var options = this.options;
8840 var parsedElements = parseElement(element);
8841 var panels = parsedElements.map(function (el, idx) {
8842 return new Panel(el, index + idx, _this);
8843 }).slice(0, lastIndex - index + 1);
8844
8845 if (panels.length <= 0) {
8846 return [];
8847 }
8848
8849 var pushedIndex = this.panelManager.insert(index, panels); // ...then calc bbox for all panels
8850
8851 this.resizePanels(panels);
8852
8853 if (!this.currentPanel) {
8854 this.currentPanel = panels[0];
8855 this.nearestPanel = panels[0];
8856 var newCenterPanel = panels[0];
8857 var newPanelPosition = this.findEstimatedPosition(newCenterPanel);
8858 state.position = newPanelPosition;
8859 this.updateAxesPosition(newPanelPosition);
8860 state.panelMaintainRatio = (newCenterPanel.getRelativeAnchorPosition() + options.gap / 2) / (newCenterPanel.getSize() + options.gap);
8861 } // Update checked indexes in infinite mode
8862
8863
8864 this.updateCheckedIndexes({
8865 min: index,
8866 max: index
8867 });
8868 state.checkedIndexes.forEach(function (indexes, idx) {
8869 var min = indexes[0],
8870 max = indexes[1];
8871
8872 if (index < min) {
8873 // Push checked index
8874 state.checkedIndexes.splice(idx, 1, [min + pushedIndex, max + pushedIndex]);
8875 }
8876 });
8877 this.resize();
8878 return panels;
8879 };
8880
8881 __proto.replace = function (index, element) {
8882 var _this = this;
8883
8884 var state = this.state;
8885 var options = this.options;
8886 var panelManager = this.panelManager;
8887 var lastIndex = panelManager.getLastIndex(); // Index should not below 0
8888
8889 if (index < 0 || index > lastIndex) {
8890 return [];
8891 }
8892
8893 var parsedElements = parseElement(element);
8894 var panels = parsedElements.map(function (el, idx) {
8895 return new Panel(el, index + idx, _this);
8896 }).slice(0, lastIndex - index + 1);
8897
8898 if (panels.length <= 0) {
8899 return [];
8900 }
8901
8902 var replacedPanels = panelManager.replace(index, panels);
8903 replacedPanels.forEach(function (panel) {
8904 var visibleIndex = _this.getVisibleIndexOf(panel);
8905
8906 if (visibleIndex > -1) {
8907 _this.visiblePanels.splice(visibleIndex, 1);
8908 }
8909 }); // ...then calc bbox for all panels
8910
8911 this.resizePanels(panels);
8912 var currentPanel = this.currentPanel;
8913 var wasEmpty = !currentPanel;
8914
8915 if (wasEmpty) {
8916 this.currentPanel = panels[0];
8917 this.nearestPanel = panels[0];
8918 var newCenterPanel = panels[0];
8919 var newPanelPosition = this.findEstimatedPosition(newCenterPanel);
8920 state.position = newPanelPosition;
8921 this.updateAxesPosition(newPanelPosition);
8922 state.panelMaintainRatio = (newCenterPanel.getRelativeAnchorPosition() + options.gap / 2) / (newCenterPanel.getSize() + options.gap);
8923 } else if (isBetween(currentPanel.getIndex(), index, index + panels.length - 1)) {
8924 // Current panel is replaced
8925 this.currentPanel = panelManager.get(currentPanel.getIndex());
8926 } // Update checked indexes in infinite mode
8927
8928
8929 this.updateCheckedIndexes({
8930 min: index,
8931 max: index + panels.length - 1
8932 });
8933 this.resize();
8934 return panels;
8935 };
8936
8937 __proto.remove = function (index, deleteCount) {
8938 if (deleteCount === void 0) {
8939 deleteCount = 1;
8940 }
8941
8942 var state = this.state; // Index should not below 0
8943
8944 index = Math.max(index, 0);
8945 var panelManager = this.panelManager;
8946 var currentIndex = this.getCurrentIndex();
8947 var removedPanels = panelManager.remove(index, deleteCount);
8948
8949 if (isBetween(currentIndex, index, index + deleteCount - 1)) {
8950 // Current panel is removed
8951 // Use panel at removing index - 1 as new current panel if it exists
8952 var newCurrentIndex = Math.max(index - 1, panelManager.getRange().min);
8953 this.currentPanel = panelManager.get(newCurrentIndex);
8954 } // Update checked indexes in infinite mode
8955
8956
8957 if (deleteCount > 0) {
8958 // Check whether removing index will affect checked indexes
8959 // Suppose index 0 is empty and removed index 1, then checked index 0 should be deleted and vice versa.
8960 this.updateCheckedIndexes({
8961 min: index - 1,
8962 max: index + deleteCount
8963 }); // Uncache visible panels to refresh panels
8964
8965 this.visiblePanels = [];
8966 }
8967
8968 if (panelManager.getPanelCount() <= 0) {
8969 this.currentPanel = undefined;
8970 this.nearestPanel = undefined;
8971 }
8972
8973 this.resize();
8974 var scrollArea = state.scrollArea;
8975
8976 if (state.position < scrollArea.prev || state.position > scrollArea.next) {
8977 var newPosition = circulate(state.position, scrollArea.prev, scrollArea.next, false);
8978 this.moveCamera(newPosition);
8979 this.updateAxesPosition(newPosition);
8980 }
8981
8982 return removedPanels;
8983 };
8984
8985 __proto.updateAdaptiveSize = function () {
8986 var state = this.state;
8987 var options = this.options;
8988 var horizontal = options.horizontal;
8989 var currentPanel = this.getCurrentPanel();
8990
8991 if (!currentPanel) {
8992 return;
8993 }
8994
8995 var shouldApplyAdaptive = options.adaptive || !state.isAdaptiveCached;
8996 var viewportStyle = this.viewportElement.style;
8997
8998 if (shouldApplyAdaptive) {
8999 var sizeToApply = void 0;
9000
9001 if (options.adaptive) {
9002 var panelBbox = currentPanel.getBbox();
9003 sizeToApply = horizontal ? panelBbox.height : panelBbox.width;
9004 } else {
9005 // Find minimum height of panels to maximum panel size
9006 var maximumPanelSize = this.panelManager.originalPanels().reduce(function (maximum, panel) {
9007 var panelBbox = panel.getBbox();
9008 return Math.max(maximum, horizontal ? panelBbox.height : panelBbox.width);
9009 }, 0);
9010 sizeToApply = maximumPanelSize;
9011 }
9012
9013 if (!state.isAdaptiveCached) {
9014 var viewportBbox = this.updateBbox();
9015 sizeToApply = Math.max(sizeToApply, horizontal ? viewportBbox.height : viewportBbox.width);
9016 state.isAdaptiveCached = true;
9017 }
9018
9019 var viewportSize = sizeToApply + "px";
9020
9021 if (horizontal) {
9022 viewportStyle.height = viewportSize;
9023 state.cachedBbox.height = sizeToApply;
9024 } else {
9025 viewportStyle.width = viewportSize;
9026 state.cachedBbox.width = sizeToApply;
9027 }
9028 }
9029 }; // Update camera position after resizing
9030
9031
9032 __proto.updateCameraPosition = function () {
9033 var state = this.state;
9034 var currentPanel = this.getCurrentPanel();
9035 var cameraPosition = this.getCameraPosition();
9036 var currentState = this.stateMachine.getState();
9037 var isFreeScroll = this.moveType.is(MOVE_TYPE.FREE_SCROLL);
9038 var relativeHangerPosition = this.getRelativeHangerPosition();
9039 var halfGap = this.options.gap / 2;
9040
9041 if (currentState.holding || currentState.playing) {
9042 this.updateVisiblePanels();
9043 return;
9044 }
9045
9046 var newPosition;
9047
9048 if (isFreeScroll) {
9049 var positionBounded = this.canSetBoundMode() && (cameraPosition === state.scrollArea.prev || cameraPosition === state.scrollArea.next);
9050 var nearestPanel = this.getNearestPanel(); // Preserve camera position if it is bound to scroll area limit
9051
9052 newPosition = positionBounded || !nearestPanel ? cameraPosition : nearestPanel.getPosition() - halfGap + (nearestPanel.getSize() + 2 * halfGap) * state.panelMaintainRatio - relativeHangerPosition;
9053 } else {
9054 newPosition = currentPanel ? currentPanel.getAnchorPosition() - relativeHangerPosition : cameraPosition;
9055 }
9056
9057 if (this.canSetBoundMode()) {
9058 newPosition = clamp(newPosition, state.scrollArea.prev, state.scrollArea.next);
9059 } // Pause & resume axes to prevent axes's "change" event triggered
9060 // This should be done before moveCamera, as moveCamera can trigger needPanel
9061
9062
9063 this.updateAxesPosition(newPosition);
9064 this.moveCamera(newPosition);
9065 };
9066
9067 __proto.updateBbox = function () {
9068 var state = this.state;
9069 var options = this.options;
9070 var viewportElement = this.viewportElement;
9071
9072 if (!state.cachedBbox) {
9073 state.cachedBbox = getBbox(viewportElement, options.useOffset);
9074 }
9075
9076 return state.cachedBbox;
9077 };
9078
9079 __proto.updatePlugins = function () {
9080 var _this = this; // update for resize
9081
9082
9083 this.plugins.forEach(function (plugin) {
9084 plugin.update && plugin.update(_this.flicking);
9085 });
9086 };
9087
9088 __proto.destroy = function (option) {
9089 var _a;
9090
9091 var state = this.state;
9092 var wrapper = this.flicking.getElement();
9093 var viewportElement = this.viewportElement;
9094 var cameraElement = this.cameraElement;
9095 var originalPanels = this.panelManager.originalPanels();
9096 this.removePlugins(this.plugins);
9097
9098 if (!option.preserveUI) {
9099 restoreStyle(viewportElement, state.originalViewportStyle);
9100 restoreStyle(cameraElement, state.originalCameraStyle);
9101
9102 if (!state.isCameraGiven && !this.options.renderExternal) {
9103 var topmostElement_1 = state.isViewportGiven ? viewportElement : wrapper;
9104 var deletingElement = state.isViewportGiven ? cameraElement : viewportElement;
9105 originalPanels.forEach(function (panel) {
9106 topmostElement_1.appendChild(panel.getElement());
9107 });
9108 topmostElement_1.removeChild(deletingElement);
9109 }
9110 }
9111
9112 this.axes.destroy();
9113 (_a = this.panInput) === null || _a === void 0 ? void 0 : _a.destroy();
9114 originalPanels.forEach(function (panel) {
9115 panel.destroy(option);
9116 }); // release resources
9117
9118 for (var x in this) {
9119 this[x] = null;
9120 }
9121 };
9122
9123 __proto.restore = function (status) {
9124 var panels = status.panels;
9125 var defaultIndex = this.options.defaultIndex;
9126 var cameraElement = this.cameraElement;
9127 var panelManager = this.panelManager; // Restore index
9128
9129 cameraElement.innerHTML = panels.map(function (panel) {
9130 return panel.html;
9131 }).join(""); // Create panels first
9132
9133 this.refreshPanels();
9134 var createdPanels = panelManager.originalPanels(); // ...then order it by its index
9135
9136 var orderedPanels = [];
9137 panels.forEach(function (panel, idx) {
9138 var createdPanel = createdPanels[idx];
9139 createdPanel.setIndex(panel.index);
9140 orderedPanels[panel.index] = createdPanel;
9141 });
9142 panelManager.replacePanels(orderedPanels, []);
9143 panelManager.setCloneCount(0); // No clones at this point
9144
9145 var panelCount = panelManager.getPanelCount();
9146
9147 if (panelCount > 0) {
9148 this.currentPanel = panelManager.get(status.index) || panelManager.get(defaultIndex) || panelManager.firstPanel();
9149 this.nearestPanel = this.currentPanel;
9150 } else {
9151 this.currentPanel = undefined;
9152 this.nearestPanel = undefined;
9153 }
9154
9155 this.visiblePanels = orderedPanels.filter(function (panel) {
9156 return Boolean(panel);
9157 });
9158 this.resize();
9159 this.axes.setTo({
9160 flick: status.position
9161 }, 0);
9162 this.moveCamera(status.position);
9163 };
9164
9165 __proto.calcVisiblePanels = function () {
9166 var allPanels = this.panelManager.allPanels();
9167
9168 if (this.options.renderOnlyVisible) {
9169 var cameraPos_1 = this.getCameraPosition();
9170 var viewportSize_1 = this.getSize();
9171 var basePanel = this.nearestPanel;
9172
9173 var getNextPanel = function (panel) {
9174 var nextPanel = panel.nextSibling;
9175
9176 if (nextPanel && nextPanel.getPosition() >= panel.getPosition()) {
9177 return nextPanel;
9178 } else {
9179 return null;
9180 }
9181 };
9182
9183 var getPrevPanel = function (panel) {
9184 var prevPanel = panel.prevSibling;
9185
9186 if (prevPanel && prevPanel.getPosition() <= panel.getPosition()) {
9187 return prevPanel;
9188 } else {
9189 return null;
9190 }
9191 };
9192
9193 var isOutOfBoundNext = function (panel) {
9194 return panel.getPosition() >= cameraPos_1 + viewportSize_1;
9195 };
9196
9197 var isOutOfBoundPrev = function (panel) {
9198 return panel.getPosition() + panel.getSize() <= cameraPos_1;
9199 };
9200
9201 var getVisiblePanels = function (panel, getNext, isOutOfViewport) {
9202 var visiblePanels = [];
9203 var lastPanel = panel;
9204
9205 while (true) {
9206 var nextPanel = getNext(lastPanel);
9207
9208 if (!nextPanel || isOutOfViewport(nextPanel)) {
9209 break;
9210 }
9211
9212 visiblePanels.push(nextPanel);
9213 lastPanel = nextPanel;
9214 }
9215
9216 return visiblePanels;
9217 };
9218
9219 var panelCount_1 = this.panelManager.getPanelCount();
9220
9221 var getAbsIndex_1 = function (panel) {
9222 return panel.getIndex() + (panel.getCloneIndex() + 1) * panelCount_1;
9223 };
9224
9225 var nextPanels = getVisiblePanels(basePanel, getNextPanel, isOutOfBoundNext);
9226 var prevPanels = getVisiblePanels(basePanel, getPrevPanel, isOutOfBoundPrev);
9227 return __spreadArrays([basePanel], nextPanels, prevPanels).sort(function (panel1, panel2) {
9228 return getAbsIndex_1(panel1) - getAbsIndex_1(panel2);
9229 });
9230 } else {
9231 return allPanels.filter(function (panel) {
9232 var outsetProgress = panel.getOutsetProgress();
9233 return outsetProgress > -1 && outsetProgress < 1;
9234 });
9235 }
9236 };
9237
9238 __proto.getCurrentPanel = function () {
9239 return this.currentPanel;
9240 };
9241
9242 __proto.getCurrentIndex = function () {
9243 var currentPanel = this.currentPanel;
9244 return currentPanel ? currentPanel.getIndex() : -1;
9245 };
9246
9247 __proto.getNearestPanel = function () {
9248 return this.nearestPanel;
9249 }; // Get progress from nearest panel
9250
9251
9252 __proto.getCurrentProgress = function () {
9253 var currentState = this.stateMachine.getState();
9254 var nearestPanel = currentState.playing || currentState.holding ? this.nearestPanel : this.currentPanel;
9255 var panelManager = this.panelManager;
9256
9257 if (!nearestPanel) {
9258 // There're no panels
9259 return NaN;
9260 }
9261
9262 var _a = this.getScrollArea(),
9263 prevRange = _a.prev,
9264 nextRange = _a.next;
9265
9266 var cameraPosition = this.getCameraPosition();
9267 var isOutOfBound = this.isOutOfBound();
9268 var prevPanel = nearestPanel.prevSibling;
9269 var nextPanel = nearestPanel.nextSibling;
9270 var hangerPosition = this.getHangerPosition();
9271 var nearestAnchorPos = nearestPanel.getAnchorPosition();
9272
9273 if (isOutOfBound && prevPanel && nextPanel && cameraPosition < nextRange // On the basis of anchor, prevPanel is nearestPanel.
9274 && hangerPosition - prevPanel.getAnchorPosition() < nearestAnchorPos - hangerPosition) {
9275 nearestPanel = prevPanel;
9276 nextPanel = nearestPanel.nextSibling;
9277 prevPanel = nearestPanel.prevSibling;
9278 nearestAnchorPos = nearestPanel.getAnchorPosition();
9279 }
9280
9281 var nearestIndex = nearestPanel.getIndex() + (nearestPanel.getCloneIndex() + 1) * panelManager.getPanelCount();
9282 var nearestSize = nearestPanel.getSize();
9283
9284 if (isOutOfBound) {
9285 var relativeHangerPosition = this.getRelativeHangerPosition();
9286
9287 if (nearestAnchorPos > nextRange + relativeHangerPosition) {
9288 // next bounce area: hangerPosition - relativeHangerPosition - nextRange
9289 hangerPosition = nearestAnchorPos + hangerPosition - relativeHangerPosition - nextRange;
9290 } else if (nearestAnchorPos < prevRange + relativeHangerPosition) {
9291 // prev bounce area: hangerPosition - relativeHangerPosition - prevRange
9292 hangerPosition = nearestAnchorPos + hangerPosition - relativeHangerPosition - prevRange;
9293 }
9294 }
9295
9296 var hangerIsNextToNearestPanel = hangerPosition >= nearestAnchorPos;
9297 var gap = this.options.gap;
9298 var basePosition = nearestAnchorPos;
9299 var targetPosition = nearestAnchorPos;
9300
9301 if (hangerIsNextToNearestPanel) {
9302 targetPosition = nextPanel ? nextPanel.getAnchorPosition() : nearestAnchorPos + nearestSize + gap;
9303 } else {
9304 basePosition = prevPanel ? prevPanel.getAnchorPosition() : nearestAnchorPos - nearestSize - gap;
9305 }
9306
9307 var progressBetween = (hangerPosition - basePosition) / (targetPosition - basePosition);
9308 var startIndex = hangerIsNextToNearestPanel ? nearestIndex : prevPanel ? prevPanel.getIndex() : nearestIndex - 1;
9309 return startIndex + progressBetween;
9310 }; // Update axes flick position without triggering event
9311
9312
9313 __proto.updateAxesPosition = function (position) {
9314 var axes = this.axes;
9315 axes.off();
9316 axes.setTo({
9317 flick: position
9318 }, 0);
9319 axes.on(this.axesHandlers);
9320 };
9321
9322 __proto.getSize = function () {
9323 return this.state.size;
9324 };
9325
9326 __proto.getScrollArea = function () {
9327 return this.state.scrollArea;
9328 };
9329
9330 __proto.isOutOfBound = function () {
9331 var state = this.state;
9332 var options = this.options;
9333 var scrollArea = state.scrollArea;
9334 return !options.circular && options.bound && (state.position <= scrollArea.prev || state.position >= scrollArea.next);
9335 };
9336
9337 __proto.canSetBoundMode = function () {
9338 var options = this.options;
9339 return options.bound && !options.circular;
9340 };
9341
9342 __proto.getViewportElement = function () {
9343 return this.viewportElement;
9344 };
9345
9346 __proto.getCameraElement = function () {
9347 return this.cameraElement;
9348 };
9349
9350 __proto.getScrollAreaSize = function () {
9351 var scrollArea = this.state.scrollArea;
9352 return scrollArea.next - scrollArea.prev;
9353 };
9354
9355 __proto.getRelativeHangerPosition = function () {
9356 return this.state.relativeHangerPosition;
9357 };
9358
9359 __proto.getHangerPosition = function () {
9360 return this.state.position + this.state.relativeHangerPosition;
9361 };
9362
9363 __proto.getCameraPosition = function () {
9364 return this.state.position;
9365 };
9366
9367 __proto.getPositionOffset = function () {
9368 return this.state.positionOffset;
9369 };
9370
9371 __proto.getCheckedIndexes = function () {
9372 return this.state.checkedIndexes;
9373 };
9374
9375 __proto.getVisiblePanels = function () {
9376 return this.visiblePanels;
9377 };
9378
9379 __proto.setCurrentPanel = function (panel) {
9380 this.currentPanel = panel;
9381 };
9382
9383 __proto.setLastIndex = function (index) {
9384 var currentPanel = this.currentPanel;
9385 var panelManager = this.panelManager;
9386 panelManager.setLastIndex(index);
9387
9388 if (currentPanel && currentPanel.getIndex() > index) {
9389 this.currentPanel = panelManager.lastPanel();
9390 }
9391
9392 this.resize();
9393 };
9394
9395 __proto.setVisiblePanels = function (panels) {
9396 this.visiblePanels = panels;
9397 };
9398
9399 __proto.connectAxesHandler = function (handlers) {
9400 var axes = this.axes;
9401 this.axesHandlers = handlers;
9402 axes.on(handlers);
9403 };
9404
9405 __proto.addPlugins = function (plugins) {
9406 var _this = this;
9407
9408 var newPlugins = [].concat(plugins);
9409 newPlugins.forEach(function (plugin) {
9410 plugin.init(_this.flicking);
9411 });
9412 this.plugins = this.plugins.concat(newPlugins);
9413 return this;
9414 };
9415
9416 __proto.removePlugins = function (plugins) {
9417 var _this = this;
9418
9419 var currentPlugins = this.plugins;
9420 var removedPlugins = [].concat(plugins);
9421 removedPlugins.forEach(function (plugin) {
9422 var index = currentPlugins.indexOf(plugin);
9423
9424 if (index > -1) {
9425 currentPlugins.splice(index, 1);
9426 }
9427
9428 plugin.destroy(_this.flicking);
9429 });
9430 return this;
9431 };
9432
9433 __proto.updateCheckedIndexes = function (changedRange) {
9434 var state = this.state;
9435 var removed = 0;
9436 state.checkedIndexes.concat().forEach(function (indexes, idx) {
9437 var min = indexes[0],
9438 max = indexes[1]; // Can fill part of indexes in range
9439
9440 if (changedRange.min <= max && changedRange.max >= min) {
9441 // Remove checked index from list
9442 state.checkedIndexes.splice(idx - removed, 1);
9443 removed++;
9444 }
9445 });
9446 };
9447
9448 __proto.appendUncachedPanelElements = function (panels) {
9449 var _this = this;
9450
9451 var options = this.options;
9452 var fragment = document.createDocumentFragment();
9453
9454 if (options.isEqualSize) {
9455 var prevVisiblePanels = this.visiblePanels;
9456 var equalSizeClasses_1 = options.isEqualSize; // for readability
9457
9458 var cached_1 = {};
9459 this.visiblePanels = [];
9460 Object.keys(this.panelBboxes).forEach(function (className) {
9461 cached_1[className] = true;
9462 });
9463 panels.forEach(function (panel) {
9464 var overlappedClass = panel.getOverlappedClass(equalSizeClasses_1);
9465
9466 if (overlappedClass && !cached_1[overlappedClass]) {
9467 if (!options.renderExternal) {
9468 fragment.appendChild(panel.getElement());
9469 }
9470
9471 _this.visiblePanels.push(panel);
9472
9473 cached_1[overlappedClass] = true;
9474 } else if (!overlappedClass) {
9475 if (!options.renderExternal) {
9476 fragment.appendChild(panel.getElement());
9477 }
9478
9479 _this.visiblePanels.push(panel);
9480 }
9481 });
9482 prevVisiblePanels.forEach(function (panel) {
9483 _this.addVisiblePanel(panel);
9484 });
9485 } else {
9486 if (!options.renderExternal) {
9487 panels.forEach(function (panel) {
9488 return fragment.appendChild(panel.getElement());
9489 });
9490 }
9491
9492 this.visiblePanels = panels.filter(function (panel) {
9493 return Boolean(panel);
9494 });
9495 }
9496
9497 if (!options.renderExternal) {
9498 this.cameraElement.appendChild(fragment);
9499 }
9500 };
9501
9502 __proto.updateClonePanels = function () {
9503 var panelManager = this.panelManager; // Clone panels in circular mode
9504
9505 if (this.options.circular && panelManager.getPanelCount() > 0) {
9506 this.clonePanels();
9507 this.updateClonedPanelPositions();
9508 }
9509
9510 panelManager.chainAllPanels();
9511 };
9512
9513 __proto.getVisibleIndexOf = function (panel) {
9514 return findIndex(this.visiblePanels, function (visiblePanel) {
9515 return visiblePanel === panel;
9516 });
9517 };
9518
9519 __proto.build = function () {
9520 this.setElements();
9521 this.applyCSSValue();
9522 this.setMoveType();
9523 this.setAxesInstance();
9524 this.refreshPanels();
9525 this.setDefaultPanel();
9526 this.resize();
9527 this.moveToDefaultPanel();
9528 };
9529
9530 __proto.setElements = function () {
9531 var state = this.state;
9532 var options = this.options;
9533 var wrapper = this.flicking.getElement();
9534 var classPrefix = options.classPrefix;
9535 var viewportCandidate = wrapper.children[0];
9536 var hasViewportElement = viewportCandidate && hasClass(viewportCandidate, classPrefix + "-viewport");
9537 var viewportElement = hasViewportElement ? viewportCandidate : document.createElement("div");
9538 var cameraCandidate = hasViewportElement ? viewportElement.children[0] : wrapper.children[0];
9539 var hasCameraElement = cameraCandidate && hasClass(cameraCandidate, classPrefix + "-camera");
9540 var cameraElement = hasCameraElement ? cameraCandidate : document.createElement("div");
9541
9542 if (!hasCameraElement) {
9543 cameraElement.className = classPrefix + "-camera";
9544 var panelElements = hasViewportElement ? viewportElement.children : wrapper.children; // Make all panels to be a child of camera element
9545 // wrapper <- viewport <- camera <- panels[1...n]
9546
9547 toArray$3(panelElements).forEach(function (child) {
9548 cameraElement.appendChild(child);
9549 });
9550 } else {
9551 state.originalCameraStyle = {
9552 className: cameraElement.getAttribute("class"),
9553 style: cameraElement.getAttribute("style")
9554 };
9555 }
9556
9557 if (!hasViewportElement) {
9558 viewportElement.className = classPrefix + "-viewport"; // Add viewport element to wrapper
9559
9560 wrapper.appendChild(viewportElement);
9561 } else {
9562 state.originalViewportStyle = {
9563 className: viewportElement.getAttribute("class"),
9564 style: viewportElement.getAttribute("style")
9565 };
9566 }
9567
9568 if (!hasCameraElement || !hasViewportElement) {
9569 viewportElement.appendChild(cameraElement);
9570 }
9571
9572 this.viewportElement = viewportElement;
9573 this.cameraElement = cameraElement;
9574 state.isViewportGiven = hasViewportElement;
9575 state.isCameraGiven = hasCameraElement;
9576 };
9577
9578 __proto.applyCSSValue = function () {
9579 var options = this.options;
9580 var viewportElement = this.viewportElement;
9581 var cameraElement = this.cameraElement;
9582 var viewportStyle = this.viewportElement.style; // Set default css values for each element
9583
9584 applyCSS(viewportElement, DEFAULT_VIEWPORT_CSS);
9585 applyCSS(cameraElement, DEFAULT_CAMERA_CSS);
9586 viewportElement.style.zIndex = "" + options.zIndex;
9587
9588 if (options.horizontal) {
9589 viewportStyle.minHeight = "100%";
9590 viewportStyle.width = "100%";
9591 } else {
9592 viewportStyle.minWidth = "100%";
9593 viewportStyle.height = "100%";
9594 }
9595
9596 if (options.overflow) {
9597 viewportStyle.overflow = "visible";
9598 }
9599
9600 this.panelManager = new PanelManager(this.cameraElement, options);
9601 };
9602
9603 __proto.setMoveType = function () {
9604 var moveType = this.options.moveType;
9605
9606 switch (moveType.type) {
9607 case MOVE_TYPE.SNAP:
9608 this.moveType = new Snap(moveType.count);
9609 break;
9610
9611 case MOVE_TYPE.FREE_SCROLL:
9612 this.moveType = new FreeScroll();
9613 break;
9614
9615 default:
9616 throw new Error("moveType is not correct!");
9617 }
9618 };
9619
9620 __proto.setAxesInstance = function () {
9621 var state = this.state;
9622 var options = this.options;
9623 var scrollArea = state.scrollArea;
9624 this.axes = new Axes({
9625 flick: {
9626 range: [scrollArea.prev, scrollArea.next],
9627 circular: options.circular,
9628 bounce: [0, 0]
9629 }
9630 }, {
9631 easing: options.panelEffect,
9632 deceleration: options.deceleration,
9633 interruptable: true
9634 });
9635 this.createPanInput();
9636 };
9637
9638 __proto.refreshPanels = function () {
9639 var _this = this;
9640
9641 var panelManager = this.panelManager; // Panel elements were attached to camera element by Flicking class
9642
9643 var panelElements = this.cameraElement.children; // Initialize panels
9644
9645 var panels = toArray$3(panelElements).map(function (el, idx) {
9646 return new Panel(el, idx, _this);
9647 });
9648 panelManager.replacePanels(panels, []);
9649 this.visiblePanels = panels.filter(function (panel) {
9650 return Boolean(panel);
9651 });
9652 };
9653
9654 __proto.setDefaultPanel = function () {
9655 var options = this.options;
9656 var panelManager = this.panelManager;
9657 var indexRange = this.panelManager.getRange();
9658 var index = clamp(options.defaultIndex, indexRange.min, indexRange.max);
9659 this.currentPanel = panelManager.get(index);
9660 };
9661
9662 __proto.clonePanels = function () {
9663 var state = this.state;
9664 var options = this.options;
9665 var panelManager = this.panelManager;
9666 var gap = options.gap;
9667 var viewportSize = state.size;
9668 var firstPanel = panelManager.firstPanel();
9669 var lastPanel = panelManager.lastPanel(); // There're no panels exist
9670
9671 if (!firstPanel) {
9672 return;
9673 } // For each panels, clone itself while last panel's position + size is below viewport size
9674
9675
9676 var panels = panelManager.originalPanels();
9677 var reversedPanels = panels.concat().reverse();
9678 var sumOriginalPanelSize = lastPanel.getPosition() + lastPanel.getSize() - firstPanel.getPosition() + gap;
9679 var relativeAnchorPosition = firstPanel.getRelativeAnchorPosition();
9680 var relativeHangerPosition = this.getRelativeHangerPosition();
9681 var areaPrev = (relativeHangerPosition - relativeAnchorPosition) % sumOriginalPanelSize;
9682 var sizeSum = 0;
9683 var panelAtLeftBoundary;
9684
9685 for (var _i = 0, reversedPanels_1 = reversedPanels; _i < reversedPanels_1.length; _i++) {
9686 var panel = reversedPanels_1[_i];
9687
9688 if (!panel) {
9689 continue;
9690 }
9691
9692 sizeSum += panel.getSize() + gap;
9693
9694 if (sizeSum >= areaPrev) {
9695 panelAtLeftBoundary = panel;
9696 break;
9697 }
9698 }
9699
9700 var areaNext = (viewportSize - relativeHangerPosition + relativeAnchorPosition) % sumOriginalPanelSize;
9701 sizeSum = 0;
9702 var panelAtRightBoundary;
9703
9704 for (var _a = 0, panels_1 = panels; _a < panels_1.length; _a++) {
9705 var panel = panels_1[_a];
9706
9707 if (!panel) {
9708 continue;
9709 }
9710
9711 sizeSum += panel.getSize() + gap;
9712
9713 if (sizeSum >= areaNext) {
9714 panelAtRightBoundary = panel;
9715 break;
9716 }
9717 } // Need one more set of clones on prev area of original panel 0
9718
9719
9720 var needCloneOnPrev = panelAtLeftBoundary.getIndex() !== 0 && panelAtLeftBoundary.getIndex() <= panelAtRightBoundary.getIndex(); // Visible count of panel 0 on first screen
9721
9722 var panel0OnFirstscreen = Math.ceil((relativeHangerPosition + firstPanel.getSize() - relativeAnchorPosition) / sumOriginalPanelSize) + Math.ceil((viewportSize - relativeHangerPosition + relativeAnchorPosition) / sumOriginalPanelSize) - 1; // duplication
9723
9724 var cloneCount = panel0OnFirstscreen + (needCloneOnPrev ? 1 : 0);
9725 var prevCloneCount = panelManager.getCloneCount();
9726 panelManager.setCloneCount(cloneCount);
9727
9728 if (options.renderExternal) {
9729 return;
9730 }
9731
9732 if (cloneCount > prevCloneCount) {
9733 var _loop_1 = function (cloneIndex) {
9734 var _a;
9735
9736 var clones = panels.map(function (origPanel) {
9737 return origPanel.clone(cloneIndex);
9738 });
9739 var fragment = document.createDocumentFragment();
9740 clones.forEach(function (panel) {
9741 return fragment.appendChild(panel.getElement());
9742 });
9743 this_1.cameraElement.appendChild(fragment);
9744
9745 (_a = this_1.visiblePanels).push.apply(_a, clones.filter(function (clone) {
9746 return Boolean(clone);
9747 }));
9748
9749 panelManager.insertClones(cloneIndex, 0, clones);
9750 };
9751
9752 var this_1 = this; // should clone more
9753
9754 for (var cloneIndex = prevCloneCount; cloneIndex < cloneCount; cloneIndex++) {
9755 _loop_1(cloneIndex);
9756 }
9757 } else if (cloneCount < prevCloneCount) {
9758 // should remove some
9759 panelManager.removeClonesAfter(cloneCount);
9760 }
9761 };
9762
9763 __proto.moveToDefaultPanel = function () {
9764 var state = this.state;
9765 var panelManager = this.panelManager;
9766 var options = this.options;
9767 var indexRange = this.panelManager.getRange();
9768 var defaultIndex = clamp(options.defaultIndex, indexRange.min, indexRange.max);
9769 var defaultPanel = panelManager.get(defaultIndex);
9770 var defaultPosition = 0;
9771
9772 if (defaultPanel) {
9773 defaultPosition = defaultPanel.getAnchorPosition() - state.relativeHangerPosition;
9774 defaultPosition = this.canSetBoundMode() ? clamp(defaultPosition, state.scrollArea.prev, state.scrollArea.next) : defaultPosition;
9775 }
9776
9777 this.moveCamera(defaultPosition);
9778 this.axes.setTo({
9779 flick: defaultPosition
9780 }, 0);
9781 };
9782
9783 __proto.updateSize = function () {
9784 var state = this.state;
9785 var options = this.options;
9786 var panels = this.panelManager.originalPanels().filter(function (panel) {
9787 return Boolean(panel);
9788 });
9789 var bbox = this.updateBbox();
9790 var prevSize = state.size; // Update size & hanger position
9791
9792 state.size = options.horizontal ? bbox.width : bbox.height;
9793
9794 if (prevSize !== state.size) {
9795 state.relativeHangerPosition = parseArithmeticExpression(options.hanger, state.size);
9796 state.infiniteThreshold = parseArithmeticExpression(options.infiniteThreshold, state.size);
9797 }
9798
9799 if (panels.length <= 0) {
9800 return;
9801 }
9802
9803 this.resizePanels(panels);
9804 };
9805
9806 __proto.updateOriginalPanelPositions = function () {
9807 var gap = this.options.gap;
9808 var panelManager = this.panelManager;
9809 var firstPanel = panelManager.firstPanel();
9810 var panels = panelManager.originalPanels();
9811
9812 if (!firstPanel) {
9813 return;
9814 }
9815
9816 var currentPanel = this.currentPanel;
9817 var nearestPanel = this.nearestPanel;
9818 var currentState = this.stateMachine.getState();
9819 var scrollArea = this.state.scrollArea; // Update panel position && fit to wrapper
9820
9821 var nextPanelPos = firstPanel.getPosition();
9822 var maintainingPanel = firstPanel;
9823
9824 if (nearestPanel) {
9825 // We should maintain nearestPanel's position
9826 var looped = !isBetween(currentState.lastPosition + currentState.delta, scrollArea.prev, scrollArea.next);
9827 maintainingPanel = looped ? currentPanel : nearestPanel;
9828 } else if (firstPanel.getIndex() > 0) {
9829 maintainingPanel = currentPanel;
9830 }
9831
9832 var panelsBeforeMaintainPanel = panels.slice(0, maintainingPanel.getIndex() + (maintainingPanel.getCloneIndex() + 1) * panels.length);
9833 var accumulatedSize = panelsBeforeMaintainPanel.reduce(function (total, panel) {
9834 return total + panel.getSize() + gap;
9835 }, 0);
9836 nextPanelPos = maintainingPanel.getPosition() - accumulatedSize;
9837 panels.forEach(function (panel) {
9838 var newPosition = nextPanelPos;
9839 var panelSize = panel.getSize();
9840 panel.setPosition(newPosition);
9841 nextPanelPos += panelSize + gap;
9842 });
9843
9844 if (!this.options.renderOnlyVisible) {
9845 panels.forEach(function (panel) {
9846 return panel.setPositionCSS();
9847 });
9848 }
9849 };
9850
9851 __proto.updateClonedPanelPositions = function () {
9852 var state = this.state;
9853 var options = this.options;
9854 var panelManager = this.panelManager;
9855 var clonedPanels = panelManager.clonedPanels().reduce(function (allClones, clones) {
9856 return __spreadArrays(allClones, clones);
9857 }, []).filter(function (panel) {
9858 return Boolean(panel);
9859 });
9860 var scrollArea = state.scrollArea;
9861 var firstPanel = panelManager.firstPanel();
9862 var lastPanel = panelManager.lastPanel();
9863
9864 if (!firstPanel) {
9865 return;
9866 }
9867
9868 var sumOriginalPanelSize = lastPanel.getPosition() + lastPanel.getSize() - firstPanel.getPosition() + options.gap; // Locate all cloned panels linearly first
9869
9870 for (var _i = 0, clonedPanels_1 = clonedPanels; _i < clonedPanels_1.length; _i++) {
9871 var panel = clonedPanels_1[_i];
9872 var origPanel = panel.getOriginalPanel();
9873 var cloneIndex = panel.getCloneIndex();
9874 var cloneBasePos = sumOriginalPanelSize * (cloneIndex + 1);
9875 var clonedPanelPos = cloneBasePos + origPanel.getPosition();
9876 panel.setPosition(clonedPanelPos);
9877 }
9878
9879 var lastReplacePosition = firstPanel.getPosition(); // reverse() pollutes original array, so copy it with concat()
9880
9881 for (var _a = 0, _b = clonedPanels.concat().reverse(); _a < _b.length; _a++) {
9882 var panel = _b[_a];
9883 var panelSize = panel.getSize();
9884 var replacePosition = lastReplacePosition - panelSize - options.gap;
9885
9886 if (replacePosition + panelSize <= scrollArea.prev) {
9887 // Replace is not meaningful, as it won't be seen in current scroll area
9888 break;
9889 }
9890
9891 panel.setPosition(replacePosition);
9892 lastReplacePosition = replacePosition;
9893 }
9894
9895 if (!this.options.renderOnlyVisible) {
9896 clonedPanels.forEach(function (panel) {
9897 panel.setPositionCSS();
9898 });
9899 }
9900 };
9901
9902 __proto.updateVisiblePanelPositions = function () {
9903 var _this = this;
9904
9905 if (this.options.renderOnlyVisible) {
9906 this.visiblePanels.forEach(function (panel) {
9907 panel.setPositionCSS(_this.state.positionOffset);
9908 });
9909 }
9910 };
9911
9912 __proto.updateScrollArea = function () {
9913 var state = this.state;
9914 var panelManager = this.panelManager;
9915 var options = this.options;
9916 var axes = this.axes; // Set viewport scrollable area
9917
9918 var firstPanel = panelManager.firstPanel();
9919 var lastPanel = panelManager.lastPanel();
9920 var relativeHangerPosition = state.relativeHangerPosition;
9921
9922 if (!firstPanel) {
9923 state.scrollArea = {
9924 prev: 0,
9925 next: 0
9926 };
9927 } else if (this.canSetBoundMode()) {
9928 var sumOriginalPanelSize = lastPanel.getPosition() + lastPanel.getSize() - firstPanel.getPosition();
9929
9930 if (sumOriginalPanelSize >= state.size) {
9931 state.scrollArea = {
9932 prev: firstPanel.getPosition(),
9933 next: lastPanel.getPosition() + lastPanel.getSize() - state.size
9934 };
9935 } else {
9936 // Find anchor position of set of the combined panels
9937 var relAnchorPosOfCombined = parseArithmeticExpression(options.anchor, sumOriginalPanelSize);
9938 var anchorPos = firstPanel.getPosition() + clamp(relAnchorPosOfCombined, sumOriginalPanelSize - (state.size - relativeHangerPosition), relativeHangerPosition);
9939 state.scrollArea = {
9940 prev: anchorPos - relativeHangerPosition,
9941 next: anchorPos - relativeHangerPosition
9942 };
9943 }
9944 } else if (options.circular) {
9945 var sumOriginalPanelSize = lastPanel.getPosition() + lastPanel.getSize() - firstPanel.getPosition() + options.gap; // Maximum scroll extends to first clone sequence's first panel
9946
9947 state.scrollArea = {
9948 prev: firstPanel.getAnchorPosition() - relativeHangerPosition,
9949 next: sumOriginalPanelSize + firstPanel.getAnchorPosition() - relativeHangerPosition
9950 };
9951 } else {
9952 state.scrollArea = {
9953 prev: firstPanel.getAnchorPosition() - relativeHangerPosition,
9954 next: lastPanel.getAnchorPosition() - relativeHangerPosition
9955 };
9956 }
9957
9958 var viewportSize = state.size;
9959 var bounce = options.bounce;
9960 var parsedBounce;
9961
9962 if (isArray(bounce)) {
9963 parsedBounce = bounce.map(function (val) {
9964 return parseArithmeticExpression(val, viewportSize, DEFAULT_OPTIONS.bounce);
9965 });
9966 } else {
9967 var parsedVal = parseArithmeticExpression(bounce, viewportSize, DEFAULT_OPTIONS.bounce);
9968 parsedBounce = [parsedVal, parsedVal];
9969 } // Update axes range and bounce
9970
9971
9972 var flick = axes.axis.flick;
9973 flick.range = [state.scrollArea.prev, state.scrollArea.next];
9974 flick.bounce = parsedBounce;
9975 };
9976
9977 __proto.checkNeedPanel = function (axesEvent) {
9978 var state = this.state;
9979 var options = this.options;
9980 var panelManager = this.panelManager;
9981 var currentPanel = this.currentPanel;
9982 var nearestPanel = this.nearestPanel;
9983 var currentState = this.stateMachine.getState();
9984
9985 if (!options.infinite) {
9986 return;
9987 }
9988
9989 var gap = options.gap;
9990 var infiniteThreshold = state.infiniteThreshold;
9991 var maxLastIndex = panelManager.getLastIndex();
9992
9993 if (maxLastIndex < 0) {
9994 return;
9995 }
9996
9997 if (!currentPanel || !nearestPanel) {
9998 // There're no panels
9999 this.triggerNeedPanel({
10000 axesEvent: axesEvent,
10001 siblingPanel: null,
10002 direction: null,
10003 indexRange: {
10004 min: 0,
10005 max: maxLastIndex,
10006 length: maxLastIndex + 1
10007 }
10008 });
10009 return;
10010 }
10011
10012 var originalNearestPosition = nearestPanel.getPosition(); // Check next direction
10013
10014 var checkingPanel = !currentState.holding && !currentState.playing ? currentPanel : nearestPanel;
10015
10016 while (checkingPanel) {
10017 var currentIndex = checkingPanel.getIndex();
10018 var nextSibling = checkingPanel.nextSibling;
10019 var lastPanel = panelManager.lastPanel();
10020 var atLastPanel = currentIndex === lastPanel.getIndex();
10021 var nextIndex = !atLastPanel && nextSibling ? nextSibling.getIndex() : maxLastIndex + 1;
10022 var currentNearestPosition = nearestPanel.getPosition();
10023 var panelRight = checkingPanel.getPosition() + checkingPanel.getSize() - (currentNearestPosition - originalNearestPosition);
10024 var cameraNext = state.position + state.size; // There're empty panels between
10025
10026 var emptyPanelExistsBetween = nextIndex - currentIndex > 1; // Expected prev panel's left position is smaller than camera position
10027
10028 var overThreshold = panelRight + gap - infiniteThreshold <= cameraNext;
10029
10030 if (emptyPanelExistsBetween && overThreshold) {
10031 this.triggerNeedPanel({
10032 axesEvent: axesEvent,
10033 siblingPanel: checkingPanel,
10034 direction: DIRECTION.NEXT,
10035 indexRange: {
10036 min: currentIndex + 1,
10037 max: nextIndex - 1,
10038 length: nextIndex - currentIndex - 1
10039 }
10040 });
10041 } // Trigger needPanel in circular & at max panel index
10042
10043
10044 if (options.circular && currentIndex === maxLastIndex && overThreshold) {
10045 var firstPanel = panelManager.firstPanel();
10046 var firstIndex = firstPanel ? firstPanel.getIndex() : -1;
10047
10048 if (firstIndex > 0) {
10049 this.triggerNeedPanel({
10050 axesEvent: axesEvent,
10051 siblingPanel: checkingPanel,
10052 direction: DIRECTION.NEXT,
10053 indexRange: {
10054 min: 0,
10055 max: firstIndex - 1,
10056 length: firstIndex
10057 }
10058 });
10059 }
10060 } // Check whether panels are changed
10061
10062
10063 var lastPanelAfterNeed = panelManager.lastPanel();
10064 var atLastPanelAfterNeed = lastPanelAfterNeed && currentIndex === lastPanelAfterNeed.getIndex();
10065
10066 if (atLastPanelAfterNeed || !overThreshold) {
10067 break;
10068 }
10069
10070 checkingPanel = checkingPanel.nextSibling;
10071 } // Check prev direction
10072
10073
10074 checkingPanel = nearestPanel;
10075
10076 while (checkingPanel) {
10077 var cameraPrev = state.position;
10078 var checkingIndex = checkingPanel.getIndex();
10079 var prevSibling = checkingPanel.prevSibling;
10080 var firstPanel = panelManager.firstPanel();
10081 var atFirstPanel = checkingIndex === firstPanel.getIndex();
10082 var prevIndex = !atFirstPanel && prevSibling ? prevSibling.getIndex() : -1;
10083 var currentNearestPosition = nearestPanel.getPosition();
10084 var panelLeft = checkingPanel.getPosition() - (currentNearestPosition - originalNearestPosition); // There're empty panels between
10085
10086 var emptyPanelExistsBetween = checkingIndex - prevIndex > 1; // Expected prev panel's right position is smaller than camera position
10087
10088 var overThreshold = panelLeft - gap + infiniteThreshold >= cameraPrev;
10089
10090 if (emptyPanelExistsBetween && overThreshold) {
10091 this.triggerNeedPanel({
10092 axesEvent: axesEvent,
10093 siblingPanel: checkingPanel,
10094 direction: DIRECTION.PREV,
10095 indexRange: {
10096 min: prevIndex + 1,
10097 max: checkingIndex - 1,
10098 length: checkingIndex - prevIndex - 1
10099 }
10100 });
10101 } // Trigger needPanel in circular & at panel 0
10102
10103
10104 if (options.circular && checkingIndex === 0 && overThreshold) {
10105 var lastPanel = panelManager.lastPanel();
10106
10107 if (lastPanel && lastPanel.getIndex() < maxLastIndex) {
10108 var lastIndex = lastPanel.getIndex();
10109 this.triggerNeedPanel({
10110 axesEvent: axesEvent,
10111 siblingPanel: checkingPanel,
10112 direction: DIRECTION.PREV,
10113 indexRange: {
10114 min: lastIndex + 1,
10115 max: maxLastIndex,
10116 length: maxLastIndex - lastIndex
10117 }
10118 });
10119 }
10120 } // Check whether panels were changed
10121
10122
10123 var firstPanelAfterNeed = panelManager.firstPanel();
10124 var atFirstPanelAfterNeed = firstPanelAfterNeed && checkingIndex === firstPanelAfterNeed.getIndex(); // Looped in circular mode
10125
10126 if (atFirstPanelAfterNeed || !overThreshold) {
10127 break;
10128 }
10129
10130 checkingPanel = checkingPanel.prevSibling;
10131 }
10132 };
10133
10134 __proto.triggerNeedPanel = function (params) {
10135 var _this = this;
10136
10137 var axesEvent = params.axesEvent,
10138 siblingPanel = params.siblingPanel,
10139 direction = params.direction,
10140 indexRange = params.indexRange;
10141 var options = this.options;
10142 var checkedIndexes = this.state.checkedIndexes;
10143 var alreadyTriggered = checkedIndexes.some(function (_a) {
10144 var min = _a[0],
10145 max = _a[1];
10146 return min === indexRange.min || max === indexRange.max;
10147 });
10148 var hasHandler = this.flicking.hasOn(EVENTS.NEED_PANEL);
10149
10150 if (alreadyTriggered || !hasHandler) {
10151 return;
10152 } // Should done before triggering event, as we can directly add panels by event callback
10153
10154
10155 checkedIndexes.push([indexRange.min, indexRange.max]);
10156 var index = siblingPanel ? siblingPanel.getIndex() : 0;
10157 var isTrusted = axesEvent ? axesEvent.isTrusted : false;
10158 this.triggerEvent(EVENTS.NEED_PANEL, axesEvent, isTrusted, {
10159 index: index,
10160 panel: siblingPanel,
10161 direction: direction,
10162 range: indexRange,
10163 fill: function (element) {
10164 var panelManager = _this.panelManager;
10165
10166 if (!siblingPanel) {
10167 return _this.insert(panelManager.getRange().max + 1, element);
10168 }
10169
10170 var parsedElements = parseElement(element); // Slice elements to fit size equal to empty spaces
10171
10172 var elements = direction === DIRECTION.NEXT ? parsedElements.slice(0, indexRange.length) : parsedElements.slice(-indexRange.length);
10173
10174 if (direction === DIRECTION.NEXT) {
10175 if (options.circular && index === panelManager.getLastIndex()) {
10176 // needPanel event is triggered on last index, insert at index 0
10177 return _this.insert(0, elements);
10178 } else {
10179 return siblingPanel.insertAfter(elements);
10180 }
10181 } else if (direction === DIRECTION.PREV) {
10182 if (options.circular && index === 0) {
10183 // needPanel event is triggered on first index(0), insert at the last index
10184 return _this.insert(indexRange.max - elements.length + 1, elements);
10185 } else {
10186 return siblingPanel.insertBefore(elements);
10187 }
10188 } else {
10189 // direction is null when there're no panels exist
10190 return _this.insert(0, elements);
10191 }
10192 }
10193 });
10194 };
10195
10196 __proto.updateVisiblePanels = function () {
10197 var state = this.state;
10198 var options = this.options;
10199 var panelManager = this.panelManager;
10200 var currentState = this.stateMachine.getState();
10201 var cameraElement = this.cameraElement;
10202 var renderExternal = options.renderExternal,
10203 renderOnlyVisible = options.renderOnlyVisible;
10204
10205 if (!renderOnlyVisible) {
10206 return;
10207 }
10208
10209 if (!this.nearestPanel) {
10210 this.visiblePanels = [];
10211
10212 while (cameraElement.firstChild) {
10213 cameraElement.removeChild(cameraElement.firstChild);
10214 }
10215
10216 return;
10217 }
10218
10219 var prevVisiblePanels = this.visiblePanels;
10220 var newVisiblePanels = this.calcVisiblePanels();
10221
10222 var _a = this.checkVisiblePanelChange(prevVisiblePanels, newVisiblePanels),
10223 addedPanels = _a.addedPanels,
10224 removedPanels = _a.removedPanels;
10225
10226 if (addedPanels.length <= 0 && removedPanels.length <= 0) {
10227 // Visible panels not changed
10228 return;
10229 }
10230
10231 if (currentState.holding) {
10232 newVisiblePanels.push.apply(newVisiblePanels, removedPanels);
10233 } else {
10234 var firstVisiblePanelPos = newVisiblePanels[0].getPosition();
10235 state.positionOffset = firstVisiblePanelPos;
10236 }
10237
10238 newVisiblePanels.forEach(function (panel) {
10239 panel.setPositionCSS(state.positionOffset);
10240 });
10241
10242 if (!renderExternal) {
10243 if (!currentState.holding) {
10244 removedPanels.forEach(function (panel) {
10245 var panelElement = panel.getElement();
10246 panelElement.parentNode && cameraElement.removeChild(panelElement);
10247 });
10248 }
10249
10250 var fragment_1 = document.createDocumentFragment();
10251 addedPanels.forEach(function (panel) {
10252 fragment_1.appendChild(panel.getElement());
10253 });
10254 cameraElement.appendChild(fragment_1);
10255 }
10256
10257 var firstVisiblePanel = newVisiblePanels[0];
10258 var lastVisiblePanel = newVisiblePanels[newVisiblePanels.length - 1];
10259
10260 var getAbsIndex = function (panel) {
10261 return panel.getIndex() + (panel.getCloneIndex() + 1) * panelManager.getPanelCount();
10262 };
10263
10264 var newVisibleRange = {
10265 min: getAbsIndex(firstVisiblePanel),
10266 max: getAbsIndex(lastVisiblePanel)
10267 };
10268 this.visiblePanels = newVisiblePanels;
10269 this.flicking.trigger(EVENTS.VISIBLE_CHANGE, {
10270 type: EVENTS.VISIBLE_CHANGE,
10271 range: newVisibleRange
10272 });
10273 };
10274
10275 __proto.checkVisiblePanelChange = function (prevVisiblePanels, newVisiblePanels) {
10276 var prevRefCount = prevVisiblePanels.map(function () {
10277 return 0;
10278 });
10279 var newRefCount = newVisiblePanels.map(function () {
10280 return 0;
10281 });
10282 prevVisiblePanels.forEach(function (prevPanel, prevIndex) {
10283 newVisiblePanels.forEach(function (newPanel, newIndex) {
10284 if (prevPanel === newPanel) {
10285 prevRefCount[prevIndex]++;
10286 newRefCount[newIndex]++;
10287 }
10288 });
10289 });
10290 var removedPanels = prevRefCount.reduce(function (removed, count, index) {
10291 return count === 0 ? __spreadArrays(removed, [prevVisiblePanels[index]]) : removed;
10292 }, []);
10293 var addedPanels = newRefCount.reduce(function (added, count, index) {
10294 return count === 0 ? __spreadArrays(added, [newVisiblePanels[index]]) : added;
10295 }, []);
10296 return {
10297 removedPanels: removedPanels,
10298 addedPanels: addedPanels
10299 };
10300 };
10301
10302 __proto.resizePanels = function (panels) {
10303 var options = this.options;
10304 var panelBboxes = this.panelBboxes;
10305
10306 if (options.isEqualSize === true) {
10307 if (!panelBboxes.default) {
10308 var defaultPanel = panels[0];
10309 panelBboxes.default = defaultPanel.getBbox();
10310 }
10311
10312 var defaultBbox_1 = panelBboxes.default;
10313 panels.forEach(function (panel) {
10314 panel.resize(defaultBbox_1);
10315 });
10316 return;
10317 } else if (options.isEqualSize) {
10318 var equalSizeClasses_2 = options.isEqualSize;
10319 panels.forEach(function (panel) {
10320 var overlappedClass = panel.getOverlappedClass(equalSizeClasses_2);
10321
10322 if (overlappedClass) {
10323 panel.resize(panelBboxes[overlappedClass]);
10324 panelBboxes[overlappedClass] = panel.getBbox();
10325 } else {
10326 panel.resize();
10327 }
10328 });
10329 return;
10330 }
10331
10332 panels.forEach(function (panel) {
10333 panel.resize();
10334 });
10335 };
10336
10337 __proto.createPanInput = function () {
10338 var options = this.options;
10339 this.panInput = new PanInput(this.viewportElement, {
10340 inputType: options.inputType,
10341 thresholdAngle: options.thresholdAngle,
10342 iOSEdgeSwipeThreshold: options.iOSEdgeSwipeThreshold,
10343 scale: options.horizontal ? [-1, 0] : [0, -1]
10344 });
10345 this.axes.connect(options.horizontal ? ["flick", ""] : ["", "flick"], this.panInput);
10346 };
10347
10348 return Viewport;
10349 }();
10350
10351 /**
10352 * Copyright (c) 2015 NAVER Corp.
10353 * egjs projects are licensed under the MIT license
10354 */
10355 /**
10356 * @memberof eg
10357 * @extends eg.Component
10358 * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest" , "edge" : "latest", "ios" : "7+", "an" : "4.X+"}
10359 * @requires {@link https://github.com/naver/egjs-component|eg.Component}
10360 * @requires {@link https://github.com/naver/egjs-axes|eg.Axes}
10361 * @see Easing Functions Cheat Sheet {@link http://easings.net/} <ko>이징 함수 Cheat Sheet {@link http://easings.net/}</ko>
10362 */
10363
10364 var Flicking =
10365 /*#__PURE__*/
10366 function (_super) {
10367 __extends(Flicking, _super);
10368 /**
10369 * @param element A base element for the eg.Flicking module. When specifying a value as a `string` type, you must specify a css selector string to select the element.<ko>eg.Flicking 모듈을 사용할 기준 요소. `string`타입으로 값 지정시 요소를 선택하기 위한 css 선택자 문자열을 지정해야 한다.</ko>
10370 * @param options An option object of the eg.Flicking module<ko>eg.Flicking 모듈의 옵션 객체</ko>
10371 * @param {string} [options.classPrefix="eg-flick"] A prefix of class names will be added for the panels, viewport, and camera.<ko>패널들과 뷰포트, 카메라에 추가될 클래스 이름의 접두사.</ko>
10372 * @param {number} [options.deceleration=0.0075] Deceleration value for panel movement animation for animation triggered by manual user input. A higher value means a shorter running time.<ko>사용자의 동작으로 가속도가 적용된 패널 이동 애니메이션의 감속도. 값이 높을수록 애니메이션 실행 시간이 짧아진다.</ko>
10373 * @param {boolean} [options.horizontal=true] The direction of panel movement. (true: horizontal, false: vertical)<ko>패널 이동 방향. (true: 가로방향, false: 세로방향)</ko>
10374 * @param {boolean} [options.circular=false] Enables circular mode, which connects first/last panel for continuous scrolling.<ko>순환 모드를 활성화한다. 순환 모드에서는 양 끝의 패널이 서로 연결되어 끊김없는 스크롤이 가능하다.</ko>
10375 * @param {boolean} [options.infinite=false] Enables infinite mode, which can automatically trigger needPanel until reaching the last panel's index reaches the lastIndex.<ko>무한 모드를 활성화한다. 무한 모드에서는 needPanel 이벤트를 자동으로 트리거한다. 해당 동작은 마지막 패널의 인덱스가 lastIndex와 일치할때까지 일어난다.</ko>
10376 * @param {number} [options.infiniteThreshold=0] A Threshold from viewport edge before triggering `needPanel` event in infinite mode.<ko>무한 모드에서 `needPanel`이벤트가 발생하기 위한 뷰포트 끝으로부터의 최대 거리.</ko>
10377 * @param {number} [options.lastIndex=Infinity] Maximum panel index that Flicking can set. Flicking won't trigger `needPanel` when the event's panel index is greater than it.<br/>Also, if the last panel's index reached a given index, you can't add more panels.<ko>Flicking이 설정 가능한 패널의 최대 인덱스. `needPanel` 이벤트에 지정된 인덱스가 최대 패널의 개수보다 같거나 커야 하는 경우에 이벤트를 트리거하지 않게 한다.<br>또한, 마지막 패널의 인덱스가 주어진 인덱스와 동일할 경우, 새로운 패널을 더 이상 추가할 수 없다.</ko>
10378 * @param {number} [options.threshold=40] Movement threshold to change panel(unit: pixel). It should be dragged above the threshold to change the current panel.<ko>패널 변경을 위한 이동 임계값 (단위: 픽셀). 주어진 값 이상으로 스크롤해야만 패널 변경이 가능하다.</ko>
10379 * @param {number} [options.duration=100] Duration of the panel movement animation. (unit: ms)<ko>패널 이동 애니메이션 진행 시간.(단위: ms)</ko>
10380 * @param {function} [options.panelEffect=x => 1 - Math.pow(1 - x, 3)] An easing function applied to the panel movement animation. Default value is `easeOutCubic`.<ko>패널 이동 애니메이션에 적용할 easing함수. 기본값은 `easeOutCubic`이다.</ko>
10381 * @param {number} [options.defaultIndex=0] Index of the panel to set as default when initializing. A zero-based integer.<ko>초기화시 지정할 디폴트 패널의 인덱스로, 0부터 시작하는 정수.</ko>
10382 * @param {string[]} [options.inputType=["touch,"mouse"]] Types of input devices to enable.({@link https://naver.github.io/egjs-axes/release/latest/doc/global.html#PanInputOption Reference})<ko>활성화할 입력 장치 종류. ({@link https://naver.github.io/egjs-axes/release/latest/doc/global.html#PanInputOption 참고})</ko>
10383 * @param {number} [options.thresholdAngle=45] The threshold angle value(0 ~ 90).<br>If the input angle from click/touched position is above or below this value in horizontal and vertical mode each, scrolling won't happen.<ko>스크롤 동작을 막기 위한 임계각(0 ~ 90).<br>클릭/터치한 지점으로부터 계산된 사용자 입력의 각도가 horizontal/vertical 모드에서 각각 크거나 작으면, 스크롤 동작이 이루어지지 않는다.</ko>
10384 * @param {number|string|number[]|string[]} [options.bounce=[10,10]] The size value of the bounce area. Only can be enabled when `circular=false`.<br>You can set different bounce value for prev/next direction by using array.<br>`number` for px value, and `string` for px, and % value relative to viewport size.(ex - 0, "10px", "20%")<ko>바운스 영역의 크기값. `circular=false`인 경우에만 사용할 수 있다.<br>배열을 통해 prev/next 방향에 대해 서로 다른 바운스 값을 지정 가능하다.<br>`number`를 통해 px값을, `stirng`을 통해 px 혹은 뷰포트 크기 대비 %값을 사용할 수 있다.(ex - 0, "10px", "20%")</ko>
10385 * @param {boolean} [options.autoResize=false] Whether the `resize` method should be called automatically after a window resize event.<ko>window의 `resize` 이벤트 이후 자동으로 resize()메소드를 호출할지의 여부.</ko>
10386 * @param {boolean} [options.adaptive=false] Whether the height(horizontal)/width(vertical) of the viewport element reflects the height/width value of the panel after completing the movement.<ko>목적 패널로 이동한 후 그 패널의 높이(horizontal)/너비(vertical)값을 뷰포트 요소의 높이/너비값에 반영할지 여부.</ko>
10387 * @param {number|""} [options.zIndex=2000] z-index value for viewport element.<ko>뷰포트 엘리먼트의 z-index 값.</ko>
10388 * @param {boolean} [options.bound=false] Prevent the view from going out of the first/last panel. Only can be enabled when `circular=false`.<ko>뷰가 첫번째와 마지막 패널 밖으로 나가는 것을 막아준다. `circular=false`인 경우에만 사용할 수 있다.</ko>
10389 * @param {boolean} [options.overflow=false] Disables CSS property `overflow: hidden` in viewport if `true`.<ko>`true`로 설정시 뷰포트에 `overflow: hidden` 속성을 해제한다.</ko>
10390 * @param {string} [options.hanger="50%"] The reference position of the hanger in the viewport, which hangs panel anchors should be stopped at.<br>It should be provided in px or % value of viewport size.<br>You can combinate those values with plus/minus sign.<br>ex) "50", "100px", "0%", "25% + 100px"<ko>뷰포트 내부의 행어의 위치. 패널의 앵커들이 뷰포트 내에서 멈추는 지점에 해당한다.<br>px값이나, 뷰포트의 크기 대비 %값을 사용할 수 있고, 이를 + 혹은 - 기호로 연계하여 사용할 수도 있다.<br>예) "50", "100px", "0%", "25% + 100px"</ko>
10391 * @param {string} [options.anchor="50%"] The reference position of the anchor in panels, which can be hanged by viewport hanger.<br>It should be provided in px or % value of panel size.<br>You can combinate those values with plus/minus sign.<br>ex) "50", "100px", "0%", "25% + 100px"<ko>패널 내부의 앵커의 위치. 뷰포트의 행어와 연계하여 패널이 화면 내에서 멈추는 지점을 설정할 수 있다.<br>px값이나, 패널의 크기 대비 %값을 사용할 수 있고, 이를 + 혹은 - 기호로 연계하여 사용할 수도 있다.<br>예) "50", "100px", "0%", "25% + 100px"</ko>
10392 * @param {number} [options.gap=0] Space value between panels. Should be given in number.(px)<ko>패널간에 부여할 간격의 크기를 나타내는 숫자.(px)</ko>
10393 * @param {eg.Flicking.MoveTypeOption} [options.moveType="snap"] Movement style by user input. (ex: snap, freeScroll)<ko>사용자 입력에 의한 이동 방식.(ex: snap, freeScroll)</ko>
10394 * @param {boolean} [options.useOffset=false] Whether to use `offsetWidth`/`offsetHeight` instead of `getBoundingClientRect` for panel/viewport size calculation.<br/>You can use this option to calculate the original panel size when CSS transform is applied to viewport or panel.<br/>⚠️ If panel size is not fixed integer value, there can be a 1px gap between panels.<ko>패널과 뷰포트의 크기를 계산할 때 `offsetWidth`/`offsetHeight`를 `getBoundingClientRect` 대신 사용할지 여부.<br/>패널이나 뷰포트에 CSS transform이 설정되어 있을 때 원래 패널 크기를 계산하려면 옵션을 활성화한다.<br/>⚠️ 패널의 크기가 정수로 고정되어있지 않다면 패널 사이에 1px의 공간이 생길 수 있다.</ko>
10395 * @param {boolean} [options.renderOnlyVisible=false] Whether to render visible panels only. This can dramatically increase performance when there're many panels.<ko>보이는 패널만 렌더링할지 여부를 설정한다. 패널이 많을 경우에 퍼포먼스를 크게 향상시킬 수 있다.</ko>
10396 * @param {boolean|string[]} [options.isEqualSize=false] This option indicates whether all panels have the same size(true) of first panel, or it can hold a list of class names that determines panel size.<br/>Enabling this option can increase performance while recalculating panel size.<ko>모든 패널의 크기가 동일한지(true), 혹은 패널 크기를 결정하는 패널 클래스들의 리스트.<br/>이 옵션을 설정하면 패널 크기 재설정시에 성능을 높일 수 있다.</ko>
10397 * @param {boolean} [options.isConstantSize=false] Whether all panels have a constant size that won't be changed after resize. Enabling this option can increase performance while recalculating panel size.<ko>모든 패널의 크기가 불변인지의 여부. 이 옵션을 'true'로 설정하면 패널 크기 재설정시에 성능을 높일 수 있다.</ko>
10398 * @param {boolean} [options.renderExternal=false] Whether to use external rendering. It will delegate DOM manipulation and can synchronize the rendered state by calling `sync()` method. You can use this option to use in frameworks like React, Vue, Angular, which has its states and rendering methods.<ko>외부 렌더링을 사용할 지의 여부. 이 옵션을 사용시 렌더링을 외부에 위임할 수 있고, `sync()`를 호출하여 그 상태를 동기화할 수 있다. 이 옵션을 사용하여, React, Vue, Angular 등 자체적인 상태와 렌더링 방법을 갖는 프레임워크에 대응할 수 있다.</ko>
10399 * @param {boolean} [options.resizeOnContentsReady=false] Whether to resize the Flicking after the image/video elements inside viewport are ready.<br/>Use this property to prevent wrong Flicking layout caused by dynamic image / video sizes.<ko>Flicking 내부의 이미지 / 비디오 엘리먼트들이 전부 로드되었을 때 Flicking의 크기를 재계산하기 위한 옵션.<br/>이미지 / 비디오 크기가 고정 크기가 아닐 경우 사용하여 레이아웃이 잘못되는 것을 방지할 수 있다.</ko>
10400 * @param {boolean} [options.collectStatistics=true] Whether to collect statistics on how you are using `Flicking`. These statistical data do not contain any personal information and are used only as a basis for the development of a user-friendly product.<ko>어떻게 `Flicking`을 사용하고 있는지에 대한 통계 수집 여부를 나타낸다. 이 통계자료는 개인정보를 포함하고 있지 않으며 오직 사용자 친화적인 제품으로 발전시키기 위한 근거자료로서 활용한다.</ko>
10401 */
10402
10403
10404 function Flicking(element, options) {
10405 if (options === void 0) {
10406 options = {};
10407 }
10408
10409 var _this = _super.call(this) || this;
10410
10411 _this.contentsReadyChecker = null;
10412 _this.isPanelChangedAtBeforeSync = false;
10413 /**
10414 * Update panels to current state.
10415 * @ko 패널들을 현재 상태에 맞춰 갱신한다.
10416 * @method
10417 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
10418 */
10419
10420 _this.resize = function () {
10421 var viewport = _this.viewport;
10422 var options = _this.options;
10423
10424 var wrapper = _this.getElement();
10425
10426 var allPanels = viewport.panelManager.allPanels();
10427
10428 if (!options.isConstantSize) {
10429 allPanels.forEach(function (panel) {
10430 return panel.unCacheBbox();
10431 });
10432 }
10433
10434 var shouldResetElements = options.renderOnlyVisible && !options.isConstantSize && options.isEqualSize !== true; // Temporarily set parent's height to prevent scroll (#333)
10435
10436 var parent = wrapper.parentElement;
10437 var origStyle = parent.style.height;
10438 parent.style.height = parent.offsetHeight + "px";
10439 viewport.unCacheBbox(); // This should be done before adding panels, to lower performance issue
10440
10441 viewport.updateBbox();
10442
10443 if (shouldResetElements) {
10444 viewport.appendUncachedPanelElements(allPanels);
10445 }
10446
10447 viewport.resize();
10448 parent.style.height = origStyle;
10449 return _this;
10450 };
10451
10452 _this.triggerEvent = function (eventName, // visibleChange event has no common event definition from other events
10453 axesEvent, isTrusted, params) {
10454 if (params === void 0) {
10455 params = {};
10456 }
10457
10458 var viewport = _this.viewport;
10459 var canceled = true; // Ignore events before viewport is initialized
10460
10461 if (viewport) {
10462 var state = viewport.stateMachine.getState();
10463
10464 var _a = viewport.getScrollArea(),
10465 prev = _a.prev,
10466 next = _a.next;
10467
10468 var pos = viewport.getCameraPosition();
10469 var progress = getProgress(pos, [prev, prev, next]);
10470
10471 if (_this.options.circular) {
10472 progress %= 1;
10473 }
10474
10475 canceled = !_super.prototype.trigger.call(_this, eventName, merge({
10476 type: eventName,
10477 index: _this.getIndex(),
10478 panel: _this.getCurrentPanel(),
10479 direction: state.direction,
10480 holding: state.holding,
10481 progress: progress,
10482 axesEvent: axesEvent,
10483 isTrusted: isTrusted
10484 }, params));
10485 }
10486
10487 return {
10488 onSuccess: function (callback) {
10489 if (!canceled) {
10490 callback();
10491 }
10492
10493 return this;
10494 },
10495 onStopped: function (callback) {
10496 if (canceled) {
10497 callback();
10498 }
10499
10500 return this;
10501 }
10502 };
10503 }; // Return result of "move" event triggered
10504
10505
10506 _this.moveCamera = function (axesEvent) {
10507 var viewport = _this.viewport;
10508 var state = viewport.stateMachine.getState();
10509 var options = _this.options;
10510 var pos = axesEvent.pos.flick;
10511 var previousPosition = viewport.getCameraPosition();
10512
10513 if (axesEvent.isTrusted && state.holding) {
10514 var inputOffset = options.horizontal ? axesEvent.inputEvent.offsetX : axesEvent.inputEvent.offsetY;
10515 var isNextDirection = inputOffset < 0;
10516 var cameraChange = pos - previousPosition;
10517 var looped = isNextDirection === pos < previousPosition;
10518
10519 if (options.circular && looped) {
10520 // Reached at max/min range of axes
10521 var scrollAreaSize = viewport.getScrollAreaSize();
10522 cameraChange = (cameraChange > 0 ? -1 : 1) * (scrollAreaSize - Math.abs(cameraChange));
10523 }
10524
10525 var currentDirection = cameraChange === 0 ? state.direction : cameraChange > 0 ? DIRECTION.NEXT : DIRECTION.PREV;
10526 state.direction = currentDirection;
10527 }
10528
10529 state.delta += axesEvent.delta.flick;
10530 viewport.moveCamera(pos, axesEvent);
10531 return _this.triggerEvent(EVENTS.MOVE, axesEvent, axesEvent.isTrusted).onStopped(function () {
10532 // Undo camera movement
10533 viewport.moveCamera(previousPosition, axesEvent);
10534 });
10535 }; // Set flicking wrapper user provided
10536
10537
10538 var wrapper;
10539
10540 if (isString(element)) {
10541 wrapper = document.querySelector(element);
10542
10543 if (!wrapper) {
10544 throw new Error("Base element doesn't exist.");
10545 }
10546 } else if (element.nodeName && element.nodeType === 1) {
10547 wrapper = element;
10548 } else {
10549 throw new Error("Element should be provided in string or HTMLElement.");
10550 }
10551
10552 _this.wrapper = wrapper; // Override default options
10553
10554 _this.options = merge({}, DEFAULT_OPTIONS, options); // Override moveType option
10555
10556 var currentOptions = _this.options;
10557 var moveType = currentOptions.moveType;
10558
10559 if (moveType in DEFAULT_MOVE_TYPE_OPTIONS) {
10560 currentOptions.moveType = DEFAULT_MOVE_TYPE_OPTIONS[moveType];
10561 } // Make viewport instance with panel container element
10562
10563
10564 _this.viewport = new Viewport(_this, _this.options, _this.triggerEvent);
10565
10566 _this.listenInput();
10567
10568 _this.listenResize();
10569
10570 return _this; // if (this.options.collectStatistics) {
10571 // sendEvent(
10572 // "usage",
10573 // "options",
10574 // options,
10575 // );
10576 // }
10577 }
10578 /**
10579 * Move to the previous panel if it exists.
10580 * @ko 이전 패널이 존재시 해당 패널로 이동한다.
10581 * @param [duration=options.duration] Duration of the panel movement animation.(unit: ms)<ko>패널 이동 애니메이션 진행 시간.(단위: ms)</ko>
10582 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
10583 */
10584
10585
10586 var __proto = Flicking.prototype;
10587
10588 __proto.prev = function (duration) {
10589 var currentPanel = this.getCurrentPanel();
10590 var currentState = this.viewport.stateMachine.getState();
10591
10592 if (currentPanel && currentState.type === STATE_TYPE.IDLE) {
10593 var prevPanel = currentPanel.prev();
10594
10595 if (prevPanel) {
10596 prevPanel.focus(duration);
10597 }
10598 }
10599
10600 return this;
10601 };
10602 /**
10603 * Move to the next panel if it exists.
10604 * @ko 다음 패널이 존재시 해당 패널로 이동한다.
10605 * @param [duration=options.duration] Duration of the panel movement animation(unit: ms).<ko>패널 이동 애니메이션 진행 시간.(단위: ms)</ko>
10606 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
10607 */
10608
10609
10610 __proto.next = function (duration) {
10611 var currentPanel = this.getCurrentPanel();
10612 var currentState = this.viewport.stateMachine.getState();
10613
10614 if (currentPanel && currentState.type === STATE_TYPE.IDLE) {
10615 var nextPanel = currentPanel.next();
10616
10617 if (nextPanel) {
10618 nextPanel.focus(duration);
10619 }
10620 }
10621
10622 return this;
10623 };
10624 /**
10625 * Move to the panel of given index.
10626 * @ko 주어진 인덱스에 해당하는 패널로 이동한다.
10627 * @param index The index number of the panel to move.<ko>이동할 패널의 인덱스 번호.</ko>
10628 * @param duration [duration=options.duration] Duration of the panel movement.(unit: ms)<ko>패널 이동 애니메이션 진행 시간.(단위: ms)</ko>
10629 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
10630 */
10631
10632
10633 __proto.moveTo = function (index, duration) {
10634 var viewport = this.viewport;
10635 var panel = viewport.panelManager.get(index);
10636 var state = viewport.stateMachine.getState();
10637
10638 if (!panel || state.type !== STATE_TYPE.IDLE) {
10639 return this;
10640 }
10641
10642 var anchorPosition = panel.getAnchorPosition();
10643 var hangerPosition = viewport.getHangerPosition();
10644 var targetPanel = panel;
10645
10646 if (this.options.circular) {
10647 var scrollAreaSize = viewport.getScrollAreaSize(); // Check all three possible locations, find the nearest position among them.
10648
10649 var possiblePositions = [anchorPosition - scrollAreaSize, anchorPosition, anchorPosition + scrollAreaSize];
10650 var nearestPosition = possiblePositions.reduce(function (nearest, current) {
10651 return Math.abs(current - hangerPosition) < Math.abs(nearest - hangerPosition) ? current : nearest;
10652 }, Infinity) - panel.getRelativeAnchorPosition();
10653 var identicals = panel.getIdenticalPanels();
10654 var offset = nearestPosition - anchorPosition;
10655
10656 if (offset > 0) {
10657 // First cloned panel is nearest
10658 targetPanel = identicals[1];
10659 } else if (offset < 0) {
10660 // Last cloned panel is nearest
10661 targetPanel = identicals[identicals.length - 1];
10662 }
10663
10664 targetPanel = targetPanel.clone(targetPanel.getCloneIndex(), true);
10665 targetPanel.setPosition(nearestPosition);
10666 }
10667
10668 var currentIndex = this.getIndex();
10669
10670 if (hangerPosition === targetPanel.getAnchorPosition() && currentIndex === index) {
10671 return this;
10672 }
10673
10674 var eventType = panel.getIndex() === viewport.getCurrentIndex() ? "" : EVENTS.CHANGE;
10675 viewport.moveTo(targetPanel, viewport.findEstimatedPosition(targetPanel), eventType, null, duration);
10676 return this;
10677 };
10678 /**
10679 * Return index of the current panel. `-1` if no panel exists.
10680 * @ko 현재 패널의 인덱스 번호를 반환한다. 패널이 하나도 없을 경우 `-1`을 반환한다.
10681 * @return Current panel's index, zero-based integer.<ko>현재 패널의 인덱스 번호. 0부터 시작하는 정수.</ko>
10682 */
10683
10684
10685 __proto.getIndex = function () {
10686 return this.viewport.getCurrentIndex();
10687 };
10688 /**
10689 * Return the wrapper element user provided in constructor.
10690 * @ko 사용자가 생성자에서 제공한 래퍼 엘리먼트를 반환한다.
10691 * @return Wrapper element user provided.<ko>사용자가 제공한 래퍼 엘리먼트.</ko>
10692 */
10693
10694
10695 __proto.getElement = function () {
10696 return this.wrapper;
10697 };
10698 /**
10699 * Return the viewport element's size.
10700 * @ko 뷰포트 엘리먼트의 크기를 반환한다.
10701 * @return Width if horizontal: true, height if horizontal: false
10702 */
10703
10704
10705 __proto.getSize = function () {
10706 return this.viewport.getSize();
10707 };
10708 /**
10709 * Return current panel. `null` if no panel exists.
10710 * @ko 현재 패널을 반환한다. 패널이 하나도 없을 경우 `null`을 반환한다.
10711 * @return Current panel.<ko>현재 패널.</ko>
10712 */
10713
10714
10715 __proto.getCurrentPanel = function () {
10716 var viewport = this.viewport;
10717 var panel = viewport.getCurrentPanel();
10718 return panel ? panel : null;
10719 };
10720 /**
10721 * Return the panel of given index. `null` if it doesn't exists.
10722 * @ko 주어진 인덱스에 해당하는 패널을 반환한다. 해당 패널이 존재하지 않을 시 `null`이다.
10723 * @return Panel of given index.<ko>주어진 인덱스에 해당하는 패널.</ko>
10724 */
10725
10726
10727 __proto.getPanel = function (index) {
10728 var viewport = this.viewport;
10729 var panel = viewport.panelManager.get(index);
10730 return panel ? panel : null;
10731 };
10732 /**
10733 * Return all panels.
10734 * @ko 모든 패널들을 반환한다.
10735 * @param - Should include cloned panels or not.<ko>복사된 패널들을 포함할지의 여부.</ko>
10736 * @return All panels.<ko>모든 패널들.</ko>
10737 */
10738
10739
10740 __proto.getAllPanels = function (includeClone) {
10741 var viewport = this.viewport;
10742 var panelManager = viewport.panelManager;
10743 var panels = includeClone ? panelManager.allPanels() : panelManager.originalPanels();
10744 return panels.filter(function (panel) {
10745 return !!panel;
10746 });
10747 };
10748 /**
10749 * Return the panels currently shown in viewport area.
10750 * @ko 현재 뷰포트 영역에서 보여지고 있는 패널들을 반환한다.
10751 * @return Panels currently shown in viewport area.<ko>현재 뷰포트 영역에 보여지는 패널들</ko>
10752 */
10753
10754
10755 __proto.getVisiblePanels = function () {
10756 return this.viewport.calcVisiblePanels();
10757 };
10758 /**
10759 * Return length of original panels.
10760 * @ko 원본 패널의 개수를 반환한다.
10761 * @return Length of original panels.<ko>원본 패널의 개수</ko>
10762 */
10763
10764
10765 __proto.getPanelCount = function () {
10766 return this.viewport.panelManager.getPanelCount();
10767 };
10768 /**
10769 * Return how many groups of clones are created.
10770 * @ko 몇 개의 클론 그룹이 생성되었는지를 반환한다.
10771 * @return Length of cloned panel groups.<ko>클론된 패널 그룹의 개수</ko>
10772 */
10773
10774
10775 __proto.getCloneCount = function () {
10776 return this.viewport.panelManager.getCloneCount();
10777 };
10778 /**
10779 * Get maximum panel index for `infinite` mode.
10780 * @ko `infinite` 모드에서 적용되는 추가 가능한 패널의 최대 인덱스 값을 반환한다.
10781 * @see {@link eg.Flicking.FlickingOptions}
10782 * @return Maximum index of panel that can be added.<ko>최대 추가 가능한 패널의 인덱스.</ko>
10783 */
10784
10785
10786 __proto.getLastIndex = function () {
10787 return this.viewport.panelManager.getLastIndex();
10788 };
10789 /**
10790 * Set maximum panel index for `infinite' mode.<br>[needPanel]{@link eg.Flicking#events:needPanel} won't be triggered anymore when last panel's index reaches it.<br>Also, you can't add more panels after it.
10791 * @ko `infinite` 모드에서 적용되는 패널의 최대 인덱스를 설정한다.<br>마지막 패널의 인덱스가 설정한 값에 도달할 경우 더 이상 [needPanel]{@link eg.Flicking#events:needPanel} 이벤트가 발생되지 않는다.<br>또한, 설정한 인덱스 이후로 새로운 패널을 추가할 수 없다.
10792 * @param - Maximum panel index.
10793 * @see {@link eg.Flicking.FlickingOptions}
10794 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
10795 */
10796
10797
10798 __proto.setLastIndex = function (index) {
10799 this.viewport.setLastIndex(index);
10800 return this;
10801 };
10802 /**
10803 * Return panel movement animation.
10804 * @ko 현재 패널 이동 애니메이션이 진행 중인지를 반환한다.
10805 * @return Is animating or not.<ko>애니메이션 진행 여부.</ko>
10806 */
10807
10808
10809 __proto.isPlaying = function () {
10810 return this.viewport.stateMachine.getState().playing;
10811 };
10812 /**
10813 * Unblock input devices.
10814 * @ko 막았던 입력 장치로부터의 입력을 푼다.
10815 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
10816 */
10817
10818
10819 __proto.enableInput = function () {
10820 this.viewport.enable();
10821 return this;
10822 };
10823 /**
10824 * Block input devices.
10825 * @ko 입력 장치로부터의 입력을 막는다.
10826 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
10827 */
10828
10829
10830 __proto.disableInput = function () {
10831 this.viewport.disable();
10832 return this;
10833 };
10834 /**
10835 * Get current flicking status. You can restore current state by giving returned value to [setStatus()]{@link eg.Flicking#setStatus}.
10836 * @ko 현재 상태 값을 반환한다. 반환받은 값을 [setStatus()]{@link eg.Flicking#setStatus} 메소드의 인자로 지정하면 현재 상태를 복원할 수 있다.
10837 * @return An object with current status value information.<ko>현재 상태값 정보를 가진 객체.</ko>
10838 */
10839
10840
10841 __proto.getStatus = function () {
10842 var viewport = this.viewport;
10843 var panels = viewport.panelManager.originalPanels().filter(function (panel) {
10844 return !!panel;
10845 }).map(function (panel) {
10846 return {
10847 html: panel.getElement().outerHTML,
10848 index: panel.getIndex()
10849 };
10850 });
10851 return {
10852 index: viewport.getCurrentIndex(),
10853 panels: panels,
10854 position: viewport.getCameraPosition()
10855 };
10856 };
10857 /**
10858 * Restore to the state of the `status`.
10859 * @ko `status`의 상태로 복원한다.
10860 * @param status Status value to be restored. You can specify the return value of the [getStatus()]{@link eg.Flicking#getStatus} method.<ko>복원할 상태 값. [getStatus()]{@link eg.Flicking#getStatus}메서드의 반환값을 지정하면 된다.</ko>
10861 */
10862
10863
10864 __proto.setStatus = function (status) {
10865 this.viewport.restore(status);
10866 };
10867 /**
10868 * Add plugins that can have different effects on Flicking.
10869 * @ko 플리킹에 다양한 효과를 부여할 수 있는 플러그인을 추가한다.
10870 * @param - The plugin(s) to add.<ko>추가할 플러그인(들).</ko>
10871 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
10872 */
10873
10874
10875 __proto.addPlugins = function (plugins) {
10876 this.viewport.addPlugins(plugins);
10877 return this;
10878 };
10879 /**
10880 * Remove plugins from Flicking.
10881 * @ko 플리킹으로부터 플러그인들을 제거한다.
10882 * @param - The plugin(s) to remove.<ko>제거 플러그인(들).</ko>
10883 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
10884 */
10885
10886
10887 __proto.removePlugins = function (plugins) {
10888 this.viewport.removePlugins(plugins);
10889 return this;
10890 };
10891 /**
10892 * Return the reference element and all its children to the state they were in before the instance was created. Remove all attached event handlers. Specify `null` for all attributes of the instance (including inherited attributes).
10893 * @ko 기준 요소와 그 하위 패널들을 인스턴스 생성전의 상태로 되돌린다. 부착된 모든 이벤트 핸들러를 탈거한다. 인스턴스의 모든 속성(상속받은 속성포함)에 `null`을 지정한다.
10894 * @example
10895 * const flick = new eg.Flicking("#flick");
10896 * flick.destroy();
10897 * console.log(flick.moveTo); // null
10898 */
10899
10900
10901 __proto.destroy = function (option) {
10902 var _a;
10903
10904 if (option === void 0) {
10905 option = {};
10906 }
10907
10908 this.off();
10909
10910 if (this.options.autoResize) {
10911 window.removeEventListener("resize", this.resize);
10912 }
10913
10914 this.viewport.destroy(option);
10915 (_a = this.contentsReadyChecker) === null || _a === void 0 ? void 0 : _a.destroy(); // release resources
10916
10917 for (var x in this) {
10918 this[x] = null;
10919 }
10920 };
10921 /**
10922 * Add new panels at the beginning of panels.
10923 * @ko 제일 앞에 새로운 패널을 추가한다.
10924 * @param element - Either HTMLElement, HTML string, or array of them.<br>It can be also HTML string of multiple elements with same depth.<ko>HTMLElement 혹은 HTML 문자열, 혹은 그것들의 배열도 가능하다.<br>또한, 같은 depth의 여러 개의 엘리먼트에 해당하는 HTML 문자열도 가능하다.</ko>
10925 * @return Array of appended panels.<ko>추가된 패널들의 배열</ko>
10926 * @example
10927 * // Suppose there were no panels at initialization
10928 * const flicking = new eg.Flicking("#flick");
10929 * flicking.replace(3, document.createElement("div")); // Add new panel at index 3
10930 * flicking.prepend("\<div\>Panel\</div\>"); // Prepended at index 2
10931 * flicking.prepend(["\<div\>Panel\</div\>", document.createElement("div")]); // Prepended at index 0, 1
10932 * flicking.prepend("\<div\>Panel\</div\>"); // Prepended at index 0, pushing every panels behind it.
10933 */
10934
10935
10936 __proto.prepend = function (element) {
10937 var viewport = this.viewport;
10938 var parsedElements = parseElement(element);
10939 var insertingIndex = Math.max(viewport.panelManager.getRange().min - parsedElements.length, 0);
10940 var prependedPanels = viewport.insert(insertingIndex, parsedElements);
10941 this.checkContentsReady(prependedPanels);
10942 return prependedPanels;
10943 };
10944 /**
10945 * Add new panels at the end of panels.
10946 * @ko 제일 끝에 새로운 패널을 추가한다.
10947 * @param element - Either HTMLElement, HTML string, or array of them.<br>It can be also HTML string of multiple elements with same depth.<ko>HTMLElement 혹은 HTML 문자열, 혹은 그것들의 배열도 가능하다.<br>또한, 같은 depth의 여러 개의 엘리먼트에 해당하는 HTML 문자열도 가능하다.</ko>
10948 * @return Array of appended panels.<ko>추가된 패널들의 배열</ko>
10949 * @example
10950 * // Suppose there were no panels at initialization
10951 * const flicking = new eg.Flicking("#flick");
10952 * flicking.append(document.createElement("div")); // Appended at index 0
10953 * flicking.append("\<div\>Panel\</div\>"); // Appended at index 1
10954 * flicking.append(["\<div\>Panel\</div\>", document.createElement("div")]); // Appended at index 2, 3
10955 * // Even this is possible
10956 * flicking.append("\<div\>Panel 1\</div\>\<div\>Panel 2\</div\>"); // Appended at index 4, 5
10957 */
10958
10959
10960 __proto.append = function (element) {
10961 var viewport = this.viewport;
10962 var appendedPanels = viewport.insert(viewport.panelManager.getRange().max + 1, element);
10963 this.checkContentsReady(appendedPanels);
10964 return appendedPanels;
10965 };
10966 /**
10967 * Replace existing panels with new panels from given index. If target index is empty, add new panel at target index.
10968 * @ko 주어진 인덱스로부터의 패널들을 새로운 패널들로 교체한다. 인덱스에 해당하는 자리가 비어있다면, 새로운 패널을 해당 자리에 집어넣는다.
10969 * @param index - Start index to replace new panels.<ko>새로운 패널들로 교체할 시작 인덱스</ko>
10970 * @param element - Either HTMLElement, HTML string, or array of them.<br>It can be also HTML string of multiple elements with same depth.<ko>HTMLElement 혹은 HTML 문자열, 혹은 그것들의 배열도 가능하다.<br>또한, 같은 depth의 여러 개의 엘리먼트에 해당하는 HTML 문자열도 가능하다.</ko>
10971 * @return Array of created panels by replace.<ko>교체되어 새롭게 추가된 패널들의 배열</ko>
10972 * @example
10973 * // Suppose there were no panels at initialization
10974 * const flicking = new eg.Flicking("#flick");
10975 *
10976 * // This will add new panel at index 3,
10977 * // Index 0, 1, 2 is empty at this moment.
10978 * // [empty, empty, empty, PANEL]
10979 * flicking.replace(3, document.createElement("div"));
10980 *
10981 * // As index 2 was empty, this will also add new panel at index 2.
10982 * // [empty, empty, PANEL, PANEL]
10983 * flicking.replace(2, "\<div\>Panel\</div\>");
10984 *
10985 * // Index 3 was not empty, so it will replace previous one.
10986 * // It will also add new panels at index 4 and 5.
10987 * // before - [empty, empty, PANEL, PANEL]
10988 * // after - [empty, empty, PANEL, NEW_PANEL, NEW_PANEL, NEW_PANEL]
10989 * flicking.replace(3, ["\<div\>Panel\</div\>", "\<div\>Panel\</div\>", "\<div\>Panel\</div\>"])
10990 */
10991
10992
10993 __proto.replace = function (index, element) {
10994 var replacedPanels = this.viewport.replace(index, element);
10995 this.checkContentsReady(replacedPanels);
10996 return replacedPanels;
10997 };
10998 /**
10999 * Remove panel at target index. This will decrease index of panels behind it.
11000 * @ko `index`에 해당하는 자리의 패널을 제거한다. 수행시 `index` 이후의 패널들의 인덱스가 감소된다.
11001 * @param index - Index of panel to remove.<ko>제거할 패널의 인덱스</ko>
11002 * @param {number} [deleteCount=1] - Number of panels to remove from index.<ko>`index` 이후로 제거할 패널의 개수.</ko>
11003 * @return Array of removed panels<ko>제거된 패널들의 배열</ko>
11004 */
11005
11006
11007 __proto.remove = function (index, deleteCount) {
11008 if (deleteCount === void 0) {
11009 deleteCount = 1;
11010 }
11011
11012 return this.viewport.remove(index, deleteCount);
11013 };
11014 /**
11015 * Get indexes to render. Should be used with `renderOnlyVisible` option.
11016 * `beforeSync` should be called before this method for a correct result.
11017 * @private
11018 * @ko 렌더링이 필요한 인덱스들을 반환한다. `renderOnlyVisible` 옵션과 함께 사용해야 한다. 정확한 결과를 위해선 `beforeSync`를 이전에 호출해야만 합니다.
11019 * @param - Info object of how panel infos are changed.<ko>패널 정보들의 변경 정보를 담는 오브젝트.</ko>
11020 * @return Array of indexes to render.<ko>렌더링할 인덱스의 배열</ko>
11021 */
11022
11023
11024 __proto.getRenderingIndexes = function (diffResult) {
11025 var viewport = this.viewport;
11026 var visiblePanels = viewport.getVisiblePanels();
11027 var maintained = diffResult.maintained.reduce(function (values, _a) {
11028 var before = _a[0],
11029 after = _a[1];
11030 values[after] = before;
11031 return values;
11032 }, {});
11033 var panelCount = diffResult.list.length;
11034 var added = diffResult.added;
11035
11036 var getPanelAbsIndex = function (panel) {
11037 return panel.getIndex() + (panel.getCloneIndex() + 1) * panelCount;
11038 };
11039
11040 var visibleIndexes = visiblePanels.map(function (panel) {
11041 return getPanelAbsIndex(panel);
11042 }).filter(function (val) {
11043 return maintained[val % panelCount] != null;
11044 });
11045
11046 var renderingPanels = __spreadArrays(visibleIndexes, added);
11047
11048 var allPanels = viewport.panelManager.allPanels();
11049 viewport.setVisiblePanels(renderingPanels.map(function (index) {
11050 return allPanels[index];
11051 }));
11052 return renderingPanels;
11053 };
11054 /**
11055 * Synchronize info of panels instance with info given by external rendering.
11056 * @ko 외부 렌더링 방식에 의해 입력받은 패널의 정보와 현재 플리킹이 갖는 패널 정보를 동기화한다.
11057 * @private
11058 * @param - Info object of how panel infos are changed.<ko>패널 정보들의 변경 정보를 담는 오브젝트.</ko>
11059 * @param - Whether called from sync method <ko> sync 메소드로부터 호출됐는지 여부 </ko>
11060 */
11061
11062
11063 __proto.beforeSync = function (diffInfo) {
11064 var _this = this;
11065
11066 var maintained = diffInfo.maintained,
11067 added = diffInfo.added,
11068 changed = diffInfo.changed,
11069 removed = diffInfo.removed;
11070 var viewport = this.viewport;
11071 var panelManager = viewport.panelManager;
11072 var isCircular = this.options.circular;
11073 var cloneCount = panelManager.getCloneCount();
11074 var prevClonedPanels = panelManager.clonedPanels(); // Update visible panels
11075
11076 var newVisiblePanels = viewport.getVisiblePanels().filter(function (panel) {
11077 return findIndex(removed, function (index) {
11078 return index === panel.getIndex();
11079 }) < 0;
11080 });
11081 viewport.setVisiblePanels(newVisiblePanels); // Did not changed at all
11082
11083 if (added.length <= 0 && removed.length <= 0 && changed.length <= 0 && cloneCount === prevClonedPanels.length) {
11084 return this;
11085 }
11086
11087 var prevOriginalPanels = panelManager.originalPanels();
11088 var newPanels = [];
11089 var newClones = counter(cloneCount).map(function () {
11090 return [];
11091 });
11092 maintained.forEach(function (_a) {
11093 var beforeIdx = _a[0],
11094 afterIdx = _a[1];
11095 newPanels[afterIdx] = prevOriginalPanels[beforeIdx];
11096 newPanels[afterIdx].setIndex(afterIdx);
11097 });
11098 added.forEach(function (addIndex) {
11099 newPanels[addIndex] = new Panel(null, addIndex, _this.viewport);
11100 });
11101
11102 if (isCircular) {
11103 counter(cloneCount).forEach(function (groupIndex) {
11104 var prevCloneGroup = prevClonedPanels[groupIndex];
11105 var newCloneGroup = newClones[groupIndex];
11106 maintained.forEach(function (_a) {
11107 var beforeIdx = _a[0],
11108 afterIdx = _a[1];
11109 newCloneGroup[afterIdx] = prevCloneGroup ? prevCloneGroup[beforeIdx] : newPanels[afterIdx].clone(groupIndex, false);
11110 newCloneGroup[afterIdx].setIndex(afterIdx);
11111 });
11112 added.forEach(function (addIndex) {
11113 var newPanel = newPanels[addIndex];
11114 newCloneGroup[addIndex] = newPanel.clone(groupIndex, false);
11115 });
11116 });
11117 }
11118
11119 added.forEach(function (index) {
11120 viewport.updateCheckedIndexes({
11121 min: index,
11122 max: index
11123 });
11124 });
11125 removed.forEach(function (index) {
11126 viewport.updateCheckedIndexes({
11127 min: index - 1,
11128 max: index + 1
11129 });
11130 });
11131 var checkedIndexes = viewport.getCheckedIndexes();
11132 checkedIndexes.forEach(function (_a, idx) {
11133 var min = _a[0],
11134 max = _a[1]; // Push checked indexes backward
11135
11136 var pushedIndex = added.filter(function (index) {
11137 return index < min && panelManager.has(index);
11138 }).length - removed.filter(function (index) {
11139 return index < min;
11140 }).length;
11141 checkedIndexes.splice(idx, 1, [min + pushedIndex, max + pushedIndex]);
11142 }); // Only effective only when there are least one panel which have changed its index
11143
11144 if (changed.length > 0) {
11145 // Removed checked index by changed ones after pushing
11146 maintained.forEach(function (_a) {
11147 var next = _a[1];
11148 viewport.updateCheckedIndexes({
11149 min: next,
11150 max: next
11151 });
11152 });
11153 }
11154
11155 panelManager.replacePanels(newPanels, newClones);
11156 this.isPanelChangedAtBeforeSync = true;
11157 };
11158 /**
11159 * Synchronize info of panels with DOM info given by external rendering.
11160 * @ko 외부 렌더링 방식에 의해 입력받은 DOM의 정보와 현재 플리킹이 갖는 패널 정보를 동기화 한다.
11161 * @private
11162 * @param - Info object of how panel elements are changed.<ko>패널의 DOM 요소들의 변경 정보를 담는 오브젝트.</ko>
11163 */
11164
11165
11166 __proto.sync = function (diffInfo) {
11167 var list = diffInfo.list,
11168 maintained = diffInfo.maintained,
11169 added = diffInfo.added,
11170 changed = diffInfo.changed,
11171 removed = diffInfo.removed; // Did not changed at all
11172
11173 if (added.length <= 0 && removed.length <= 0 && changed.length <= 0) {
11174 return this;
11175 }
11176
11177 var viewport = this.viewport;
11178 var _a = this.options,
11179 renderOnlyVisible = _a.renderOnlyVisible,
11180 circular = _a.circular;
11181 var panelManager = viewport.panelManager;
11182
11183 if (!renderOnlyVisible) {
11184 var indexRange = panelManager.getRange();
11185 var beforeDiffInfo = diffInfo;
11186
11187 if (circular) {
11188 var prevOriginalPanelCount_1 = indexRange.max;
11189 var originalPanelCount_1 = list.length / (panelManager.getCloneCount() + 1) >> 0;
11190 var originalAdded = added.filter(function (index) {
11191 return index < originalPanelCount_1;
11192 });
11193 var originalRemoved = removed.filter(function (index) {
11194 return index <= prevOriginalPanelCount_1;
11195 });
11196 var originalMaintained = maintained.filter(function (_a) {
11197 var beforeIdx = _a[0];
11198 return beforeIdx <= prevOriginalPanelCount_1;
11199 });
11200 var originalChanged = changed.filter(function (_a) {
11201 var beforeIdx = _a[0];
11202 return beforeIdx <= prevOriginalPanelCount_1;
11203 });
11204 beforeDiffInfo = {
11205 added: originalAdded,
11206 maintained: originalMaintained,
11207 removed: originalRemoved,
11208 changed: originalChanged
11209 };
11210 }
11211
11212 this.beforeSync(beforeDiffInfo);
11213 }
11214
11215 var visiblePanels = renderOnlyVisible ? viewport.getVisiblePanels() : this.getAllPanels(true);
11216 added.forEach(function (addedIndex) {
11217 var addedElement = list[addedIndex];
11218 var beforePanel = visiblePanels[addedIndex];
11219 beforePanel.setElement(addedElement); // As it can be 0
11220
11221 beforePanel.unCacheBbox();
11222 });
11223
11224 if (this.isPanelChangedAtBeforeSync) {
11225 // Reset visible panels
11226 viewport.setVisiblePanels([]);
11227 this.isPanelChangedAtBeforeSync = false;
11228 }
11229
11230 viewport.resize();
11231 return this;
11232 };
11233
11234 __proto.listenInput = function () {
11235 var flicking = this;
11236 var viewport = flicking.viewport;
11237 var stateMachine = viewport.stateMachine; // Set event context
11238
11239 flicking.eventContext = {
11240 flicking: flicking,
11241 viewport: flicking.viewport,
11242 transitTo: stateMachine.transitTo,
11243 triggerEvent: flicking.triggerEvent,
11244 moveCamera: flicking.moveCamera,
11245 stopCamera: viewport.stopCamera
11246 };
11247 var handlers = {};
11248
11249 var _loop_1 = function (key) {
11250 var eventType = AXES_EVENTS[key];
11251
11252 handlers[eventType] = function (e) {
11253 return stateMachine.fire(eventType, e, flicking.eventContext);
11254 };
11255 };
11256
11257 for (var key in AXES_EVENTS) {
11258 _loop_1(key);
11259 } // Connect Axes instance with PanInput
11260
11261
11262 flicking.viewport.connectAxesHandler(handlers);
11263 };
11264
11265 __proto.listenResize = function () {
11266 var _this = this;
11267
11268 var options = this.options;
11269
11270 if (options.autoResize) {
11271 window.addEventListener("resize", this.resize);
11272 }
11273
11274 if (options.resizeOnContentsReady) {
11275 var contentsReadyChecker = new ImReady();
11276 contentsReadyChecker.on("preReady", function () {
11277 _this.resize();
11278 });
11279 contentsReadyChecker.on("readyElement", function (e) {
11280 if (e.hasLoading && e.isPreReadyOver) {
11281 _this.resize();
11282 }
11283 });
11284 contentsReadyChecker.on("error", function (e) {
11285 _this.trigger(EVENTS.CONTENT_ERROR, {
11286 type: EVENTS.CONTENT_ERROR,
11287 element: e.element
11288 });
11289 });
11290 contentsReadyChecker.check([this.wrapper]);
11291 this.contentsReadyChecker = contentsReadyChecker;
11292 }
11293 };
11294
11295 __proto.checkContentsReady = function (panels) {
11296 var _a;
11297
11298 (_a = this.contentsReadyChecker) === null || _a === void 0 ? void 0 : _a.check(panels.map(function (panel) {
11299 return panel.getElement();
11300 }));
11301 };
11302 /**
11303 * Version info string
11304 * @ko 버전정보 문자열
11305 * @example
11306 * eg.Flicking.VERSION; // ex) 3.0.0
11307 * @memberof eg.Flicking
11308 */
11309
11310
11311 Flicking.VERSION = "3.7.1";
11312 /**
11313 * Direction constant - "PREV" or "NEXT"
11314 * @ko 방향 상수 - "PREV" 또는 "NEXT"
11315 * @type {object}
11316 * @property {"PREV"} PREV - Prev direction from current hanger position.<br/>It's `left(←️)` direction when `horizontal: true`.<br/>Or, `up(↑️)` direction when `horizontal: false`.<ko>현재 행어를 기준으로 이전 방향.<br/>`horizontal: true`일 경우 `왼쪽(←️)` 방향.<br/>`horizontal: false`일 경우 `위쪽(↑️)`방향이다.</ko>
11317 * @property {"NEXT"} NEXT - Next direction from current hanger position.<br/>It's `right(→)` direction when `horizontal: true`.<br/>Or, `down(↓️)` direction when `horizontal: false`.<ko>현재 행어를 기준으로 다음 방향.<br/>`horizontal: true`일 경우 `오른쪽(→)` 방향.<br/>`horizontal: false`일 경우 `아래쪽(↓️)`방향이다.</ko>
11318 * @example
11319 * eg.Flicking.DIRECTION.PREV; // "PREV"
11320 * eg.Flicking.DIRECTION.NEXT; // "NEXT"
11321 */
11322
11323 Flicking.DIRECTION = DIRECTION;
11324 /**
11325 * Event type object with event name strings.
11326 * @ko 이벤트 이름 문자열들을 담은 객체
11327 * @type {object}
11328 * @property {"holdStart"} HOLD_START - holdStart event<ko>holdStart 이벤트</ko>
11329 * @property {"holdEnd"} HOLD_END - holdEnd event<ko>holdEnd 이벤트</ko>
11330 * @property {"moveStart"} MOVE_START - moveStart event<ko>moveStart 이벤트</ko>
11331 * @property {"move"} MOVE - move event<ko>move 이벤트</ko>
11332 * @property {"moveEnd"} MOVE_END - moveEnd event<ko>moveEnd 이벤트</ko>
11333 * @property {"change"} CHANGE - change event<ko>change 이벤트</ko>
11334 * @property {"restore"} RESTORE - restore event<ko>restore 이벤트</ko>
11335 * @property {"select"} SELECT - select event<ko>select 이벤트</ko>
11336 * @property {"needPanel"} NEED_PANEL - needPanel event<ko>needPanel 이벤트</ko>
11337 * @example
11338 * eg.Flicking.EVENTS.MOVE_START; // "MOVE_START"
11339 */
11340
11341 Flicking.EVENTS = EVENTS;
11342 return Flicking;
11343 }(Component);
11344
11345 Flicking.withFlickingMethods = withFlickingMethods;
11346 Flicking.DEFAULT_OPTIONS = DEFAULT_OPTIONS;
11347 Flicking.MOVE_TYPE = MOVE_TYPE;
11348
11349 return Flicking;
11350
11351})));
11352//# sourceMappingURL=flicking.pkgd.js.map