@egjs/flicking 4.2.4 → 4.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. package/README.md +1 -1
  2. package/declaration/Flicking.d.ts +24 -11
  3. package/declaration/camera/Camera.d.ts +5 -4
  4. package/declaration/camera/CircularCamera.d.ts +3 -2
  5. package/declaration/const/error.d.ts +3 -1
  6. package/declaration/const/external.d.ts +5 -0
  7. package/declaration/control/Control.d.ts +2 -2
  8. package/declaration/control/FreeControl.d.ts +1 -1
  9. package/declaration/control/StrictControl.d.ts +1 -1
  10. package/declaration/control/states/State.d.ts +2 -1
  11. package/declaration/core/AutoResizer.d.ts +13 -0
  12. package/declaration/core/VirtualManager.d.ts +37 -0
  13. package/declaration/core/index.d.ts +2 -1
  14. package/declaration/core/panel/ExternalPanel.d.ts +9 -5
  15. package/declaration/core/panel/Panel.d.ts +17 -10
  16. package/declaration/core/panel/VirtualPanel.d.ts +19 -0
  17. package/declaration/core/panel/index.d.ts +4 -3
  18. package/declaration/core/panel/provider/ElementProvider.d.ts +7 -0
  19. package/declaration/core/panel/provider/ExternalElementProvider.d.ts +8 -0
  20. package/declaration/core/panel/provider/VanillaElementProvider.d.ts +10 -0
  21. package/declaration/core/panel/provider/VirtualElementProvider.d.ts +13 -0
  22. package/declaration/core/panel/provider/index.d.ts +6 -0
  23. package/declaration/index.d.ts +11 -1
  24. package/declaration/renderer/ExternalRenderer.d.ts +1 -0
  25. package/declaration/renderer/Renderer.d.ts +18 -13
  26. package/declaration/renderer/VanillaRenderer.d.ts +2 -7
  27. package/declaration/renderer/index.d.ts +1 -0
  28. package/declaration/renderer/strategy/NormalRenderingStrategy.d.ts +25 -0
  29. package/declaration/renderer/strategy/RenderingStrategy.d.ts +15 -0
  30. package/declaration/renderer/strategy/VirtualRenderingStrategy.d.ts +17 -0
  31. package/declaration/renderer/strategy/index.d.ts +5 -0
  32. package/declaration/utils.d.ts +7 -1
  33. package/dist/flicking.esm.js +4649 -3767
  34. package/dist/flicking.esm.js.map +1 -1
  35. package/dist/flicking.js +4689 -3783
  36. package/dist/flicking.js.map +1 -1
  37. package/dist/flicking.min.js +2 -2
  38. package/dist/flicking.min.js.map +1 -1
  39. package/dist/flicking.pkgd.js +4359 -2062
  40. package/dist/flicking.pkgd.js.map +1 -1
  41. package/dist/flicking.pkgd.min.js +2 -2
  42. package/dist/flicking.pkgd.min.js.map +1 -1
  43. package/package.json +2 -1
  44. package/src/Flicking.ts +148 -30
  45. package/src/camera/BoundCamera.ts +2 -2
  46. package/src/camera/Camera.ts +59 -36
  47. package/src/camera/CircularCamera.ts +54 -29
  48. package/src/camera/LinearCamera.ts +1 -1
  49. package/src/cfc/getRenderingPanels.ts +6 -1
  50. package/src/cfc/sync.ts +2 -2
  51. package/src/const/error.ts +6 -3
  52. package/src/const/external.ts +6 -0
  53. package/src/control/AxesController.ts +17 -9
  54. package/src/control/Control.ts +37 -39
  55. package/src/control/FreeControl.ts +4 -4
  56. package/src/control/SnapControl.ts +3 -3
  57. package/src/control/StrictControl.ts +4 -4
  58. package/src/control/states/AnimatingState.ts +6 -3
  59. package/src/control/states/State.ts +4 -2
  60. package/src/core/AutoResizer.ts +81 -0
  61. package/src/core/VirtualManager.ts +188 -0
  62. package/src/core/index.ts +3 -1
  63. package/src/core/panel/ExternalPanel.ts +23 -15
  64. package/src/core/panel/Panel.ts +68 -60
  65. package/src/core/panel/VirtualPanel.ts +110 -0
  66. package/src/core/panel/index.ts +5 -4
  67. package/src/core/panel/provider/ElementProvider.ts +13 -0
  68. package/src/core/panel/provider/ExternalElementProvider.ts +15 -0
  69. package/src/core/panel/provider/VanillaElementProvider.ts +40 -0
  70. package/src/core/panel/provider/VirtualElementProvider.ts +45 -0
  71. package/src/core/panel/provider/index.ts +18 -0
  72. package/src/index.ts +12 -1
  73. package/src/index.umd.ts +2 -0
  74. package/src/renderer/ExternalRenderer.ts +36 -4
  75. package/src/renderer/Renderer.ts +174 -69
  76. package/src/renderer/VanillaRenderer.ts +28 -86
  77. package/src/renderer/index.ts +2 -0
  78. package/src/renderer/strategy/NormalRenderingStrategy.ts +109 -0
  79. package/src/renderer/strategy/RenderingStrategy.ts +21 -0
  80. package/src/renderer/strategy/VirtualRenderingStrategy.ts +110 -0
  81. package/src/renderer/strategy/index.ts +17 -0
  82. package/src/utils.ts +36 -2
  83. package/declaration/core/panel/ElementPanel.d.ts +0 -14
  84. package/declaration/exports.d.ts +0 -10
  85. package/src/core/panel/ElementPanel.ts +0 -52
  86. package/src/exports.ts +0 -16
