@syncfusion/ej2-lists 31.1.17 → 31.2.12

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,1362 +0,0 @@
1
- /* eslint-disable no-inner-declarations */
2
- import { extend, merge, isNullOrUndefined, getValue, SanitizeHtmlHelper } from '@syncfusion/ej2-base';
3
- import { attributes, prepend, isVisible, append, addClass } from '@syncfusion/ej2-base';
4
- import { compile } from '@syncfusion/ej2-base';
5
- import { DataManager, Query } from '@syncfusion/ej2-data';
6
-
7
- export let cssClass: ClassList = {
8
- li: 'e-list-item',
9
- ul: 'e-list-parent e-ul',
10
- group: 'e-list-group-item',
11
- icon: 'e-list-icon',
12
- text: 'e-list-text',
13
- check: 'e-list-check',
14
- checked: 'e-checked',
15
- selected: 'e-selected',
16
- expanded: 'e-expanded',
17
- textContent: 'e-text-content',
18
- hasChild: 'e-has-child',
19
- level: 'e-level',
20
- url: 'e-list-url',
21
- collapsible: 'e-icon-collapsible',
22
- disabled: 'e-disabled',
23
- image: 'e-list-img',
24
- iconWrapper: 'e-icon-wrapper',
25
- anchorWrap: 'e-anchor-wrap',
26
- navigable: 'e-navigable'
27
- };
28
-
29
- /**
30
- * An interface that holds item class list
31
- */
32
- export interface ClassList {
33
- li: string;
34
- ul: string;
35
- group: string;
36
- icon: string;
37
- text: string;
38
- check: string;
39
- checked: string;
40
- selected: string;
41
- expanded: string;
42
- textContent: string;
43
- hasChild: string;
44
- level: string;
45
- url: string;
46
- collapsible: string;
47
- disabled: string;
48
- image: string;
49
- iconWrapper: string;
50
- anchorWrap: string;
51
- navigable: string;
52
- }
53
-
54
- /* eslint-disable @typescript-eslint/no-explicit-any */
55
- /* eslint-disable @typescript-eslint/explicit-module-boundary-types */
56
- /**
57
- * Sorting Order
58
- */
59
- export type SortOrder = 'None' | 'Ascending' | 'Descending';
60
-
61
- /**
62
- * Base List Generator
63
- */
64
- // eslint-disable-next-line @typescript-eslint/no-namespace
65
- export namespace ListBase {
66
-
67
- /**
68
- *
69
- * Default mapped fields.
70
- */
71
- export const defaultMappedFields: FieldsMapping = {
72
- id: 'id',
73
- text: 'text',
74
- url: 'url',
75
- value: 'value',
76
- isChecked: 'isChecked',
77
- enabled: 'enabled',
78
- expanded: 'expanded',
79
- selected: 'selected',
80
- iconCss: 'iconCss',
81
- child: 'child',
82
- isVisible: 'isVisible',
83
- hasChildren: 'hasChildren',
84
- tooltip: 'tooltip',
85
- htmlAttributes: 'htmlAttributes',
86
- urlAttributes: 'urlAttributes',
87
- imageAttributes: 'imageAttributes',
88
- imageUrl: 'imageUrl',
89
- groupBy: null,
90
- sortBy: null
91
- };
92
-
93
- const defaultAriaAttributes: AriaAttributesMapping = {
94
- level: 1,
95
- listRole: 'presentation',
96
- itemRole: 'presentation',
97
- groupItemRole: 'group',
98
- itemText: 'list-item',
99
- wrapperRole: 'presentation'
100
- };
101
-
102
- const defaultListBaseOptions: ListBaseOptions = {
103
- showCheckBox: false,
104
- showIcon: false,
105
- enableHtmlSanitizer: false,
106
- expandCollapse: false,
107
- fields: defaultMappedFields,
108
- ariaAttributes: defaultAriaAttributes,
109
- listClass: '',
110
- itemClass: '',
111
- processSubChild: false,
112
- sortOrder: 'None',
113
- template: null,
114
- groupTemplate: null,
115
- headerTemplate: null,
116
- expandIconClass: 'e-icon-collapsible',
117
- moduleName: 'list',
118
- expandIconPosition: 'Right',
119
- itemNavigable: false
120
- };
121
-
122
- /**
123
- * Function helps to created and return the UL Li element based on your data.
124
- *
125
- * @param {createElementParams} createElement - Specifies an array of JSON data.
126
- *
127
- * @param {{Object}[]} dataSource - Specifies an array of JSON data.
128
- *
129
- * @param {ListBaseOptions} [options] - Specifies the list options that need to provide.
130
- *
131
- * @param {boolean} [isSingleLevel] - Specifies the list options that need to provide.
132
- *
133
- * @param {any} [componentInstance] - Specifies the list options that need to provide.
134
- *
135
- * @returns {createElement} createListFromJson - Specifies the list options that need to provide.
136
- */
137
- export function createList(
138
- createElement: createElementParams, dataSource: { [key: string]: Object }[] | string[] | number[],
139
- options?: ListBaseOptions, isSingleLevel?: boolean, componentInstance?: any):
140
- HTMLElement {
141
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
142
- const ariaAttributes: AriaAttributesMapping = extend({}, defaultAriaAttributes, curOpt.ariaAttributes);
143
- const type: string = typeofData(dataSource).typeof as string;
144
- if (type === 'string' || type === 'number') {
145
- return createListFromArray(createElement, <string[] | number[]>dataSource, isSingleLevel, options, componentInstance);
146
- } else {
147
- return createListFromJson(
148
- createElement,
149
- <{ [key: string]: Object }[]>dataSource,
150
- options,
151
- ariaAttributes.level,
152
- isSingleLevel,
153
- componentInstance
154
- );
155
- }
156
- }
157
-
158
- /**
159
- * Function helps to created an element list based on string array input .
160
- *
161
- * @param {createElementParams} createElement - Specifies an array of JSON data.
162
- *
163
- * @param {{Object}[]} dataSource - Specifies an array of JSON data.
164
- *
165
- * @param {boolean} [isSingleLevel] - Specifies the list options that need to provide.
166
- *
167
- * @param {ListBaseOptions} [options] - Specifies the list options that need to provide.
168
- *
169
- * @param {any} [componentInstance] - Specifies the list options that need to provide.
170
- *
171
- * @returns {createElement} generateUL - returns the list options that need to provide.
172
- */
173
- export function createListFromArray(
174
- createElement: createElementParams, dataSource: string[] | number[],
175
- isSingleLevel?: boolean, options?: ListBaseOptions, componentInstance?: any): HTMLElement {
176
- const subChild: HTMLElement[] = createListItemFromArray(createElement, dataSource, isSingleLevel, options, componentInstance);
177
- return generateUL(createElement, subChild, null, options);
178
- }
179
- /**
180
- * Function helps to created an element list based on string array input .
181
- *
182
- * @param {createElementParams} createElement - Specifies an array of JSON data.
183
- *
184
- * @param {{Object}[]} dataSource - Specifies an array of JSON data.
185
- *
186
- * @param {boolean} [isSingleLevel] - Specifies the list options that need to provide.
187
- *
188
- * @param {ListBaseOptions} [options] - Specifies the list options that need to provide.
189
- *
190
- * @param {any} [componentInstance] - Specifies the list options that need to provide.
191
- *
192
- * @returns {HTMLElement[]} subChild - returns the list options that need to provide.
193
- */
194
- export function createListItemFromArray(
195
- createElement: createElementParams, dataSource: string[] | number[],
196
- isSingleLevel?: boolean, options?: ListBaseOptions, componentInstance?: any): HTMLElement[] {
197
- const subChild: HTMLElement[] = [];
198
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
199
- cssClass = getModuleClass(curOpt.moduleName);
200
- const id: string = generateId(); // generate id for drop-down-list option.
201
- for (let i: number = 0; i < dataSource.length; i++) {
202
- if (isNullOrUndefined(dataSource[i as number])) {
203
- continue;
204
- }
205
- let li: HTMLElement;
206
- if (curOpt.itemCreating && typeof curOpt.itemCreating === 'function') {
207
- const curData: object = {
208
- dataSource: dataSource,
209
- curData: dataSource[i as number],
210
- text: dataSource[i as number],
211
- options: curOpt
212
- };
213
- curOpt.itemCreating(curData);
214
- }
215
-
216
- if (isSingleLevel) {
217
- li = generateSingleLevelLI(createElement, dataSource[i as number], undefined, null, null, [], null, id, i, options);
218
- } else {
219
- li = generateLI(createElement, dataSource[i as number], undefined, null, null, options, componentInstance);
220
- }
221
- if (curOpt.itemCreated && typeof curOpt.itemCreated === 'function') {
222
- const curData: Object = {
223
- dataSource: dataSource,
224
- curData: dataSource[i as number],
225
- text: dataSource[i as number],
226
- item: li,
227
- options: curOpt
228
- };
229
- curOpt.itemCreated(curData);
230
- }
231
-
232
- subChild.push(li);
233
- }
234
-
235
- return subChild;
236
- }
237
-
238
- /**
239
- * Function helps to created an element list based on array of JSON input .
240
- *
241
- * @param {createElementParams} createElement - Specifies an array of JSON data.
242
- *
243
- * @param {{Object}[]} dataSource - Specifies an array of JSON data.
244
- *
245
- * @param {ListBaseOptions} [options] - Specifies the list options that need to provide.
246
- *
247
- * @param {number} [level] - Specifies the list options that need to provide.
248
- *
249
- * @param {boolean} [isSingleLevel] - Specifies the list options that need to provide.
250
- *
251
- * @param {any} [componentInstance] - Specifies the list options that need to provide.
252
- *
253
- * @returns {HTMLElement[]} child - returns the list options that need to provide.
254
- */
255
- export function createListItemFromJson(
256
- createElement: createElementParams, dataSource: { [key: string]: Object }[],
257
- options?: ListBaseOptions, level?: number, isSingleLevel?: boolean, componentInstance?: any): HTMLElement[] {
258
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
259
- cssClass = getModuleClass(curOpt.moduleName);
260
- const fields: FieldsMapping = (componentInstance &&
261
- (componentInstance.getModuleName() === 'listview' || componentInstance.getModuleName() === 'multiselect'))
262
- ? curOpt.fields : extend({}, defaultMappedFields, curOpt.fields);
263
- const ariaAttributes: AriaAttributesMapping = extend({}, defaultAriaAttributes, curOpt.ariaAttributes);
264
- let id: string;
265
- let checkboxElement: HTMLElement[] = [];
266
- if (level) {
267
- ariaAttributes.level = level;
268
- }
269
- const child: HTMLElement[] = [];
270
- let li: HTMLElement;
271
- let anchorElement: HTMLElement;
272
- if (dataSource && dataSource.length && !isNullOrUndefined(typeofData(dataSource).item) &&
273
- !Object.prototype.hasOwnProperty.call(typeofData(dataSource).item, fields.id)) {
274
- id = generateId(); // generate id for drop-down-list option.
275
- }
276
- for (let i: number = 0; i < dataSource.length; i++) {
277
- let fieldData: { [key: string]: Object } = <{ [key: string]: Object }>getFieldValues(dataSource[i as number], fields);
278
- if (isNullOrUndefined(dataSource[i as number])) { continue; }
279
- if (curOpt.itemCreating && typeof curOpt.itemCreating === 'function') {
280
- const curData: { [key: string]: object | string } = {
281
- dataSource: dataSource,
282
- curData: dataSource[i as number],
283
- text: fieldData[fields.text],
284
- options: curOpt,
285
- fields: fields
286
- };
287
- curOpt.itemCreating(curData);
288
- }
289
- const curItem: { [key: string]: Object } = dataSource[i as number];
290
- if (curOpt.itemCreating && typeof curOpt.itemCreating === 'function') {
291
- fieldData = <{ [key: string]: Object }>getFieldValues(dataSource[i as number], fields);
292
- }
293
- if (Object.prototype.hasOwnProperty.call(fieldData, fields.id) && !isNullOrUndefined(fieldData[fields.id])) {
294
- id = <string>fieldData[fields.id];
295
- }
296
- const innerEle: HTMLElement[] = [];
297
- if (curOpt.showCheckBox) {
298
- if (curOpt.itemNavigable && (fieldData[fields.url] || fieldData[fields.urlAttributes])) {
299
- checkboxElement.push(createElement('input', { className: cssClass.check, attrs: { type: 'checkbox' } }));
300
- } else {
301
- innerEle.push(createElement('input', { className: cssClass.check, attrs: { type: 'checkbox' } }));
302
- }
303
- }
304
- if (isSingleLevel === true) {
305
- if (curOpt.showIcon && Object.prototype.hasOwnProperty.call(fieldData, fields.iconCss)
306
- && !isNullOrUndefined(fieldData[fields.iconCss])) {
307
- innerEle.push(createElement('span', { className: cssClass.icon + ' ' + <string>fieldData[fields.iconCss] }));
308
- }
309
- li = generateSingleLevelLI(
310
- createElement,
311
- curItem,
312
- fieldData,
313
- fields,
314
- curOpt.itemClass,
315
- innerEle,
316
- (Object.prototype.hasOwnProperty.call(curItem, 'isHeader') &&
317
- (curItem as { isHeader: Object } & { [key: string]: Object }).isHeader) ? true : false,
318
- id,
319
- i, options);
320
- anchorElement = li.querySelector('.' + cssClass.anchorWrap);
321
- if (Object.prototype.hasOwnProperty.call(fieldData, fields.tooltip)) {
322
- let tooltipText: string = <string>fieldData[fields.tooltip];
323
- if (options && options.enableHtmlSanitizer) {
324
- tooltipText = SanitizeHtmlHelper.sanitize(tooltipText);
325
- } else {
326
- let tooltipTextElement: HTMLElement = createElement('span', { innerHTML: tooltipText });
327
- tooltipText = tooltipTextElement.innerText;
328
- tooltipTextElement = null;
329
- }
330
- li.setAttribute('title', tooltipText);
331
- }
332
- if (curOpt.itemNavigable && checkboxElement.length) {
333
- prepend(checkboxElement, li.firstElementChild);
334
- }
335
- } else {
336
- li = generateLI(createElement, curItem, fieldData, fields, curOpt.itemClass, options, componentInstance);
337
- li.classList.add(cssClass.level + '-' + ariaAttributes.level);
338
- li.setAttribute('aria-level', ariaAttributes.level.toString());
339
- if (ariaAttributes.groupItemRole === 'presentation' || ariaAttributes.itemRole === 'presentation') {
340
- li.removeAttribute('aria-level');
341
- }
342
- anchorElement = li.querySelector('.' + cssClass.anchorWrap);
343
- if (Object.prototype.hasOwnProperty.call(fieldData, fields.tooltip)) {
344
- let tooltipText: string = <string>fieldData[fields.tooltip];
345
- if (options && options.enableHtmlSanitizer) {
346
- tooltipText = SanitizeHtmlHelper.sanitize(tooltipText);
347
- } else {
348
- let tooltipTextElement: HTMLElement = createElement('span', { innerHTML: tooltipText });
349
- tooltipText = tooltipTextElement.innerText;
350
- tooltipTextElement = null;
351
- }
352
- li.setAttribute('title', tooltipText);
353
- }
354
- if (Object.prototype.hasOwnProperty.call(fieldData, fields.htmlAttributes) && fieldData[fields.htmlAttributes]) {
355
- const htmlAttributes: { [key: string]: string } = <{ [key: string]: string }>fieldData[fields.htmlAttributes];
356
- // Check if 'class' attribute is present and not an empty string
357
- if ('class' in htmlAttributes && typeof htmlAttributes['class'] === 'string' && htmlAttributes['class'].trim() === '') {
358
- delete htmlAttributes['class'];
359
- }
360
- setAttribute(li, htmlAttributes);
361
- }
362
- if (Object.prototype.hasOwnProperty.call(fieldData, fields.enabled) && fieldData[fields.enabled] === false) {
363
- li.classList.add(cssClass.disabled);
364
- }
365
- if (Object.prototype.hasOwnProperty.call(fieldData, fields.isVisible) && fieldData[fields.isVisible] === false) {
366
- li.style.display = 'none';
367
- }
368
- if (Object.prototype.hasOwnProperty.call(fieldData, fields.imageUrl) && !isNullOrUndefined(fieldData[fields.imageUrl])
369
- && !curOpt.template) {
370
- const attr: { [key: string]: string } = { src: <string>fieldData[fields.imageUrl], alt: !isNullOrUndefined(<string>fieldData.name) ? ('Displaying ' + <string>fieldData.name + ' Image') : 'Displaying Image'};
371
- merge(attr, fieldData[fields.imageAttributes]);
372
- const imageElemnt: HTMLElement = createElement('img', { className: cssClass.image, attrs: attr });
373
- if (anchorElement) {
374
- anchorElement.insertAdjacentElement('afterbegin', imageElemnt);
375
- } else {
376
- prepend([imageElemnt], li.firstElementChild);
377
- }
378
- }
379
- if (curOpt.showIcon && Object.prototype.hasOwnProperty.call(fieldData, fields.iconCss) &&
380
- !isNullOrUndefined(fieldData[fields.iconCss]) && !curOpt.template) {
381
- const iconElement: HTMLElement = createElement('div', { className: cssClass.icon + ' ' + <string>fieldData[fields.iconCss] });
382
- if (anchorElement) {
383
- anchorElement.insertAdjacentElement('afterbegin', iconElement);
384
- } else {
385
- prepend([iconElement], li.firstElementChild);
386
- }
387
- }
388
- if (innerEle.length) {
389
- prepend(innerEle, li.firstElementChild);
390
- }
391
- if (curOpt.itemNavigable && checkboxElement.length) {
392
- prepend(checkboxElement, li.firstElementChild);
393
- }
394
- processSubChild(createElement, fieldData, fields, dataSource, curOpt, li, ariaAttributes.level);
395
- }
396
- if (anchorElement) {
397
- addClass([li], [cssClass.navigable]);
398
- }
399
- if (curOpt.itemCreated && typeof curOpt.itemCreated === 'function') {
400
- const curData: { [key: string]: object | string } = {
401
- dataSource: dataSource,
402
- curData: dataSource[i as number],
403
- text: fieldData[fields.text],
404
- item: li,
405
- options: curOpt,
406
- fields: fields
407
- };
408
- curOpt.itemCreated(curData);
409
- }
410
- checkboxElement = [];
411
- child.push(li);
412
- }
413
- return child;
414
- }
415
-
416
- /**
417
- * Function helps to created an element list based on array of JSON input .
418
- *
419
- * @param {createElementParams} createElement - Specifies an array of JSON data.
420
- *
421
- * @param {{Object}[]} dataSource - Specifies an array of JSON data.
422
- *
423
- * @param {ListBaseOptions} [options] - Specifies the list options that need to provide.
424
- *
425
- * @param {number} [level] - Specifies the list options that need to provide.
426
- *
427
- * @param {boolean} [isSingleLevel] - Specifies the list options that need to provide.
428
- *
429
- * @param {any} [componentInstance] - Specifies the list options that need to provide.
430
- *
431
- * @returns {createElement} generateUL - Specifies the list options that need to provide.
432
- */
433
- export function createListFromJson(
434
- createElement: createElementParams, dataSource: { [key: string]: Object }[],
435
- options?: ListBaseOptions, level?: number, isSingleLevel?: boolean, componentInstance?: any): HTMLElement {
436
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
437
- const li: HTMLElement[] = createListItemFromJson(createElement, dataSource, options, level, isSingleLevel, componentInstance);
438
- return generateUL(createElement, li, curOpt.listClass, options);
439
- }
440
-
441
-
442
- /**
443
- * Return the next or previous visible element.
444
- *
445
- * @param {Element[]|NodeList} elementArray - An element array to find next or previous element.
446
- * @param {Element} element - An element to find next or previous after this element.
447
- * @param {boolean} [isPrevious] - Specify when the need get previous element from array.
448
- * @returns {Element|undefined} The next or previous visible element, or undefined if the element array is empty.
449
- */
450
- export function getSiblingLI(elementArray: Element[] | NodeList, element: Element, isPrevious?: boolean): Element {
451
-
452
- cssClass = getModuleClass(defaultListBaseOptions.moduleName);
453
- if (!elementArray || !elementArray.length) { return void 0; }
454
- let siblingLI: Element;
455
- let liIndex: number;
456
- const liCollections: Element[] = Array.prototype.slice.call(elementArray);
457
- if (element) {
458
- liIndex = indexOf(element, liCollections);
459
- } else {
460
- liIndex = (isPrevious === true ? liCollections.length : -1);
461
- }
462
- siblingLI = liCollections[liIndex + (isPrevious === true ? -1 : 1)];
463
- while (siblingLI && (!isVisible(siblingLI) || siblingLI.classList.contains(cssClass.disabled))) {
464
- liIndex = liIndex + (isPrevious === true ? -1 : 1);
465
- siblingLI = liCollections[liIndex as number];
466
- }
467
- return siblingLI;
468
- }
469
-
470
- /**
471
- * Return the index of the li element
472
- *
473
- * @param {Element} item - An element to find next or previous after this element.
474
- * @param {Element[]} elementArray - An element array to find index of given li.
475
- * @returns {number} - The index of the item in the element array, or undefined if either parameter is false.
476
- */
477
- export function indexOf(item: Element, elementArray: Element[] | NodeList): number {
478
- if (!elementArray || !item) { return void 0; } else {
479
- let liCollections: Element[] = <Element[]>elementArray;
480
- liCollections = Array.prototype.slice.call(elementArray);
481
- return liCollections.indexOf(item);
482
- }
483
- }
484
-
485
-
486
- /**
487
- * Returns the grouped data from given dataSource.
488
- *
489
- * @param {{Object}[]} dataSource - The JSON data which is necessary to process.
490
- * @param {FieldsMapping} fields - Fields that are mapped from the data source.
491
- * @param {SortOrder} [sortOrder='None'] - Specifies final result sort order. Defaults to 'None'.
492
- * @returns {Object[]} - The grouped data.
493
- */
494
- export function groupDataSource(
495
- dataSource: { [key: string]: Object }[],
496
- fields: FieldsMapping,
497
- sortOrder: SortOrder = 'None'): { [key: string]: Object }[] {
498
- const curFields: FieldsMapping = extend({}, defaultMappedFields, fields);
499
- let cusQuery: Query = new Query().group(curFields.groupBy);
500
-
501
- // need to remove once sorting issues fixed in DataManager
502
- cusQuery = addSorting(sortOrder, 'key', cusQuery);
503
-
504
- const ds: { [key: string]: Object }[] = getDataSource(dataSource, cusQuery);
505
- dataSource = [];
506
-
507
- for (let j: number = 0; j < ds.length; j++) {
508
- const itemObj: { [key: string]: Object }[]
509
- = (ds[j as number] as { items: { [key: string]: Object }[] } & { [key: string]: Object }).items;
510
- const grpItem: { [key: string]: Object } = {};
511
- const hdr: string = 'isHeader';
512
- grpItem[curFields.text] = (ds[j as number] as { key: string } & { [key: string]: Object }).key;
513
- grpItem[`${hdr}`] = true;
514
- let newtext: string = curFields.text;
515
- if (newtext === 'id') {
516
- newtext = 'text';
517
- grpItem[`${newtext}`] = ds[j as number].key;
518
- }
519
- grpItem._id = 'group-list-item-' + ((ds[j as number] as { [key: string]: Object }).key ?
520
- (ds[j as number] as { [key: string]: Object }).key.toString().trim() : 'undefined');
521
- grpItem.items = itemObj;
522
- dataSource.push(grpItem);
523
- for (let k: number = 0; k < itemObj.length; k++) {
524
- dataSource.push(itemObj[k as number]);
525
- }
526
- }
527
- return dataSource;
528
- }
529
-
530
- /**
531
- * Returns a sorted query object.
532
- *
533
- * @param {SortOrder} sortOrder - Specifies that sort order.
534
- * @param {string} sortBy - Specifies sortBy fields.
535
- * @param {Query} query - Pass if any existing query.
536
- * @returns {Query} - The updated query object with sorting applied.
537
- */
538
- export function addSorting(sortOrder: SortOrder, sortBy: string, query: Query = new Query()): Query {
539
- if (sortOrder === 'Ascending') {
540
- query.sortBy(sortBy, 'ascending', true);
541
- } else if (sortOrder === 'Descending') {
542
- query.sortBy(sortBy, 'descending', true);
543
- } else {
544
- for (let i: number = 0; i < query.queries.length; i++) {
545
- if (query.queries[i as number].fn === 'onSortBy') {
546
- query.queries.splice(i, 1);
547
- }
548
- }
549
- }
550
- return query;
551
- }
552
-
553
-
554
- /**
555
- * Return an array of JSON Data that processed based on queries.
556
- *
557
- * @param {{Object}[]} dataSource - Specifies local JSON data source.
558
- *
559
- * @param {Query} query - Specifies query that need to process.
560
- *
561
- * @returns {Object[]} - An array of objects representing the retrieved data.
562
- */
563
- export function getDataSource(dataSource: { [key: string]: Object }[], query: Query): { [key: string]: Object }[] {
564
- return <{ [key: string]: Object }[]>new DataManager(<{ [key: string]: Object }[]>dataSource)
565
- .executeLocal(query);
566
- }
567
- /**
568
- * Created JSON data based the UL and LI element
569
- *
570
- * @param {HTMLElement|Element} element - UL element that need to convert as a JSON
571
- * @param {ListBaseOptions} [options] - Specifies ListBase option for fields.
572
- * @returns {Object[]} - An array of objects representing the JSON data.
573
- */
574
- export function createJsonFromElement(
575
- element: HTMLElement | Element, options?: ListBaseOptions): { [key: string]: Object }[] {
576
-
577
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
578
- const fields: FieldsMapping = extend({}, defaultMappedFields, curOpt.fields);
579
- const curEle: HTMLElement = <HTMLElement>element.cloneNode(true);
580
- const jsonAr: { [key: string]: {} }[] = [];
581
-
582
- curEle.classList.add('json-parent');
583
- const childs: HTMLElement[] = <HTMLElement[] & NodeListOf<HTMLElement>>curEle.querySelectorAll('.json-parent>li');
584
- curEle.classList.remove('json-parent');
585
-
586
- for (let i: number = 0; i < childs.length; i++) {
587
- const li: HTMLElement = childs[i as number];
588
- const anchor: HTMLElement = li.querySelector('a');
589
- const ul: Element = li.querySelector('ul');
590
- const json: { [key: string]: {} } = {};
591
- const childNodes: NodeList = anchor ? anchor.childNodes : li.childNodes;
592
- const keys: string[] = Object.keys(childNodes);
593
- for (let i: number = 0; i < childNodes.length; i++) {
594
- if (!(childNodes[Number(keys[i as number])]).hasChildNodes()) {
595
- json[fields.text] = childNodes[Number(keys[i as number])].textContent;
596
- }
597
- }
598
- let attributes: { [key: string]: string } = getAllAttributes(li);
599
- if (attributes.id) {
600
- json[fields.id] = attributes.id;
601
- delete attributes.id;
602
- } else {
603
- json[fields.id] = generateId();
604
- }
605
- if (Object.keys(attributes).length) {
606
- json[fields.htmlAttributes] = attributes;
607
- }
608
- if (anchor) {
609
- attributes = getAllAttributes(anchor);
610
- if (Object.keys(attributes).length) {
611
- json[fields.urlAttributes] = attributes;
612
- }
613
- }
614
- if (ul) {
615
- json[fields.child] = createJsonFromElement(ul, options);
616
- }
617
- jsonAr.push(json);
618
- }
619
-
620
- return jsonAr;
621
-
622
- }
623
- /**
624
- * Determines the type of data in an array of objects, strings, or numbers.
625
- *
626
- * @param {Object[] | string[] | number[]} data - The array containing objects, strings, or numbers.
627
- * @returns {{typeof: (string | null), item: (Object | string | number)}} - An object containing the type of data and the corresponding item.
628
- */
629
- function typeofData(data: { [key: string]: Object }[] | string[] | number[]): { [key: string]: Object } {
630
- let match: { [key: string]: Object } = <{ [key: string]: Object }>{ typeof: null, item: null };
631
- for (let i: number = 0; i < data.length; i++) {
632
- if (!isNullOrUndefined(data[i as number])) {
633
- return match = { typeof: typeof data[i as number], item: data[i as number] };
634
- }
635
- }
636
- return match;
637
- }
638
- /**
639
- * Sets attributes on an HTML element.
640
- *
641
- * @param {HTMLElement} element - The HTML element to set attributes on.
642
- * @param {Object.<string, string>} elementAttributes - An object containing attribute names and their corresponding values.
643
- * @returns {void}
644
- */
645
- function setAttribute(element: HTMLElement, elementAttributes: { [key: string]: string }): void {
646
- const attr: { [key: string]: string } = {};
647
- merge(attr, elementAttributes);
648
- if (attr.class) {
649
- addClass([element], attr.class.split(' '));
650
- delete attr.class;
651
- }
652
- attributes(element, attr);
653
- }
654
- /**
655
- * Retrieves all attributes of an HTML element.
656
- *
657
- * @param {HTMLElement} element - The HTML element to retrieve attributes from.
658
- * @returns {Object.<string, string>} - An object containing attribute names as keys and their corresponding values as values.
659
- */
660
- function getAllAttributes(element: HTMLElement): { [key: string]: string } {
661
- const attributes: { [key: string]: string } = {};
662
- const attr: NamedNodeMap = element.attributes;
663
- for (let index: number = 0; index < attr.length; index++) {
664
- attributes[attr[index as number].nodeName] = attr[index as number].nodeValue;
665
- }
666
- return attributes;
667
- }
668
-
669
-
670
- /**
671
- * Created UL element from content template.
672
- *
673
- * @param {createElementParams} createElement - Specifies an array of JSON data.
674
- * @param {string} template - that need to convert and generate li element.
675
- * @param {{Object}[]} dataSource - Specifies local JSON data source.
676
- * @param {FieldsMapping} [fields] - Specifies fields for mapping the dataSource.
677
- * @param {ListBaseOptions} [options] - Specifies ListBase option for fields.
678
- * @param {any} [componentInstance] - Specifies component instance.
679
- * @returns {HTMLElement} - The generated LI element.
680
- */
681
- export function renderContentTemplate(
682
- createElement: createElementParams, template: string | Function, dataSource: { [key: string]: Object }[] | string[] | number[],
683
- fields?: FieldsMapping, options?: ListBaseOptions, componentInstance?: any): HTMLElement {
684
- cssClass = getModuleClass(defaultListBaseOptions.moduleName);
685
- const ulElement: HTMLElement = createElement('ul', { className: cssClass.ul, attrs: { role: 'presentation' } });
686
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
687
- const curFields: FieldsMapping = extend({}, defaultMappedFields, fields);
688
- const compiledString: Function = compileTemplate(template);
689
- const liCollection: HTMLElement[] = [];
690
- let value: string;
691
- const id: string = generateId(); // generate id for drop-down-list option.
692
- for (let i: number = 0; i < dataSource.length; i++) {
693
- let fieldData: { [key: string]: Object } = <{ [key: string]: Object }>getFieldValues(dataSource[i as number], curFields);
694
- const curItem: { [key: string]: Object } | string | number = dataSource[i as number];
695
- const isHeader: Object = (curItem as { isHeader: Object } & { [key: string]: Object }).isHeader;
696
- if (typeof dataSource[i as number] === 'string' || typeof dataSource[i as number] === 'number') {
697
- value = curItem as string;
698
- } else {
699
- value = fieldData[curFields.value] as string;
700
- }
701
- if (curOpt.itemCreating && typeof curOpt.itemCreating === 'function') {
702
- const curData: object = {
703
- dataSource: dataSource,
704
- curData: curItem,
705
- text: value,
706
- options: curOpt,
707
- fields: curFields
708
- };
709
- curOpt.itemCreating(curData);
710
- }
711
- if (curOpt.itemCreating && typeof curOpt.itemCreating === 'function') {
712
- fieldData = <{ [key: string]: Object }>getFieldValues(dataSource[i as number], curFields);
713
- if (typeof dataSource[i as number] === 'string' || typeof dataSource[i as number] === 'number') {
714
- value = curItem as string;
715
- } else {
716
- value = fieldData[curFields.value] as string;
717
- }
718
- }
719
- const li: HTMLElement = createElement('li', {
720
- id: id + '-' + i,
721
- className: isHeader ? cssClass.group : cssClass.li, attrs: { role: 'presentation' }
722
- });
723
- if (isHeader) {
724
- if (typeof dataSource[i as number] === 'string' || typeof dataSource[i as number] === 'number') {
725
- li.innerText = curItem as string;
726
- } else {
727
- li.innerText = fieldData[curFields.text] as string;
728
- }
729
- } else {
730
- const currentID: string = isHeader ? curOpt.groupTemplateID : curOpt.templateID;
731
- if (isHeader) {
732
- if (componentInstance && componentInstance.getModuleName() !== 'listview') {
733
- const compiledElement: HTMLElement[] = compiledString(
734
- curItem,
735
- componentInstance,
736
- 'headerTemplate',
737
- currentID,
738
- !!curOpt.isStringTemplate,
739
- null,
740
- li);
741
- if (compiledElement) {
742
- append(compiledElement, li);
743
- }
744
- } else {
745
- append(compiledString(curItem, componentInstance, 'headerTemplate', currentID, !!curOpt.isStringTemplate), li);
746
- }
747
- } else {
748
- if (componentInstance && componentInstance.getModuleName() !== 'listview') {
749
- const compiledElement: HTMLElement[] = compiledString(
750
- curItem,
751
- componentInstance,
752
- 'template',
753
- currentID,
754
- !!curOpt.isStringTemplate,
755
- null,
756
- li);
757
- if (compiledElement) {
758
- append(compiledElement, li);
759
- }
760
- } else {
761
- append(compiledString(curItem, componentInstance, 'template', currentID, !!curOpt.isStringTemplate), li);
762
- }
763
- }
764
- li.setAttribute('data-value', isNullOrUndefined(value) ? 'null' : value);
765
- li.setAttribute('role', 'option');
766
- }
767
- if (curOpt.itemCreated && typeof curOpt.itemCreated === 'function') {
768
- const curData: Object = {
769
- dataSource: dataSource,
770
- curData: curItem,
771
- text: value,
772
- item: li,
773
- options: curOpt,
774
- fields: curFields
775
- };
776
- curOpt.itemCreated(curData);
777
- }
778
- liCollection.push(li);
779
- }
780
- append(liCollection, ulElement);
781
- return ulElement;
782
- }
783
- /**
784
- * Created header items from group template.
785
- *
786
- * @param {string | Function} groupTemplate - that need to convert and generate li element.
787
- *
788
- * @param {{Object}[]} groupDataSource - Specifies local JSON data source.
789
- *
790
- * @param {FieldsMapping} fields - Specifies fields for mapping the dataSource.
791
- *
792
- * @param {Element[]} headerItems - Specifies ListBase header items.
793
- *
794
- * @param {ListBaseOptions} [options] - Optional ListBase options.
795
- *
796
- * @param {*} [componentInstance] - Optional component instance.
797
- *
798
- * @returns {Element[]} - An array of header elements with the rendered group template content.
799
- */
800
- export function renderGroupTemplate(
801
- groupTemplate: string | Function,
802
- // tslint:disable-next-line
803
- groupDataSource: { [key: string]: Object }[],
804
- fields: FieldsMapping,
805
- headerItems: Element[], options?: ListBaseOptions, componentInstance?: any): Element[] {
806
- const compiledString: Function = compileTemplate(groupTemplate);
807
- const curFields: FieldsMapping = extend({}, defaultMappedFields, fields);
808
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
809
- const category: string = curFields.groupBy;
810
- for (const header of headerItems) {
811
- const headerData: { [key: string]: string; } = {};
812
- headerData[`${category}`] = header.textContent;
813
- header.innerHTML = '';
814
- if (componentInstance && componentInstance.getModuleName() !== 'listview') {
815
- const compiledElement: HTMLElement[] = compiledString(
816
- headerData,
817
- componentInstance,
818
- 'groupTemplate',
819
- curOpt.groupTemplateID,
820
- !!curOpt.isStringTemplate, null, header);
821
- if (compiledElement) {
822
- append(compiledElement, header);
823
- }
824
- } else {
825
- append(compiledString(headerData, componentInstance, 'groupTemplate', curOpt.groupTemplateID, !!curOpt.isStringTemplate), header);
826
- }
827
- }
828
- return headerItems;
829
- }
830
- /**
831
- * Generates a random hexadecimal ID string.
832
- *
833
- * @returns {string} - The generated ID string.
834
- */
835
- export function generateId(): string {
836
- return Math.floor((1 + Math.random()) * 0x10000)
837
- .toString(16)
838
- .substring(1);
839
- }
840
- /**
841
- * Processes the sub-child elements and creates corresponding elements based on the provided field data and options.
842
- *
843
- * @param {Function} createElement - Function for creating elements.
844
- * @param {Object} fieldData - Field data containing sub-child information.
845
- * @param {FieldsMapping} fields - Field mappings.
846
- * @param {Object[]} ds - The data source array containing sub-child elements.
847
- * @param {ListBaseOptions} options - ListBase options.
848
- * @param {HTMLElement} element - The parent HTML element to append sub-child elements to.
849
- * @param {number} level - The level of the sub-child elements.
850
- * @returns {void}
851
- */
852
- function processSubChild(
853
- createElement: createElementParams, fieldData: { [key: string]: Object }, fields: FieldsMapping, ds: { [key: string]: Object }[],
854
- options: ListBaseOptions, element: HTMLElement, level: number): void {
855
- // Get SubList
856
- const subDS: { [key: string]: Object }[] = <{ [key: string]: Object }[]>fieldData[fields.child] || [];
857
- let hasChildren: boolean = <boolean>fieldData[fields.hasChildren];
858
- //Create Sub child
859
- if (subDS.length) {
860
- hasChildren = true;
861
- element.classList.add(cssClass.hasChild);
862
- if (options.processSubChild) {
863
- const subLi: HTMLElement = <HTMLElement>createListFromJson(createElement, subDS, options, ++level);
864
- element.appendChild(subLi);
865
- }
866
- }
867
-
868
- // Create expand and collapse node
869
- if (!!options.expandCollapse && hasChildren && !options.template) {
870
- element.firstElementChild.classList.add(cssClass.iconWrapper);
871
- const expandElement: Function = options.expandIconPosition === 'Left' ? prepend : append;
872
- expandElement(
873
- [createElement('div', { className: 'e-icons ' + options.expandIconClass })],
874
- element.querySelector('.' + cssClass.textContent));
875
- }
876
- }
877
- /**
878
- * Generates a single-level LI (list item) element based on the provided item and field data.
879
- *
880
- * @param {Function} createElement - Function for creating elements.
881
- * @param {string | Object | number} item - The item data.
882
- * @param {Object} fieldData - Field data mapped from the item.
883
- * @param {FieldsMapping} [fields] - Field mappings.
884
- * @param {string} [className] - Optional class name to add to the created LI element.
885
- * @param {HTMLElement[]} [innerElements] - Optional array of inner elements to append to the LI element.
886
- * @param {boolean} [grpLI] - Indicates if the LI element is a group item.
887
- * @param {string} [id] - The ID of the LI element.
888
- * @param {number} [index] - The index of the LI element.
889
- * @param {ListBaseOptions} [options] - Optional ListBase options.
890
- * @returns {HTMLElement} - The generated LI element.
891
- */
892
- function generateSingleLevelLI(
893
- createElement: createElementParams, item: string | { [key: string]: Object } | number,
894
- fieldData: { [key: string]: Object }, fields?: FieldsMapping, className?: string, innerElements?: HTMLElement[],
895
- grpLI?: boolean, id?: string, index?: number, options?: ListBaseOptions):
896
- HTMLElement {
897
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
898
- const ariaAttributes: AriaAttributesMapping = extend({}, defaultAriaAttributes, curOpt.ariaAttributes);
899
- let text: string = <string>item;
900
- let value: string = <string>item;
901
- let dataSource: { [key: string]: string } | { [key: string]: object };
902
- if (typeof item !== 'string' && typeof item !== 'number' && typeof item !== 'boolean') {
903
- dataSource = <{ [key: string]: Object }>item;
904
- text = (typeof fieldData[fields.text] === 'boolean' || typeof fieldData[fields.text] === 'number') ?
905
- <string>fieldData[fields.text] : (<string>fieldData[fields.text] || '');
906
- value = <string>fieldData[fields.value];
907
- }
908
- let elementID: string;
909
- if (!isNullOrUndefined(dataSource) && !isNullOrUndefined(fieldData[fields.id])
910
- && fieldData[fields.id] !== '') {
911
- elementID = id;
912
- } else {
913
- elementID = id + '-' + index;
914
- }
915
- const li: HTMLElement = createElement('li', {
916
- className: (grpLI === true ? cssClass.group : cssClass.li) + ' ' + (isNullOrUndefined(className) ? '' : className),
917
- id: elementID, attrs: (ariaAttributes.groupItemRole !== '' && ariaAttributes.itemRole !== '' ?
918
- { role: (grpLI === true ? ariaAttributes.groupItemRole : ariaAttributes.itemRole) } : {})
919
- });
920
- if (dataSource && Object.prototype.hasOwnProperty.call(fieldData, fields.enabled) && fieldData[fields.enabled].toString() === 'false') {
921
- li.classList.add(cssClass.disabled);
922
- }
923
- if (options && options.enableHtmlSanitizer) {
924
- text = SanitizeHtmlHelper.sanitize(text);
925
- }
926
- if (grpLI) {
927
- li.innerText = text;
928
- } else {
929
- li.setAttribute('data-value', isNullOrUndefined(value) ? 'null' : value);
930
-
931
- li.setAttribute('role', 'option');
932
- if (dataSource && Object.prototype.hasOwnProperty.call(fieldData, fields.htmlAttributes) && fieldData[fields.htmlAttributes]) {
933
- setAttribute(li, <{ [key: string]: string }>fieldData[fields.htmlAttributes]);
934
- }
935
-
936
- if (innerElements.length && !curOpt.itemNavigable) { append(innerElements, li); }
937
-
938
- if (dataSource && (fieldData[fields.url] || (fieldData[fields.urlAttributes] &&
939
- (fieldData[fields.urlAttributes] as { [key: string]: Object }).href))) {
940
- li.appendChild(anchorTag(createElement, dataSource, fields, text, innerElements, curOpt.itemNavigable));
941
- } else {
942
- if (innerElements.length && curOpt.itemNavigable) { append(innerElements, li); }
943
- li.appendChild(document.createTextNode(text));
944
- }
945
- }
946
- return li;
947
- }
948
- /**
949
- * Returns a set of CSS class names based on the provided module name.
950
- *
951
- * @param {string} moduleName - The name of the module.
952
- * @returns {ClassList} - The CSS class names associated with the module.
953
- */
954
- function getModuleClass(moduleName: string): ClassList {
955
- let moduleClass: ClassList;
956
- // eslint-disable-next-line
957
- return moduleClass = {
958
- li: `e-${moduleName}-item`,
959
- ul: `e-${moduleName}-parent e-ul`,
960
- group: `e-${moduleName}-group-item`,
961
- icon: `e-${moduleName}-icon`,
962
- text: `e-${moduleName}-text`,
963
- check: `e-${moduleName}-check`,
964
- checked: 'e-checked',
965
- selected: 'e-selected',
966
- expanded: 'e-expanded',
967
- textContent: 'e-text-content',
968
- hasChild: 'e-has-child',
969
- level: 'e-level',
970
- url: `e-${moduleName}-url`,
971
- collapsible: 'e-icon-collapsible',
972
- disabled: 'e-disabled',
973
- image: `e-${moduleName}-img`,
974
- iconWrapper: 'e-icon-wrapper',
975
- anchorWrap: 'e-anchor-wrap',
976
- navigable: 'e-navigable'
977
- };
978
- }
979
- /**
980
- * Creates an anchor tag (<a>) element based on the provided data source, fields, and text.
981
- *
982
- * @param {Function} createElement - Function for creating elements.
983
- * @param {object} dataSource - The data source containing URL-related fields.
984
- * @param {FieldsMapping} fields - Field mappings for the data source.
985
- * @param {string} text - The text content of the anchor tag.
986
- * @param {HTMLElement[]} innerElements - Optional array of inner elements to append to the anchor tag.
987
- * @param {boolean} isFullNavigation - Indicates whether the anchor tag should be for full navigation.
988
- * @returns {HTMLElement} The created anchor tag element.
989
- */
990
- function anchorTag(
991
- createElement: createElementParams, dataSource: { [key: string]: object } | { [key: string]: string },
992
- fields: FieldsMapping, text: string, innerElements: HTMLElement[], isFullNavigation: boolean): HTMLElement {
993
- const fieldData: { [key: string]: Object } = <{ [key: string]: Object }>getFieldValues(dataSource, fields);
994
- const attr: { [key: string]: string } = { href: <string>fieldData[fields.url] };
995
- if (Object.prototype.hasOwnProperty.call(fieldData, fields.urlAttributes) && fieldData[fields.urlAttributes]) {
996
- merge(attr, fieldData[fields.urlAttributes]);
997
- attr.href = <string>fieldData[fields.url] ? <string>fieldData[fields.url] :
998
- (fieldData[fields.urlAttributes] as { [key: string]: Object }).href as string;
999
- }
1000
- let anchorTag: HTMLElement;
1001
- if (!isFullNavigation) {
1002
- anchorTag = createElement('a', { className: cssClass.text + ' ' + cssClass.url, innerHTML: text });
1003
- } else {
1004
- anchorTag = createElement('a', { className: cssClass.text + ' ' + cssClass.url });
1005
- const anchorWrapper: HTMLElement = createElement('div', { className: cssClass.anchorWrap });
1006
- if (innerElements && innerElements.length) {
1007
- append(innerElements, anchorWrapper);
1008
- }
1009
- anchorWrapper.appendChild(document.createTextNode(text));
1010
- append([anchorWrapper], anchorTag);
1011
- }
1012
- setAttribute(anchorTag, attr);
1013
- return anchorTag;
1014
- }
1015
- /**
1016
- * Generates an LI element based on the provided item and field data.
1017
- *
1018
- * @param {Function} createElement - Function for creating elements.
1019
- * @param {string | Object | number} item - The item data.
1020
- * @param {Object} fieldData - Field data mapped from the item.
1021
- * @param {FieldsMapping} fields - Field mappings.
1022
- * @param {string} [className] - Optional class name to add to the created LI element.
1023
- * @param {ListBaseOptions} [options] - Optional ListBase options.
1024
- * @param {*} [componentInstance] - Optional component instance.
1025
- * @returns {HTMLElement} - The generated LI element.
1026
- */
1027
- function generateLI(
1028
- createElement: createElementParams, item: string | { [key: string]: Object } | number, fieldData: { [key: string]: Object },
1029
- fields: FieldsMapping, className?: string, options?: ListBaseOptions, componentInstance?: any): HTMLElement {
1030
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
1031
- const ariaAttributes: AriaAttributesMapping = extend({}, defaultAriaAttributes, curOpt.ariaAttributes);
1032
- let text: string = <string>item;
1033
- let uID: string;
1034
- let grpLI: boolean;
1035
- let dataSource: { [key: string]: string } | { [key: string]: object };
1036
- if (typeof item !== 'string' && typeof item !== 'number') {
1037
- dataSource = <{ [key: string]: Object }>item;
1038
- text = <string>fieldData[fields.text] || '';
1039
- uID = (isNullOrUndefined(<string>fieldData['_id'])) ? <string>fieldData[fields.id] : <string>fieldData['_id'];
1040
- grpLI = (Object.prototype.hasOwnProperty.call(item, 'isHeader') && (item as { isHeader: Object } & { [key: string]: Object }).isHeader)
1041
- ? true : false;
1042
- }
1043
- if (options && options.enableHtmlSanitizer) {
1044
- text = SanitizeHtmlHelper.sanitize(text);
1045
- }
1046
- const li: HTMLElement = createElement('li', {
1047
- className: (grpLI === true ? cssClass.group : cssClass.li) + ' ' + (isNullOrUndefined(className) ? '' : className),
1048
- attrs: (ariaAttributes.groupItemRole !== '' && ariaAttributes.itemRole !== '' ?
1049
- { role: (grpLI === true ? ariaAttributes.groupItemRole : ariaAttributes.itemRole) } : {})
1050
- });
1051
-
1052
- if (!isNullOrUndefined(uID) === true) {
1053
- li.setAttribute('data-uid', uID);
1054
- }
1055
- else {
1056
- li.setAttribute('data-uid', generateId());
1057
- }
1058
- if (grpLI && options && options.groupTemplate) {
1059
- const compiledString: Function = compileTemplate(options.groupTemplate);
1060
- if (componentInstance && componentInstance.getModuleName() !== 'listview') {
1061
- const compiledElement: HTMLElement[] = compiledString(
1062
- item,
1063
- componentInstance,
1064
- 'groupTemplate',
1065
- curOpt.groupTemplateID,
1066
- !!curOpt.isStringTemplate,
1067
- null,
1068
- li);
1069
- if (compiledElement) {
1070
- append(compiledElement, li);
1071
- }
1072
- } else {
1073
- append(compiledString(item, componentInstance, 'groupTemplate', curOpt.groupTemplateID, !!curOpt.isStringTemplate), li);
1074
- }
1075
- } else if (!grpLI && options && options.template) {
1076
- const compiledString: Function = compileTemplate(options.template);
1077
- if (componentInstance && componentInstance.getModuleName() !== 'listview') {
1078
- const compiledElement: HTMLElement[] = compiledString(
1079
- item,
1080
- componentInstance,
1081
- 'template',
1082
- curOpt.templateID,
1083
- !!curOpt.isStringTemplate,
1084
- null,
1085
- li);
1086
- if (compiledElement) {
1087
- append(compiledElement, li);
1088
- }
1089
- } else {
1090
- append(compiledString(item, componentInstance, 'template', curOpt.templateID, !!curOpt.isStringTemplate), li);
1091
- }
1092
- } else {
1093
- const innerDiv: HTMLElement = createElement('div', {
1094
- className: cssClass.textContent,
1095
- attrs: (ariaAttributes.wrapperRole !== '' ? { role: ariaAttributes.wrapperRole } : {})
1096
- });
1097
- if (dataSource && (fieldData[fields.url] || (fieldData[fields.urlAttributes] &&
1098
- (fieldData[fields.urlAttributes] as { [key: string]: Object }).href))) {
1099
- innerDiv.appendChild(anchorTag(createElement, dataSource, fields, text, null, curOpt.itemNavigable));
1100
- } else {
1101
- const element: HTMLElement = createElement('span', {
1102
- className: cssClass.text,
1103
- attrs: (ariaAttributes.itemText !== '' ? { role: ariaAttributes.itemText } : {})
1104
- });
1105
- if (options && options.enableHtmlSanitizer) {
1106
- element.innerText = text;
1107
- } else {
1108
- element.innerHTML = text;
1109
- }
1110
- innerDiv.appendChild(element);
1111
- }
1112
- li.appendChild(innerDiv);
1113
- }
1114
- return li;
1115
- }
1116
-
1117
- /**
1118
- * Returns UL element based on the given LI element.
1119
- *
1120
- * @param {Function} createElement - Function for creating elements.
1121
- *
1122
- * @param {HTMLElement[]} liElement - Specifies array of LI element.
1123
- *
1124
- * @param {string} [className] - Specifies class name that need to be added in UL element.
1125
- *
1126
- * @param {ListBaseOptions} [options] - Specifies ListBase options.
1127
- *
1128
- * @returns {HTMLElement} - The created UL element.
1129
- */
1130
- export function generateUL(
1131
- createElement: createElementParams, liElement: HTMLElement[], className?: string, options?: ListBaseOptions): HTMLElement {
1132
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
1133
- const ariaAttributes: AriaAttributesMapping = extend({}, defaultAriaAttributes, curOpt.ariaAttributes);
1134
- cssClass = getModuleClass(curOpt.moduleName);
1135
- const ulElement: HTMLElement = createElement('ul', {
1136
- className: cssClass.ul + ' ' + (isNullOrUndefined(className) ? '' : className),
1137
- attrs: (ariaAttributes.listRole !== '' ? { role: ariaAttributes.listRole } : {})
1138
- });
1139
-
1140
- append(liElement, ulElement);
1141
-
1142
- return ulElement;
1143
- }
1144
-
1145
- /**
1146
- * Returns LI element with additional DIV tag based on the given LI element.
1147
- *
1148
- * @param {Function} createElement - Function for creating elements.
1149
- *
1150
- * @param {liElement} liElement - Specifies LI element.
1151
- *
1152
- * @param {string} [className] - Specifies class name that need to be added in created DIV element.
1153
- *
1154
- * @param {ListBaseOptions} [options] - Specifies ListBase options.
1155
- *
1156
- * @returns {HTMLElement} - The modified LI element.
1157
- */
1158
- export function generateIcon(
1159
- createElement: createElementParams, liElement: HTMLElement, className?: string, options?: ListBaseOptions): HTMLElement {
1160
- const curOpt: ListBaseOptions = extend({}, defaultListBaseOptions, options);
1161
- cssClass = getModuleClass(curOpt.moduleName);
1162
- const expandElement: Function = curOpt.expandIconPosition === 'Left' ? prepend : append;
1163
- expandElement(
1164
- [createElement('div', {
1165
- className: 'e-icons ' + curOpt.expandIconClass + ' ' +
1166
- (isNullOrUndefined(className) ? '' : className)
1167
- })],
1168
- liElement.querySelector('.' + cssClass.textContent));
1169
-
1170
- return liElement;
1171
- }
1172
-
1173
- }
1174
-
1175
- export type createElementParams = (
1176
- tag: string,
1177
- prop?: { id?: string, className?: string, innerHTML?: string, styles?: string, attrs?: { [key: string]: string } }
1178
- ) => HTMLElement;
1179
-
1180
- /**
1181
- * An interface that holds the field mappings
1182
- */
1183
- export interface FieldsMapping {
1184
- id?: string;
1185
- text?: string;
1186
- value?: string;
1187
- isChecked?: string;
1188
- isVisible?: string;
1189
- url?: string;
1190
- enabled?: string;
1191
- groupBy?: string;
1192
- expanded?: string;
1193
- selected?: string;
1194
- iconCss?: string;
1195
- child?: string;
1196
- tooltip?: string;
1197
- hasChildren?: string;
1198
- htmlAttributes?: string;
1199
- urlAttributes?: string;
1200
- imageUrl?: string;
1201
- imageAttributes?: string;
1202
- sortBy?: string
1203
-
1204
- }
1205
-
1206
- /**
1207
- * An enum type that denotes the Expand Icon Position. Available options are as follows Right, Left;
1208
- */
1209
- export type Position = 'Right' | 'Left';
1210
-
1211
- /**
1212
- * An interface that holds item aria attributes mapping
1213
- */
1214
- export interface AriaAttributesMapping {
1215
- level?: number;
1216
- listRole?: string;
1217
- itemRole?: string;
1218
- groupItemRole?: string;
1219
- itemText?: string;
1220
- wrapperRole?: string;
1221
- }
1222
-
1223
- /**
1224
- * Basic ListBase Options
1225
- */
1226
- export interface ListBaseOptions {
1227
- /**
1228
- * Specifies that fields that mapped in dataSource
1229
- */
1230
- fields?: FieldsMapping;
1231
- /**
1232
- * Specifies the aria attributes
1233
- */
1234
- ariaAttributes?: AriaAttributesMapping;
1235
- /**
1236
- * Specifies to show checkBox
1237
- */
1238
- showCheckBox?: boolean;
1239
- /**
1240
- * Specifies to show icon
1241
- */
1242
- showIcon?: boolean;
1243
- /**
1244
- * Specifies to show collapsible icon
1245
- */
1246
- expandCollapse?: boolean;
1247
- /**
1248
- * Specifies when need to add additional UL list class
1249
- */
1250
- listClass?: string;
1251
- /**
1252
- * Specifies when need to add additional LI item class
1253
- */
1254
- itemClass?: string;
1255
- /**
1256
- * Enables when need process depth child processing.
1257
- */
1258
- processSubChild?: boolean;
1259
- /**
1260
- * Specifies the sort order
1261
- */
1262
- sortOrder?: SortOrder;
1263
- /**
1264
- * Specifies the item template
1265
- */
1266
- template?: string | Function;
1267
- /**
1268
- * Specifies the group header template
1269
- */
1270
- groupTemplate?: string | Function;
1271
- /**
1272
- * Specifies the ListView header template
1273
- */
1274
- headerTemplate?: string | Function;
1275
- /**
1276
- * Specifies the callback function that triggered before each list creation
1277
- */
1278
- itemCreating?: Function;
1279
- /**
1280
- * Specifies the callback function that triggered after each list creation
1281
- */
1282
- itemCreated?: Function;
1283
- /**
1284
- * Specifies the customizable expand icon class
1285
- */
1286
- expandIconClass?: string;
1287
- /**
1288
- * Specifies the customized class name based on their module name
1289
- */
1290
- moduleName?: string;
1291
- /**
1292
- * Specifies the expand/collapse icon position
1293
- */
1294
- expandIconPosition?: Position;
1295
- /**
1296
- * Specifies the template ID
1297
- */
1298
- templateID?: string;
1299
- /**
1300
- * Specifies the groupTemplate ID
1301
- */
1302
- groupTemplateID?: string;
1303
- /**
1304
- * Force template compiler to compile as string template
1305
- */
1306
- isStringTemplate?: string;
1307
- /**
1308
- * Defines whether to allow the cross scripting site or not.
1309
- */
1310
- enableHtmlSanitizer?: boolean;
1311
- /**
1312
- * If set true to this property then the entire list will be navigate-able instead of text element
1313
- */
1314
- itemNavigable?: boolean;
1315
- }
1316
-
1317
- /**
1318
- * Used to get dataSource item from complex data using fields.
1319
- *
1320
- * @param {Object} dataItem - Specifies an JSON or String data.
1321
- *
1322
- * @param {FieldsMapping} fields - Fields that are mapped from the dataSource.
1323
- * @returns {Object|string|number} - The retrieved field values.
1324
- */
1325
- export function getFieldValues(dataItem: { [key: string]: Object } | string | number, fields: FieldsMapping)
1326
- : { [key: string]: Object } | string | number {
1327
- const fieldData: { [key: string]: Object } = {};
1328
- if (isNullOrUndefined(dataItem) || typeof (dataItem) === 'string' || typeof (dataItem) === 'number'
1329
- || !isNullOrUndefined((<{ [key: string]: Object }>dataItem).isHeader)) {
1330
- return dataItem;
1331
- } else {
1332
- for (const field of Object.keys(fields)) {
1333
- const dataField: string = (<{ [key: string]: Object }>fields)[`${field}`] as string;
1334
- const value: { [key: string]: Object } = !isNullOrUndefined(dataField) &&
1335
- typeof (dataField) === 'string' ? getValue(dataField, dataItem) : undefined;
1336
- if (!isNullOrUndefined(value)) {
1337
- fieldData[`${dataField}`] = value;
1338
- }
1339
- }
1340
- }
1341
- return fieldData;
1342
- }
1343
- /**
1344
- * Compiles a template string or function into a compiled function.
1345
- *
1346
- * @param {string | Function} template - The template string or function to compile.
1347
- * @returns {Function | undefined} - The compiled function, or undefined if the input is false.
1348
- */
1349
- function compileTemplate(template: string | Function): Function {
1350
- if (template) {
1351
- try {
1352
- if (typeof template !== 'function' && document.querySelector(template)) {
1353
- return compile(document.querySelector(template).innerHTML.trim());
1354
- } else {
1355
- return compile(template);
1356
- }
1357
- } catch (e) {
1358
- return compile(template);
1359
- }
1360
- }
1361
- return undefined;
1362
- }