UNPKG

189 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(require('@egjs/component'), require('@egjs/imready'), require('@egjs/axes')) :
11 typeof define === 'function' && define.amd ? define(['@egjs/component', '@egjs/imready', '@egjs/axes'], factory) :
12 (global = global || self, (global.eg = global.eg || {}, global.eg.Flicking = factory(global.eg.Component, global.ImReady, global.eg.Axes)));
13}(this, (function (Component, ImReady, Axes) { '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) 2015 NAVER Corp.
62 * egjs projects are licensed under the MIT license
63 */
64 var MOVE_TYPE = {
65 SNAP: "snap",
66 FREE_SCROLL: "freeScroll"
67 };
68 var DEFAULT_MOVE_TYPE_OPTIONS = {
69 snap: {
70 type: "snap",
71 count: 1
72 },
73 freeScroll: {
74 type: "freeScroll"
75 }
76 };
77 var isBrowser = typeof document !== "undefined";
78 /**
79 * Default options for creating Flicking.
80 * @ko 플리킹을 만들 때 사용하는 기본 옵션들
81 * @private
82 * @memberof eg.Flicking
83 */
84
85 var DEFAULT_OPTIONS = {
86 classPrefix: "eg-flick",
87 deceleration: 0.0075,
88 horizontal: true,
89 circular: false,
90 infinite: false,
91 infiniteThreshold: 0,
92 lastIndex: Infinity,
93 threshold: 40,
94 duration: 100,
95 panelEffect: function (x) {
96 return 1 - Math.pow(1 - x, 3);
97 },
98 defaultIndex: 0,
99 inputType: ["touch", "mouse"],
100 thresholdAngle: 45,
101 bounce: 10,
102 autoResize: false,
103 adaptive: false,
104 zIndex: 2000,
105 bound: false,
106 overflow: false,
107 hanger: "50%",
108 anchor: "50%",
109 gap: 0,
110 moveType: DEFAULT_MOVE_TYPE_OPTIONS.snap,
111 useOffset: false,
112 isEqualSize: false,
113 isConstantSize: false,
114 renderOnlyVisible: false,
115 renderExternal: false,
116 resizeOnContentsReady: false,
117 iOSEdgeSwipeThreshold: 30,
118 collectStatistics: true
119 };
120 var DEFAULT_VIEWPORT_CSS = {
121 position: "relative",
122 zIndex: DEFAULT_OPTIONS.zIndex,
123 overflow: "hidden"
124 };
125 var DEFAULT_CAMERA_CSS = {
126 width: "100%",
127 height: "100%",
128 willChange: "transform"
129 };
130 var DEFAULT_PANEL_CSS = {
131 position: "absolute"
132 };
133 var EVENTS = {
134 HOLD_START: "holdStart",
135 HOLD_END: "holdEnd",
136 MOVE_START: "moveStart",
137 MOVE: "move",
138 MOVE_END: "moveEnd",
139 CHANGE: "change",
140 RESTORE: "restore",
141 SELECT: "select",
142 NEED_PANEL: "needPanel",
143 VISIBLE_CHANGE: "visibleChange",
144 CONTENT_ERROR: "contentError"
145 };
146 var AXES_EVENTS = {
147 HOLD: "hold",
148 CHANGE: "change",
149 RELEASE: "release",
150 ANIMATION_END: "animationEnd",
151 FINISH: "finish"
152 };
153 var STATE_TYPE = {
154 IDLE: 0,
155 HOLDING: 1,
156 DRAGGING: 2,
157 ANIMATING: 3,
158 DISABLED: 4
159 };
160 var DIRECTION = {
161 PREV: "PREV",
162 NEXT: "NEXT"
163 };
164 var FLICKING_METHODS = {
165 prev: true,
166 next: true,
167 moveTo: true,
168 getIndex: true,
169 getAllPanels: true,
170 getCurrentPanel: true,
171 getElement: true,
172 getSize: true,
173 getPanel: true,
174 getPanelCount: true,
175 getStatus: true,
176 getVisiblePanels: true,
177 enableInput: true,
178 disableInput: true,
179 destroy: true,
180 resize: true,
181 setStatus: true,
182 isPlaying: true
183 }; // Check whether browser supports transform: translate3d
184 // https://stackoverflow.com/questions/5661671/detecting-transform-translate3d-support
185
186 var checkTranslateSupport = function () {
187 var transforms = {
188 webkitTransform: "-webkit-transform",
189 msTransform: "-ms-transform",
190 MozTransform: "-moz-transform",
191 OTransform: "-o-transform",
192 transform: "transform"
193 };
194
195 if (!isBrowser) {
196 return {
197 name: transforms.transform,
198 has3d: true
199 };
200 }
201
202 var supportedStyle = document.documentElement.style;
203 var transformName = "";
204
205 for (var prefixedTransform in transforms) {
206 if (prefixedTransform in supportedStyle) {
207 transformName = prefixedTransform;
208 }
209 }
210
211 if (!transformName) {
212 throw new Error("Browser doesn't support CSS3 2D Transforms.");
213 }
214
215 var el = document.createElement("div");
216 document.documentElement.insertBefore(el, null);
217 el.style[transformName] = "translate3d(1px, 1px, 1px)";
218 var styleVal = window.getComputedStyle(el).getPropertyValue(transforms[transformName]);
219 el.parentElement.removeChild(el);
220 var transformInfo = {
221 name: transformName,
222 has3d: styleVal.length > 0 && styleVal !== "none"
223 };
224
225 checkTranslateSupport = function () {
226 return transformInfo;
227 };
228
229 return transformInfo;
230 };
231 var TRANSFORM = checkTranslateSupport();
232
233 /**
234 * Copyright (c) 2015 NAVER Corp.
235 * egjs projects are licensed under the MIT license
236 */
237 function merge(target) {
238 var srcs = [];
239
240 for (var _i = 1; _i < arguments.length; _i++) {
241 srcs[_i - 1] = arguments[_i];
242 }
243
244 srcs.forEach(function (source) {
245 Object.keys(source).forEach(function (key) {
246 var value = source[key];
247 target[key] = value;
248 });
249 });
250 return target;
251 }
252 function parseElement(element) {
253 if (!Array.isArray(element)) {
254 element = [element];
255 }
256
257 var elements = [];
258 element.forEach(function (el) {
259 if (isString(el)) {
260 var tempDiv = document.createElement("div");
261 tempDiv.innerHTML = el;
262 elements.push.apply(elements, toArray(tempDiv.children));
263
264 while (tempDiv.firstChild) {
265 tempDiv.removeChild(tempDiv.firstChild);
266 }
267 } else {
268 elements.push(el);
269 }
270 });
271 return elements;
272 }
273 function isString(value) {
274 return typeof value === "string";
275 } // Get class list of element as string array
276
277 function addClass(element, className) {
278 if (element.classList) {
279 element.classList.add(className);
280 } else {
281 if (!hasClass(element, className)) {
282 element.className = (element.className + " " + className).replace(/\s{2,}/g, " ");
283 }
284 }
285 }
286 function hasClass(element, className) {
287 if (element.classList) {
288 return element.classList.contains(className);
289 } else {
290 return element.className.split(" ").indexOf(className) >= 0;
291 }
292 }
293 function applyCSS(element, cssObj) {
294 Object.keys(cssObj).forEach(function (property) {
295 element.style[property] = cssObj[property];
296 });
297 }
298 function clamp(val, min, max) {
299 return Math.max(Math.min(val, max), min);
300 } // Min: inclusive, Max: exclusive
301
302 function isBetween(val, min, max) {
303 return val >= min && val <= max;
304 }
305 function toArray(iterable) {
306 return [].slice.call(iterable);
307 }
308 function isArray(arr) {
309 return arr && arr.constructor === Array;
310 }
311 function parseArithmeticExpression(cssValue, base, defaultVal) {
312 // Set base / 2 to default value, if it's undefined
313 var defaultValue = defaultVal != null ? defaultVal : base / 2;
314 var cssRegex = /(?:(\+|\-)\s*)?(\d+(?:\.\d+)?(%|px)?)/g;
315
316 if (typeof cssValue === "number") {
317 return clamp(cssValue, 0, base);
318 }
319
320 var idx = 0;
321 var calculatedValue = 0;
322 var matchResult = cssRegex.exec(cssValue);
323
324 while (matchResult != null) {
325 var sign = matchResult[1];
326 var value = matchResult[2];
327 var unit = matchResult[3];
328 var parsedValue = parseFloat(value);
329
330 if (idx <= 0) {
331 sign = sign || "+";
332 } // Return default value for values not in good form
333
334
335 if (!sign) {
336 return defaultValue;
337 }
338
339 if (unit === "%") {
340 parsedValue = parsedValue / 100 * base;
341 }
342
343 calculatedValue += sign === "+" ? parsedValue : -parsedValue; // Match next occurrence
344
345 ++idx;
346 matchResult = cssRegex.exec(cssValue);
347 } // None-matched
348
349
350 if (idx === 0) {
351 return defaultValue;
352 } // Clamp between 0 ~ base
353
354
355 return clamp(calculatedValue, 0, base);
356 }
357 function getProgress(pos, range) {
358 // start, anchor, end
359 // -1 , 0 , 1
360 var min = range[0],
361 center = range[1],
362 max = range[2];
363
364 if (pos > center && max - center) {
365 // 0 ~ 1
366 return (pos - center) / (max - center);
367 } else if (pos < center && center - min) {
368 // -1 ~ 0
369 return (pos - center) / (center - min);
370 } else if (pos !== center && max - min) {
371 return (pos - min) / (max - min);
372 }
373
374 return 0;
375 }
376 function findIndex(iterable, callback) {
377 for (var i = 0; i < iterable.length; i += 1) {
378 var element = iterable[i];
379
380 if (element && callback(element)) {
381 return i;
382 }
383 }
384
385 return -1;
386 } // return [0, 1, ...., max - 1]
387
388 function counter(max) {
389 var counterArray = [];
390
391 for (var i = 0; i < max; i += 1) {
392 counterArray[i] = i;
393 }
394
395 return counterArray;
396 } // Circulate number between range [min, max]
397
398 /*
399 * "indexed" means min and max is not same, so if it's true "min - 1" should be max
400 * While if it's false, "min - 1" should be "max - 1"
401 * use `indexed: true` when it should be used for circulating integers like index
402 * or `indexed: false` when it should be used for something like positions.
403 */
404
405 function circulate(value, min, max, indexed) {
406 var size = indexed ? max - min + 1 : max - min;
407
408 if (value < min) {
409 var offset = indexed ? (min - value - 1) % size : (min - value) % size;
410 value = max - offset;
411 } else if (value > max) {
412 var offset = indexed ? (value - max - 1) % size : (value - max) % size;
413 value = min + offset;
414 }
415
416 return value;
417 }
418 function restoreStyle(element, originalStyle) {
419 originalStyle.className ? element.setAttribute("class", originalStyle.className) : element.removeAttribute("class");
420 originalStyle.style ? element.setAttribute("style", originalStyle.style) : element.removeAttribute("style");
421 }
422 /**
423 * Decorator that makes the method of flicking available in the framework.
424 * @ko 프레임워크에서 플리킹의 메소드를 사용할 수 있게 하는 데코레이터.
425 * @memberof eg.Flicking
426 * @private
427 * @example
428 * ```js
429 * import Flicking, { withFlickingMethods } from "@egjs/flicking";
430 *
431 * class Flicking extends React.Component<Partial<FlickingProps & FlickingOptions>> {
432 * &#64;withFlickingMethods
433 * private flicking: Flicking;
434 * }
435 * ```
436 */
437
438 function withFlickingMethods(prototype, flickingName) {
439 Object.keys(FLICKING_METHODS).forEach(function (name) {
440 if (prototype[name]) {
441 return;
442 }
443
444 prototype[name] = function () {
445 var _a;
446
447 var args = [];
448
449 for (var _i = 0; _i < arguments.length; _i++) {
450 args[_i] = arguments[_i];
451 }
452
453 var result = (_a = this[flickingName])[name].apply(_a, args); // fix `this` type to return your own `flicking` instance to the instance using the decorator.
454
455
456 if (result === this[flickingName]) {
457 return this;
458 } else {
459 return result;
460 }
461 };
462 });
463 }
464 function getBbox(element, useOffset) {
465 var bbox;
466
467 if (useOffset) {
468 bbox = {
469 x: 0,
470 y: 0,
471 width: element.offsetWidth,
472 height: element.offsetHeight
473 };
474 } else {
475 var clientRect = element.getBoundingClientRect();
476 bbox = {
477 x: clientRect.left,
478 y: clientRect.top,
479 width: clientRect.width,
480 height: clientRect.height
481 };
482 }
483
484 return bbox;
485 }
486
487 /**
488 * Copyright (c) 2015 NAVER Corp.
489 * egjs projects are licensed under the MIT license
490 */
491
492 var Panel =
493 /*#__PURE__*/
494 function () {
495 function Panel(element, index, viewport) {
496 this.viewport = viewport;
497 this.prevSibling = null;
498 this.nextSibling = null;
499 this.clonedPanels = [];
500 this.state = {
501 index: index,
502 position: 0,
503 relativeAnchorPosition: 0,
504 size: 0,
505 isClone: false,
506 isVirtual: false,
507 cloneIndex: -1,
508 originalStyle: {
509 className: "",
510 style: ""
511 },
512 cachedBbox: null
513 };
514 this.setElement(element);
515 }
516
517 var __proto = Panel.prototype;
518
519 __proto.resize = function (givenBbox) {
520 var state = this.state;
521 var options = this.viewport.options;
522 var bbox = givenBbox ? givenBbox : this.getBbox();
523 this.state.cachedBbox = bbox;
524 var prevSize = state.size;
525 state.size = options.horizontal ? bbox.width : bbox.height;
526
527 if (prevSize !== state.size) {
528 state.relativeAnchorPosition = parseArithmeticExpression(options.anchor, state.size);
529 }
530
531 if (!state.isClone) {
532 this.clonedPanels.forEach(function (panel) {
533 var cloneState = panel.state;
534 cloneState.size = state.size;
535 cloneState.cachedBbox = state.cachedBbox;
536 cloneState.relativeAnchorPosition = state.relativeAnchorPosition;
537 });
538 }
539 };
540
541 __proto.unCacheBbox = function () {
542 this.state.cachedBbox = null;
543 };
544
545 __proto.getProgress = function () {
546 var viewport = this.viewport;
547 var options = viewport.options;
548 var panelCount = viewport.panelManager.getPanelCount();
549 var scrollAreaSize = viewport.getScrollAreaSize();
550 var relativeIndex = (options.circular ? Math.floor(this.getPosition() / scrollAreaSize) * panelCount : 0) + this.getIndex();
551 var progress = relativeIndex - viewport.getCurrentProgress();
552 return progress;
553 };
554
555 __proto.getOutsetProgress = function () {
556 var viewport = this.viewport;
557 var outsetRange = [-this.getSize(), viewport.getRelativeHangerPosition() - this.getRelativeAnchorPosition(), viewport.getSize()];
558 var relativePanelPosition = this.getPosition() - viewport.getCameraPosition();
559 var outsetProgress = getProgress(relativePanelPosition, outsetRange);
560 return outsetProgress;
561 };
562
563 __proto.getVisibleRatio = function () {
564 var viewport = this.viewport;
565 var panelSize = this.getSize();
566 var relativePanelPosition = this.getPosition() - viewport.getCameraPosition();
567 var rightRelativePanelPosition = relativePanelPosition + panelSize;
568 var visibleSize = Math.min(viewport.getSize(), rightRelativePanelPosition) - Math.max(relativePanelPosition, 0);
569 var visibleRatio = visibleSize >= 0 ? visibleSize / panelSize : 0;
570 return visibleRatio;
571 };
572
573 __proto.focus = function (duration) {
574 var viewport = this.viewport;
575 var currentPanel = viewport.getCurrentPanel();
576 var hangerPosition = viewport.getHangerPosition();
577 var anchorPosition = this.getAnchorPosition();
578
579 if (hangerPosition === anchorPosition || !currentPanel) {
580 return;
581 }
582
583 var currentPosition = currentPanel.getPosition();
584 var eventType = currentPosition === this.getPosition() ? "" : EVENTS.CHANGE;
585 viewport.moveTo(this, viewport.findEstimatedPosition(this), eventType, null, duration);
586 };
587
588 __proto.update = function (updateFunction, shouldResize) {
589 if (updateFunction === void 0) {
590 updateFunction = null;
591 }
592
593 if (shouldResize === void 0) {
594 shouldResize = true;
595 }
596
597 var identicalPanels = this.getIdenticalPanels();
598
599 if (updateFunction) {
600 identicalPanels.forEach(function (eachPanel) {
601 updateFunction(eachPanel.getElement());
602 });
603 }
604
605 if (shouldResize) {
606 identicalPanels.forEach(function (eachPanel) {
607 eachPanel.unCacheBbox();
608 });
609 this.viewport.addVisiblePanel(this);
610 this.viewport.resize();
611 }
612 };
613
614 __proto.prev = function () {
615 var viewport = this.viewport;
616 var options = viewport.options;
617 var prevSibling = this.prevSibling;
618
619 if (!prevSibling) {
620 return null;
621 }
622
623 var currentIndex = this.getIndex();
624 var currentPosition = this.getPosition();
625 var prevPanelIndex = prevSibling.getIndex();
626 var prevPanelPosition = prevSibling.getPosition();
627 var prevPanelSize = prevSibling.getSize();
628 var hasEmptyPanelBetween = currentIndex - prevPanelIndex > 1;
629 var notYetMinPanel = options.infinite && currentIndex > 0 && prevPanelIndex > currentIndex;
630
631 if (hasEmptyPanelBetween || notYetMinPanel) {
632 // Empty panel exists between
633 return null;
634 }
635
636 var newPosition = currentPosition - prevPanelSize - options.gap;
637 var prevPanel = prevSibling;
638
639 if (prevPanelPosition !== newPosition) {
640 prevPanel = prevSibling.clone(prevSibling.getCloneIndex(), true);
641 prevPanel.setPosition(newPosition);
642 }
643
644 return prevPanel;
645 };
646
647 __proto.next = function () {
648 var viewport = this.viewport;
649 var options = viewport.options;
650 var nextSibling = this.nextSibling;
651 var lastIndex = viewport.panelManager.getLastIndex();
652
653 if (!nextSibling) {
654 return null;
655 }
656
657 var currentIndex = this.getIndex();
658 var currentPosition = this.getPosition();
659 var nextPanelIndex = nextSibling.getIndex();
660 var nextPanelPosition = nextSibling.getPosition();
661 var hasEmptyPanelBetween = nextPanelIndex - currentIndex > 1;
662 var notYetMaxPanel = options.infinite && currentIndex < lastIndex && nextPanelIndex < currentIndex;
663
664 if (hasEmptyPanelBetween || notYetMaxPanel) {
665 return null;
666 }
667
668 var newPosition = currentPosition + this.getSize() + options.gap;
669 var nextPanel = nextSibling;
670
671 if (nextPanelPosition !== newPosition) {
672 nextPanel = nextSibling.clone(nextSibling.getCloneIndex(), true);
673 nextPanel.setPosition(newPosition);
674 }
675
676 return nextPanel;
677 };
678
679 __proto.insertBefore = function (element) {
680 var viewport = this.viewport;
681 var parsedElements = parseElement(element);
682 var firstPanel = viewport.panelManager.firstPanel();
683 var prevSibling = this.prevSibling; // Finding correct inserting index
684 // While it should insert removing empty spaces,
685 // It also should have to be bigger than prevSibling' s index
686
687 var targetIndex = prevSibling && firstPanel.getIndex() !== this.getIndex() ? Math.max(prevSibling.getIndex() + 1, this.getIndex() - parsedElements.length) : Math.max(this.getIndex() - parsedElements.length, 0);
688 return viewport.insert(targetIndex, parsedElements);
689 };
690
691 __proto.insertAfter = function (element) {
692 return this.viewport.insert(this.getIndex() + 1, element);
693 };
694
695 __proto.remove = function () {
696 this.viewport.remove(this.getIndex());
697 return this;
698 };
699
700 __proto.destroy = function (option) {
701 if (!option.preserveUI) {
702 var originalStyle = this.state.originalStyle;
703 restoreStyle(this.element, originalStyle);
704 } // release resources
705
706
707 for (var x in this) {
708 this[x] = null;
709 }
710 };
711
712 __proto.getElement = function () {
713 return this.element;
714 };
715
716 __proto.getAnchorPosition = function () {
717 return this.state.position + this.state.relativeAnchorPosition;
718 };
719
720 __proto.getRelativeAnchorPosition = function () {
721 return this.state.relativeAnchorPosition;
722 };
723
724 __proto.getIndex = function () {
725 return this.state.index;
726 };
727
728 __proto.getPosition = function () {
729 return this.state.position;
730 };
731
732 __proto.getSize = function () {
733 return this.state.size;
734 };
735
736 __proto.getBbox = function () {
737 var state = this.state;
738 var viewport = this.viewport;
739 var element = this.element;
740 var options = viewport.options;
741
742 if (!element) {
743 state.cachedBbox = {
744 x: 0,
745 y: 0,
746 width: 0,
747 height: 0
748 };
749 } else if (!state.cachedBbox) {
750 var wasVisible = Boolean(element.parentNode);
751 var cameraElement = viewport.getCameraElement();
752
753 if (!wasVisible) {
754 cameraElement.appendChild(element);
755 viewport.addVisiblePanel(this);
756 }
757
758 state.cachedBbox = getBbox(element, options.useOffset);
759
760 if (!wasVisible && viewport.options.renderExternal) {
761 cameraElement.removeChild(element);
762 }
763 }
764
765 return state.cachedBbox;
766 };
767
768 __proto.isClone = function () {
769 return this.state.isClone;
770 };
771
772 __proto.getOverlappedClass = function (classes) {
773 var element = this.element;
774
775 for (var _i = 0, classes_1 = classes; _i < classes_1.length; _i++) {
776 var className = classes_1[_i];
777
778 if (hasClass(element, className)) {
779 return className;
780 }
781 }
782 };
783
784 __proto.getCloneIndex = function () {
785 return this.state.cloneIndex;
786 };
787
788 __proto.getClonedPanels = function () {
789 var state = this.state;
790 return state.isClone ? this.original.getClonedPanels() : this.clonedPanels;
791 };
792
793 __proto.getIdenticalPanels = function () {
794 var state = this.state;
795 return state.isClone ? this.original.getIdenticalPanels() : __spreadArrays([this], this.clonedPanels);
796 };
797
798 __proto.getOriginalPanel = function () {
799 return this.state.isClone ? this.original : this;
800 };
801
802 __proto.setIndex = function (index) {
803 var state = this.state;
804 state.index = index;
805 this.clonedPanels.forEach(function (panel) {
806 return panel.state.index = index;
807 });
808 };
809
810 __proto.setPosition = function (pos) {
811 this.state.position = pos;
812 return this;
813 };
814
815 __proto.setPositionCSS = function (offset) {
816 if (offset === void 0) {
817 offset = 0;
818 }
819
820 if (!this.element) {
821 return;
822 }
823
824 var state = this.state;
825 var pos = state.position;
826 var options = this.viewport.options;
827 var elementStyle = this.element.style;
828 var currentElementStyle = options.horizontal ? elementStyle.left : elementStyle.top;
829 var styleToApply = pos - offset + "px";
830
831 if (!state.isVirtual && currentElementStyle !== styleToApply) {
832 options.horizontal ? elementStyle.left = styleToApply : elementStyle.top = styleToApply;
833 }
834 };
835
836 __proto.clone = function (cloneIndex, isVirtual, element) {
837 if (isVirtual === void 0) {
838 isVirtual = false;
839 }
840
841 var state = this.state;
842 var viewport = this.viewport;
843 var cloneElement = element;
844
845 if (!cloneElement && this.element) {
846 cloneElement = isVirtual ? this.element : this.element.cloneNode(true);
847 }
848
849 var clonedPanel = new Panel(cloneElement, state.index, viewport);
850 var clonedState = clonedPanel.state;
851 clonedPanel.original = state.isClone ? this.original : this;
852 clonedState.isClone = true;
853 clonedState.isVirtual = isVirtual;
854 clonedState.cloneIndex = cloneIndex; // Inherit some state values
855
856 clonedState.size = state.size;
857 clonedState.relativeAnchorPosition = state.relativeAnchorPosition;
858 clonedState.originalStyle = state.originalStyle;
859 clonedState.cachedBbox = state.cachedBbox;
860
861 if (!isVirtual) {
862 this.clonedPanels.push(clonedPanel);
863 } else {
864 clonedPanel.prevSibling = this.prevSibling;
865 clonedPanel.nextSibling = this.nextSibling;
866 }
867
868 return clonedPanel;
869 };
870
871 __proto.removeElement = function () {
872 if (!this.viewport.options.renderExternal) {
873 var element = this.element;
874 element.parentNode && element.parentNode.removeChild(element);
875 } // Do the same thing for clones
876
877
878 if (!this.state.isClone) {
879 this.removeClonedPanelsAfter(0);
880 }
881 };
882
883 __proto.removeClonedPanelsAfter = function (start) {
884 var options = this.viewport.options;
885 var removingPanels = this.clonedPanels.splice(start);
886
887 if (!options.renderExternal) {
888 removingPanels.forEach(function (panel) {
889 panel.removeElement();
890 });
891 }
892 };
893
894 __proto.setElement = function (element) {
895 if (!element) {
896 return;
897 }
898
899 var currentElement = this.element;
900
901 if (element !== currentElement) {
902 var options = this.viewport.options;
903
904 if (currentElement) {
905 if (options.horizontal) {
906 element.style.left = currentElement.style.left;
907 } else {
908 element.style.top = currentElement.style.top;
909 }
910 } else {
911 var originalStyle = this.state.originalStyle;
912 originalStyle.className = element.getAttribute("class");
913 originalStyle.style = element.getAttribute("style");
914 }
915
916 this.element = element;
917
918 if (options.classPrefix) {
919 addClass(element, options.classPrefix + "-panel");
920 } // Update size info after applying panel css
921
922
923 applyCSS(this.element, DEFAULT_PANEL_CSS);
924 }
925 };
926
927 return Panel;
928 }();
929
930 /**
931 * Copyright (c) 2015 NAVER Corp.
932 * egjs projects are licensed under the MIT license
933 */
934
935 var PanelManager =
936 /*#__PURE__*/
937 function () {
938 function PanelManager(cameraElement, options) {
939 this.cameraElement = cameraElement;
940 this.panels = [];
941 this.clones = [];
942 this.range = {
943 min: -1,
944 max: -1
945 };
946 this.length = 0;
947 this.cloneCount = 0;
948 this.options = options;
949 this.lastIndex = options.lastIndex;
950 }
951
952 var __proto = PanelManager.prototype;
953
954 __proto.firstPanel = function () {
955 return this.panels[this.range.min];
956 };
957
958 __proto.lastPanel = function () {
959 return this.panels[this.range.max];
960 };
961
962 __proto.allPanels = function () {
963 return __spreadArrays(this.panels, this.clones.reduce(function (allClones, clones) {
964 return __spreadArrays(allClones, clones);
965 }, []));
966 };
967
968 __proto.originalPanels = function () {
969 return this.panels;
970 };
971
972 __proto.clonedPanels = function () {
973 return this.clones;
974 };
975
976 __proto.replacePanels = function (newPanels, newClones) {
977 this.panels = newPanels;
978 this.clones = newClones;
979 this.range = {
980 min: findIndex(newPanels, function (panel) {
981 return Boolean(panel);
982 }),
983 max: newPanels.length - 1
984 };
985 this.length = newPanels.filter(function (panel) {
986 return Boolean(panel);
987 }).length;
988 };
989
990 __proto.has = function (index) {
991 return !!this.panels[index];
992 };
993
994 __proto.get = function (index) {
995 return this.panels[index];
996 };
997
998 __proto.getPanelCount = function () {
999 return this.length;
1000 };
1001
1002 __proto.getLastIndex = function () {
1003 return this.lastIndex;
1004 };
1005
1006 __proto.getRange = function () {
1007 return this.range;
1008 };
1009
1010 __proto.getCloneCount = function () {
1011 return this.cloneCount;
1012 };
1013
1014 __proto.setLastIndex = function (lastIndex) {
1015 this.lastIndex = lastIndex;
1016 var firstPanel = this.firstPanel();
1017 var lastPanel = this.lastPanel();
1018
1019 if (!firstPanel || !lastPanel) {
1020 return; // no meaning of updating range & length
1021 } // Remove panels above new last index
1022
1023
1024 var range = this.range;
1025
1026 if (lastPanel.getIndex() > lastIndex) {
1027 var removingPanels = this.panels.splice(lastIndex + 1);
1028 this.length -= removingPanels.length;
1029 var firstRemovedPanel = removingPanels.filter(function (panel) {
1030 return !!panel;
1031 })[0];
1032 var possibleLastPanel = firstRemovedPanel.prevSibling;
1033
1034 if (possibleLastPanel) {
1035 range.max = possibleLastPanel.getIndex();
1036 } else {
1037 range.min = -1;
1038 range.max = -1;
1039 }
1040
1041 if (this.shouldRender()) {
1042 removingPanels.forEach(function (panel) {
1043 return panel.removeElement();
1044 });
1045 }
1046 }
1047 };
1048
1049 __proto.setCloneCount = function (cloneCount) {
1050 this.cloneCount = cloneCount;
1051 }; // Insert at index
1052 // Returns pushed elements from index, inserting at 'empty' position doesn't push elements behind it
1053
1054
1055 __proto.insert = function (index, newPanels) {
1056 var panels = this.panels;
1057 var range = this.range;
1058 var isCircular = this.options.circular;
1059 var lastIndex = this.lastIndex; // Find first panel that index is greater than inserting index
1060
1061 var nextSibling = this.findFirstPanelFrom(index); // if it's null, element will be inserted at last position
1062 // https://developer.mozilla.org/ko/docs/Web/API/Node/insertBefore#Syntax
1063
1064 var firstPanel = this.firstPanel();
1065 var siblingElement = nextSibling ? nextSibling.getElement() : isCircular && firstPanel ? firstPanel.getClonedPanels()[0].getElement() : null; // Insert panels before sibling element
1066
1067 this.insertNewPanels(newPanels, siblingElement);
1068 var pushedIndex = newPanels.length; // Like when setting index 50 while visible panels are 0, 1, 2
1069
1070 if (index > range.max) {
1071 newPanels.forEach(function (panel, offset) {
1072 panels[index + offset] = panel;
1073 });
1074 } else {
1075 var panelsAfterIndex = panels.slice(index, index + newPanels.length); // Find empty from beginning
1076
1077 var emptyPanelCount = findIndex(panelsAfterIndex, function (panel) {
1078 return !!panel;
1079 });
1080
1081 if (emptyPanelCount < 0) {
1082 // All empty
1083 emptyPanelCount = panelsAfterIndex.length;
1084 }
1085
1086 pushedIndex = newPanels.length - emptyPanelCount; // Insert removing empty panels
1087
1088 panels.splice.apply(panels, __spreadArrays([index, emptyPanelCount], newPanels)); // Remove panels after last index
1089
1090 if (panels.length > lastIndex + 1) {
1091 var removedPanels = panels.splice(lastIndex + 1).filter(function (panel) {
1092 return Boolean(panel);
1093 });
1094 this.length -= removedPanels.length; // Find first
1095
1096 var newLastIndex = lastIndex - findIndex(this.panels.concat().reverse(), function (panel) {
1097 return !!panel;
1098 }); // Can be filled with empty after newLastIndex
1099
1100 this.panels.splice(newLastIndex + 1);
1101 this.range.max = newLastIndex;
1102
1103 if (this.shouldRender()) {
1104 removedPanels.forEach(function (panel) {
1105 return panel.removeElement();
1106 });
1107 }
1108 }
1109 } // Update index of previous panels
1110
1111
1112 if (pushedIndex > 0) {
1113 panels.slice(index + newPanels.length).forEach(function (panel) {
1114 panel.setIndex(panel.getIndex() + pushedIndex);
1115 });
1116 } // Update state
1117
1118
1119 this.length += newPanels.length;
1120 this.updateIndex(index);
1121
1122 if (isCircular) {
1123 this.addNewClones(index, newPanels, newPanels.length - pushedIndex, nextSibling);
1124 var clones = this.clones;
1125 var panelCount_1 = this.panels.length;
1126
1127 if (clones[0] && clones[0].length > lastIndex + 1) {
1128 clones.forEach(function (cloneSet) {
1129 cloneSet.splice(panelCount_1);
1130 });
1131 }
1132 }
1133
1134 return pushedIndex;
1135 };
1136
1137 __proto.replace = function (index, newPanels) {
1138 var panels = this.panels;
1139 var range = this.range;
1140 var options = this.options;
1141 var isCircular = options.circular; // Find first panel that index is greater than inserting index
1142
1143 var nextSibling = this.findFirstPanelFrom(index + newPanels.length); // if it's null, element will be inserted at last position
1144 // https://developer.mozilla.org/ko/docs/Web/API/Node/insertBefore#Syntax
1145
1146 var firstPanel = this.firstPanel();
1147 var siblingElement = nextSibling ? nextSibling.getElement() : isCircular && firstPanel ? firstPanel.getClonedPanels()[0].getElement() : null; // Insert panels before sibling element
1148
1149 this.insertNewPanels(newPanels, siblingElement);
1150
1151 if (index > range.max) {
1152 // Temporarily insert null at index to use splice()
1153 panels[index] = null;
1154 }
1155
1156 var replacedPanels = panels.splice.apply(panels, __spreadArrays([index, newPanels.length], newPanels));
1157 var wasNonEmptyCount = replacedPanels.filter(function (panel) {
1158 return Boolean(panel);
1159 }).length; // Suppose inserting [1, 2, 3] at 0 position when there were [empty, 1]
1160 // So length should be increased by 3(inserting panels) - 1(non-empty panels)
1161
1162 this.length += newPanels.length - wasNonEmptyCount;
1163 this.updateIndex(index);
1164
1165 if (isCircular) {
1166 this.addNewClones(index, newPanels, newPanels.length, nextSibling);
1167 }
1168
1169 if (this.shouldRender()) {
1170 replacedPanels.forEach(function (panel) {
1171 return panel && panel.removeElement();
1172 });
1173 }
1174
1175 return replacedPanels;
1176 };
1177
1178 __proto.remove = function (index, deleteCount) {
1179 if (deleteCount === void 0) {
1180 deleteCount = 1;
1181 }
1182
1183 var isCircular = this.options.circular;
1184 var panels = this.panels;
1185 var clones = this.clones; // Delete count should be equal or larger than 0
1186
1187 deleteCount = Math.max(deleteCount, 0);
1188 var deletedPanels = panels.splice(index, deleteCount).filter(function (panel) {
1189 return !!panel;
1190 });
1191
1192 if (this.shouldRender()) {
1193 deletedPanels.forEach(function (panel) {
1194 return panel.removeElement();
1195 });
1196 }
1197
1198 if (isCircular) {
1199 clones.forEach(function (cloneSet) {
1200 cloneSet.splice(index, deleteCount);
1201 });
1202 } // Update indexes
1203
1204
1205 panels.slice(index).forEach(function (panel) {
1206 panel.setIndex(panel.getIndex() - deleteCount);
1207 }); // Check last panel is empty
1208
1209 var lastIndex = panels.length - 1;
1210
1211 if (!panels[lastIndex]) {
1212 var reversedPanels = panels.concat().reverse();
1213 var nonEmptyIndexFromLast = findIndex(reversedPanels, function (panel) {
1214 return !!panel;
1215 });
1216 lastIndex = nonEmptyIndexFromLast < 0 ? -1 // All empty
1217 : lastIndex - nonEmptyIndexFromLast; // Remove all empty panels from last
1218
1219 panels.splice(lastIndex + 1);
1220
1221 if (isCircular) {
1222 clones.forEach(function (cloneSet) {
1223 cloneSet.splice(lastIndex + 1);
1224 });
1225 }
1226 } // Update range & length
1227
1228
1229 this.range = {
1230 min: findIndex(panels, function (panel) {
1231 return !!panel;
1232 }),
1233 max: lastIndex
1234 };
1235 this.length -= deletedPanels.length;
1236
1237 if (this.length <= 0) {
1238 // Reset clones
1239 this.clones = [];
1240 this.cloneCount = 0;
1241 }
1242
1243 return deletedPanels;
1244 };
1245
1246 __proto.chainAllPanels = function () {
1247 var allPanels = this.allPanels().filter(function (panel) {
1248 return !!panel;
1249 });
1250 var allPanelsCount = allPanels.length;
1251
1252 if (allPanelsCount <= 1) {
1253 return;
1254 }
1255
1256 allPanels.slice(1, allPanels.length - 1).forEach(function (panel, idx) {
1257 var prevPanel = allPanels[idx];
1258 var nextPanel = allPanels[idx + 2];
1259 panel.prevSibling = prevPanel;
1260 panel.nextSibling = nextPanel;
1261 });
1262 var firstPanel = allPanels[0];
1263 var lastPanel = allPanels[allPanelsCount - 1];
1264 firstPanel.prevSibling = null;
1265 firstPanel.nextSibling = allPanels[1];
1266 lastPanel.prevSibling = allPanels[allPanelsCount - 2];
1267 lastPanel.nextSibling = null;
1268
1269 if (this.options.circular) {
1270 firstPanel.prevSibling = lastPanel;
1271 lastPanel.nextSibling = firstPanel;
1272 }
1273 };
1274
1275 __proto.insertClones = function (cloneIndex, index, clonedPanels, deleteCount) {
1276 if (deleteCount === void 0) {
1277 deleteCount = 0;
1278 }
1279
1280 var clones = this.clones;
1281 var lastIndex = this.lastIndex;
1282
1283 if (!clones[cloneIndex]) {
1284 var newClones_1 = [];
1285 clonedPanels.forEach(function (panel, offset) {
1286 newClones_1[index + offset] = panel;
1287 });
1288 clones[cloneIndex] = newClones_1;
1289 } else {
1290 var insertTarget_1 = clones[cloneIndex];
1291
1292 if (index >= insertTarget_1.length) {
1293 clonedPanels.forEach(function (panel, offset) {
1294 insertTarget_1[index + offset] = panel;
1295 });
1296 } else {
1297 insertTarget_1.splice.apply(insertTarget_1, __spreadArrays([index, deleteCount], clonedPanels)); // Remove panels after last index
1298
1299 if (clonedPanels.length > lastIndex + 1) {
1300 clonedPanels.splice(lastIndex + 1);
1301 }
1302 }
1303 }
1304 }; // clones are operating in set
1305
1306
1307 __proto.removeClonesAfter = function (cloneIndex) {
1308 var panels = this.panels;
1309 panels.forEach(function (panel) {
1310 panel.removeClonedPanelsAfter(cloneIndex);
1311 });
1312 this.clones.splice(cloneIndex);
1313 };
1314
1315 __proto.findPanelOf = function (element) {
1316 var allPanels = this.allPanels();
1317
1318 for (var _i = 0, allPanels_1 = allPanels; _i < allPanels_1.length; _i++) {
1319 var panel = allPanels_1[_i];
1320
1321 if (!panel) {
1322 continue;
1323 }
1324
1325 var panelElement = panel.getElement();
1326
1327 if (panelElement.contains(element)) {
1328 return panel;
1329 }
1330 }
1331 };
1332
1333 __proto.findFirstPanelFrom = function (index) {
1334 for (var _i = 0, _a = this.panels.slice(index); _i < _a.length; _i++) {
1335 var panel = _a[_i];
1336
1337 if (panel && panel.getIndex() >= index && panel.getElement().parentNode) {
1338 return panel;
1339 }
1340 }
1341 };
1342
1343 __proto.addNewClones = function (index, originalPanels, deleteCount, nextSibling) {
1344 var _this = this;
1345
1346 var cameraElement = this.cameraElement;
1347 var cloneCount = this.getCloneCount();
1348 var lastPanel = this.lastPanel();
1349 var lastPanelClones = lastPanel ? lastPanel.getClonedPanels() : [];
1350 var nextSiblingClones = nextSibling ? nextSibling.getClonedPanels() : [];
1351
1352 var _loop_1 = function (cloneIndex) {
1353 var cloneNextSibling = nextSiblingClones[cloneIndex];
1354 var lastPanelSibling = lastPanelClones[cloneIndex];
1355 var cloneSiblingElement = cloneNextSibling ? cloneNextSibling.getElement() : lastPanelSibling ? lastPanelSibling.getElement().nextElementSibling : null;
1356 var newClones = originalPanels.map(function (panel) {
1357 var clone = panel.clone(cloneIndex);
1358
1359 if (_this.shouldRender()) {
1360 cameraElement.insertBefore(clone.getElement(), cloneSiblingElement);
1361 }
1362
1363 return clone;
1364 });
1365 this_1.insertClones(cloneIndex, index, newClones, deleteCount);
1366 };
1367
1368 var this_1 = this;
1369
1370 for (var _i = 0, _a = counter(cloneCount); _i < _a.length; _i++) {
1371 var cloneIndex = _a[_i];
1372
1373 _loop_1(cloneIndex);
1374 }
1375 };
1376
1377 __proto.updateIndex = function (insertingIndex) {
1378 var panels = this.panels;
1379 var range = this.range;
1380 var newLastIndex = panels.length - 1;
1381
1382 if (newLastIndex > range.max) {
1383 range.max = newLastIndex;
1384 }
1385
1386 if (insertingIndex < range.min || range.min < 0) {
1387 range.min = insertingIndex;
1388 }
1389 };
1390
1391 __proto.insertNewPanels = function (newPanels, siblingElement) {
1392 if (this.shouldRender()) {
1393 var fragment_1 = document.createDocumentFragment();
1394 newPanels.forEach(function (panel) {
1395 return fragment_1.appendChild(panel.getElement());
1396 });
1397 this.cameraElement.insertBefore(fragment_1, siblingElement);
1398 }
1399 };
1400
1401 __proto.shouldRender = function () {
1402 var options = this.options;
1403 return !options.renderExternal && !options.renderOnlyVisible;
1404 };
1405
1406 return PanelManager;
1407 }();
1408
1409 /**
1410 * Copyright (c) 2015 NAVER Corp.
1411 * egjs projects are licensed under the MIT license
1412 */
1413 var State =
1414 /*#__PURE__*/
1415 function () {
1416 function State() {
1417 this.delta = 0;
1418 this.direction = null;
1419 this.targetPanel = null;
1420 this.lastPosition = 0;
1421 }
1422
1423 var __proto = State.prototype;
1424
1425 __proto.onEnter = function (prevState) {
1426 this.delta = prevState.delta;
1427 this.direction = prevState.direction;
1428 this.targetPanel = prevState.targetPanel;
1429 this.lastPosition = prevState.lastPosition;
1430 };
1431
1432 __proto.onExit = function (nextState) {// DO NOTHING
1433 };
1434
1435 __proto.onHold = function (e, context) {// DO NOTHING
1436 };
1437
1438 __proto.onChange = function (e, context) {// DO NOTHING
1439 };
1440
1441 __proto.onRelease = function (e, context) {// DO NOTHING
1442 };
1443
1444 __proto.onAnimationEnd = function (e, context) {// DO NOTHING
1445 };
1446
1447 __proto.onFinish = function (e, context) {// DO NOTHING
1448 };
1449
1450 return State;
1451 }();
1452
1453 /**
1454 * Copyright (c) 2015 NAVER Corp.
1455 * egjs projects are licensed under the MIT license
1456 */
1457
1458 var IdleState =
1459 /*#__PURE__*/
1460 function (_super) {
1461 __extends(IdleState, _super);
1462
1463 function IdleState() {
1464 var _this = _super !== null && _super.apply(this, arguments) || this;
1465
1466 _this.type = STATE_TYPE.IDLE;
1467 _this.holding = false;
1468 _this.playing = false;
1469 return _this;
1470 }
1471
1472 var __proto = IdleState.prototype;
1473
1474 __proto.onEnter = function () {
1475 this.direction = null;
1476 this.targetPanel = null;
1477 this.delta = 0;
1478 this.lastPosition = 0;
1479 };
1480
1481 __proto.onHold = function (e, _a) {
1482 var flicking = _a.flicking,
1483 viewport = _a.viewport,
1484 triggerEvent = _a.triggerEvent,
1485 transitTo = _a.transitTo; // Shouldn't do any action until any panels on flicking area
1486
1487 if (flicking.getPanelCount() <= 0) {
1488 if (viewport.options.infinite) {
1489 viewport.moveCamera(viewport.getCameraPosition(), e);
1490 }
1491
1492 transitTo(STATE_TYPE.DISABLED);
1493 return;
1494 }
1495
1496 this.lastPosition = viewport.getCameraPosition();
1497 triggerEvent(EVENTS.HOLD_START, e, true).onSuccess(function () {
1498 transitTo(STATE_TYPE.HOLDING);
1499 }).onStopped(function () {
1500 transitTo(STATE_TYPE.DISABLED);
1501 });
1502 }; // By methods call
1503
1504
1505 __proto.onChange = function (e, context) {
1506 var triggerEvent = context.triggerEvent,
1507 transitTo = context.transitTo;
1508 triggerEvent(EVENTS.MOVE_START, e, false).onSuccess(function () {
1509 // Trigger AnimatingState's onChange, to trigger "move" event immediately
1510 transitTo(STATE_TYPE.ANIMATING).onChange(e, context);
1511 }).onStopped(function () {
1512 transitTo(STATE_TYPE.DISABLED);
1513 });
1514 };
1515
1516 return IdleState;
1517 }(State);
1518
1519 /**
1520 * Copyright (c) 2015 NAVER Corp.
1521 * egjs projects are licensed under the MIT license
1522 */
1523
1524 var HoldingState =
1525 /*#__PURE__*/
1526 function (_super) {
1527 __extends(HoldingState, _super);
1528
1529 function HoldingState() {
1530 var _this = _super !== null && _super.apply(this, arguments) || this;
1531
1532 _this.type = STATE_TYPE.HOLDING;
1533 _this.holding = true;
1534 _this.playing = true;
1535 _this.releaseEvent = null;
1536 return _this;
1537 }
1538
1539 var __proto = HoldingState.prototype;
1540
1541 __proto.onChange = function (e, context) {
1542 var flicking = context.flicking,
1543 triggerEvent = context.triggerEvent,
1544 transitTo = context.transitTo;
1545 var offset = flicking.options.horizontal ? e.inputEvent.offsetX : e.inputEvent.offsetY;
1546 this.direction = offset < 0 ? DIRECTION.NEXT : DIRECTION.PREV;
1547 triggerEvent(EVENTS.MOVE_START, e, true).onSuccess(function () {
1548 // Trigger DraggingState's onChange, to trigger "move" event immediately
1549 transitTo(STATE_TYPE.DRAGGING).onChange(e, context);
1550 }).onStopped(function () {
1551 transitTo(STATE_TYPE.DISABLED);
1552 });
1553 };
1554
1555 __proto.onRelease = function (e, context) {
1556 var viewport = context.viewport,
1557 triggerEvent = context.triggerEvent,
1558 transitTo = context.transitTo;
1559 triggerEvent(EVENTS.HOLD_END, e, true);
1560
1561 if (e.delta.flick !== 0) {
1562 // Sometimes "release" event on axes triggered before "change" event
1563 // Especially if user flicked panel fast in really short amount of time
1564 // if delta is not zero, that means above case happened.
1565 // Event flow should be HOLD_START -> MOVE_START -> MOVE -> HOLD_END
1566 // At least one move event should be included between holdStart and holdEnd
1567 e.setTo({
1568 flick: viewport.getCameraPosition()
1569 }, 0);
1570 transitTo(STATE_TYPE.IDLE);
1571 return;
1572 } // Can't handle select event here,
1573 // As "finish" axes event happens
1574
1575
1576 this.releaseEvent = e;
1577 };
1578
1579 __proto.onFinish = function (e, _a) {
1580 var viewport = _a.viewport,
1581 triggerEvent = _a.triggerEvent,
1582 transitTo = _a.transitTo; // Should transite to IDLE state before select event
1583 // As user expects hold is already finished
1584
1585 transitTo(STATE_TYPE.IDLE);
1586
1587 if (!this.releaseEvent) {
1588 return;
1589 } // Handle release event here
1590 // To prevent finish event called twice
1591
1592
1593 var releaseEvent = this.releaseEvent; // Static click
1594
1595 var srcEvent = releaseEvent.inputEvent.srcEvent;
1596 var clickedElement;
1597
1598 if (srcEvent.type === "touchend") {
1599 var touchEvent = srcEvent;
1600 var touch = touchEvent.changedTouches[0];
1601 clickedElement = document.elementFromPoint(touch.clientX, touch.clientY);
1602 } else {
1603 clickedElement = srcEvent.target;
1604 }
1605
1606 var clickedPanel = viewport.panelManager.findPanelOf(clickedElement);
1607 var cameraPosition = viewport.getCameraPosition();
1608
1609 if (clickedPanel) {
1610 var clickedPanelPosition = clickedPanel.getPosition();
1611 var direction = clickedPanelPosition > cameraPosition ? DIRECTION.NEXT : clickedPanelPosition < cameraPosition ? DIRECTION.PREV : null; // Don't provide axes event, to use axes instance instead
1612
1613 triggerEvent(EVENTS.SELECT, null, true, {
1614 direction: direction,
1615 index: clickedPanel.getIndex(),
1616 panel: clickedPanel
1617 });
1618 }
1619 };
1620
1621 return HoldingState;
1622 }(State);
1623
1624 /**
1625 * Copyright (c) 2015 NAVER Corp.
1626 * egjs projects are licensed under the MIT license
1627 */
1628
1629 var DraggingState =
1630 /*#__PURE__*/
1631 function (_super) {
1632 __extends(DraggingState, _super);
1633
1634 function DraggingState() {
1635 var _this = _super !== null && _super.apply(this, arguments) || this;
1636
1637 _this.type = STATE_TYPE.DRAGGING;
1638 _this.holding = true;
1639 _this.playing = true;
1640 return _this;
1641 }
1642
1643 var __proto = DraggingState.prototype;
1644
1645 __proto.onChange = function (e, _a) {
1646 var moveCamera = _a.moveCamera,
1647 transitTo = _a.transitTo;
1648
1649 if (!e.delta.flick) {
1650 return;
1651 }
1652
1653 moveCamera(e).onStopped(function () {
1654 transitTo(STATE_TYPE.DISABLED);
1655 });
1656 };
1657
1658 __proto.onRelease = function (e, context) {
1659 var flicking = context.flicking,
1660 viewport = context.viewport,
1661 triggerEvent = context.triggerEvent,
1662 transitTo = context.transitTo,
1663 stopCamera = context.stopCamera;
1664 var delta = this.delta;
1665 var absDelta = Math.abs(delta);
1666 var options = flicking.options;
1667 var horizontal = options.horizontal;
1668 var moveType = viewport.moveType;
1669 var inputEvent = e.inputEvent;
1670 var velocity = horizontal ? inputEvent.velocityX : inputEvent.velocityY;
1671 var inputDelta = horizontal ? inputEvent.deltaX : inputEvent.deltaY;
1672 var isNextDirection = Math.abs(velocity) > 1 ? velocity < 0 : absDelta > 0 ? delta > 0 : inputDelta < 0;
1673 var swipeDistance = viewport.options.bound ? Math.max(absDelta, Math.abs(inputDelta)) : absDelta;
1674 var swipeAngle = inputEvent.deltaX ? Math.abs(180 * Math.atan(inputEvent.deltaY / inputEvent.deltaX) / Math.PI) : 90;
1675 var belowAngleThreshold = horizontal ? swipeAngle <= options.thresholdAngle : swipeAngle > options.thresholdAngle;
1676 var overThreshold = swipeDistance >= options.threshold && belowAngleThreshold;
1677 var moveTypeContext = {
1678 viewport: viewport,
1679 axesEvent: e,
1680 state: this,
1681 swipeDistance: swipeDistance,
1682 isNextDirection: isNextDirection
1683 }; // Update last position to cope with Axes's animating behavior
1684 // Axes uses start position when animation start
1685
1686 triggerEvent(EVENTS.HOLD_END, e, true);
1687 var targetPanel = this.targetPanel;
1688
1689 if (!overThreshold && targetPanel) {
1690 // Interrupted while animating
1691 var interruptDestInfo = moveType.findPanelWhenInterrupted(moveTypeContext);
1692 viewport.moveTo(interruptDestInfo.panel, interruptDestInfo.destPos, interruptDestInfo.eventType, e, interruptDestInfo.duration);
1693 transitTo(STATE_TYPE.ANIMATING);
1694 return;
1695 }
1696
1697 var currentPanel = viewport.getCurrentPanel();
1698 var nearestPanel = viewport.getNearestPanel();
1699
1700 if (!currentPanel || !nearestPanel) {
1701 // There're no panels
1702 e.stop();
1703 transitTo(STATE_TYPE.IDLE);
1704 return;
1705 }
1706
1707 var destInfo = overThreshold ? moveType.findTargetPanel(moveTypeContext) : moveType.findRestorePanel(moveTypeContext);
1708 viewport.moveTo(destInfo.panel, destInfo.destPos, destInfo.eventType, e, destInfo.duration).onSuccess(function () {
1709 transitTo(STATE_TYPE.ANIMATING);
1710 }).onStopped(function () {
1711 transitTo(STATE_TYPE.DISABLED);
1712 stopCamera(e);
1713 });
1714 };
1715
1716 return DraggingState;
1717 }(State);
1718
1719 /**
1720 * Copyright (c) 2015 NAVER Corp.
1721 * egjs projects are licensed under the MIT license
1722 */
1723
1724 var AnimatingState =
1725 /*#__PURE__*/
1726 function (_super) {
1727 __extends(AnimatingState, _super);
1728
1729 function AnimatingState() {
1730 var _this = _super !== null && _super.apply(this, arguments) || this;
1731
1732 _this.type = STATE_TYPE.ANIMATING;
1733 _this.holding = false;
1734 _this.playing = true;
1735 return _this;
1736 }
1737
1738 var __proto = AnimatingState.prototype;
1739
1740 __proto.onHold = function (e, _a) {
1741 var viewport = _a.viewport,
1742 triggerEvent = _a.triggerEvent,
1743 transitTo = _a.transitTo;
1744 var options = viewport.options;
1745 var scrollArea = viewport.getScrollArea();
1746 var scrollAreaSize = viewport.getScrollAreaSize();
1747 var loopCount = Math.floor((this.lastPosition + this.delta - scrollArea.prev) / scrollAreaSize);
1748 var targetPanel = this.targetPanel;
1749
1750 if (options.circular && loopCount !== 0 && targetPanel) {
1751 var cloneCount = viewport.panelManager.getCloneCount();
1752 var originalTargetPosition = targetPanel.getPosition(); // cloneIndex is from -1 to cloneCount - 1
1753
1754 var newCloneIndex = circulate(targetPanel.getCloneIndex() - loopCount, -1, cloneCount - 1, true);
1755 var newTargetPosition = originalTargetPosition - loopCount * scrollAreaSize;
1756 var newTargetPanel = targetPanel.getIdenticalPanels()[newCloneIndex + 1].clone(newCloneIndex, true); // Set new target panel considering looped count
1757
1758 newTargetPanel.setPosition(newTargetPosition);
1759 this.targetPanel = newTargetPanel;
1760 } // Reset last position and delta
1761
1762
1763 this.delta = 0;
1764 this.lastPosition = viewport.getCameraPosition(); // Update current panel as current nearest panel
1765
1766 viewport.setCurrentPanel(viewport.getNearestPanel());
1767 triggerEvent(EVENTS.HOLD_START, e, true).onSuccess(function () {
1768 transitTo(STATE_TYPE.DRAGGING);
1769 }).onStopped(function () {
1770 transitTo(STATE_TYPE.DISABLED);
1771 });
1772 };
1773
1774 __proto.onChange = function (e, _a) {
1775 var moveCamera = _a.moveCamera,
1776 transitTo = _a.transitTo;
1777
1778 if (!e.delta.flick) {
1779 return;
1780 }
1781
1782 moveCamera(e).onStopped(function () {
1783 transitTo(STATE_TYPE.DISABLED);
1784 });
1785 };
1786
1787 __proto.onFinish = function (e, _a) {
1788 var flicking = _a.flicking,
1789 viewport = _a.viewport,
1790 triggerEvent = _a.triggerEvent,
1791 transitTo = _a.transitTo;
1792 var isTrusted = e && e.isTrusted;
1793 viewport.options.bound ? viewport.setCurrentPanel(this.targetPanel) : viewport.setCurrentPanel(viewport.getNearestPanel());
1794
1795 if (flicking.options.adaptive) {
1796 viewport.updateAdaptiveSize();
1797 }
1798
1799 transitTo(STATE_TYPE.IDLE);
1800 viewport.updateCameraPosition();
1801 triggerEvent(EVENTS.MOVE_END, e, isTrusted, {
1802 direction: this.direction
1803 });
1804 };
1805
1806 return AnimatingState;
1807 }(State);
1808
1809 /**
1810 * Copyright (c) 2015 NAVER Corp.
1811 * egjs projects are licensed under the MIT license
1812 */
1813
1814 var DisabledState =
1815 /*#__PURE__*/
1816 function (_super) {
1817 __extends(DisabledState, _super);
1818
1819 function DisabledState() {
1820 var _this = _super !== null && _super.apply(this, arguments) || this;
1821
1822 _this.type = STATE_TYPE.DISABLED;
1823 _this.holding = false;
1824 _this.playing = true;
1825 return _this;
1826 }
1827
1828 var __proto = DisabledState.prototype;
1829
1830 __proto.onAnimationEnd = function (e, _a) {
1831 var transitTo = _a.transitTo;
1832 transitTo(STATE_TYPE.IDLE);
1833 };
1834
1835 __proto.onChange = function (e, _a) {
1836 var viewport = _a.viewport,
1837 transitTo = _a.transitTo; // Can stop Axes's change event
1838
1839 e.stop(); // Should update axes position as it's already changed at this moment
1840
1841 viewport.updateAxesPosition(viewport.getCameraPosition());
1842 transitTo(STATE_TYPE.IDLE);
1843 };
1844
1845 __proto.onRelease = function (e, _a) {
1846 var transitTo = _a.transitTo; // This is needed when stopped hold start event
1847
1848 if (e.delta.flick === 0) {
1849 transitTo(STATE_TYPE.IDLE);
1850 }
1851 };
1852
1853 return DisabledState;
1854 }(State);
1855
1856 /**
1857 * Copyright (c) 2015 NAVER Corp.
1858 * egjs projects are licensed under the MIT license
1859 */
1860
1861 var StateMachine =
1862 /*#__PURE__*/
1863 function () {
1864 function StateMachine() {
1865 var _this = this;
1866
1867 this.state = new IdleState();
1868
1869 this.transitTo = function (nextStateType) {
1870 var currentState = _this.state;
1871
1872 if (currentState.type !== nextStateType) {
1873 var nextState = void 0;
1874
1875 switch (nextStateType) {
1876 case STATE_TYPE.IDLE:
1877 nextState = new IdleState();
1878 break;
1879
1880 case STATE_TYPE.HOLDING:
1881 nextState = new HoldingState();
1882 break;
1883
1884 case STATE_TYPE.DRAGGING:
1885 nextState = new DraggingState();
1886 break;
1887
1888 case STATE_TYPE.ANIMATING:
1889 nextState = new AnimatingState();
1890 break;
1891
1892 case STATE_TYPE.DISABLED:
1893 nextState = new DisabledState();
1894 break;
1895 }
1896
1897 currentState.onExit(nextState);
1898 nextState.onEnter(currentState);
1899 _this.state = nextState;
1900 }
1901
1902 return _this.state;
1903 };
1904 }
1905
1906 var __proto = StateMachine.prototype;
1907
1908 __proto.fire = function (eventType, e, context) {
1909 var currentState = this.state;
1910
1911 switch (eventType) {
1912 case AXES_EVENTS.HOLD:
1913 currentState.onHold(e, context);
1914 break;
1915
1916 case AXES_EVENTS.CHANGE:
1917 currentState.onChange(e, context);
1918 break;
1919
1920 case AXES_EVENTS.RELEASE:
1921 currentState.onRelease(e, context);
1922 break;
1923
1924 case AXES_EVENTS.ANIMATION_END:
1925 currentState.onAnimationEnd(e, context);
1926 break;
1927
1928 case AXES_EVENTS.FINISH:
1929 currentState.onFinish(e, context);
1930 break;
1931 }
1932 };
1933
1934 __proto.getState = function () {
1935 return this.state;
1936 };
1937
1938 return StateMachine;
1939 }();
1940
1941 /**
1942 * Copyright (c) 2015 NAVER Corp.
1943 * egjs projects are licensed under the MIT license
1944 */
1945
1946 var MoveType =
1947 /*#__PURE__*/
1948 function () {
1949 function MoveType() {}
1950
1951 var __proto = MoveType.prototype;
1952
1953 __proto.is = function (type) {
1954 return type === this.type;
1955 };
1956
1957 __proto.findRestorePanel = function (ctx) {
1958 var viewport = ctx.viewport;
1959 var options = viewport.options;
1960 var panel = options.circular ? this.findRestorePanelInCircularMode(ctx) : viewport.getCurrentPanel();
1961 return {
1962 panel: panel,
1963 destPos: viewport.findEstimatedPosition(panel),
1964 duration: options.duration,
1965 eventType: EVENTS.RESTORE
1966 };
1967 };
1968
1969 __proto.findPanelWhenInterrupted = function (ctx) {
1970 var state = ctx.state,
1971 viewport = ctx.viewport;
1972 var targetPanel = state.targetPanel;
1973 return {
1974 panel: targetPanel,
1975 destPos: viewport.findEstimatedPosition(targetPanel),
1976 duration: viewport.options.duration,
1977 eventType: ""
1978 };
1979 }; // Calculate minimum distance to "change" panel
1980
1981
1982 __proto.calcBrinkOfChange = function (ctx) {
1983 var viewport = ctx.viewport,
1984 isNextDirection = ctx.isNextDirection;
1985 var options = viewport.options;
1986 var currentPanel = viewport.getCurrentPanel();
1987 var halfGap = options.gap / 2;
1988 var relativeAnchorPosition = currentPanel.getRelativeAnchorPosition(); // Minimum distance needed to decide prev/next panel as nearest
1989
1990 /*
1991 * | Prev | Next |
1992 * |--------|--------------|
1993 * [][ |<-Anchor ][] <- Panel + Half-Gap
1994 */
1995
1996 var minimumDistanceToChange = isNextDirection ? currentPanel.getSize() - relativeAnchorPosition + halfGap : relativeAnchorPosition + halfGap;
1997 minimumDistanceToChange = Math.max(minimumDistanceToChange, options.threshold);
1998 return minimumDistanceToChange;
1999 };
2000
2001 __proto.findRestorePanelInCircularMode = function (ctx) {
2002 var viewport = ctx.viewport;
2003 var originalPanel = viewport.getCurrentPanel().getOriginalPanel();
2004 var hangerPosition = viewport.getHangerPosition();
2005 var firstClonedPanel = originalPanel.getIdenticalPanels()[1];
2006 var lapped = Math.abs(originalPanel.getAnchorPosition() - hangerPosition) > Math.abs(firstClonedPanel.getAnchorPosition() - hangerPosition);
2007 return !ctx.isNextDirection && lapped ? firstClonedPanel : originalPanel;
2008 };
2009
2010 return MoveType;
2011 }();
2012
2013 /**
2014 * Copyright (c) 2015 NAVER Corp.
2015 * egjs projects are licensed under the MIT license
2016 */
2017
2018 var Snap =
2019 /*#__PURE__*/
2020 function (_super) {
2021 __extends(Snap, _super);
2022
2023 function Snap(count) {
2024 var _this = _super.call(this) || this;
2025
2026 _this.type = MOVE_TYPE.SNAP;
2027 _this.count = count;
2028 return _this;
2029 }
2030
2031 var __proto = Snap.prototype;
2032
2033 __proto.findTargetPanel = function (ctx) {
2034 var viewport = ctx.viewport,
2035 axesEvent = ctx.axesEvent,
2036 swipeDistance = ctx.swipeDistance;
2037 var snapCount = this.count;
2038 var eventDelta = Math.abs(axesEvent.delta.flick);
2039 var currentPanel = viewport.getCurrentPanel();
2040 var nearestPanel = viewport.getNearestPanel();
2041 var minimumDistanceToChange = this.calcBrinkOfChange(ctx);
2042 var nearestIsCurrent = nearestPanel.getIndex() === currentPanel.getIndex(); // This can happen when bounce is 0
2043
2044 var shouldMoveWhenBounceIs0 = viewport.canSetBoundMode() && nearestIsCurrent;
2045 var shouldMoveToAdjacent = !viewport.isOutOfBound() && (swipeDistance <= minimumDistanceToChange || shouldMoveWhenBounceIs0);
2046
2047 if (snapCount > 1 && eventDelta > minimumDistanceToChange) {
2048 return this.findSnappedPanel(ctx);
2049 } else if (shouldMoveToAdjacent) {
2050 return this.findAdjacentPanel(ctx);
2051 } else {
2052 return {
2053 panel: nearestPanel,
2054 duration: viewport.options.duration,
2055 destPos: viewport.findEstimatedPosition(nearestPanel),
2056 // As swipeDistance holds mouse/touch position change regardless of bounce option value
2057 // swipDistance > minimumDistanceToChange can happen in bounce area
2058 // Second condition is for handling that.
2059 eventType: swipeDistance <= minimumDistanceToChange || viewport.isOutOfBound() && nearestIsCurrent ? EVENTS.RESTORE : EVENTS.CHANGE
2060 };
2061 }
2062 };
2063
2064 __proto.findSnappedPanel = function (ctx) {
2065 var axesEvent = ctx.axesEvent,
2066 viewport = ctx.viewport,
2067 state = ctx.state,
2068 isNextDirection = ctx.isNextDirection;
2069 var eventDelta = Math.abs(axesEvent.delta.flick);
2070 var minimumDistanceToChange = this.calcBrinkOfChange(ctx);
2071 var snapCount = this.count;
2072 var options = viewport.options;
2073 var scrollAreaSize = viewport.getScrollAreaSize();
2074 var halfGap = options.gap / 2;
2075 var estimatedHangerPos = axesEvent.destPos.flick + viewport.getRelativeHangerPosition();
2076 var panelToMove = viewport.getNearestPanel();
2077 var cycleIndex = panelToMove.getCloneIndex() + 1; // 0(original) or 1(clone)
2078
2079 var passedPanelCount = 0;
2080
2081 while (passedPanelCount < snapCount) {
2082 // Since panelToMove holds also cloned panels, we should use original panel's position
2083 var originalPanel = panelToMove.getOriginalPanel();
2084 var panelPosition = originalPanel.getPosition() + cycleIndex * scrollAreaSize;
2085 var panelSize = originalPanel.getSize();
2086 var panelNextPosition = panelPosition + panelSize + halfGap;
2087 var panelPrevPosition = panelPosition - halfGap; // Current panelToMove contains destPos
2088
2089 if (isNextDirection && panelNextPosition > estimatedHangerPos || !isNextDirection && panelPrevPosition < estimatedHangerPos) {
2090 break;
2091 }
2092
2093 var siblingPanel = isNextDirection ? panelToMove.nextSibling : panelToMove.prevSibling;
2094
2095 if (!siblingPanel) {
2096 break;
2097 }
2098
2099 var panelIndex = panelToMove.getIndex();
2100 var siblingIndex = siblingPanel.getIndex();
2101
2102 if (isNextDirection && siblingIndex <= panelIndex || !isNextDirection && siblingIndex >= panelIndex) {
2103 cycleIndex = isNextDirection ? cycleIndex + 1 : cycleIndex - 1;
2104 }
2105
2106 panelToMove = siblingPanel;
2107 passedPanelCount += 1;
2108 }
2109
2110 var originalPosition = panelToMove.getOriginalPanel().getPosition();
2111
2112 if (cycleIndex !== 0) {
2113 panelToMove = panelToMove.clone(panelToMove.getCloneIndex(), true);
2114 panelToMove.setPosition(originalPosition + cycleIndex * scrollAreaSize);
2115 }
2116
2117 var defaultDuration = viewport.options.duration;
2118 var duration = clamp(axesEvent.duration, defaultDuration, defaultDuration * passedPanelCount);
2119 return {
2120 panel: panelToMove,
2121 destPos: viewport.findEstimatedPosition(panelToMove),
2122 duration: duration,
2123 eventType: Math.max(eventDelta, state.delta) > minimumDistanceToChange ? EVENTS.CHANGE : EVENTS.RESTORE
2124 };
2125 };
2126
2127 __proto.findAdjacentPanel = function (ctx) {
2128 var viewport = ctx.viewport,
2129 isNextDirection = ctx.isNextDirection;
2130 var options = viewport.options;
2131 var currentIndex = viewport.getCurrentIndex();
2132 var currentPanel = viewport.panelManager.get(currentIndex);
2133 var hangerPosition = viewport.getHangerPosition();
2134 var scrollArea = viewport.getScrollArea();
2135 var firstClonedPanel = currentPanel.getIdenticalPanels()[1];
2136 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
2137
2138 var basePanel = lapped ? firstClonedPanel : currentPanel;
2139 var basePosition = basePanel.getPosition();
2140 var adjacentPanel = isNextDirection ? basePanel.nextSibling : basePanel.prevSibling;
2141 var eventType = adjacentPanel ? EVENTS.CHANGE : EVENTS.RESTORE;
2142 var panelToMove = adjacentPanel ? adjacentPanel : basePanel;
2143 var targetRelativeAnchorPosition = panelToMove.getRelativeAnchorPosition();
2144 var estimatedPanelPosition = options.circular ? isNextDirection ? basePosition + basePanel.getSize() + targetRelativeAnchorPosition + options.gap : basePosition - (panelToMove.getSize() - targetRelativeAnchorPosition) - options.gap : panelToMove.getAnchorPosition();
2145 var estimatedPosition = estimatedPanelPosition - viewport.getRelativeHangerPosition();
2146 var destPos = viewport.canSetBoundMode() ? clamp(estimatedPosition, scrollArea.prev, scrollArea.next) : estimatedPosition;
2147 return {
2148 panel: panelToMove,
2149 destPos: destPos,
2150 duration: options.duration,
2151 eventType: eventType
2152 };
2153 };
2154
2155 return Snap;
2156 }(MoveType);
2157
2158 /**
2159 * Copyright (c) 2015 NAVER Corp.
2160 * egjs projects are licensed under the MIT license
2161 */
2162
2163 var FreeScroll =
2164 /*#__PURE__*/
2165 function (_super) {
2166 __extends(FreeScroll, _super);
2167
2168 function FreeScroll() {
2169 var _this = // Set snap count to Infinity
2170 _super.call(this, Infinity) || this;
2171
2172 _this.type = MOVE_TYPE.FREE_SCROLL;
2173 return _this;
2174 }
2175
2176 var __proto = FreeScroll.prototype;
2177
2178 __proto.findTargetPanel = function (ctx) {
2179 var axesEvent = ctx.axesEvent,
2180 state = ctx.state,
2181 viewport = ctx.viewport;
2182 var destPos = axesEvent.destPos.flick;
2183 var minimumDistanceToChange = this.calcBrinkOfChange(ctx);
2184 var scrollArea = viewport.getScrollArea();
2185 var currentPanel = viewport.getCurrentPanel();
2186 var options = viewport.options;
2187 var delta = Math.abs(axesEvent.delta.flick + state.delta);
2188
2189 if (delta > minimumDistanceToChange) {
2190 var destInfo = _super.prototype.findSnappedPanel.call(this, ctx);
2191
2192 destInfo.duration = axesEvent.duration;
2193 destInfo.destPos = destPos;
2194 destInfo.eventType = !options.circular && destInfo.panel === currentPanel ? "" : EVENTS.CHANGE;
2195 return destInfo;
2196 } else {
2197 var estimatedPosition = options.circular ? circulate(destPos, scrollArea.prev, scrollArea.next, false) : destPos;
2198 estimatedPosition = clamp(estimatedPosition, scrollArea.prev, scrollArea.next);
2199 estimatedPosition += viewport.getRelativeHangerPosition();
2200 var estimatedPanel = viewport.findNearestPanelAt(estimatedPosition);
2201 return {
2202 panel: estimatedPanel,
2203 destPos: destPos,
2204 duration: axesEvent.duration,
2205 eventType: ""
2206 };
2207 }
2208 };
2209
2210 __proto.findRestorePanel = function (ctx) {
2211 return this.findTargetPanel(ctx);
2212 };
2213
2214 __proto.findPanelWhenInterrupted = function (ctx) {
2215 var viewport = ctx.viewport;
2216 return {
2217 panel: viewport.getNearestPanel(),
2218 destPos: viewport.getCameraPosition(),
2219 duration: 0,
2220 eventType: ""
2221 };
2222 };
2223
2224 __proto.calcBrinkOfChange = function (ctx) {
2225 var viewport = ctx.viewport,
2226 isNextDirection = ctx.isNextDirection;
2227 var options = viewport.options;
2228 var currentPanel = viewport.getCurrentPanel();
2229 var halfGap = options.gap / 2;
2230 var lastPosition = viewport.stateMachine.getState().lastPosition;
2231 var currentPanelPosition = currentPanel.getPosition(); // As camera can stop anywhere in free scroll mode,
2232 // minimumDistanceToChange should be calculated differently.
2233 // Ref #191(https://github.com/naver/egjs-flicking/issues/191)
2234
2235 var lastHangerPosition = lastPosition + viewport.getRelativeHangerPosition();
2236 var scrollAreaSize = viewport.getScrollAreaSize();
2237 var minimumDistanceToChange = isNextDirection ? currentPanelPosition + currentPanel.getSize() - lastHangerPosition + halfGap : lastHangerPosition - currentPanelPosition + halfGap;
2238 minimumDistanceToChange = Math.abs(minimumDistanceToChange % scrollAreaSize);
2239 return Math.min(minimumDistanceToChange, scrollAreaSize - minimumDistanceToChange);
2240 };
2241
2242 return FreeScroll;
2243 }(Snap);
2244
2245 var Viewport =
2246 /*#__PURE__*/
2247 function () {
2248 function Viewport(flicking, options, triggerEvent) {
2249 var _this = this;
2250
2251 this.plugins = [];
2252
2253 this.stopCamera = function (axesEvent) {
2254 if (axesEvent && axesEvent.setTo) {
2255 axesEvent.setTo({
2256 flick: _this.state.position
2257 }, 0);
2258 }
2259
2260 _this.stateMachine.transitTo(STATE_TYPE.IDLE);
2261 };
2262
2263 this.flicking = flicking;
2264 this.triggerEvent = triggerEvent;
2265 this.state = {
2266 size: 0,
2267 position: 0,
2268 panelMaintainRatio: 0,
2269 relativeHangerPosition: 0,
2270 positionOffset: 0,
2271 scrollArea: {
2272 prev: 0,
2273 next: 0
2274 },
2275 translate: TRANSFORM,
2276 infiniteThreshold: 0,
2277 checkedIndexes: [],
2278 isAdaptiveCached: false,
2279 isViewportGiven: false,
2280 isCameraGiven: false,
2281 originalViewportStyle: {
2282 className: null,
2283 style: null
2284 },
2285 originalCameraStyle: {
2286 className: null,
2287 style: null
2288 },
2289 cachedBbox: null
2290 };
2291 this.options = options;
2292 this.stateMachine = new StateMachine();
2293 this.visiblePanels = [];
2294 this.panelBboxes = {};
2295 this.build();
2296 }
2297
2298 var __proto = Viewport.prototype;
2299
2300 __proto.moveTo = function (panel, destPos, eventType, axesEvent, duration) {
2301 var _this = this;
2302
2303 if (duration === void 0) {
2304 duration = this.options.duration;
2305 }
2306
2307 var state = this.state;
2308 var currentState = this.stateMachine.getState();
2309 var currentPosition = state.position;
2310 var isTrusted = axesEvent ? axesEvent.isTrusted : false;
2311 var direction = destPos === currentPosition ? null : destPos > currentPosition ? DIRECTION.NEXT : DIRECTION.PREV;
2312 var eventResult;
2313
2314 if (eventType === EVENTS.CHANGE) {
2315 eventResult = this.triggerEvent(EVENTS.CHANGE, axesEvent, isTrusted, {
2316 index: panel.getIndex(),
2317 panel: panel,
2318 direction: direction
2319 });
2320 } else if (eventType === EVENTS.RESTORE) {
2321 eventResult = this.triggerEvent(EVENTS.RESTORE, axesEvent, isTrusted);
2322 } else {
2323 eventResult = {
2324 onSuccess: function (callback) {
2325 callback();
2326 return this;
2327 },
2328 onStopped: function () {
2329 return this;
2330 }
2331 };
2332 }
2333
2334 eventResult.onSuccess(function () {
2335 currentState.delta = 0;
2336 currentState.lastPosition = _this.getCameraPosition();
2337 currentState.targetPanel = panel;
2338 currentState.direction = destPos === currentPosition ? null : destPos > currentPosition ? DIRECTION.NEXT : DIRECTION.PREV;
2339
2340 if (destPos === currentPosition) {
2341 // no move
2342 _this.nearestPanel = panel;
2343 _this.currentPanel = panel;
2344 }
2345
2346 if (axesEvent && axesEvent.setTo) {
2347 // freeScroll only occurs in release events
2348 axesEvent.setTo({
2349 flick: destPos
2350 }, duration);
2351 } else {
2352 _this.axes.setTo({
2353 flick: destPos
2354 }, duration);
2355 }
2356 });
2357 return eventResult;
2358 };
2359
2360 __proto.moveCamera = function (pos, axesEvent) {
2361 var state = this.state;
2362 var options = this.options;
2363 var transform = state.translate.name;
2364 var scrollArea = state.scrollArea; // Update position & nearestPanel
2365
2366 if (options.circular && !isBetween(pos, scrollArea.prev, scrollArea.next)) {
2367 pos = circulate(pos, scrollArea.prev, scrollArea.next, false);
2368 }
2369
2370 state.position = pos;
2371 this.nearestPanel = this.findNearestPanel();
2372 var nearestPanel = this.nearestPanel;
2373 var originalNearestPosition = nearestPanel ? nearestPanel.getPosition() : 0; // From 0(panel position) to 1(panel position + panel size)
2374 // When it's on gap area value will be (val > 1 || val < 0)
2375
2376 if (nearestPanel) {
2377 var hangerPosition = this.getHangerPosition();
2378 var panelPosition = nearestPanel.getPosition();
2379 var panelSize = nearestPanel.getSize();
2380 var halfGap = options.gap / 2; // As panel's range is from panel position - half gap ~ panel pos + panel size + half gap
2381
2382 state.panelMaintainRatio = (hangerPosition - panelPosition + halfGap) / (panelSize + 2 * halfGap);
2383 } else {
2384 state.panelMaintainRatio = 0;
2385 }
2386
2387 this.checkNeedPanel(axesEvent); // Possibly modified after need panel, if it's looped
2388
2389 var modifiedNearestPosition = nearestPanel ? nearestPanel.getPosition() : 0;
2390 pos += modifiedNearestPosition - originalNearestPosition;
2391 state.position = pos;
2392 this.updateVisiblePanels(); // Offset is needed to fix camera layer size in visible-only rendering mode
2393
2394 var posOffset = options.renderOnlyVisible ? state.positionOffset : 0;
2395 var moveVector = options.horizontal ? [-(pos - posOffset), 0] : [0, -(pos - posOffset)];
2396 var moveCoord = moveVector.map(function (coord) {
2397 return Math.round(coord) + "px";
2398 }).join(", ");
2399 this.cameraElement.style[transform] = state.translate.has3d ? "translate3d(" + moveCoord + ", 0px)" : "translate(" + moveCoord + ")";
2400 };
2401
2402 __proto.unCacheBbox = function () {
2403 var state = this.state;
2404 var options = this.options;
2405 state.cachedBbox = null;
2406 this.visiblePanels = [];
2407 var viewportElement = this.viewportElement;
2408
2409 if (!options.horizontal) {
2410 // Don't preserve previous width for adaptive resizing
2411 viewportElement.style.width = "";
2412 } else {
2413 viewportElement.style.height = "";
2414 }
2415
2416 state.isAdaptiveCached = false;
2417 this.panelBboxes = {};
2418 };
2419
2420 __proto.resize = function () {
2421 this.updateSize();
2422 this.updateOriginalPanelPositions();
2423 this.updateAdaptiveSize();
2424 this.updateScrollArea();
2425 this.updateClonePanels();
2426 this.updateVisiblePanelPositions();
2427 this.updateCameraPosition();
2428 this.updatePlugins();
2429 }; // Find nearest anchor from current hanger position
2430
2431
2432 __proto.findNearestPanel = function () {
2433 var state = this.state;
2434 var panelManager = this.panelManager;
2435 var hangerPosition = this.getHangerPosition();
2436
2437 if (this.isOutOfBound()) {
2438 var position = state.position;
2439 return position <= state.scrollArea.prev ? panelManager.firstPanel() : panelManager.lastPanel();
2440 }
2441
2442 return this.findNearestPanelAt(hangerPosition);
2443 };
2444
2445 __proto.findNearestPanelAt = function (position) {
2446 var panelManager = this.panelManager;
2447 var allPanels = panelManager.allPanels();
2448 var minimumDistance = Infinity;
2449 var nearestPanel;
2450
2451 for (var _i = 0, allPanels_1 = allPanels; _i < allPanels_1.length; _i++) {
2452 var panel = allPanels_1[_i];
2453
2454 if (!panel) {
2455 continue;
2456 }
2457
2458 var prevPosition = panel.getPosition();
2459 var nextPosition = prevPosition + panel.getSize(); // Use shortest distance from panel's range
2460
2461 var distance = isBetween(position, prevPosition, nextPosition) ? 0 : Math.min(Math.abs(prevPosition - position), Math.abs(nextPosition - position));
2462
2463 if (distance > minimumDistance) {
2464 break;
2465 } else if (distance === minimumDistance) {
2466 var minimumAnchorDistance = Math.abs(position - nearestPanel.getAnchorPosition());
2467 var anchorDistance = Math.abs(position - panel.getAnchorPosition());
2468
2469 if (anchorDistance > minimumAnchorDistance) {
2470 break;
2471 }
2472 }
2473
2474 minimumDistance = distance;
2475 nearestPanel = panel;
2476 }
2477
2478 return nearestPanel;
2479 };
2480
2481 __proto.findNearestIdenticalPanel = function (panel) {
2482 var nearest = panel;
2483 var shortestDistance = Infinity;
2484 var hangerPosition = this.getHangerPosition();
2485 var identicals = panel.getIdenticalPanels();
2486 identicals.forEach(function (identical) {
2487 var anchorPosition = identical.getAnchorPosition();
2488 var distance = Math.abs(anchorPosition - hangerPosition);
2489
2490 if (distance < shortestDistance) {
2491 nearest = identical;
2492 shortestDistance = distance;
2493 }
2494 });
2495 return nearest;
2496 }; // Find shortest camera position that distance is minimum
2497
2498
2499 __proto.findShortestPositionToPanel = function (panel) {
2500 var state = this.state;
2501 var options = this.options;
2502 var anchorPosition = panel.getAnchorPosition();
2503 var hangerPosition = this.getHangerPosition();
2504 var distance = Math.abs(hangerPosition - anchorPosition);
2505 var scrollAreaSize = state.scrollArea.next - state.scrollArea.prev;
2506
2507 if (!options.circular) {
2508 var position = anchorPosition - state.relativeHangerPosition;
2509 return this.canSetBoundMode() ? clamp(position, state.scrollArea.prev, state.scrollArea.next) : position;
2510 } else {
2511 // If going out of viewport border is more efficient way of moving, choose that position
2512 return distance <= scrollAreaSize - distance ? anchorPosition - state.relativeHangerPosition : anchorPosition > hangerPosition // PREV TO NEXT
2513 ? anchorPosition - state.relativeHangerPosition - scrollAreaSize // NEXT TO PREV
2514 : anchorPosition - state.relativeHangerPosition + scrollAreaSize;
2515 }
2516 };
2517
2518 __proto.findEstimatedPosition = function (panel) {
2519 var scrollArea = this.getScrollArea();
2520 var estimatedPosition = panel.getAnchorPosition() - this.getRelativeHangerPosition();
2521 estimatedPosition = this.canSetBoundMode() ? clamp(estimatedPosition, scrollArea.prev, scrollArea.next) : estimatedPosition;
2522 return estimatedPosition;
2523 };
2524
2525 __proto.addVisiblePanel = function (panel) {
2526 if (this.getVisibleIndexOf(panel) < 0) {
2527 this.visiblePanels.push(panel);
2528 }
2529 };
2530
2531 __proto.enable = function () {
2532 if (!this.panInput) {
2533 this.createPanInput();
2534 }
2535 };
2536
2537 __proto.disable = function () {
2538 if (this.panInput) {
2539 this.panInput.destroy();
2540 this.panInput = null;
2541 this.stateMachine.transitTo(STATE_TYPE.IDLE);
2542 }
2543 };
2544
2545 __proto.insert = function (index, element) {
2546 var _this = this;
2547
2548 var lastIndex = this.panelManager.getLastIndex(); // Index should not below 0
2549
2550 if (index < 0 || index > lastIndex) {
2551 return [];
2552 }
2553
2554 var state = this.state;
2555 var options = this.options;
2556 var parsedElements = parseElement(element);
2557 var panels = parsedElements.map(function (el, idx) {
2558 return new Panel(el, index + idx, _this);
2559 }).slice(0, lastIndex - index + 1);
2560
2561 if (panels.length <= 0) {
2562 return [];
2563 }
2564
2565 var pushedIndex = this.panelManager.insert(index, panels); // ...then calc bbox for all panels
2566
2567 this.resizePanels(panels);
2568
2569 if (!this.currentPanel) {
2570 this.currentPanel = panels[0];
2571 this.nearestPanel = panels[0];
2572 var newCenterPanel = panels[0];
2573 var newPanelPosition = this.findEstimatedPosition(newCenterPanel);
2574 state.position = newPanelPosition;
2575 this.updateAxesPosition(newPanelPosition);
2576 state.panelMaintainRatio = (newCenterPanel.getRelativeAnchorPosition() + options.gap / 2) / (newCenterPanel.getSize() + options.gap);
2577 } // Update checked indexes in infinite mode
2578
2579
2580 this.updateCheckedIndexes({
2581 min: index,
2582 max: index
2583 });
2584 state.checkedIndexes.forEach(function (indexes, idx) {
2585 var min = indexes[0],
2586 max = indexes[1];
2587
2588 if (index < min) {
2589 // Push checked index
2590 state.checkedIndexes.splice(idx, 1, [min + pushedIndex, max + pushedIndex]);
2591 }
2592 });
2593 this.resize();
2594 return panels;
2595 };
2596
2597 __proto.replace = function (index, element) {
2598 var _this = this;
2599
2600 var state = this.state;
2601 var options = this.options;
2602 var panelManager = this.panelManager;
2603 var lastIndex = panelManager.getLastIndex(); // Index should not below 0
2604
2605 if (index < 0 || index > lastIndex) {
2606 return [];
2607 }
2608
2609 var parsedElements = parseElement(element);
2610 var panels = parsedElements.map(function (el, idx) {
2611 return new Panel(el, index + idx, _this);
2612 }).slice(0, lastIndex - index + 1);
2613
2614 if (panels.length <= 0) {
2615 return [];
2616 }
2617
2618 var replacedPanels = panelManager.replace(index, panels);
2619 replacedPanels.forEach(function (panel) {
2620 var visibleIndex = _this.getVisibleIndexOf(panel);
2621
2622 if (visibleIndex > -1) {
2623 _this.visiblePanels.splice(visibleIndex, 1);
2624 }
2625 }); // ...then calc bbox for all panels
2626
2627 this.resizePanels(panels);
2628 var currentPanel = this.currentPanel;
2629 var wasEmpty = !currentPanel;
2630
2631 if (wasEmpty) {
2632 this.currentPanel = panels[0];
2633 this.nearestPanel = panels[0];
2634 var newCenterPanel = panels[0];
2635 var newPanelPosition = this.findEstimatedPosition(newCenterPanel);
2636 state.position = newPanelPosition;
2637 this.updateAxesPosition(newPanelPosition);
2638 state.panelMaintainRatio = (newCenterPanel.getRelativeAnchorPosition() + options.gap / 2) / (newCenterPanel.getSize() + options.gap);
2639 } else if (isBetween(currentPanel.getIndex(), index, index + panels.length - 1)) {
2640 // Current panel is replaced
2641 this.currentPanel = panelManager.get(currentPanel.getIndex());
2642 } // Update checked indexes in infinite mode
2643
2644
2645 this.updateCheckedIndexes({
2646 min: index,
2647 max: index + panels.length - 1
2648 });
2649 this.resize();
2650 return panels;
2651 };
2652
2653 __proto.remove = function (index, deleteCount) {
2654 if (deleteCount === void 0) {
2655 deleteCount = 1;
2656 }
2657
2658 var state = this.state; // Index should not below 0
2659
2660 index = Math.max(index, 0);
2661 var panelManager = this.panelManager;
2662 var currentIndex = this.getCurrentIndex();
2663 var removedPanels = panelManager.remove(index, deleteCount);
2664
2665 if (isBetween(currentIndex, index, index + deleteCount - 1)) {
2666 // Current panel is removed
2667 // Use panel at removing index - 1 as new current panel if it exists
2668 var newCurrentIndex = Math.max(index - 1, panelManager.getRange().min);
2669 this.currentPanel = panelManager.get(newCurrentIndex);
2670 } // Update checked indexes in infinite mode
2671
2672
2673 if (deleteCount > 0) {
2674 // Check whether removing index will affect checked indexes
2675 // Suppose index 0 is empty and removed index 1, then checked index 0 should be deleted and vice versa.
2676 this.updateCheckedIndexes({
2677 min: index - 1,
2678 max: index + deleteCount
2679 }); // Uncache visible panels to refresh panels
2680
2681 this.visiblePanels = [];
2682 }
2683
2684 if (panelManager.getPanelCount() <= 0) {
2685 this.currentPanel = undefined;
2686 this.nearestPanel = undefined;
2687 }
2688
2689 this.resize();
2690 var scrollArea = state.scrollArea;
2691
2692 if (state.position < scrollArea.prev || state.position > scrollArea.next) {
2693 var newPosition = circulate(state.position, scrollArea.prev, scrollArea.next, false);
2694 this.moveCamera(newPosition);
2695 this.updateAxesPosition(newPosition);
2696 }
2697
2698 return removedPanels;
2699 };
2700
2701 __proto.updateAdaptiveSize = function () {
2702 var state = this.state;
2703 var options = this.options;
2704 var horizontal = options.horizontal;
2705 var currentPanel = this.getCurrentPanel();
2706
2707 if (!currentPanel) {
2708 return;
2709 }
2710
2711 var shouldApplyAdaptive = options.adaptive || !state.isAdaptiveCached;
2712 var viewportStyle = this.viewportElement.style;
2713
2714 if (shouldApplyAdaptive) {
2715 var sizeToApply = void 0;
2716
2717 if (options.adaptive) {
2718 var panelBbox = currentPanel.getBbox();
2719 sizeToApply = horizontal ? panelBbox.height : panelBbox.width;
2720 } else {
2721 // Find minimum height of panels to maximum panel size
2722 var maximumPanelSize = this.panelManager.originalPanels().reduce(function (maximum, panel) {
2723 var panelBbox = panel.getBbox();
2724 return Math.max(maximum, horizontal ? panelBbox.height : panelBbox.width);
2725 }, 0);
2726 sizeToApply = maximumPanelSize;
2727 }
2728
2729 if (!state.isAdaptiveCached) {
2730 var viewportBbox = this.updateBbox();
2731 sizeToApply = Math.max(sizeToApply, horizontal ? viewportBbox.height : viewportBbox.width);
2732 state.isAdaptiveCached = true;
2733 }
2734
2735 var viewportSize = sizeToApply + "px";
2736
2737 if (horizontal) {
2738 viewportStyle.height = viewportSize;
2739 state.cachedBbox.height = sizeToApply;
2740 } else {
2741 viewportStyle.width = viewportSize;
2742 state.cachedBbox.width = sizeToApply;
2743 }
2744 }
2745 }; // Update camera position after resizing
2746
2747
2748 __proto.updateCameraPosition = function () {
2749 var state = this.state;
2750 var currentPanel = this.getCurrentPanel();
2751 var cameraPosition = this.getCameraPosition();
2752 var currentState = this.stateMachine.getState();
2753 var isFreeScroll = this.moveType.is(MOVE_TYPE.FREE_SCROLL);
2754 var relativeHangerPosition = this.getRelativeHangerPosition();
2755 var halfGap = this.options.gap / 2;
2756
2757 if (currentState.holding || currentState.playing) {
2758 this.updateVisiblePanels();
2759 return;
2760 }
2761
2762 var newPosition;
2763
2764 if (isFreeScroll) {
2765 var positionBounded = this.canSetBoundMode() && (cameraPosition === state.scrollArea.prev || cameraPosition === state.scrollArea.next);
2766 var nearestPanel = this.getNearestPanel(); // Preserve camera position if it is bound to scroll area limit
2767
2768 newPosition = positionBounded || !nearestPanel ? cameraPosition : nearestPanel.getPosition() - halfGap + (nearestPanel.getSize() + 2 * halfGap) * state.panelMaintainRatio - relativeHangerPosition;
2769 } else {
2770 newPosition = currentPanel ? currentPanel.getAnchorPosition() - relativeHangerPosition : cameraPosition;
2771 }
2772
2773 if (this.canSetBoundMode()) {
2774 newPosition = clamp(newPosition, state.scrollArea.prev, state.scrollArea.next);
2775 } // Pause & resume axes to prevent axes's "change" event triggered
2776 // This should be done before moveCamera, as moveCamera can trigger needPanel
2777
2778
2779 this.updateAxesPosition(newPosition);
2780 this.moveCamera(newPosition);
2781 };
2782
2783 __proto.updateBbox = function () {
2784 var state = this.state;
2785 var options = this.options;
2786 var viewportElement = this.viewportElement;
2787
2788 if (!state.cachedBbox) {
2789 state.cachedBbox = getBbox(viewportElement, options.useOffset);
2790 }
2791
2792 return state.cachedBbox;
2793 };
2794
2795 __proto.updatePlugins = function () {
2796 var _this = this; // update for resize
2797
2798
2799 this.plugins.forEach(function (plugin) {
2800 plugin.update && plugin.update(_this.flicking);
2801 });
2802 };
2803
2804 __proto.destroy = function (option) {
2805 var _a;
2806
2807 var state = this.state;
2808 var wrapper = this.flicking.getElement();
2809 var viewportElement = this.viewportElement;
2810 var cameraElement = this.cameraElement;
2811 var originalPanels = this.panelManager.originalPanels();
2812 this.removePlugins(this.plugins);
2813
2814 if (!option.preserveUI) {
2815 restoreStyle(viewportElement, state.originalViewportStyle);
2816 restoreStyle(cameraElement, state.originalCameraStyle);
2817
2818 if (!state.isCameraGiven && !this.options.renderExternal) {
2819 var topmostElement_1 = state.isViewportGiven ? viewportElement : wrapper;
2820 var deletingElement = state.isViewportGiven ? cameraElement : viewportElement;
2821 originalPanels.forEach(function (panel) {
2822 topmostElement_1.appendChild(panel.getElement());
2823 });
2824 topmostElement_1.removeChild(deletingElement);
2825 }
2826 }
2827
2828 this.axes.destroy();
2829 (_a = this.panInput) === null || _a === void 0 ? void 0 : _a.destroy();
2830 originalPanels.forEach(function (panel) {
2831 panel.destroy(option);
2832 }); // release resources
2833
2834 for (var x in this) {
2835 this[x] = null;
2836 }
2837 };
2838
2839 __proto.restore = function (status) {
2840 var panels = status.panels;
2841 var defaultIndex = this.options.defaultIndex;
2842 var cameraElement = this.cameraElement;
2843 var panelManager = this.panelManager; // Restore index
2844
2845 cameraElement.innerHTML = panels.map(function (panel) {
2846 return panel.html;
2847 }).join(""); // Create panels first
2848
2849 this.refreshPanels();
2850 var createdPanels = panelManager.originalPanels(); // ...then order it by its index
2851
2852 var orderedPanels = [];
2853 panels.forEach(function (panel, idx) {
2854 var createdPanel = createdPanels[idx];
2855 createdPanel.setIndex(panel.index);
2856 orderedPanels[panel.index] = createdPanel;
2857 });
2858 panelManager.replacePanels(orderedPanels, []);
2859 panelManager.setCloneCount(0); // No clones at this point
2860
2861 var panelCount = panelManager.getPanelCount();
2862
2863 if (panelCount > 0) {
2864 this.currentPanel = panelManager.get(status.index) || panelManager.get(defaultIndex) || panelManager.firstPanel();
2865 this.nearestPanel = this.currentPanel;
2866 } else {
2867 this.currentPanel = undefined;
2868 this.nearestPanel = undefined;
2869 }
2870
2871 this.visiblePanels = orderedPanels.filter(function (panel) {
2872 return Boolean(panel);
2873 });
2874 this.resize();
2875 this.axes.setTo({
2876 flick: status.position
2877 }, 0);
2878 this.moveCamera(status.position);
2879 };
2880
2881 __proto.calcVisiblePanels = function () {
2882 var allPanels = this.panelManager.allPanels();
2883
2884 if (this.options.renderOnlyVisible) {
2885 var cameraPos_1 = this.getCameraPosition();
2886 var viewportSize_1 = this.getSize();
2887 var basePanel = this.nearestPanel;
2888
2889 var getNextPanel = function (panel) {
2890 var nextPanel = panel.nextSibling;
2891
2892 if (nextPanel && nextPanel.getPosition() >= panel.getPosition()) {
2893 return nextPanel;
2894 } else {
2895 return null;
2896 }
2897 };
2898
2899 var getPrevPanel = function (panel) {
2900 var prevPanel = panel.prevSibling;
2901
2902 if (prevPanel && prevPanel.getPosition() <= panel.getPosition()) {
2903 return prevPanel;
2904 } else {
2905 return null;
2906 }
2907 };
2908
2909 var isOutOfBoundNext = function (panel) {
2910 return panel.getPosition() >= cameraPos_1 + viewportSize_1;
2911 };
2912
2913 var isOutOfBoundPrev = function (panel) {
2914 return panel.getPosition() + panel.getSize() <= cameraPos_1;
2915 };
2916
2917 var getVisiblePanels = function (panel, getNext, isOutOfViewport) {
2918 var visiblePanels = [];
2919 var lastPanel = panel;
2920
2921 while (true) {
2922 var nextPanel = getNext(lastPanel);
2923
2924 if (!nextPanel || isOutOfViewport(nextPanel)) {
2925 break;
2926 }
2927
2928 visiblePanels.push(nextPanel);
2929 lastPanel = nextPanel;
2930 }
2931
2932 return visiblePanels;
2933 };
2934
2935 var panelCount_1 = this.panelManager.getPanelCount();
2936
2937 var getAbsIndex_1 = function (panel) {
2938 return panel.getIndex() + (panel.getCloneIndex() + 1) * panelCount_1;
2939 };
2940
2941 var nextPanels = getVisiblePanels(basePanel, getNextPanel, isOutOfBoundNext);
2942 var prevPanels = getVisiblePanels(basePanel, getPrevPanel, isOutOfBoundPrev);
2943 return __spreadArrays([basePanel], nextPanels, prevPanels).sort(function (panel1, panel2) {
2944 return getAbsIndex_1(panel1) - getAbsIndex_1(panel2);
2945 });
2946 } else {
2947 return allPanels.filter(function (panel) {
2948 var outsetProgress = panel.getOutsetProgress();
2949 return outsetProgress > -1 && outsetProgress < 1;
2950 });
2951 }
2952 };
2953
2954 __proto.getCurrentPanel = function () {
2955 return this.currentPanel;
2956 };
2957
2958 __proto.getCurrentIndex = function () {
2959 var currentPanel = this.currentPanel;
2960 return currentPanel ? currentPanel.getIndex() : -1;
2961 };
2962
2963 __proto.getNearestPanel = function () {
2964 return this.nearestPanel;
2965 }; // Get progress from nearest panel
2966
2967
2968 __proto.getCurrentProgress = function () {
2969 var currentState = this.stateMachine.getState();
2970 var nearestPanel = currentState.playing || currentState.holding ? this.nearestPanel : this.currentPanel;
2971 var panelManager = this.panelManager;
2972
2973 if (!nearestPanel) {
2974 // There're no panels
2975 return NaN;
2976 }
2977
2978 var _a = this.getScrollArea(),
2979 prevRange = _a.prev,
2980 nextRange = _a.next;
2981
2982 var cameraPosition = this.getCameraPosition();
2983 var isOutOfBound = this.isOutOfBound();
2984 var prevPanel = nearestPanel.prevSibling;
2985 var nextPanel = nearestPanel.nextSibling;
2986 var hangerPosition = this.getHangerPosition();
2987 var nearestAnchorPos = nearestPanel.getAnchorPosition();
2988
2989 if (isOutOfBound && prevPanel && nextPanel && cameraPosition < nextRange // On the basis of anchor, prevPanel is nearestPanel.
2990 && hangerPosition - prevPanel.getAnchorPosition() < nearestAnchorPos - hangerPosition) {
2991 nearestPanel = prevPanel;
2992 nextPanel = nearestPanel.nextSibling;
2993 prevPanel = nearestPanel.prevSibling;
2994 nearestAnchorPos = nearestPanel.getAnchorPosition();
2995 }
2996
2997 var nearestIndex = nearestPanel.getIndex() + (nearestPanel.getCloneIndex() + 1) * panelManager.getPanelCount();
2998 var nearestSize = nearestPanel.getSize();
2999
3000 if (isOutOfBound) {
3001 var relativeHangerPosition = this.getRelativeHangerPosition();
3002
3003 if (nearestAnchorPos > nextRange + relativeHangerPosition) {
3004 // next bounce area: hangerPosition - relativeHangerPosition - nextRange
3005 hangerPosition = nearestAnchorPos + hangerPosition - relativeHangerPosition - nextRange;
3006 } else if (nearestAnchorPos < prevRange + relativeHangerPosition) {
3007 // prev bounce area: hangerPosition - relativeHangerPosition - prevRange
3008 hangerPosition = nearestAnchorPos + hangerPosition - relativeHangerPosition - prevRange;
3009 }
3010 }
3011
3012 var hangerIsNextToNearestPanel = hangerPosition >= nearestAnchorPos;
3013 var gap = this.options.gap;
3014 var basePosition = nearestAnchorPos;
3015 var targetPosition = nearestAnchorPos;
3016
3017 if (hangerIsNextToNearestPanel) {
3018 targetPosition = nextPanel ? nextPanel.getAnchorPosition() : nearestAnchorPos + nearestSize + gap;
3019 } else {
3020 basePosition = prevPanel ? prevPanel.getAnchorPosition() : nearestAnchorPos - nearestSize - gap;
3021 }
3022
3023 var progressBetween = (hangerPosition - basePosition) / (targetPosition - basePosition);
3024 var startIndex = hangerIsNextToNearestPanel ? nearestIndex : prevPanel ? prevPanel.getIndex() : nearestIndex - 1;
3025 return startIndex + progressBetween;
3026 }; // Update axes flick position without triggering event
3027
3028
3029 __proto.updateAxesPosition = function (position) {
3030 var axes = this.axes;
3031 axes.off();
3032 axes.setTo({
3033 flick: position
3034 }, 0);
3035 axes.on(this.axesHandlers);
3036 };
3037
3038 __proto.getSize = function () {
3039 return this.state.size;
3040 };
3041
3042 __proto.getScrollArea = function () {
3043 return this.state.scrollArea;
3044 };
3045
3046 __proto.isOutOfBound = function () {
3047 var state = this.state;
3048 var options = this.options;
3049 var scrollArea = state.scrollArea;
3050 return !options.circular && options.bound && (state.position <= scrollArea.prev || state.position >= scrollArea.next);
3051 };
3052
3053 __proto.canSetBoundMode = function () {
3054 var options = this.options;
3055 return options.bound && !options.circular;
3056 };
3057
3058 __proto.getViewportElement = function () {
3059 return this.viewportElement;
3060 };
3061
3062 __proto.getCameraElement = function () {
3063 return this.cameraElement;
3064 };
3065
3066 __proto.getScrollAreaSize = function () {
3067 var scrollArea = this.state.scrollArea;
3068 return scrollArea.next - scrollArea.prev;
3069 };
3070
3071 __proto.getRelativeHangerPosition = function () {
3072 return this.state.relativeHangerPosition;
3073 };
3074
3075 __proto.getHangerPosition = function () {
3076 return this.state.position + this.state.relativeHangerPosition;
3077 };
3078
3079 __proto.getCameraPosition = function () {
3080 return this.state.position;
3081 };
3082
3083 __proto.getPositionOffset = function () {
3084 return this.state.positionOffset;
3085 };
3086
3087 __proto.getCheckedIndexes = function () {
3088 return this.state.checkedIndexes;
3089 };
3090
3091 __proto.getVisiblePanels = function () {
3092 return this.visiblePanels;
3093 };
3094
3095 __proto.setCurrentPanel = function (panel) {
3096 this.currentPanel = panel;
3097 };
3098
3099 __proto.setLastIndex = function (index) {
3100 var currentPanel = this.currentPanel;
3101 var panelManager = this.panelManager;
3102 panelManager.setLastIndex(index);
3103
3104 if (currentPanel && currentPanel.getIndex() > index) {
3105 this.currentPanel = panelManager.lastPanel();
3106 }
3107
3108 this.resize();
3109 };
3110
3111 __proto.setVisiblePanels = function (panels) {
3112 this.visiblePanels = panels;
3113 };
3114
3115 __proto.connectAxesHandler = function (handlers) {
3116 var axes = this.axes;
3117 this.axesHandlers = handlers;
3118 axes.on(handlers);
3119 };
3120
3121 __proto.addPlugins = function (plugins) {
3122 var _this = this;
3123
3124 var newPlugins = [].concat(plugins);
3125 newPlugins.forEach(function (plugin) {
3126 plugin.init(_this.flicking);
3127 });
3128 this.plugins = this.plugins.concat(newPlugins);
3129 return this;
3130 };
3131
3132 __proto.removePlugins = function (plugins) {
3133 var _this = this;
3134
3135 var currentPlugins = this.plugins;
3136 var removedPlugins = [].concat(plugins);
3137 removedPlugins.forEach(function (plugin) {
3138 var index = currentPlugins.indexOf(plugin);
3139
3140 if (index > -1) {
3141 currentPlugins.splice(index, 1);
3142 }
3143
3144 plugin.destroy(_this.flicking);
3145 });
3146 return this;
3147 };
3148
3149 __proto.updateCheckedIndexes = function (changedRange) {
3150 var state = this.state;
3151 var removed = 0;
3152 state.checkedIndexes.concat().forEach(function (indexes, idx) {
3153 var min = indexes[0],
3154 max = indexes[1]; // Can fill part of indexes in range
3155
3156 if (changedRange.min <= max && changedRange.max >= min) {
3157 // Remove checked index from list
3158 state.checkedIndexes.splice(idx - removed, 1);
3159 removed++;
3160 }
3161 });
3162 };
3163
3164 __proto.appendUncachedPanelElements = function (panels) {
3165 var _this = this;
3166
3167 var options = this.options;
3168 var fragment = document.createDocumentFragment();
3169
3170 if (options.isEqualSize) {
3171 var prevVisiblePanels = this.visiblePanels;
3172 var equalSizeClasses_1 = options.isEqualSize; // for readability
3173
3174 var cached_1 = {};
3175 this.visiblePanels = [];
3176 Object.keys(this.panelBboxes).forEach(function (className) {
3177 cached_1[className] = true;
3178 });
3179 panels.forEach(function (panel) {
3180 var overlappedClass = panel.getOverlappedClass(equalSizeClasses_1);
3181
3182 if (overlappedClass && !cached_1[overlappedClass]) {
3183 if (!options.renderExternal) {
3184 fragment.appendChild(panel.getElement());
3185 }
3186
3187 _this.visiblePanels.push(panel);
3188
3189 cached_1[overlappedClass] = true;
3190 } else if (!overlappedClass) {
3191 if (!options.renderExternal) {
3192 fragment.appendChild(panel.getElement());
3193 }
3194
3195 _this.visiblePanels.push(panel);
3196 }
3197 });
3198 prevVisiblePanels.forEach(function (panel) {
3199 _this.addVisiblePanel(panel);
3200 });
3201 } else {
3202 if (!options.renderExternal) {
3203 panels.forEach(function (panel) {
3204 return fragment.appendChild(panel.getElement());
3205 });
3206 }
3207
3208 this.visiblePanels = panels.filter(function (panel) {
3209 return Boolean(panel);
3210 });
3211 }
3212
3213 if (!options.renderExternal) {
3214 this.cameraElement.appendChild(fragment);
3215 }
3216 };
3217
3218 __proto.updateClonePanels = function () {
3219 var panelManager = this.panelManager; // Clone panels in circular mode
3220
3221 if (this.options.circular && panelManager.getPanelCount() > 0) {
3222 this.clonePanels();
3223 this.updateClonedPanelPositions();
3224 }
3225
3226 panelManager.chainAllPanels();
3227 };
3228
3229 __proto.getVisibleIndexOf = function (panel) {
3230 return findIndex(this.visiblePanels, function (visiblePanel) {
3231 return visiblePanel === panel;
3232 });
3233 };
3234
3235 __proto.build = function () {
3236 this.setElements();
3237 this.applyCSSValue();
3238 this.setMoveType();
3239 this.setAxesInstance();
3240 this.refreshPanels();
3241 this.setDefaultPanel();
3242 this.resize();
3243 this.moveToDefaultPanel();
3244 };
3245
3246 __proto.setElements = function () {
3247 var state = this.state;
3248 var options = this.options;
3249 var wrapper = this.flicking.getElement();
3250 var classPrefix = options.classPrefix;
3251 var viewportCandidate = wrapper.children[0];
3252 var hasViewportElement = viewportCandidate && hasClass(viewportCandidate, classPrefix + "-viewport");
3253 var viewportElement = hasViewportElement ? viewportCandidate : document.createElement("div");
3254 var cameraCandidate = hasViewportElement ? viewportElement.children[0] : wrapper.children[0];
3255 var hasCameraElement = cameraCandidate && hasClass(cameraCandidate, classPrefix + "-camera");
3256 var cameraElement = hasCameraElement ? cameraCandidate : document.createElement("div");
3257
3258 if (!hasCameraElement) {
3259 cameraElement.className = classPrefix + "-camera";
3260 var panelElements = hasViewportElement ? viewportElement.children : wrapper.children; // Make all panels to be a child of camera element
3261 // wrapper <- viewport <- camera <- panels[1...n]
3262
3263 toArray(panelElements).forEach(function (child) {
3264 cameraElement.appendChild(child);
3265 });
3266 } else {
3267 state.originalCameraStyle = {
3268 className: cameraElement.getAttribute("class"),
3269 style: cameraElement.getAttribute("style")
3270 };
3271 }
3272
3273 if (!hasViewportElement) {
3274 viewportElement.className = classPrefix + "-viewport"; // Add viewport element to wrapper
3275
3276 wrapper.appendChild(viewportElement);
3277 } else {
3278 state.originalViewportStyle = {
3279 className: viewportElement.getAttribute("class"),
3280 style: viewportElement.getAttribute("style")
3281 };
3282 }
3283
3284 if (!hasCameraElement || !hasViewportElement) {
3285 viewportElement.appendChild(cameraElement);
3286 }
3287
3288 this.viewportElement = viewportElement;
3289 this.cameraElement = cameraElement;
3290 state.isViewportGiven = hasViewportElement;
3291 state.isCameraGiven = hasCameraElement;
3292 };
3293
3294 __proto.applyCSSValue = function () {
3295 var options = this.options;
3296 var viewportElement = this.viewportElement;
3297 var cameraElement = this.cameraElement;
3298 var viewportStyle = this.viewportElement.style; // Set default css values for each element
3299
3300 applyCSS(viewportElement, DEFAULT_VIEWPORT_CSS);
3301 applyCSS(cameraElement, DEFAULT_CAMERA_CSS);
3302 viewportElement.style.zIndex = "" + options.zIndex;
3303
3304 if (options.horizontal) {
3305 viewportStyle.minHeight = "100%";
3306 viewportStyle.width = "100%";
3307 } else {
3308 viewportStyle.minWidth = "100%";
3309 viewportStyle.height = "100%";
3310 }
3311
3312 if (options.overflow) {
3313 viewportStyle.overflow = "visible";
3314 }
3315
3316 this.panelManager = new PanelManager(this.cameraElement, options);
3317 };
3318
3319 __proto.setMoveType = function () {
3320 var moveType = this.options.moveType;
3321
3322 switch (moveType.type) {
3323 case MOVE_TYPE.SNAP:
3324 this.moveType = new Snap(moveType.count);
3325 break;
3326
3327 case MOVE_TYPE.FREE_SCROLL:
3328 this.moveType = new FreeScroll();
3329 break;
3330
3331 default:
3332 throw new Error("moveType is not correct!");
3333 }
3334 };
3335
3336 __proto.setAxesInstance = function () {
3337 var state = this.state;
3338 var options = this.options;
3339 var scrollArea = state.scrollArea;
3340 this.axes = new Axes({
3341 flick: {
3342 range: [scrollArea.prev, scrollArea.next],
3343 circular: options.circular,
3344 bounce: [0, 0]
3345 }
3346 }, {
3347 easing: options.panelEffect,
3348 deceleration: options.deceleration,
3349 interruptable: true
3350 });
3351 this.createPanInput();
3352 };
3353
3354 __proto.refreshPanels = function () {
3355 var _this = this;
3356
3357 var panelManager = this.panelManager; // Panel elements were attached to camera element by Flicking class
3358
3359 var panelElements = this.cameraElement.children; // Initialize panels
3360
3361 var panels = toArray(panelElements).map(function (el, idx) {
3362 return new Panel(el, idx, _this);
3363 });
3364 panelManager.replacePanels(panels, []);
3365 this.visiblePanels = panels.filter(function (panel) {
3366 return Boolean(panel);
3367 });
3368 };
3369
3370 __proto.setDefaultPanel = function () {
3371 var options = this.options;
3372 var panelManager = this.panelManager;
3373 var indexRange = this.panelManager.getRange();
3374 var index = clamp(options.defaultIndex, indexRange.min, indexRange.max);
3375 this.currentPanel = panelManager.get(index);
3376 };
3377
3378 __proto.clonePanels = function () {
3379 var state = this.state;
3380 var options = this.options;
3381 var panelManager = this.panelManager;
3382 var gap = options.gap;
3383 var viewportSize = state.size;
3384 var firstPanel = panelManager.firstPanel();
3385 var lastPanel = panelManager.lastPanel(); // There're no panels exist
3386
3387 if (!firstPanel) {
3388 return;
3389 } // For each panels, clone itself while last panel's position + size is below viewport size
3390
3391
3392 var panels = panelManager.originalPanels();
3393 var reversedPanels = panels.concat().reverse();
3394 var sumOriginalPanelSize = lastPanel.getPosition() + lastPanel.getSize() - firstPanel.getPosition() + gap;
3395 var relativeAnchorPosition = firstPanel.getRelativeAnchorPosition();
3396 var relativeHangerPosition = this.getRelativeHangerPosition();
3397 var areaPrev = (relativeHangerPosition - relativeAnchorPosition) % sumOriginalPanelSize;
3398 var sizeSum = 0;
3399 var panelAtLeftBoundary;
3400
3401 for (var _i = 0, reversedPanels_1 = reversedPanels; _i < reversedPanels_1.length; _i++) {
3402 var panel = reversedPanels_1[_i];
3403
3404 if (!panel) {
3405 continue;
3406 }
3407
3408 sizeSum += panel.getSize() + gap;
3409
3410 if (sizeSum >= areaPrev) {
3411 panelAtLeftBoundary = panel;
3412 break;
3413 }
3414 }
3415
3416 var areaNext = (viewportSize - relativeHangerPosition + relativeAnchorPosition) % sumOriginalPanelSize;
3417 sizeSum = 0;
3418 var panelAtRightBoundary;
3419
3420 for (var _a = 0, panels_1 = panels; _a < panels_1.length; _a++) {
3421 var panel = panels_1[_a];
3422
3423 if (!panel) {
3424 continue;
3425 }
3426
3427 sizeSum += panel.getSize() + gap;
3428
3429 if (sizeSum >= areaNext) {
3430 panelAtRightBoundary = panel;
3431 break;
3432 }
3433 } // Need one more set of clones on prev area of original panel 0
3434
3435
3436 var needCloneOnPrev = panelAtLeftBoundary.getIndex() !== 0 && panelAtLeftBoundary.getIndex() <= panelAtRightBoundary.getIndex(); // Visible count of panel 0 on first screen
3437
3438 var panel0OnFirstscreen = Math.ceil((relativeHangerPosition + firstPanel.getSize() - relativeAnchorPosition) / sumOriginalPanelSize) + Math.ceil((viewportSize - relativeHangerPosition + relativeAnchorPosition) / sumOriginalPanelSize) - 1; // duplication
3439
3440 var cloneCount = panel0OnFirstscreen + (needCloneOnPrev ? 1 : 0);
3441 var prevCloneCount = panelManager.getCloneCount();
3442 panelManager.setCloneCount(cloneCount);
3443
3444 if (options.renderExternal) {
3445 return;
3446 }
3447
3448 if (cloneCount > prevCloneCount) {
3449 var _loop_1 = function (cloneIndex) {
3450 var _a;
3451
3452 var clones = panels.map(function (origPanel) {
3453 return origPanel.clone(cloneIndex);
3454 });
3455 var fragment = document.createDocumentFragment();
3456 clones.forEach(function (panel) {
3457 return fragment.appendChild(panel.getElement());
3458 });
3459 this_1.cameraElement.appendChild(fragment);
3460
3461 (_a = this_1.visiblePanels).push.apply(_a, clones.filter(function (clone) {
3462 return Boolean(clone);
3463 }));
3464
3465 panelManager.insertClones(cloneIndex, 0, clones);
3466 };
3467
3468 var this_1 = this; // should clone more
3469
3470 for (var cloneIndex = prevCloneCount; cloneIndex < cloneCount; cloneIndex++) {
3471 _loop_1(cloneIndex);
3472 }
3473 } else if (cloneCount < prevCloneCount) {
3474 // should remove some
3475 panelManager.removeClonesAfter(cloneCount);
3476 }
3477 };
3478
3479 __proto.moveToDefaultPanel = function () {
3480 var state = this.state;
3481 var panelManager = this.panelManager;
3482 var options = this.options;
3483 var indexRange = this.panelManager.getRange();
3484 var defaultIndex = clamp(options.defaultIndex, indexRange.min, indexRange.max);
3485 var defaultPanel = panelManager.get(defaultIndex);
3486 var defaultPosition = 0;
3487
3488 if (defaultPanel) {
3489 defaultPosition = defaultPanel.getAnchorPosition() - state.relativeHangerPosition;
3490 defaultPosition = this.canSetBoundMode() ? clamp(defaultPosition, state.scrollArea.prev, state.scrollArea.next) : defaultPosition;
3491 }
3492
3493 this.moveCamera(defaultPosition);
3494 this.axes.setTo({
3495 flick: defaultPosition
3496 }, 0);
3497 };
3498
3499 __proto.updateSize = function () {
3500 var state = this.state;
3501 var options = this.options;
3502 var panels = this.panelManager.originalPanels().filter(function (panel) {
3503 return Boolean(panel);
3504 });
3505 var bbox = this.updateBbox();
3506 var prevSize = state.size; // Update size & hanger position
3507
3508 state.size = options.horizontal ? bbox.width : bbox.height;
3509
3510 if (prevSize !== state.size) {
3511 state.relativeHangerPosition = parseArithmeticExpression(options.hanger, state.size);
3512 state.infiniteThreshold = parseArithmeticExpression(options.infiniteThreshold, state.size);
3513 }
3514
3515 if (panels.length <= 0) {
3516 return;
3517 }
3518
3519 this.resizePanels(panels);
3520 };
3521
3522 __proto.updateOriginalPanelPositions = function () {
3523 var gap = this.options.gap;
3524 var panelManager = this.panelManager;
3525 var firstPanel = panelManager.firstPanel();
3526 var panels = panelManager.originalPanels();
3527
3528 if (!firstPanel) {
3529 return;
3530 }
3531
3532 var currentPanel = this.currentPanel;
3533 var nearestPanel = this.nearestPanel;
3534 var currentState = this.stateMachine.getState();
3535 var scrollArea = this.state.scrollArea; // Update panel position && fit to wrapper
3536
3537 var nextPanelPos = firstPanel.getPosition();
3538 var maintainingPanel = firstPanel;
3539
3540 if (nearestPanel) {
3541 // We should maintain nearestPanel's position
3542 var looped = !isBetween(currentState.lastPosition + currentState.delta, scrollArea.prev, scrollArea.next);
3543 maintainingPanel = looped ? currentPanel : nearestPanel;
3544 } else if (firstPanel.getIndex() > 0) {
3545 maintainingPanel = currentPanel;
3546 }
3547
3548 var panelsBeforeMaintainPanel = panels.slice(0, maintainingPanel.getIndex() + (maintainingPanel.getCloneIndex() + 1) * panels.length);
3549 var accumulatedSize = panelsBeforeMaintainPanel.reduce(function (total, panel) {
3550 return total + panel.getSize() + gap;
3551 }, 0);
3552 nextPanelPos = maintainingPanel.getPosition() - accumulatedSize;
3553 panels.forEach(function (panel) {
3554 var newPosition = nextPanelPos;
3555 var panelSize = panel.getSize();
3556 panel.setPosition(newPosition);
3557 nextPanelPos += panelSize + gap;
3558 });
3559
3560 if (!this.options.renderOnlyVisible) {
3561 panels.forEach(function (panel) {
3562 return panel.setPositionCSS();
3563 });
3564 }
3565 };
3566
3567 __proto.updateClonedPanelPositions = function () {
3568 var state = this.state;
3569 var options = this.options;
3570 var panelManager = this.panelManager;
3571 var clonedPanels = panelManager.clonedPanels().reduce(function (allClones, clones) {
3572 return __spreadArrays(allClones, clones);
3573 }, []).filter(function (panel) {
3574 return Boolean(panel);
3575 });
3576 var scrollArea = state.scrollArea;
3577 var firstPanel = panelManager.firstPanel();
3578 var lastPanel = panelManager.lastPanel();
3579
3580 if (!firstPanel) {
3581 return;
3582 }
3583
3584 var sumOriginalPanelSize = lastPanel.getPosition() + lastPanel.getSize() - firstPanel.getPosition() + options.gap; // Locate all cloned panels linearly first
3585
3586 for (var _i = 0, clonedPanels_1 = clonedPanels; _i < clonedPanels_1.length; _i++) {
3587 var panel = clonedPanels_1[_i];
3588 var origPanel = panel.getOriginalPanel();
3589 var cloneIndex = panel.getCloneIndex();
3590 var cloneBasePos = sumOriginalPanelSize * (cloneIndex + 1);
3591 var clonedPanelPos = cloneBasePos + origPanel.getPosition();
3592 panel.setPosition(clonedPanelPos);
3593 }
3594
3595 var lastReplacePosition = firstPanel.getPosition(); // reverse() pollutes original array, so copy it with concat()
3596
3597 for (var _a = 0, _b = clonedPanels.concat().reverse(); _a < _b.length; _a++) {
3598 var panel = _b[_a];
3599 var panelSize = panel.getSize();
3600 var replacePosition = lastReplacePosition - panelSize - options.gap;
3601
3602 if (replacePosition + panelSize <= scrollArea.prev) {
3603 // Replace is not meaningful, as it won't be seen in current scroll area
3604 break;
3605 }
3606
3607 panel.setPosition(replacePosition);
3608 lastReplacePosition = replacePosition;
3609 }
3610
3611 if (!this.options.renderOnlyVisible) {
3612 clonedPanels.forEach(function (panel) {
3613 panel.setPositionCSS();
3614 });
3615 }
3616 };
3617
3618 __proto.updateVisiblePanelPositions = function () {
3619 var _this = this;
3620
3621 if (this.options.renderOnlyVisible) {
3622 this.visiblePanels.forEach(function (panel) {
3623 panel.setPositionCSS(_this.state.positionOffset);
3624 });
3625 }
3626 };
3627
3628 __proto.updateScrollArea = function () {
3629 var state = this.state;
3630 var panelManager = this.panelManager;
3631 var options = this.options;
3632 var axes = this.axes; // Set viewport scrollable area
3633
3634 var firstPanel = panelManager.firstPanel();
3635 var lastPanel = panelManager.lastPanel();
3636 var relativeHangerPosition = state.relativeHangerPosition;
3637
3638 if (!firstPanel) {
3639 state.scrollArea = {
3640 prev: 0,
3641 next: 0
3642 };
3643 } else if (this.canSetBoundMode()) {
3644 var sumOriginalPanelSize = lastPanel.getPosition() + lastPanel.getSize() - firstPanel.getPosition();
3645
3646 if (sumOriginalPanelSize >= state.size) {
3647 state.scrollArea = {
3648 prev: firstPanel.getPosition(),
3649 next: lastPanel.getPosition() + lastPanel.getSize() - state.size
3650 };
3651 } else {
3652 // Find anchor position of set of the combined panels
3653 var relAnchorPosOfCombined = parseArithmeticExpression(options.anchor, sumOriginalPanelSize);
3654 var anchorPos = firstPanel.getPosition() + clamp(relAnchorPosOfCombined, sumOriginalPanelSize - (state.size - relativeHangerPosition), relativeHangerPosition);
3655 state.scrollArea = {
3656 prev: anchorPos - relativeHangerPosition,
3657 next: anchorPos - relativeHangerPosition
3658 };
3659 }
3660 } else if (options.circular) {
3661 var sumOriginalPanelSize = lastPanel.getPosition() + lastPanel.getSize() - firstPanel.getPosition() + options.gap; // Maximum scroll extends to first clone sequence's first panel
3662
3663 state.scrollArea = {
3664 prev: firstPanel.getAnchorPosition() - relativeHangerPosition,
3665 next: sumOriginalPanelSize + firstPanel.getAnchorPosition() - relativeHangerPosition
3666 };
3667 } else {
3668 state.scrollArea = {
3669 prev: firstPanel.getAnchorPosition() - relativeHangerPosition,
3670 next: lastPanel.getAnchorPosition() - relativeHangerPosition
3671 };
3672 }
3673
3674 var viewportSize = state.size;
3675 var bounce = options.bounce;
3676 var parsedBounce;
3677
3678 if (isArray(bounce)) {
3679 parsedBounce = bounce.map(function (val) {
3680 return parseArithmeticExpression(val, viewportSize, DEFAULT_OPTIONS.bounce);
3681 });
3682 } else {
3683 var parsedVal = parseArithmeticExpression(bounce, viewportSize, DEFAULT_OPTIONS.bounce);
3684 parsedBounce = [parsedVal, parsedVal];
3685 } // Update axes range and bounce
3686
3687
3688 var flick = axes.axis.flick;
3689 flick.range = [state.scrollArea.prev, state.scrollArea.next];
3690 flick.bounce = parsedBounce;
3691 };
3692
3693 __proto.checkNeedPanel = function (axesEvent) {
3694 var state = this.state;
3695 var options = this.options;
3696 var panelManager = this.panelManager;
3697 var currentPanel = this.currentPanel;
3698 var nearestPanel = this.nearestPanel;
3699 var currentState = this.stateMachine.getState();
3700
3701 if (!options.infinite) {
3702 return;
3703 }
3704
3705 var gap = options.gap;
3706 var infiniteThreshold = state.infiniteThreshold;
3707 var maxLastIndex = panelManager.getLastIndex();
3708
3709 if (maxLastIndex < 0) {
3710 return;
3711 }
3712
3713 if (!currentPanel || !nearestPanel) {
3714 // There're no panels
3715 this.triggerNeedPanel({
3716 axesEvent: axesEvent,
3717 siblingPanel: null,
3718 direction: null,
3719 indexRange: {
3720 min: 0,
3721 max: maxLastIndex,
3722 length: maxLastIndex + 1
3723 }
3724 });
3725 return;
3726 }
3727
3728 var originalNearestPosition = nearestPanel.getPosition(); // Check next direction
3729
3730 var checkingPanel = !currentState.holding && !currentState.playing ? currentPanel : nearestPanel;
3731
3732 while (checkingPanel) {
3733 var currentIndex = checkingPanel.getIndex();
3734 var nextSibling = checkingPanel.nextSibling;
3735 var lastPanel = panelManager.lastPanel();
3736 var atLastPanel = currentIndex === lastPanel.getIndex();
3737 var nextIndex = !atLastPanel && nextSibling ? nextSibling.getIndex() : maxLastIndex + 1;
3738 var currentNearestPosition = nearestPanel.getPosition();
3739 var panelRight = checkingPanel.getPosition() + checkingPanel.getSize() - (currentNearestPosition - originalNearestPosition);
3740 var cameraNext = state.position + state.size; // There're empty panels between
3741
3742 var emptyPanelExistsBetween = nextIndex - currentIndex > 1; // Expected prev panel's left position is smaller than camera position
3743
3744 var overThreshold = panelRight + gap - infiniteThreshold <= cameraNext;
3745
3746 if (emptyPanelExistsBetween && overThreshold) {
3747 this.triggerNeedPanel({
3748 axesEvent: axesEvent,
3749 siblingPanel: checkingPanel,
3750 direction: DIRECTION.NEXT,
3751 indexRange: {
3752 min: currentIndex + 1,
3753 max: nextIndex - 1,
3754 length: nextIndex - currentIndex - 1
3755 }
3756 });
3757 } // Trigger needPanel in circular & at max panel index
3758
3759
3760 if (options.circular && currentIndex === maxLastIndex && overThreshold) {
3761 var firstPanel = panelManager.firstPanel();
3762 var firstIndex = firstPanel ? firstPanel.getIndex() : -1;
3763
3764 if (firstIndex > 0) {
3765 this.triggerNeedPanel({
3766 axesEvent: axesEvent,
3767 siblingPanel: checkingPanel,
3768 direction: DIRECTION.NEXT,
3769 indexRange: {
3770 min: 0,
3771 max: firstIndex - 1,
3772 length: firstIndex
3773 }
3774 });
3775 }
3776 } // Check whether panels are changed
3777
3778
3779 var lastPanelAfterNeed = panelManager.lastPanel();
3780 var atLastPanelAfterNeed = lastPanelAfterNeed && currentIndex === lastPanelAfterNeed.getIndex();
3781
3782 if (atLastPanelAfterNeed || !overThreshold) {
3783 break;
3784 }
3785
3786 checkingPanel = checkingPanel.nextSibling;
3787 } // Check prev direction
3788
3789
3790 checkingPanel = nearestPanel;
3791
3792 while (checkingPanel) {
3793 var cameraPrev = state.position;
3794 var checkingIndex = checkingPanel.getIndex();
3795 var prevSibling = checkingPanel.prevSibling;
3796 var firstPanel = panelManager.firstPanel();
3797 var atFirstPanel = checkingIndex === firstPanel.getIndex();
3798 var prevIndex = !atFirstPanel && prevSibling ? prevSibling.getIndex() : -1;
3799 var currentNearestPosition = nearestPanel.getPosition();
3800 var panelLeft = checkingPanel.getPosition() - (currentNearestPosition - originalNearestPosition); // There're empty panels between
3801
3802 var emptyPanelExistsBetween = checkingIndex - prevIndex > 1; // Expected prev panel's right position is smaller than camera position
3803
3804 var overThreshold = panelLeft - gap + infiniteThreshold >= cameraPrev;
3805
3806 if (emptyPanelExistsBetween && overThreshold) {
3807 this.triggerNeedPanel({
3808 axesEvent: axesEvent,
3809 siblingPanel: checkingPanel,
3810 direction: DIRECTION.PREV,
3811 indexRange: {
3812 min: prevIndex + 1,
3813 max: checkingIndex - 1,
3814 length: checkingIndex - prevIndex - 1
3815 }
3816 });
3817 } // Trigger needPanel in circular & at panel 0
3818
3819
3820 if (options.circular && checkingIndex === 0 && overThreshold) {
3821 var lastPanel = panelManager.lastPanel();
3822
3823 if (lastPanel && lastPanel.getIndex() < maxLastIndex) {
3824 var lastIndex = lastPanel.getIndex();
3825 this.triggerNeedPanel({
3826 axesEvent: axesEvent,
3827 siblingPanel: checkingPanel,
3828 direction: DIRECTION.PREV,
3829 indexRange: {
3830 min: lastIndex + 1,
3831 max: maxLastIndex,
3832 length: maxLastIndex - lastIndex
3833 }
3834 });
3835 }
3836 } // Check whether panels were changed
3837
3838
3839 var firstPanelAfterNeed = panelManager.firstPanel();
3840 var atFirstPanelAfterNeed = firstPanelAfterNeed && checkingIndex === firstPanelAfterNeed.getIndex(); // Looped in circular mode
3841
3842 if (atFirstPanelAfterNeed || !overThreshold) {
3843 break;
3844 }
3845
3846 checkingPanel = checkingPanel.prevSibling;
3847 }
3848 };
3849
3850 __proto.triggerNeedPanel = function (params) {
3851 var _this = this;
3852
3853 var axesEvent = params.axesEvent,
3854 siblingPanel = params.siblingPanel,
3855 direction = params.direction,
3856 indexRange = params.indexRange;
3857 var options = this.options;
3858 var checkedIndexes = this.state.checkedIndexes;
3859 var alreadyTriggered = checkedIndexes.some(function (_a) {
3860 var min = _a[0],
3861 max = _a[1];
3862 return min === indexRange.min || max === indexRange.max;
3863 });
3864 var hasHandler = this.flicking.hasOn(EVENTS.NEED_PANEL);
3865
3866 if (alreadyTriggered || !hasHandler) {
3867 return;
3868 } // Should done before triggering event, as we can directly add panels by event callback
3869
3870
3871 checkedIndexes.push([indexRange.min, indexRange.max]);
3872 var index = siblingPanel ? siblingPanel.getIndex() : 0;
3873 var isTrusted = axesEvent ? axesEvent.isTrusted : false;
3874 this.triggerEvent(EVENTS.NEED_PANEL, axesEvent, isTrusted, {
3875 index: index,
3876 panel: siblingPanel,
3877 direction: direction,
3878 range: indexRange,
3879 fill: function (element) {
3880 var panelManager = _this.panelManager;
3881
3882 if (!siblingPanel) {
3883 return _this.insert(panelManager.getRange().max + 1, element);
3884 }
3885
3886 var parsedElements = parseElement(element); // Slice elements to fit size equal to empty spaces
3887
3888 var elements = direction === DIRECTION.NEXT ? parsedElements.slice(0, indexRange.length) : parsedElements.slice(-indexRange.length);
3889
3890 if (direction === DIRECTION.NEXT) {
3891 if (options.circular && index === panelManager.getLastIndex()) {
3892 // needPanel event is triggered on last index, insert at index 0
3893 return _this.insert(0, elements);
3894 } else {
3895 return siblingPanel.insertAfter(elements);
3896 }
3897 } else if (direction === DIRECTION.PREV) {
3898 if (options.circular && index === 0) {
3899 // needPanel event is triggered on first index(0), insert at the last index
3900 return _this.insert(indexRange.max - elements.length + 1, elements);
3901 } else {
3902 return siblingPanel.insertBefore(elements);
3903 }
3904 } else {
3905 // direction is null when there're no panels exist
3906 return _this.insert(0, elements);
3907 }
3908 }
3909 });
3910 };
3911
3912 __proto.updateVisiblePanels = function () {
3913 var state = this.state;
3914 var options = this.options;
3915 var panelManager = this.panelManager;
3916 var currentState = this.stateMachine.getState();
3917 var cameraElement = this.cameraElement;
3918 var renderExternal = options.renderExternal,
3919 renderOnlyVisible = options.renderOnlyVisible;
3920
3921 if (!renderOnlyVisible) {
3922 return;
3923 }
3924
3925 if (!this.nearestPanel) {
3926 this.visiblePanels = [];
3927
3928 while (cameraElement.firstChild) {
3929 cameraElement.removeChild(cameraElement.firstChild);
3930 }
3931
3932 return;
3933 }
3934
3935 var prevVisiblePanels = this.visiblePanels;
3936 var newVisiblePanels = this.calcVisiblePanels();
3937
3938 var _a = this.checkVisiblePanelChange(prevVisiblePanels, newVisiblePanels),
3939 addedPanels = _a.addedPanels,
3940 removedPanels = _a.removedPanels;
3941
3942 if (addedPanels.length <= 0 && removedPanels.length <= 0) {
3943 // Visible panels not changed
3944 return;
3945 }
3946
3947 if (currentState.holding) {
3948 newVisiblePanels.push.apply(newVisiblePanels, removedPanels);
3949 } else {
3950 var firstVisiblePanelPos = newVisiblePanels[0].getPosition();
3951 state.positionOffset = firstVisiblePanelPos;
3952 }
3953
3954 newVisiblePanels.forEach(function (panel) {
3955 panel.setPositionCSS(state.positionOffset);
3956 });
3957
3958 if (!renderExternal) {
3959 if (!currentState.holding) {
3960 removedPanels.forEach(function (panel) {
3961 var panelElement = panel.getElement();
3962 panelElement.parentNode && cameraElement.removeChild(panelElement);
3963 });
3964 }
3965
3966 var fragment_1 = document.createDocumentFragment();
3967 addedPanels.forEach(function (panel) {
3968 fragment_1.appendChild(panel.getElement());
3969 });
3970 cameraElement.appendChild(fragment_1);
3971 }
3972
3973 var firstVisiblePanel = newVisiblePanels[0];
3974 var lastVisiblePanel = newVisiblePanels[newVisiblePanels.length - 1];
3975
3976 var getAbsIndex = function (panel) {
3977 return panel.getIndex() + (panel.getCloneIndex() + 1) * panelManager.getPanelCount();
3978 };
3979
3980 var newVisibleRange = {
3981 min: getAbsIndex(firstVisiblePanel),
3982 max: getAbsIndex(lastVisiblePanel)
3983 };
3984 this.visiblePanels = newVisiblePanels;
3985 this.flicking.trigger(EVENTS.VISIBLE_CHANGE, {
3986 type: EVENTS.VISIBLE_CHANGE,
3987 range: newVisibleRange
3988 });
3989 };
3990
3991 __proto.checkVisiblePanelChange = function (prevVisiblePanels, newVisiblePanels) {
3992 var prevRefCount = prevVisiblePanels.map(function () {
3993 return 0;
3994 });
3995 var newRefCount = newVisiblePanels.map(function () {
3996 return 0;
3997 });
3998 prevVisiblePanels.forEach(function (prevPanel, prevIndex) {
3999 newVisiblePanels.forEach(function (newPanel, newIndex) {
4000 if (prevPanel === newPanel) {
4001 prevRefCount[prevIndex]++;
4002 newRefCount[newIndex]++;
4003 }
4004 });
4005 });
4006 var removedPanels = prevRefCount.reduce(function (removed, count, index) {
4007 return count === 0 ? __spreadArrays(removed, [prevVisiblePanels[index]]) : removed;
4008 }, []);
4009 var addedPanels = newRefCount.reduce(function (added, count, index) {
4010 return count === 0 ? __spreadArrays(added, [newVisiblePanels[index]]) : added;
4011 }, []);
4012 return {
4013 removedPanels: removedPanels,
4014 addedPanels: addedPanels
4015 };
4016 };
4017
4018 __proto.resizePanels = function (panels) {
4019 var options = this.options;
4020 var panelBboxes = this.panelBboxes;
4021
4022 if (options.isEqualSize === true) {
4023 if (!panelBboxes.default) {
4024 var defaultPanel = panels[0];
4025 panelBboxes.default = defaultPanel.getBbox();
4026 }
4027
4028 var defaultBbox_1 = panelBboxes.default;
4029 panels.forEach(function (panel) {
4030 panel.resize(defaultBbox_1);
4031 });
4032 return;
4033 } else if (options.isEqualSize) {
4034 var equalSizeClasses_2 = options.isEqualSize;
4035 panels.forEach(function (panel) {
4036 var overlappedClass = panel.getOverlappedClass(equalSizeClasses_2);
4037
4038 if (overlappedClass) {
4039 panel.resize(panelBboxes[overlappedClass]);
4040 panelBboxes[overlappedClass] = panel.getBbox();
4041 } else {
4042 panel.resize();
4043 }
4044 });
4045 return;
4046 }
4047
4048 panels.forEach(function (panel) {
4049 panel.resize();
4050 });
4051 };
4052
4053 __proto.createPanInput = function () {
4054 var options = this.options;
4055 this.panInput = new Axes.PanInput(this.viewportElement, {
4056 inputType: options.inputType,
4057 thresholdAngle: options.thresholdAngle,
4058 iOSEdgeSwipeThreshold: options.iOSEdgeSwipeThreshold,
4059 scale: options.horizontal ? [-1, 0] : [0, -1]
4060 });
4061 this.axes.connect(options.horizontal ? ["flick", ""] : ["", "flick"], this.panInput);
4062 };
4063
4064 return Viewport;
4065 }();
4066
4067 /**
4068 * Copyright (c) 2015 NAVER Corp.
4069 * egjs projects are licensed under the MIT license
4070 */
4071 /**
4072 * @memberof eg
4073 * @extends eg.Component
4074 * @support {"ie": "10+", "ch" : "latest", "ff" : "latest", "sf" : "latest" , "edge" : "latest", "ios" : "7+", "an" : "4.X+"}
4075 * @requires {@link https://github.com/naver/egjs-component|eg.Component}
4076 * @requires {@link https://github.com/naver/egjs-axes|eg.Axes}
4077 * @see Easing Functions Cheat Sheet {@link http://easings.net/} <ko>이징 함수 Cheat Sheet {@link http://easings.net/}</ko>
4078 */
4079
4080 var Flicking =
4081 /*#__PURE__*/
4082 function (_super) {
4083 __extends(Flicking, _super);
4084 /**
4085 * @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>
4086 * @param options An option object of the eg.Flicking module<ko>eg.Flicking 모듈의 옵션 객체</ko>
4087 * @param {string} [options.classPrefix="eg-flick"] A prefix of class names will be added for the panels, viewport, and camera.<ko>패널들과 뷰포트, 카메라에 추가될 클래스 이름의 접두사.</ko>
4088 * @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>
4089 * @param {boolean} [options.horizontal=true] The direction of panel movement. (true: horizontal, false: vertical)<ko>패널 이동 방향. (true: 가로방향, false: 세로방향)</ko>
4090 * @param {boolean} [options.circular=false] Enables circular mode, which connects first/last panel for continuous scrolling.<ko>순환 모드를 활성화한다. 순환 모드에서는 양 끝의 패널이 서로 연결되어 끊김없는 스크롤이 가능하다.</ko>
4091 * @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>
4092 * @param {number} [options.infiniteThreshold=0] A Threshold from viewport edge before triggering `needPanel` event in infinite mode.<ko>무한 모드에서 `needPanel`이벤트가 발생하기 위한 뷰포트 끝으로부터의 최대 거리.</ko>
4093 * @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>
4094 * @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>
4095 * @param {number} [options.duration=100] Duration of the panel movement animation. (unit: ms)<ko>패널 이동 애니메이션 진행 시간.(단위: ms)</ko>
4096 * @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>
4097 * @param {number} [options.defaultIndex=0] Index of the panel to set as default when initializing. A zero-based integer.<ko>초기화시 지정할 디폴트 패널의 인덱스로, 0부터 시작하는 정수.</ko>
4098 * @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>
4099 * @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>
4100 * @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>
4101 * @param {boolean} [options.autoResize=false] Whether the `resize` method should be called automatically after a window resize event.<ko>window의 `resize` 이벤트 이후 자동으로 resize()메소드를 호출할지의 여부.</ko>
4102 * @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>
4103 * @param {number|""} [options.zIndex=2000] z-index value for viewport element.<ko>뷰포트 엘리먼트의 z-index 값.</ko>
4104 * @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>
4105 * @param {boolean} [options.overflow=false] Disables CSS property `overflow: hidden` in viewport if `true`.<ko>`true`로 설정시 뷰포트에 `overflow: hidden` 속성을 해제한다.</ko>
4106 * @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>
4107 * @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>
4108 * @param {number} [options.gap=0] Space value between panels. Should be given in number.(px)<ko>패널간에 부여할 간격의 크기를 나타내는 숫자.(px)</ko>
4109 * @param {eg.Flicking.MoveTypeOption} [options.moveType="snap"] Movement style by user input. (ex: snap, freeScroll)<ko>사용자 입력에 의한 이동 방식.(ex: snap, freeScroll)</ko>
4110 * @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>
4111 * @param {boolean} [options.renderOnlyVisible=false] Whether to render visible panels only. This can dramatically increase performance when there're many panels.<ko>보이는 패널만 렌더링할지 여부를 설정한다. 패널이 많을 경우에 퍼포먼스를 크게 향상시킬 수 있다.</ko>
4112 * @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>
4113 * @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>
4114 * @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>
4115 * @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>
4116 * @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>
4117 */
4118
4119
4120 function Flicking(element, options) {
4121 if (options === void 0) {
4122 options = {};
4123 }
4124
4125 var _this = _super.call(this) || this;
4126
4127 _this.contentsReadyChecker = null;
4128 _this.isPanelChangedAtBeforeSync = false;
4129 /**
4130 * Update panels to current state.
4131 * @ko 패널들을 현재 상태에 맞춰 갱신한다.
4132 * @method
4133 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
4134 */
4135
4136 _this.resize = function () {
4137 var viewport = _this.viewport;
4138 var options = _this.options;
4139
4140 var wrapper = _this.getElement();
4141
4142 var allPanels = viewport.panelManager.allPanels();
4143
4144 if (!options.isConstantSize) {
4145 allPanels.forEach(function (panel) {
4146 return panel.unCacheBbox();
4147 });
4148 }
4149
4150 var shouldResetElements = options.renderOnlyVisible && !options.isConstantSize && options.isEqualSize !== true; // Temporarily set parent's height to prevent scroll (#333)
4151
4152 var parent = wrapper.parentElement;
4153 var origStyle = parent.style.height;
4154 parent.style.height = parent.offsetHeight + "px";
4155 viewport.unCacheBbox(); // This should be done before adding panels, to lower performance issue
4156
4157 viewport.updateBbox();
4158
4159 if (shouldResetElements) {
4160 viewport.appendUncachedPanelElements(allPanels);
4161 }
4162
4163 viewport.resize();
4164 parent.style.height = origStyle;
4165 return _this;
4166 };
4167
4168 _this.triggerEvent = function (eventName, // visibleChange event has no common event definition from other events
4169 axesEvent, isTrusted, params) {
4170 if (params === void 0) {
4171 params = {};
4172 }
4173
4174 var viewport = _this.viewport;
4175 var canceled = true; // Ignore events before viewport is initialized
4176
4177 if (viewport) {
4178 var state = viewport.stateMachine.getState();
4179
4180 var _a = viewport.getScrollArea(),
4181 prev = _a.prev,
4182 next = _a.next;
4183
4184 var pos = viewport.getCameraPosition();
4185 var progress = getProgress(pos, [prev, prev, next]);
4186
4187 if (_this.options.circular) {
4188 progress %= 1;
4189 }
4190
4191 canceled = !_super.prototype.trigger.call(_this, eventName, merge({
4192 type: eventName,
4193 index: _this.getIndex(),
4194 panel: _this.getCurrentPanel(),
4195 direction: state.direction,
4196 holding: state.holding,
4197 progress: progress,
4198 axesEvent: axesEvent,
4199 isTrusted: isTrusted
4200 }, params));
4201 }
4202
4203 return {
4204 onSuccess: function (callback) {
4205 if (!canceled) {
4206 callback();
4207 }
4208
4209 return this;
4210 },
4211 onStopped: function (callback) {
4212 if (canceled) {
4213 callback();
4214 }
4215
4216 return this;
4217 }
4218 };
4219 }; // Return result of "move" event triggered
4220
4221
4222 _this.moveCamera = function (axesEvent) {
4223 var viewport = _this.viewport;
4224 var state = viewport.stateMachine.getState();
4225 var options = _this.options;
4226 var pos = axesEvent.pos.flick;
4227 var previousPosition = viewport.getCameraPosition();
4228
4229 if (axesEvent.isTrusted && state.holding) {
4230 var inputOffset = options.horizontal ? axesEvent.inputEvent.offsetX : axesEvent.inputEvent.offsetY;
4231 var isNextDirection = inputOffset < 0;
4232 var cameraChange = pos - previousPosition;
4233 var looped = isNextDirection === pos < previousPosition;
4234
4235 if (options.circular && looped) {
4236 // Reached at max/min range of axes
4237 var scrollAreaSize = viewport.getScrollAreaSize();
4238 cameraChange = (cameraChange > 0 ? -1 : 1) * (scrollAreaSize - Math.abs(cameraChange));
4239 }
4240
4241 var currentDirection = cameraChange === 0 ? state.direction : cameraChange > 0 ? DIRECTION.NEXT : DIRECTION.PREV;
4242 state.direction = currentDirection;
4243 }
4244
4245 state.delta += axesEvent.delta.flick;
4246 viewport.moveCamera(pos, axesEvent);
4247 return _this.triggerEvent(EVENTS.MOVE, axesEvent, axesEvent.isTrusted).onStopped(function () {
4248 // Undo camera movement
4249 viewport.moveCamera(previousPosition, axesEvent);
4250 });
4251 }; // Set flicking wrapper user provided
4252
4253
4254 var wrapper;
4255
4256 if (isString(element)) {
4257 wrapper = document.querySelector(element);
4258
4259 if (!wrapper) {
4260 throw new Error("Base element doesn't exist.");
4261 }
4262 } else if (element.nodeName && element.nodeType === 1) {
4263 wrapper = element;
4264 } else {
4265 throw new Error("Element should be provided in string or HTMLElement.");
4266 }
4267
4268 _this.wrapper = wrapper; // Override default options
4269
4270 _this.options = merge({}, DEFAULT_OPTIONS, options); // Override moveType option
4271
4272 var currentOptions = _this.options;
4273 var moveType = currentOptions.moveType;
4274
4275 if (moveType in DEFAULT_MOVE_TYPE_OPTIONS) {
4276 currentOptions.moveType = DEFAULT_MOVE_TYPE_OPTIONS[moveType];
4277 } // Make viewport instance with panel container element
4278
4279
4280 _this.viewport = new Viewport(_this, _this.options, _this.triggerEvent);
4281
4282 _this.listenInput();
4283
4284 _this.listenResize();
4285
4286 return _this; // if (this.options.collectStatistics) {
4287 // sendEvent(
4288 // "usage",
4289 // "options",
4290 // options,
4291 // );
4292 // }
4293 }
4294 /**
4295 * Move to the previous panel if it exists.
4296 * @ko 이전 패널이 존재시 해당 패널로 이동한다.
4297 * @param [duration=options.duration] Duration of the panel movement animation.(unit: ms)<ko>패널 이동 애니메이션 진행 시간.(단위: ms)</ko>
4298 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
4299 */
4300
4301
4302 var __proto = Flicking.prototype;
4303
4304 __proto.prev = function (duration) {
4305 var currentPanel = this.getCurrentPanel();
4306 var currentState = this.viewport.stateMachine.getState();
4307
4308 if (currentPanel && currentState.type === STATE_TYPE.IDLE) {
4309 var prevPanel = currentPanel.prev();
4310
4311 if (prevPanel) {
4312 prevPanel.focus(duration);
4313 }
4314 }
4315
4316 return this;
4317 };
4318 /**
4319 * Move to the next panel if it exists.
4320 * @ko 다음 패널이 존재시 해당 패널로 이동한다.
4321 * @param [duration=options.duration] Duration of the panel movement animation(unit: ms).<ko>패널 이동 애니메이션 진행 시간.(단위: ms)</ko>
4322 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
4323 */
4324
4325
4326 __proto.next = function (duration) {
4327 var currentPanel = this.getCurrentPanel();
4328 var currentState = this.viewport.stateMachine.getState();
4329
4330 if (currentPanel && currentState.type === STATE_TYPE.IDLE) {
4331 var nextPanel = currentPanel.next();
4332
4333 if (nextPanel) {
4334 nextPanel.focus(duration);
4335 }
4336 }
4337
4338 return this;
4339 };
4340 /**
4341 * Move to the panel of given index.
4342 * @ko 주어진 인덱스에 해당하는 패널로 이동한다.
4343 * @param index The index number of the panel to move.<ko>이동할 패널의 인덱스 번호.</ko>
4344 * @param duration [duration=options.duration] Duration of the panel movement.(unit: ms)<ko>패널 이동 애니메이션 진행 시간.(단위: ms)</ko>
4345 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
4346 */
4347
4348
4349 __proto.moveTo = function (index, duration) {
4350 var viewport = this.viewport;
4351 var panel = viewport.panelManager.get(index);
4352 var state = viewport.stateMachine.getState();
4353
4354 if (!panel || state.type !== STATE_TYPE.IDLE) {
4355 return this;
4356 }
4357
4358 var anchorPosition = panel.getAnchorPosition();
4359 var hangerPosition = viewport.getHangerPosition();
4360 var targetPanel = panel;
4361
4362 if (this.options.circular) {
4363 var scrollAreaSize = viewport.getScrollAreaSize(); // Check all three possible locations, find the nearest position among them.
4364
4365 var possiblePositions = [anchorPosition - scrollAreaSize, anchorPosition, anchorPosition + scrollAreaSize];
4366 var nearestPosition = possiblePositions.reduce(function (nearest, current) {
4367 return Math.abs(current - hangerPosition) < Math.abs(nearest - hangerPosition) ? current : nearest;
4368 }, Infinity) - panel.getRelativeAnchorPosition();
4369 var identicals = panel.getIdenticalPanels();
4370 var offset = nearestPosition - anchorPosition;
4371
4372 if (offset > 0) {
4373 // First cloned panel is nearest
4374 targetPanel = identicals[1];
4375 } else if (offset < 0) {
4376 // Last cloned panel is nearest
4377 targetPanel = identicals[identicals.length - 1];
4378 }
4379
4380 targetPanel = targetPanel.clone(targetPanel.getCloneIndex(), true);
4381 targetPanel.setPosition(nearestPosition);
4382 }
4383
4384 var currentIndex = this.getIndex();
4385
4386 if (hangerPosition === targetPanel.getAnchorPosition() && currentIndex === index) {
4387 return this;
4388 }
4389
4390 var eventType = panel.getIndex() === viewport.getCurrentIndex() ? "" : EVENTS.CHANGE;
4391 viewport.moveTo(targetPanel, viewport.findEstimatedPosition(targetPanel), eventType, null, duration);
4392 return this;
4393 };
4394 /**
4395 * Return index of the current panel. `-1` if no panel exists.
4396 * @ko 현재 패널의 인덱스 번호를 반환한다. 패널이 하나도 없을 경우 `-1`을 반환한다.
4397 * @return Current panel's index, zero-based integer.<ko>현재 패널의 인덱스 번호. 0부터 시작하는 정수.</ko>
4398 */
4399
4400
4401 __proto.getIndex = function () {
4402 return this.viewport.getCurrentIndex();
4403 };
4404 /**
4405 * Return the wrapper element user provided in constructor.
4406 * @ko 사용자가 생성자에서 제공한 래퍼 엘리먼트를 반환한다.
4407 * @return Wrapper element user provided.<ko>사용자가 제공한 래퍼 엘리먼트.</ko>
4408 */
4409
4410
4411 __proto.getElement = function () {
4412 return this.wrapper;
4413 };
4414 /**
4415 * Return the viewport element's size.
4416 * @ko 뷰포트 엘리먼트의 크기를 반환한다.
4417 * @return Width if horizontal: true, height if horizontal: false
4418 */
4419
4420
4421 __proto.getSize = function () {
4422 return this.viewport.getSize();
4423 };
4424 /**
4425 * Return current panel. `null` if no panel exists.
4426 * @ko 현재 패널을 반환한다. 패널이 하나도 없을 경우 `null`을 반환한다.
4427 * @return Current panel.<ko>현재 패널.</ko>
4428 */
4429
4430
4431 __proto.getCurrentPanel = function () {
4432 var viewport = this.viewport;
4433 var panel = viewport.getCurrentPanel();
4434 return panel ? panel : null;
4435 };
4436 /**
4437 * Return the panel of given index. `null` if it doesn't exists.
4438 * @ko 주어진 인덱스에 해당하는 패널을 반환한다. 해당 패널이 존재하지 않을 시 `null`이다.
4439 * @return Panel of given index.<ko>주어진 인덱스에 해당하는 패널.</ko>
4440 */
4441
4442
4443 __proto.getPanel = function (index) {
4444 var viewport = this.viewport;
4445 var panel = viewport.panelManager.get(index);
4446 return panel ? panel : null;
4447 };
4448 /**
4449 * Return all panels.
4450 * @ko 모든 패널들을 반환한다.
4451 * @param - Should include cloned panels or not.<ko>복사된 패널들을 포함할지의 여부.</ko>
4452 * @return All panels.<ko>모든 패널들.</ko>
4453 */
4454
4455
4456 __proto.getAllPanels = function (includeClone) {
4457 var viewport = this.viewport;
4458 var panelManager = viewport.panelManager;
4459 var panels = includeClone ? panelManager.allPanels() : panelManager.originalPanels();
4460 return panels.filter(function (panel) {
4461 return !!panel;
4462 });
4463 };
4464 /**
4465 * Return the panels currently shown in viewport area.
4466 * @ko 현재 뷰포트 영역에서 보여지고 있는 패널들을 반환한다.
4467 * @return Panels currently shown in viewport area.<ko>현재 뷰포트 영역에 보여지는 패널들</ko>
4468 */
4469
4470
4471 __proto.getVisiblePanels = function () {
4472 return this.viewport.calcVisiblePanels();
4473 };
4474 /**
4475 * Return length of original panels.
4476 * @ko 원본 패널의 개수를 반환한다.
4477 * @return Length of original panels.<ko>원본 패널의 개수</ko>
4478 */
4479
4480
4481 __proto.getPanelCount = function () {
4482 return this.viewport.panelManager.getPanelCount();
4483 };
4484 /**
4485 * Return how many groups of clones are created.
4486 * @ko 몇 개의 클론 그룹이 생성되었는지를 반환한다.
4487 * @return Length of cloned panel groups.<ko>클론된 패널 그룹의 개수</ko>
4488 */
4489
4490
4491 __proto.getCloneCount = function () {
4492 return this.viewport.panelManager.getCloneCount();
4493 };
4494 /**
4495 * Get maximum panel index for `infinite` mode.
4496 * @ko `infinite` 모드에서 적용되는 추가 가능한 패널의 최대 인덱스 값을 반환한다.
4497 * @see {@link eg.Flicking.FlickingOptions}
4498 * @return Maximum index of panel that can be added.<ko>최대 추가 가능한 패널의 인덱스.</ko>
4499 */
4500
4501
4502 __proto.getLastIndex = function () {
4503 return this.viewport.panelManager.getLastIndex();
4504 };
4505 /**
4506 * 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.
4507 * @ko `infinite` 모드에서 적용되는 패널의 최대 인덱스를 설정한다.<br>마지막 패널의 인덱스가 설정한 값에 도달할 경우 더 이상 [needPanel]{@link eg.Flicking#events:needPanel} 이벤트가 발생되지 않는다.<br>또한, 설정한 인덱스 이후로 새로운 패널을 추가할 수 없다.
4508 * @param - Maximum panel index.
4509 * @see {@link eg.Flicking.FlickingOptions}
4510 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
4511 */
4512
4513
4514 __proto.setLastIndex = function (index) {
4515 this.viewport.setLastIndex(index);
4516 return this;
4517 };
4518 /**
4519 * Return panel movement animation.
4520 * @ko 현재 패널 이동 애니메이션이 진행 중인지를 반환한다.
4521 * @return Is animating or not.<ko>애니메이션 진행 여부.</ko>
4522 */
4523
4524
4525 __proto.isPlaying = function () {
4526 return this.viewport.stateMachine.getState().playing;
4527 };
4528 /**
4529 * Unblock input devices.
4530 * @ko 막았던 입력 장치로부터의 입력을 푼다.
4531 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
4532 */
4533
4534
4535 __proto.enableInput = function () {
4536 this.viewport.enable();
4537 return this;
4538 };
4539 /**
4540 * Block input devices.
4541 * @ko 입력 장치로부터의 입력을 막는다.
4542 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
4543 */
4544
4545
4546 __proto.disableInput = function () {
4547 this.viewport.disable();
4548 return this;
4549 };
4550 /**
4551 * Get current flicking status. You can restore current state by giving returned value to [setStatus()]{@link eg.Flicking#setStatus}.
4552 * @ko 현재 상태 값을 반환한다. 반환받은 값을 [setStatus()]{@link eg.Flicking#setStatus} 메소드의 인자로 지정하면 현재 상태를 복원할 수 있다.
4553 * @return An object with current status value information.<ko>현재 상태값 정보를 가진 객체.</ko>
4554 */
4555
4556
4557 __proto.getStatus = function () {
4558 var viewport = this.viewport;
4559 var panels = viewport.panelManager.originalPanels().filter(function (panel) {
4560 return !!panel;
4561 }).map(function (panel) {
4562 return {
4563 html: panel.getElement().outerHTML,
4564 index: panel.getIndex()
4565 };
4566 });
4567 return {
4568 index: viewport.getCurrentIndex(),
4569 panels: panels,
4570 position: viewport.getCameraPosition()
4571 };
4572 };
4573 /**
4574 * Restore to the state of the `status`.
4575 * @ko `status`의 상태로 복원한다.
4576 * @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>
4577 */
4578
4579
4580 __proto.setStatus = function (status) {
4581 this.viewport.restore(status);
4582 };
4583 /**
4584 * Add plugins that can have different effects on Flicking.
4585 * @ko 플리킹에 다양한 효과를 부여할 수 있는 플러그인을 추가한다.
4586 * @param - The plugin(s) to add.<ko>추가할 플러그인(들).</ko>
4587 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
4588 */
4589
4590
4591 __proto.addPlugins = function (plugins) {
4592 this.viewport.addPlugins(plugins);
4593 return this;
4594 };
4595 /**
4596 * Remove plugins from Flicking.
4597 * @ko 플리킹으로부터 플러그인들을 제거한다.
4598 * @param - The plugin(s) to remove.<ko>제거 플러그인(들).</ko>
4599 * @return {eg.Flicking} The instance itself.<ko>인스턴스 자기 자신.</ko>
4600 */
4601
4602
4603 __proto.removePlugins = function (plugins) {
4604 this.viewport.removePlugins(plugins);
4605 return this;
4606 };
4607 /**
4608 * 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).
4609 * @ko 기준 요소와 그 하위 패널들을 인스턴스 생성전의 상태로 되돌린다. 부착된 모든 이벤트 핸들러를 탈거한다. 인스턴스의 모든 속성(상속받은 속성포함)에 `null`을 지정한다.
4610 * @example
4611 * const flick = new eg.Flicking("#flick");
4612 * flick.destroy();
4613 * console.log(flick.moveTo); // null
4614 */
4615
4616
4617 __proto.destroy = function (option) {
4618 var _a;
4619
4620 if (option === void 0) {
4621 option = {};
4622 }
4623
4624 this.off();
4625
4626 if (this.options.autoResize) {
4627 window.removeEventListener("resize", this.resize);
4628 }
4629
4630 this.viewport.destroy(option);
4631 (_a = this.contentsReadyChecker) === null || _a === void 0 ? void 0 : _a.destroy(); // release resources
4632
4633 for (var x in this) {
4634 this[x] = null;
4635 }
4636 };
4637 /**
4638 * Add new panels at the beginning of panels.
4639 * @ko 제일 앞에 새로운 패널을 추가한다.
4640 * @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>
4641 * @return Array of appended panels.<ko>추가된 패널들의 배열</ko>
4642 * @example
4643 * // Suppose there were no panels at initialization
4644 * const flicking = new eg.Flicking("#flick");
4645 * flicking.replace(3, document.createElement("div")); // Add new panel at index 3
4646 * flicking.prepend("\<div\>Panel\</div\>"); // Prepended at index 2
4647 * flicking.prepend(["\<div\>Panel\</div\>", document.createElement("div")]); // Prepended at index 0, 1
4648 * flicking.prepend("\<div\>Panel\</div\>"); // Prepended at index 0, pushing every panels behind it.
4649 */
4650
4651
4652 __proto.prepend = function (element) {
4653 var viewport = this.viewport;
4654 var parsedElements = parseElement(element);
4655 var insertingIndex = Math.max(viewport.panelManager.getRange().min - parsedElements.length, 0);
4656 var prependedPanels = viewport.insert(insertingIndex, parsedElements);
4657 this.checkContentsReady(prependedPanels);
4658 return prependedPanels;
4659 };
4660 /**
4661 * Add new panels at the end of panels.
4662 * @ko 제일 끝에 새로운 패널을 추가한다.
4663 * @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>
4664 * @return Array of appended panels.<ko>추가된 패널들의 배열</ko>
4665 * @example
4666 * // Suppose there were no panels at initialization
4667 * const flicking = new eg.Flicking("#flick");
4668 * flicking.append(document.createElement("div")); // Appended at index 0
4669 * flicking.append("\<div\>Panel\</div\>"); // Appended at index 1
4670 * flicking.append(["\<div\>Panel\</div\>", document.createElement("div")]); // Appended at index 2, 3
4671 * // Even this is possible
4672 * flicking.append("\<div\>Panel 1\</div\>\<div\>Panel 2\</div\>"); // Appended at index 4, 5
4673 */
4674
4675
4676 __proto.append = function (element) {
4677 var viewport = this.viewport;
4678 var appendedPanels = viewport.insert(viewport.panelManager.getRange().max + 1, element);
4679 this.checkContentsReady(appendedPanels);
4680 return appendedPanels;
4681 };
4682 /**
4683 * Replace existing panels with new panels from given index. If target index is empty, add new panel at target index.
4684 * @ko 주어진 인덱스로부터의 패널들을 새로운 패널들로 교체한다. 인덱스에 해당하는 자리가 비어있다면, 새로운 패널을 해당 자리에 집어넣는다.
4685 * @param index - Start index to replace new panels.<ko>새로운 패널들로 교체할 시작 인덱스</ko>
4686 * @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>
4687 * @return Array of created panels by replace.<ko>교체되어 새롭게 추가된 패널들의 배열</ko>
4688 * @example
4689 * // Suppose there were no panels at initialization
4690 * const flicking = new eg.Flicking("#flick");
4691 *
4692 * // This will add new panel at index 3,
4693 * // Index 0, 1, 2 is empty at this moment.
4694 * // [empty, empty, empty, PANEL]
4695 * flicking.replace(3, document.createElement("div"));
4696 *
4697 * // As index 2 was empty, this will also add new panel at index 2.
4698 * // [empty, empty, PANEL, PANEL]
4699 * flicking.replace(2, "\<div\>Panel\</div\>");
4700 *
4701 * // Index 3 was not empty, so it will replace previous one.
4702 * // It will also add new panels at index 4 and 5.
4703 * // before - [empty, empty, PANEL, PANEL]
4704 * // after - [empty, empty, PANEL, NEW_PANEL, NEW_PANEL, NEW_PANEL]
4705 * flicking.replace(3, ["\<div\>Panel\</div\>", "\<div\>Panel\</div\>", "\<div\>Panel\</div\>"])
4706 */
4707
4708
4709 __proto.replace = function (index, element) {
4710 var replacedPanels = this.viewport.replace(index, element);
4711 this.checkContentsReady(replacedPanels);
4712 return replacedPanels;
4713 };
4714 /**
4715 * Remove panel at target index. This will decrease index of panels behind it.
4716 * @ko `index`에 해당하는 자리의 패널을 제거한다. 수행시 `index` 이후의 패널들의 인덱스가 감소된다.
4717 * @param index - Index of panel to remove.<ko>제거할 패널의 인덱스</ko>
4718 * @param {number} [deleteCount=1] - Number of panels to remove from index.<ko>`index` 이후로 제거할 패널의 개수.</ko>
4719 * @return Array of removed panels<ko>제거된 패널들의 배열</ko>
4720 */
4721
4722
4723 __proto.remove = function (index, deleteCount) {
4724 if (deleteCount === void 0) {
4725 deleteCount = 1;
4726 }
4727
4728 return this.viewport.remove(index, deleteCount);
4729 };
4730 /**
4731 * Get indexes to render. Should be used with `renderOnlyVisible` option.
4732 * `beforeSync` should be called before this method for a correct result.
4733 * @private
4734 * @ko 렌더링이 필요한 인덱스들을 반환한다. `renderOnlyVisible` 옵션과 함께 사용해야 한다. 정확한 결과를 위해선 `beforeSync`를 이전에 호출해야만 합니다.
4735 * @param - Info object of how panel infos are changed.<ko>패널 정보들의 변경 정보를 담는 오브젝트.</ko>
4736 * @return Array of indexes to render.<ko>렌더링할 인덱스의 배열</ko>
4737 */
4738
4739
4740 __proto.getRenderingIndexes = function (diffResult) {
4741 var viewport = this.viewport;
4742 var visiblePanels = viewport.getVisiblePanels();
4743 var maintained = diffResult.maintained.reduce(function (values, _a) {
4744 var before = _a[0],
4745 after = _a[1];
4746 values[after] = before;
4747 return values;
4748 }, {});
4749 var panelCount = diffResult.list.length;
4750 var added = diffResult.added;
4751
4752 var getPanelAbsIndex = function (panel) {
4753 return panel.getIndex() + (panel.getCloneIndex() + 1) * panelCount;
4754 };
4755
4756 var visibleIndexes = visiblePanels.map(function (panel) {
4757 return getPanelAbsIndex(panel);
4758 }).filter(function (val) {
4759 return maintained[val % panelCount] != null;
4760 });
4761
4762 var renderingPanels = __spreadArrays(visibleIndexes, added);
4763
4764 var allPanels = viewport.panelManager.allPanels();
4765 viewport.setVisiblePanels(renderingPanels.map(function (index) {
4766 return allPanels[index];
4767 }));
4768 return renderingPanels;
4769 };
4770 /**
4771 * Synchronize info of panels instance with info given by external rendering.
4772 * @ko 외부 렌더링 방식에 의해 입력받은 패널의 정보와 현재 플리킹이 갖는 패널 정보를 동기화한다.
4773 * @private
4774 * @param - Info object of how panel infos are changed.<ko>패널 정보들의 변경 정보를 담는 오브젝트.</ko>
4775 * @param - Whether called from sync method <ko> sync 메소드로부터 호출됐는지 여부 </ko>
4776 */
4777
4778
4779 __proto.beforeSync = function (diffInfo) {
4780 var _this = this;
4781
4782 var maintained = diffInfo.maintained,
4783 added = diffInfo.added,
4784 changed = diffInfo.changed,
4785 removed = diffInfo.removed;
4786 var viewport = this.viewport;
4787 var panelManager = viewport.panelManager;
4788 var isCircular = this.options.circular;
4789 var cloneCount = panelManager.getCloneCount();
4790 var prevClonedPanels = panelManager.clonedPanels(); // Update visible panels
4791
4792 var newVisiblePanels = viewport.getVisiblePanels().filter(function (panel) {
4793 return findIndex(removed, function (index) {
4794 return index === panel.getIndex();
4795 }) < 0;
4796 });
4797 viewport.setVisiblePanels(newVisiblePanels); // Did not changed at all
4798
4799 if (added.length <= 0 && removed.length <= 0 && changed.length <= 0 && cloneCount === prevClonedPanels.length) {
4800 return this;
4801 }
4802
4803 var prevOriginalPanels = panelManager.originalPanels();
4804 var newPanels = [];
4805 var newClones = counter(cloneCount).map(function () {
4806 return [];
4807 });
4808 maintained.forEach(function (_a) {
4809 var beforeIdx = _a[0],
4810 afterIdx = _a[1];
4811 newPanels[afterIdx] = prevOriginalPanels[beforeIdx];
4812 newPanels[afterIdx].setIndex(afterIdx);
4813 });
4814 added.forEach(function (addIndex) {
4815 newPanels[addIndex] = new Panel(null, addIndex, _this.viewport);
4816 });
4817
4818 if (isCircular) {
4819 counter(cloneCount).forEach(function (groupIndex) {
4820 var prevCloneGroup = prevClonedPanels[groupIndex];
4821 var newCloneGroup = newClones[groupIndex];
4822 maintained.forEach(function (_a) {
4823 var beforeIdx = _a[0],
4824 afterIdx = _a[1];
4825 newCloneGroup[afterIdx] = prevCloneGroup ? prevCloneGroup[beforeIdx] : newPanels[afterIdx].clone(groupIndex, false);
4826 newCloneGroup[afterIdx].setIndex(afterIdx);
4827 });
4828 added.forEach(function (addIndex) {
4829 var newPanel = newPanels[addIndex];
4830 newCloneGroup[addIndex] = newPanel.clone(groupIndex, false);
4831 });
4832 });
4833 }
4834
4835 added.forEach(function (index) {
4836 viewport.updateCheckedIndexes({
4837 min: index,
4838 max: index
4839 });
4840 });
4841 removed.forEach(function (index) {
4842 viewport.updateCheckedIndexes({
4843 min: index - 1,
4844 max: index + 1
4845 });
4846 });
4847 var checkedIndexes = viewport.getCheckedIndexes();
4848 checkedIndexes.forEach(function (_a, idx) {
4849 var min = _a[0],
4850 max = _a[1]; // Push checked indexes backward
4851
4852 var pushedIndex = added.filter(function (index) {
4853 return index < min && panelManager.has(index);
4854 }).length - removed.filter(function (index) {
4855 return index < min;
4856 }).length;
4857 checkedIndexes.splice(idx, 1, [min + pushedIndex, max + pushedIndex]);
4858 }); // Only effective only when there are least one panel which have changed its index
4859
4860 if (changed.length > 0) {
4861 // Removed checked index by changed ones after pushing
4862 maintained.forEach(function (_a) {
4863 var next = _a[1];
4864 viewport.updateCheckedIndexes({
4865 min: next,
4866 max: next
4867 });
4868 });
4869 }
4870
4871 panelManager.replacePanels(newPanels, newClones);
4872 this.isPanelChangedAtBeforeSync = true;
4873 };
4874 /**
4875 * Synchronize info of panels with DOM info given by external rendering.
4876 * @ko 외부 렌더링 방식에 의해 입력받은 DOM의 정보와 현재 플리킹이 갖는 패널 정보를 동기화 한다.
4877 * @private
4878 * @param - Info object of how panel elements are changed.<ko>패널의 DOM 요소들의 변경 정보를 담는 오브젝트.</ko>
4879 */
4880
4881
4882 __proto.sync = function (diffInfo) {
4883 var list = diffInfo.list,
4884 maintained = diffInfo.maintained,
4885 added = diffInfo.added,
4886 changed = diffInfo.changed,
4887 removed = diffInfo.removed; // Did not changed at all
4888
4889 if (added.length <= 0 && removed.length <= 0 && changed.length <= 0) {
4890 return this;
4891 }
4892
4893 var viewport = this.viewport;
4894 var _a = this.options,
4895 renderOnlyVisible = _a.renderOnlyVisible,
4896 circular = _a.circular;
4897 var panelManager = viewport.panelManager;
4898
4899 if (!renderOnlyVisible) {
4900 var indexRange = panelManager.getRange();
4901 var beforeDiffInfo = diffInfo;
4902
4903 if (circular) {
4904 var prevOriginalPanelCount_1 = indexRange.max;
4905 var originalPanelCount_1 = list.length / (panelManager.getCloneCount() + 1) >> 0;
4906 var originalAdded = added.filter(function (index) {
4907 return index < originalPanelCount_1;
4908 });
4909 var originalRemoved = removed.filter(function (index) {
4910 return index <= prevOriginalPanelCount_1;
4911 });
4912 var originalMaintained = maintained.filter(function (_a) {
4913 var beforeIdx = _a[0];
4914 return beforeIdx <= prevOriginalPanelCount_1;
4915 });
4916 var originalChanged = changed.filter(function (_a) {
4917 var beforeIdx = _a[0];
4918 return beforeIdx <= prevOriginalPanelCount_1;
4919 });
4920 beforeDiffInfo = {
4921 added: originalAdded,
4922 maintained: originalMaintained,
4923 removed: originalRemoved,
4924 changed: originalChanged
4925 };
4926 }
4927
4928 this.beforeSync(beforeDiffInfo);
4929 }
4930
4931 var visiblePanels = renderOnlyVisible ? viewport.getVisiblePanels() : this.getAllPanels(true);
4932 added.forEach(function (addedIndex) {
4933 var addedElement = list[addedIndex];
4934 var beforePanel = visiblePanels[addedIndex];
4935 beforePanel.setElement(addedElement); // As it can be 0
4936
4937 beforePanel.unCacheBbox();
4938 });
4939
4940 if (this.isPanelChangedAtBeforeSync) {
4941 // Reset visible panels
4942 viewport.setVisiblePanels([]);
4943 this.isPanelChangedAtBeforeSync = false;
4944 }
4945
4946 viewport.resize();
4947 return this;
4948 };
4949
4950 __proto.listenInput = function () {
4951 var flicking = this;
4952 var viewport = flicking.viewport;
4953 var stateMachine = viewport.stateMachine; // Set event context
4954
4955 flicking.eventContext = {
4956 flicking: flicking,
4957 viewport: flicking.viewport,
4958 transitTo: stateMachine.transitTo,
4959 triggerEvent: flicking.triggerEvent,
4960 moveCamera: flicking.moveCamera,
4961 stopCamera: viewport.stopCamera
4962 };
4963 var handlers = {};
4964
4965 var _loop_1 = function (key) {
4966 var eventType = AXES_EVENTS[key];
4967
4968 handlers[eventType] = function (e) {
4969 return stateMachine.fire(eventType, e, flicking.eventContext);
4970 };
4971 };
4972
4973 for (var key in AXES_EVENTS) {
4974 _loop_1(key);
4975 } // Connect Axes instance with PanInput
4976
4977
4978 flicking.viewport.connectAxesHandler(handlers);
4979 };
4980
4981 __proto.listenResize = function () {
4982 var _this = this;
4983
4984 var options = this.options;
4985
4986 if (options.autoResize) {
4987 window.addEventListener("resize", this.resize);
4988 }
4989
4990 if (options.resizeOnContentsReady) {
4991 var contentsReadyChecker = new ImReady();
4992 contentsReadyChecker.on("preReady", function () {
4993 _this.resize();
4994 });
4995 contentsReadyChecker.on("readyElement", function (e) {
4996 if (e.hasLoading && e.isPreReadyOver) {
4997 _this.resize();
4998 }
4999 });
5000 contentsReadyChecker.on("error", function (e) {
5001 _this.trigger(EVENTS.CONTENT_ERROR, {
5002 type: EVENTS.CONTENT_ERROR,
5003 element: e.element
5004 });
5005 });
5006 contentsReadyChecker.check([this.wrapper]);
5007 this.contentsReadyChecker = contentsReadyChecker;
5008 }
5009 };
5010
5011 __proto.checkContentsReady = function (panels) {
5012 var _a;
5013
5014 (_a = this.contentsReadyChecker) === null || _a === void 0 ? void 0 : _a.check(panels.map(function (panel) {
5015 return panel.getElement();
5016 }));
5017 };
5018 /**
5019 * Version info string
5020 * @ko 버전정보 문자열
5021 * @example
5022 * eg.Flicking.VERSION; // ex) 3.0.0
5023 * @memberof eg.Flicking
5024 */
5025
5026
5027 Flicking.VERSION = "3.7.1";
5028 /**
5029 * Direction constant - "PREV" or "NEXT"
5030 * @ko 방향 상수 - "PREV" 또는 "NEXT"
5031 * @type {object}
5032 * @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>
5033 * @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>
5034 * @example
5035 * eg.Flicking.DIRECTION.PREV; // "PREV"
5036 * eg.Flicking.DIRECTION.NEXT; // "NEXT"
5037 */
5038
5039 Flicking.DIRECTION = DIRECTION;
5040 /**
5041 * Event type object with event name strings.
5042 * @ko 이벤트 이름 문자열들을 담은 객체
5043 * @type {object}
5044 * @property {"holdStart"} HOLD_START - holdStart event<ko>holdStart 이벤트</ko>
5045 * @property {"holdEnd"} HOLD_END - holdEnd event<ko>holdEnd 이벤트</ko>
5046 * @property {"moveStart"} MOVE_START - moveStart event<ko>moveStart 이벤트</ko>
5047 * @property {"move"} MOVE - move event<ko>move 이벤트</ko>
5048 * @property {"moveEnd"} MOVE_END - moveEnd event<ko>moveEnd 이벤트</ko>
5049 * @property {"change"} CHANGE - change event<ko>change 이벤트</ko>
5050 * @property {"restore"} RESTORE - restore event<ko>restore 이벤트</ko>
5051 * @property {"select"} SELECT - select event<ko>select 이벤트</ko>
5052 * @property {"needPanel"} NEED_PANEL - needPanel event<ko>needPanel 이벤트</ko>
5053 * @example
5054 * eg.Flicking.EVENTS.MOVE_START; // "MOVE_START"
5055 */
5056
5057 Flicking.EVENTS = EVENTS;
5058 return Flicking;
5059 }(Component);
5060
5061 Flicking.withFlickingMethods = withFlickingMethods;
5062 Flicking.DEFAULT_OPTIONS = DEFAULT_OPTIONS;
5063 Flicking.MOVE_TYPE = MOVE_TYPE;
5064
5065 return Flicking;
5066
5067})));
5068//# sourceMappingURL=flicking.js.map