|
1 |
|
2 /* tslint:disable */ |
|
3 /* eslint-disable */ |
|
4 (function ($) { |
|
5 class DataAdapter { |
|
6 constructor ( config ) { |
|
7 if ( !config ) { |
|
8 config = {}; |
|
9 } |
|
10 |
|
11 const that = Object.assign( this, config ); |
|
12 |
|
13 const generateKey = function () { |
|
14 const S4 = function () { |
|
15 return ( ( ( 1 + Math.random() ) * 0x10000 ) | 0 ).toString( 16 ).substring( 1 ); |
|
16 }; |
|
17 return S4(); |
|
18 }; |
|
19 |
|
20 that.key = generateKey(); |
|
21 |
|
22 that.boundSource = []; |
|
23 that.dataItemById = []; |
|
24 |
|
25 if ( that.allowAdd === undefined ) { |
|
26 that.allowAdd = true; |
|
27 } |
|
28 |
|
29 if ( that.allowRemove === undefined ) { |
|
30 that.allowRemove = true; |
|
31 } |
|
32 |
|
33 if ( that.allowUpdate === undefined ) { |
|
34 that.allowUpdate = true; |
|
35 } |
|
36 |
|
37 if ( config.observable === undefined ) { |
|
38 that.observable = true; |
|
39 } |
|
40 |
|
41 |
|
42 if ( !config.dataSource ) { |
|
43 that.dataSource = []; |
|
44 } |
|
45 |
|
46 if ( !config.dataFields ) { |
|
47 that.dataFields = []; |
|
48 } |
|
49 else { |
|
50 /* if (config.dataSource && config.dataSource.length > 0) { |
|
51 const keys = Object.keys(config.dataSource[0]); |
|
52 |
|
53 // that.dataFields = []; |
|
54 |
|
55 for (let i = 0; i < keys.length; i++) { |
|
56 |
|
57 } |
|
58 } |
|
59 */ |
|
60 } |
|
61 |
|
62 if ( !config.dataSourceType ) { |
|
63 that.dataSourceType = 'array'; |
|
64 } |
|
65 |
|
66 if ( !config.id ) { |
|
67 that.id = null; |
|
68 } |
|
69 |
|
70 if ( !config.autoFetch ) { |
|
71 that.autoFetch = true; |
|
72 } |
|
73 |
|
74 if ( config.dataFields ) { |
|
75 that.dataFields = config.dataFields; |
|
76 } |
|
77 |
|
78 Object.defineProperty( that, 'groupBy', { |
|
79 configurable: false, |
|
80 enumerable: true, |
|
81 get() { |
|
82 if ( !that._groupBy ) { |
|
83 return []; |
|
84 } |
|
85 |
|
86 return that._groupBy; |
|
87 }, |
|
88 set( value ) { |
|
89 const updateGrouping = () => { |
|
90 that.boundHierarchy = null; |
|
91 that.refreshHierarchy(); |
|
92 |
|
93 if ( that.onGroup ) { |
|
94 that.onGroup(); |
|
95 } |
|
96 } |
|
97 |
|
98 that._groupBy = [].concat(value); |
|
99 |
|
100 if ( that.isInitialized ) { |
|
101 updateGrouping(); |
|
102 } |
|
103 } |
|
104 } ); |
|
105 |
|
106 if ( !config.groupBy ) { |
|
107 that.groupBy = []; |
|
108 } |
|
109 else { |
|
110 if ( config.groupBy.toArray ) { |
|
111 that.groupBy = config.groupBy.toArray(); |
|
112 } |
|
113 else { |
|
114 that.groupBy = config.groupBy; |
|
115 } |
|
116 } |
|
117 |
|
118 if ( config && config.autoBind !== false ) { |
|
119 that.dataBind(); |
|
120 } |
|
121 |
|
122 that.isInitialized = true; |
|
123 } |
|
124 |
|
125 get dataFields() { |
|
126 const that = this; |
|
127 |
|
128 return that._dataFields; |
|
129 } |
|
130 |
|
131 set dataFields( value ) { |
|
132 const that = this; |
|
133 |
|
134 that._dataFields = that._getDataFieldObjects( value ); |
|
135 |
|
136 return that._dataFields; |
|
137 } |
|
138 |
|
139 _getDataFieldObjects( dataFields ) { |
|
140 //const that = this; |
|
141 |
|
142 let dataFieldObjects = []; |
|
143 |
|
144 if ( typeof dataFields === 'number' ) { |
|
145 const charCode = 'A'.charCodeAt( 0 ); |
|
146 let prefix = ''; |
|
147 let index = 0; |
|
148 |
|
149 for ( let i = 0; i < dataFields; i++ ) { |
|
150 const letter = String.fromCharCode( charCode + index ); |
|
151 |
|
152 index++; |
|
153 |
|
154 const label = prefix + letter; |
|
155 |
|
156 dataFieldObjects.push( { name: label, dataType: 'string' } ) |
|
157 |
|
158 if ( index >= 26 ) { |
|
159 index = 0; |
|
160 prefix += 'A'; |
|
161 } |
|
162 } |
|
163 } |
|
164 else if ( dataFields.length > 0 ) { |
|
165 for ( let i = 0; i < dataFields.length; i++ ) { |
|
166 const dataField = dataFields[ i ]; |
|
167 |
|
168 if ( typeof dataField === 'string' ) { |
|
169 const dataFieldParts = dataField.split( ':' ); |
|
170 const name = dataFieldParts[ 0 ].trim(); |
|
171 const dataType = dataFieldParts.length > 1 ? dataFieldParts[ 1 ].trim() : 'string'; |
|
172 |
|
173 dataFieldObjects.push( { name: name, dataType: dataType } ); |
|
174 } |
|
175 else { |
|
176 dataFieldObjects.push( dataField ); |
|
177 } |
|
178 } |
|
179 } |
|
180 |
|
181 return dataFieldObjects; |
|
182 } |
|
183 |
|
184 get dataSource() { |
|
185 const that = this; |
|
186 |
|
187 if ( !that._dataSource ) { |
|
188 that._dataSource = []; |
|
189 } |
|
190 |
|
191 return that._dataSource; |
|
192 } |
|
193 |
|
194 set dataSource( value ) { |
|
195 const that = this; |
|
196 |
|
197 that._dataSource = value; |
|
198 |
|
199 if ( that.isInitialized ) { |
|
200 that.boundSource = false === that.observable ? [] : new JQX.ObservableArray(); |
|
201 that.dataItemById = []; |
|
202 that.bindingCompleted = false; |
|
203 that.dataBind(); |
|
204 } |
|
205 } |
|
206 |
|
207 get canNotify() { |
|
208 const that = this; |
|
209 |
|
210 if ( that._canNotify === undefined ) { |
|
211 that._canNotify = true; |
|
212 } |
|
213 |
|
214 return that._canNotify; |
|
215 } |
|
216 |
|
217 set canNotify( value ) { |
|
218 const that = this; |
|
219 |
|
220 that._canNotify = value; |
|
221 } |
|
222 |
|
223 _notify( changeArgs ) { |
|
224 const that = this; |
|
225 |
|
226 if ( !that.canNotify ) { |
|
227 return; |
|
228 } |
|
229 |
|
230 if ( that.notifyFn ) { |
|
231 that.notifyFn( changeArgs ); |
|
232 } |
|
233 } |
|
234 |
|
235 notify( notifyFn ) { |
|
236 const that = this; |
|
237 |
|
238 if ( notifyFn ) { |
|
239 that.notifyFn = notifyFn; |
|
240 } |
|
241 } |
|
242 |
|
243 toArray() { |
|
244 const that = this; |
|
245 |
|
246 return that.boundSource.toArray(); |
|
247 } |
|
248 |
|
249 dataBind() { |
|
250 const that = this; |
|
251 |
|
252 that.clear(); |
|
253 |
|
254 const completed = () => { |
|
255 |
|
256 |
|
257 that._onBindingComplete(); |
|
258 } |
|
259 |
|
260 if ( typeof that.dataSource === 'string' && ( that.dataSource.indexOf( '.json' ) >= 0 ) ) { |
|
261 that.url = that.dataSource; |
|
262 that.dataSourceType = 'json'; |
|
263 |
|
264 new Ajax( that, ( data/*, status*/ ) => { |
|
265 that.dataSource = data; |
|
266 |
|
267 that._bindToJSON(); |
|
268 } ); |
|
269 } |
|
270 else if ( typeof that.dataSource === 'string' && ( that.dataSource.indexOf( '.xlsx' ) >= 0 ) ) { |
|
271 that.url = that.dataSource; |
|
272 that.dataSourceType = 'xlsx'; |
|
273 |
|
274 new Ajax( that, ( data/*, status*/ ) => { |
|
275 if ( !data[ 0 ] ) { |
|
276 data = []; |
|
277 that._bindToArray(); |
|
278 completed(); |
|
279 return; |
|
280 } |
|
281 |
|
282 const keys = Object.keys( data[ 0 ] ); |
|
283 const dataFieldMap = {}; |
|
284 const dataRows = []; |
|
285 |
|
286 if ( that.exportHeader !== false ) { |
|
287 let index = 0; |
|
288 |
|
289 for ( let key in keys ) { |
|
290 const name = keys[ key ]; |
|
291 |
|
292 dataFieldMap[ name ] = that.dataFields[ index++ ].name; |
|
293 } |
|
294 |
|
295 for ( let i = 1; i < data.length; i++ ) { |
|
296 const row = data[ i ]; |
|
297 const dataRow = {}; |
|
298 |
|
299 for ( let key in keys ) { |
|
300 const name = keys[ key ]; |
|
301 |
|
302 dataRow[ dataFieldMap[ name ] ] = row[ name ]; |
|
303 } |
|
304 |
|
305 dataRows.push( dataRow ); |
|
306 } |
|
307 |
|
308 that.dataSource = dataRows; |
|
309 } |
|
310 |
|
311 that._bindToArray(); |
|
312 completed(); |
|
313 } ); |
|
314 } |
|
315 else if ( typeof that.dataSource === 'string' && ( that.dataSource.indexOf( '.csv' ) >= 0 ) ) { |
|
316 that.dataSourceType = 'csv'; |
|
317 |
|
318 new Ajax( that, (/*data, status*/ ) => { |
|
319 that._bindToArray(); |
|
320 } ); |
|
321 } |
|
322 else if ( typeof that.dataSource === 'string' && ( that.dataSource.indexOf( '.tsv' ) >= 0 ) ) { |
|
323 that.dataSourceType = 'tsv'; |
|
324 |
|
325 new Ajax( that, (/*data, status*/ ) => { |
|
326 } ); |
|
327 } |
|
328 else if ( that.dataSourceType === 'array' ) { |
|
329 that._bindToArray(); |
|
330 completed(); |
|
331 } |
|
332 else if ( that.dataSourceType === 'json' ) { |
|
333 that._bindToJSON(); |
|
334 completed(); |
|
335 } |
|
336 } |
|
337 |
|
338 _onBindingComplete() { |
|
339 const that = this; |
|
340 |
|
341 that._buildHierarchy(); |
|
342 |
|
343 if ( that.onBindingComplete ) { |
|
344 that.onBindingComplete( { data: that.boundSource } ); |
|
345 } |
|
346 |
|
347 if ( that._notify ) { |
|
348 that._notify( { action: 'bindingComplete', data: that.boundSource } ); |
|
349 } |
|
350 |
|
351 that.bindingCompleted = true; |
|
352 } |
|
353 |
|
354 refreshHierarchy() { |
|
355 const that = this; |
|
356 |
|
357 that._buildHierarchy(); |
|
358 } |
|
359 |
|
360 find() { |
|
361 const that = this; |
|
362 |
|
363 return that.boundSource.find.apply( that.boundSource, arguments ); |
|
364 } |
|
365 |
|
366 onVirtualDataSourceRequested( requestCallback, details ) { |
|
367 const that = this; |
|
368 |
|
369 let first = details ? details.first : Infinity; |
|
370 let last = details ? details.last : Infinity; |
|
371 let row = details ? details.row : null; |
|
372 |
|
373 if ( undefined === first ) { |
|
374 first = Infinity; |
|
375 } |
|
376 |
|
377 if ( undefined === last ) { |
|
378 last = Infinity; |
|
379 } |
|
380 |
|
381 that.virtualFirstIndex = first; |
|
382 that.virtualLastIndex = last; |
|
383 |
|
384 if ( that.virtualDataSource ) { |
|
385 const getDataSource = function ( ExcelAdapterSettings ) { |
|
386 if ( ExcelAdapterSettings.virtualDataSourceLength !== undefined ) { |
|
387 that.virtualDataSourceLength = ExcelAdapterSettings.virtualDataSourceLength; |
|
388 } |
|
389 |
|
390 new JQX.ExcelAdapter( |
|
391 { |
|
392 dataSource: ExcelAdapterSettings.dataSource, |
|
393 dataFields: ExcelAdapterSettings.dataFields || that.dataFields, |
|
394 data: details, |
|
395 onBindingComplete( event ) { |
|
396 |
|
397 if ( that.virtualDataSourceOnExpand && row ) { |
|
398 if ( event.data && event.data.length > 0 ) { |
|
399 that.add( event.data, row.$.id ); |
|
400 } |
|
401 else { |
|
402 row.leaf = true; |
|
403 } |
|
404 |
|
405 if ( that.onFilter ) { |
|
406 that.onFilter() |
|
407 } |
|
408 |
|
409 requestCallback(); |
|
410 |
|
411 return; |
|
412 } |
|
413 |
|
414 if ( first === Infinity ) { |
|
415 that.add( event.data ); |
|
416 } |
|
417 else { |
|
418 let items = []; |
|
419 let indexes = []; |
|
420 |
|
421 for ( let i = 0; i < event.data.length; i++ ) { |
|
422 const item = event.data[ i ]; |
|
423 |
|
424 if ( first + i <= last ) { |
|
425 items.push( item ); |
|
426 indexes.push( first + i ); |
|
427 } |
|
428 } |
|
429 |
|
430 that.update( indexes, items ); |
|
431 } |
|
432 |
|
433 |
|
434 if ( that.onFilter ) { |
|
435 that.onFilter() |
|
436 } |
|
437 |
|
438 requestCallback(); |
|
439 } |
|
440 } ); |
|
441 } |
|
442 |
|
443 let hasCache = false; |
|
444 |
|
445 const isEmpty = ( obj ) => Object.entries( obj ).length === 0 && ( obj.constructor === Object || obj.constructor === Array ); |
|
446 const canCache = isEmpty( details.sorting ) && isEmpty( details.filtering ) && isEmpty( details.grouping ) && !details.row && ( details.action !== 'filter' && details.action !== 'sort' && details.action !== 'group' ); |
|
447 |
|
448 if ( that.virtualDataSourceCache && first !== Infinity && canCache ) { |
|
449 let cachedCount = 0; |
|
450 |
|
451 for ( let i = first; i < last; i++ ) { |
|
452 if ( !that[ i ].$.isEmpty ) { |
|
453 cachedCount++; |
|
454 } |
|
455 } |
|
456 |
|
457 if ( cachedCount === last - first ) { |
|
458 hasCache = true; |
|
459 } |
|
460 } |
|
461 |
|
462 if ( hasCache ) { |
|
463 requestCallback(); |
|
464 } |
|
465 else { |
|
466 if ( details.action === 'expand' ) { |
|
467 that.virtualDataSourceOnExpand( getDataSource, { |
|
468 first: first, |
|
469 last: last, |
|
470 row: details.row, |
|
471 sorting: details.sorting, |
|
472 filtering: details.filtering, |
|
473 grouping: details.grouping, |
|
474 action: details.action |
|
475 } ); |
|
476 } |
|
477 else { |
|
478 that.virtualDataSource( getDataSource, { |
|
479 first: first, |
|
480 last: last, |
|
481 sorting: details.sorting, |
|
482 filtering: details.filtering, |
|
483 filterOperator: details.filterOperator || 'and', |
|
484 grouping: details.grouping, |
|
485 action: details.action |
|
486 } ); |
|
487 } |
|
488 } |
|
489 } |
|
490 else { |
|
491 requestCallback(); |
|
492 } |
|
493 } |
|
494 |
|
495 add( item, parentId ) { |
|
496 const that = this; |
|
497 |
|
498 if ( !item ) { |
|
499 return; |
|
500 } |
|
501 |
|
502 let result = true; |
|
503 |
|
504 const addItem = function ( item ) { |
|
505 const itemObject = that._getDataItem( item, that.boundSource.length ); |
|
506 |
|
507 that[ that.boundSource.length ] = itemObject; |
|
508 that.dataItemById[ itemObject.$.id ] = itemObject; |
|
509 |
|
510 const pushResult = that.boundSource.push( itemObject ); |
|
511 |
|
512 if ( parentId !== undefined ) { |
|
513 itemObject.$.parentId = parentId; |
|
514 } |
|
515 |
|
516 if ( !pushResult ) { |
|
517 result = false; |
|
518 } |
|
519 |
|
520 return itemObject; |
|
521 } |
|
522 |
|
523 if ( item.length ) { |
|
524 let itemObjects = []; |
|
525 |
|
526 for ( let i = 0; i < item.length; i++ ) { |
|
527 const itemObject = addItem( item[ i ] ); |
|
528 |
|
529 itemObjects.push( itemObject ); |
|
530 } |
|
531 |
|
532 that._notify( { action: 'add', data: itemObjects } ); |
|
533 } |
|
534 else { |
|
535 const itemObject = addItem( item ); |
|
536 |
|
537 that._notify( { action: 'add', data: itemObject } ); |
|
538 } |
|
539 |
|
540 that.refreshHierarchy(); |
|
541 |
|
542 return result; |
|
543 } |
|
544 |
|
545 refreshIndexes() { |
|
546 const that = this; |
|
547 |
|
548 for (let i = 0; i < that.boundSource.length; i++) { |
|
549 that[i] = that.boundSource[i]; |
|
550 that[i].$.index = i; |
|
551 that.dataItemById[that[i].$.id] = that[i]; |
|
552 } |
|
553 |
|
554 let i = that.boundSource.length; |
|
555 |
|
556 while (that[i]) { |
|
557 delete that[i]; |
|
558 i++; |
|
559 } |
|
560 } |
|
561 |
|
562 removeLast() { |
|
563 const that = this; |
|
564 |
|
565 delete that[that.boundSource.length - 1]; |
|
566 const result = that.boundSource.pop(); |
|
567 delete that.dataItemById[result.$.id]; |
|
568 |
|
569 that._notify({ action: 'removeLast', data: result }); |
|
570 |
|
571 that.refreshHierarchy(); |
|
572 |
|
573 return result; |
|
574 } |
|
575 |
|
576 removeAt(index) { |
|
577 const that = this; |
|
578 |
|
579 const item = that.boundSource[index]; |
|
580 |
|
581 if (!item) { |
|
582 throw new Error('Invalid Item Index'); |
|
583 } |
|
584 |
|
585 that.boundSource.splice(index, 1); |
|
586 delete that.dataItemById[item.$.id]; |
|
587 that.refreshIndexes(); |
|
588 |
|
589 that._notify({ action: 'remove', index: index, data: item }); |
|
590 |
|
591 that.refreshHierarchy(); |
|
592 } |
|
593 |
|
594 update( index, dataSourceItem ) { |
|
595 const that = this; |
|
596 |
|
597 if ( JQX.Utilities.Types.isArray( index ) && JQX.Utilities.Types.isArray( dataSourceItem ) ) { |
|
598 if ( index.length === 0 && dataSourceItem.length === 0 ) { |
|
599 that.refreshHierarchy(); |
|
600 return; |
|
601 } |
|
602 } |
|
603 |
|
604 if ( dataSourceItem.length && index.length ) { |
|
605 let itemObjects = []; |
|
606 |
|
607 for ( let i = 0; i < index.length; i++ ) { |
|
608 const itemObject = that._getDataItem( dataSourceItem[ i ], index[ i ] ); |
|
609 const currentIndex = index[ i ]; |
|
610 |
|
611 itemObjects.push( itemObject ); |
|
612 |
|
613 that.boundSource[ currentIndex ] = itemObject; |
|
614 that[ currentIndex ] = that.boundSource[ currentIndex ]; |
|
615 that.dataItemById[ itemObject.$.id ] = that[ currentIndex ]; |
|
616 } |
|
617 |
|
618 that._notify( { action: 'update', index: index, data: itemObjects } ); |
|
619 |
|
620 that.refreshHierarchy(); |
|
621 |
|
622 return; |
|
623 } |
|
624 |
|
625 const itemObject = that._getDataItem( dataSourceItem, index ); |
|
626 |
|
627 that.boundSource[ index ] = itemObject; |
|
628 that[ index ] = that.boundSource[ index ]; |
|
629 that.dataItemById[ itemObject.$.id ] = that[ index ]; |
|
630 |
|
631 that._notify( { action: 'update', index: index, data: itemObject } ); |
|
632 |
|
633 that.refreshHierarchy(); |
|
634 |
|
635 return itemObject; |
|
636 } |
|
637 |
|
638 insert( index, item ) { |
|
639 const that = this; |
|
640 |
|
641 item = that._getDataItem( item, index ); |
|
642 |
|
643 const result = that.boundSource.splice( index, 0, item ); |
|
644 |
|
645 that.refreshIndexes(); |
|
646 |
|
647 that._notify( { action: 'insert', index: index, data: item } ); |
|
648 |
|
649 that.refreshHierarchy(); |
|
650 |
|
651 return result; |
|
652 } |
|
653 |
|
654 move( from, to ) { |
|
655 if ( to > from && to - from === 1 || from === to ) { |
|
656 return; |
|
657 } |
|
658 |
|
659 const that = this, |
|
660 recordToMove = that.boundSource.splice( from, 1 )[ 0 ]; |
|
661 |
|
662 if ( to > from ) { |
|
663 to--; |
|
664 that.boundSource.splice( to, 0, recordToMove ); |
|
665 } |
|
666 else { |
|
667 that.boundSource.splice( to, 0, recordToMove ); |
|
668 } |
|
669 |
|
670 that.refreshIndexes(); |
|
671 |
|
672 that._notify( { action: 'move', index: to, data: that.boundSource[ to ] } ); |
|
673 |
|
674 that.refreshHierarchy(); |
|
675 } |
|
676 |
|
677 indexOf( item ) { |
|
678 const that = this; |
|
679 const index = that.boundSource.indexOf( item ); |
|
680 |
|
681 return index; |
|
682 } |
|
683 |
|
684 get length() { |
|
685 const that = this; |
|
686 |
|
687 if ( that.virtualDataSourceLength !== undefined ) { |
|
688 return that.virtualDataSourceLength; |
|
689 } |
|
690 |
|
691 if ( that.dataSourceLength ) { |
|
692 return that.dataSourceLength; |
|
693 } |
|
694 |
|
695 if ( typeof ( that.dataSource ) === 'number' ) { |
|
696 return that.dataSource; |
|
697 } |
|
698 |
|
699 if ( that.bindingCompleted ) { |
|
700 return that.boundSource.length; |
|
701 } |
|
702 |
|
703 if ( that.dataSource && typeof that.dataSource !== 'string' && that.dataSource.length ) { |
|
704 return that.dataSource.length; |
|
705 } |
|
706 |
|
707 return that.boundSource.length; |
|
708 } |
|
709 |
|
710 clear() { |
|
711 const that = this; |
|
712 |
|
713 if ( !that.isInitialized ) { |
|
714 that._cachedValues = []; |
|
715 that.dataItemById = []; |
|
716 return; |
|
717 } |
|
718 |
|
719 for ( let i = 0; i < that.boundSource.length; i++ ) { |
|
720 delete that[ i ]; |
|
721 } |
|
722 |
|
723 that._cachedValues = []; |
|
724 that.boundSource = that.observable ? new JQX.ObservableArray() : []; |
|
725 that.dataItemById = []; |
|
726 that.refreshHierarchy(); |
|
727 } |
|
728 |
|
729 _getId( id, item, index ) { |
|
730 if ( id !== null && id.name !== undefined ) { |
|
731 if ( id.name && item.getAttribute ) { |
|
732 let result = item.getAttribute( id.name ); |
|
733 if ( result !== null && result.toString().length > 0 ) { |
|
734 return result; |
|
735 } |
|
736 else if ( id.map ) { |
|
737 try { |
|
738 let result = item.getAttribute( id.map ); |
|
739 if ( result !== null && result.toString().length > 0 ) { |
|
740 return result; |
|
741 } |
|
742 } |
|
743 catch ( error ) { |
|
744 return index; |
|
745 } |
|
746 } |
|
747 return; |
|
748 } |
|
749 } |
|
750 |
|
751 if ( id ) { |
|
752 if ( id.toString().length > 0 && item.getAttribute ) { |
|
753 let result = item.getAttribute( id ); |
|
754 if ( result !== null && result.toString().length > 0 ) { |
|
755 return result.trim().split( ' ' ).join( '' ).replace( /([ #;?%&,.+*~\':'!^$[\]()=>|\/@])/g, '' ); |
|
756 } |
|
757 else { |
|
758 let splitMap = id.split( this.mapChar ); |
|
759 if ( splitMap.length > 1 ) { |
|
760 let d = item; |
|
761 for ( let p = 0; p < splitMap.length; p++ ) { |
|
762 if ( d !== undefined ) { |
|
763 d = d[ splitMap[ p ] ]; |
|
764 } |
|
765 } |
|
766 if ( d !== undefined ) { |
|
767 return d; |
|
768 } |
|
769 } |
|
770 else { |
|
771 if ( item[ id ] !== undefined ) { |
|
772 return item[ id ]; |
|
773 } |
|
774 } |
|
775 } |
|
776 } |
|
777 } |
|
778 |
|
779 return index; |
|
780 } |
|
781 |
|
782 _buildHierarchy() { |
|
783 const that = this; |
|
784 |
|
785 if ( !that.reservedNames ) { |
|
786 that.reservedNames = { |
|
787 leaf: 'leaf', |
|
788 parent: 'parent', |
|
789 expanded: 'expanded', |
|
790 checked: 'checked', |
|
791 selected: 'selected', |
|
792 level: 'level', |
|
793 icon: 'icon', |
|
794 data: 'data' |
|
795 } |
|
796 } |
|
797 else { |
|
798 const names = that.reservedNames; |
|
799 |
|
800 if ( !names.leaf ) { |
|
801 names.leaf = 'leaf'; |
|
802 } |
|
803 if ( !names.parent ) { |
|
804 names.parent = 'parent'; |
|
805 } |
|
806 if ( !names.expanded ) { |
|
807 names.expanded = 'expanded'; |
|
808 } |
|
809 if ( !names.checked ) { |
|
810 names.checked = 'checked'; |
|
811 } |
|
812 if ( !names.selected ) { |
|
813 names.selected = 'selected'; |
|
814 } |
|
815 if ( !names.level ) { |
|
816 names.level = 'level'; |
|
817 } |
|
818 if ( !names.data ) { |
|
819 names.data = 'data'; |
|
820 } |
|
821 |
|
822 } |
|
823 |
|
824 const names = that.reservedNames; |
|
825 |
|
826 if ( that.childrenDataField ) { |
|
827 const hierarchy = []; |
|
828 |
|
829 for ( let i = 0; i < that.boundSource.length; i++ ) { |
|
830 const item = Object.assign( {}, that.boundSource[ i ] ); |
|
831 |
|
832 if ( !item ) { |
|
833 continue; |
|
834 } |
|
835 |
|
836 hierarchy.push( item ); |
|
837 |
|
838 const addItems = function ( item ) { |
|
839 const splitMap = that.childrenDataField.split( that.mapChar ); |
|
840 let children = null; |
|
841 |
|
842 if ( splitMap.length > 1 ) { |
|
843 let data = item; |
|
844 |
|
845 for ( let p = 0; p < splitMap.length; p++ ) { |
|
846 if ( data !== undefined ) { |
|
847 data = data[ splitMap[ p ] ]; |
|
848 } |
|
849 } |
|
850 |
|
851 children = data; |
|
852 } |
|
853 else { |
|
854 children = item[ 'children' ]; |
|
855 } |
|
856 |
|
857 item[ 'children' ] = children; |
|
858 |
|
859 if ( item[ 'children' ] === null || item[ 'children' ] === undefined || ( item[ 'children' ] && item[ 'children' ].length === 0 ) ) { |
|
860 item[ names.leaf ] = true; |
|
861 } |
|
862 } |
|
863 |
|
864 addItems( item ); |
|
865 item[ names.level ] = 0; |
|
866 |
|
867 if ( !item.$ ) { |
|
868 item.$ = {}; |
|
869 } |
|
870 |
|
871 item[ names.parent ] = null; |
|
872 item[ names.data ] = item; |
|
873 |
|
874 if ( item[ names.expanded ] === undefined ) { |
|
875 item[ names.expanded ] = false; |
|
876 } |
|
877 |
|
878 const drillThrough = function ( parent, children ) { |
|
879 if ( !children ) { |
|
880 parent[ 'children' ] = new Array(); |
|
881 return; |
|
882 } |
|
883 |
|
884 for ( let i = 0; i < children.length; i++ ) { |
|
885 let item = that._getDataItem( children[ i ], i ); |
|
886 |
|
887 if ( !item ) { |
|
888 continue; |
|
889 } |
|
890 |
|
891 addItems( item ); |
|
892 item[ names.level ] = parent[ names.level ] + 1; |
|
893 item[ names.parent ] = parent; |
|
894 item[ names.data ] = item; |
|
895 |
|
896 if ( parent ) { |
|
897 parent[ 'children' ][ i ] = item; |
|
898 } |
|
899 |
|
900 |
|
901 if ( item[ names.expanded ] === undefined ) { |
|
902 item[ names.expanded ] = false; |
|
903 } |
|
904 |
|
905 drillThrough( item, item[ 'children' ] ); |
|
906 } |
|
907 } |
|
908 |
|
909 drillThrough( item, item[ 'children' ] ); |
|
910 } |
|
911 |
|
912 |
|
913 that.boundHierarchy = hierarchy; |
|
914 |
|
915 if ( !that._boundSourceUpdate ) { |
|
916 for ( let i = 0; i < that.boundHierarchy.length; i++ ) { |
|
917 const item = that.boundHierarchy[ i ]; |
|
918 |
|
919 if ( item.children ) { |
|
920 const drillThrough = function ( item ) { |
|
921 if ( !that.dataItemById[ item.$.id ] ) { |
|
922 that.boundSource.canNotify = false; |
|
923 that.dataItemById[ item.$.id ] = item; |
|
924 that[ that.boundSource.length ] = item; |
|
925 that.boundSource.push( item ); |
|
926 that.boundSource.canNotify = true; |
|
927 } |
|
928 |
|
929 if ( item.children ) { |
|
930 for ( let i = 0; i < item.children.length; i++ ) { |
|
931 const child = item.children[ i ]; |
|
932 |
|
933 if ( child.children ) { |
|
934 drillThrough( child ); |
|
935 } |
|
936 } |
|
937 } |
|
938 } |
|
939 |
|
940 drillThrough( item ); |
|
941 } |
|
942 } |
|
943 |
|
944 that._boundSourceUpdate = true; |
|
945 } |
|
946 } |
|
947 |
|
948 if ( that.xmlRoot && that.dataSourceType === 'xml' ) { |
|
949 that.boundHierarchy = this._getHierarchy( 'uid', '_parentuid', 'children', null, that.boundSource ); |
|
950 } |
|
951 |
|
952 if ( that.keyDataField && that.parentDataField ) { |
|
953 that.boundHierarchy = this._getHierarchy( that.keyDataField, that.parentDataField, 'children', null, that.boundSource ); |
|
954 } |
|
955 |
|
956 if ( that.groupBy && that.groupBy.length > 0 ) { |
|
957 that.boundHierarchy = this._getGroupHierarchy( that.groupBy, 'children', 'label', null, 'data', null, 'parent', that.boundSource ); |
|
958 } |
|
959 |
|
960 if ( that.virtualDataSourceOnExpand ) { |
|
961 that.boundHierarchy = this._getHierarchy( 'id', 'parentId', 'children', null, that.boundSource ); |
|
962 } |
|
963 } |
|
964 |
|
965 |
|
966 _getGroupHierarchy( groups, collectionName, groupName, mappingFields, itemName, valueName, parentName, data, startIndex ) { |
|
967 let that = this; |
|
968 |
|
969 if ( !startIndex ) { |
|
970 startIndex = 0; |
|
971 } |
|
972 |
|
973 let names = that.reservedNames; |
|
974 |
|
975 const guid = function () { |
|
976 function s4() { |
|
977 return Math.floor( ( 1 + Math.random() ) * 0x10000 ) |
|
978 .toString( 16 ) |
|
979 .substring( 1 ); |
|
980 } |
|
981 |
|
982 return s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4(); |
|
983 } |
|
984 |
|
985 let groupHashCodes = new Array(); |
|
986 for ( let iGroupColumn = 0; iGroupColumn < groups.length; iGroupColumn++ ) { |
|
987 groupHashCodes[ iGroupColumn ] = guid(); |
|
988 } |
|
989 |
|
990 if ( !collectionName ) { |
|
991 collectionName = 'children'; |
|
992 } |
|
993 |
|
994 if ( !groupName ) { |
|
995 groupName = 'group'; |
|
996 } |
|
997 |
|
998 if ( !itemName ) { |
|
999 itemName = 'item'; |
|
1000 } |
|
1001 |
|
1002 if ( !parentName ) { |
|
1003 parentName = 'parent'; |
|
1004 } |
|
1005 |
|
1006 if ( undefined === valueName ) { |
|
1007 valueName = 'value'; |
|
1008 } |
|
1009 |
|
1010 const groupboundSource = new Array(); |
|
1011 const hashItemGroups = new Array(); |
|
1012 |
|
1013 let groupboundSourceIndex = 0; |
|
1014 |
|
1015 const getItem = function ( item ) { |
|
1016 let itemObj = item; |
|
1017 if ( mappingFields ) { |
|
1018 for ( let mappingField in mappingFields ) { |
|
1019 const mappingObject = mappingFields[ mappingField ]; |
|
1020 |
|
1021 if ( mappingObject.name && mappingObject.map ) { |
|
1022 itemObj[ mappingObject.map ] = itemObj[ mappingObject.name ]; |
|
1023 } |
|
1024 } |
|
1025 } |
|
1026 |
|
1027 return itemObj; |
|
1028 } |
|
1029 |
|
1030 for ( let obj = 0; obj < data.length; obj++ ) { |
|
1031 let item = Object.assign( {}, getItem( data[ obj ] ) ); |
|
1032 |
|
1033 item[ names.leaf ] = false; |
|
1034 |
|
1035 let itemKeysHierarchy = new Array(); |
|
1036 let keys = 0; |
|
1037 |
|
1038 for ( let iGroupColumn = 0; iGroupColumn < groups.length; iGroupColumn++ ) { |
|
1039 const group = groups[ iGroupColumn ]; |
|
1040 const value = item[ group ]; |
|
1041 |
|
1042 if ( null === value ) { |
|
1043 continue; |
|
1044 } |
|
1045 |
|
1046 itemKeysHierarchy[ keys++ ] = { value: value, group: group, hash: groupHashCodes[ iGroupColumn ] }; |
|
1047 } |
|
1048 |
|
1049 if ( itemKeysHierarchy.length !== groups.length ) { |
|
1050 break; |
|
1051 } |
|
1052 |
|
1053 let parentItem = null; |
|
1054 let lookupKey = ''; |
|
1055 |
|
1056 for ( let q = 0; q < itemKeysHierarchy.length; q++ ) { |
|
1057 const itemKey = itemKeysHierarchy[ q ].value; |
|
1058 const groupDataField = itemKeysHierarchy[ q ].group; |
|
1059 const columnHash = itemKeysHierarchy[ q ].hash; |
|
1060 |
|
1061 lookupKey = lookupKey + '_' + columnHash + '_' + itemKey; |
|
1062 |
|
1063 if ( hashItemGroups[ lookupKey ] !== undefined && hashItemGroups[ lookupKey ] !== null ) { |
|
1064 parentItem = hashItemGroups[ lookupKey ]; |
|
1065 continue; |
|
1066 } |
|
1067 |
|
1068 if ( parentItem === null ) { |
|
1069 parentItem = { $: {} }; |
|
1070 |
|
1071 parentItem[ names.level ] = 0; |
|
1072 parentItem[ names.leaf ] = false; |
|
1073 parentItem[ parentName ] = null; |
|
1074 parentItem[ groupName ] = itemKey; |
|
1075 parentItem[ itemName ] = item; |
|
1076 parentItem[ 'groupDataField' ] = groupDataField; |
|
1077 |
|
1078 if ( !parentItem[ groupDataField ] ) { |
|
1079 parentItem[ groupDataField ] = parentItem.data[ groupDataField ]; |
|
1080 } |
|
1081 |
|
1082 if ( item[ names.expanded ] !== undefined ) { |
|
1083 parentItem[ names.expanded ] = item[ names.expanded ]; |
|
1084 } |
|
1085 else { |
|
1086 parentItem[ names.expanded ] = false; |
|
1087 } |
|
1088 |
|
1089 if ( valueName ) { |
|
1090 parentItem[ valueName ] = item[ valueName ]; |
|
1091 } |
|
1092 |
|
1093 parentItem[ collectionName ] = new Array(); |
|
1094 |
|
1095 let uid = groupboundSource.length + startIndex; |
|
1096 |
|
1097 if ( !this.id || typeof item.$.id === 'number' || isFinite( item.$.id ) ) { |
|
1098 uid = 'Item' + uid; |
|
1099 } |
|
1100 if ( parentItem.$.id === undefined ) { |
|
1101 parentItem.$.id = uid; |
|
1102 } |
|
1103 |
|
1104 groupboundSource[ groupboundSourceIndex++ ] = parentItem; |
|
1105 } |
|
1106 else { |
|
1107 const subItem = { $: {} }; |
|
1108 |
|
1109 subItem[ names.level ] = parentItem[ names.level ] + 1; |
|
1110 subItem[ parentName ] = parentItem; |
|
1111 subItem[ groupName ] = itemKey; |
|
1112 subItem[ collectionName ] = new Array(); |
|
1113 subItem[ itemName ] = item; |
|
1114 subItem[ 'groupDataField' ] = groupDataField; |
|
1115 subItem[ names.leaf ] = false; |
|
1116 |
|
1117 if ( !subItem[ groupDataField ] ) { |
|
1118 subItem[ groupDataField ] = subItem.data[ groupDataField ]; |
|
1119 } |
|
1120 |
|
1121 if ( item[ names.expanded ] !== undefined ) { |
|
1122 subItem[ names.expanded ] = item[ names.expanded ]; |
|
1123 } |
|
1124 else { |
|
1125 subItem[ names.expanded ] = false; |
|
1126 } |
|
1127 |
|
1128 if ( valueName ) { |
|
1129 subItem[ valueName ] = item[ valueName ]; |
|
1130 } |
|
1131 |
|
1132 if ( subItem.$.id === undefined ) { |
|
1133 subItem.$.id = parentItem.$.id + '_' + parentItem[ collectionName ].length; |
|
1134 } |
|
1135 |
|
1136 parentItem[ collectionName ][ parentItem[ collectionName ].length ] = subItem; |
|
1137 parentItem = subItem; |
|
1138 } |
|
1139 |
|
1140 hashItemGroups[ lookupKey ] = parentItem; |
|
1141 } |
|
1142 |
|
1143 if ( item ) { |
|
1144 item[ names.leaf ] = true; |
|
1145 } |
|
1146 |
|
1147 if ( parentItem !== null ) { |
|
1148 if ( this.id === null ) { |
|
1149 if ( undefined === item.$.id ) { |
|
1150 item.$.id = parentItem.$.id + '_' + parentItem[ collectionName ].length; |
|
1151 } |
|
1152 } |
|
1153 else { |
|
1154 if ( undefined === item.$.id ) { |
|
1155 if ( item.$.id.toString().indexOf( parentItem.$.id ) === -1 ) { |
|
1156 item.$.id = parentItem.$.id + '_' + item.$.id; |
|
1157 } |
|
1158 } |
|
1159 } |
|
1160 |
|
1161 item[ parentName ] = parentItem; |
|
1162 item[ names.level ] = parentItem[ names.level ] + 1; |
|
1163 parentItem[ collectionName ][ parentItem[ collectionName ].length ] = item; |
|
1164 } |
|
1165 else { |
|
1166 if ( undefined === item.$.id ) { |
|
1167 item.$.id = guid(); |
|
1168 } |
|
1169 } |
|
1170 } |
|
1171 |
|
1172 return groupboundSource; |
|
1173 } |
|
1174 |
|
1175 _getHierarchy( fieldName, parentFieldName, collectionName, mappingFields, boundSource ) { |
|
1176 const that = this; |
|
1177 |
|
1178 const databoundHierarchy = new Array(); |
|
1179 let flatData = this.boundSource; |
|
1180 |
|
1181 if ( boundSource ) { |
|
1182 flatData = boundSource; |
|
1183 } |
|
1184 |
|
1185 if ( this.boundSource.length === 0 ) |
|
1186 return null; |
|
1187 |
|
1188 const childrenName = collectionName !== null ? collectionName : 'children'; |
|
1189 let items = new Array(); |
|
1190 let data = flatData; |
|
1191 let dataLength = data.length; |
|
1192 let names = that.reservedNames; |
|
1193 |
|
1194 const getItem = function ( item ) { |
|
1195 let itemObj = item; |
|
1196 if ( mappingFields ) { |
|
1197 for ( let mappingField in mappingFields ) { |
|
1198 const mappingObject = mappingFields[ mappingField ]; |
|
1199 |
|
1200 if ( mappingObject.name && mappingObject.map ) { |
|
1201 itemObj[ mappingObject.map ] = itemObj[ mappingObject.name ]; |
|
1202 } |
|
1203 } |
|
1204 } |
|
1205 |
|
1206 return itemObj; |
|
1207 } |
|
1208 |
|
1209 // build hierarchical source. |
|
1210 for ( let i = 0; i < dataLength; i++ ) { |
|
1211 let item = data[ i ]; |
|
1212 let parentId = item[ parentFieldName ]; |
|
1213 let id = item[ fieldName ]; |
|
1214 |
|
1215 if ( parentFieldName === 'parentId' ) { |
|
1216 parentId = item.$.parentId; |
|
1217 } |
|
1218 |
|
1219 if ( fieldName === 'id' ) { |
|
1220 id = item.$.id; |
|
1221 } |
|
1222 |
|
1223 item[ childrenName ] = new Array(); |
|
1224 |
|
1225 items[ id ] = { parentId: parentId, item: item }; |
|
1226 } |
|
1227 |
|
1228 for ( let i = 0; i < dataLength; i++ ) { |
|
1229 const item = data[ i ]; |
|
1230 let parentId = item[ parentFieldName ]; |
|
1231 let id = item[ fieldName ]; |
|
1232 |
|
1233 if ( parentFieldName === 'parentId' ) { |
|
1234 parentId = item.$.parentId; |
|
1235 } |
|
1236 |
|
1237 if ( fieldName === 'id' ) { |
|
1238 id = item.$.id; |
|
1239 } |
|
1240 |
|
1241 if ( items[ parentId ] !== undefined ) { |
|
1242 let item = { parentId: parentId, item: items[ id ].item }; |
|
1243 let parentItem = items[ parentId ].item; |
|
1244 if ( !parentItem[ childrenName ] ) { |
|
1245 parentItem[ childrenName ] = new Array(); |
|
1246 } |
|
1247 let length = parentItem[ childrenName ].length; |
|
1248 item = item.item; |
|
1249 |
|
1250 if ( !names ) { |
|
1251 if ( item.parent === undefined ) { |
|
1252 item.parent = parentItem; |
|
1253 } |
|
1254 } |
|
1255 else { |
|
1256 if ( item[ names.parent ] === undefined ) { |
|
1257 item[ names.parent ] = parentItem; |
|
1258 } |
|
1259 } |
|
1260 |
|
1261 const itemObj = getItem( item ); |
|
1262 |
|
1263 parentItem[ childrenName ][ length ] = itemObj; |
|
1264 items[ parentId ].item = parentItem; |
|
1265 items[ id ].item = item; |
|
1266 |
|
1267 } |
|
1268 else { |
|
1269 let item = items[ id ].item; |
|
1270 if ( !names ) { |
|
1271 if ( item.parent === undefined ) { |
|
1272 item.parent = null; |
|
1273 } |
|
1274 } |
|
1275 else { |
|
1276 if ( item[ names.parent ] === undefined ) { |
|
1277 item[ names.parent ] = null; |
|
1278 } |
|
1279 } |
|
1280 |
|
1281 const itemObj = getItem( item ); |
|
1282 |
|
1283 if ( !names ) { |
|
1284 itemObj.level = 0; |
|
1285 } |
|
1286 else { |
|
1287 itemObj[ names.level ] = 0; |
|
1288 } |
|
1289 |
|
1290 databoundHierarchy[ databoundHierarchy.length ] = itemObj; |
|
1291 } |
|
1292 } |
|
1293 if ( databoundHierarchy.length !== 0 ) { |
|
1294 let updateLevels = function ( level, children ) { |
|
1295 for ( let i = 0; i < children.length; i++ ) { |
|
1296 const child = children[ i ]; |
|
1297 |
|
1298 if ( !names ) { |
|
1299 child.level = level; |
|
1300 } |
|
1301 else { |
|
1302 child[ names.level ] = level; |
|
1303 } |
|
1304 |
|
1305 const childChildren = child[ childrenName ]; |
|
1306 |
|
1307 if ( childChildren ) { |
|
1308 if ( childChildren.length > 0 ) { |
|
1309 updateLevels( level + 1, childChildren ); |
|
1310 } |
|
1311 else { |
|
1312 if ( that.virtualDataSourceOnExpand ) { |
|
1313 if ( child.leaf === undefined ) { |
|
1314 child.leaf = false; |
|
1315 } |
|
1316 } |
|
1317 else { |
|
1318 if ( !names ) { |
|
1319 child.leaf = true; |
|
1320 } |
|
1321 else { |
|
1322 child[ names.leaf ] = true; |
|
1323 } |
|
1324 } |
|
1325 } |
|
1326 } |
|
1327 else { |
|
1328 if ( that.virtualDataSourceOnExpand ) { |
|
1329 if ( child.leaf === undefined ) { |
|
1330 child.leaf = false; |
|
1331 } |
|
1332 } |
|
1333 else { |
|
1334 if ( !names ) { |
|
1335 child.leaf = true; |
|
1336 } |
|
1337 else { |
|
1338 child[ names.leaf ] = true; |
|
1339 } |
|
1340 } |
|
1341 } |
|
1342 } |
|
1343 }; |
|
1344 updateLevels( 0, databoundHierarchy ); |
|
1345 } |
|
1346 return databoundHierarchy; |
|
1347 } |
|
1348 |
|
1349 summarize( summaryItems, boundSource ) { |
|
1350 const that = this; |
|
1351 |
|
1352 if ( !Array.isArray( summaryItems ) ) { |
|
1353 summaryItems = [ summaryItems ]; |
|
1354 } |
|
1355 |
|
1356 let tempSummaryItems = []; |
|
1357 |
|
1358 for ( let i = 0; i < summaryItems.length; i++ ) { |
|
1359 const summaryItem = summaryItems[ i ]; |
|
1360 |
|
1361 for ( let name in summaryItem ) { |
|
1362 const functions = summaryItem[ name ]; |
|
1363 |
|
1364 tempSummaryItems.push( { dataField: name, functions: functions } ) |
|
1365 } |
|
1366 } |
|
1367 |
|
1368 summaryItems = tempSummaryItems; |
|
1369 |
|
1370 let data = {}; |
|
1371 let summaryByDataField = new Array(); |
|
1372 |
|
1373 if ( !boundSource ) { |
|
1374 boundSource = that.boundSource; |
|
1375 } |
|
1376 |
|
1377 let length = boundSource.length; |
|
1378 |
|
1379 if ( length === 0 ) { |
|
1380 return; |
|
1381 } |
|
1382 |
|
1383 if ( length === undefined ) { |
|
1384 return; |
|
1385 } |
|
1386 |
|
1387 for ( let i = 0; i < length; i++ ) { |
|
1388 let dataItem = boundSource[ i ]; |
|
1389 |
|
1390 for ( let j = 0; j < summaryItems.length; j++ ) { |
|
1391 const summaryItem = summaryItems[ j ]; |
|
1392 let value = dataItem[ summaryItem.dataField ]; |
|
1393 |
|
1394 if ( summaryItem.functions ) { |
|
1395 data[ summaryItem.dataField ] = data[ summaryItem.dataField ] || {}; |
|
1396 summaryByDataField[ summaryItem.dataField ] = summaryByDataField[ summaryItem.dataField ] || 0; |
|
1397 summaryByDataField[ summaryItem.dataField ]++; |
|
1398 |
|
1399 const _summaryItemFunction = function ( summaryItemObject ) { |
|
1400 for ( let name in summaryItemObject ) { |
|
1401 let oldValue = data[ summaryItem.dataField ][ name ]; |
|
1402 |
|
1403 if ( oldValue === null || oldValue === undefined ) { |
|
1404 data[ summaryItem.dataField ][ name ] = 0; |
|
1405 oldValue = 0; |
|
1406 } |
|
1407 |
|
1408 if ( typeof summaryItemObject[ name ] === 'function' ) { |
|
1409 oldValue = summaryItemObject[ name ]( oldValue, value, summaryItem.dataField, dataItem ); |
|
1410 } |
|
1411 data[ summaryItem.dataField ][ name ] = oldValue; |
|
1412 } |
|
1413 } |
|
1414 |
|
1415 let canParse = parseFloat( value ); |
|
1416 |
|
1417 if ( isNaN( canParse ) ) { |
|
1418 canParse = false; |
|
1419 } |
|
1420 else { |
|
1421 canParse = true; |
|
1422 } |
|
1423 |
|
1424 if ( canParse ) { |
|
1425 value = parseFloat( value ); |
|
1426 } |
|
1427 |
|
1428 if ( typeof value === 'number' && isFinite( value ) ) { |
|
1429 summaryItem.functions.forEach( function ( summaryItemFunction ) { |
|
1430 let oldValue = data[ summaryItem.dataField ][ summaryItemFunction ]; |
|
1431 |
|
1432 if ( oldValue === null || oldValue === undefined ) { |
|
1433 oldValue = 0; |
|
1434 |
|
1435 if ( summaryItemFunction === 'min' ) { |
|
1436 oldValue = 9999999999999; |
|
1437 } |
|
1438 |
|
1439 if ( summaryItemFunction === 'max' ) { |
|
1440 oldValue = -9999999999999; |
|
1441 } |
|
1442 |
|
1443 if (summaryItemFunction === 'median') { |
|
1444 oldValue = []; |
|
1445 } |
|
1446 } |
|
1447 |
|
1448 if ( summaryItemFunction === 'sum' || summaryItemFunction === 'avg' || summaryItemFunction === 'stdev' |
|
1449 || summaryItemFunction === 'stdevp' || summaryItemFunction === 'var' || summaryItemFunction === 'varp' ) { |
|
1450 oldValue += parseFloat( value ); |
|
1451 } |
|
1452 else if ( summaryItemFunction === 'product' ) { |
|
1453 if ( i === 0 ) |
|
1454 oldValue = parseFloat( value ); |
|
1455 else |
|
1456 oldValue *= parseFloat( value ); |
|
1457 } |
|
1458 else if ( summaryItemFunction === 'min' ) { |
|
1459 oldValue = Math.min( oldValue, parseFloat( value ) ); |
|
1460 } |
|
1461 else if ( summaryItemFunction === 'max' ) { |
|
1462 oldValue = Math.max( oldValue, parseFloat( value ) ); |
|
1463 } |
|
1464 else if ( summaryItemFunction === 'count' ) { |
|
1465 oldValue++; |
|
1466 } |
|
1467 else if (summaryItemFunction === 'median') { |
|
1468 oldValue.push(parseFloat(value)); |
|
1469 } |
|
1470 else if ( typeof ( summaryItemFunction ) === 'object' ) { |
|
1471 _summaryItemFunction( summaryItemFunction ); |
|
1472 return; |
|
1473 } |
|
1474 |
|
1475 data[ summaryItem.dataField ][ summaryItemFunction ] = oldValue; |
|
1476 } ); |
|
1477 } |
|
1478 else { |
|
1479 summaryItem.functions.forEach( function ( summaryItemFunction ) { |
|
1480 if ( summaryItemFunction === 'min' || summaryItemFunction === 'max' || summaryItemFunction === 'count' || summaryItemFunction === 'product' || summaryItemFunction === 'sum' |
|
1481 || summaryItemFunction === 'avg' || summaryItemFunction === 'stdev' |
|
1482 || summaryItemFunction === 'stdevp' || summaryItemFunction === 'var' || summaryItemFunction === 'varp' ) { |
|
1483 if ( value === null ) { |
|
1484 return true; |
|
1485 } |
|
1486 |
|
1487 let oldValue = data[ summaryItem.dataField ][ summaryItemFunction ]; |
|
1488 |
|
1489 if ( oldValue === null || oldValue === undefined ) { |
|
1490 oldValue = 0; |
|
1491 } |
|
1492 |
|
1493 data[ summaryItem.dataField ][ summaryItemFunction ] = oldValue; |
|
1494 |
|
1495 return true; |
|
1496 } |
|
1497 |
|
1498 if ( typeof ( summaryItemFunction ) === 'object' ) { |
|
1499 _summaryItemFunction( summaryItemFunction ); |
|
1500 } |
|
1501 } ); |
|
1502 } |
|
1503 } |
|
1504 } |
|
1505 } |
|
1506 |
|
1507 for ( let j = 0; j < summaryItems.length; j++ ) { |
|
1508 const summaryItem = summaryItems[ j ]; |
|
1509 |
|
1510 if ( !summaryItem.functions ) { |
|
1511 continue; |
|
1512 } |
|
1513 if ( !data[ summaryItem.dataField ] ) { |
|
1514 data[ summaryItem.dataField ] = {}; |
|
1515 |
|
1516 summaryItem.functions.forEach( function ( summaryItemFunction ) { |
|
1517 data[ summaryItem.dataField ][ summaryItemFunction ] = 0; |
|
1518 } ); |
|
1519 } |
|
1520 |
|
1521 if ( data[ summaryItem.dataField ][ 'avg' ] !== undefined ) { |
|
1522 const value = data[ summaryItem.dataField ][ 'avg' ]; |
|
1523 const dataValues = summaryByDataField[ summaryItem.dataField ]; |
|
1524 |
|
1525 if ( dataValues === 0 || dataValues === undefined ) { |
|
1526 data[ summaryItem.dataField ][ 'avg' ] = 0; |
|
1527 } |
|
1528 else { |
|
1529 data[ summaryItem.dataField ][ 'avg' ] = value / dataValues; |
|
1530 } |
|
1531 } |
|
1532 else if ( data[ summaryItem.dataField ][ 'count' ] !== undefined ) { |
|
1533 data[ summaryItem.dataField ][ 'count' ] = length; |
|
1534 } |
|
1535 else if (data[summaryItem.dataField]['median'] !== undefined) { |
|
1536 let population = data[summaryItem.dataField]['median']; |
|
1537 |
|
1538 population.sort(function (a, b) { |
|
1539 return a - b; |
|
1540 }); |
|
1541 |
|
1542 data[summaryItem.dataField]['median'] = |
|
1543 0.5 * (population[Math.floor((population.length + 1) / 2) - 1] + population[Math.ceil((population.length + 1) / 2) - 1]); |
|
1544 } |
|
1545 |
|
1546 // stdev, stdevp, var, varp. |
|
1547 // stdev - Standard deviation on a sample. |
|
1548 // varp - Variance on an entire population. |
|
1549 // let - Variance on a sample. |
|
1550 if ( data[ summaryItem.dataField ][ 'stdev' ] || data[ summaryItem.dataField ][ 'stdevp' ] |
|
1551 || data[ summaryItem.dataField ][ 'var' ] || data[ summaryItem.dataField ][ 'varp' ] ) { |
|
1552 summaryItem.functions.forEach( function ( summaryItemFunction ) { |
|
1553 if ( summaryItemFunction === 'stdev' || summaryItemFunction === 'var' || summaryItemFunction === 'varp' || summaryItemFunction === 'stdevp' ) { |
|
1554 const value = data[ summaryItem.dataField ][ summaryItemFunction ]; |
|
1555 const count = length; |
|
1556 const average = ( value / length ); |
|
1557 let sumSq = 0.0; |
|
1558 |
|
1559 for ( let i = 0; i < length; i++ ) { |
|
1560 let dataItem = boundSource[ i ]; |
|
1561 let value = dataItem[ summaryItem.dataField ]; |
|
1562 |
|
1563 sumSq += ( value - average ) * ( value - average ); |
|
1564 } |
|
1565 |
|
1566 let denominator = ( summaryItemFunction === 'stdevp' || summaryItemFunction === 'varp' ) ? count : count - 1; |
|
1567 |
|
1568 if ( denominator === 0 ) { |
|
1569 denominator = 1; |
|
1570 } |
|
1571 |
|
1572 if ( summaryItemFunction === 'var' || summaryItemFunction === 'varp' ) { |
|
1573 data[ summaryItem.dataField ][ summaryItemFunction ] = sumSq / denominator; |
|
1574 } |
|
1575 else if ( summaryItemFunction === 'stdevp' || summaryItemFunction === 'stdev' ) { |
|
1576 data[ summaryItem.dataField ][ summaryItemFunction ] = Math.sqrt( sumSq / denominator ); |
|
1577 } |
|
1578 } |
|
1579 } ); |
|
1580 } |
|
1581 } |
|
1582 return data; |
|
1583 } |
|
1584 |
|
1585 deserialize(stringValue, type, nullable) { |
|
1586 const nullValue = stringValue === 'null'; |
|
1587 |
|
1588 if (stringValue === undefined || (nullValue && !nullable)) { |
|
1589 return undefined; |
|
1590 } |
|
1591 |
|
1592 if (nullValue && nullable) { |
|
1593 return null; |
|
1594 } |
|
1595 |
|
1596 if (type === 'boolean' || type === 'bool') { |
|
1597 if (stringValue === null) { |
|
1598 return false; |
|
1599 } |
|
1600 |
|
1601 // Boolean properties are set based on the presence of the attribute: if the attribute exists at all, the value is true. |
|
1602 return true; |
|
1603 } |
|
1604 else if (type === 'number' || type === 'float') { |
|
1605 if (stringValue === 'NaN') { |
|
1606 return NaN; |
|
1607 } |
|
1608 |
|
1609 if (stringValue === 'Infinity') { |
|
1610 return Infinity; |
|
1611 } |
|
1612 |
|
1613 if (stringValue === '-Infinity') { |
|
1614 return -Infinity; |
|
1615 } |
|
1616 |
|
1617 return parseFloat(stringValue); |
|
1618 } |
|
1619 else if (type === 'int' || type === 'integer') { |
|
1620 if (stringValue === 'NaN') { |
|
1621 return NaN; |
|
1622 } |
|
1623 |
|
1624 if (stringValue === 'Infinity') { |
|
1625 return Infinity; |
|
1626 } |
|
1627 |
|
1628 if (stringValue === '-Infinity') { |
|
1629 return -Infinity; |
|
1630 } |
|
1631 |
|
1632 return parseInt(stringValue); |
|
1633 } |
|
1634 else if (type === 'string') { |
|
1635 return stringValue; |
|
1636 } |
|
1637 else if (type === 'any') { |
|
1638 return stringValue; |
|
1639 } |
|
1640 else if (type === 'date') { |
|
1641 return new Date(stringValue); |
|
1642 } |
|
1643 else if (type === 'function') { |
|
1644 if (typeof window[stringValue] === 'function') { |
|
1645 return window[stringValue]; |
|
1646 } |
|
1647 } |
|
1648 else if (type === 'array' || type === 'object') { |
|
1649 try { |
|
1650 const jsonObject = JSON.parse(stringValue); |
|
1651 |
|
1652 if (jsonObject) { |
|
1653 return jsonObject; |
|
1654 } |
|
1655 } |
|
1656 catch (er) { |
|
1657 if (window[stringValue] && (typeof window[stringValue] === 'object')) { |
|
1658 return window[stringValue]; |
|
1659 } |
|
1660 else if (type === 'array' && stringValue.indexOf('[') >= 0) { |
|
1661 if (stringValue.indexOf('{') >= 0) { |
|
1662 let array = stringValue.replace(/{/ig, '').replace('[', '').replace(']', '').replace(/'/ig, '').replace(/"/ig, '').trim(); |
|
1663 |
|
1664 array = array.split('},'); |
|
1665 |
|
1666 for (let i = 0; i < array.length; i++) { |
|
1667 let parsedObject = { |
|
1668 }; |
|
1669 |
|
1670 let parts = array[i].trim().split(','); |
|
1671 |
|
1672 for (let j = 0; j < parts.length; j++) { |
|
1673 const key = parts[j].split(':')[0].trim(); |
|
1674 const value = parts[j].split(':')[1].trim(); |
|
1675 |
|
1676 parsedObject[key] = value; |
|
1677 } |
|
1678 |
|
1679 array[i] = parsedObject; |
|
1680 } |
|
1681 |
|
1682 return array; |
|
1683 } |
|
1684 |
|
1685 const array = stringValue.replace('[', '').replace(']', '').replace(/'/ig, '').replace(/"/ig, '').trim().split(','); |
|
1686 |
|
1687 return array; |
|
1688 } |
|
1689 } |
|
1690 } |
|
1691 |
|
1692 return undefined; |
|
1693 } |
|
1694 |
|
1695 _getDataItem( dataSourceItem, index ) { |
|
1696 const that = this; |
|
1697 const itemObject = {}; |
|
1698 const unboundMode = typeof ( that.dataSource ) === 'number' || that.dataSourceLength; |
|
1699 |
|
1700 if ( !dataSourceItem ) { |
|
1701 return { $: { id: index, isEmpty: true, index: index } } |
|
1702 } |
|
1703 |
|
1704 if ( typeof dataSourceItem === 'string' ) { |
|
1705 dataSourceItem = { '': dataSourceItem }; |
|
1706 } |
|
1707 |
|
1708 if ( unboundMode ) { |
|
1709 for ( let j = 0; j < that.dataFields.length; j++ ) { |
|
1710 const dataField = that.dataFields ? that.dataFields[ j ] : {}; |
|
1711 |
|
1712 itemObject[ dataField.name ] = ''; |
|
1713 } |
|
1714 |
|
1715 itemObject.$ = {}; |
|
1716 itemObject.$.id = index; |
|
1717 itemObject.$.index = index; |
|
1718 |
|
1719 return itemObject; |
|
1720 } |
|
1721 |
|
1722 const dataItem = dataSourceItem; |
|
1723 |
|
1724 if ( dataItem.expanded !== undefined ) { |
|
1725 itemObject.expanded = dataItem.expanded; |
|
1726 |
|
1727 if ( dataItem.expanded === 'true' || dataItem.expanded === true || dataItem.expanded === 1 ) { |
|
1728 itemObject.expanded = true; |
|
1729 } |
|
1730 else { |
|
1731 itemObject.expanded = false; |
|
1732 } |
|
1733 } |
|
1734 |
|
1735 if ( that.childrenDataField ) { |
|
1736 if ( dataItem[ that.childrenDataField ] !== undefined ) { |
|
1737 itemObject.children = dataItem[ that.childrenDataField ]; |
|
1738 } |
|
1739 } |
|
1740 else { |
|
1741 if ( dataItem.children !== undefined ) { |
|
1742 itemObject.children = dataItem.children; |
|
1743 } |
|
1744 else if ( dataItem.items !== undefined ) { |
|
1745 itemObject.children = dataItem.items; |
|
1746 } |
|
1747 } |
|
1748 if ( dataItem.leaf !== undefined ) { |
|
1749 itemObject.leaf = dataItem.leaf; |
|
1750 } |
|
1751 |
|
1752 if ( dataItem.level !== undefined ) { |
|
1753 itemObject.level = dataItem.level; |
|
1754 } |
|
1755 |
|
1756 if ( that.keyDataField ) { |
|
1757 if ( dataItem[ that.keyDataField ] !== undefined ) { |
|
1758 itemObject[ that.keyDataField ] = dataItem[ that.keyDataField ]; |
|
1759 } |
|
1760 } |
|
1761 |
|
1762 if ( that.parentDataField ) { |
|
1763 if ( dataItem[ that.parentDataField ] !== undefined ) { |
|
1764 itemObject[ that.parentDataField ] = dataItem[ that.parentDataField ]; |
|
1765 } |
|
1766 } |
|
1767 |
|
1768 if ( that.dataFields.length === 0 ) { |
|
1769 const names = Object.getOwnPropertyNames( dataSourceItem ); |
|
1770 |
|
1771 for ( let i = 0; i < names.length; i++ ) { |
|
1772 if ( names[ i ] === '$' ) { |
|
1773 continue; |
|
1774 } |
|
1775 |
|
1776 that.dataFields.push( { name: names[ i ], dataType: 'string' } ); |
|
1777 } |
|
1778 } |
|
1779 |
|
1780 for ( let j = 0; j < that.dataFields.length; j++ ) { |
|
1781 const dataField = that.dataFields ? that.dataFields[ j ] : {}; |
|
1782 let value = ''; |
|
1783 |
|
1784 dataField.dataType = dataField.type; |
|
1785 |
|
1786 if ( undefined === dataField || dataField === null ) { |
|
1787 continue; |
|
1788 } |
|
1789 |
|
1790 if ( dataSourceItem.length ) { |
|
1791 value = dataSourceItem[ j ]; |
|
1792 } |
|
1793 |
|
1794 if ( dataField.map ) { |
|
1795 let splitMap = dataField.map.split( that.mapChar ); |
|
1796 |
|
1797 if ( splitMap.length > 0 ) { |
|
1798 let dataMappedItem = dataItem; |
|
1799 |
|
1800 for ( let p = 0; p < splitMap.length; p++ ) { |
|
1801 if ( !dataItem ) { |
|
1802 continue; |
|
1803 } |
|
1804 |
|
1805 dataMappedItem = dataMappedItem[ splitMap[ p ] ]; |
|
1806 } |
|
1807 |
|
1808 value = dataMappedItem; |
|
1809 } |
|
1810 else { |
|
1811 value = dataItem[ dataField.map ]; |
|
1812 } |
|
1813 } |
|
1814 |
|
1815 if ( value !== undefined && value !== null ) { |
|
1816 value = value.toString(); |
|
1817 } |
|
1818 else { |
|
1819 if ( value === undefined && value !== null ) { |
|
1820 value = ''; |
|
1821 } |
|
1822 } |
|
1823 |
|
1824 |
|
1825 let isEmptyString = false; |
|
1826 // searches by both selectors when necessary. |
|
1827 if ( value === '' ) { |
|
1828 isEmptyString = true; |
|
1829 value = dataSourceItem[ dataField.name ]; |
|
1830 |
|
1831 if ( value !== undefined && value !== null ) { |
|
1832 if ( dataField.dataType !== 'array' ) { |
|
1833 if ( dataField.dataType !== 'date' ) { |
|
1834 value = value.toString(); |
|
1835 } |
|
1836 } |
|
1837 } |
|
1838 else { |
|
1839 value = ''; |
|
1840 } |
|
1841 } |
|
1842 |
|
1843 if ( value === '[object Object]' && dataField.map && isEmptyString ) { |
|
1844 value = ''; |
|
1845 } |
|
1846 |
|
1847 if ( that._cachedValues[ '' + value + '_' + dataField.dataType ] ) { |
|
1848 value = that._cachedValues[ '' + value + '_' + dataField.dataType ]; |
|
1849 } |
|
1850 else { |
|
1851 if ( dataField.dataType === 'bool' || dataField.dataType === 'boolean' ) { |
|
1852 if ( value === 'true' || value === '1' ) { |
|
1853 value = true; |
|
1854 } |
|
1855 else if ( value === 'false' || value === '0' ) { |
|
1856 value = false; |
|
1857 } |
|
1858 } |
|
1859 else { |
|
1860 value = that.deserialize( '' + value, dataField.dataType, true ); |
|
1861 } |
|
1862 |
|
1863 that._cachedValues[ value + '_' + dataField.dataType ] = value; |
|
1864 } |
|
1865 |
|
1866 if ( dataField.dataType !== 'string' && dataField.dataType !== 'boolean' && dataField.dataType !== 'bool' ) { |
|
1867 if ( isNaN( value ) || value === -Infinity || value === Infinity ) { |
|
1868 value = 0; |
|
1869 } |
|
1870 } |
|
1871 |
|
1872 itemObject[ dataField.name ] = value; |
|
1873 } |
|
1874 |
|
1875 let itemObjectId = index; |
|
1876 |
|
1877 if ( that.id ) { |
|
1878 itemObjectId = dataItem[ that.id ]; |
|
1879 if ( typeof ( itemObjectId ) === 'object' ) { |
|
1880 itemObjectId = index; |
|
1881 } |
|
1882 } |
|
1883 else if ( !that.virtualDataSource && that.dataItemById && that.dataItemById[ itemObjectId ] ) { |
|
1884 itemObjectId = that.length; |
|
1885 } |
|
1886 |
|
1887 if ( !itemObject.$ ) { |
|
1888 itemObject.$ = {}; |
|
1889 } |
|
1890 |
|
1891 itemObject.$.id = itemObjectId; |
|
1892 itemObject.$.index = index; |
|
1893 |
|
1894 return new Object( itemObject ); |
|
1895 } |
|
1896 |
|
1897 _bindToArray() { |
|
1898 const that = this; |
|
1899 |
|
1900 const unboundMode = typeof ( that.dataSource ) === 'number' || that.dataSourceLength; |
|
1901 const dataArray = []; |
|
1902 |
|
1903 that.boundSource.canNotify = false; |
|
1904 |
|
1905 for ( let i = 0; i < that.length; i++ ) { |
|
1906 const dataSourceItem = unboundMode ? {} : that.dataSource[ i ]; |
|
1907 const itemObject = that._getDataItem( dataSourceItem, i ); |
|
1908 |
|
1909 dataArray.push( itemObject ); |
|
1910 } |
|
1911 |
|
1912 if ( unboundMode && that.dataSourceLength && that.dataSource.length > 0 ) { |
|
1913 for ( let i = 0; i < that.dataSource.length; i++ ) { |
|
1914 const cell = that.dataSource[ i ].cell; |
|
1915 const value = that.dataSource[ i ].value; |
|
1916 |
|
1917 const row = cell.replace( /[^0-9]/g, '' ); |
|
1918 const dataField = cell.replace( /[0-9]/g, '' ); |
|
1919 |
|
1920 dataArray[ row - 1 ][ dataField ] = value; |
|
1921 } |
|
1922 } |
|
1923 |
|
1924 that.boundSource = dataArray; |
|
1925 |
|
1926 for ( let i = 0; i < that.length; i++ ) { |
|
1927 that[ i ] = that.boundSource[ i ]; |
|
1928 that.dataItemById[ that[ i ].$.id ] = that[ i ]; |
|
1929 } |
|
1930 |
|
1931 that.boundSource.canNotify = true; |
|
1932 } |
|
1933 |
|
1934 _bindToJSON() { |
|
1935 const that = this; |
|
1936 |
|
1937 const dataArray = []; |
|
1938 |
|
1939 const dataEntries = Object.entries( that.dataSource ); |
|
1940 |
|
1941 that.boundSource.canNotify = false; |
|
1942 |
|
1943 for ( let i = 0; i < dataEntries.length; i++ ) { |
|
1944 const dataSourceItem = dataEntries[ i ]; |
|
1945 const itemObject = that._getDataItem( dataSourceItem, i ); |
|
1946 |
|
1947 dataArray.push( itemObject ); |
|
1948 } |
|
1949 |
|
1950 that.boundSource = false === that.observable ? dataArray : new JQX.ObservableArray( dataArray ); |
|
1951 |
|
1952 for ( let i = 0; i < that.length; i++ ) { |
|
1953 that[ i ] = that.boundSource[ i ]; |
|
1954 that.dataItemById[ that[ i ].$.id ] = that[ i ]; |
|
1955 } |
|
1956 |
|
1957 that.boundSource.canNotify = true; |
|
1958 } |
|
1959 |
|
1960 sortBy( dataField, dataType, orderBy ) { |
|
1961 const that = this; |
|
1962 |
|
1963 if ( !dataType ) { |
|
1964 for ( let i = 0; i < that.dataFields.length; i++ ) { |
|
1965 const field = that.dataFields[ i ]; |
|
1966 |
|
1967 if ( field.name === dataField ) { |
|
1968 dataType = field.dataType; |
|
1969 break; |
|
1970 } |
|
1971 } |
|
1972 } |
|
1973 |
|
1974 if ( that.boundHierarchy ) { |
|
1975 if ( ( !dataField || dataField.length === 0 ) && that.groupBy.length > 0 ) { |
|
1976 that.refreshHierarchy(); |
|
1977 return; |
|
1978 } |
|
1979 |
|
1980 const sortBy = function ( hierarchy ) { |
|
1981 that._sort( hierarchy, dataField, orderBy, dataType ); |
|
1982 |
|
1983 for ( let i = 0; i < hierarchy.length; i++ ) { |
|
1984 const item = hierarchy[ i ]; |
|
1985 |
|
1986 if ( item[ 'children' ] ) { |
|
1987 sortBy( item[ 'children' ], dataField, orderBy, dataType ); |
|
1988 } |
|
1989 } |
|
1990 } |
|
1991 |
|
1992 sortBy( that.boundHierarchy ); |
|
1993 } |
|
1994 else { |
|
1995 that._sort( that.boundSource, dataField, orderBy, dataType ); |
|
1996 } |
|
1997 } |
|
1998 |
|
1999 _createFilter( dataType, filterExpressions ) { |
|
2000 const filterOperators = { |
|
2001 '=': 'EQUAL', |
|
2002 '<>': 'NOT_EQUAL', |
|
2003 '<': 'LESS_THAN', |
|
2004 '>': 'GREATER_THAN', |
|
2005 '<=': 'LESS_THAN_OR_EQUAL', |
|
2006 '>=': 'GREATER_THAN_OR_EQUAL', |
|
2007 'equal': 'EQUAL', |
|
2008 'not equal': 'NOT_EQUAL', |
|
2009 'less than': 'LESS_THAN', |
|
2010 'greater than': 'GREATER_THAN', |
|
2011 'greater than or equal': 'GREATER_THAN_OR_EQUAL', |
|
2012 'less than or equal': 'LESS_THAN_OR_EQUAL', |
|
2013 'starts with': 'STARTS_WITH', |
|
2014 'ends with': 'ENDS_WITH', |
|
2015 'null': 'null', |
|
2016 '': 'EMPTY', |
|
2017 'isblank': 'EMPTY', |
|
2018 'isnotblank': 'NOT_EMPTY', |
|
2019 'contains': 'CONTAINS', |
|
2020 'notcontains': 'DOES_NOT_CONTAIN', |
|
2021 'startswith': 'STARTS_WITH', |
|
2022 'endswith': 'ENDS_WITH', |
|
2023 'NULL': 'NULL', |
|
2024 'NOT_NULL': 'NOT_NULL' |
|
2025 }; |
|
2026 |
|
2027 let filterExpressionsArray = []; |
|
2028 |
|
2029 for ( let i = 0; i < filterExpressions.length; i++ ) { |
|
2030 const filterExpression = filterExpressions[ i ]; |
|
2031 |
|
2032 const filterExpressionParts = filterExpression.indexOf( '"' ) === -1 ? filterExpression.split( ' ' ) : filterExpression.split( '"' ); |
|
2033 let filter = []; |
|
2034 |
|
2035 for ( let j = 0; j < filterExpressionParts.length; j++ ) { |
|
2036 const part = filterExpressionParts[ j ]; |
|
2037 |
|
2038 if ( part !== '' ) { |
|
2039 filter.push( part.trim() ); |
|
2040 } |
|
2041 } |
|
2042 |
|
2043 filterExpressionsArray.push( filter ); |
|
2044 } |
|
2045 |
|
2046 const filterGroup = new JQX.FilterGroup(); |
|
2047 const filterGroupOperators = []; |
|
2048 const filterSubGroups = []; |
|
2049 |
|
2050 for ( let i = 0; i < filterExpressionsArray.length; i++ ) { |
|
2051 const filterExpression = filterExpressionsArray[ i ]; |
|
2052 |
|
2053 |
|
2054 if ( filterExpression.length > 1 ) { |
|
2055 const filterSubGroup = new JQX.FilterGroup(); |
|
2056 |
|
2057 let operator = 'and'; |
|
2058 let filterExpressionPartsCounter = 0; |
|
2059 |
|
2060 for ( let j = 0; j < filterExpression.length; j++ ) { |
|
2061 const value = filterExpression[ j ]; |
|
2062 |
|
2063 if ( value === 'and' || value === 'or' ) { |
|
2064 operator = value; |
|
2065 continue; |
|
2066 } |
|
2067 |
|
2068 filterExpressionPartsCounter++; |
|
2069 |
|
2070 if ( filterExpressionPartsCounter === 2 ) { |
|
2071 const filter = filterSubGroup.createFilter( dataType, value, filterOperators[ filterExpression[ j - 1 ] ] ); |
|
2072 |
|
2073 filterExpressionPartsCounter = 0; |
|
2074 |
|
2075 if ( operator ) { |
|
2076 filterSubGroup.addFilter( operator, filter ); |
|
2077 } |
|
2078 } |
|
2079 } |
|
2080 |
|
2081 filterSubGroups.push( filterSubGroup ); |
|
2082 } |
|
2083 else { |
|
2084 const filterGroupOperator = filterExpression[ 0 ]; |
|
2085 |
|
2086 if ( filterGroupOperator !== 'and' && filterGroupOperator !== 'or' ) { |
|
2087 throw new Error( 'Filter Exprresion expects "AND" or "OR", but the token is: ' + filterGroupOperator ); |
|
2088 } |
|
2089 |
|
2090 filterGroupOperators.push( filterGroupOperator ); |
|
2091 } |
|
2092 } |
|
2093 |
|
2094 let operatorsCounter = 0; |
|
2095 |
|
2096 if ( filterSubGroups.length === 1 ) { |
|
2097 return filterSubGroups[ 0 ]; |
|
2098 } |
|
2099 |
|
2100 for ( let i = 0; i < filterSubGroups.length; i++ ) { |
|
2101 let operator = filterGroupOperators[ operatorsCounter ]; |
|
2102 |
|
2103 if ( ( i + 1 ) % 2 === 0 ) { |
|
2104 operatorsCounter++; |
|
2105 } |
|
2106 |
|
2107 if ( !operator ) { |
|
2108 operator = 'and'; |
|
2109 } |
|
2110 |
|
2111 filterGroup.addFilter( operator, filterSubGroups[ i ] ); |
|
2112 } |
|
2113 |
|
2114 return filterGroup; |
|
2115 } |
|
2116 |
|
2117 filterBy( dataField, ...filterExpressions ) { |
|
2118 const that = this; |
|
2119 |
|
2120 |
|
2121 const dataType = ( () => { |
|
2122 for ( let i = 0; i < that.dataFields.length; i++ ) { |
|
2123 const field = that.dataFields[ i ]; |
|
2124 |
|
2125 if ( field.name === dataField ) { |
|
2126 return field.dataType; |
|
2127 } |
|
2128 } |
|
2129 } )(); |
|
2130 |
|
2131 |
|
2132 const filterGroup = that._createFilter( dataType, filterExpressions ); |
|
2133 |
|
2134 let filteredData = that.boundSource.filter( ( value ) => { |
|
2135 const evaluation = filterGroup.evaluate( value[ dataField ] ); |
|
2136 |
|
2137 return evaluation; |
|
2138 } ); |
|
2139 |
|
2140 return filteredData; |
|
2141 } |
|
2142 |
|
2143 _filter( filters, operator = 'and' ) { |
|
2144 const that = this; |
|
2145 const filterGroups = []; |
|
2146 const dataFields = []; |
|
2147 |
|
2148 if ( filters.length === 0 ) { |
|
2149 that.clearFilter(); |
|
2150 return; |
|
2151 } |
|
2152 |
|
2153 const dataType = ( dataField ) => { |
|
2154 for ( let i = 0; i < that.dataFields.length; i++ ) { |
|
2155 const field = that.dataFields[ i ]; |
|
2156 |
|
2157 if ( field.name === dataField ) { |
|
2158 return field.dataType; |
|
2159 } |
|
2160 } |
|
2161 }; |
|
2162 let defaultResult, operatorSpecificEval; |
|
2163 |
|
2164 if ( operator === 'and' ) { |
|
2165 defaultResult = true; |
|
2166 operatorSpecificEval = function ( result, filterGroup, row ) { |
|
2167 return result && filterGroup.evaluate( row[ filterGroup.dataField ] ); |
|
2168 }; |
|
2169 } |
|
2170 else { |
|
2171 defaultResult = false; |
|
2172 operatorSpecificEval = function ( result, filterGroup, row ) { |
|
2173 return result || filterGroup.evaluate( row[ filterGroup.dataField ] ); |
|
2174 }; |
|
2175 } |
|
2176 |
|
2177 for ( let i = 0; i < filters.length; i++ ) { |
|
2178 const filter = filters[ i ]; |
|
2179 const dataField = filter[ 0 ]; |
|
2180 let filterGroup = null; |
|
2181 |
|
2182 if ( filter[ 1 ] instanceof JQX.FilterGroup ) { |
|
2183 filterGroup = filter[ 1 ]; |
|
2184 } |
|
2185 else { |
|
2186 filterGroup = that._createFilter( dataType( dataField ), filter.splice( 1 ) ); |
|
2187 } |
|
2188 |
|
2189 if ( filterGroup ) { |
|
2190 dataFields.push( dataField ); |
|
2191 filterGroup.dataField = dataField; |
|
2192 filterGroups.push( filterGroup ); |
|
2193 } |
|
2194 } |
|
2195 |
|
2196 if ( that.boundHierarchy ) { |
|
2197 const filter = function ( row ) { |
|
2198 let result = defaultResult; |
|
2199 |
|
2200 for ( let j = 0; j < filterGroups.length; j++ ) { |
|
2201 const filterGroup = filterGroups[ j ]; |
|
2202 |
|
2203 result = operatorSpecificEval( result, filterGroup, row ); |
|
2204 } |
|
2205 |
|
2206 row.$.filtered = result; |
|
2207 |
|
2208 return result; |
|
2209 } |
|
2210 |
|
2211 const filterBy = function ( hierarchy, parentItem, root ) { |
|
2212 let filteredCount = 0; |
|
2213 |
|
2214 for ( let i = 0; i < hierarchy.length; i++ ) { |
|
2215 const item = hierarchy[ i ]; |
|
2216 |
|
2217 filter( item ); |
|
2218 |
|
2219 if ( item.$.filtered ) { |
|
2220 filteredCount++; |
|
2221 } |
|
2222 |
|
2223 if ( item[ 'children' ] ) { |
|
2224 filterBy( item[ 'children' ], item, parentItem ); |
|
2225 } |
|
2226 } |
|
2227 |
|
2228 if ( filteredCount > 0 && that.groupBy.length > 0 && parentItem ) { |
|
2229 parentItem.$.filtered = true; |
|
2230 |
|
2231 if ( root && !root.$.filtered ) { |
|
2232 root.$.filtered = true; |
|
2233 } |
|
2234 } |
|
2235 else { |
|
2236 if ( filteredCount > 0 && filteredCount !== hierarchy.length && parentItem ) { |
|
2237 parentItem.$.filtered = null; |
|
2238 |
|
2239 if ( root && !root.$.filtered ) { |
|
2240 root.$.filtered = null; |
|
2241 } |
|
2242 } |
|
2243 } |
|
2244 } |
|
2245 |
|
2246 filterBy( that.boundHierarchy, null, null ); |
|
2247 } |
|
2248 else { |
|
2249 for ( let i = 0; i < that.boundSource.length; i++ ) { |
|
2250 const row = that.boundSource[ i ]; |
|
2251 |
|
2252 let result = defaultResult; |
|
2253 |
|
2254 for ( let j = 0; j < filterGroups.length; j++ ) { |
|
2255 const filterGroup = filterGroups[ j ]; |
|
2256 |
|
2257 result = operatorSpecificEval( result, filterGroup, row ); |
|
2258 } |
|
2259 |
|
2260 row.$.filtered = result; |
|
2261 } |
|
2262 } |
|
2263 |
|
2264 if ( that.onFilter ) { |
|
2265 that.onFilter() |
|
2266 } |
|
2267 } |
|
2268 |
|
2269 clearGroup() { |
|
2270 const that = this; |
|
2271 |
|
2272 that.groupBy = []; |
|
2273 that.boundHierarchy = null; |
|
2274 that.refreshHierarchy(); |
|
2275 |
|
2276 if ( that.onGroup ) { |
|
2277 that.onGroup() |
|
2278 } |
|
2279 } |
|
2280 |
|
2281 clearFilter() { |
|
2282 const that = this; |
|
2283 |
|
2284 for ( let i = 0; i < that.boundSource.length; i++ ) { |
|
2285 const row = that.boundSource[ i ]; |
|
2286 |
|
2287 row.$.filtered = true; |
|
2288 } |
|
2289 |
|
2290 if ( that.boundHierarchy ) { |
|
2291 const filterBy = function ( hierarchy, parentItem, root ) { |
|
2292 //let filteredCount = 0; |
|
2293 |
|
2294 for ( let i = 0; i < hierarchy.length; i++ ) { |
|
2295 const item = hierarchy[ i ]; |
|
2296 |
|
2297 item.$.filtered = true; |
|
2298 |
|
2299 if ( item.$.filtered ) { |
|
2300 //filteredCount++; |
|
2301 } |
|
2302 |
|
2303 if ( item[ 'children' ] ) { |
|
2304 filterBy( item[ 'children' ], item, parentItem ); |
|
2305 } |
|
2306 } |
|
2307 |
|
2308 if ( parentItem ) { |
|
2309 parentItem.$.filtered = true; |
|
2310 |
|
2311 if ( root && !root.$.filtered ) { |
|
2312 root.$.filtered = true; |
|
2313 } |
|
2314 } |
|
2315 } |
|
2316 |
|
2317 filterBy( that.boundHierarchy, null, null ); |
|
2318 } |
|
2319 |
|
2320 if ( that.onFilter ) { |
|
2321 that.onFilter() |
|
2322 } |
|
2323 } |
|
2324 |
|
2325 clearSort() { |
|
2326 const that = this; |
|
2327 |
|
2328 that._sort( that.boundSource, [], [], [] ); |
|
2329 } |
|
2330 |
|
2331 _sort( dataSource, sortColumns, directions, dataTypes, customSortingCallback ) { |
|
2332 const that = this; |
|
2333 |
|
2334 let isObservableArray = false; |
|
2335 |
|
2336 if ( dataSource.length === 0 ) { |
|
2337 return; |
|
2338 } |
|
2339 |
|
2340 if ( dataSource && dataSource.constructor && dataSource instanceof JQX.ObservableArray ) { |
|
2341 isObservableArray = true; |
|
2342 } |
|
2343 |
|
2344 if ( !dataSource || !( Array.isArray( dataSource ) ) || dataSource.length === 0 || |
|
2345 !sortColumns || Array.isArray( sortColumns ) && sortColumns.length === 0 ) { |
|
2346 if ( !isObservableArray && !that.boundHierarchy ) { |
|
2347 throw new Error( 'sort: Missing or Invalid arguments!' ); |
|
2348 } |
|
2349 } |
|
2350 |
|
2351 if ( typeof sortColumns === 'string' ) { |
|
2352 sortColumns = [ sortColumns ]; |
|
2353 } |
|
2354 |
|
2355 const directionCoefficients = [], |
|
2356 compareFunctions = []; |
|
2357 |
|
2358 if ( directions === undefined ) { |
|
2359 directions = []; |
|
2360 } |
|
2361 |
|
2362 const getCompareFunction = function ( a, knownDataType ) { |
|
2363 // gets data type of column (not necessary if the Grid provides this information) |
|
2364 const dataType = knownDataType || typeof a; |
|
2365 let compareFunction; |
|
2366 |
|
2367 switch ( dataType ) { |
|
2368 case 'string': |
|
2369 compareFunction = new Intl.Collator().compare; |
|
2370 break; |
|
2371 case 'number': |
|
2372 compareFunction = function ( a, b ) { |
|
2373 return a - b; |
|
2374 }; |
|
2375 break; |
|
2376 case 'boolean': |
|
2377 case 'bool': |
|
2378 compareFunction = function ( a, b ) { |
|
2379 if ( a === b ) { |
|
2380 return 0; |
|
2381 } |
|
2382 else if ( a === false ) { |
|
2383 return -1; |
|
2384 } |
|
2385 else { |
|
2386 return 1; |
|
2387 } |
|
2388 }; |
|
2389 break; |
|
2390 case 'date': |
|
2391 case 'time': |
|
2392 case 'dateTime': |
|
2393 if ( a instanceof Date ) { |
|
2394 compareFunction = function ( a, b ) { |
|
2395 return a.getTime() - b.getTime(); |
|
2396 }; |
|
2397 } |
|
2398 else if ( a instanceof JQX.Utilities.DateTime || |
|
2399 a instanceof JQX.Utilities.BigNumber ) { |
|
2400 compareFunction = function ( a, b ) { |
|
2401 return a.compare( b ); |
|
2402 }; |
|
2403 } |
|
2404 break; |
|
2405 case 'object': |
|
2406 if ( a instanceof Date ) { |
|
2407 compareFunction = function ( a, b ) { |
|
2408 return a.getTime() - b.getTime(); |
|
2409 }; |
|
2410 } |
|
2411 else if ( a instanceof JQX.Utilities.DateTime || |
|
2412 a instanceof JQX.Utilities.BigNumber ) { |
|
2413 compareFunction = function ( a, b ) { |
|
2414 return a.compare( b ); |
|
2415 }; |
|
2416 } |
|
2417 else if ( a instanceof JQX.Utilities.Complex || ( window.NIComplex && a instanceof window.NIComplex ) ) { |
|
2418 const complexNumericProcessor = new JQX.Utilities.ComplexNumericProcessor(); |
|
2419 |
|
2420 compareFunction = function ( a, b ) { |
|
2421 return complexNumericProcessor.compareComplexNumbers( a, b ); |
|
2422 } |
|
2423 } |
|
2424 |
|
2425 break; |
|
2426 } |
|
2427 |
|
2428 return compareFunction; |
|
2429 } |
|
2430 |
|
2431 for ( let i = 0; i < sortColumns.length; i++ ) { |
|
2432 if ( directions[ i ] === undefined || directions[ i ] === 'asc' || directions[ i ] === 'ascending' ) { |
|
2433 directionCoefficients[ i ] = 1; |
|
2434 } |
|
2435 else { |
|
2436 directionCoefficients[ i ] = -1; |
|
2437 } |
|
2438 |
|
2439 const value = dataSource[ 0 ][ sortColumns[ i ] ]; |
|
2440 |
|
2441 compareFunctions[ i ] = getCompareFunction( value, dataTypes[ i ] ); |
|
2442 } |
|
2443 |
|
2444 if ( customSortingCallback ) { |
|
2445 customSortingCallback( dataSource, sortColumns, directions, compareFunctions ); |
|
2446 return; |
|
2447 } |
|
2448 |
|
2449 dataSource.sort( function ( a, b ) { |
|
2450 for ( let i = 0; i < sortColumns.length; i++ ) { |
|
2451 const result = compareFunctions[ i ]( a[ sortColumns[ i ] ], b[ sortColumns[ i ] ] ); |
|
2452 |
|
2453 if ( result === 0 ) { |
|
2454 if ( sortColumns[ i + 1 ] ) { |
|
2455 continue; |
|
2456 } |
|
2457 else if ( a._index !== undefined ) { |
|
2458 // makes sorting stable |
|
2459 return ( a._index - b._index ) * directionCoefficients[ i ]; |
|
2460 } |
|
2461 |
|
2462 return 0; |
|
2463 } |
|
2464 |
|
2465 return result * directionCoefficients[ i ]; |
|
2466 } |
|
2467 |
|
2468 if ( sortColumns.length === 0 ) { |
|
2469 if ( a.$.index < b.$.index ) { |
|
2470 return -1; |
|
2471 } |
|
2472 |
|
2473 if ( a.$.index > b.$.index ) { |
|
2474 return 1; |
|
2475 } |
|
2476 |
|
2477 return 0; |
|
2478 |
|
2479 } |
|
2480 } ); |
|
2481 |
|
2482 for ( let i = 0; i < dataSource.length; i++ ) { |
|
2483 that[ i ] = dataSource[ i ]; |
|
2484 } |
|
2485 } |
|
2486 |
|
2487 static Filter( dataSource, filterColumns, filterGroups, customFilteringCallback, operator = 'and' ) { |
|
2488 let defaultResult, operatorSpecificEval; |
|
2489 |
|
2490 if ( operator === 'and' ) { |
|
2491 defaultResult = true; |
|
2492 operatorSpecificEval = function ( result, dataItem, filterColumn, filterGroup ) { |
|
2493 if ( customFilteringCallback ) { |
|
2494 return result && customFilteringCallback( dataItem, filterColumn, filterGroup ); |
|
2495 } |
|
2496 |
|
2497 return result && filterGroup.evaluate( dataItem[ filterColumn ] ); |
|
2498 }; |
|
2499 } |
|
2500 else { |
|
2501 defaultResult = false; |
|
2502 operatorSpecificEval = function ( result, dataItem, filterColumn, filterGroup ) { |
|
2503 if ( customFilteringCallback ) { |
|
2504 return result || customFilteringCallback( dataItem, filterColumn, filterGroup ); |
|
2505 } |
|
2506 |
|
2507 return result || filterGroup.evaluate( dataItem[ filterColumn ] ); |
|
2508 }; |
|
2509 } |
|
2510 |
|
2511 const filteredData = dataSource.filter( ( dataItem ) => { |
|
2512 let result = defaultResult; |
|
2513 |
|
2514 for ( let i = 0; i < filterGroups.length; i++ ) { |
|
2515 const filterGroup = filterGroups[ i ]; |
|
2516 const filterColumn = filterColumns[ i ]; |
|
2517 |
|
2518 result = operatorSpecificEval( result, dataItem, filterColumn, filterGroup ); |
|
2519 } |
|
2520 |
|
2521 return result; |
|
2522 } ); |
|
2523 |
|
2524 return filteredData; |
|
2525 } |
|
2526 |
|
2527 filter( filterColumns, filterGroups, customFilteringCallback ) { |
|
2528 JQX.ExcelAdapter.Filter( this.boundSource, filterColumns, filterGroups, customFilteringCallback ); |
|
2529 } |
|
2530 |
|
2531 sort( sortColumns, directions, customSortingCallback ) { |
|
2532 JQX.ExcelAdapter.Sort( this.boundSource, sortColumns, directions, customSortingCallback ); |
|
2533 } |
|
2534 |
|
2535 static Sort( dataSource, sortColumns, directions, customSortingCallback ) { |
|
2536 const getCompareFunction = function ( a ) { |
|
2537 // gets data type of column (not necessary if the Grid provides this information) |
|
2538 const dataType = typeof a; |
|
2539 let compareFunction; |
|
2540 |
|
2541 switch ( dataType ) { |
|
2542 case 'string': |
|
2543 compareFunction = new Intl.Collator().compare; |
|
2544 break; |
|
2545 case 'number': |
|
2546 compareFunction = function ( a, b ) { |
|
2547 return a - b; |
|
2548 }; |
|
2549 break; |
|
2550 case 'boolean': |
|
2551 compareFunction = function ( a, b ) { |
|
2552 if ( a === b ) { |
|
2553 return 0; |
|
2554 } |
|
2555 else if ( a === false ) { |
|
2556 return -1; |
|
2557 } |
|
2558 else { |
|
2559 return 1; |
|
2560 } |
|
2561 }; |
|
2562 break; |
|
2563 case 'object': |
|
2564 if ( a instanceof Date ) { |
|
2565 compareFunction = function ( a, b ) { |
|
2566 return a.getTime() - b.getTime(); |
|
2567 }; |
|
2568 } |
|
2569 else if ( a instanceof JQX.Utilities.DateTime || |
|
2570 a instanceof BigNumberNG ) { |
|
2571 compareFunction = function ( a, b ) { |
|
2572 return a.compare( b ); |
|
2573 }; |
|
2574 } |
|
2575 else if ( a instanceof JQX.Utilities.Complex || ( window.NIComplex && a instanceof window.NIComplex ) ) { |
|
2576 const complexNumericProcessor = new JQX.Utilities.ComplexNumericProcessor(); |
|
2577 |
|
2578 compareFunction = function ( a, b ) { |
|
2579 return complexNumericProcessor.compareComplexNumbers( a, b ); |
|
2580 } |
|
2581 } |
|
2582 |
|
2583 break; |
|
2584 } |
|
2585 |
|
2586 return compareFunction; |
|
2587 } |
|
2588 |
|
2589 if ( !dataSource || !( Array.isArray( dataSource ) ) || dataSource.length === 0 || |
|
2590 !sortColumns || Array.isArray( sortColumns ) && sortColumns.length === 0 ) { |
|
2591 return; |
|
2592 } |
|
2593 |
|
2594 if ( typeof sortColumns === 'string' ) { |
|
2595 sortColumns = [ sortColumns ]; |
|
2596 } |
|
2597 |
|
2598 const directionCoefficients = [], |
|
2599 compareFunctions = []; |
|
2600 |
|
2601 if ( directions === undefined ) { |
|
2602 directions = []; |
|
2603 } |
|
2604 |
|
2605 for ( let i = 0; i < sortColumns.length; i++ ) { |
|
2606 if ( directions[ i ] === undefined || directions[ i ] === 'asc' || directions[ i ] === 'ascending' ) { |
|
2607 directionCoefficients[ i ] = 1; |
|
2608 } |
|
2609 else { |
|
2610 directionCoefficients[ i ] = -1; |
|
2611 } |
|
2612 |
|
2613 compareFunctions[ i ] = getCompareFunction( dataSource[ 0 ][ sortColumns[ i ] ] ); |
|
2614 } |
|
2615 |
|
2616 if ( customSortingCallback ) { |
|
2617 customSortingCallback( dataSource, sortColumns, directions, compareFunctions ); |
|
2618 return; |
|
2619 } |
|
2620 |
|
2621 const sortedData = dataSource.slice( 0 ); |
|
2622 |
|
2623 sortedData.sort( function ( a, b ) { |
|
2624 for ( let i = 0; i < sortColumns.length; i++ ) { |
|
2625 const result = compareFunctions[ i ]( a[ sortColumns[ i ] ], b[ sortColumns[ i ] ] ); |
|
2626 |
|
2627 if ( result === 0 ) { |
|
2628 if ( sortColumns[ i + 1 ] ) { |
|
2629 continue; |
|
2630 } |
|
2631 else if ( a._index !== undefined ) { |
|
2632 // makes sorting stable |
|
2633 return ( a._index - b._index ) * directionCoefficients[ i ]; |
|
2634 } |
|
2635 |
|
2636 return 0; |
|
2637 } |
|
2638 |
|
2639 return result * directionCoefficients[ i ]; |
|
2640 } |
|
2641 } ); |
|
2642 |
|
2643 return sortedData; |
|
2644 } |
|
2645 } |
|
2646 |
|
2647 window.jqxDataSource = DataAdapter; |
|
2648 |
|
2649 class Ajax { |
|
2650 constructor ( config, callback ) { |
|
2651 const that = this; |
|
2652 |
|
2653 that.config = config; |
|
2654 that.callback = callback; |
|
2655 |
|
2656 if ( config.autoFetch === false ) { |
|
2657 return; |
|
2658 } |
|
2659 |
|
2660 that.call( config ); |
|
2661 } |
|
2662 |
|
2663 call( config ) { |
|
2664 const that = this; |
|
2665 |
|
2666 if ( !config ) { |
|
2667 config = that.config; |
|
2668 } |
|
2669 |
|
2670 let method = 'GET', |
|
2671 url = config.url, |
|
2672 body = null, |
|
2673 async = true; |
|
2674 |
|
2675 if ( config.type ) { |
|
2676 method = config.type; |
|
2677 } |
|
2678 |
|
2679 if ( config.data ) { |
|
2680 if ( method === 'GET' ) { |
|
2681 url += '?'; |
|
2682 |
|
2683 for ( let prop in config.data ) { |
|
2684 if ( config.data.hasOwnProperty( prop ) ) { |
|
2685 url += encodeURI( prop + '=' + config.data[ prop ] + '&' ); |
|
2686 } |
|
2687 } |
|
2688 |
|
2689 if ( url.charAt( url.length - 1 ) === '&' ) { |
|
2690 url = url.slice( 0, url.length - 1 ); |
|
2691 } |
|
2692 } |
|
2693 else if ( method === 'POST' ) { |
|
2694 body = JSON.stringify( config.data ); |
|
2695 } |
|
2696 } |
|
2697 |
|
2698 if ( config && config.async === false && config.dataSourceType !== 'xlsx' ) { |
|
2699 async = false; |
|
2700 } |
|
2701 |
|
2702 if ( window.fetch !== undefined && async ) { |
|
2703 that.ajaxFetch( config, method, url, body ); |
|
2704 } |
|
2705 else { |
|
2706 that.ajaxXMLHttpRequest( config, method, url, body, async ); |
|
2707 } |
|
2708 } |
|
2709 |
|
2710 ajaxFetch( config, method, url, body ) { |
|
2711 // prepare fetch config |
|
2712 const that = this; |
|
2713 const fetchInit = { method: method }; |
|
2714 let parseMethod; |
|
2715 |
|
2716 switch ( config.dataSourceType ) { |
|
2717 case 'json': |
|
2718 parseMethod = 'json'; |
|
2719 break; |
|
2720 case 'xlsx': |
|
2721 parseMethod = 'arrayBuffer'; |
|
2722 break; |
|
2723 default: |
|
2724 parseMethod = 'text'; |
|
2725 } |
|
2726 |
|
2727 if ( config ) { |
|
2728 if ( config.contentType ) { |
|
2729 fetchInit.headers = new Headers( { |
|
2730 'Content-Type': config.contentType |
|
2731 } ); |
|
2732 } |
|
2733 } |
|
2734 |
|
2735 if ( body !== null ) { |
|
2736 fetchInit.body = body; |
|
2737 } |
|
2738 |
|
2739 let status, fetchTimeout, timeouted; |
|
2740 |
|
2741 if ( config.timeout ) { |
|
2742 fetchTimeout = setTimeout( function () { |
|
2743 timeouted = true; |
|
2744 }, config.timeout ); |
|
2745 } |
|
2746 |
|
2747 if ( config.beforeSend ) { |
|
2748 const beforeSendResult = config.beforeSend( fetchInit, config ); |
|
2749 |
|
2750 if ( beforeSendResult === false ) { |
|
2751 return; |
|
2752 } |
|
2753 } |
|
2754 |
|
2755 // fetch resource |
|
2756 fetch( url, fetchInit ) |
|
2757 .then( function ( response ) { |
|
2758 if ( timeouted ) { |
|
2759 status = 408; |
|
2760 throw new Error( 'timeout' ); |
|
2761 } |
|
2762 |
|
2763 if ( fetchTimeout ) { |
|
2764 clearTimeout( fetchTimeout ); |
|
2765 } |
|
2766 |
|
2767 status = response.status; |
|
2768 |
|
2769 if ( !response.ok ) { |
|
2770 throw new Error( response.statusText ); |
|
2771 } |
|
2772 |
|
2773 return response[ parseMethod ](); |
|
2774 } ) |
|
2775 .then( function ( data ) { |
|
2776 if ( parseMethod === 'arrayBuffer' ) { |
|
2777 return JSZip.loadAsync( data ).then( function ( zipData ) { |
|
2778 // "data" represents the whole XLSX/ZIP file |
|
2779 return zipData.files[ 'xl/worksheets/sheet1.xml' ].async( 'text' ).then( function ( sheet1 ) { |
|
2780 return zipData.files[ 'xl/sharedStrings.xml' ].async( 'text' ).then( function ( sharedStrings ) { |
|
2781 const parsedData = that.parseXLSXData( sheet1, sharedStrings ); |
|
2782 |
|
2783 that.ajaxComplete( config, parsedData, status ); |
|
2784 } ); |
|
2785 } ); |
|
2786 } ); |
|
2787 } |
|
2788 else { |
|
2789 that.ajaxComplete( config, data, status ); |
|
2790 } |
|
2791 } ) |
|
2792 .catch( function ( error ) { |
|
2793 if ( error.message === 'JSZip is not defined' ) { |
|
2794 error.message = 'JSZip is not defined. Please include a reference to JSZip to be able to load data from XLSX files.'; |
|
2795 } |
|
2796 |
|
2797 if ( config && config.loadError ) { |
|
2798 config.loadError( status, error ); |
|
2799 } |
|
2800 |
|
2801 if ( that.callback ) { |
|
2802 that.callback( error, status ); |
|
2803 } |
|
2804 } ); |
|
2805 } |
|
2806 |
|
2807 ajaxXMLHttpRequest( config, method, url, body, async ) { |
|
2808 const request = new XMLHttpRequest(); |
|
2809 const that = this; |
|
2810 |
|
2811 request.open( method, url, async ); |
|
2812 |
|
2813 request.ontimeout = function () { |
|
2814 if ( config && config.loadError ) { |
|
2815 config.loadError( 408, 'timeout' ); |
|
2816 } |
|
2817 }; |
|
2818 |
|
2819 request.onload = function () { |
|
2820 if ( request.readyState === 4 ) { |
|
2821 const status = request.status; |
|
2822 let data = request.response; |
|
2823 |
|
2824 if ( status >= 200 && status <= 299 ) { |
|
2825 if ( config.dataSourceType === 'json' ) { |
|
2826 data = JSON.parse( data ); |
|
2827 } |
|
2828 |
|
2829 that.ajaxComplete( config, data, status ); |
|
2830 } |
|
2831 else if ( config && config.loadError ) { |
|
2832 config.loadError( status, data ); |
|
2833 } |
|
2834 } |
|
2835 }; |
|
2836 |
|
2837 request.onerror = function () { |
|
2838 if ( config && config.loadError ) { |
|
2839 config.loadError( request.status, request.response ); |
|
2840 } |
|
2841 }; |
|
2842 |
|
2843 if ( config && config.contentType ) { |
|
2844 request.setRequestHeader( 'Content-Type', config.contentType ); |
|
2845 } |
|
2846 |
|
2847 if ( async && config.timeout ) { |
|
2848 request.timeout = config.timeout; |
|
2849 } |
|
2850 |
|
2851 if ( config.beforeSend ) { |
|
2852 const beforeSendResult = config.beforeSend( request, config ); |
|
2853 |
|
2854 if ( beforeSendResult === false ) { |
|
2855 return; |
|
2856 } |
|
2857 } |
|
2858 |
|
2859 request.send( body ); |
|
2860 } |
|
2861 |
|
2862 ajaxComplete( config, data, status ) { |
|
2863 if ( !config ) { |
|
2864 return; |
|
2865 } |
|
2866 |
|
2867 if ( config.beforeLoadComplete ) { |
|
2868 const processedData = config.beforeLoadComplete( data ); |
|
2869 |
|
2870 if ( processedData ) { |
|
2871 data = processedData; |
|
2872 } |
|
2873 } |
|
2874 |
|
2875 if ( config.loadComplete ) { |
|
2876 config.loadComplete( data, status ); |
|
2877 } |
|
2878 |
|
2879 if ( this.callback ) { |
|
2880 this.callback( data, status ); |
|
2881 } |
|
2882 } |
|
2883 |
|
2884 parseXLSXData( sheet1, sharedStrings ) { |
|
2885 const parser = new DOMParser(), |
|
2886 sharedStringsDocument = parser.parseFromString( sharedStrings, 'text/xml' ), |
|
2887 sharedStringsContainers = Array.from( sharedStringsDocument.getElementsByTagName( 'si' ) ), |
|
2888 sharedStringsCollection = [], |
|
2889 sheet1Document = parser.parseFromString( sheet1, 'text/xml' ), |
|
2890 rows = Array.from( sheet1Document.getElementsByTagName( 'row' ) ), |
|
2891 parsedData = []; |
|
2892 |
|
2893 sharedStringsContainers.forEach( function ( si ) { |
|
2894 let texts = si.getElementsByTagName( 't' ); |
|
2895 |
|
2896 if ( texts.length === 1 ) { |
|
2897 sharedStringsCollection.push( texts[ 0 ].innerHTML ); |
|
2898 } |
|
2899 else { |
|
2900 let text = ''; |
|
2901 |
|
2902 texts = Array.from( texts ); |
|
2903 texts.forEach( function ( t ) { |
|
2904 text += t.innerHTML; |
|
2905 } ); |
|
2906 sharedStringsCollection.push( text ); |
|
2907 } |
|
2908 } ); |
|
2909 |
|
2910 rows.forEach( function ( row ) { |
|
2911 const rowObject = {}, |
|
2912 cells = Array.from( row.getElementsByTagName( 'c' ) ); |
|
2913 |
|
2914 cells.forEach( function ( cell/*, index*/ ) { |
|
2915 const column = cell.getAttribute( 'r' ).match( /\D+/ )[ 0 ], |
|
2916 type = cell.getAttribute( 't' ), |
|
2917 xmlValue = cell.getElementsByTagName( 'v' )[ 0 ].innerHTML; |
|
2918 let value; |
|
2919 |
|
2920 switch ( type ) { |
|
2921 case 's': |
|
2922 // string |
|
2923 value = sharedStringsCollection[ parseFloat( xmlValue ) ]; |
|
2924 break; |
|
2925 case 'b': |
|
2926 // boolean |
|
2927 value = parseFloat( xmlValue ) === 1; |
|
2928 break; |
|
2929 default: |
|
2930 // number or date |
|
2931 value = parseFloat( xmlValue ); |
|
2932 } |
|
2933 |
|
2934 rowObject[ column ] = value; |
|
2935 } ); |
|
2936 |
|
2937 parsedData.push( rowObject ); |
|
2938 } ); |
|
2939 |
|
2940 return parsedData; |
|
2941 } |
|
2942 } |
|
2943 if ($.jqx && $.jqx.dataAdapter) { |
|
2944 $.jqx.dataAdapter.Importer = DataAdapter; |
|
2945 } |
|
2946 })(jqxBaseFramework); |