@@ -0,0 +1,188 @@
1
+ /*
2
+ * Copyright (c) 2015 NAVER Corp.
3
+ * egjs projects are licensed under the MIT license
4
+ */
5
+ import Flicking from "../Flicking";
6
+ import { range } from "../utils";
7
+ import { CLASS } from "../const/external";
8
+
9
+ import VirtualPanel from "./panel/VirtualPanel";
10
+
11
+ export interface VirtualOptions {
12
+ renderPanel: (panel: VirtualPanel, index: number) => string;
13
+ initialPanelCount: number;
14
+ cache?: boolean;
15
+ panelClass?: string;
16
+ }
17
+
18
+ /**
19
+ * A manager class to add / remove virtual panels
20
+ */
21
+ class VirtualManager {
22
+ private _flicking: Flicking;
23
+
24
+ private _renderPanel: (panel: VirtualPanel, index: number) => string;
25
+ private _initialPanelCount: number;
26
+ private _cache: boolean;
27
+ private _panelClass: string;
28
+
29
+ private _elements: Array<{ nativeElement: HTMLElement; visible: boolean }>;
30
+
31
+ public get elements() { return this._elements; }
32
+
33
+ // Options
34
+ /**
35
+ * A rendering function for the panel element's innerHTML
36
+ * @ko 패널 엘리먼트의 innerHTML을 렌더링하는 함수
37
+ * @type {function}
38
+ * @param {VirtualPanel} panel Instance of the panel<ko>패널 인스턴스</ko>
39
+ * @param {number} index Index of the panel<ko>패널 인덱스</ko>
40
+ * @default "() => {}"
41
+ */
42
+ public get renderPanel() { return this._renderPanel; }
43
+ /**
44
+ * Initial panel count to render
45
+ * @ko 최초로 렌더링할 패널의 개수
46
+ * @readonly
47
+ * @type {number}
48
+ * @default -1
49
+ */
50
+ public get initialPanelCount() { return this._initialPanelCount; }
51
+ /**
52
+ * Whether to cache rendered panel's innerHTML
53
+ * @ko 렌더링된 패널의 innerHTML 정보를 캐시할지 여부
54
+ * @type {boolean}
55
+ * @default false
56
+ */
57
+ public get cache() { return this._cache; }
58
+ /**
59
+ * The class name that will be applied to rendered panel elements
60
+ * @ko 렌더링되는 패널 엘리먼트에 적용될 클래스 이름
61
+ * @type {string}
62
+ * @default "flicking-panel"
63
+ */
64
+ public get panelClass() { return this._panelClass; }
65
+
66
+ public set renderPanel(val: VirtualOptions["renderPanel"]) {
67
+ this._renderPanel = val;
68
+ this._flicking.renderer.panels.forEach((panel: VirtualPanel) => panel.uncacheRenderResult());
69
+ }
70
+
71
+ public set cache(val: NonNullable<VirtualOptions["cache"]>) { this._cache = val; }
72
+ public set panelClass(val: NonNullable<VirtualOptions["panelClass"]>) { this._panelClass = val; }
73
+
74
+ public constructor(flicking: Flicking, options: VirtualOptions | null) {
75
+ this._flicking = flicking;
76
+
77
+ this._renderPanel = options?.renderPanel ?? (() => "");
78
+ this._initialPanelCount = options?.initialPanelCount ?? -1;
79
+ this._cache = options?.cache ?? false;
80
+ this._panelClass = options?.panelClass ?? CLASS.DEFAULT_VIRTUAL;
81
+
82
+ this._elements = [];
83
+ }
84
+
85
+ public init() {
86
+ const flicking = this._flicking;
87
+
88
+ if (!flicking.virtualEnabled) return;
89
+
90
+ if (!flicking.renderExternal) {
91
+ this._initVirtualElements();
92
+ }
93
+
94
+ const virtualElements = flicking.camera.children;
95
+ this._elements = virtualElements.map(el => ({ nativeElement: el, visible: true }));
96
+ }
97
+
98
+ public show(index: number) {
99
+ const el = this._elements[index];
100
+ const nativeEl = el.nativeElement;
101
+
102
+ el.visible = true;
103
+
104
+ if (nativeEl.style.display) {
105
+ nativeEl.style.display = "";
106
+ }
107
+ }
108
+
109
+ public hide(index: number) {
110
+ const el = this._elements[index];
111
+ const nativeEl = el.nativeElement;
112
+
113
+ el.visible = false;
114
+ nativeEl.style.display = "none";
115
+ }
116
+
117
+ /**
118
+ * Add new virtual panels at the end of the list
119
+ * @ko 새로운 가상 패널들을 리스트의 끝에 추가합니다
120
+ * @param {number} count The number of panels to add<ko>추가할 패널의 개수</ko>
121
+ * @returns {Array<VirtualPanel>} The new panels added<ko>새롭게 추가된 패널들</ko>
122
+ */
123
+ public append(count: number = 1): VirtualPanel[] {
124
+ const flicking = this._flicking;
125
+
126
+ return this.insert(flicking.panels.length, count);
127
+ }
128
+
129
+ /**
130
+ * Add new virtual panels at the start of the list
131
+ * @ko 새로운 가상 패널들을 리스트의 시작에 추가합니다
132
+ * @param {number} count The number of panels to add<ko>추가할 패널의 개수</ko>
133
+ * @returns {Array<VirtualPanel>} The new panels added<ko>새롭게 추가된 패널들</ko>
134
+ */
135
+ public prepend(count: number = 1): VirtualPanel[] {
136
+ return this.insert(0, count);
137
+ }
138
+
139
+ /**
140
+ * Add new virtual panels at the given index
141
+ * @ko 새로운 가상 패널들을 주어진 인덱스에 추가합니다
142
+ * @param {number} count The number of panels to add<ko>추가할 패널의 개수</ko>
143
+ * @returns {Array<VirtualPanel>} The new panels added<ko>새롭게 추가된 패널들</ko>
144
+ */
145
+ public insert(index: number, count: number = 1): VirtualPanel[] {
146
+ if (count <= 0) return [];
147
+
148
+ const flicking = this._flicking;
149
+
150
+ return flicking.renderer.batchInsert({ index, elements: range(count), hasDOMInElements: false }) as VirtualPanel[];
151
+ }
152
+
153
+ /**
154
+ * Remove panels at the given index
155
+ * @ko 주어진 인덱스에서 패널들을 삭제합니다
156
+ * @param {number} count The number of panels to remove<ko>삭제할 패널의 개수</ko>
157
+ * @returns {Array<VirtualPanel>} The panels removed<ko>삭제된 패널들</ko>
158
+ */
159
+ public remove(index: number, count: number): VirtualPanel[] {
160
+ if (count <= 0) return [];
161
+
162
+ const flicking = this._flicking;
163
+
164
+ return flicking.renderer.batchRemove({ index, deleteCount: count, hasDOMInElements: false }) as VirtualPanel[];
165
+ }
166
+
167
+ private _initVirtualElements() {
168
+ const flicking = this._flicking;
169
+ const cameraElement = flicking.camera.element;
170
+ const panelsPerView = flicking.panelsPerView;
171
+ const fragment = document.createDocumentFragment();
172
+
173
+ const newElements = range(panelsPerView + 1).map(idx => {
174
+ const panelEl = document.createElement("div");
175
+ panelEl.className = this._panelClass;
176
+ panelEl.dataset.elementIndex = idx.toString();
177
+ return panelEl;
178
+ });
179
+
180
+ newElements.forEach(el => {
181
+ fragment.appendChild(el);
182
+ });
183
+
184
+ cameraElement.appendChild(fragment);
185
+ }
186
+ }
187
+
188
+ export default VirtualManager;
package/src/core/index.ts CHANGED
@@ -5,11 +5,13 @@
5
5
  import Viewport from "./Viewport";
