UNPKG

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