1 | (function ($) {
|
2 | $.extend(true, window, {
|
3 | Slick: {
|
4 | Data: {
|
5 | DataView: DataView,
|
6 | Aggregators: {
|
7 | Avg: AvgAggregator,
|
8 | Min: MinAggregator,
|
9 | Max: MaxAggregator,
|
10 | Sum: SumAggregator,
|
11 | Count: CountAggregator
|
12 | }
|
13 | }
|
14 | }
|
15 | });
|
16 |
|
17 |
|
18 | |
19 |
|
20 |
|
21 |
|
22 |
|
23 |
|
24 | function DataView(options) {
|
25 | var self = this;
|
26 |
|
27 | var defaults = {
|
28 | groupItemMetadataProvider: null,
|
29 | inlineFilters: false
|
30 | };
|
31 |
|
32 |
|
33 |
|
34 | var idProperty = "id";
|
35 | var items = [];
|
36 | var rows = [];
|
37 | var idxById = {};
|
38 | var rowsById = null;
|
39 | var filter = null;
|
40 | var updated = null;
|
41 | var suspend = false;
|
42 | var sortAsc = true;
|
43 | var fastSortField;
|
44 | var sortComparer;
|
45 | var refreshHints = {};
|
46 | var prevRefreshHints = {};
|
47 | var filterArgs;
|
48 | var filteredItems = [];
|
49 | var compiledFilter;
|
50 | var compiledFilterWithCaching;
|
51 | var filterCache = [];
|
52 |
|
53 |
|
54 | var groupingInfoDefaults = {
|
55 | getter: null,
|
56 | formatter: null,
|
57 | comparer: function (a, b) {
|
58 | return (a.value === b.value ? 0 :
|
59 | (a.value > b.value ? 1 : -1)
|
60 | );
|
61 | },
|
62 | predefinedValues: [],
|
63 | aggregators: [],
|
64 | aggregateEmpty: false,
|
65 | aggregateCollapsed: false,
|
66 | aggregateChildGroups: false,
|
67 | collapsed: false,
|
68 | displayTotalsRow: true,
|
69 | lazyTotalsCalculation: false
|
70 | };
|
71 | var groupingInfos = [];
|
72 | var groups = [];
|
73 | var toggledGroupsByLevel = [];
|
74 | var groupingDelimiter = ':|:';
|
75 |
|
76 | var pagesize = 0;
|
77 | var pagenum = 0;
|
78 | var totalRows = 0;
|
79 |
|
80 |
|
81 | var onSetItemsCalled = new Slick.Event();
|
82 | var onRowCountChanged = new Slick.Event();
|
83 | var onRowsChanged = new Slick.Event();
|
84 | var onRowsOrCountChanged = new Slick.Event();
|
85 | var onBeforePagingInfoChanged = new Slick.Event();
|
86 | var onPagingInfoChanged = new Slick.Event();
|
87 | var onGroupExpanded = new Slick.Event();
|
88 | var onGroupCollapsed = new Slick.Event();
|
89 |
|
90 | options = $.extend(true, {}, defaults, options);
|
91 |
|
92 |
|
93 | function beginUpdate() {
|
94 | suspend = true;
|
95 | }
|
96 |
|
97 | function endUpdate() {
|
98 | suspend = false;
|
99 | refresh();
|
100 | }
|
101 |
|
102 | function setRefreshHints(hints) {
|
103 | refreshHints = hints;
|
104 | }
|
105 |
|
106 | function setFilterArgs(args) {
|
107 | filterArgs = args;
|
108 | }
|
109 |
|
110 | function updateIdxById(startingIndex) {
|
111 | startingIndex = startingIndex || 0;
|
112 | var id;
|
113 | for (var i = startingIndex, l = items.length; i < l; i++) {
|
114 | id = items[i][idProperty];
|
115 | if (id === undefined) {
|
116 | throw new Error("Each data element must implement a unique 'id' property");
|
117 | }
|
118 | idxById[id] = i;
|
119 | }
|
120 | }
|
121 |
|
122 | function ensureIdUniqueness() {
|
123 | var id;
|
124 | for (var i = 0, l = items.length; i < l; i++) {
|
125 | id = items[i][idProperty];
|
126 | if (id === undefined || idxById[id] !== i) {
|
127 | throw new Error("Each data element must implement a unique 'id' property");
|
128 | }
|
129 | }
|
130 | }
|
131 |
|
132 | function getItems() {
|
133 | return items;
|
134 | }
|
135 |
|
136 | function getIdPropertyName() {
|
137 | return idProperty;
|
138 | }
|
139 |
|
140 | function setItems(data, objectIdProperty) {
|
141 | if (objectIdProperty !== undefined) {
|
142 | idProperty = objectIdProperty;
|
143 | }
|
144 | items = filteredItems = data;
|
145 | idxById = {};
|
146 | updateIdxById();
|
147 | ensureIdUniqueness();
|
148 | refresh();
|
149 | onSetItemsCalled.notify({ idProperty: objectIdProperty }, null, self);
|
150 | }
|
151 |
|
152 | function setPagingOptions(args) {
|
153 | onBeforePagingInfoChanged.notify(getPagingInfo(), null, self);
|
154 |
|
155 | if (args.pageSize != undefined) {
|
156 | pagesize = args.pageSize;
|
157 | pagenum = pagesize ? Math.min(pagenum, Math.max(0, Math.ceil(totalRows / pagesize) - 1)) : 0;
|
158 | }
|
159 |
|
160 | if (args.pageNum != undefined) {
|
161 | pagenum = Math.min(args.pageNum, Math.max(0, Math.ceil(totalRows / pagesize) - 1));
|
162 | }
|
163 |
|
164 | onPagingInfoChanged.notify(getPagingInfo(), null, self);
|
165 |
|
166 | refresh();
|
167 | }
|
168 |
|
169 | function getPagingInfo() {
|
170 | var totalPages = pagesize ? Math.max(1, Math.ceil(totalRows / pagesize)) : 1;
|
171 | return { pageSize: pagesize, pageNum: pagenum, totalRows: totalRows, totalPages: totalPages, dataView: self };
|
172 | }
|
173 |
|
174 | function sort(comparer, ascending) {
|
175 | sortAsc = ascending;
|
176 | sortComparer = comparer;
|
177 | fastSortField = null;
|
178 | if (ascending === false) {
|
179 | items.reverse();
|
180 | }
|
181 | items.sort(comparer);
|
182 | if (ascending === false) {
|
183 | items.reverse();
|
184 | }
|
185 | idxById = {};
|
186 | updateIdxById();
|
187 | refresh();
|
188 | }
|
189 |
|
190 | |
191 |
|
192 |
|
193 |
|
194 |
|
195 | function fastSort(field, ascending) {
|
196 | sortAsc = ascending;
|
197 | fastSortField = field;
|
198 | sortComparer = null;
|
199 | var oldToString = Object.prototype.toString;
|
200 | Object.prototype.toString = (typeof field == "function") ? field : function () {
|
201 | return this[field];
|
202 | };
|
203 |
|
204 |
|
205 | if (ascending === false) {
|
206 | items.reverse();
|
207 | }
|
208 | items.sort();
|
209 | Object.prototype.toString = oldToString;
|
210 | if (ascending === false) {
|
211 | items.reverse();
|
212 | }
|
213 | idxById = {};
|
214 | updateIdxById();
|
215 | refresh();
|
216 | }
|
217 |
|
218 | function reSort() {
|
219 | if (sortComparer) {
|
220 | sort(sortComparer, sortAsc);
|
221 | } else if (fastSortField) {
|
222 | fastSort(fastSortField, sortAsc);
|
223 | }
|
224 | }
|
225 |
|
226 | function getFilteredItems() {
|
227 | return filteredItems;
|
228 | }
|
229 |
|
230 |
|
231 | function getFilter() {
|
232 | return filter;
|
233 | }
|
234 |
|
235 | function setFilter(filterFn) {
|
236 | filter = filterFn;
|
237 | if (options.inlineFilters) {
|
238 | compiledFilter = compileFilter();
|
239 | compiledFilterWithCaching = compileFilterWithCaching();
|
240 | }
|
241 | refresh();
|
242 | }
|
243 |
|
244 | function getGrouping() {
|
245 | return groupingInfos;
|
246 | }
|
247 |
|
248 | function setGrouping(groupingInfo) {
|
249 | if (!options.groupItemMetadataProvider) {
|
250 | options.groupItemMetadataProvider = new Slick.Data.GroupItemMetadataProvider();
|
251 | }
|
252 |
|
253 | groups = [];
|
254 | toggledGroupsByLevel = [];
|
255 | groupingInfo = groupingInfo || [];
|
256 | groupingInfos = (groupingInfo instanceof Array) ? groupingInfo : [groupingInfo];
|
257 |
|
258 | for (var i = 0; i < groupingInfos.length; i++) {
|
259 | var gi = groupingInfos[i] = $.extend(true, {}, groupingInfoDefaults, groupingInfos[i]);
|
260 | gi.getterIsAFn = typeof gi.getter === "function";
|
261 |
|
262 |
|
263 | gi.compiledAccumulators = [];
|
264 | var idx = gi.aggregators.length;
|
265 | while (idx--) {
|
266 | gi.compiledAccumulators[idx] = compileAccumulatorLoop(gi.aggregators[idx]);
|
267 | }
|
268 |
|
269 | toggledGroupsByLevel[i] = {};
|
270 | }
|
271 |
|
272 | refresh();
|
273 | }
|
274 |
|
275 | |
276 |
|
277 |
|
278 | function groupBy(valueGetter, valueFormatter, sortComparer) {
|
279 | if (valueGetter == null) {
|
280 | setGrouping([]);
|
281 | return;
|
282 | }
|
283 |
|
284 | setGrouping({
|
285 | getter: valueGetter,
|
286 | formatter: valueFormatter,
|
287 | comparer: sortComparer
|
288 | });
|
289 | }
|
290 |
|
291 | |
292 |
|
293 |
|
294 | function setAggregators(groupAggregators, includeCollapsed) {
|
295 | if (!groupingInfos.length) {
|
296 | throw new Error("At least one grouping must be specified before calling setAggregators().");
|
297 | }
|
298 |
|
299 | groupingInfos[0].aggregators = groupAggregators;
|
300 | groupingInfos[0].aggregateCollapsed = includeCollapsed;
|
301 |
|
302 | setGrouping(groupingInfos);
|
303 | }
|
304 |
|
305 | function getItemByIdx(i) {
|
306 | return items[i];
|
307 | }
|
308 |
|
309 | function getIdxById(id) {
|
310 | return idxById[id];
|
311 | }
|
312 |
|
313 | function ensureRowsByIdCache() {
|
314 | if (!rowsById) {
|
315 | rowsById = {};
|
316 | for (var i = 0, l = rows.length; i < l; i++) {
|
317 | rowsById[rows[i][idProperty]] = i;
|
318 | }
|
319 | }
|
320 | }
|
321 |
|
322 | function getRowByItem(item) {
|
323 | ensureRowsByIdCache();
|
324 | return rowsById[item[idProperty]];
|
325 | }
|
326 |
|
327 | function getRowById(id) {
|
328 | ensureRowsByIdCache();
|
329 | return rowsById[id];
|
330 | }
|
331 |
|
332 | function getItemById(id) {
|
333 | return items[idxById[id]];
|
334 | }
|
335 |
|
336 | function mapItemsToRows(itemArray) {
|
337 | var rows = [];
|
338 | ensureRowsByIdCache();
|
339 | for (var i = 0, l = itemArray.length; i < l; i++) {
|
340 | var row = rowsById[itemArray[i][idProperty]];
|
341 | if (row != null) {
|
342 | rows[rows.length] = row;
|
343 | }
|
344 | }
|
345 | return rows;
|
346 | }
|
347 |
|
348 | function mapIdsToRows(idArray) {
|
349 | var rows = [];
|
350 | ensureRowsByIdCache();
|
351 | for (var i = 0, l = idArray.length; i < l; i++) {
|
352 | var row = rowsById[idArray[i]];
|
353 | if (row != null) {
|
354 | rows[rows.length] = row;
|
355 | }
|
356 | }
|
357 | return rows;
|
358 | }
|
359 |
|
360 | function mapRowsToIds(rowArray) {
|
361 | var ids = [];
|
362 | for (var i = 0, l = rowArray.length; i < l; i++) {
|
363 | if (rowArray[i] < rows.length) {
|
364 | ids[ids.length] = rows[rowArray[i]][idProperty];
|
365 | }
|
366 | }
|
367 | return ids;
|
368 | }
|
369 |
|
370 | function updateItem(id, item) {
|
371 |
|
372 | if (idxById[id] === undefined) {
|
373 | throw new Error("Invalid id");
|
374 | }
|
375 |
|
376 |
|
377 |
|
378 | if (id !== item[idProperty]) {
|
379 |
|
380 | var newId = item[idProperty];
|
381 | if (newId == null) {
|
382 | throw new Error("Cannot update item to associate with a null id");
|
383 | }
|
384 | if (idxById[newId] !== undefined) {
|
385 | throw new Error("Cannot update item to associate with a non-unique id");
|
386 | }
|
387 | idxById[newId] = idxById[id];
|
388 | delete idxById[id];
|
389 |
|
390 |
|
391 | if (updated && updated[id]) {
|
392 | delete updated[id];
|
393 | }
|
394 |
|
395 |
|
396 |
|
397 | id = newId;
|
398 | }
|
399 | items[idxById[id]] = item;
|
400 |
|
401 |
|
402 |
|
403 | if (!updated) {
|
404 | updated = {};
|
405 | }
|
406 | updated[id] = true;
|
407 | refresh();
|
408 | }
|
409 |
|
410 | function insertItem(insertBefore, item) {
|
411 | items.splice(insertBefore, 0, item);
|
412 | updateIdxById(insertBefore);
|
413 | refresh();
|
414 | }
|
415 |
|
416 | function addItem(item) {
|
417 | items.push(item);
|
418 | updateIdxById(items.length - 1);
|
419 | refresh();
|
420 | }
|
421 |
|
422 | function deleteItem(id) {
|
423 | var idx = idxById[id];
|
424 | if (idx === undefined) {
|
425 | throw new Error("Invalid id");
|
426 | }
|
427 | delete idxById[id];
|
428 | items.splice(idx, 1);
|
429 | updateIdxById(idx);
|
430 | refresh();
|
431 | }
|
432 |
|
433 | function sortedAddItem(item) {
|
434 | if (!sortComparer) {
|
435 | throw new Error("sortedAddItem() requires a sort comparer, use sort()");
|
436 | }
|
437 | insertItem(sortedIndex(item), item);
|
438 | }
|
439 |
|
440 | function sortedUpdateItem(id, item) {
|
441 | if (idxById[id] === undefined || id !== item[idProperty]) {
|
442 | throw new Error("Invalid or non-matching id " + idxById[id]);
|
443 | }
|
444 | if (!sortComparer) {
|
445 | throw new Error("sortedUpdateItem() requires a sort comparer, use sort()");
|
446 | }
|
447 | var oldItem = getItemById(id);
|
448 | if (sortComparer(oldItem, item) !== 0) {
|
449 |
|
450 | deleteItem(id);
|
451 | sortedAddItem(item);
|
452 | }
|
453 | else {
|
454 | updateItem(id, item);
|
455 | }
|
456 | }
|
457 |
|
458 | function sortedIndex(searchItem) {
|
459 | var low = 0, high = items.length;
|
460 |
|
461 | while (low < high) {
|
462 | var mid = low + high >>> 1;
|
463 | if (sortComparer(items[mid], searchItem) === -1) {
|
464 | low = mid + 1;
|
465 | }
|
466 | else {
|
467 | high = mid;
|
468 | }
|
469 | }
|
470 | return low;
|
471 | }
|
472 |
|
473 | function getLength() {
|
474 | return rows.length;
|
475 | }
|
476 |
|
477 | function getItem(i) {
|
478 | var item = rows[i];
|
479 |
|
480 |
|
481 | if (item && item.__group && item.totals && !item.totals.initialized) {
|
482 | var gi = groupingInfos[item.level];
|
483 | if (!gi.displayTotalsRow) {
|
484 | calculateTotals(item.totals);
|
485 | item.title = gi.formatter ? gi.formatter(item) : item.value;
|
486 | }
|
487 | }
|
488 |
|
489 | else if (item && item.__groupTotals && !item.initialized) {
|
490 | calculateTotals(item);
|
491 | }
|
492 |
|
493 | return item;
|
494 | }
|
495 |
|
496 | function getItemMetadata(i) {
|
497 | var item = rows[i];
|
498 | if (item === undefined) {
|
499 | return null;
|
500 | }
|
501 |
|
502 |
|
503 | if (item.__group) {
|
504 | return options.groupItemMetadataProvider.getGroupRowMetadata(item);
|
505 | }
|
506 |
|
507 |
|
508 | if (item.__groupTotals) {
|
509 | return options.groupItemMetadataProvider.getTotalsRowMetadata(item);
|
510 | }
|
511 |
|
512 | return null;
|
513 | }
|
514 |
|
515 | function expandCollapseAllGroups(level, collapse) {
|
516 | if (level == null) {
|
517 | for (var i = 0; i < groupingInfos.length; i++) {
|
518 | toggledGroupsByLevel[i] = {};
|
519 | groupingInfos[i].collapsed = collapse;
|
520 |
|
521 | if (collapse === true) {
|
522 | onGroupCollapsed.notify({ level: i, groupingKey: null });
|
523 | } else {
|
524 | onGroupExpanded.notify({ level: i, groupingKey: null });
|
525 | }
|
526 | }
|
527 | } else {
|
528 | toggledGroupsByLevel[level] = {};
|
529 | groupingInfos[level].collapsed = collapse;
|
530 |
|
531 | if (collapse === true) {
|
532 | onGroupCollapsed.notify({ level: level, groupingKey: null });
|
533 | } else {
|
534 | onGroupExpanded.notify({ level: level, groupingKey: null });
|
535 | }
|
536 | }
|
537 | refresh();
|
538 | }
|
539 |
|
540 | |
541 |
|
542 |
|
543 | function collapseAllGroups(level) {
|
544 | expandCollapseAllGroups(level, true);
|
545 | }
|
546 |
|
547 | |
548 |
|
549 |
|
550 | function expandAllGroups(level) {
|
551 | expandCollapseAllGroups(level, false);
|
552 | }
|
553 |
|
554 | function expandCollapseGroup(level, groupingKey, collapse) {
|
555 | toggledGroupsByLevel[level][groupingKey] = groupingInfos[level].collapsed ^ collapse;
|
556 | refresh();
|
557 | }
|
558 |
|
559 | |
560 |
|
561 |
|
562 |
|
563 |
|
564 |
|
565 | function collapseGroup(varArgs) {
|
566 | var args = Array.prototype.slice.call(arguments);
|
567 | var arg0 = args[0];
|
568 | var groupingKey;
|
569 | var level;
|
570 |
|
571 | if (args.length === 1 && arg0.indexOf(groupingDelimiter) !== -1) {
|
572 | groupingKey = arg0;
|
573 | level = arg0.split(groupingDelimiter).length - 1;
|
574 | } else {
|
575 | groupingKey = args.join(groupingDelimiter);
|
576 | level = args.length - 1;
|
577 | }
|
578 |
|
579 | expandCollapseGroup(level, groupingKey, true);
|
580 | onGroupCollapsed.notify({ level: level, groupingKey: groupingKey });
|
581 | }
|
582 |
|
583 | |
584 |
|
585 |
|
586 |
|
587 |
|
588 |
|
589 | function expandGroup(varArgs) {
|
590 | var args = Array.prototype.slice.call(arguments);
|
591 | var arg0 = args[0];
|
592 | var groupingKey;
|
593 | var level;
|
594 |
|
595 | if (args.length === 1 && arg0.indexOf(groupingDelimiter) !== -1) {
|
596 | level = arg0.split(groupingDelimiter).length - 1;
|
597 | groupingKey = arg0;
|
598 | } else {
|
599 | level = args.length - 1;
|
600 | groupingKey = args.join(groupingDelimiter);
|
601 | }
|
602 |
|
603 | expandCollapseGroup(level, groupingKey, false);
|
604 | onGroupExpanded.notify({ level: level, groupingKey: groupingKey });
|
605 | }
|
606 |
|
607 | function getGroups() {
|
608 | return groups;
|
609 | }
|
610 |
|
611 | function extractGroups(rows, parentGroup) {
|
612 | var group;
|
613 | var val;
|
614 | var groups = [];
|
615 | var groupsByVal = {};
|
616 | var r;
|
617 | var level = parentGroup ? parentGroup.level + 1 : 0;
|
618 | var gi = groupingInfos[level];
|
619 |
|
620 | for (var i = 0, l = gi.predefinedValues.length; i < l; i++) {
|
621 | val = gi.predefinedValues[i];
|
622 | group = groupsByVal[val];
|
623 | if (!group) {
|
624 | group = new Slick.Group();
|
625 | group.value = val;
|
626 | group.level = level;
|
627 | group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : '') + val;
|
628 | groups[groups.length] = group;
|
629 | groupsByVal[val] = group;
|
630 | }
|
631 | }
|
632 |
|
633 | for (var i = 0, l = rows.length; i < l; i++) {
|
634 | r = rows[i];
|
635 | val = gi.getterIsAFn ? gi.getter(r) : r[gi.getter];
|
636 | group = groupsByVal[val];
|
637 | if (!group) {
|
638 | group = new Slick.Group();
|
639 | group.value = val;
|
640 | group.level = level;
|
641 | group.groupingKey = (parentGroup ? parentGroup.groupingKey + groupingDelimiter : '') + val;
|
642 | groups[groups.length] = group;
|
643 | groupsByVal[val] = group;
|
644 | }
|
645 |
|
646 | group.rows[group.count++] = r;
|
647 | }
|
648 |
|
649 | if (level < groupingInfos.length - 1) {
|
650 | for (var i = 0; i < groups.length; i++) {
|
651 | group = groups[i];
|
652 | group.groups = extractGroups(group.rows, group);
|
653 | }
|
654 | }
|
655 |
|
656 | if(groups.length) {
|
657 | addTotals(groups);
|
658 | }
|
659 |
|
660 | groups.sort(groupingInfos[level].comparer);
|
661 |
|
662 | return groups;
|
663 | }
|
664 |
|
665 | function calculateTotals(totals) {
|
666 | var group = totals.group;
|
667 | var gi = groupingInfos[group.level];
|
668 | var isLeafLevel = (group.level == groupingInfos.length);
|
669 | var agg, idx = gi.aggregators.length;
|
670 |
|
671 | if (!isLeafLevel && gi.aggregateChildGroups) {
|
672 |
|
673 | var i = group.groups.length;
|
674 | while (i--) {
|
675 | if (!group.groups[i].totals.initialized) {
|
676 | calculateTotals(group.groups[i].totals);
|
677 | }
|
678 | }
|
679 | }
|
680 |
|
681 | while (idx--) {
|
682 | agg = gi.aggregators[idx];
|
683 | agg.init();
|
684 | if (!isLeafLevel && gi.aggregateChildGroups) {
|
685 | gi.compiledAccumulators[idx].call(agg, group.groups);
|
686 | } else {
|
687 | gi.compiledAccumulators[idx].call(agg, group.rows);
|
688 | }
|
689 | agg.storeResult(totals);
|
690 | }
|
691 | totals.initialized = true;
|
692 | }
|
693 |
|
694 | function addGroupTotals(group) {
|
695 | var gi = groupingInfos[group.level];
|
696 | var totals = new Slick.GroupTotals();
|
697 | totals.group = group;
|
698 | group.totals = totals;
|
699 | if (!gi.lazyTotalsCalculation) {
|
700 | calculateTotals(totals);
|
701 | }
|
702 | }
|
703 |
|
704 | function addTotals(groups, level) {
|
705 | level = level || 0;
|
706 | var gi = groupingInfos[level];
|
707 | var groupCollapsed = gi.collapsed;
|
708 | var toggledGroups = toggledGroupsByLevel[level];
|
709 | var idx = groups.length, g;
|
710 | while (idx--) {
|
711 | g = groups[idx];
|
712 |
|
713 | if (g.collapsed && !gi.aggregateCollapsed) {
|
714 | continue;
|
715 | }
|
716 |
|
717 |
|
718 | if (g.groups) {
|
719 | addTotals(g.groups, level + 1);
|
720 | }
|
721 |
|
722 | if (gi.aggregators.length && (
|
723 | gi.aggregateEmpty || g.rows.length || (g.groups && g.groups.length))) {
|
724 | addGroupTotals(g);
|
725 | }
|
726 |
|
727 | g.collapsed = groupCollapsed ^ toggledGroups[g.groupingKey];
|
728 | g.title = gi.formatter ? gi.formatter(g) : g.value;
|
729 | }
|
730 | }
|
731 |
|
732 | function flattenGroupedRows(groups, level) {
|
733 | level = level || 0;
|
734 | var gi = groupingInfos[level];
|
735 | var groupedRows = [], rows, gl = 0, g;
|
736 | for (var i = 0, l = groups.length; i < l; i++) {
|
737 | g = groups[i];
|
738 | groupedRows[gl++] = g;
|
739 |
|
740 | if (!g.collapsed) {
|
741 | rows = g.groups ? flattenGroupedRows(g.groups, level + 1) : g.rows;
|
742 | for (var j = 0, jj = rows.length; j < jj; j++) {
|
743 | groupedRows[gl++] = rows[j];
|
744 | }
|
745 | }
|
746 |
|
747 | if (g.totals && gi.displayTotalsRow && (!g.collapsed || gi.aggregateCollapsed)) {
|
748 | groupedRows[gl++] = g.totals;
|
749 | }
|
750 | }
|
751 | return groupedRows;
|
752 | }
|
753 |
|
754 | function getFunctionInfo(fn) {
|
755 | var fnStr = fn.toString();
|
756 | var usingEs5 = fnStr.indexOf('function') >= 0;
|
757 | var fnRegex = usingEs5 ? /^function[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/ : /^[^(]*\(([^)]*)\)\s*{([\s\S]*)}$/;
|
758 | var matches = fn.toString().match(fnRegex);
|
759 | return {
|
760 | params: matches[1].split(","),
|
761 | body: matches[2]
|
762 | };
|
763 | }
|
764 |
|
765 | function compileAccumulatorLoop(aggregator) {
|
766 | if (aggregator.accumulate) {
|
767 | var accumulatorInfo = getFunctionInfo(aggregator.accumulate);
|
768 | var fn = new Function(
|
769 | "_items",
|
770 | "for (var " + accumulatorInfo.params[0] + ", _i=0, _il=_items.length; _i<_il; _i++) {" +
|
771 | accumulatorInfo.params[0] + " = _items[_i]; " +
|
772 | accumulatorInfo.body +
|
773 | "}"
|
774 | );
|
775 | var fnName = "compiledAccumulatorLoop";
|
776 | fn.displayName = fnName;
|
777 | fn.name = setFunctionName(fn, fnName);
|
778 | return fn;
|
779 | } else {
|
780 | return function noAccumulator() {
|
781 | }
|
782 | }
|
783 | }
|
784 |
|
785 | function compileFilter() {
|
786 | var filterInfo = getFunctionInfo(filter);
|
787 |
|
788 | var filterPath1 = "{ continue _coreloop; }$1";
|
789 | var filterPath2 = "{ _retval[_idx++] = $item$; continue _coreloop; }$1";
|
790 |
|
791 | var filterBody = filterInfo.body
|
792 | .replace(/return false\s*([;}]|\}|$)/gi, filterPath1)
|
793 | .replace(/return!1([;}]|\}|$)/gi, filterPath1)
|
794 | .replace(/return true\s*([;}]|\}|$)/gi, filterPath2)
|
795 | .replace(/return!0([;}]|\}|$)/gi, filterPath2)
|
796 | .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
|
797 | "{ if ($1) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
|
798 |
|
799 |
|
800 |
|
801 | var tpl = [
|
802 |
|
803 | "var _retval = [], _idx = 0; ",
|
804 | "var $item$, $args$ = _args; ",
|
805 | "_coreloop: ",
|
806 | "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
|
807 | "$item$ = _items[_i]; ",
|
808 | "$filter$; ",
|
809 | "} ",
|
810 | "return _retval; "
|
811 |
|
812 | ].join("");
|
813 | tpl = tpl.replace(/\$filter\$/gi, filterBody);
|
814 | tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
|
815 | tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
|
816 |
|
817 | var fn = new Function("_items,_args", tpl);
|
818 | var fnName = "compiledFilter";
|
819 | fn.displayName = fnName;
|
820 | fn.name = setFunctionName(fn, fnName);
|
821 | return fn;
|
822 | }
|
823 |
|
824 | function compileFilterWithCaching() {
|
825 | var filterInfo = getFunctionInfo(filter);
|
826 |
|
827 | var filterPath1 = "{ continue _coreloop; }$1";
|
828 | var filterPath2 = "{ _cache[_i] = true;_retval[_idx++] = $item$; continue _coreloop; }$1";
|
829 |
|
830 | var filterBody = filterInfo.body
|
831 | .replace(/return false\s*([;}]|\}|$)/gi, filterPath1)
|
832 | .replace(/return!1([;}]|\}|$)/gi, filterPath1)
|
833 | .replace(/return true\s*([;}]|\}|$)/gi, filterPath2)
|
834 | .replace(/return!0([;}]|\}|$)/gi, filterPath2)
|
835 | .replace(/return ([^;}]+?)\s*([;}]|$)/gi,
|
836 | "{ if ((_cache[_i] = $1)) { _retval[_idx++] = $item$; }; continue _coreloop; }$2");
|
837 |
|
838 |
|
839 |
|
840 | var tpl = [
|
841 |
|
842 | "var _retval = [], _idx = 0; ",
|
843 | "var $item$, $args$ = _args; ",
|
844 | "_coreloop: ",
|
845 | "for (var _i = 0, _il = _items.length; _i < _il; _i++) { ",
|
846 | "$item$ = _items[_i]; ",
|
847 | "if (_cache[_i]) { ",
|
848 | "_retval[_idx++] = $item$; ",
|
849 | "continue _coreloop; ",
|
850 | "} ",
|
851 | "$filter$; ",
|
852 | "} ",
|
853 | "return _retval; "
|
854 |
|
855 | ].join("");
|
856 | tpl = tpl.replace(/\$filter\$/gi, filterBody);
|
857 | tpl = tpl.replace(/\$item\$/gi, filterInfo.params[0]);
|
858 | tpl = tpl.replace(/\$args\$/gi, filterInfo.params[1]);
|
859 |
|
860 | var fn = new Function("_items,_args,_cache", tpl);
|
861 | var fnName = "compiledFilterWithCaching";
|
862 | fn.displayName = fnName;
|
863 | fn.name = setFunctionName(fn, fnName);
|
864 | return fn;
|
865 | }
|
866 |
|
867 | |
868 |
|
869 |
|
870 |
|
871 |
|
872 |
|
873 |
|
874 | function setFunctionName(fn, fnName) {
|
875 | try {
|
876 | Object.defineProperty(fn, 'name', {
|
877 | writable: true,
|
878 | value: fnName
|
879 | });
|
880 | } catch (err) {
|
881 | fn.name = fnName;
|
882 | }
|
883 | }
|
884 |
|
885 | function uncompiledFilter(items, args) {
|
886 | var retval = [], idx = 0;
|
887 |
|
888 | for (var i = 0, ii = items.length; i < ii; i++) {
|
889 | if (filter(items[i], args)) {
|
890 | retval[idx++] = items[i];
|
891 | }
|
892 | }
|
893 |
|
894 | return retval;
|
895 | }
|
896 |
|
897 | function uncompiledFilterWithCaching(items, args, cache) {
|
898 | var retval = [], idx = 0, item;
|
899 |
|
900 | for (var i = 0, ii = items.length; i < ii; i++) {
|
901 | item = items[i];
|
902 | if (cache[i]) {
|
903 | retval[idx++] = item;
|
904 | } else if (filter(item, args)) {
|
905 | retval[idx++] = item;
|
906 | cache[i] = true;
|
907 | }
|
908 | }
|
909 |
|
910 | return retval;
|
911 | }
|
912 |
|
913 | function getFilteredAndPagedItems(items) {
|
914 | if (filter) {
|
915 | var batchFilter = options.inlineFilters ? compiledFilter : uncompiledFilter;
|
916 | var batchFilterWithCaching = options.inlineFilters ? compiledFilterWithCaching : uncompiledFilterWithCaching;
|
917 |
|
918 | if (refreshHints.isFilterNarrowing) {
|
919 | filteredItems = batchFilter(filteredItems, filterArgs);
|
920 | } else if (refreshHints.isFilterExpanding) {
|
921 | filteredItems = batchFilterWithCaching(items, filterArgs, filterCache);
|
922 | } else if (!refreshHints.isFilterUnchanged) {
|
923 | filteredItems = batchFilter(items, filterArgs);
|
924 | }
|
925 | } else {
|
926 |
|
927 |
|
928 |
|
929 | filteredItems = pagesize ? items : items.concat();
|
930 | }
|
931 |
|
932 |
|
933 | var paged;
|
934 | if (pagesize) {
|
935 | if (filteredItems.length <= pagenum * pagesize) {
|
936 | if (filteredItems.length === 0) {
|
937 | pagenum = 0;
|
938 | } else {
|
939 | pagenum = Math.floor((filteredItems.length - 1) / pagesize);
|
940 | }
|
941 | }
|
942 | paged = filteredItems.slice(pagesize * pagenum, pagesize * pagenum + pagesize);
|
943 | } else {
|
944 | paged = filteredItems;
|
945 | }
|
946 | return { totalRows: filteredItems.length, rows: paged };
|
947 | }
|
948 |
|
949 | function getRowDiffs(rows, newRows) {
|
950 | var item, r, eitherIsNonData, diff = [];
|
951 | var from = 0, to = Math.max(newRows.length, rows.length);
|
952 |
|
953 | if (refreshHints && refreshHints.ignoreDiffsBefore) {
|
954 | from = Math.max(0,
|
955 | Math.min(newRows.length, refreshHints.ignoreDiffsBefore));
|
956 | }
|
957 |
|
958 | if (refreshHints && refreshHints.ignoreDiffsAfter) {
|
959 | to = Math.min(newRows.length,
|
960 | Math.max(0, refreshHints.ignoreDiffsAfter));
|
961 | }
|
962 |
|
963 | for (var i = from, rl = rows.length; i < to; i++) {
|
964 | if (i >= rl) {
|
965 | diff[diff.length] = i;
|
966 | } else {
|
967 | item = newRows[i];
|
968 | r = rows[i];
|
969 |
|
970 | if (!item || (groupingInfos.length && (eitherIsNonData = (item.__nonDataRow) || (r.__nonDataRow)) &&
|
971 | item.__group !== r.__group ||
|
972 | item.__group && !item.equals(r))
|
973 | || (eitherIsNonData &&
|
974 |
|
975 |
|
976 |
|
977 | (item.__groupTotals || r.__groupTotals))
|
978 | || item[idProperty] != r[idProperty]
|
979 | || (updated && updated[item[idProperty]])
|
980 | ) {
|
981 | diff[diff.length] = i;
|
982 | }
|
983 | }
|
984 | }
|
985 | return diff;
|
986 | }
|
987 |
|
988 | function recalc(_items) {
|
989 | rowsById = null;
|
990 |
|
991 | if (refreshHints.isFilterNarrowing != prevRefreshHints.isFilterNarrowing ||
|
992 | refreshHints.isFilterExpanding != prevRefreshHints.isFilterExpanding) {
|
993 | filterCache = [];
|
994 | }
|
995 |
|
996 | var filteredItems = getFilteredAndPagedItems(_items);
|
997 | totalRows = filteredItems.totalRows;
|
998 | var newRows = filteredItems.rows;
|
999 |
|
1000 | groups = [];
|
1001 | if (groupingInfos.length) {
|
1002 | groups = extractGroups(newRows);
|
1003 | if (groups.length) {
|
1004 | newRows = flattenGroupedRows(groups);
|
1005 | }
|
1006 | }
|
1007 |
|
1008 | var diff = getRowDiffs(rows, newRows);
|
1009 |
|
1010 | rows = newRows;
|
1011 |
|
1012 | return diff;
|
1013 | }
|
1014 |
|
1015 | function refresh() {
|
1016 | if (suspend) {
|
1017 | return;
|
1018 | }
|
1019 |
|
1020 | var previousPagingInfo = $.extend(true, {}, getPagingInfo());
|
1021 |
|
1022 | var countBefore = rows.length;
|
1023 | var totalRowsBefore = totalRows;
|
1024 |
|
1025 | var diff = recalc(items, filter);
|
1026 |
|
1027 |
|
1028 |
|
1029 | if (pagesize && totalRows < pagenum * pagesize) {
|
1030 | pagenum = Math.max(0, Math.ceil(totalRows / pagesize) - 1);
|
1031 | diff = recalc(items, filter);
|
1032 | }
|
1033 |
|
1034 | updated = null;
|
1035 | prevRefreshHints = refreshHints;
|
1036 | refreshHints = {};
|
1037 |
|
1038 | if (totalRowsBefore !== totalRows) {
|
1039 | onBeforePagingInfoChanged.notify(previousPagingInfo, null, self);
|
1040 | onPagingInfoChanged.notify(getPagingInfo(), null, self);
|
1041 | }
|
1042 | if (countBefore !== rows.length) {
|
1043 | onRowCountChanged.notify({ previous: countBefore, current: rows.length, dataView: self, callingOnRowsChanged: (diff.length > 0) }, null, self);
|
1044 | }
|
1045 | if (diff.length > 0) {
|
1046 | onRowsChanged.notify({ rows: diff, dataView: self, calledOnRowCountChanged: (countBefore !== rows.length) }, null, self);
|
1047 | }
|
1048 | if (countBefore !== rows.length || diff.length > 0) {
|
1049 | onRowsOrCountChanged.notify({
|
1050 | rowsDiff: diff, previousRowCount: countBefore, currentRowCount: rows.length,
|
1051 | rowCountChanged: countBefore !== rows.length, rowsChanged: diff.length > 0, dataView: self
|
1052 | }, null, self);
|
1053 | }
|
1054 | }
|
1055 |
|
1056 | |
1057 |
|
1058 |
|
1059 |
|
1060 |
|
1061 |
|
1062 |
|
1063 |
|
1064 |
|
1065 |
|
1066 |
|
1067 |
|
1068 |
|
1069 |
|
1070 |
|
1071 |
|
1072 |
|
1073 |
|
1074 |
|
1075 | function syncGridSelection(grid, preserveHidden, preserveHiddenOnSelectionChange) {
|
1076 | var self = this;
|
1077 | var inHandler;
|
1078 | var selectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
|
1079 | var onSelectedRowIdsChanged = new Slick.Event();
|
1080 |
|
1081 | function setSelectedRowIds(rowIds) {
|
1082 | if (selectedRowIds.join(",") == rowIds.join(",")) {
|
1083 | return;
|
1084 | }
|
1085 |
|
1086 | selectedRowIds = rowIds;
|
1087 |
|
1088 | onSelectedRowIdsChanged.notify({
|
1089 | "grid": grid,
|
1090 | "ids": selectedRowIds,
|
1091 | "dataView": self
|
1092 | }, new Slick.EventData(), self);
|
1093 | }
|
1094 |
|
1095 | function update() {
|
1096 | if (selectedRowIds.length > 0) {
|
1097 | inHandler = true;
|
1098 | var selectedRows = self.mapIdsToRows(selectedRowIds);
|
1099 | if (!preserveHidden) {
|
1100 | setSelectedRowIds(self.mapRowsToIds(selectedRows));
|
1101 | }
|
1102 | grid.setSelectedRows(selectedRows);
|
1103 | inHandler = false;
|
1104 | }
|
1105 | }
|
1106 |
|
1107 | grid.onSelectedRowsChanged.subscribe(function (e, args) {
|
1108 | if (inHandler) { return; }
|
1109 | var newSelectedRowIds = self.mapRowsToIds(grid.getSelectedRows());
|
1110 | if (!preserveHiddenOnSelectionChange || !grid.getOptions().multiSelect) {
|
1111 | setSelectedRowIds(newSelectedRowIds);
|
1112 | } else {
|
1113 |
|
1114 | var existing = $.grep(selectedRowIds, function (id) { return self.getRowById(id) === undefined; });
|
1115 |
|
1116 | setSelectedRowIds(existing.concat(newSelectedRowIds));
|
1117 | }
|
1118 | });
|
1119 |
|
1120 | this.onRowsOrCountChanged.subscribe(update);
|
1121 |
|
1122 | return onSelectedRowIdsChanged;
|
1123 | }
|
1124 |
|
1125 | function syncGridCellCssStyles(grid, key) {
|
1126 | var hashById;
|
1127 | var inHandler;
|
1128 |
|
1129 |
|
1130 |
|
1131 | storeCellCssStyles(grid.getCellCssStyles(key));
|
1132 |
|
1133 | function storeCellCssStyles(hash) {
|
1134 | hashById = {};
|
1135 | for (var row in hash) {
|
1136 | var id = rows[row][idProperty];
|
1137 | hashById[id] = hash[row];
|
1138 | }
|
1139 | }
|
1140 |
|
1141 | function update() {
|
1142 | if (hashById) {
|
1143 | inHandler = true;
|
1144 | ensureRowsByIdCache();
|
1145 | var newHash = {};
|
1146 | for (var id in hashById) {
|
1147 | var row = rowsById[id];
|
1148 | if (row != undefined) {
|
1149 | newHash[row] = hashById[id];
|
1150 | }
|
1151 | }
|
1152 | grid.setCellCssStyles(key, newHash);
|
1153 | inHandler = false;
|
1154 | }
|
1155 | }
|
1156 |
|
1157 | grid.onCellCssStylesChanged.subscribe(function (e, args) {
|
1158 | if (inHandler) { return; }
|
1159 | if (key != args.key) { return; }
|
1160 | if (args.hash) {
|
1161 | storeCellCssStyles(args.hash);
|
1162 | } else {
|
1163 | grid.onCellCssStylesChanged.unsubscribe();
|
1164 | self.onRowsOrCountChanged.unsubscribe(update);
|
1165 | }
|
1166 | });
|
1167 |
|
1168 | this.onRowsOrCountChanged.subscribe(update);
|
1169 | }
|
1170 |
|
1171 | $.extend(this, {
|
1172 |
|
1173 | "beginUpdate": beginUpdate,
|
1174 | "endUpdate": endUpdate,
|
1175 | "setPagingOptions": setPagingOptions,
|
1176 | "getPagingInfo": getPagingInfo,
|
1177 | "getIdPropertyName": getIdPropertyName,
|
1178 | "getItems": getItems,
|
1179 | "setItems": setItems,
|
1180 | "setFilter": setFilter,
|
1181 | "getFilter": getFilter,
|
1182 | "getFilteredItems": getFilteredItems,
|
1183 | "sort": sort,
|
1184 | "fastSort": fastSort,
|
1185 | "reSort": reSort,
|
1186 | "setGrouping": setGrouping,
|
1187 | "getGrouping": getGrouping,
|
1188 | "groupBy": groupBy,
|
1189 | "setAggregators": setAggregators,
|
1190 | "collapseAllGroups": collapseAllGroups,
|
1191 | "expandAllGroups": expandAllGroups,
|
1192 | "collapseGroup": collapseGroup,
|
1193 | "expandGroup": expandGroup,
|
1194 | "getGroups": getGroups,
|
1195 | "getIdxById": getIdxById,
|
1196 | "getRowByItem": getRowByItem,
|
1197 | "getRowById": getRowById,
|
1198 | "getItemById": getItemById,
|
1199 | "getItemByIdx": getItemByIdx,
|
1200 | "mapItemsToRows": mapItemsToRows,
|
1201 | "mapRowsToIds": mapRowsToIds,
|
1202 | "mapIdsToRows": mapIdsToRows,
|
1203 | "setRefreshHints": setRefreshHints,
|
1204 | "setFilterArgs": setFilterArgs,
|
1205 | "refresh": refresh,
|
1206 | "updateItem": updateItem,
|
1207 | "insertItem": insertItem,
|
1208 | "addItem": addItem,
|
1209 | "deleteItem": deleteItem,
|
1210 | "sortedAddItem": sortedAddItem,
|
1211 | "sortedUpdateItem": sortedUpdateItem,
|
1212 | "syncGridSelection": syncGridSelection,
|
1213 | "syncGridCellCssStyles": syncGridCellCssStyles,
|
1214 |
|
1215 |
|
1216 | "getLength": getLength,
|
1217 | "getItem": getItem,
|
1218 | "getItemMetadata": getItemMetadata,
|
1219 |
|
1220 |
|
1221 | "onSetItemsCalled": onSetItemsCalled,
|
1222 | "onRowCountChanged": onRowCountChanged,
|
1223 | "onRowsChanged": onRowsChanged,
|
1224 | "onRowsOrCountChanged": onRowsOrCountChanged,
|
1225 | "onBeforePagingInfoChanged": onBeforePagingInfoChanged,
|
1226 | "onPagingInfoChanged": onPagingInfoChanged,
|
1227 | "onGroupExpanded": onGroupExpanded,
|
1228 | "onGroupCollapsed": onGroupCollapsed
|
1229 | });
|
1230 | }
|
1231 |
|
1232 | function AvgAggregator(field) {
|
1233 | this.field_ = field;
|
1234 |
|
1235 | this.init = function () {
|
1236 | this.count_ = 0;
|
1237 | this.nonNullCount_ = 0;
|
1238 | this.sum_ = 0;
|
1239 | };
|
1240 |
|
1241 | this.accumulate = function (item) {
|
1242 | var val = item[this.field_];
|
1243 | this.count_++;
|
1244 | if (val != null && val !== "" && !isNaN(val)) {
|
1245 | this.nonNullCount_++;
|
1246 | this.sum_ += parseFloat(val);
|
1247 | }
|
1248 | };
|
1249 |
|
1250 | this.storeResult = function (groupTotals) {
|
1251 | if (!groupTotals.avg) {
|
1252 | groupTotals.avg = {};
|
1253 | }
|
1254 | if (this.nonNullCount_ !== 0) {
|
1255 | groupTotals.avg[this.field_] = this.sum_ / this.nonNullCount_;
|
1256 | }
|
1257 | };
|
1258 | }
|
1259 |
|
1260 | function MinAggregator(field) {
|
1261 | this.field_ = field;
|
1262 |
|
1263 | this.init = function () {
|
1264 | this.min_ = null;
|
1265 | };
|
1266 |
|
1267 | this.accumulate = function (item) {
|
1268 | var val = item[this.field_];
|
1269 | if (val != null && val !== "" && !isNaN(val)) {
|
1270 | if (this.min_ == null || val < this.min_) {
|
1271 | this.min_ = val;
|
1272 | }
|
1273 | }
|
1274 | };
|
1275 |
|
1276 | this.storeResult = function (groupTotals) {
|
1277 | if (!groupTotals.min) {
|
1278 | groupTotals.min = {};
|
1279 | }
|
1280 | groupTotals.min[this.field_] = this.min_;
|
1281 | };
|
1282 | }
|
1283 |
|
1284 | function MaxAggregator(field) {
|
1285 | this.field_ = field;
|
1286 |
|
1287 | this.init = function () {
|
1288 | this.max_ = null;
|
1289 | };
|
1290 |
|
1291 | this.accumulate = function (item) {
|
1292 | var val = item[this.field_];
|
1293 | if (val != null && val !== "" && !isNaN(val)) {
|
1294 | if (this.max_ == null || val > this.max_) {
|
1295 | this.max_ = val;
|
1296 | }
|
1297 | }
|
1298 | };
|
1299 |
|
1300 | this.storeResult = function (groupTotals) {
|
1301 | if (!groupTotals.max) {
|
1302 | groupTotals.max = {};
|
1303 | }
|
1304 | groupTotals.max[this.field_] = this.max_;
|
1305 | };
|
1306 | }
|
1307 |
|
1308 | function SumAggregator(field) {
|
1309 | this.field_ = field;
|
1310 |
|
1311 | this.init = function () {
|
1312 | this.sum_ = null;
|
1313 | };
|
1314 |
|
1315 | this.accumulate = function (item) {
|
1316 | var val = item[this.field_];
|
1317 | if (val != null && val !== "" && !isNaN(val)) {
|
1318 | this.sum_ += parseFloat(val);
|
1319 | }
|
1320 | };
|
1321 |
|
1322 | this.storeResult = function (groupTotals) {
|
1323 | if (!groupTotals.sum) {
|
1324 | groupTotals.sum = {};
|
1325 | }
|
1326 | groupTotals.sum[this.field_] = this.sum_;
|
1327 | };
|
1328 | }
|
1329 |
|
1330 | function CountAggregator(field) {
|
1331 | this.field_ = field;
|
1332 |
|
1333 | this.init = function () {
|
1334 | };
|
1335 |
|
1336 | this.storeResult = function (groupTotals) {
|
1337 | if (!groupTotals.count) {
|
1338 | groupTotals.count = {};
|
1339 | }
|
1340 | groupTotals.count[this.field_] = groupTotals.group.rows.length;
|
1341 | };
|
1342 | }
|
1343 |
|
1344 |
|
1345 |
|
1346 |
|
1347 | })(jQuery);
|