6
6
  import FlickingError from "./FlickingError";
7
7
  import AnchorPoint from "./AnchorPoint";
8
+ import VirtualManager from "./VirtualManager";
8
9
 
9
10
  export {
10
11
  Viewport,
11
12
  FlickingError,
12
- AnchorPoint
13
+ AnchorPoint,
14
+ VirtualManager
13
15
  };
14
16
 
15
17
  export * from "./panel";
@@ -3,29 +3,37 @@
3
3
  * egjs projects are licensed under the MIT license
4
4
  */
5
5
  import Panel, { PanelOptions } from "./Panel";
6
+ import ExternalElementProvider from "./provider/ExternalElementProvider";
6
7
 
7
- export interface ExternalPanelOptions<T> extends PanelOptions {
8
- externalComponent: T;
8
+ export interface ExternalPanelOptions extends PanelOptions {
9
+ elementProvider: ExternalElementProvider;
9
10
  }
10
11
 
11
12
  /**
12
- * An slide data component that holds information of a single HTMLElement
13
+ * A slide data component that holds information of a single HTMLElement
13
14
  * @ko 슬라이드 데이터 컴포넌트로, 단일 HTMLElement의 정보를 갖고 있습니다
14
15
  */
15
- abstract class ExternalPanel<T = any> extends Panel {
16
- protected _externalComponent: T;
17
-
18
- /**
19
- * @param {object} options An options object<ko>옵션 오브젝트</ko>
20
- * @param {HTMLElement} [options.el] A `HTMLElement` panel's referencing<ko>패널이 참조하는 `HTMLElement`</ko>
21
- * @param {number} [options.index] An initial index of the panel<ko>패널의 초기 인덱스</ko>
22
- * @param {Constants.ALIGN | string | number} [options.align] An initial {@link Flicking#align align} value of the panel<ko>패널의 초기 {@link Flicking#align align}값</ko>
23
- * @param {Flicking} [options.flicking] A Flicking instance panel's referencing<ko>패널이 참조하는 {@link Flicking} 인스턴스</ko>
24
- */
25
- public constructor(options: ExternalPanelOptions<T>) {
16
+ class ExternalPanel extends Panel {
17
+ protected _elProvider: ExternalElementProvider;
18
+
19
+ public get rendered() { return this._elProvider.rendered; }
20
+
21
+ public constructor(options: ExternalPanelOptions) {
26
22
  super(options);
27
23
 
28
- this._externalComponent = options.externalComponent;
24
+ this._elProvider = options.elementProvider;
25
+ }
26
+
27
+ public markForShow() {
28
+ this._elProvider.show(this._flicking);
29
+
30
+ return super.markForShow();
31
+ }
32
+
33
+ public markForHide() {
34
+ this._elProvider.hide(this._flicking);
35
+
36
+ return super.markForHide();
29
37
  }
30
38
  }
31
39
 
@@ -3,26 +3,36 @@
3
3
  * egjs projects are licensed under the MIT license
4
4
  */
5
5
  import Flicking from "../../Flicking";
6
- import { getProgress, getStyle, isString, parseAlign } from "../../utils";
6
+ import { getProgress, getStyle, parseAlign, setSize } from "../../utils";
7
7
  import { ALIGN, DIRECTION } from "../../const/external";
8
8
  import { LiteralUnion, ValueOf } from "../../type/internal";
9
9
 
10
+ import ElementProvider from "./provider/ElementProvider";
11
+
10
12
  export interface PanelOptions {
11
13
  index: number;
12
14
  align: LiteralUnion<ValueOf<typeof ALIGN>> | number;
13
15
  flicking: Flicking;
16
+ elementProvider: ElementProvider;
14
17
  }
15
18
 
16
- abstract class Panel {
19
+ /**
20
+ * A slide data component that holds information of a single HTMLElement
21
+ * @ko 슬라이드 데이터 컴포넌트로, 단일 HTMLElement의 정보를 갖고 있습니다
22
+ */
23
+ class Panel {
17
24
  // Internal States
18
25
  protected _flicking: Flicking;
26
+ protected _elProvider: ElementProvider;
19
27
  protected _index: number;
20
28
  protected _pos: number;
21
29
  protected _size: number;
22
30
  protected _height: number;
23
31
  protected _margin: { prev: number; next: number };
24
32
  protected _alignPos: number; // Actual align pos
33
+ protected _rendered: boolean;
25
34
  protected _removed: boolean;
35
+ protected _loading: boolean;
26
36
  protected _toggleDirection: ValueOf<typeof DIRECTION>;
27
37
  protected _toggled: boolean;
28
38
  protected _togglePosition: number;
@@ -37,7 +47,12 @@ abstract class Panel {
37
47
  * @type {HTMLElement}
38
48
  * @readonly
39
49
  */
40
- abstract get element(): HTMLElement;
50
+ public get element() { return this._elProvider.element; }
51
+ /**
52
+ * @internal
53
+ * @readonly
54
+ */
55
+ public get elementProvider() { return this._elProvider; }
41
56
  /**
42
57
  * Index of the panel
43
58
  * @ko 패널의 인덱스
@@ -108,7 +123,14 @@ abstract class Panel {
108
123
  * @type {boolean}
109
124
  * @readonly
110
125
  */
111
- public abstract get rendered();
126
+ public get rendered() { return this._rendered; }
127
+ /**
128
+ * A value indicating whether the panel's image/video is not loaded and waiting for resize
129
+ * @ko 패널 내부의 이미지/비디오가 아직 로드되지 않아 {@link Panel#resize resize}될 것인지를 나타내는 값
130
+ * @type {boolean}
131
+ * @readonly
132
+ */
133
+ public get loading() { return this._loading; }
112
134
  /**
113
135
  * Panel element's range of the bounding box
114
136
  * @ko 패널 엘리먼트의 Bounding box 범위
@@ -221,6 +243,8 @@ abstract class Panel {
221
243
  return visibleSize / size;
222
244
  }
223
245
 
246
+ public set loading(val: boolean) { this._loading = val; }
247
+
224
248
  // Options Getter
225
249
  /**
226
250
  * A value indicating where the {@link Panel#alignPosition alignPosition} should be located at inside the panel element
@@ -229,7 +253,7 @@ abstract class Panel {
229
253
  */
230
254
  public get align() { return this._align; }
231
255
 
232
- // Options Getter
256
+ // Options Setter
233
257
  public set align(val: PanelOptions["align"]) { this._align = val; }
234
258
 
235
259
  /**
@@ -237,18 +261,23 @@ abstract class Panel {
237
261
  * @param {number} [options.index] An initial index of the panel<ko>패널의 초기 인덱스</ko>
238
262
  * @param {Constants.ALIGN | string | number} [options.align] An initial {@link Flicking#align align} value of the panel<ko>패널의 초기 {@link Flicking#align align}값</ko>
239
263
  * @param {Flicking} [options.flicking] A Flicking instance panel's referencing<ko>패널이 참조하는 {@link Flicking} 인스턴스</ko>
264
+ * @param {Flicking} [options.elementProvider] A provider instance that redirects elements<ko>실제 엘리먼트를 반환하는 엘리먼트 공급자의 인스턴스</ko>
240
265
  */
241
266
  public constructor({
242
267
  index,
243
268
  align,
244
- flicking
269
+ flicking,
270
+ elementProvider
245
271
  }: PanelOptions) {
246
272
  this._index = index;
247
273
  this._flicking = flicking;
274
+ this._elProvider = elementProvider;
248
275
 
249
276
  this._align = align;
250
277
 
251
278
  this._removed = false;
279
+ this._rendered = true;
280
+ this._loading = false;
252
281
  this._resetInternalStates();
253
282
  }
254
283
 
@@ -256,13 +285,19 @@ abstract class Panel {
256
285
  * Mark panel element to be appended on the camera element
257
286
  * @internal
258
287
  */
259
- public abstract markForShow();
288
+ public markForShow() {
289
+ this._rendered = true;
290
+ this._elProvider.show(this._flicking);
291
+ }
260
292
 
261
293
  /**
262
294
  * Mark panel element to be removed from the camera element
263
295
  * @internal
264
296
  */
265
- public abstract markForHide();
297
+ public markForHide() {
298
+ this._rendered = false;
299
+ this._elProvider.hide(this._flicking);
300
+ }
266
301
 
267
302
  /**
268
303
  * Update size of the panel
@@ -277,16 +312,16 @@ abstract class Panel {
277
312
  margin: { prev: number; next: number };
278
313
  }): this {
279
314
  const el = this.element;
280
- const elStyle = getStyle(el);
281
315
  const flicking = this._flicking;
282
316
  const horizontal = flicking.horizontal;
283
- const prevPanel = flicking.renderer.panels[this._index - 1];
284
317
 
285
318
  if (cached) {
286
319
  this._size = cached.size;
287
320
  this._margin = { ...cached.margin };
288
321
  this._height = cached.height;
289
322
  } else {
323
+ const elStyle = getStyle(el);
324
+
290
325
  this._size = horizontal ? el.offsetWidth : el.offsetHeight;
291
326
  this._margin = horizontal
292
327
  ? {
@@ -299,10 +334,7 @@ abstract class Panel {
299
334
  this._height = horizontal ? el.offsetHeight : this._size;
300
335
  }
301
336
 
302
- this._pos = prevPanel
303
- ? prevPanel.range.max + prevPanel.margin.next + this._margin.prev
304
- : this._margin.prev;
305
-
337
+ this.updatePosition();
306
338
  this._updateAlignPos();
307
339
 
308
340
  return this;
@@ -317,29 +349,11 @@ abstract class Panel {
317
349
  * @chainable
318
350
  * @return {this}
319
351
  */
320
- public setSize({
321
- width,
322
- height
323
- }: Partial<{
352
+ public setSize(size: Partial<{
324
353
  width: number | string;
325
354
  height: number | string;
326
355
  }>): this {
327
- const el = this.element;
328
-
329
- if (width != null) {
330
- if (isString(width)) {
331
- el.style.width = width;
332
- } else {
333
- el.style.width = `${width}px`;
334
- }
335
- }
336
- if (height != null) {
337
- if (isString(height)) {
338
- el.style.height = height;
339
- } else {
340
- el.style.height = `${height}px`;
341
- }
342
- }
356
+ setSize(this.element, size);
343
357
 
344
358
  return this;
345
359
  }
@@ -376,7 +390,7 @@ abstract class Panel {
376
390
  }
377
391
 
378
392
  /**
379
- * Check whether the given range is fully included in this panel's area
393
+ * Check whether the given range is fully included in this panel's area (inclusive)
380
394
  * @ko 주어진 범위가 이 패널 내부에 완전히 포함되는지를 반환합니다
381
395
  * @param {number} min Minimum value of the range to check<ko>확인하고자 하는 최소 범위</ko>
382
396
  * @param {number} max Maximum value of the range to check<ko>확인하고자 하는 최대 범위</ko>
@@ -395,6 +409,19 @@ abstract class Panel {
395
409
  return max >= panelRange.min && min <= panelRange.max;
396
410
  }
397
411
 
412
+ /**
413
+ * Check whether the panel is visble in the given range (exclusive)
414
+ * @ko 주어진 범위 내에서 이 패널의 일부가 보여지는지를 반환합니다
415
+ * @param {number} min Minimum value of the range to check<ko>확인하고자 하는 최소 범위</ko>
416
+ * @param {number} max Maximum value of the range to check<ko>확인하고자 하는 최대 범위</ko>
417
+ * @returns {boolean} A Boolean value indicating whether the panel is visible<ko>해당 범위 내에서 패널을 볼 수 있는지 여부</ko>
418
+ */
419
+ public isVisibleOnRange(min: number, max: number): boolean {
420
+ const panelRange = this.range;
421
+
422
+ return max > panelRange.min && min < panelRange.max;
423
+ }
424
+
398
425
  /**
399
426
  * Move {@link Camera} to this panel
400
427
  * @ko {@link Camera}를 이 패널로 이동합니다
@@ -472,28 +499,15 @@ abstract class Panel {
472
499
  }
473
500
 
474
501
  /**
475
- * Increase panel's position by the given value
476
- * @ko 패널의 위치를 주어진 값만큼 증가시킵니다
477
502
  * @internal
478
- * @chainable
479
- * @param val An integer greater than or equal to 0<ko>0보다 같거나 큰 정수</ko>
480
- * @returns {this}
481
503
  */
482
- public increasePosition(val: number): this {
483
- this._moveBy(Math.max(val, 0));
484
- return this;
485
- }
504
+ public updatePosition(): this {
505
+ const prevPanel = this._flicking.renderer.panels[this._index - 1];
506
+
507
+ this._pos = prevPanel
508
+ ? prevPanel.range.max + prevPanel.margin.next + this._margin.prev
509
+ : this._margin.prev;
486
510
 
487
- /**
488
- * Decrease panel's position by the given value
489
- * @ko 패널의위치를 주어진 값만큼 감소시킵니다
490
- * @internal
491
- * @chainable
492
- * @param val An integer greater than or equal to 0<ko>0보다 같거나 큰 정수</ko>
493
- * @returns {this}
494
- */
495
- public decreasePosition(val: number): this {
496
- this._moveBy(-Math.max(val, 0));
497
511
  return this;
498
512
  }
499
513
 
@@ -563,12 +577,6 @@ abstract class Panel {
563
577
  return this;
564
578
  }
565
579
 
566
- private _moveBy(val: number): this {
567
- this._pos += val;
568
-
569
- return this;
570
- }
571
-
572
580
  private _updateAlignPos() {
573
581
  this._alignPos = parseAlign(this._align, this._size);
574
582
  }
@@ -0,0 +1,110 @@
1
+ /*
2
+ * Copyright (c) 2015 NAVER Corp.
3
+ * egjs projects are licensed under the MIT license
4
+ */
5
+ import { DIRECTION } from "../../const/external";
6
+ import { circulateIndex } from "../../utils";
7
+
8
+ import Panel, { PanelOptions } from "./Panel";
9
+ import VirtualElementProvider from "./provider/VirtualElementProvider";
10
+
11
+ interface VirtualPanelOptions extends PanelOptions {
12
+ elementProvider: VirtualElementProvider;
13
+ }
14
+
15
+ /**
16
+ * An slide data component that holds information of a single HTMLElement
17
+ * @ko 슬라이드 데이터 컴포넌트로, 단일 HTMLElement의 정보를 갖고 있습니다
18
+ */
19
+ class VirtualPanel extends Panel {
20
+ protected _elProvider: VirtualElementProvider;
21
+ protected _cachedInnerHTML: string | null;
22
+
23
+ /**
24
+ * `HTMLElement` that panel's referencing
25
+ * @ko 패널이 참조하고 있는 `HTMLElement`
26
+ * @type {HTMLElement}
27
+ * @readonly
28
+ */
29
+ public get element() { return this._elProvider.element; }
30
+
31
+ /**
32
+ * Cached innerHTML by the previous render function
33
+ * @ko 이전 렌더링에서 캐시된 innerHTML 정보
34
+ * @type {string|null}
35
+ * @readonly
36
+ */
37
+ public get cachedInnerHTML() { return this._cachedInnerHTML; }
38
+
39
+ /**
40
+ * An number for indexing which element it will be rendered on
41
+ * @ko 몇 번째 엘리먼트에 렌더링될 것인지를 나타내는 숫자
42
+ * @type {number}
43
+ * @readonly
44
+ */
45
+ public get elementIndex() {
46
+ const flicking = this._flicking;
47
+ const virtualElCount = flicking.panelsPerView + 1;
48
+ const panelCount = flicking.panelCount;
49
+ let index = this._index;
50
+
51
+ if (this._toggled) {
52
+ // To prevent element duplication
53
+ index = this._toggleDirection === DIRECTION.NEXT
54
+ ? index + panelCount
55
+ : index - panelCount;
56
+ }
57
+
58
+ return circulateIndex(index, virtualElCount);
59
+ }
60
+
61
+ /**
62
+ * @param {object} options An options object<ko>옵션 오브젝트</ko>
63
+ * @param {number} [options.index] An initial index of the panel<ko>패널의 초기 인덱스</ko>
64
+ * @param {Constants.ALIGN | string | number} [options.align] An initial {@link Flicking#align align} value of the panel<ko>패널의 초기 {@link Flicking#align align}값</ko>
65
+ * @param {Flicking} [options.flicking] A Flicking instance panel's referencing<ko>패널이 참조하는 {@link Flicking} 인스턴스</ko>
66
+ */
67
+ public constructor(options: VirtualPanelOptions) {
68
+ super(options);
69
+
70
+ options.elementProvider.init(this);
71
+ this._elProvider = options.elementProvider;
72
+ this._cachedInnerHTML = null;
73
+ }
74
+
75
+ public cacheRenderResult(result: string) {
76
+ this._cachedInnerHTML = result;
77
+ }
78
+
79
+ public uncacheRenderResult() {
80
+ this._cachedInnerHTML = null;
81
+ }
82
+
83
+ public render() {
84
+ const flicking = this._flicking;
85
+ const { renderPanel, cache } = flicking.virtual;
86
+
87
+ const element = this._elProvider.element;
88
+ const newInnerHTML = this._cachedInnerHTML || renderPanel(this, this._index);
89
+
90
+ if (newInnerHTML === element.innerHTML) return;
91
+
92
+ element.innerHTML = newInnerHTML;
93
+
94
+ if (cache) {
95
+ this.cacheRenderResult(newInnerHTML);
96
+ }
97
+ }
98
+
99
+ public increaseIndex(val: number) {
100
+ this.uncacheRenderResult();
101
+ return super.increaseIndex(val);
102
+ }
103
+
104
+ public decreaseIndex(val: number) {
105
+ this.uncacheRenderResult();
106
+ return super.decreaseIndex(val);
107
+ }
108
+ }
109
+
110
+ export default VirtualPanel;
@@ -3,17 +3,18 @@
3
3
  * egjs projects are licensed under the MIT license
4
4
  */
5
5
  import Panel, { PanelOptions } from "./Panel";
6
- import ElementPanel, { ElementPanelOptions } from "./ElementPanel";
7
6
  import ExternalPanel, { ExternalPanelOptions } from "./ExternalPanel";
7
+ import VirtualPanel from "./VirtualPanel";
8
+
9
+ export * from "./provider";
8
10
 
9
11
  export {
10
12
  Panel,
11
- ElementPanel,
12
- ExternalPanel
13
+ ExternalPanel,
14
+ VirtualPanel
13
15
  };
14
16
 
15
17
  export type {
16
18
  PanelOptions,
17
- ElementPanelOptions,
18
19
  ExternalPanelOptions
19
20
  };
@@ -0,0 +1,13 @@
1
+ /*
2
+ * Copyright (c) 2015 NAVER Corp.
3
+ * egjs projects are licensed under the MIT license
4
+ */
5
+ import Flicking from "../../../Flicking";
6
+
7
+ interface ElementProvider {
8
+ element: HTMLElement;
9
+ show(flicking: Flicking): void;
10
+ hide(flicking: Flicking): void;
11
+ }
12
+
13
+ export default ElementProvider;
@@ -0,0 +1,15 @@
1
+ /*
2
+ * Copyright (c) 2015 NAVER Corp.
3
+ * egjs projects are licensed under the MIT license
4
+ */
5
+ import Flicking from "../../../Flicking";
6
+
7
+ import ElementProvider from "./ElementProvider";
8
+
9
+ interface ExternalElementProvider extends ElementProvider {
10
+ rendered: boolean;
11
+ show(flicking: Flicking): any;
12
+ hide(flicking: Flicking): any;
13
+ }
14
+
15
+ export default ExternalElementProvider;