@syncfusion/ej2-lists 19.4.38 → 19.4.55

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.
@@ -1,2603 +0,0 @@
1
- import { Virtualization } from './virtualization';
2
- import { merge, formatUnit, isNullOrUndefined, append, detach, ModuleDeclaration, extend } from '@syncfusion/ej2-base';
3
- import { attributes, addClass, removeClass, prepend, closest, remove } from '@syncfusion/ej2-base';
4
- import { Component, EventHandler, BaseEventArgs, Property, Complex, Event } from '@syncfusion/ej2-base';
5
- import { NotifyPropertyChanges, INotifyPropertyChanged, ChildProperty } from '@syncfusion/ej2-base';
6
- import { KeyboardEventArgs, EmitType, compile, SanitizeHtmlHelper } from '@syncfusion/ej2-base';
7
- import { Animation, AnimationOptions, Effect, rippleEffect, Touch, SwipeEventArgs } from '@syncfusion/ej2-base';
8
- import { DataManager, Query } from '@syncfusion/ej2-data';
9
- import { createCheckBox } from '@syncfusion/ej2-buttons';
10
- import { ListBase, ListBaseOptions, SortOrder, getFieldValues, FieldsMapping } from '../common/list-base';
11
- import { ListViewModel, FieldSettingsModel } from './list-view-model';
12
-
13
- // Effect Configuration Effect[] = [fromViewBackward,fromViewForward,toViewBackward,toviewForward];
14
- const effectsConfig: { [key: string]: Effect[] } = {
15
- 'None': [],
16
- 'SlideLeft': ['SlideRightOut', 'SlideLeftOut', 'SlideLeftIn', 'SlideRightIn'],
17
- 'SlideDown': ['SlideTopOut', 'SlideBottomOut', 'SlideBottomIn', 'SlideTopIn'],
18
- 'Zoom': ['FadeOut', 'FadeZoomOut', 'FadeZoomIn', 'FadeIn'],
19
- 'Fade': ['FadeOut', 'FadeOut', 'FadeIn', 'FadeIn']
20
- };
21
-
22
- const effectsRTLConfig: { [key: string]: Effect[] } = {
23
- 'None': [],
24
- 'SlideLeft': ['SlideLeftOut', 'SlideRightOut', 'SlideRightIn', 'SlideLeftIn'],
25
- 'SlideDown': ['SlideBottomOut', 'SlideTopOut', 'SlideTopIn', 'SlideBottomIn'],
26
- 'Zoom': ['FadeZoomOut', 'FadeOut', 'FadeIn', 'FadeZoomIn'],
27
- 'Fade': ['FadeOut', 'FadeOut', 'FadeIn', 'FadeIn']
28
- };
29
-
30
- // don't use space in classnames.
31
- export const classNames: ClassNames = {
32
- root: 'e-listview',
33
- hover: 'e-hover',
34
- selected: 'e-active',
35
- focused: 'e-focused',
36
- parentItem: 'e-list-parent',
37
- listItem: 'e-list-item',
38
- listIcon: 'e-list-icon',
39
- textContent: 'e-text-content',
40
- listItemText: 'e-list-text',
41
- groupListItem: 'e-list-group-item',
42
- hasChild: 'e-has-child',
43
- view: 'e-view',
44
- header: 'e-list-header',
45
- headerText: 'e-headertext',
46
- headerTemplateText: 'e-headertemplate-text',
47
- text: 'e-text',
48
- disable: 'e-disabled',
49
- content: 'e-content',
50
- icon: 'e-icons',
51
- backIcon: 'e-icon-back',
52
- checkboxWrapper: 'e-checkbox-wrapper',
53
- checkbox: 'e-checkbox',
54
- checked: 'e-check',
55
- checklist: 'e-checklist',
56
- checkboxIcon: 'e-frame',
57
- checkboxRight: 'e-checkbox-right',
58
- checkboxLeft: 'e-checkbox-left',
59
- listviewCheckbox: 'e-listview-checkbox',
60
- itemCheckList: 'e-checklist',
61
- virtualElementContainer: 'e-list-virtualcontainer'
62
- };
63
-
64
- const LISTVIEW_TEMPLATE_PROPERTY: string = 'Template';
65
- const LISTVIEW_GROUPTEMPLATE_PROPERTY: string = 'GroupTemplate';
66
- const LISTVIEW_HEADERTEMPLATE_PROPERTY: string = 'HeaderTemplate';
67
- const swipeVelocity: number = 0.5;
68
-
69
- /**
70
- * An interface that holds options of fields.
71
- */
72
- export interface Fields {
73
- /**
74
- * Specifies the id field mapped in dataSource.
75
- */
76
- id?: string | number;
77
- /**
78
- * The `text` property is used to map the text value from the data source for each list item.
79
- */
80
- text?: string | number;
81
- /**
82
- * It is used to map the custom field values of list item from the dataSource.
83
- */
84
- [key: string]: Object | string | number | undefined;
85
- }
86
-
87
-
88
- /**
89
- * Represents the field settings of the ListView.
90
- */
91
-
92
- export class FieldSettings extends ChildProperty<FieldSettings> {
93
-
94
- /**
95
- * Specifies the id field mapped in dataSource.
96
- */
97
- @Property('id')
98
- public id: string;
99
- /**
100
- * The `text` property is used to map the text value from the data source for each list item.
101
- */
102
- @Property('text')
103
- public text: string;
104
-
105
- /**
106
- * The `isChecked` property is used to check whether the list items are in checked state or not.
107
- */
108
- @Property('isChecked')
109
- public isChecked: string;
110
- /**
111
- * The `isVisible` property is used to check whether the list items are in visible state or not.
112
- */
113
- @Property('isVisible')
114
- public isVisible: string;
115
- /**
116
- * Specifies the enabled state of the ListView component.
117
- * And, we can disable the component using this property by setting its value as false.
118
- */
119
- @Property('enabled')
120
- public enabled: string;
121
- /**
122
- * The `iconCss` is used to customize the icon to the list items dynamically.
123
- * We can add a specific image to the icons using `iconCss` property.
124
- */
125
- @Property('iconCss')
126
- public iconCss: string;
127
- /**
128
- * The `child` property is used for nested navigation of listed items.
129
- */
130
- @Property('child')
131
- public child: string;
132
- /**
133
- * The `tooltip` is used to display the information about the target element while hovering on list items.
134
- */
135
- @Property('tooltip')
136
- public tooltip: string;
137
-
138
- /**
139
- * The `groupBy` property is used to wraps the ListView elements into a group.
140
- */
141
- @Property('groupBy')
142
- public groupBy: string;
143
-
144
- /**
145
- * The `sortBy` property used to enable the sorting of list items to be ascending or descending order.
146
- */
147
- @Property('text')
148
- public sortBy: string;
149
-
150
- /**
151
- * The `htmlAttributes` allows additional attributes such as id, class, etc., and
152
- * accepts n number of attributes in a key-value pair format.
153
- */
154
- @Property('htmlAttributes')
155
- public htmlAttributes: string;
156
- /**
157
- * Specifies the `tableName` used to fetch data from a specific table in the server.
158
- */
159
- @Property('tableName')
160
- public tableName: string;
161
- }
162
-
163
- /**
164
- * An interface that holds animation settings.
165
- */
166
- export interface AnimationSettings {
167
- /**
168
- * It is used to specify the effect which is shown in sub list transform.
169
- */
170
- effect?: ListViewEffect;
171
- /**
172
- * It is used to specify the time duration of transform object.
173
- */
174
- duration?: number;
175
- /**
176
- * It is used to specify the easing effect applied while transform
177
- */
178
- easing?: string;
179
- }
180
-
181
- /**
182
- * An enum type that denotes the effects of the ListView. Available options are as follows None, SlideLeft, SlideDown, Zoom, Fade;
183
- */
184
- export type ListViewEffect = 'None' | 'SlideLeft' | 'SlideDown' | 'Zoom' | 'Fade';
185
-
186
- /**
187
- * An enum type that denotes the position of checkbox of the ListView. Available options are as follows Left and Right;
188
- */
189
- export type checkBoxPosition = 'Left' | 'Right';
190
-
191
-
192
- /**
193
- * Represents the EJ2 ListView control.
194
- * ```html
195
- * <div id="listview">
196
- * <ul>
197
- * <li>Favorite</li>
198
- * <li>Documents</li>
199
- * <li>Downloads</li>
200
- * </ul>
201
- * </div>
202
- * ```
203
- * ```typescript
204
- * var listviewObject = new ListView({});
205
- * listviewObject.appendTo("#listview");
206
- * ```
207
- */
208
- @NotifyPropertyChanges
209
- export class ListView extends Component<HTMLElement> implements INotifyPropertyChanged {
210
-
211
- private ulElement: HTMLElement;
212
- private selectedLI: Element;
213
- // eslint-disable-next-line
214
- private onUIScrolled: Function;
215
- private curUL: HTMLElement;
216
- private curDSLevel: string[];
217
- private curViewDS: DataSource[] | string[] | number[];
218
- private curDSJSON: DataSource;
219
- public localData: DataSource[];
220
- private liCollection: HTMLElement[];
221
- private headerEle: HTMLElement;
222
- private contentContainer: HTMLElement;
223
- private touchModule: Touch;
224
- private listBaseOption: ListBaseOptions;
225
- public virtualizationModule: Virtualization;
226
- private animateOptions: AnimationOptions;
227
- // eslint-disable-next-line
228
- private rippleFn: Function;
229
- private isNestedList: boolean;
230
- private currentLiElements: HTMLElement[];
231
- private selectedData: string[] | string;
232
- private selectedId: string[];
233
- private isWindow: boolean;
234
- private selectedItems: SelectedItem;
235
- private aniObj: Animation;
236
- private LISTVIEW_TEMPLATE_ID: string;
237
- private LISTVIEW_GROUPTEMPLATE_ID: string;
238
- private LISTVIEW_HEADERTEMPLATE_ID: string;
239
- private liElement: Element;
240
- private virtualCheckBox: Element | string;
241
- private liElementHeight: number;
242
- private previousSelectedItems: string[] = [];
243
- private hiddenItems: string[] = [];
244
- private enabledItems: string[] = [];
245
- private disabledItems: string[] = [];
246
- private isOffline: boolean;
247
- /**
248
- * The `cssClass` property is used to add a user-preferred class name in the root element of the ListView,
249
- * using which we can customize the component (both CSS and functionality customization)
250
- *
251
- * {% codeBlock src='listview/cssClass/index.md' %}{% endcodeBlock %}
252
- *
253
- * @default ''
254
- */
255
- @Property('')
256
- public cssClass: string;
257
-
258
- /**
259
- * If `enableVirtualization` set to true, which will increase the ListView performance, while loading a large amount of data.
260
- *
261
- * {% codeBlock src='listview/enableVirtualization/index.md' %}{% endcodeBlock %}
262
- *
263
- * @default false
264
- */
265
- @Property(false)
266
- public enableVirtualization: boolean;
267
-
268
- /**
269
- * The `htmlAttributes` allows additional attributes such as id, class, etc., and
270
- * accepts n number of attributes in a key-value pair format.
271
- *
272
- * {% codeBlock src='listview/htmlAttributes/index.md' %}{% endcodeBlock %}
273
- *
274
- * @default {}
275
- */
276
- @Property({})
277
- public htmlAttributes: { [key: string]: string; };
278
-
279
- /**
280
- * If `enable` set to true, the list items are enabled.
281
- * And, we can disable the component using this property by setting its value as false.
282
- *
283
- * {% codeBlock src='listview/enable/index.md' %}{% endcodeBlock %}
284
- *
285
- * @default true
286
- */
287
- @Property(true)
288
- public enable: boolean;
289
- /* es-lint disable */
290
- /**
291
- * The `dataSource` provides the data to render the ListView component which is mapped with the fields of ListView.
292
- *
293
- * @isGenericType true
294
- *
295
- * {% codeBlock src='listview/dataSource/index.md' %}{% endcodeBlock %}
296
- *
297
- * @default []
298
- */
299
- @Property([])
300
- public dataSource: { [key: string]: Object }[] | string[] | number[] | DataManager;
301
- /* es-lint enable */
302
- /**
303
- * The `query` is used to fetch the specific data from dataSource by using where and select keywords.
304
- *
305
- * {% codeBlock src='listview/query/index.md' %}{% endcodeBlock %}
306
- *
307
- * @default null
308
- */
309
- @Property()
310
- public query: Query;
311
-
312
- /**
313
- * The `fields` is used to map keys from the dataSource which extracts the appropriate data from the dataSource
314
- * with specified mapped with the column fields to render the ListView.
315
- *
316
- * {% codeBlock src='listview/fields/index.md' %}{% endcodeBlock %}
317
- *
318
- * @default defaultMappedFields
319
- */
320
- @Complex<FieldSettingsModel>(ListBase.defaultMappedFields, FieldSettings)
321
- public fields: FieldSettingsModel;
322
-
323
- /**
324
- * The `animation` property provides an option to apply the different
325
- * animations on the ListView component.
326
- *
327
- * {% codeBlock src='listview/animation/index.md' %}{% endcodeBlock %}
328
- *
329
- *
330
- * @default { effect: 'SlideLeft', duration: 400, easing: 'ease' }
331
- */
332
- @Property<AnimationSettings>({ effect: 'SlideLeft', duration: 400, easing: 'ease' })
333
- public animation: AnimationSettings;
334
-
335
- /**
336
- * The `sortOrder` is used to sort the data source. The available type of sort orders are,
337
- * * `None` - The data source is not sorting.
338
- * * `Ascending` - The data source is sorting with ascending order.
339
- * * `Descending` - The data source is sorting with descending order.
340
- *
341
- * {% codeBlock src='listview/sortOrder/index.md' %}{% endcodeBlock %}
342
- *
343
- * @default 'None'
344
- */
345
- @Property<SortOrder>('None')
346
- public sortOrder: SortOrder;
347
-
348
- /**
349
- * If `showIcon` set to true, which will show or hide the icon of the list item.
350
- *
351
- * {% codeBlock src='listview/showIcon/index.md' %}{% endcodeBlock %}
352
- *
353
- * @default false
354
- */
355
- @Property<boolean>(false)
356
- public showIcon: boolean;
357
-
358
- /**
359
- * If `showCheckBox` set to true, which will show or hide the checkbox.
360
- *
361
- * {% codeBlock src='listview/showCheckBox/index.md' %}{% endcodeBlock %}
362
- *
363
- *
364
- * @default false
365
- */
366
- @Property<boolean>(false)
367
- public showCheckBox: boolean;
368
-
369
- /**
370
- * The `checkBoxPosition` is used to set the position of check box in a list item.
371
- * By default, the `checkBoxPosition` is Left, which will appear before the text content in a list item.
372
- *
373
- * {% codeBlock src='listview/checkBoxPosition/index.md' %}{% endcodeBlock %}
374
- *
375
- * @default 'Left'
376
- */
377
- @Property<string>('Left')
378
- public checkBoxPosition: checkBoxPosition;
379
-
380
- /**
381
- * The `headerTitle` is used to set the title of the ListView component.
382
- *
383
- * {% codeBlock src='listview/headerTitle/index.md' %}{% endcodeBlock %}
384
- *
385
- *
386
- * @default ""
387
- */
388
- @Property<string>('')
389
- public headerTitle: string;
390
-
391
- /**
392
- * If `showHeader` set to true, which will show or hide the header of the ListView component.
393
- *
394
- * {% codeBlock src='listview/showHeader/index.md' %}{% endcodeBlock %}
395
- *
396
- * @default false
397
- */
398
- @Property<boolean>(false)
399
- public showHeader: boolean;
400
-
401
- /**
402
- * If `enableHtmlSanitizer` set to true, allows the cross-scripting site.
403
- *
404
- * {% codeBlock src='listview/enableHtmlSanitizer/index.md' %}{% endcodeBlock %}
405
- *
406
- * @default false
407
- */
408
- @Property(false)
409
- public enableHtmlSanitizer: boolean;
410
-
411
- /**
412
- * Defines the height of the ListView component which accepts both string and number values.
413
- *
414
- * {% codeBlock src='listview/height/index.md' %}{% endcodeBlock %}
415
- *
416
- * @default ''
417
- */
418
- @Property('')
419
- public height: number | string;
420
-
421
- /**
422
- * Defines the width of the ListView component which accepts both string and number values.
423
- *
424
- * {% codeBlock src='listview/width/index.md' %}{% endcodeBlock %}
425
- *
426
- * @default ''
427
- */
428
- @Property('')
429
- public width: number | string;
430
-
431
- /**
432
- * The ListView component supports to customize the content of each list items with the help of `template` property.
433
- *
434
- * {% codeBlock src='listview/template/index.md' %}{% endcodeBlock %}
435
- *
436
- * @default null
437
- * @deprecated
438
- */
439
- @Property(null)
440
- public template: string;
441
-
442
- /**
443
- * The ListView has an option to custom design the ListView header title with the help of `headerTemplate` property.
444
- *
445
- * {% codeBlock src="listview/headerTemplate/index.md" %}{% endcodeBlock %}
446
- *
447
- * @default null
448
- * @deprecated
449
- */
450
- @Property(null)
451
- public headerTemplate: string;
452
-
453
- /**
454
- * The ListView has an option to custom design the group header title with the help of `groupTemplate` property.
455
- *
456
- * {% codeBlock src="listview/groupTemplate/index.md" %}{% endcodeBlock %}
457
- *
458
- * @default null
459
- * @deprecated
460
- */
461
- @Property(null)
462
- public groupTemplate: string;
463
-
464
- /**
465
- * Triggers when we select the list item in the component.
466
- *
467
- * @event 'object'
468
- */
469
- @Event()
470
- public select: EmitType<SelectEventArgs>;
471
-
472
- /**
473
- * Triggers when every ListView action starts.
474
- *
475
- * @event 'object'
476
- */
477
- @Event()
478
- public actionBegin: EmitType<object>;
479
-
480
- /**
481
- * Triggers when every ListView actions completed.
482
- *
483
- * @event 'object'
484
- */
485
- /* es-lint disable */
486
- @Event()
487
- public actionComplete: EmitType<MouseEvent>;
488
- /* es-lint enable */
489
- /**
490
- * Triggers, when the data fetch request from the remote server, fails.
491
- *
492
- * @event 'object'
493
- *
494
- */
495
- @Event()
496
- public actionFailure: EmitType<MouseEvent>;
497
-
498
-
499
- /**
500
- * Constructor for creating the widget
501
- *
502
- * @param options
503
- *
504
- * @param element
505
- */
506
-
507
- constructor(options?: ListViewModel, element?: string | HTMLElement) {
508
- super(options, <HTMLElement | string>element);
509
- }
510
-
511
- /**
512
- * @param newProp
513
- *
514
- * @param oldProp
515
- *
516
- * @private
517
- */
518
-
519
- public onPropertyChanged(newProp: ListViewModel, oldProp: ListViewModel): void {
520
- for (const prop of Object.keys(newProp)) {
521
- switch (prop) {
522
- case 'htmlAttributes':
523
- this.setHTMLAttribute();
524
- break;
525
- case 'cssClass':
526
- this.setCSSClass(oldProp.cssClass);
527
- break;
528
- case 'enable':
529
- this.setEnable();
530
- break;
531
- case 'width':
532
- case 'height':
533
- this.setSize();
534
- break;
535
- case 'enableRtl':
536
- this.setEnableRTL();
537
- break;
538
- case 'fields':
539
- // eslint-disable-next-line
540
- this.listBaseOption.fields = (this.fields as any & { properties: object }).properties;
541
- if (this.enableVirtualization) {
542
- this.virtualizationModule.reRenderUiVirtualization();
543
- } else {
544
- this.reRender();
545
- }
546
- break;
547
- case 'headerTitle':
548
- if (!this.curDSLevel.length) {
549
- this.header(this.headerTitle, false, 'header');
550
- }
551
- break;
552
- case 'query':
553
- if (this.enableVirtualization) {
554
- this.virtualizationModule.reRenderUiVirtualization();
555
- } else {
556
- this.reRender();
557
- }
558
- break;
559
- case 'showHeader':
560
- this.header(this.headerTitle, false, 'header');
561
- break;
562
- case 'enableVirtualization':
563
- if (!isNullOrUndefined(this.contentContainer)) {
564
- detach(this.contentContainer);
565
- }
566
- this.refresh();
567
- break;
568
- case 'showCheckBox':
569
- case 'checkBoxPosition':
570
- if (this.enableVirtualization) {
571
- this.virtualizationModule.reRenderUiVirtualization();
572
- } else {
573
- this.setCheckbox();
574
- }
575
- break;
576
- case 'dataSource':
577
- if (this.enableVirtualization) {
578
- this.virtualizationModule.reRenderUiVirtualization();
579
- } else {
580
- this.reRender();
581
- }
582
- break;
583
- case 'sortOrder':
584
- case 'template':
585
- if (!this.enableVirtualization) {
586
- this.refresh();
587
- }
588
- break;
589
- case 'showIcon':
590
- if (this.enableVirtualization) {
591
- this.virtualizationModule.reRenderUiVirtualization();
592
- } else {
593
- this.listBaseOption.showIcon = this.showIcon;
594
- this.curViewDS = this.getSubDS();
595
- this.resetCurrentList();
596
- }
597
- break;
598
- default:
599
- break;
600
- }
601
- }
602
- }
603
-
604
- // Model Changes
605
- private setHTMLAttribute(): void {
606
- if (Object.keys(this.htmlAttributes).length) {
607
- attributes(this.element, this.htmlAttributes);
608
- }
609
- }
610
-
611
- private setCSSClass(oldCSSClass?: string): void {
612
- if (this.cssClass) {
613
- addClass([this.element], this.cssClass.split(' ').filter((css: string) => css));
614
- }
615
- if (oldCSSClass) {
616
- removeClass([this.element], oldCSSClass.split(' ').filter((css: string) => css));
617
- }
618
- }
619
-
620
- private setSize(): void {
621
- this.element.style.height = formatUnit(this.height);
622
- this.element.style.width = formatUnit(this.width);
623
- this.isWindow = this.element.clientHeight ? false : true;
624
- }
625
-
626
- private setEnable(): void {
627
- this.enableElement(this.element, this.enable);
628
- }
629
-
630
- private setEnableRTL(): void {
631
- if (this.enableRtl) {
632
- this.element.classList.add('e-rtl');
633
- } else {
634
- this.element.classList.remove('e-rtl');
635
- }
636
- }
637
-
638
- private enableElement(element: HTMLElement, isEnabled?: boolean): void {
639
- if (isEnabled) {
640
- element.classList.remove(classNames.disable);
641
- } else {
642
- element.classList.add(classNames.disable);
643
- }
644
- }
645
-
646
- // Support Component Functions
647
- private header(text?: string, showBack?: boolean, prop?: string): void {
648
- if (this.headerEle === undefined && this.showHeader) {
649
- if (this.enableHtmlSanitizer) {
650
- this.setProperties({ headerTitle: SanitizeHtmlHelper.sanitize(this.headerTitle) }, true);
651
- }
652
- this.headerEle = this.createElement('div', { className: classNames.header });
653
- const innerHeaderEle: HTMLElement = this.createElement('span', { className: classNames.headerText, innerHTML: this.headerTitle });
654
- const textEle: HTMLElement = this.createElement('div', { className: classNames.text, innerHTML: innerHeaderEle.outerHTML });
655
- const hedBackButton: HTMLElement = this.createElement('div', {
656
- className: classNames.icon + ' ' + classNames.backIcon + ' e-but-back',
657
- attrs: { style: 'display:none;' }
658
- });
659
- this.headerEle.appendChild(hedBackButton);
660
- this.headerEle.appendChild(textEle);
661
- if (this.headerTemplate) {
662
- // eslint-disable-next-line
663
- const compiledString: Function = compile(this.headerTemplate);
664
- const headerTemplateEle: HTMLElement = this.createElement('div', { className: classNames.headerTemplateText });
665
- // eslint-disable-next-line
666
- const compiledElement: any = compiledString({}, this, prop, this.LISTVIEW_HEADERTEMPLATE_ID, null, null, this.headerEle);
667
- if (compiledElement) {
668
- append(compiledElement, headerTemplateEle);
669
- }
670
- append([headerTemplateEle], this.headerEle);
671
- // eslint-disable-next-line
672
- if ((this as any).isReact) {
673
- this.renderReactTemplates();
674
- }
675
- }
676
- if (this.headerTemplate && this.headerTitle) {
677
- textEle.classList.add('header');
678
- }
679
- this.element.classList.add('e-has-header');
680
- prepend([this.headerEle], this.element);
681
- } else if (this.headerEle) {
682
- if (this.showHeader) {
683
- this.headerEle.style.display = '';
684
- const textEle: Element = this.headerEle.querySelector('.' + classNames.headerText);
685
- const hedBackButton: Element = this.headerEle.querySelector('.' + classNames.backIcon);
686
- if (this.enableHtmlSanitizer) {
687
- text = SanitizeHtmlHelper.sanitize(text);
688
- }
689
- textEle.innerHTML = text;
690
- if (this.headerTemplate && showBack) {
691
- textEle.parentElement.classList.remove('header');
692
- this.headerEle.querySelector('.' + classNames.headerTemplateText).classList.add('nested-header');
693
- }
694
- if (this.headerTemplate && !showBack) {
695
- textEle.parentElement.classList.add('header');
696
- this.headerEle.querySelector('.' + classNames.headerTemplateText).classList.remove('nested-header');
697
- this.headerEle.querySelector('.' + classNames.headerTemplateText).classList.add('header');
698
- }
699
- if (showBack === true) {
700
- (hedBackButton as HTMLElement).style.display = '';
701
- } else {
702
- (hedBackButton as HTMLElement).style.display = 'none';
703
- }
704
- } else {
705
- this.headerEle.style.display = 'none';
706
- }
707
- }
708
- }
709
-
710
- // Animation Related Functions
711
- private switchView(fromView: HTMLElement, toView: HTMLElement, reverse?: boolean): void {
712
- if (fromView && toView) {
713
- const fPos: string = fromView.style.position;
714
- const overflow: string = (this.element.style.overflow !== 'hidden') ? this.element.style.overflow : '';
715
-
716
- fromView.style.position = 'absolute';
717
- fromView.classList.add('e-view');
718
- let anim: Effect[];
719
- let duration: number = this.animation.duration;
720
- if (this.animation.effect) {
721
- anim = (this.enableRtl ? effectsRTLConfig[this.animation.effect] : effectsConfig[this.animation.effect]);
722
- } else {
723
- const slideLeft: string = 'SlideLeft';
724
- anim = effectsConfig[slideLeft];
725
- reverse = this.enableRtl;
726
- duration = 0;
727
- }
728
- this.element.style.overflow = 'hidden';
729
- this.aniObj.animate(fromView, {
730
- name: (reverse === true ? anim[0] : anim[1]),
731
- duration: duration,
732
- timingFunction: this.animation.easing,
733
- // eslint-disable-next-line
734
- end: (model: AnimationOptions): void => {
735
- fromView.style.display = 'none';
736
- this.element.style.overflow = overflow;
737
- fromView.style.position = fPos;
738
- fromView.classList.remove('e-view');
739
- }
740
- });
741
- toView.style.display = '';
742
- this.aniObj.animate(toView, {
743
- name: (reverse === true ? anim[2] : anim[3]),
744
- duration: duration,
745
- timingFunction: this.animation.easing,
746
- end: (): void => {
747
- this.trigger('actionComplete');
748
- }
749
- });
750
- this.curUL = toView;
751
- }
752
- }
753
-
754
- protected preRender(): void {
755
- if (this.template) {
756
- try {
757
- if (document.querySelectorAll(this.template).length) {
758
- this.setProperties({ template: document.querySelector(this.template).innerHTML.trim() }, true);
759
- }
760
- } catch (e) {
761
- compile(this.template);
762
- }
763
- }
764
- this.listBaseOption = {
765
- template: this.template,
766
- headerTemplate: this.headerTemplate,
767
- groupTemplate: this.groupTemplate, expandCollapse: true, listClass: '',
768
- ariaAttributes: {
769
- itemRole: 'option', listRole: 'presentation', itemText: '',
770
- groupItemRole: 'group', wrapperRole: 'presentation'
771
- },
772
- // eslint-disable-next-line
773
- fields: ((this.fields as any & { properties: Object }).properties) as FieldsMapping,
774
- sortOrder: this.sortOrder,
775
- showIcon: this.showIcon,
776
- itemCreated: this.renderCheckbox.bind(this),
777
- templateID: `${this.element.id}${LISTVIEW_TEMPLATE_PROPERTY}`,
778
- groupTemplateID: `${this.element.id}${LISTVIEW_GROUPTEMPLATE_PROPERTY}`,
779
- enableHtmlSanitizer: this.enableHtmlSanitizer,
780
- };
781
- this.initialization();
782
- }
783
-
784
- private initialization(): void {
785
- this.curDSLevel = [];
786
- this.animateOptions = {};
787
- this.curViewDS = [];
788
- this.currentLiElements = [];
789
- this.isNestedList = false;
790
- this.selectedData = [];
791
- this.selectedId = [];
792
- this.LISTVIEW_TEMPLATE_ID = `${this.element.id}${LISTVIEW_TEMPLATE_PROPERTY}`;
793
- this.LISTVIEW_GROUPTEMPLATE_ID = `${this.element.id}${LISTVIEW_GROUPTEMPLATE_PROPERTY}`;
794
- this.LISTVIEW_HEADERTEMPLATE_ID = `${this.element.id}${LISTVIEW_HEADERTEMPLATE_PROPERTY}`;
795
- this.aniObj = new Animation(this.animateOptions);
796
- this.removeElement(this.curUL);
797
- this.removeElement(this.ulElement);
798
- this.removeElement(this.headerEle);
799
- this.removeElement(this.contentContainer);
800
- this.curUL = this.ulElement = this.liCollection = this.headerEle = this.contentContainer = undefined;
801
- }
802
-
803
- private renderCheckbox(args: ItemCreatedArgs): void {
804
- if (args.item.classList.contains(classNames.hasChild)) {
805
- this.isNestedList = true;
806
- }
807
- if (this.showCheckBox && this.isValidLI(args.item)) {
808
- let checkboxElement: Element;
809
- let fieldData: DataSource;
810
- // eslint-disable-next-line prefer-const
811
- checkboxElement = createCheckBox(this.createElement, false, {
812
- checked: false, enableRtl: this.enableRtl,
813
- cssClass: classNames.listviewCheckbox
814
- });
815
- checkboxElement.setAttribute('role', 'checkbox');
816
- const frameElement: Element = checkboxElement.querySelector('.' + classNames.checkboxIcon);
817
- args.item.classList.add(classNames.itemCheckList);
818
- args.item.firstElementChild.classList.add(classNames.checkbox);
819
- if (typeof (this.dataSource as string[])[0] !== 'string' && typeof (this.dataSource as number[])[0] !== 'number') {
820
- fieldData = <DataSource>getFieldValues(args.curData , this.listBaseOption.fields);
821
- if (<object>fieldData[this.listBaseOption.fields.isChecked]) {
822
- this.checkInternally(args, checkboxElement);
823
- }
824
- } else if (((typeof (this.dataSource as string[])[0] === 'string' ||
825
- typeof (this.dataSource as number[])[0] === 'number') && this.selectedData.indexOf(args.text) !== -1)) {
826
- this.checkInternally(args, checkboxElement);
827
- }
828
- checkboxElement.setAttribute('aria-checked', frameElement.classList.contains(classNames.checked) ? 'true' : 'false');
829
- if (this.checkBoxPosition === 'Left') {
830
- checkboxElement.classList.add(classNames.checkboxLeft);
831
- args.item.firstElementChild.classList.add(classNames.checkboxLeft);
832
- args.item.firstElementChild.insertBefore(checkboxElement, args.item.firstElementChild.childNodes[0]);
833
- } else {
834
- checkboxElement.classList.add(classNames.checkboxRight);
835
- args.item.firstElementChild.classList.add(classNames.checkboxRight);
836
- args.item.firstElementChild.appendChild(checkboxElement);
837
- }
838
- this.currentLiElements.push(args.item);
839
- if ( this.checkBoxPosition === 'Left')
840
- {
841
- this.virtualCheckBox = args.item.firstElementChild.children[0];
842
- }
843
- else
844
- {
845
- this.virtualCheckBox = args.item.firstElementChild.lastElementChild;
846
- }
847
- }
848
- }
849
-
850
- private checkInternally(args: ItemCreatedArgs, checkboxElement: Element): void {
851
- args.item.classList.add(classNames.selected);
852
- args.item.setAttribute('aria-selected', 'true');
853
- checkboxElement.querySelector('.' + classNames.checkboxIcon).classList.add(classNames.checked);
854
- checkboxElement.setAttribute('aria-checked', 'true');
855
- }
856
-
857
- /**
858
- * Checks the specific list item by passing the unchecked fields as an argument to this method.
859
- *
860
- * @param {Fields | HTMLElement | Element} item - It accepts Fields or HTML list element as an argument.
861
- */
862
-
863
- public checkItem(item: Fields | HTMLElement | Element): void {
864
- this.toggleCheckBase(item, true);
865
- }
866
-
867
- private toggleCheckBase(item: Fields | Element | HTMLElement, checked: boolean): void {
868
- if (this.showCheckBox) {
869
- let liElement: Element = item as Element;
870
- if (item instanceof Object && (item as Object).constructor !== HTMLLIElement) {
871
- liElement = this.getLiFromObjOrElement(item);
872
- }
873
- if (!isNullOrUndefined(liElement)) {
874
- const checkboxIcon: Element = liElement.querySelector('.' + classNames.checkboxIcon);
875
- if (checked === true)
876
- {
877
- liElement.classList.add(classNames.selected);
878
- }
879
- else
880
- {
881
- liElement.classList.remove(classNames.selected);
882
- }
883
- liElement.setAttribute('aria-selected', checked ? 'true' : 'false');
884
- if (checked === true)
885
- {
886
- checkboxIcon.classList.add(classNames.checked);
887
- }
888
- else
889
- {
890
- checkboxIcon.classList.remove(classNames.checked);
891
- }
892
- checkboxIcon.parentElement.setAttribute('aria-checked', checked ? 'true' : 'false');
893
- }
894
- this.setSelectedItemData(liElement);
895
- }
896
- }
897
-
898
- /**
899
- * Uncheck the specific list item by passing the checked fields as an argument to this method.
900
- *
901
- * @param {Fields | HTMLElement | Element} item - It accepts Fields or HTML list element as an argument.
902
- */
903
-
904
- public uncheckItem(item: Fields | HTMLElement | Element): void {
905
- this.toggleCheckBase(item, false);
906
- }
907
-
908
- /**
909
- * Checks all the unchecked items in the ListView.
910
- */
911
-
912
- public checkAllItems(): void {
913
- this.toggleAllCheckBase(true);
914
- }
915
-
916
- /**
917
- * Uncheck all the checked items in ListView.
918
- */
919
-
920
- public uncheckAllItems(): void {
921
- this.toggleAllCheckBase(false);
922
- }
923
-
924
- private toggleAllCheckBase(checked: boolean): void {
925
- if (this.showCheckBox) {
926
- for (let i: number = 0; i < this.liCollection.length; i++) {
927
- const checkIcon: Element = this.liCollection[i].querySelector('.' + classNames.checkboxIcon);
928
- if (checkIcon) {
929
- if (checked) {
930
- if (!checkIcon.classList.contains(classNames.checked)) {
931
- this.checkItem(this.liCollection[i]);
932
- }
933
- } else {
934
- if (checkIcon.classList.contains(classNames.checked)) {
935
- this.uncheckItem(this.liCollection[i]);
936
- }
937
- }
938
- }
939
- }
940
- if (this.enableVirtualization) {
941
- this.virtualizationModule.checkedItem(checked);
942
- }
943
- }
944
- }
945
-
946
- private setCheckbox(): void {
947
- if (this.showCheckBox) {
948
- const liCollection: HTMLElement[] = Array.prototype.slice.call(this.element.querySelectorAll('.' + classNames.listItem));
949
- const args: ItemCreatedArgs = {
950
- item: undefined, curData: undefined, dataSource: undefined, fields: undefined,
951
- options: undefined, text: ''
952
- };
953
- for (let i: number = 0; i < liCollection.length; i++) {
954
- const element: HTMLElement = liCollection[i];
955
- args.item = element;
956
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
957
- args.curData = this.getItemData(element) as { [key: string]: Object } as any;
958
- if (element.querySelector('.' + classNames.checkboxWrapper)) {
959
- this.removeElement(element.querySelector('.' + classNames.checkboxWrapper));
960
- }
961
- this.renderCheckbox(args);
962
- if (args.item.classList.contains(classNames.selected)) {
963
- this.checkInternally(args, args.item.querySelector('.' + classNames.checkboxWrapper));
964
- }
965
- }
966
- } else {
967
- const liCollection: HTMLElement[] = Array.prototype.slice.call(this.element.querySelectorAll('.' + classNames.itemCheckList));
968
- for (let i: number = 0; i < liCollection.length; i++) {
969
- const element: HTMLElement = liCollection[i];
970
- element.classList.remove(classNames.selected);
971
- element.firstElementChild.classList.remove(classNames.checkbox);
972
- this.removeElement(element.querySelector('.' + classNames.checkboxWrapper));
973
- }
974
- if (this.selectedItems) {
975
- this.selectedItems.item.classList.add(classNames.selected);
976
- }
977
- }
978
- }
979
-
980
- /**
981
- * Refresh the height of the list item only on enabling the virtualization property.
982
- */
983
-
984
- public refreshItemHeight(): void {
985
- if (this.virtualizationModule) {
986
- this.virtualizationModule.refreshItemHeight();
987
- }
988
- }
989
-
990
- private clickHandler(e: MouseEvent): void {
991
- const target: Element = <Element>e.target;
992
- const classList: DOMTokenList = target.classList;
993
- let closestElement: HTMLElement;
994
- if (classList.contains(classNames.backIcon) || classList.contains(classNames.headerText)) {
995
- if (this.showCheckBox && this.curDSLevel[this.curDSLevel.length - 1]) {
996
- this.uncheckAllItems();
997
- }
998
- this.back();
999
- } else {
1000
- let li: HTMLElement = <HTMLElement>closest(target.parentNode, '.' + classNames.listItem);
1001
- if (li === null) { li = <HTMLElement>target; }
1002
- this.removeFocus();
1003
- if (this.enable && this.showCheckBox && this.isValidLI(li)) {
1004
- if ((e.target as HTMLElement).classList.contains(classNames.checkboxIcon)) {
1005
- li.classList.add(classNames.focused);
1006
- if (isNullOrUndefined(li.querySelector('.' + classNames.checked))) {
1007
- const args: ItemCreatedArgs = {
1008
- curData: undefined, dataSource: undefined, fields: undefined, options: undefined,
1009
- text: undefined, item: li
1010
- };
1011
- this.checkInternally(args, args.item.querySelector('.' + classNames.checkboxWrapper));
1012
- } else {
1013
- this.uncheckItem(li);
1014
- li.classList.add(classNames.focused);
1015
- }
1016
- if (this.enableVirtualization) {
1017
- this.virtualizationModule.setCheckboxLI(li, e);
1018
- }
1019
- if (e) {
1020
- const eventArgs: Object = this.selectEventData(li, e);
1021
- const checkIcon: Element = li.querySelector('.' + classNames.checkboxIcon);
1022
- merge(eventArgs, { isChecked: checkIcon.classList.contains(classNames.checked) });
1023
- this.trigger('select', eventArgs);
1024
- }
1025
- } else if (li.classList.contains(classNames.hasChild)) {
1026
- this.removeHover();
1027
- this.removeSelect();
1028
- this.removeSelect(li);
1029
- this.setSelectLI(li, e);
1030
- li.classList.remove(classNames.selected);
1031
- } else {
1032
- this.setCheckboxLI(li, e);
1033
- }
1034
- } else {
1035
- this.setSelectLI(li, e);
1036
- }
1037
- closestElement = closest((e.target as HTMLElement), 'li') as HTMLElement;
1038
- if (!isNullOrUndefined(closestElement)) {
1039
- if (closestElement.classList.contains('e-has-child') &&
1040
- !(e.target as HTMLElement).parentElement.classList.contains('e-listview-checkbox')) {
1041
- closestElement.classList.add(classNames.disable);
1042
- }
1043
- }
1044
- }
1045
- }
1046
-
1047
- private removeElement(element: HTMLElement | Element): HTMLElement | Element {
1048
- return element && element.parentNode && element.parentNode.removeChild(element);
1049
- }
1050
-
1051
- private hoverHandler(e: MouseEvent): void {
1052
- const curLi: HTMLElement = <HTMLElement>closest((<Element>e.target).parentNode, '.' + classNames.listItem);
1053
- this.setHoverLI(curLi);
1054
- }
1055
-
1056
- // eslint-disable-next-line @typescript-eslint/no-unused-vars
1057
- private leaveHandler(e: MouseEvent): void {
1058
- this.removeHover();
1059
- }
1060
- private homeKeyHandler(e: KeyboardEventArgs, end?: boolean): void {
1061
- if (Object.keys(this.dataSource).length && this.curUL) {
1062
- if (this.selectedItems) {
1063
- (this.selectedItems.item).setAttribute('aria-selected', 'false');
1064
- }
1065
- const li: Element[] = <NodeListOf<Element> & Element[]>this.curUL.querySelectorAll('.' + classNames.listItem);
1066
- const focusedElement: Element = this.curUL.querySelector('.' + classNames.focused) ||
1067
- this.curUL.querySelector('.' + classNames.selected);
1068
- if (focusedElement) {
1069
- focusedElement.classList.remove(classNames.focused);
1070
- if (!this.showCheckBox) {
1071
- focusedElement.classList.remove(classNames.selected);
1072
- }
1073
- }
1074
- const index: number = !end ? 0 : li.length - 1;
1075
- if (li[index].classList.contains(classNames.hasChild) || this.showCheckBox) {
1076
- li[index].classList.add(classNames.focused);
1077
- } else {
1078
- this.setSelectLI(li[index], e);
1079
- }
1080
- if (li[index]) {
1081
- this.element.setAttribute('aria-activedescendant', (<HTMLElement>li[index]).id.toString());
1082
- } else {
1083
- this.element.removeAttribute('aria-activedescendant');
1084
- }
1085
- }
1086
- }
1087
-
1088
- private onArrowKeyDown(e: KeyboardEventArgs, prev: boolean): Element {
1089
- let siblingLI: Element;
1090
- let li: Element;
1091
- const hasChild: boolean = !isNullOrUndefined(this.curUL.querySelector('.' + classNames.hasChild)) ? true : false;
1092
- if (hasChild || this.showCheckBox) {
1093
- li = this.curUL.querySelector('.' + classNames.focused) || this.curUL.querySelector('.' + classNames.selected);
1094
- siblingLI = ListBase.getSiblingLI(this.curUL.querySelectorAll('.' + classNames.listItem), li, prev);
1095
- if (!isNullOrUndefined(siblingLI)) {
1096
- if (li) {
1097
- li.classList.remove(classNames.focused);
1098
- if (!this.showCheckBox) {
1099
- li.classList.remove(classNames.selected);
1100
- }
1101
- }
1102
- if (siblingLI.classList.contains(classNames.hasChild) || this.showCheckBox) {
1103
- siblingLI.classList.add(classNames.focused);
1104
- } else {
1105
- this.setSelectLI(siblingLI, e);
1106
- }
1107
- }
1108
- } else {
1109
- li = this.curUL.querySelector('.' + classNames.selected);
1110
- siblingLI = ListBase.getSiblingLI(this.curUL.querySelectorAll('.' + classNames.listItem), li, prev);
1111
- this.setSelectLI(siblingLI, e);
1112
- }
1113
- if (siblingLI) {
1114
- this.element.setAttribute('aria-activedescendant', (<HTMLElement>siblingLI).id.toString());
1115
- } else {
1116
- this.element.removeAttribute('aria-activedescendant');
1117
- }
1118
- return siblingLI;
1119
- }
1120
-
1121
- private arrowKeyHandler(e: KeyboardEventArgs, prev?: boolean): void {
1122
- e.preventDefault();
1123
- if (Object.keys(this.dataSource).length && this.curUL) {
1124
- const siblingLI: Element = this.onArrowKeyDown(e, prev);
1125
- const elementTop: number = this.element.getBoundingClientRect().top;
1126
- const elementHeight: number = this.element.getBoundingClientRect().height;
1127
- const firstItemBounds: ClientRect = this.curUL.querySelector('.' + classNames.listItem).getBoundingClientRect();
1128
- let heightDiff: number;
1129
- let groupItemBounds: ClientRect;
1130
- if (this.fields.groupBy) {
1131
- groupItemBounds = this.curUL.querySelector('.' + classNames.groupListItem).getBoundingClientRect();
1132
- }
1133
- if (siblingLI) {
1134
- const siblingTop: number = siblingLI.getBoundingClientRect().top;
1135
- const siblingHeight: number = siblingLI.getBoundingClientRect().height;
1136
- if (!prev) {
1137
- const height: number = this.isWindow ? window.innerHeight : elementHeight;
1138
- heightDiff = this.isWindow ? (siblingTop + siblingHeight) :
1139
- ((siblingTop - elementTop) + siblingHeight);
1140
- if (heightDiff > height) {
1141
- if (this.isWindow === true)
1142
- {
1143
- window.scroll(0, pageYOffset + (heightDiff - height));
1144
- }
1145
- else
1146
- {
1147
- this.element.scrollTop = this.element.scrollTop + (heightDiff - height);
1148
- }
1149
- }
1150
- } else {
1151
- heightDiff = this.isWindow ? siblingTop : (siblingTop - elementTop);
1152
- if (heightDiff < 0) {
1153
- if (this.isWindow === true)
1154
- {
1155
- window.scroll(0, pageYOffset + heightDiff);
1156
- }
1157
- else
1158
- {
1159
- this.element.scrollTop = this.element.scrollTop + heightDiff;
1160
- }
1161
- }
1162
- }
1163
- } else if (this.enableVirtualization && prev && this.virtualizationModule.uiFirstIndex) {
1164
- this.onUIScrolled = () => {
1165
- this.onArrowKeyDown(e, prev);
1166
- this.onUIScrolled = undefined;
1167
- };
1168
- heightDiff = this.virtualizationModule.listItemHeight;
1169
- if ( this.isWindow === true)
1170
- {
1171
- window.scroll(0, pageYOffset - heightDiff);
1172
- }
1173
- else
1174
- {
1175
- this.element.scrollTop = this.element.scrollTop - heightDiff;
1176
- }
1177
- } else if (prev) {
1178
- if (this.showHeader && this.headerEle) {
1179
- const topHeight: number = groupItemBounds ? groupItemBounds.top : firstItemBounds.top;
1180
- const headerBounds: ClientRect = this.headerEle.getBoundingClientRect();
1181
- heightDiff = headerBounds.top < 0 ? (headerBounds.height - topHeight) : 0;
1182
- if ( this.isWindow === true)
1183
- {
1184
- window.scroll(0, pageYOffset - heightDiff);
1185
- }
1186
- else
1187
- {
1188
- this.element.scrollTop = 0;
1189
- }
1190
- } else if (this.fields.groupBy) {
1191
- heightDiff = this.isWindow ? (groupItemBounds.top < 0 ? groupItemBounds.top : 0) :
1192
- (elementTop - firstItemBounds.top) + groupItemBounds.height;
1193
- if ( this.isWindow === true)
1194
- {
1195
- window.scroll(0, pageYOffset + heightDiff);
1196
- }
1197
- else
1198
- {
1199
- this.element.scrollTop = this.element.scrollTop - heightDiff;
1200
- }
1201
- }
1202
- }
1203
- }
1204
- }
1205
-
1206
- private enterKeyHandler(e: KeyboardEventArgs): void {
1207
- if (Object.keys(this.dataSource).length && this.curUL) {
1208
- const hasChild: boolean = !isNullOrUndefined(this.curUL.querySelector('.' + classNames.hasChild)) ? true : false;
1209
- const li: Element = this.curUL.querySelector('.' + classNames.focused);
1210
- if (hasChild && li) {
1211
- li.classList.remove(classNames.focused);
1212
- if (this.showCheckBox) {
1213
- this.removeSelect();
1214
- this.removeSelect(<HTMLElement>li);
1215
- this.removeHover();
1216
- }
1217
- this.setSelectLI(li, e);
1218
- }
1219
- }
1220
- }
1221
- private spaceKeyHandler(e: KeyboardEventArgs): void {
1222
- if (this.enable && this.showCheckBox && Object.keys(this.dataSource).length && this.curUL) {
1223
- const li: Element = this.curUL.querySelector('.' + classNames.focused);
1224
- let checkboxElement: Element;
1225
- let checkIcon: Element;
1226
- if (!isNullOrUndefined(li) && isNullOrUndefined(li.querySelector('.' + classNames.checked))) {
1227
- const args: ItemCreatedArgs = {
1228
- curData: undefined, dataSource: undefined, fields: undefined, options: undefined,
1229
- text: undefined, item: <HTMLElement>li
1230
- };
1231
- checkboxElement = args.item.querySelector('.' + classNames.checkboxWrapper);
1232
- this.checkInternally(args, checkboxElement);
1233
- checkIcon = checkboxElement.querySelector('.' + classNames.checkboxIcon + '.' + classNames.icon);
1234
- } else {
1235
- this.uncheckItem(li);
1236
- }
1237
- const eventArgs: object = this.selectEventData(li, e);
1238
- merge(eventArgs, { isChecked: checkIcon ? checkIcon.classList.contains(classNames.checked) : false });
1239
- this.trigger('select', eventArgs);
1240
- }
1241
- }
1242
-
1243
- private keyActionHandler(e: KeyboardEventArgs): void {
1244
- switch (e.keyCode) {
1245
- case 36:
1246
- this.homeKeyHandler(e);
1247
- break;
1248
- case 35:
1249
- this.homeKeyHandler(e, true);
1250
- break;
1251
- case 40:
1252
- this.arrowKeyHandler(e);
1253
- break;
1254
- case 38:
1255
- this.arrowKeyHandler(e, true);
1256
- break;
1257
- case 13:
1258
- this.enterKeyHandler(e);
1259
- break;
1260
- case 8:
1261
- if (this.showCheckBox && this.curDSLevel[this.curDSLevel.length - 1]) {
1262
- this.uncheckAllItems();
1263
- }
1264
- this.back();
1265
- break;
1266
- case 32:
1267
- this.spaceKeyHandler(e);
1268
- break;
1269
- }
1270
- }
1271
-
1272
- private swipeActionHandler(e: SwipeEventArgs): void {
1273
- if (e.swipeDirection === 'Right' && e.velocity > swipeVelocity && e.originalEvent.type === 'touchend') {
1274
- if (this.showCheckBox && this.curDSLevel[this.curDSLevel.length - 1]) {
1275
- this.uncheckAllItems();
1276
- }
1277
- this.back();
1278
- }
1279
- }
1280
-
1281
- private focusout(): void {
1282
- if (Object.keys(this.dataSource).length && this.curUL) {
1283
- const focusedElement: Element = this.curUL.querySelector('.' + classNames.focused);
1284
- const activeElement: Element = this.curUL.querySelector('[aria-selected = true]');
1285
- if (focusedElement) {
1286
- focusedElement.classList.remove(classNames.focused);
1287
- if (activeElement && !this.showCheckBox) {
1288
- activeElement.classList.add(classNames.selected);
1289
- }
1290
- }
1291
- }
1292
- }
1293
-
1294
- private wireEvents(): void {
1295
- EventHandler.add(this.element, 'keydown', this.keyActionHandler, this);
1296
- EventHandler.add(this.element, 'click', this.clickHandler, this);
1297
- EventHandler.add(this.element, 'mouseover', this.hoverHandler, this);
1298
- EventHandler.add(this.element, 'mouseout', this.leaveHandler, this);
1299
- EventHandler.add(this.element, 'focusout', this.focusout, this);
1300
- this.touchModule = new Touch(this.element, { swipe: this.swipeActionHandler.bind(this) });
1301
- }
1302
-
1303
- private unWireEvents(): void {
1304
- EventHandler.remove(this.element, 'click', this.clickHandler);
1305
- EventHandler.remove(this.element, 'mouseover', this.hoverHandler);
1306
- EventHandler.remove(this.element, 'mouseout', this.leaveHandler);
1307
- EventHandler.remove(this.element, 'mouseover', this.hoverHandler);
1308
- EventHandler.remove(this.element, 'mouseout', this.leaveHandler);
1309
- this.touchModule.destroy();
1310
- }
1311
-
1312
- private removeFocus(): void {
1313
- const focusedLI: Element[] = <NodeListOf<Element> & Element[]>this.element.querySelectorAll('.' + classNames.focused);
1314
- for (const ele of focusedLI) {
1315
- ele.classList.remove(classNames.focused);
1316
- }
1317
- }
1318
-
1319
- private removeHover(): void {
1320
- const hoverLI: Element = this.element.querySelector('.' + classNames.hover);
1321
- if (hoverLI) { hoverLI.classList.remove(classNames.hover); }
1322
- }
1323
-
1324
- private removeSelect(li?: HTMLElement): void {
1325
- if (isNullOrUndefined(li)) {
1326
- const selectedLI: Element[] = <NodeListOf<Element> & Element[]>this.element.querySelectorAll('.' + classNames.selected);
1327
- for (const ele of selectedLI) {
1328
- if (this.showCheckBox && ele.querySelector('.' + classNames.checked)) {
1329
- continue;
1330
- } else {
1331
- ele.setAttribute('aria-selected', 'false');
1332
- ele.classList.remove(classNames.selected);
1333
- }
1334
- }
1335
- } else {
1336
- li.classList.remove(classNames.selected);
1337
- li.setAttribute('aria-selected', 'false');
1338
- }
1339
- }
1340
-
1341
- private isValidLI(li: Element | HTMLElement): boolean {
1342
- return (li && li.classList.contains(classNames.listItem)
1343
- && !li.classList.contains(classNames.groupListItem)
1344
- && !li.classList.contains(classNames.disable));
1345
- }
1346
-
1347
- private setCheckboxLI(li: Element, e?: MouseEvent | KeyboardEvent | FocusEvent): void {
1348
- if (this.isValidLI(li) && this.enable && this.showCheckBox) {
1349
- if (this.curUL.querySelector('.' + classNames.focused)) {
1350
- this.curUL.querySelector('.' + classNames.focused).classList.remove(classNames.focused);
1351
- }
1352
- li.classList.add(classNames.focused);
1353
- const checkboxElement: Element = li.querySelector('.' + classNames.checkboxWrapper);
1354
- const checkIcon: Element = checkboxElement.querySelector('.' + classNames.checkboxIcon + '.' + classNames.icon);
1355
- this.removeHover();
1356
- if (!checkIcon.classList.contains(classNames.checked)) {
1357
- checkIcon.classList.add(classNames.checked);
1358
- li.classList.add(classNames.selected);
1359
- li.setAttribute('aria-selected', 'true');
1360
- } else {
1361
- checkIcon.classList.remove(classNames.checked);
1362
- li.classList.remove(classNames.selected);
1363
- li.setAttribute('aria-selected', 'false');
1364
- }
1365
- checkboxElement.setAttribute('aria-checked', checkIcon.classList.contains(classNames.checked) ?
1366
- 'true' : 'false');
1367
- const eventArgs: object = this.selectEventData(li, e);
1368
- merge(eventArgs, { isChecked: checkIcon.classList.contains(classNames.checked) });
1369
- if (this.enableVirtualization) {
1370
- this.virtualizationModule.setCheckboxLI(li, e);
1371
- }
1372
- this.trigger('select', eventArgs);
1373
- this.setSelectedItemData(li);
1374
- this.renderSubList(li);
1375
- }
1376
- }
1377
-
1378
- private selectEventData(li: Element, e?: MouseEvent | KeyboardEvent | FocusEvent): Object {
1379
- const data: DataSource = this.getItemData(li);
1380
- const fieldData: DataSource = getFieldValues(data as { [key: string]: Object } , this.listBaseOption.fields) as DataSource;
1381
- let selectedItem: SelectedItem;
1382
- if (!isNullOrUndefined(data)
1383
- && typeof (this.dataSource as string[])[0] === 'string' || typeof (this.dataSource as number[])[0] === 'number') {
1384
- selectedItem = { item: li, text: li && (li as HTMLElement).innerText.trim(), data: this.dataSource as string[] | number[] };
1385
- } else {
1386
- selectedItem =
1387
- // eslint-disable-next-line
1388
- { item: li, text: fieldData && <object>fieldData[this.listBaseOption.fields.text] as any,
1389
- // eslint-disable-next-line
1390
- data: data as { [key: string]: Object } as any };
1391
- }
1392
- const eventArgs: object = {};
1393
- merge(eventArgs, selectedItem);
1394
- if (e) {
1395
- merge(eventArgs, { isInteracted: true, event: e, index: this.curUL && Array.prototype.indexOf.call(this.curUL.children, li) });
1396
- }
1397
- return eventArgs;
1398
- }
1399
-
1400
- private setSelectedItemData(li: Element): void {
1401
- const data: DataSource = this.getItemData(li);
1402
- // eslint-disable-next-line
1403
- const fieldData: DataSource = <DataSource>getFieldValues(data as { [key: string]: Object } as any, this.listBaseOption.fields);
1404
- if (!isNullOrUndefined(data) && ((typeof (this.dataSource as string[])[0] === 'string') ||
1405
- (typeof (this.dataSource as number[])[0] === 'number'))) {
1406
- this.selectedItems = {
1407
- item: li,
1408
- text: li && (li as HTMLElement).innerText.trim(),
1409
- data: this.dataSource as string[]
1410
- };
1411
- } else {
1412
- this.selectedItems = {
1413
- item: li,
1414
- // eslint-disable-next-line
1415
- text: fieldData && fieldData[this.listBaseOption.fields.text] as any,
1416
- // eslint-disable-next-line
1417
- data: data as { [key: string]: Object } as any
1418
- };
1419
- }
1420
- }
1421
-
1422
- private setSelectLI(li: Element, e?: MouseEvent | KeyboardEvent | FocusEvent): void {
1423
- if (this.isValidLI(li) && !li.classList.contains(classNames.selected) && this.enable) {
1424
- if (!this.showCheckBox) {
1425
- this.removeSelect();
1426
- }
1427
- li.classList.add(classNames.selected);
1428
- li.setAttribute('aria-selected', 'true');
1429
- this.removeHover();
1430
- this.setSelectedItemData(li);
1431
- if (this.enableVirtualization) {
1432
- this.virtualizationModule.setSelectLI(li, e);
1433
- }
1434
- const eventArgs: object = this.selectEventData(li, e);
1435
- this.trigger('select', eventArgs);
1436
- this.selectedLI = li;
1437
- this.renderSubList(li);
1438
- }
1439
- }
1440
-
1441
- private setHoverLI(li: Element): void {
1442
- if (this.isValidLI(li) && !li.classList.contains(classNames.hover) && this.enable) {
1443
- const lastLi: Element[] = <NodeListOf<Element> & Element[]>this.element.querySelectorAll('.' + classNames.hover);
1444
- if (lastLi && lastLi.length) { removeClass(lastLi, classNames.hover); }
1445
- if (!(li as Element).classList.contains(classNames.selected) || this.showCheckBox) {
1446
- (li as Element).classList.add(classNames.hover);
1447
- }
1448
- }
1449
- }
1450
-
1451
- //Data Source Related Functions
1452
- private getSubDS(): DataSource[] {
1453
- const levelKeys: string[] = this.curDSLevel;
1454
- if (levelKeys.length) {
1455
- let ds: DataSource[] = <DataSource[]>this.localData;
1456
- for (const key of levelKeys) {
1457
- const field: DataSource = {};
1458
- // eslint-disable-next-line
1459
- field[this.fields.id] = key as any;
1460
- this.curDSJSON = <DataSource[] & DataSource>this.findItemFromDS(ds, field);
1461
- const fieldData: DataSource = <DataSource>getFieldValues
1462
- // eslint-disable-next-line no-unexpected-multiline
1463
- (this.curDSJSON as { [key: string]: Object }, this.listBaseOption.fields);
1464
- ds = this.curDSJSON ? <DataSource[] & DataSource>fieldData[this.fields.child] : ds;
1465
- }
1466
- return ds;
1467
- }
1468
- return <DataSource[]>this.localData;
1469
- }
1470
-
1471
- private getItemData(li: Element | HTMLElement | Fields): DataSource {
1472
- const dataSource: DataSource[] | string[] | number[] | DataManager = this.dataSource instanceof DataManager ?
1473
- this.localData : this.dataSource;
1474
- const fields: Fields = this.getElementUID(li);
1475
- let curDS: DataSource[];
1476
- if (isNullOrUndefined(this.element.querySelector('.' + classNames.hasChild)) && this.fields.groupBy) {
1477
- curDS = <DataSource[]>this.curViewDS;
1478
- } else {
1479
- curDS = <DataSource[]>dataSource;
1480
- }
1481
-
1482
- return <DataSource>this.findItemFromDS(curDS, <DataSource>fields);
1483
- }
1484
-
1485
- private findItemFromDS(
1486
- dataSource: DataSource[],
1487
- fields: DataSource,
1488
- parent?: boolean): DataSource[] | DataSource {
1489
-
1490
- let resultJSON: DataSource[] | DataSource;
1491
-
1492
- if (dataSource && dataSource.length && fields) {
1493
- dataSource.some((data: DataSource) => {
1494
- const fieldData: DataSource =
1495
- // eslint-disable-next-line
1496
- <DataSource>getFieldValues(data as { [key: string]: Object } as any, this.listBaseOption.fields);
1497
- //(!(fid) || id === fid) && (!(ftext) || text === ftext) && (!!fid || !!ftext)
1498
- if ((fields[this.fields.id] || fields[this.fields.text]) &&
1499
- (!fields[this.fields.id] || (!isNullOrUndefined(fieldData[this.fields.id]) &&
1500
- fieldData[this.fields.id].toString()) === fields[this.fields.id].toString()) &&
1501
- (!fields[this.fields.text] || fieldData[this.fields.text] === fields[this.fields.text])) {
1502
- resultJSON = (parent ? <DataSource[] | DataSource>dataSource : data);
1503
- } else if (typeof data !== 'object' && dataSource.indexOf(data) !== -1) {
1504
- resultJSON = (parent ? <DataSource[] | DataSource>dataSource : data);
1505
- } else if (!isNullOrUndefined(fields[this.fields.id]) && isNullOrUndefined(fieldData[this.fields.id])) {
1506
- const li: Element = this.element.querySelector('[data-uid="'
1507
- + fields[this.fields.id] + '"]');
1508
- // eslint-disable-next-line
1509
- if (li && (li as HTMLElement).innerText.trim() === fieldData[this.fields.text]as any) {
1510
- resultJSON = data;
1511
- }
1512
- // eslint-disable-next-line
1513
- } else if ((fieldData as object).hasOwnProperty(this.fields.child) && (fieldData[this.fields.child] as object[]).length) {
1514
- resultJSON = <DataSource & DataSource[]>this.findItemFromDS(
1515
- <DataSource[]>fieldData[this.fields.child], fields, parent);
1516
- }
1517
- return !!resultJSON;
1518
- });
1519
- } else {
1520
- resultJSON = <DataSource[] & DataSource>dataSource;
1521
- }
1522
-
1523
- return <DataSource[] & DataSource>resultJSON;
1524
- }
1525
-
1526
- private getQuery(): Query {
1527
- const columns: string[] = [];
1528
- const query: Query = (this.query ? this.query : new Query());
1529
- if (!this.query) {
1530
- // eslint-disable-next-line
1531
- for (const column of Object.keys((this.fields as any & { properties: object }).properties)) {
1532
- if (column !== 'tableName' && !!((this.fields as DataSource)[column]) &&
1533
- (this.fields as DataSource)[column] !==
1534
- (ListBase.defaultMappedFields as DataSource)[column]
1535
- && columns.indexOf((this.fields as { [key: string]: string })[column]) === -1) {
1536
-
1537
- columns.push((this.fields as { [key: string]: string })[column]);
1538
-
1539
- }
1540
- }
1541
- query.select(columns);
1542
- // eslint-disable-next-line
1543
- if ((this.fields as any & { properties: object }).properties.hasOwnProperty('tableName')) {
1544
- query.from(this.fields.tableName);
1545
- }
1546
- }
1547
-
1548
- return query;
1549
- }
1550
-
1551
- private setViewDataSource(dataSource: DataSource[] = <DataSource[]>this.localData): void {
1552
- if (dataSource && this.fields.groupBy) {
1553
- if (this.sortOrder !== 'None') {
1554
- this.curViewDS = ListBase.groupDataSource(
1555
- ListBase.getDataSource(dataSource, ListBase.addSorting(this.sortOrder, (isNullOrUndefined(this.fields.sortBy)) ? this.fields.text : this.fields.sortBy)),
1556
- this.listBaseOption.fields, this.sortOrder);
1557
- } else {
1558
- this.curViewDS = ListBase.groupDataSource(dataSource, this.listBaseOption.fields, this.sortOrder);
1559
- }
1560
- } else if (dataSource && this.sortOrder !== 'None') {
1561
- this.curViewDS = ListBase.getDataSource(dataSource, ListBase.addSorting(this.sortOrder, (isNullOrUndefined(this.fields.sortBy)) ? this.fields.text : this.fields.sortBy));
1562
- } else {
1563
- this.curViewDS = dataSource;
1564
- }
1565
- }
1566
-
1567
- private isInAnimation(): boolean {
1568
- return this.curUL.classList.contains('.e-animate');
1569
- }
1570
-
1571
- private renderRemoteLists(e: Object, listViewComponent: ListView): void {
1572
- if (this.isDestroyed) { return; }
1573
- this.localData = (e as ResultData).result;
1574
- listViewComponent.removeElement(listViewComponent.contentContainer);
1575
- this.renderList();
1576
- this.trigger('actionComplete', e);
1577
- }
1578
-
1579
- private triggerActionFailure(e: Object): void {
1580
- if (this.isDestroyed) { return; }
1581
- this.trigger('actionFailure', e);
1582
- }
1583
-
1584
- private setLocalData(): void {
1585
- this.trigger('actionBegin');
1586
- // eslint-disable-next-line
1587
- const listViewComponent: ListView = this;
1588
- if (this.dataSource instanceof DataManager) {
1589
- if ((this.dataSource as DataManager).ready) {
1590
- (this.dataSource as DataManager).ready.then((e: Object) => {
1591
- /* eslint-disable */
1592
- this.isOffline = (this.dataSource as DataManager).dataSource.offline;
1593
- if (this.dataSource instanceof DataManager && this.isOffline) {
1594
- this.renderRemoteLists(e, listViewComponent);
1595
- }
1596
- }).catch((e: Object) => {
1597
- this.triggerActionFailure(e);
1598
- });
1599
- } else {
1600
- (this.dataSource as DataManager).executeQuery(this.getQuery()).then((e: object) => {
1601
- this.renderRemoteLists(e, listViewComponent);
1602
- }).catch((e: Object) => {
1603
- this.triggerActionFailure(e);
1604
- });
1605
- }
1606
- } else if (!this.dataSource || !(<DataSource[]>this.dataSource).length) {
1607
- const ul: HTMLElement = <HTMLElement>this.element.querySelector('ul');
1608
- if (ul) {
1609
- remove(ul);
1610
- this.setProperties({ dataSource: ListBase.createJsonFromElement(ul) }, true);
1611
- this.localData = <DataSource[]>this.dataSource;
1612
- this.renderList();
1613
- this.trigger('actionComplete', { data: this.localData });
1614
- }
1615
- } else {
1616
- this.localData = <DataSource[]>this.dataSource;
1617
- this.renderList();
1618
- this.trigger('actionComplete', { data: this.localData });
1619
- }
1620
- }
1621
-
1622
- private reRender(): void {
1623
- this.removeElement(this.headerEle);
1624
- this.removeElement(this.ulElement);
1625
- this.removeElement(this.contentContainer);
1626
- // eslint-disable-next-line
1627
- if ((this as any).isReact) {
1628
- this.clearTemplate();
1629
- }
1630
- if (Object.keys(window).indexOf('ejsInterop') === -1) {
1631
- this.element.innerHTML = '';
1632
- }
1633
- this.headerEle = this.ulElement = this.liCollection = undefined;
1634
- this.header();
1635
- this.setLocalData();
1636
- }
1637
-
1638
- private resetCurrentList(): void {
1639
- this.setViewDataSource(this.curViewDS as DataSource[]);
1640
- this.contentContainer.innerHTML = '';
1641
- this.createList();
1642
- this.renderIntoDom(this.curUL);
1643
- }
1644
-
1645
- private setAttributes(liElements: HTMLElement[]): void {
1646
- for (let i: number = 0; i < liElements.length; i++) {
1647
- const element: HTMLElement = liElements[i];
1648
- if (element.classList.contains('e-list-item')) {
1649
- element.setAttribute('id', this.element.id + '_' + element.getAttribute('data-uid'));
1650
- element.setAttribute('aria-selected', 'false');
1651
- element.setAttribute('tabindex', '-1');
1652
- }
1653
- }
1654
- }
1655
-
1656
- private createList(): void {
1657
- this.currentLiElements = [];
1658
- this.isNestedList = false;
1659
- this.ulElement = this.curUL = ListBase.createList(
1660
- this.createElement, this.curViewDS as DataSource[], this.listBaseOption, null, this);
1661
- this.liCollection = <HTMLElement[] & NodeListOf<Element>>this.curUL.querySelectorAll('.' + classNames.listItem);
1662
- this.setAttributes(this.liCollection);
1663
- }
1664
-
1665
- private exceptionEvent(e: object): void {
1666
- this.trigger('actionFailure', e);
1667
- }
1668
- private UpdateCurrentUL(): void {
1669
- this.ulElement = this.curUL = this.element.querySelector('.' + classNames.parentItem);
1670
- if (this.curUL) {
1671
- // eslint-disable-next-line
1672
- (this as any).liCollection = this.curUL.querySelectorAll('.' + classNames.listItem);
1673
- }
1674
- }
1675
-
1676
- private renderSubList(li: Element): void {
1677
- this.liElement = li;
1678
- const uID: string = li.getAttribute('data-uid');
1679
- if (li.classList.contains(classNames.hasChild) && uID) {
1680
- const ul: Element = closest(li.parentNode, '.' + classNames.parentItem);
1681
- let ele: Element = this.element.querySelector('[pid=\'' + uID + '\']');
1682
- this.curDSLevel.push(uID);
1683
- this.setViewDataSource(this.getSubDS());
1684
- if (!ele) {
1685
- const data: DataSource[] = this.curViewDS as DataSource[];
1686
- ele = ListBase.createListFromJson(this.createElement, data, this.listBaseOption, this.curDSLevel.length, null, this);
1687
- // eslint-disable-next-line
1688
- if ((this as any).isReact) {
1689
- this.renderReactTemplates();
1690
- }
1691
- const lists: HTMLElement[] = <HTMLElement[] & NodeListOf<Element>>ele.querySelectorAll('.' + classNames.listItem);
1692
- this.setAttributes(lists);
1693
- ele.setAttribute('pID', <string>uID);
1694
- (ele as HTMLElement).style.display = 'none';
1695
- this.renderIntoDom(ele);
1696
- }
1697
- this.switchView(<HTMLElement>ul, <HTMLElement>ele);
1698
- this.liCollection = <HTMLElement[] & NodeListOf<Element>>this.curUL.querySelectorAll('.' + classNames.listItem);
1699
- if (this.selectedItems) {
1700
- const fieldData: DataSource = <DataSource>
1701
- getFieldValues(<DataSource | string>this.selectedItems.data, this.listBaseOption.fields);
1702
-
1703
- // eslint-disable-next-line
1704
- this.header((fieldData[this.listBaseOption.fields.text]) as any, true, 'header');
1705
- }
1706
- this.selectedLI = undefined;
1707
- }
1708
- }
1709
-
1710
- private renderIntoDom(ele: Element): void {
1711
- this.contentContainer.appendChild(ele);
1712
- }
1713
-
1714
- private renderList(data?: DataSource[]): void {
1715
- this.setViewDataSource(data);
1716
- if (this.enableVirtualization) {
1717
- if (Object.keys(this.dataSource).length) {
1718
- if ((this.template || this.groupTemplate) && !this.virtualizationModule.isNgTemplate()) {
1719
- if ((this as any).isReact) {
1720
- if (typeof this.template == "string") {
1721
- this.listBaseOption.template = null;
1722
- }
1723
- if (typeof this.groupTemplate == "string") {
1724
- this.listBaseOption.groupTemplate = null;
1725
- }
1726
- } else {
1727
- this.listBaseOption.template = null;
1728
- this.listBaseOption.groupTemplate = null;
1729
- }
1730
- this.listBaseOption.itemCreated = this.virtualizationModule.createUIItem.bind(this.virtualizationModule);
1731
- }
1732
- }
1733
- this.virtualizationModule.uiVirtualization();
1734
- } else {
1735
- this.createList();
1736
- this.contentContainer = this.createElement('div', { className: classNames.content });
1737
- this.element.appendChild(this.contentContainer);
1738
- this.renderIntoDom(this.ulElement);
1739
- // eslint-disable-next-line
1740
- if ((this as any).isReact) {
1741
- this.renderReactTemplates();
1742
- }
1743
- }
1744
- }
1745
-
1746
- private getElementUID(obj: Fields | HTMLElement | Element): Fields {
1747
- let fields: DataSource = {};
1748
- if (obj instanceof Element) {
1749
- // eslint-disable-next-line
1750
- fields[this.fields.id] = obj.getAttribute('data-uid') as any;
1751
- } else {
1752
- fields = <DataSource>obj;
1753
- }
1754
- return fields;
1755
- }
1756
-
1757
- /**
1758
- * Initializes the ListView component rendering.
1759
- */
1760
-
1761
- public render(): void {
1762
- this.element.classList.add(classNames.root);
1763
- attributes(this.element, { role: 'list', tabindex: '0' });
1764
- this.setCSSClass();
1765
- this.setEnableRTL();
1766
- this.setEnable();
1767
- this.setSize();
1768
- this.wireEvents();
1769
- this.header();
1770
- this.setLocalData();
1771
- this.setHTMLAttribute();
1772
- this.rippleFn = rippleEffect(this.element, {
1773
- selector: '.' + classNames.listItem
1774
- });
1775
- this.renderComplete();
1776
- }
1777
-
1778
- /**
1779
- * It is used to destroy the ListView component.
1780
- */
1781
-
1782
- public destroy(): void {
1783
- // eslint-disable-next-line
1784
- if ((this as any).isReact) {
1785
- this.clearTemplate();
1786
- }
1787
- this.unWireEvents();
1788
- const classAr: string[] = [classNames.root, classNames.disable, 'e-rtl',
1789
- 'e-has-header', 'e-lib'].concat(this.cssClass.split(' ').filter((css: string) => css));
1790
- removeClass([this.element], classAr);
1791
- this.element.removeAttribute('role');
1792
- this.element.removeAttribute('tabindex');
1793
- this.curUL = this.ulElement = this.liCollection = this.headerEle = undefined;
1794
- this.element.innerHTML = '';
1795
- super.destroy();
1796
- }
1797
-
1798
- /**
1799
- * Switches back from the navigated sub list item.
1800
- */
1801
-
1802
- public back(): void {
1803
- const pID: string = this.curDSLevel[this.curDSLevel.length - 1];
1804
- if (pID === undefined || this.isInAnimation()) { return; }
1805
- this.curDSLevel.pop();
1806
- this.setViewDataSource(this.getSubDS());
1807
- let toUL: HTMLElement = <HTMLElement>this.element.querySelector('[data-uid=\'' + pID + '\']');
1808
- const fromUL: HTMLElement = this.curUL;
1809
- if (!toUL) {
1810
- this.createList();
1811
- this.renderIntoDom(this.ulElement);
1812
- toUL = this.curUL;
1813
- } else {
1814
- toUL = toUL.parentElement;
1815
- }
1816
- const fieldData: DataSource = <DataSource>getFieldValues(this.curDSJSON, this.listBaseOption.fields);
1817
- // eslint-disable-next-line
1818
- const text: string = fieldData[this.fields.text] as any;
1819
- this.switchView(fromUL, toUL, true);
1820
- this.removeFocus();
1821
- const li: HTMLElement = <HTMLElement>this.element.querySelector('[data-uid=\'' + pID + '\']');
1822
- li.classList.remove(classNames.disable);
1823
- li.classList.add(classNames.focused);
1824
- if (this.showCheckBox && li.querySelector('.' + classNames.checkboxIcon).classList.contains(classNames.checked)) {
1825
- li.setAttribute('aria-selected', 'true');
1826
- } else {
1827
- li.classList.remove(classNames.selected);
1828
- li.setAttribute('aria-selected', 'false');
1829
- }
1830
- this.liCollection = <HTMLElement[] & NodeListOf<Element>>this.curUL.querySelectorAll('.' + classNames.listItem);
1831
- if (this.enableHtmlSanitizer) {
1832
- this.setProperties({ headerTitle: SanitizeHtmlHelper.sanitize(this.headerTitle) }, true);
1833
- }
1834
- this.header((this.curDSLevel.length ? text : this.headerTitle), (this.curDSLevel.length ? true : false), 'header');
1835
- }
1836
-
1837
- /**
1838
- * Selects the list item from the ListView by passing the elements or field object.
1839
- *
1840
- * @param {Fields | HTMLElement | Element} item - We can pass element Object or Fields as Object with ID and Text fields.
1841
- */
1842
-
1843
- public selectItem(item: Fields | HTMLElement | Element): void {
1844
- if (this.enableVirtualization) {
1845
- this.virtualizationModule.selectItem(item);
1846
- } else if (this.showCheckBox) {
1847
- this.setCheckboxLI(this.getLiFromObjOrElement(item));
1848
- } else {
1849
- if (isNullOrUndefined(item) === true)
1850
- {
1851
- this.removeSelect();
1852
- }
1853
- else
1854
- {
1855
- this.setSelectLI(this.getLiFromObjOrElement(item));
1856
- }
1857
-
1858
- }
1859
- }
1860
-
1861
- private getLiFromObjOrElement(obj: Fields | HTMLElement | Element): HTMLElement {
1862
- let li: Element;
1863
- const dataSource: DataSource[] | string[] | number[] | DataManager = this.dataSource instanceof DataManager ?
1864
- this.localData : this.dataSource;
1865
- if (!isNullOrUndefined(obj)) {
1866
- if (typeof (dataSource as string[])[0] === 'string' || typeof (dataSource as number[])[0] === 'number') {
1867
- if (obj instanceof Element) {
1868
- const uid: string = (obj as HTMLElement).getAttribute('data-uid').toString();
1869
- for (let i: number = 0; i < this.liCollection.length; i++) {
1870
- if (this.liCollection[i].getAttribute('data-uid').toString() === uid) {
1871
- li = this.liCollection[i] as HTMLElement;
1872
- break;
1873
- }
1874
- }
1875
- } else {
1876
- Array.prototype.some.call(this.curUL.querySelectorAll('.' + classNames.listItem), (item: HTMLElement) => {
1877
- if (item.innerText.trim() === obj.toString()) {
1878
- li = item;
1879
- return true;
1880
- } else {
1881
- return false;
1882
- }
1883
- });
1884
- }
1885
- } else {
1886
- const resultJSON: DataSource[] | DataSource = this.getItemData(obj);
1887
- const fieldData: DataSource =
1888
- <DataSource>getFieldValues(resultJSON, this.listBaseOption.fields);
1889
- if (resultJSON) {
1890
- li = this.element.querySelector('[data-uid="'
1891
- + (<DataSource>fieldData)[this.fields.id] + '"]');
1892
- if (!this.enableVirtualization && isNullOrUndefined(li)) {
1893
- const curLi: NodeListOf<Element> = this.element.querySelectorAll('.' + classNames.listItem);
1894
- for (let i: number = 0; i < curLi.length; i++) {
1895
- // eslint-disable-next-line
1896
- if ((curLi[i] as HTMLElement).innerText.trim() === fieldData[this.fields.text] as any) {
1897
- li = curLi[i];
1898
- }
1899
- }
1900
- }
1901
- }
1902
- }
1903
- }
1904
- return <HTMLElement>li;
1905
- }
1906
-
1907
- /**
1908
- * Selects multiple list items from the ListView.
1909
- *
1910
- * @param {Fields[] | HTMLElement[] | Element[]} item - We can pass array of
1911
- * elements or array of fields Object with ID and Text fields.
1912
- */
1913
-
1914
- public selectMultipleItems(item: Fields[] | HTMLElement[] | Element[]): void {
1915
- if (!isNullOrUndefined(item)) {
1916
- for (let i: number = 0; i < item.length; i++) {
1917
- if (!isNullOrUndefined(item[i])) {
1918
- this.selectItem(item[i]);
1919
- }
1920
- }
1921
- }
1922
- }
1923
-
1924
- private getParentId(): string[] {
1925
- const parentId: string[] = [];
1926
- if (this.isNestedList) {
1927
- for (let i: number = this.curDSLevel.length - 1; i >= 0; i--) {
1928
- parentId.push(this.curDSLevel[i]);
1929
- }
1930
- }
1931
- return parentId;
1932
- }
1933
-
1934
- /**
1935
- * Gets the details of the currently selected item from the list items.
1936
- *
1937
- */
1938
-
1939
- public getSelectedItems(): SelectedItem | SelectedCollection | UISelectedItem | NestedListData {
1940
- // eslint-disable-next-line
1941
- let finalValue: any;
1942
- let isCompleted: boolean = false;
1943
- this.selectedId = [];
1944
- const dataSource: DataSource[] | string[] | number[] | DataManager = this.dataSource instanceof DataManager ?
1945
- this.localData : this.dataSource;
1946
- if (this.enableVirtualization && !isCompleted) {
1947
- finalValue = this.virtualizationModule.getSelectedItems();
1948
- isCompleted = true;
1949
- } else if (this.showCheckBox && !isCompleted) {
1950
- // eslint-disable-next-line
1951
- const liCollection: any = this.curUL.getElementsByClassName(classNames.selected);
1952
- const liTextCollection: string[] = []; const liDataCollection: DataSource[] = []; this.selectedId = [];
1953
- const dataParent: DataAndParent[] = [];
1954
- for (let i: number = 0; i < liCollection.length; i++) {
1955
- if (typeof (dataSource as string[])[0] === 'string' || typeof (dataSource as number[])[0] === 'number') {
1956
- liTextCollection.push((liCollection[i] as HTMLElement).innerText.trim());
1957
- } else {
1958
- const tempData: DataSource = this.getItemData(liCollection[i] as HTMLElement);
1959
- const fieldData: DataSource =
1960
- <DataSource>getFieldValues(tempData, this.listBaseOption.fields);
1961
- if (this.isNestedList) {
1962
- dataParent.push({ data: tempData, parentId: this.getParentId() });
1963
- } else {
1964
- liDataCollection.push(tempData);
1965
- }
1966
- if (fieldData) {
1967
- // eslint-disable-next-line
1968
- liTextCollection.push(fieldData[this.listBaseOption.fields.text] as any );
1969
- // eslint-disable-next-line
1970
- this.selectedId.push(fieldData[this.listBaseOption.fields.id] as any);
1971
- } else {
1972
- liTextCollection.push(undefined);
1973
- this.selectedId.push(undefined);
1974
- }
1975
- }
1976
- }
1977
- if ((typeof (dataSource as string[])[0] === 'string'
1978
- || typeof (dataSource as number[])[0] === 'number')
1979
- && !isCompleted) {
1980
- finalValue = { item: liCollection, data: dataSource as string[] | number[], text: liTextCollection };
1981
- isCompleted = true;
1982
- }
1983
- if (this.isNestedList && !isCompleted) {
1984
- finalValue = { item: liCollection, data: dataParent, text: liTextCollection };
1985
- isCompleted = true;
1986
- } else if (!isCompleted) {
1987
- finalValue = { item: liCollection, data: liDataCollection, text: liTextCollection };
1988
- isCompleted = true;
1989
- }
1990
- } else if (!isCompleted) {
1991
- const liElement: Element = this.element.getElementsByClassName(classNames.selected)[0];
1992
- const fieldData: DataSource =
1993
- <DataSource>getFieldValues(this.getItemData(liElement), this.listBaseOption.fields);
1994
- if ((typeof (dataSource as string[])[0] === 'string'
1995
- || typeof (dataSource as number[])[0] === 'number')
1996
- && !isCompleted) {
1997
- finalValue = (!isNullOrUndefined(liElement)) ? {
1998
- item: liElement, data: dataSource as string[] | number[],
1999
- text: (liElement as HTMLElement).innerText.trim()
2000
- } : undefined;
2001
- isCompleted = true;
2002
- } else if (!isCompleted) {
2003
- if (isNullOrUndefined(fieldData) || isNullOrUndefined(liElement)) {
2004
- finalValue = undefined;
2005
- isCompleted = true;
2006
- } else {
2007
- // eslint-disable-next-line
2008
- this.selectedId.push(fieldData[this.listBaseOption.fields.id] as any);
2009
- finalValue = {
2010
- text: fieldData[this.listBaseOption.fields.text], item: liElement,
2011
- data: this.getItemData(liElement)
2012
- };
2013
- isCompleted = true;
2014
- }
2015
- }
2016
- }
2017
- return finalValue;
2018
- }
2019
-
2020
- /**
2021
- * Finds out an item details from the current list.
2022
- *
2023
- * @param {Fields | HTMLElement | Element} item - We can pass element Object or Fields as Object with ID and Text fields.
2024
- */
2025
-
2026
- public findItem(item: Fields | HTMLElement | Element): SelectedItem {
2027
- return <SelectedItem & DataSource>this.getItemData(item);
2028
- }
2029
-
2030
- /**
2031
- * Enables the disabled list items by passing the Id and text fields.
2032
- *
2033
- * @param {Fields | HTMLElement | Element} item - We can pass element Object or Fields as Object with ID and Text fields.
2034
- */
2035
-
2036
- public enableItem(item: Fields | HTMLElement | Element): void {
2037
- this.setItemState(item, true);
2038
- if (this.enableVirtualization) {
2039
- this.virtualizationModule.enableItem(item);
2040
- }
2041
- }
2042
-
2043
- /**
2044
- * Disables the list items by passing the Id and text fields.
2045
- *
2046
- * @param {Fields | HTMLElement | Element} item - We can pass element Object or Fields as Object with ID and Text fields.
2047
- */
2048
-
2049
- public disableItem(item: Fields | HTMLElement | Element): void {
2050
- this.setItemState(item, false);
2051
- if (this.enableVirtualization) {
2052
- this.virtualizationModule.disableItem(item);
2053
- }
2054
- }
2055
-
2056
- //A function that used to set state of the list item like enable, disable.
2057
- private setItemState(item: Fields | HTMLElement | Element, isEnable: boolean): void {
2058
- const resultJSON: DataSource = this.getItemData(item);
2059
- const fieldData: DataSource = <DataSource>getFieldValues(resultJSON, this.listBaseOption.fields);
2060
- if (resultJSON) {
2061
- const li: Element = this.element.querySelector('[data-uid="' + fieldData[this.fields.id] + '"]');
2062
- if (isEnable) {
2063
- if (li) { li.classList.remove(classNames.disable); }
2064
- delete resultJSON[this.fields.enabled];
2065
- } else if (!isEnable) {
2066
- if (li) { li.classList.add(classNames.disable); }
2067
- // eslint-disable-next-line
2068
- resultJSON[this.fields.enabled] = false as any ;
2069
- }
2070
- }
2071
- }
2072
-
2073
- /**
2074
- * Shows the hide list item from the ListView.
2075
- *
2076
- * @param {Fields | HTMLElement | Element} item - We can pass element Object or Fields as Object with ID and Text fields.
2077
- */
2078
-
2079
- public showItem(item: Fields | HTMLElement | Element): void {
2080
- this.showHideItem(item, false, '');
2081
- if (this.enableVirtualization) {
2082
- this.virtualizationModule.showItem(item);
2083
- }
2084
- }
2085
-
2086
- /**
2087
- * Hides an list item from the ListView.
2088
- *
2089
- * @param {Fields | HTMLElement | Element} item - We can pass element Object or Fields as Object with ID and Text fields.
2090
- */
2091
-
2092
- public hideItem(item: Fields | HTMLElement | Element): void {
2093
- this.showHideItem(item, true, 'none');
2094
- if (this.enableVirtualization) {
2095
- this.virtualizationModule.hideItem(item);
2096
- }
2097
- }
2098
-
2099
- private showHideItem(obj: Fields | HTMLElement | Element, isHide: boolean, display: string): void {
2100
- const resultJSON: DataSource = this.getItemData(obj);
2101
- const fieldData: DataSource = <DataSource>getFieldValues(resultJSON, this.listBaseOption.fields);
2102
- if (resultJSON) {
2103
- const li: HTMLElement = <HTMLElement>this.element.querySelector('[data-uid="' + fieldData[this.fields.id] + '"]');
2104
- if (li) { li.style.display = display; }
2105
- if (isHide) {
2106
- // eslint-disable-next-line
2107
- resultJSON[this.fields.isVisible] = false as any;
2108
- } else {
2109
- delete resultJSON[this.fields.isVisible];
2110
- }
2111
- }
2112
- }
2113
-
2114
- /**
2115
- * Adds the new list item(s) to the current ListView.
2116
- * To add a new list item(s) in the ListView, we need to pass the `data` as an array of items that need
2117
- * to be added and `fields` as the target item to which we need to add the given item(s) as its children.
2118
- * For example fields: { text: 'Name', tooltip: 'Name', id:'id'}
2119
- *
2120
- * @param {{Object}[]} data - JSON Array Data that need to add.
2121
- *
2122
- * @param {Fields} fields - Target item to add the given data as its children (can be null).
2123
- *
2124
- */
2125
-
2126
- public addItem(data: { [key: string]: Object }[], fields: Fields = undefined): void {
2127
- const dataSource: DataSource[] = this.dataSource instanceof DataManager
2128
- ? this.localData : this.dataSource as DataSource[];
2129
- this.addItemInternally(data, fields, dataSource);
2130
- }
2131
-
2132
- private addItemInternally(data: DataSource[], fields: Fields, dataSource: DataSource[]): void {
2133
- if (data instanceof Array) {
2134
- if (this.enableVirtualization) {
2135
- this.virtualizationModule.addItem(data, fields, dataSource);
2136
- } else {
2137
- const ds: DataSource = <DataSource>this.findItemFromDS(
2138
- <DataSource[]>dataSource, <DataSource>fields);
2139
- let child: DataSource[];
2140
- if (ds) {
2141
- const fieldData: DataSource = <DataSource>getFieldValues(ds, this.listBaseOption.fields);
2142
- child = <DataSource[]>fieldData[this.fields.child];
2143
- if (!child) {
2144
- child = [];
2145
- }
2146
- child = child.concat(data);
2147
- }
2148
- // check for whether target is nested level or top level in list
2149
- if (ds instanceof Array) {
2150
- for (let i: number = 0; i < data.length; i++) {
2151
- dataSource.push(data[i]);
2152
- this.setViewDataSource(dataSource);
2153
- // since it is top level target, get the content container's first child
2154
- // as it is always the top level UL
2155
- const targetUL: HTMLElement = this.contentContainer
2156
- ? <HTMLElement>this.contentContainer.children[0]
2157
- : null;
2158
- // check for whether the list was previously empty or not, if it is
2159
- // proceed to call initial render
2160
- if (this.contentContainer && targetUL) {
2161
- this.addItemIntoDom(data[i], targetUL, this.curViewDS as DataSource[]);
2162
- } else {
2163
- this.reRender();
2164
- }
2165
- }
2166
- this.liCollection = <HTMLElement[] & NodeListOf<Element>>this.curUL.querySelectorAll('.' + classNames.listItem);
2167
- } else {
2168
- // proceed as target item is in nested level, only if it is a valid target ds
2169
- if (ds) {
2170
- ds[this.fields.child] = child;
2171
- this.addItemInNestedList(ds, data);
2172
- }
2173
- }
2174
- }
2175
- }
2176
- }
2177
-
2178
- private addItemInNestedList(targetItemData: DataSource, itemQueue: DataSource[]): void {
2179
- // eslint-disable-next-line
2180
- const targetItemId: string = targetItemData[this.fields.id] as any;
2181
- const targetChildDS: DataSource[] = targetItemData[this.fields.child] as DataSource[];
2182
- const isAlreadyRenderedUL: HTMLElement | null = this.element.querySelector('[pid=\'' + targetItemId + '\']');
2183
- const targetLi: HTMLElement | null = this.element.querySelector('[data-uid=\'' + targetItemId + '\']');
2184
- const targetUL: HTMLElement | null = isAlreadyRenderedUL
2185
- ? isAlreadyRenderedUL
2186
- : targetLi
2187
- ? <HTMLElement>closest(targetLi, 'ul')
2188
- : null;
2189
- const targetDS: DataSource[] = isAlreadyRenderedUL ? targetChildDS : [targetItemData];
2190
- const isTargetEmptyChild: boolean = targetLi ? !targetLi.classList.contains(classNames.hasChild) : false;
2191
- let isRefreshTemplateNeeded: boolean = false;
2192
- // if li element is already rendered, that element needs to be refreshed so that
2193
- // it becomes child viewable due to new child items are added now
2194
- if (isTargetEmptyChild) {
2195
- const targetRefreshedElement: HTMLElement[] = ListBase.createListItemFromJson(
2196
- this.createElement, targetDS, this.listBaseOption, null, null, this);
2197
- this.setAttributes(targetRefreshedElement);
2198
- targetUL.insertBefore(targetRefreshedElement[0], targetLi);
2199
- detach(targetLi);
2200
- isRefreshTemplateNeeded = true;
2201
- }
2202
- // if it is already rendered element, we need to create and append new elements
2203
- if (isAlreadyRenderedUL && itemQueue) {
2204
- for (let i: number = 0; i < itemQueue.length; i++) {
2205
- targetDS.push(itemQueue[i]);
2206
- this.addItemIntoDom(itemQueue[i], targetUL, targetDS);
2207
- }
2208
- isRefreshTemplateNeeded = true;
2209
- }
2210
- }
2211
-
2212
- private addItemIntoDom(currentItem: DataSource, targetUL: HTMLElement, curViewDS: DataSource[]): void {
2213
- const index: number = curViewDS.indexOf(currentItem);
2214
- this.addListItem(currentItem, index, targetUL, curViewDS);
2215
- const curItemDS: DataSource = curViewDS[index - 1];
2216
- if (curItemDS && curItemDS.isHeader && (curItemDS.items as DataSource[]).length === 1) {
2217
- this.addListItem(curItemDS, (index - 1), targetUL, curViewDS);
2218
- }
2219
- }
2220
-
2221
- private addListItem(dataSource: DataSource, index: number, ulElement: HTMLElement, curViewDS: DataSource[]): void {
2222
- let target: HTMLElement = this.getLiFromObjOrElement((curViewDS as DataSource[])[index + 1]) ||
2223
- this.getLiFromObjOrElement((curViewDS as DataSource[])[index + 2]) || null;
2224
- const li: HTMLElement[] = ListBase.createListItemFromJson(this.createElement, [dataSource], this.listBaseOption, null, null, this);
2225
- this.setAttributes(li);
2226
- // eslint-disable-next-line
2227
- if (this.template && (this as any).isReact) {
2228
- this.renderReactTemplates();
2229
- }
2230
- if (this.fields.groupBy && curViewDS[index + 1] && curViewDS[index + 1].isHeader) {
2231
- let targetEle: HTMLElement = this.getLiFromObjOrElement(curViewDS[index - 1]);
2232
- if (targetEle) {
2233
- target = targetEle.nextElementSibling as HTMLElement;
2234
- }
2235
- }
2236
- ulElement.insertBefore(li[0], target);
2237
- }
2238
-
2239
- /**
2240
- * Removes the list item from the data source based on a passed
2241
- * element like fields: { text: 'Name', tooltip: 'Name', id:'id'}
2242
- *
2243
- * @param {Fields | HTMLElement | Element} item - We can pass element Object or Fields as Object with ID and Text fields.
2244
- */
2245
-
2246
- public removeItem(item: Fields | HTMLElement | Element): void {
2247
- const listDataSource: DataSource[] = this.dataSource instanceof DataManager
2248
- ? this.localData : this.dataSource as DataSource[];
2249
- if (this.enableVirtualization) {
2250
- this.virtualizationModule.removeItem(item);
2251
- } else {
2252
- this.removeItemFromList(item, listDataSource);
2253
- }
2254
- }
2255
-
2256
- private removeItemFromList(obj: Fields | Element | HTMLElement, listDataSource: DataSource[]): void {
2257
- const curViewDS: DataSource[] = this.curViewDS as DataSource[];
2258
- const fields: Fields = obj instanceof Element ? this.getElementUID(obj) : obj;
2259
- let dataSource: DataSource[] | DataSource;
2260
- // eslint-disable-next-line prefer-const
2261
- dataSource = this.findItemFromDS(listDataSource, <DataSource>fields, true);
2262
- if (dataSource) {
2263
- let data: DataSource | DataSource[];
2264
- // eslint-disable-next-line prefer-const
2265
- data = this.findItemFromDS(dataSource as DataSource[], <DataSource>fields);
2266
- const index: number = curViewDS.indexOf(data as DataSource);
2267
- const li: HTMLElement = this.getLiFromObjOrElement(obj);
2268
- let groupLi: HTMLElement;
2269
- this.validateNestedView(li);
2270
- if (this.fields.groupBy && this.curViewDS[index - 1] &&
2271
- curViewDS[index - 1].isHeader &&
2272
- (curViewDS[index - 1].items as DataSource[]).length === 1) {
2273
- if (li && (li.previousElementSibling as HTMLElement).classList.contains(classNames.groupListItem) &&
2274
- (isNullOrUndefined(li.nextElementSibling) || (li.nextElementSibling &&
2275
- (li.nextElementSibling as HTMLElement).classList.contains(classNames.groupListItem)))) {
2276
- groupLi = li.previousElementSibling as HTMLElement;
2277
- }
2278
- }
2279
- if (li) {
2280
- detach(li);
2281
- }
2282
- if (groupLi) {
2283
- detach(groupLi);
2284
- }
2285
- // eslint-disable-next-line
2286
- const foundData: any = ((<DataSource[]>dataSource).length - 1) <= 0
2287
- ? this.findParent(
2288
- this.localData,
2289
- this.fields.id,
2290
- // eslint-disable-next-line
2291
- (value: string) => value === (data as DataSource)[this.fields.id] as any,
2292
- null) : null;
2293
- const dsIndex: number = (dataSource as DataSource[]).indexOf(data as DataSource);
2294
- (dataSource as DataSource[]).splice(dsIndex, 1);
2295
- this.setViewDataSource(listDataSource);
2296
- if (foundData
2297
- && foundData.parent
2298
- && Array.isArray(foundData.parent[this.fields.child])
2299
- && foundData.parent[this.fields.child].length <= 0) {
2300
- const parentLi: HTMLElement | null = this.getLiFromObjOrElement(foundData.parent);
2301
- if (parentLi) {
2302
- const li: HTMLElement[] = ListBase.createListItemFromJson(
2303
- this.createElement,
2304
- [foundData.parent],
2305
- this.listBaseOption,
2306
- null,
2307
- null,
2308
- this);
2309
- this.setAttributes(li);
2310
- parentLi.parentElement.insertBefore(li[0], parentLi);
2311
- parentLi.parentElement.removeChild(parentLi);
2312
- }
2313
- }
2314
- if (dataSource.length <= 0) {
2315
- this.back();
2316
- }
2317
- this.liCollection = Array.prototype.slice.call(this.element.querySelectorAll('.' + classNames.listItem));
2318
- }
2319
- }
2320
-
2321
- // validate before removing an element whether the current view is inside target element's child view
2322
- private validateNestedView(li: HTMLElement | null): void {
2323
- const liID: string = li ? li.getAttribute('data-uid').toString().toLowerCase() : null;
2324
- if (liID && this.curDSLevel && this.curDSLevel.length > 0) {
2325
- while (this.curDSLevel.some((id: string) => id.toString().toLowerCase() === liID)) {
2326
- this.back();
2327
- }
2328
- }
2329
- }
2330
-
2331
- /**
2332
- * Removes multiple items from the ListView by passing the array of elements or array of field objects.
2333
- *
2334
- * @param {Fields[] | HTMLElement[] | Element[]} item - We can pass array of elements or array of field Object with ID and Text fields.
2335
- */
2336
-
2337
- public removeMultipleItems(item: HTMLElement[] | Element[] | Fields[]): void {
2338
- if (item.length) {
2339
- for (let i: number = 0; i < item.length; i++) {
2340
- this.removeItem(item[i]);
2341
- }
2342
- }
2343
- }
2344
-
2345
- // eslint-disable-next-line
2346
- private findParent(dataSource: any, id: string, callback: Function, parent: object): object {
2347
- // eslint-disable-next-line no-prototype-builtins
2348
- if (dataSource.hasOwnProperty(id) && callback(dataSource[id]) === true) {
2349
- return extend({}, dataSource);
2350
- }
2351
-
2352
- for (let i: number = 0; i < Object.keys(dataSource).length; i++) {
2353
- if (dataSource[Object.keys(dataSource)[i]]
2354
- && typeof dataSource[Object.keys(dataSource)[i]] === 'object') {
2355
- // eslint-disable-next-line
2356
- const result: any = this.findParent(dataSource[Object.keys(dataSource)[i]], id, callback, dataSource);
2357
- if (result != null) {
2358
- if (!result.parent) { result.parent = parent; }
2359
- return result;
2360
- }
2361
- }
2362
- }
2363
- return null;
2364
- }
2365
-
2366
- // Module Required function
2367
- protected getModuleName(): string {
2368
- return 'listview';
2369
- }
2370
-
2371
- public requiredModules(): ModuleDeclaration[] {
2372
- const modules: ModuleDeclaration[] = [];
2373
- if (this.enableVirtualization) {
2374
- modules.push({ args: [this], member: 'virtualization' });
2375
- }
2376
-
2377
- return modules;
2378
- }
2379
-
2380
-
2381
- /**
2382
- * Get the properties to be maintained in the persisted state.
2383
- */
2384
-
2385
- protected getPersistData(): string {
2386
- return this.addOnPersist(['cssClass', 'enableRtl', 'htmlAttributes',
2387
- 'enable', 'fields', 'animation', 'headerTitle',
2388
- 'sortOrder', 'showIcon', 'height', 'width', 'showCheckBox', 'checkBoxPosition']);
2389
- }
2390
-
2391
- }
2392
-
2393
- interface ResultData {
2394
- result: { [key: string]: object }[];
2395
- }
2396
-
2397
- /** @hidden */
2398
- export interface ClassNames {
2399
- root: string;
2400
- hover: string;
2401
- focused: string;
2402
- selected: string;
2403
- parentItem: string;
2404
- listItem: string;
2405
- hasChild: string;
2406
- view: string;
2407
- header: string;
2408
- text: string;
2409
- headerText: string;
2410
- headerTemplateText: string;
2411
- listItemText: string;
2412
- listIcon: string;
2413
- textContent: string;
2414
- groupListItem: string;
2415
- disable: string;
2416
- content: string;
2417
- backIcon: string;
2418
- icon: string;
2419
- checkboxWrapper: string;
2420
- checkbox: string;
2421
- checked: string;
2422
- checkboxIcon: string;
2423
- checklist: string;
2424
- checkboxRight: string;
2425
- checkboxLeft: string;
2426
- listviewCheckbox: string;
2427
- itemCheckList: string;
2428
- virtualElementContainer: string;
2429
- }
2430
-
2431
- /**
2432
- * An interface that holds list selected item.
2433
- */
2434
- export interface ListSelectedItem {
2435
- /**
2436
- * Specifies the selected item dataSource collection.
2437
- *
2438
- * @isGenericType true
2439
- */
2440
- data?: object[];
2441
- /**
2442
- * Specifies the selected item text collection.
2443
- */
2444
- text?: string[];
2445
- /**
2446
- * Specifies index of the selected element.
2447
- * Available only in virtualization.
2448
- */
2449
- index?: number[];
2450
- /**
2451
- * Specifies the hierarchical parent id collection of the current view.
2452
- * Available only in nested list with checkbox enabled.
2453
- */
2454
- parentId?: string[];
2455
- }
2456
-
2457
- /**
2458
- * An interface that holds selected item.
2459
- */
2460
- export interface SelectedItem {
2461
- /**
2462
- * It denotes the selected item text.
2463
- */
2464
- text: string;
2465
-
2466
- /**
2467
- * It denotes the selected item list element.
2468
- *
2469
- */
2470
- item: HTMLElement | Element;
2471
-
2472
- /**
2473
- * It denotes the selected item dataSource JSON object.
2474
- *
2475
- * @isGenericType true
2476
- */
2477
- data: { [key: string]: Object } | string[] | number[];
2478
-
2479
- }
2480
-
2481
- /**
2482
- * An interface that holds selected collection.
2483
- */
2484
- export interface SelectedCollection {
2485
- /**
2486
- * It denotes the selected item text data or collection.
2487
- */
2488
- text: string | string[];
2489
-
2490
- /**
2491
- * It denotes the selected item list element or element collection.
2492
- */
2493
- item: HTMLElement | Element[] | NodeList;
2494
-
2495
- /**
2496
- * It denotes the selected item dataSource JSON object or object collection.
2497
- *
2498
- * @isGenericType true
2499
- */
2500
- data: { [key: string]: object } | { [key: string]: object }[] | string[] | number[];
2501
- }
2502
-
2503
- /**
2504
- * An interface that holds UI selected item.
2505
- */
2506
- export interface UISelectedItem {
2507
- /**
2508
- * It denotes the selected item text data or collection.
2509
- */
2510
- text: string | number | string[] | number[];
2511
-
2512
- /**
2513
- * It denotes the selected item list element or element collection.
2514
- */
2515
- item?: HTMLElement | Element[] | NodeList;
2516
-
2517
- /**
2518
- * It denotes the selected item dataSource JSON object or object collection.
2519
- *
2520
- * @isGenericType true
2521
- */
2522
- data: { [key: string]: object } | { [key: string]: object }[] | string | number | string[] | number[];
2523
- /**
2524
- * It is used to denote the index of the selected element.
2525
- */
2526
- index?: number | number[];
2527
- /**
2528
- * It is used to check whether the element is checked or not.
2529
- */
2530
- isChecked?: boolean;
2531
- }
2532
-
2533
- /**
2534
- * An interface that holds details of data and parent.
2535
- */
2536
- export interface DataAndParent {
2537
- /**
2538
- * It denotes the selected item dataSource JSON object or object collection.
2539
- *
2540
- * @isGenericType true
2541
- */
2542
- data: { [key: string]: object } | { [key: string]: object }[] | string[];
2543
- /**
2544
- * It denotes the selected item's parent id;
2545
- */
2546
- parentId: string[];
2547
- }
2548
-
2549
- /**
2550
- * An interface that holds nested list data.
2551
- */
2552
- export interface NestedListData {
2553
- /**
2554
- * It denotes the selected item text data or collection.
2555
- */
2556
- text: string | string[];
2557
- /**
2558
- * It denotes the selected item list element or element collection.
2559
- */
2560
- item: HTMLElement | Element[] | NodeList;
2561
- /**
2562
- * It denotes the selected item dataSource JSON object with it's parent id.
2563
- */
2564
- data: DataAndParent[];
2565
- }
2566
-
2567
- /**
2568
- * An interface that holds selected event arguments
2569
- */
2570
- export interface SelectEventArgs extends BaseEventArgs, SelectedItem {
2571
- /**
2572
- * Specifies that event has triggered by user interaction.
2573
- */
2574
- isInteracted: boolean;
2575
- /**
2576
- * Specifies that event argument when event raised by other event.
2577
- */
2578
- event: MouseEvent | KeyboardEvent;
2579
- /**
2580
- * It is used to denote the index of the selected element.
2581
- */
2582
- index: number;
2583
- /**
2584
- * It is used to check whether the element is checked or not.
2585
- */
2586
- isChecked?: boolean;
2587
- }
2588
-
2589
- /**
2590
- * An interface that holds item created event arguments
2591
- */
2592
- export interface ItemCreatedArgs {
2593
- curData: { [key: string]: object };
2594
- dataSource: { [key: string]: object } | string[];
2595
- fields: FieldsMapping;
2596
- item: HTMLElement;
2597
- options: ListBaseOptions;
2598
- text: string;
2599
- }
2600
-
2601
- interface DataSource {
2602
- [key: string]: object;
2603
- }