@swimlane/ngx-datatable 18.0.0 → 20.0.0-alpha-1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (136) hide show
  1. package/README.md +0 -1
  2. package/esm2020/lib/components/body/body-cell.component.mjs +432 -0
  3. package/esm2020/lib/components/body/body-group-header-template.directive.mjs +16 -0
  4. package/esm2020/lib/components/body/body-group-header.directive.mjs +62 -0
  5. package/esm2020/lib/components/body/body-row-wrapper.component.mjs +140 -0
  6. package/esm2020/lib/components/body/body-row.component.mjs +262 -0
  7. package/esm2020/lib/components/body/body.component.mjs +863 -0
  8. package/esm2020/lib/components/body/progress-bar.component.mjs +27 -0
  9. package/esm2020/lib/components/body/scroller.component.mjs +91 -0
  10. package/esm2020/lib/components/body/selection.component.mjs +150 -0
  11. package/esm2020/lib/components/body/summary/summary-row.component.mjs +105 -0
  12. package/esm2020/lib/components/columns/column-cell.directive.mjs +14 -0
  13. package/esm2020/lib/components/columns/column-header.directive.mjs +14 -0
  14. package/esm2020/lib/components/columns/column.directive.mjs +98 -0
  15. package/esm2020/lib/components/columns/tree.directive.mjs +14 -0
  16. package/esm2020/lib/components/datatable.component.mjs +1008 -0
  17. package/esm2020/lib/components/footer/footer-template.directive.mjs +14 -0
  18. package/esm2020/lib/components/footer/footer.component.mjs +128 -0
  19. package/esm2020/lib/components/footer/footer.directive.mjs +35 -0
  20. package/esm2020/lib/components/footer/pager.component.mjs +181 -0
  21. package/esm2020/lib/components/header/header-cell.component.mjs +243 -0
  22. package/esm2020/lib/components/header/header.component.mjs +376 -0
  23. package/esm2020/lib/components/row-detail/row-detail-template.directive.mjs +16 -0
  24. package/esm2020/lib/components/row-detail/row-detail.directive.mjs +63 -0
  25. package/esm2020/lib/directives/draggable.directive.mjs +108 -0
  26. package/esm2020/lib/directives/long-press.directive.mjs +117 -0
  27. package/esm2020/lib/directives/orderable.directive.mjs +136 -0
  28. package/esm2020/lib/directives/resizeable.directive.mjs +93 -0
  29. package/esm2020/lib/directives/visibility.directive.mjs +63 -0
  30. package/{esm2015/lib/events.js → esm2020/lib/events.mjs} +0 -0
  31. package/esm2020/lib/ngx-datatable.module.mjs +139 -0
  32. package/esm2020/lib/services/column-changes.service.mjs +24 -0
  33. package/esm2020/lib/services/dimensions-helper.service.mjs +17 -0
  34. package/esm2020/lib/services/scrollbar-helper.service.mjs +37 -0
  35. package/{esm2015/lib/types/click.type.js → esm2020/lib/types/click.type.mjs} +0 -0
  36. package/{esm2015/lib/types/column-mode.type.js → esm2020/lib/types/column-mode.type.mjs} +0 -0
  37. package/{esm2015/lib/types/contextmenu.type.js → esm2020/lib/types/contextmenu.type.mjs} +0 -0
  38. package/{esm2015/lib/types/selection.type.js → esm2020/lib/types/selection.type.mjs} +0 -0
  39. package/{esm2015/lib/types/sort-direction.type.js → esm2020/lib/types/sort-direction.type.mjs} +0 -0
  40. package/{esm2015/lib/types/sort-prop-dir.type.js → esm2020/lib/types/sort-prop-dir.type.mjs} +1 -0
  41. package/{esm2015/lib/types/sort.type.js → esm2020/lib/types/sort.type.mjs} +0 -0
  42. package/{esm2015/lib/types/table-column.type.js → esm2020/lib/types/table-column.type.mjs} +1 -0
  43. package/{esm2015/lib/utils/camel-case.js → esm2020/lib/utils/camel-case.mjs} +0 -0
  44. package/{esm2015/lib/utils/column-helper.js → esm2020/lib/utils/column-helper.mjs} +0 -0
  45. package/{esm2015/lib/utils/column-prop-getters.js → esm2020/lib/utils/column-prop-getters.mjs} +0 -0
  46. package/{esm2015/lib/utils/column.js → esm2020/lib/utils/column.mjs} +0 -0
  47. package/{esm2015/lib/utils/elm-from-point.js → esm2020/lib/utils/elm-from-point.mjs} +0 -0
  48. package/{esm2015/lib/utils/id.js → esm2020/lib/utils/id.mjs} +0 -0
  49. package/{esm2015/lib/utils/keys.js → esm2020/lib/utils/keys.mjs} +0 -0
  50. package/{esm2015/lib/utils/math.js → esm2020/lib/utils/math.mjs} +0 -0
  51. package/esm2020/lib/utils/prefixes.mjs +38 -0
  52. package/{esm2015/lib/utils/row-height-cache.js → esm2020/lib/utils/row-height-cache.mjs} +0 -0
  53. package/{esm2015/lib/utils/selection.js → esm2020/lib/utils/selection.mjs} +0 -0
  54. package/{esm2015/lib/utils/sort.js → esm2020/lib/utils/sort.mjs} +0 -0
  55. package/{esm2015/lib/utils/throttle.js → esm2020/lib/utils/throttle.mjs} +0 -0
  56. package/{esm2015/lib/utils/translate.js → esm2020/lib/utils/translate.mjs} +0 -0
  57. package/{esm2015/lib/utils/tree.js → esm2020/lib/utils/tree.mjs} +0 -0
  58. package/{esm2015/public-api.js → esm2020/public-api.mjs} +0 -0
  59. package/{esm2015/swimlane-ngx-datatable.js → esm2020/swimlane-ngx-datatable.mjs} +0 -0
  60. package/fesm2015/{swimlane-ngx-datatable.js → swimlane-ngx-datatable.mjs} +4104 -3337
  61. package/fesm2015/swimlane-ngx-datatable.mjs.map +1 -0
  62. package/fesm2020/swimlane-ngx-datatable.mjs +5974 -0
  63. package/fesm2020/swimlane-ngx-datatable.mjs.map +1 -0
  64. package/lib/components/body/body-cell.component.d.ts +3 -0
  65. package/lib/components/body/body-group-header-template.directive.d.ts +3 -0
  66. package/lib/components/body/body-group-header.directive.d.ts +3 -0
  67. package/lib/components/body/body-row-wrapper.component.d.ts +3 -0
  68. package/lib/components/body/body-row.component.d.ts +3 -0
  69. package/lib/components/body/body.component.d.ts +3 -0
  70. package/lib/components/body/progress-bar.component.d.ts +3 -0
  71. package/lib/components/body/scroller.component.d.ts +3 -0
  72. package/lib/components/body/selection.component.d.ts +3 -0
  73. package/lib/components/body/summary/summary-row.component.d.ts +3 -0
  74. package/lib/components/columns/column-cell.directive.d.ts +3 -0
  75. package/lib/components/columns/column-header.directive.d.ts +3 -0
  76. package/lib/components/columns/column.directive.d.ts +3 -0
  77. package/lib/components/columns/tree.directive.d.ts +3 -0
  78. package/lib/components/datatable.component.d.ts +3 -0
  79. package/lib/components/footer/footer-template.directive.d.ts +3 -0
  80. package/lib/components/footer/footer.component.d.ts +3 -0
  81. package/lib/components/footer/footer.directive.d.ts +3 -0
  82. package/lib/components/footer/pager.component.d.ts +3 -0
  83. package/lib/components/header/header-cell.component.d.ts +3 -0
  84. package/lib/components/header/header.component.d.ts +3 -0
  85. package/lib/components/row-detail/row-detail-template.directive.d.ts +3 -0
  86. package/lib/components/row-detail/row-detail.directive.d.ts +3 -0
  87. package/lib/directives/draggable.directive.d.ts +3 -0
  88. package/lib/directives/long-press.directive.d.ts +3 -0
  89. package/lib/directives/orderable.directive.d.ts +3 -0
  90. package/lib/directives/resizeable.directive.d.ts +3 -0
  91. package/lib/directives/visibility.directive.d.ts +3 -0
  92. package/lib/ngx-datatable.module.d.ts +33 -0
  93. package/lib/services/column-changes.service.d.ts +3 -0
  94. package/lib/services/dimensions-helper.service.d.ts +3 -0
  95. package/lib/services/scrollbar-helper.service.d.ts +3 -0
  96. package/package.json +24 -12
  97. package/swimlane-ngx-datatable.d.ts +1 -0
  98. package/bundles/swimlane-ngx-datatable.umd.js +0 -5876
  99. package/bundles/swimlane-ngx-datatable.umd.js.map +0 -1
  100. package/bundles/swimlane-ngx-datatable.umd.min.js +0 -2
  101. package/bundles/swimlane-ngx-datatable.umd.min.js.map +0 -1
  102. package/esm2015/lib/components/body/body-cell.component.js +0 -361
  103. package/esm2015/lib/components/body/body-group-header-template.directive.js +0 -15
  104. package/esm2015/lib/components/body/body-group-header.directive.js +0 -54
  105. package/esm2015/lib/components/body/body-row-wrapper.component.js +0 -106
  106. package/esm2015/lib/components/body/body-row.component.js +0 -212
  107. package/esm2015/lib/components/body/body.component.js +0 -713
  108. package/esm2015/lib/components/body/progress-bar.component.js +0 -17
  109. package/esm2015/lib/components/body/scroller.component.js +0 -83
  110. package/esm2015/lib/components/body/selection.component.js +0 -140
  111. package/esm2015/lib/components/body/summary/summary-row.component.js +0 -81
  112. package/esm2015/lib/components/columns/column-cell.directive.js +0 -13
  113. package/esm2015/lib/components/columns/column-header.directive.js +0 -13
  114. package/esm2015/lib/components/columns/column.directive.js +0 -65
  115. package/esm2015/lib/components/columns/tree.directive.js +0 -13
  116. package/esm2015/lib/components/datatable.component.js +0 -925
  117. package/esm2015/lib/components/footer/footer-template.directive.js +0 -13
  118. package/esm2015/lib/components/footer/footer.component.js +0 -75
  119. package/esm2015/lib/components/footer/footer.directive.js +0 -22
  120. package/esm2015/lib/components/footer/pager.component.js +0 -136
  121. package/esm2015/lib/components/header/header-cell.component.js +0 -191
  122. package/esm2015/lib/components/header/header.component.js +0 -295
  123. package/esm2015/lib/components/row-detail/row-detail-template.directive.js +0 -15
  124. package/esm2015/lib/components/row-detail/row-detail.directive.js +0 -55
  125. package/esm2015/lib/directives/draggable.directive.js +0 -102
  126. package/esm2015/lib/directives/long-press.directive.js +0 -103
  127. package/esm2015/lib/directives/orderable.directive.js +0 -131
  128. package/esm2015/lib/directives/resizeable.directive.js +0 -89
  129. package/esm2015/lib/directives/visibility.directive.js +0 -62
  130. package/esm2015/lib/ngx-datatable.module.js +0 -96
  131. package/esm2015/lib/services/column-changes.service.js +0 -21
  132. package/esm2015/lib/services/dimensions-helper.service.js +0 -14
  133. package/esm2015/lib/services/scrollbar-helper.service.js +0 -34
  134. package/esm2015/lib/utils/prefixes.js +0 -40
  135. package/fesm2015/swimlane-ngx-datatable.js.map +0 -1
  136. package/swimlane-ngx-datatable.metadata.json +0 -1
@@ -1,713 +0,0 @@
1
- import { Component, Output, EventEmitter, Input, HostBinding, ChangeDetectorRef, ViewChild, ChangeDetectionStrategy } from '@angular/core';
2
- import { ScrollerComponent } from './scroller.component';
3
- import { columnsByPin, columnGroupWidths } from '../../utils/column';
4
- import { RowHeightCache } from '../../utils/row-height-cache';
5
- import { translateXY } from '../../utils/translate';
6
- export class DataTableBodyComponent {
7
- /**
8
- * Creates an instance of DataTableBodyComponent.
9
- */
10
- constructor(cd) {
11
- this.cd = cd;
12
- this.selected = [];
13
- this.scroll = new EventEmitter();
14
- this.page = new EventEmitter();
15
- this.activate = new EventEmitter();
16
- this.select = new EventEmitter();
17
- this.detailToggle = new EventEmitter();
18
- this.rowContextmenu = new EventEmitter(false);
19
- this.treeAction = new EventEmitter();
20
- this.rowHeightsCache = new RowHeightCache();
21
- this.temp = [];
22
- this.offsetY = 0;
23
- this.indexes = {};
24
- this.rowIndexes = new WeakMap();
25
- this.rowExpansions = [];
26
- /**
27
- * Get the height of the detail row.
28
- */
29
- this.getDetailRowHeight = (row, index) => {
30
- if (!this.rowDetail) {
31
- return 0;
32
- }
33
- const rowHeight = this.rowDetail.rowHeight;
34
- return typeof rowHeight === 'function' ? rowHeight(row, index) : rowHeight;
35
- };
36
- // declare fn here so we can get access to the `this` property
37
- this.rowTrackingFn = (index, row) => {
38
- const idx = this.getRowIndex(row);
39
- if (this.trackByProp) {
40
- return row[this.trackByProp];
41
- }
42
- else {
43
- return idx;
44
- }
45
- };
46
- }
47
- set pageSize(val) {
48
- this._pageSize = val;
49
- this.recalcLayout();
50
- }
51
- get pageSize() {
52
- return this._pageSize;
53
- }
54
- set rows(val) {
55
- this._rows = val;
56
- this.recalcLayout();
57
- }
58
- get rows() {
59
- return this._rows;
60
- }
61
- set columns(val) {
62
- this._columns = val;
63
- const colsByPin = columnsByPin(val);
64
- this.columnGroupWidths = columnGroupWidths(colsByPin, val);
65
- }
66
- get columns() {
67
- return this._columns;
68
- }
69
- set offset(val) {
70
- this._offset = val;
71
- if (!this.scrollbarV || (this.scrollbarV && !this.virtualization))
72
- this.recalcLayout();
73
- }
74
- get offset() {
75
- return this._offset;
76
- }
77
- set rowCount(val) {
78
- this._rowCount = val;
79
- this.recalcLayout();
80
- }
81
- get rowCount() {
82
- return this._rowCount;
83
- }
84
- get bodyWidth() {
85
- if (this.scrollbarH) {
86
- return this.innerWidth + 'px';
87
- }
88
- else {
89
- return '100%';
90
- }
91
- }
92
- set bodyHeight(val) {
93
- if (this.scrollbarV) {
94
- this._bodyHeight = val + 'px';
95
- }
96
- else {
97
- this._bodyHeight = 'auto';
98
- }
99
- this.recalcLayout();
100
- }
101
- get bodyHeight() {
102
- return this._bodyHeight;
103
- }
104
- /**
105
- * Returns if selection is enabled.
106
- */
107
- get selectEnabled() {
108
- return !!this.selectionType;
109
- }
110
- /**
111
- * Property that would calculate the height of scroll bar
112
- * based on the row heights cache for virtual scroll and virtualization. Other scenarios
113
- * calculate scroll height automatically (as height will be undefined).
114
- */
115
- get scrollHeight() {
116
- if (this.scrollbarV && this.virtualization && this.rowCount) {
117
- return this.rowHeightsCache.query(this.rowCount - 1);
118
- }
119
- // avoid TS7030: Not all code paths return a value.
120
- return undefined;
121
- }
122
- /**
123
- * Called after the constructor, initializing input properties
124
- */
125
- ngOnInit() {
126
- if (this.rowDetail) {
127
- this.listener = this.rowDetail.toggle.subscribe(({ type, value }) => {
128
- if (type === 'row') {
129
- this.toggleRowExpansion(value);
130
- }
131
- if (type === 'all') {
132
- this.toggleAllRows(value);
133
- }
134
- // Refresh rows after toggle
135
- // Fixes #883
136
- this.updateIndexes();
137
- this.updateRows();
138
- this.cd.markForCheck();
139
- });
140
- }
141
- if (this.groupHeader) {
142
- this.listener = this.groupHeader.toggle.subscribe(({ type, value }) => {
143
- if (type === 'group') {
144
- this.toggleRowExpansion(value);
145
- }
146
- if (type === 'all') {
147
- this.toggleAllRows(value);
148
- }
149
- // Refresh rows after toggle
150
- // Fixes #883
151
- this.updateIndexes();
152
- this.updateRows();
153
- this.cd.markForCheck();
154
- });
155
- }
156
- }
157
- /**
158
- * Called once, before the instance is destroyed.
159
- */
160
- ngOnDestroy() {
161
- if (this.rowDetail || this.groupHeader) {
162
- this.listener.unsubscribe();
163
- }
164
- }
165
- /**
166
- * Updates the Y offset given a new offset.
167
- */
168
- updateOffsetY(offset) {
169
- // scroller is missing on empty table
170
- if (!this.scroller) {
171
- return;
172
- }
173
- if (this.scrollbarV && this.virtualization && offset) {
174
- // First get the row Index that we need to move to.
175
- const rowIndex = this.pageSize * offset;
176
- offset = this.rowHeightsCache.query(rowIndex - 1);
177
- }
178
- else if (this.scrollbarV && !this.virtualization) {
179
- offset = 0;
180
- }
181
- this.scroller.setOffset(offset || 0);
182
- }
183
- /**
184
- * Body was scrolled, this is mainly useful for
185
- * when a user is server-side pagination via virtual scroll.
186
- */
187
- onBodyScroll(event) {
188
- const scrollYPos = event.scrollYPos;
189
- const scrollXPos = event.scrollXPos;
190
- // if scroll change, trigger update
191
- // this is mainly used for header cell positions
192
- if (this.offsetY !== scrollYPos || this.offsetX !== scrollXPos) {
193
- this.scroll.emit({
194
- offsetY: scrollYPos,
195
- offsetX: scrollXPos
196
- });
197
- }
198
- this.offsetY = scrollYPos;
199
- this.offsetX = scrollXPos;
200
- this.updateIndexes();
201
- this.updatePage(event.direction);
202
- this.updateRows();
203
- }
204
- /**
205
- * Updates the page given a direction.
206
- */
207
- updatePage(direction) {
208
- let offset = this.indexes.first / this.pageSize;
209
- if (direction === 'up') {
210
- offset = Math.ceil(offset);
211
- }
212
- else if (direction === 'down') {
213
- offset = Math.floor(offset);
214
- }
215
- if (direction !== undefined && !isNaN(offset)) {
216
- this.page.emit({ offset });
217
- }
218
- }
219
- /**
220
- * Updates the rows in the view port
221
- */
222
- updateRows() {
223
- const { first, last } = this.indexes;
224
- let rowIndex = first;
225
- let idx = 0;
226
- const temp = [];
227
- // if grouprowsby has been specified treat row paging
228
- // parameters as group paging parameters ie if limit 10 has been
229
- // specified treat it as 10 groups rather than 10 rows
230
- if (this.groupedRows) {
231
- let maxRowsPerGroup = 3;
232
- // if there is only one group set the maximum number of
233
- // rows per group the same as the total number of rows
234
- if (this.groupedRows.length === 1) {
235
- maxRowsPerGroup = this.groupedRows[0].value.length;
236
- }
237
- while (rowIndex < last && rowIndex < this.groupedRows.length) {
238
- // Add the groups into this page
239
- const group = this.groupedRows[rowIndex];
240
- this.rowIndexes.set(group, rowIndex);
241
- if (group.value) {
242
- // add indexes for each group item
243
- group.value.forEach((g, i) => {
244
- const _idx = `${rowIndex}-${i}`;
245
- this.rowIndexes.set(g, _idx);
246
- });
247
- }
248
- temp[idx] = group;
249
- idx++;
250
- // Group index in this context
251
- rowIndex++;
252
- }
253
- }
254
- else {
255
- while (rowIndex < last && rowIndex < this.rowCount) {
256
- const row = this.rows[rowIndex];
257
- if (row) {
258
- // add indexes for each row
259
- this.rowIndexes.set(row, rowIndex);
260
- temp[idx] = row;
261
- }
262
- idx++;
263
- rowIndex++;
264
- }
265
- }
266
- this.temp = temp;
267
- }
268
- /**
269
- * Get the row height
270
- */
271
- getRowHeight(row) {
272
- // if its a function return it
273
- if (typeof this.rowHeight === 'function') {
274
- return this.rowHeight(row);
275
- }
276
- return this.rowHeight;
277
- }
278
- /**
279
- * @param group the group with all rows
280
- */
281
- getGroupHeight(group) {
282
- let rowHeight = 0;
283
- if (group.value) {
284
- for (let index = 0; index < group.value.length; index++) {
285
- rowHeight += this.getRowAndDetailHeight(group.value[index]);
286
- }
287
- }
288
- return rowHeight;
289
- }
290
- /**
291
- * Calculate row height based on the expanded state of the row.
292
- */
293
- getRowAndDetailHeight(row) {
294
- let rowHeight = this.getRowHeight(row);
295
- const expanded = this.getRowExpanded(row);
296
- // Adding detail row height if its expanded.
297
- if (expanded) {
298
- rowHeight += this.getDetailRowHeight(row);
299
- }
300
- return rowHeight;
301
- }
302
- /**
303
- * Calculates the styles for the row so that the rows can be moved in 2D space
304
- * during virtual scroll inside the DOM. In the below case the Y position is
305
- * manipulated. As an example, if the height of row 0 is 30 px and row 1 is
306
- * 100 px then following styles are generated:
307
- *
308
- * transform: translate3d(0px, 0px, 0px); -> row0
309
- * transform: translate3d(0px, 30px, 0px); -> row1
310
- * transform: translate3d(0px, 130px, 0px); -> row2
311
- *
312
- * Row heights have to be calculated based on the row heights cache as we wont
313
- * be able to determine which row is of what height before hand. In the above
314
- * case the positionY of the translate3d for row2 would be the sum of all the
315
- * heights of the rows before it (i.e. row0 and row1).
316
- *
317
- * @param rows the row that needs to be placed in the 2D space.
318
- * @returns the CSS3 style to be applied
319
- *
320
- * @memberOf DataTableBodyComponent
321
- */
322
- getRowsStyles(rows) {
323
- const styles = {};
324
- // only add styles for the group if there is a group
325
- if (this.groupedRows) {
326
- styles.width = this.columnGroupWidths.total;
327
- }
328
- if (this.scrollbarV && this.virtualization) {
329
- let idx = 0;
330
- if (this.groupedRows) {
331
- // Get the latest row rowindex in a group
332
- const row = rows[rows.length - 1];
333
- idx = row ? this.getRowIndex(row) : 0;
334
- }
335
- else {
336
- idx = this.getRowIndex(rows);
337
- }
338
- // const pos = idx * rowHeight;
339
- // The position of this row would be the sum of all row heights
340
- // until the previous row position.
341
- const pos = this.rowHeightsCache.query(idx - 1);
342
- translateXY(styles, 0, pos);
343
- }
344
- return styles;
345
- }
346
- /**
347
- * Calculate bottom summary row offset for scrollbar mode.
348
- * For more information about cache and offset calculation
349
- * see description for `getRowsStyles` method
350
- *
351
- * @returns the CSS3 style to be applied
352
- *
353
- * @memberOf DataTableBodyComponent
354
- */
355
- getBottomSummaryRowStyles() {
356
- if (!this.scrollbarV || !this.rows || !this.rows.length) {
357
- return null;
358
- }
359
- const styles = { position: 'absolute' };
360
- const pos = this.rowHeightsCache.query(this.rows.length - 1);
361
- translateXY(styles, 0, pos);
362
- return styles;
363
- }
364
- /**
365
- * Hides the loading indicator
366
- */
367
- hideIndicator() {
368
- setTimeout(() => (this.loadingIndicator = false), 500);
369
- }
370
- /**
371
- * Updates the index of the rows in the viewport
372
- */
373
- updateIndexes() {
374
- let first = 0;
375
- let last = 0;
376
- if (this.scrollbarV) {
377
- if (this.virtualization) {
378
- // Calculation of the first and last indexes will be based on where the
379
- // scrollY position would be at. The last index would be the one
380
- // that shows up inside the view port the last.
381
- const height = parseInt(this.bodyHeight, 0);
382
- first = this.rowHeightsCache.getRowIndex(this.offsetY);
383
- last = this.rowHeightsCache.getRowIndex(height + this.offsetY) + 1;
384
- }
385
- else {
386
- // If virtual rows are not needed
387
- // We render all in one go
388
- first = 0;
389
- last = this.rowCount;
390
- }
391
- }
392
- else {
393
- // The server is handling paging and will pass an array that begins with the
394
- // element at a specified offset. first should always be 0 with external paging.
395
- if (!this.externalPaging) {
396
- first = Math.max(this.offset * this.pageSize, 0);
397
- }
398
- last = Math.min(first + this.pageSize, this.rowCount);
399
- }
400
- this.indexes = { first, last };
401
- }
402
- /**
403
- * Refreshes the full Row Height cache. Should be used
404
- * when the entire row array state has changed.
405
- */
406
- refreshRowHeightCache() {
407
- if (!this.scrollbarV || (this.scrollbarV && !this.virtualization)) {
408
- return;
409
- }
410
- // clear the previous row height cache if already present.
411
- // this is useful during sorts, filters where the state of the
412
- // rows array is changed.
413
- this.rowHeightsCache.clearCache();
414
- // Initialize the tree only if there are rows inside the tree.
415
- if (this.rows && this.rows.length) {
416
- const rowExpansions = new Set();
417
- for (const row of this.rows) {
418
- if (this.getRowExpanded(row)) {
419
- rowExpansions.add(row);
420
- }
421
- }
422
- this.rowHeightsCache.initCache({
423
- rows: this.rows,
424
- rowHeight: this.rowHeight,
425
- detailRowHeight: this.getDetailRowHeight,
426
- externalVirtual: this.scrollbarV && this.externalPaging,
427
- rowCount: this.rowCount,
428
- rowIndexes: this.rowIndexes,
429
- rowExpansions
430
- });
431
- }
432
- }
433
- /**
434
- * Gets the index for the view port
435
- */
436
- getAdjustedViewPortIndex() {
437
- // Capture the row index of the first row that is visible on the viewport.
438
- // If the scroll bar is just below the row which is highlighted then make that as the
439
- // first index.
440
- const viewPortFirstRowIndex = this.indexes.first;
441
- if (this.scrollbarV && this.virtualization) {
442
- const offsetScroll = this.rowHeightsCache.query(viewPortFirstRowIndex - 1);
443
- return offsetScroll <= this.offsetY ? viewPortFirstRowIndex - 1 : viewPortFirstRowIndex;
444
- }
445
- return viewPortFirstRowIndex;
446
- }
447
- /**
448
- * Toggle the Expansion of the row i.e. if the row is expanded then it will
449
- * collapse and vice versa. Note that the expanded status is stored as
450
- * a part of the row object itself as we have to preserve the expanded row
451
- * status in case of sorting and filtering of the row set.
452
- */
453
- toggleRowExpansion(row) {
454
- // Capture the row index of the first row that is visible on the viewport.
455
- const viewPortFirstRowIndex = this.getAdjustedViewPortIndex();
456
- const rowExpandedIdx = this.getRowExpandedIdx(row, this.rowExpansions);
457
- const expanded = rowExpandedIdx > -1;
458
- // If the detailRowHeight is auto --> only in case of non-virtualized scroll
459
- if (this.scrollbarV && this.virtualization) {
460
- const detailRowHeight = this.getDetailRowHeight(row) * (expanded ? -1 : 1);
461
- // const idx = this.rowIndexes.get(row) || 0;
462
- const idx = this.getRowIndex(row);
463
- this.rowHeightsCache.update(idx, detailRowHeight);
464
- }
465
- // Update the toggled row and update thive nevere heights in the cache.
466
- if (expanded) {
467
- this.rowExpansions.splice(rowExpandedIdx, 1);
468
- }
469
- else {
470
- this.rowExpansions.push(row);
471
- }
472
- this.detailToggle.emit({
473
- rows: [row],
474
- currentIndex: viewPortFirstRowIndex
475
- });
476
- }
477
- /**
478
- * Expand/Collapse all the rows no matter what their state is.
479
- */
480
- toggleAllRows(expanded) {
481
- // clear prev expansions
482
- this.rowExpansions = [];
483
- // Capture the row index of the first row that is visible on the viewport.
484
- const viewPortFirstRowIndex = this.getAdjustedViewPortIndex();
485
- if (expanded) {
486
- for (const row of this.rows) {
487
- this.rowExpansions.push(row);
488
- }
489
- }
490
- if (this.scrollbarV) {
491
- // Refresh the full row heights cache since every row was affected.
492
- this.recalcLayout();
493
- }
494
- // Emit all rows that have been expanded.
495
- this.detailToggle.emit({
496
- rows: this.rows,
497
- currentIndex: viewPortFirstRowIndex
498
- });
499
- }
500
- /**
501
- * Recalculates the table
502
- */
503
- recalcLayout() {
504
- this.refreshRowHeightCache();
505
- this.updateIndexes();
506
- this.updateRows();
507
- }
508
- /**
509
- * Tracks the column
510
- */
511
- columnTrackingFn(index, column) {
512
- return column.$$id;
513
- }
514
- /**
515
- * Gets the row pinning group styles
516
- */
517
- stylesByGroup(group) {
518
- const widths = this.columnGroupWidths;
519
- const offsetX = this.offsetX;
520
- const styles = {
521
- width: `${widths[group]}px`
522
- };
523
- if (group === 'left') {
524
- translateXY(styles, offsetX, 0);
525
- }
526
- else if (group === 'right') {
527
- const bodyWidth = parseInt(this.innerWidth + '', 0);
528
- const totalDiff = widths.total - bodyWidth;
529
- const offsetDiff = totalDiff - offsetX;
530
- const offset = offsetDiff * -1;
531
- translateXY(styles, offset, 0);
532
- }
533
- return styles;
534
- }
535
- /**
536
- * Returns if the row was expanded and set default row expansion when row expansion is empty
537
- */
538
- getRowExpanded(row) {
539
- if (this.rowExpansions.length === 0 && this.groupExpansionDefault) {
540
- for (const group of this.groupedRows) {
541
- this.rowExpansions.push(group);
542
- }
543
- }
544
- return this.getRowExpandedIdx(row, this.rowExpansions) > -1;
545
- }
546
- getRowExpandedIdx(row, expanded) {
547
- if (!expanded || !expanded.length)
548
- return -1;
549
- const rowId = this.rowIdentity(row);
550
- return expanded.findIndex(r => {
551
- const id = this.rowIdentity(r);
552
- return id === rowId;
553
- });
554
- }
555
- /**
556
- * Gets the row index given a row
557
- */
558
- getRowIndex(row) {
559
- return this.rowIndexes.get(row) || 0;
560
- }
561
- onTreeAction(row) {
562
- this.treeAction.emit({ row });
563
- }
564
- }
565
- DataTableBodyComponent.decorators = [
566
- { type: Component, args: [{
567
- selector: 'datatable-body',
568
- template: `
569
- <datatable-progress *ngIf="loadingIndicator"> </datatable-progress>
570
- <datatable-selection
571
- #selector
572
- [selected]="selected"
573
- [rows]="rows"
574
- [selectCheck]="selectCheck"
575
- [selectEnabled]="selectEnabled"
576
- [selectionType]="selectionType"
577
- [rowIdentity]="rowIdentity"
578
- (select)="select.emit($event)"
579
- (activate)="activate.emit($event)"
580
- >
581
- <datatable-scroller
582
- *ngIf="rows?.length"
583
- [scrollbarV]="scrollbarV"
584
- [scrollbarH]="scrollbarH"
585
- [scrollHeight]="scrollHeight"
586
- [scrollWidth]="columnGroupWidths?.total"
587
- (scroll)="onBodyScroll($event)"
588
- >
589
- <datatable-summary-row
590
- *ngIf="summaryRow && summaryPosition === 'top'"
591
- [rowHeight]="summaryHeight"
592
- [offsetX]="offsetX"
593
- [innerWidth]="innerWidth"
594
- [rows]="rows"
595
- [columns]="columns"
596
- >
597
- </datatable-summary-row>
598
- <datatable-row-wrapper
599
- [groupedRows]="groupedRows"
600
- *ngFor="let group of temp; let i = index; trackBy: rowTrackingFn"
601
- [innerWidth]="innerWidth"
602
- [ngStyle]="getRowsStyles(group)"
603
- [rowDetail]="rowDetail"
604
- [groupHeader]="groupHeader"
605
- [offsetX]="offsetX"
606
- [detailRowHeight]="getDetailRowHeight(group && group[i], i)"
607
- [row]="group"
608
- [expanded]="getRowExpanded(group)"
609
- [rowIndex]="getRowIndex(group && group[i])"
610
- (rowContextmenu)="rowContextmenu.emit($event)"
611
- >
612
- <datatable-body-row
613
- *ngIf="!groupedRows; else groupedRowsTemplate"
614
- tabindex="-1"
615
- [isSelected]="selector.getRowSelected(group)"
616
- [innerWidth]="innerWidth"
617
- [offsetX]="offsetX"
618
- [columns]="columns"
619
- [rowHeight]="getRowHeight(group)"
620
- [row]="group"
621
- [rowIndex]="getRowIndex(group)"
622
- [expanded]="getRowExpanded(group)"
623
- [rowClass]="rowClass"
624
- [displayCheck]="displayCheck"
625
- [treeStatus]="group && group.treeStatus"
626
- (treeAction)="onTreeAction(group)"
627
- (activate)="selector.onActivate($event, indexes.first + i)"
628
- >
629
- </datatable-body-row>
630
- <ng-template #groupedRowsTemplate>
631
- <datatable-body-row
632
- *ngFor="let row of group.value; let i = index; trackBy: rowTrackingFn"
633
- tabindex="-1"
634
- [isSelected]="selector.getRowSelected(row)"
635
- [innerWidth]="innerWidth"
636
- [offsetX]="offsetX"
637
- [columns]="columns"
638
- [rowHeight]="getRowHeight(row)"
639
- [row]="row"
640
- [group]="group.value"
641
- [rowIndex]="getRowIndex(row)"
642
- [expanded]="getRowExpanded(row)"
643
- [rowClass]="rowClass"
644
- (activate)="selector.onActivate($event, i)"
645
- >
646
- </datatable-body-row>
647
- </ng-template>
648
- </datatable-row-wrapper>
649
- <datatable-summary-row
650
- *ngIf="summaryRow && summaryPosition === 'bottom'"
651
- [ngStyle]="getBottomSummaryRowStyles()"
652
- [rowHeight]="summaryHeight"
653
- [offsetX]="offsetX"
654
- [innerWidth]="innerWidth"
655
- [rows]="rows"
656
- [columns]="columns"
657
- >
658
- </datatable-summary-row>
659
- </datatable-scroller>
660
- <div class="empty-row" *ngIf="!rows?.length && !loadingIndicator" [innerHTML]="emptyMessage"></div>
661
- </datatable-selection>
662
- `,
663
- changeDetection: ChangeDetectionStrategy.OnPush,
664
- host: {
665
- class: 'datatable-body'
666
- }
667
- },] }
668
- ];
669
- DataTableBodyComponent.ctorParameters = () => [
670
- { type: ChangeDetectorRef }
671
- ];
672
- DataTableBodyComponent.propDecorators = {
673
- scrollbarV: [{ type: Input }],
674
- scrollbarH: [{ type: Input }],
675
- loadingIndicator: [{ type: Input }],
676
- externalPaging: [{ type: Input }],
677
- rowHeight: [{ type: Input }],
678
- offsetX: [{ type: Input }],
679
- emptyMessage: [{ type: Input }],
680
- selectionType: [{ type: Input }],
681
- selected: [{ type: Input }],
682
- rowIdentity: [{ type: Input }],
683
- rowDetail: [{ type: Input }],
684
- groupHeader: [{ type: Input }],
685
- selectCheck: [{ type: Input }],
686
- displayCheck: [{ type: Input }],
687
- trackByProp: [{ type: Input }],
688
- rowClass: [{ type: Input }],
689
- groupedRows: [{ type: Input }],
690
- groupExpansionDefault: [{ type: Input }],
691
- innerWidth: [{ type: Input }],
692
- groupRowsBy: [{ type: Input }],
693
- virtualization: [{ type: Input }],
694
- summaryRow: [{ type: Input }],
695
- summaryPosition: [{ type: Input }],
696
- summaryHeight: [{ type: Input }],
697
- pageSize: [{ type: Input }],
698
- rows: [{ type: Input }],
699
- columns: [{ type: Input }],
700
- offset: [{ type: Input }],
701
- rowCount: [{ type: Input }],
702
- bodyWidth: [{ type: HostBinding, args: ['style.width',] }],
703
- bodyHeight: [{ type: Input }, { type: HostBinding, args: ['style.height',] }],
704
- scroll: [{ type: Output }],
705
- page: [{ type: Output }],
706
- activate: [{ type: Output }],
707
- select: [{ type: Output }],
708
- detailToggle: [{ type: Output }],
709
- rowContextmenu: [{ type: Output }],
710
- treeAction: [{ type: Output }],
711
- scroller: [{ type: ViewChild, args: [ScrollerComponent,] }]
712
- };
713
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYm9keS5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zd2ltbGFuZS9uZ3gtZGF0YXRhYmxlL3NyYy9saWIvY29tcG9uZW50cy9ib2R5L2JvZHkuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxTQUFTLEVBQ1QsTUFBTSxFQUNOLFlBQVksRUFDWixLQUFLLEVBQ0wsV0FBVyxFQUNYLGlCQUFpQixFQUNqQixTQUFTLEVBR1QsdUJBQXVCLEVBQ3hCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLHNCQUFzQixDQUFDO0FBRXpELE9BQU8sRUFBRSxZQUFZLEVBQUUsaUJBQWlCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDOUQsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBd0dwRCxNQUFNLE9BQU8sc0JBQXNCO0lBaUpqQzs7T0FFRztJQUNILFlBQW9CLEVBQXFCO1FBQXJCLE9BQUUsR0FBRixFQUFFLENBQW1CO1FBM0loQyxhQUFRLEdBQVUsRUFBRSxDQUFDO1FBd0ZwQixXQUFNLEdBQXNCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDL0MsU0FBSSxHQUFzQixJQUFJLFlBQVksRUFBRSxDQUFDO1FBQzdDLGFBQVEsR0FBc0IsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNqRCxXQUFNLEdBQXNCLElBQUksWUFBWSxFQUFFLENBQUM7UUFDL0MsaUJBQVksR0FBc0IsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUNyRCxtQkFBYyxHQUFHLElBQUksWUFBWSxDQUFrQyxLQUFLLENBQUMsQ0FBQztRQUMxRSxlQUFVLEdBQXNCLElBQUksWUFBWSxFQUFFLENBQUM7UUF3QjdELG9CQUFlLEdBQW1CLElBQUksY0FBYyxF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QUs7MkJBQ0wsS0FBSzswQkFDTCxLQUFLO3VCQUNMLEtBQUs7MEJBQ0wsS0FBSztvQ0FDTCxLQUFLO3lCQUNMLEtBQUs7MEJBQ0wsS0FBSzs2QkFDTCxLQUFLO3lCQUNMLEtBQUs7OEJBQ0wsS0FBSzs0QkFDTCxLQUFLO3VCQUVMLEtBQUs7bUJBU0wsS0FBSztzQkFTTCxLQUFLO3FCQVVMLEtBQUs7dUJBU0wsS0FBSzt3QkFTTCxXQUFXLFNBQUMsYUFBYTt5QkFTekIsS0FBSyxZQUNMLFdBQVcsU0FBQyxjQUFjO3FCQWUxQixNQUFNO21CQUNOLE1BQU07dUJBQ04sTUFBTTtxQkFDTixNQUFNOzJCQUNOLE1BQU07NkJBQ04sTUFBTTt5QkFDTixNQUFNO3VCQUVOLFNBQVMsU0FBQyxpQkFBaUIiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQge1xuICBDb21wb25lbnQsXG4gIE91dHB1dCxcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgSG9zdEJpbmRpbmcsXG4gIENoYW5nZURldGVjdG9yUmVmLFxuICBWaWV3Q2hpbGQsXG4gIE9uSW5pdCxcbiAgT25EZXN0cm95LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneVxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IFNjcm9sbGVyQ29tcG9uZW50IH0gZnJvbSAnLi9zY3JvbGxlci5jb21wb25lbnQnO1xuaW1wb3J0IHsgU2VsZWN0aW9uVHlwZSB9IGZyb20gJy4uLy4uL3R5cGVzL3NlbGVjdGlvbi50eXBlJztcbmltcG9ydCB7IGNvbHVtbnNCeVBpbiwgY29sdW1uR3JvdXBXaWR0aHMgfSBmcm9tICcuLi8uLi91dGlscy9jb2x1bW4nO1xuaW1wb3J0IHsgUm93SGVpZ2h0Q2FjaGUgfSBmcm9tICcuLi8uLi91dGlscy9yb3ctaGVpZ2h0LWNhY2hlJztcbmltcG9ydCB7IHRyYW5zbGF0ZVhZIH0gZnJvbSAnLi4vLi4vdXRpbHMvdHJhbnNsYXRlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnZGF0YXRhYmxlLWJvZHknLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkYXRhdGFibGUtcHJvZ3Jlc3MgKm5nSWY9XCJsb2FkaW5nSW5kaWNhdG9yXCI+IDwvZGF0YXRhYmxlLXByb2dyZXNzPlxuICAgIDxkYXRhdGFibGUtc2VsZWN0aW9uXG4gICAgICAjc2VsZWN0b3JcbiAgICAgIFtzZWxlY3RlZF09XCJzZWxlY3RlZFwiXG4gICAgICBbcm93c109XCJyb3dzXCJcbiAgICAgIFtzZWxlY3RDaGVja109XCJzZWxlY3RDaGVja1wiXG4gICAgICBbc2VsZWN0RW5hYmxlZF09XCJzZWxlY3RFbmFibGVkXCJcbiAgICAgIFtzZWxlY3Rpb25UeXBlXT1cInNlbGVjdGlvblR5cGVcIlxuICAgICAgW3Jvd0lkZW50aXR5XT1cInJvd0lkZW50aXR5XCJcbiAgICAgIChzZWxlY3QpPVwic2VsZWN0LmVtaXQoJGV2ZW50KVwiXG4gICAgICAoYWN0aXZhdGUpPVwiYWN0aXZhdGUuZW1pdCgkZXZlbnQpXCJcbiAgICA+XG4gICAgICA8ZGF0YXRhYmxlLXNjcm9sbGVyXG4gICAgICAgICpuZ0lmPVwicm93cz8ubGVuZ3RoXCJcbiAgICAgICAgW3Njcm9sbGJhclZdPVwic2Nyb2xsYmFyVlwiXG4gICAgICAgIFtzY3JvbGxiYXJIXT1cInNjcm9sbGJhckhcIlxuICAgICAgICBbc2Nyb2xsSGVpZ2h0XT1cInNjcm9sbEhlaWdodFwiXG4gICAgICAgIFtzY3JvbGxXaWR0aF09XCJjb2x1bW5Hcm91cFdpZHRocz8udG90YWxcIlxuICAgICAgICAoc2Nyb2xsKT1cIm9uQm9keVNjcm9sbCgkZXZlbnQpXCJcbiAgICAgID5cbiAgICAgICAgPGRhdGF0YWJsZS1zdW1tYXJ5LXJvd1xuICAgICAgICAgICpuZ0lmPVwic3VtbWFyeVJvdyAmJiBzdW1tYXJ5UG9zaXRpb24gPT09ICd0b3AnXCJcbiAgICAgICAgICBbcm93SGVpZ2h0XT1cInN1bW1hcnlIZWlnaHRcIlxuICAgICAgICAgIFtvZmZzZXRYXT1cIm9mZnNldFhcIlxuICAgICAgICAgIFtpbm5lcldpZHRoXT1cImlubmVyV2lkdGhcIlxuICAgICAgICAgIFtyb3dzXT1cInJvd3NcIlxuICAgICAgICAgIFtjb2x1bW5zXT1cImNvbHVtbnNcIlxuICAgICAgICA+XG4gICAgICAgIDwvZGF0YXRhYmxlLXN1bW1hcnktcm93PlxuICAgICAgICA8ZGF0YXRhYmxlLXJvdy13cmFwcGVyXG4gICAgICAgICAgW2dyb3VwZWRSb3dzXT1cImdyb3VwZWRSb3dzXCJcbiAgICAgICAgICAqbmdGb3I9XCJsZXQgZ3JvdXAgb2YgdGVtcDsgbGV0IGkgPSBpbmRleDsgdHJhY2tCeTogcm93VHJhY2tpbmdGblwiXG4gICAgICAgICAgW2lubmVyV2lkdGhdPVwiaW5uZXJXaWR0aFwiXG4gICAgICAgICAgW25nU3R5bGVdPVwiZ2V0Um93c1N0eWxlcyhncm91cClcIlxuICAgICAgICAgIFtyb3dEZXRhaWxdPVwicm93RGV0YWlsXCJcbiAgICAgICAgICBbZ3JvdXBIZWFkZXJdPVwiZ3JvdXBIZWFkZXJcIlxuICAgICAgICAgIFtvZmZzZXRYXT1cIm9mZnNldFhcIlxuICAgICAgICAgIFtkZXRhaWxSb3dIZWlnaHRdPVwiZ2V0RGV0YWlsUm93SGVpZ2h0KGdyb3VwICYmIGdyb3VwW2ldLCBpKVwiXG4gICAgICAgICAgW3Jvd109XCJncm91cFwiXG4gICAgICAgICAgW2V4cGFuZGVkXT1cImdldFJvd0V4cGFuZGVkKGdyb3VwKVwiXG4gICAgICAgICAgW3Jvd0luZGV4XT1cImdldFJvd0luZGV4KGdyb3VwICYmIGdyb3VwW2ldKVwiXG4gICAgICAgICAgKHJvd0NvbnRleHRtZW51KT1cInJvd0NvbnRleHRtZW51LmVtaXQoJGV2ZW50KVwiXG4gICAgICAgID5cbiAgICAgICAgICA8ZGF0YXRhYmxlLWJvZHktcm93XG4gICAgICAgICAgICAqbmdJZj1cIiFncm91cGVkUm93czsgZWxzZSBncm91cGVkUm93c1RlbXBsYXRlXCJcbiAgICAgICAgICAgIHRhYmluZGV4PVwiLTFcIlxuICAgICAgICAgICAgW2lzU2VsZWN0ZWRdPVwic2VsZWN0b3IuZ2V0Um93U2VsZWN0ZWQoZ3JvdXApXCJcbiAgICAgICAgICAgIFtpbm5lcldpZHRoXT1cImlubmVyV2lkdGhcIlxuICAgICAgICAgICAgW29mZnNldFhdPVwib2Zmc2V0WFwiXG4gICAgICAgICAgICBbY29sdW1uc109XCJjb2x1bW5zXCJcbiAgICAgICAgICAgIFtyb3dIZWlnaHRdPVwiZ2V0Um93SGVpZ2h0KGdyb3VwKVwiXG4gICAgICAgICAgICBbcm93XT1cImdyb3VwXCJcbiAgICAgICAgICAgIFtyb3dJbmRleF09XCJnZXRSb3dJbmRleChncm91cClcIlxuICAgICAgICAgICAgW2V4cGFuZGVkXT1cImdldFJvd0V4cGFuZGVkKGdyb3VwKVwiXG4gICAgICAgICAgICBbcm93Q2xhc3NdPVwicm93Q2xhc3NcIlxuICAgICAgICAgICAgW2Rpc3BsYXlDaGVja109XCJkaXNwbGF5Q2hlY2tcIlxuICAgICAgICAgICAgW3RyZWVTdGF0dXNdPVwiZ3JvdXAgJiYgZ3JvdXAudHJlZVN0YXR1c1wiXG4gICAgICAgICAgICAodHJlZUFjdGlvbik9XCJvblRyZWVBY3Rpb24oZ3JvdXApXCJcbiAgICAgICAgICAgIChhY3RpdmF0ZSk9XCJzZWxlY3Rvci5vbkFjdGl2YXRlKCRldmVudCwgaW5kZXhlcy5maXJzdCArIGkpXCJcbiAgICAgICAgICA+XG4gICAgICAgICAgPC9kYXRhdGFibGUtYm9keS1yb3c+XG4gICAgICAgICAgPG5nLXRlbXBsYXRlICNncm91cGVkUm93c1RlbXBsYXRlPlxuICAgICAgICAgICAgPGRhdGF0YWJsZS1ib2R5LXJvd1xuICAgICAgICAgICAgICAqbmdGb3I9XCJsZXQgcm93IG9mIGdyb3VwLnZhbHVlOyBsZXQgaSA9IGluZGV4OyB0cmFja0J5OiByb3dUcmFja2luZ0ZuXCJcbiAgICAgICAgICAgICAgdGFiaW5kZXg9XCItMVwiXG4gICAgICAgICAgICAgIFtpc1NlbGVjdGVkXT1cInNlbGVjdG9yLmdldFJvd1NlbGVjdGVkKHJvdylcIlxuICAgICAgICAgICAgICBbaW5uZXJXaWR0aF09XCJpbm5lcldpZHRoXCJcbiAgICAgICAgICAgICAgW29mZnNldFhdPVwib2Zmc2V0WFwiXG4gICAgICAgICAgICAgIFtjb2x1bW5zXT1cImNvbHVtbnNcIlxuICAgICAgICAgICAgICBbcm93SGVpZ2h0XT1cImdldFJvd0hlaWdodChyb3cpXCJcbiAgICAgICAgICAgICAgW3Jvd109XCJyb3dcIlxuICAgICAgICAgICAgICBbZ3JvdXBdPVwiZ3JvdXAudmFsdWVcIlxuICAgICAgICAgICAgICBbcm93SW5kZXhdPVwiZ2V0Um93SW5kZXgocm93KVwiXG4gICAgICAgICAgICAgIFtleHBhbmRlZF09XCJnZXRSb3dFeHBhbmRlZChyb3cpXCJcbiAgICAgICAgICAgICAgW3Jvd0NsYXNzXT1cInJvd0NsYXNzXCJcbiAgICAgICAgICAgICAgKGFjdGl2YXRlKT1cInNlbGVjdG9yLm9uQWN0aXZhdGUoJGV2ZW50LCBpKVwiXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICA8L2RhdGF0YWJsZS1ib2R5LXJvdz5cbiAgICAgICAgICA8L25nLXRlbXBsYXRlPlxuICAgICAgICA8L2RhdGF0YWJsZS1yb3ctd3JhcHBlcj5cbiAgICAgICAgPGRhdGF0YWJsZS1zdW1tYXJ5LXJvd1xuICAgICAgICAgICpuZ0lmPVwic3VtbWFyeVJvdyAmJiBzdW1tYXJ5UG9zaXRpb24gPT09ICdib3R0b20nXCJcbiAgICAgICAgICBbbmdTdHlsZV09XCJnZXRCb3R0b21TdW1tYXJ5Um93U3R5bGVzKClcIlxuICAgICAgICAgIFtyb3dIZWlnaHRdPVwic3VtbWFyeUhlaWdodFwiXG4gICAgICAgICAgW29mZnNldFhdPVwib2Zmc2V0WFwiXG4gICAgICAgICAgW2lubmVyV2lkdGhdPVwiaW5uZXJXaWR0aFwiXG4gICAgICAgICAgW3Jvd3NdPVwicm93c1wiXG4gICAgICAgICAgW2NvbHVtbnNdPVwiY29sdW1uc1wiXG4gICAgICAgID5cbiAgICAgICAgPC9kYXRhdGFibGUtc3VtbWFyeS1yb3c+XG4gICAgICA8L2RhdGF0YWJsZS1zY3JvbGxlcj5cbiAgICAgIDxkaXYgY2xhc3M9XCJlbXB0eS1yb3dcIiAqbmdJZj1cIiFyb3dzPy5sZW5ndGggJiYgIWxvYWRpbmdJbmRpY2F0b3JcIiBbaW5uZXJIVE1MXT1cImVtcHR5TWVzc2FnZVwiPjwvZGl2PlxuICAgIDwvZGF0YXRhYmxlLXNlbGVjdGlvbj5cbiAgYCxcbiAgY2hhbmdlRGV0ZWN0aW9uOiBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneS5PblB1c2gsXG4gIGhvc3Q6IHtcbiAgICBjbGFzczogJ2RhdGF0YWJsZS1ib2R5J1xuICB9XG59KVxuZXhwb3J0IGNsYXNzIERhdGFUYWJsZUJvZHlDb21wb25lbnQgaW1wbGVtZW50cyBPbkluaXQsIE9uRGVzdHJveSB7XG4gIEBJbnB1dCgpIHNjcm9sbGJhclY6IGJvb2xlYW47XG4gIEBJbnB1dCgpIHNjcm9sbGJhckg6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGxvYWRpbmdJbmRpY2F0b3I6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGV4dGVybmFsUGFnaW5nOiBib29sZWFuO1xuICBASW5wdXQoKSByb3dIZWlnaHQ6IG51bWJlciB8ICdhdXRvJyB8ICgocm93PzogYW55KSA9PiBudW1iZXIpO1xuICBASW5wdXQoKSBvZmZzZXRYOiBudW1iZXI7XG4gIEBJbnB1dCgpIGVtcHR5TWVzc2FnZTogc3RyaW5nO1xuICBASW5wdXQoKSBzZWxlY3Rpb25UeXBlOiBTZWxlY3Rpb25UeXBlO1xuICBASW5wdXQoKSBzZWxlY3RlZDogYW55W10gPSBbXTtcbiAgQElucHV0KCkgcm93SWRlbnRpdHk6IGFueTtcbiAgQElucHV0KCkgcm93RGV0YWlsOiBhbnk7XG4gIEBJbnB1dCgpIGdyb3VwSGVhZGVyOiBhbnk7XG4gIEBJbnB1dCgpIHNlbGVjdENoZWNrOiBhbnk7XG4gIEBJbnB1dCgpIGRpc3BsYXlDaGVjazogYW55O1xuICBASW5wdXQoKSB0cmFja0J5UHJvcDogc3RyaW5nO1xuICBASW5wdXQoKSByb3dDbGFzczogYW55O1xuICBASW5wdXQoKSBncm91cGVkUm93czogYW55O1xuICBASW5wdXQoKSBncm91cEV4cGFuc2lvbkRlZmF1bHQ6IGJvb2xlYW47XG4gIEBJbnB1dCgpIGlubmVyV2lkdGg6IG51bWJlcjtcbiAgQElucHV0KCkgZ3JvdXBSb3dzQnk6IHN0cmluZztcbiAgQElucHV0KCkgdmlydHVhbGl6YXRpb246IGJvb2xlYW47XG4gIEBJbnB1dCgpIHN1bW1hcnlSb3c6IGJvb2xlYW47XG4gIEBJbnB1dCgpIHN1bW1hcnlQb3NpdGlvbjogc3RyaW5nO1xuICBASW5wdXQoKSBzdW1tYXJ5SGVpZ2h0OiBudW1iZXI7XG5cbiAgQElucHV0KCkgc2V0IHBhZ2VTaXplKHZhbDogbnVtYmVyKSB7XG4gICAgdGhpcy5fcGFnZVNpemUgPSB2YWw7XG4gICAgdGhpcy5yZWNhbGNMYXlvdXQoKTtcbiAgfVxuXG4gIGdldCBwYWdlU2l6ZSgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9wYWdlU2l6ZTtcbiAgfVxuXG4gIEBJbnB1dCgpIHNldCByb3dzKHZhbDogYW55W10pIHtcbiAgICB0aGlzLl9yb3dzID0gdmFsO1xuICAgIHRoaXMucmVjYWxjTGF5b3V0KCk7XG4gIH1cblxuICBnZXQgcm93cygpOiBhbnlbXSB7XG4gICAgcmV0dXJuIHRoaXMuX3Jvd3M7XG4gIH1cblxuICBASW5wdXQoKSBzZXQgY29sdW1ucyh2YWw6IGFueVtdKSB7XG4gICAgdGhpcy5fY29sdW1ucyA9IHZhbDtcbiAgICBjb25zdCBjb2xzQnlQaW4gPSBjb2x1bW5zQnlQaW4odmFsKTtcbiAgICB0aGlzLmNvbHVtbkdyb3VwV2lkdGhzID0gY29sdW1uR3JvdXBXaWR0aHMoY29sc0J5UGluLCB2YWwpO1xuICB9XG5cbiAgZ2V0IGNvbHVtbnMoKTogYW55W10ge1xuICAgIHJldHVybiB0aGlzLl9jb2x1bW5zO1xuICB9XG5cbiAgQElucHV0KCkgc2V0IG9mZnNldCh2YWw6IG51bWJlcikge1xuICAgIHRoaXMuX29mZnNldCA9IHZhbDtcbiAgICBpZiAoIXRoaXMuc2Nyb2xsYmFyViB8fCAodGhpcy5zY3JvbGxiYXJWICYmICF0aGlzLnZpcnR1YWxpemF0aW9uKSkgdGhpcy5yZWNhbGNMYXlvdXQoKTtcbiAgfVxuXG4gIGdldCBvZmZzZXQoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5fb2Zmc2V0O1xuICB9XG5cbiAgQElucHV0KCkgc2V0IHJvd0NvdW50KHZhbDogbnVtYmVyKSB7XG4gICAgdGhpcy5fcm93Q291bnQgPSB2YWw7XG4gICAgdGhpcy5yZWNhbGNMYXlvdXQoKTtcbiAgfVxuXG4gIGdldCByb3dDb3VudCgpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLl9yb3dDb3VudDtcbiAgfVxuXG4gIEBIb3N0QmluZGluZygnc3R5bGUud2lkdGgnKVxuICBnZXQgYm9keVdpZHRoKCk6IHN0cmluZyB7XG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFySCkge1xuICAgICAgcmV0dXJuIHRoaXMuaW5uZXJXaWR0aCArICdweCc7XG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiAnMTAwJSc7XG4gICAgfVxuICB9XG5cbiAgQElucHV0KClcbiAgQEhvc3RCaW5kaW5nKCdzdHlsZS5oZWlnaHQnKVxuICBzZXQgYm9keUhlaWdodCh2YWwpIHtcbiAgICBpZiAodGhpcy5zY3JvbGxiYXJWKSB7XG4gICAgICB0aGlzLl9ib2R5SGVpZ2h0ID0gdmFsICsgJ3B4JztcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5fYm9keUhlaWdodCA9ICdhdXRvJztcbiAgICB9XG5cbiAgICB0aGlzLnJlY2FsY0xheW91dCgpO1xuICB9XG5cbiAgZ2V0IGJvZHlIZWlnaHQoKSB7XG4gICAgcmV0dXJuIHRoaXMuX2JvZHlIZWlnaHQ7XG4gIH1cblxuICBAT3V0cHV0KCkgc2Nyb2xsOiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIHBhZ2U6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgYWN0aXZhdGU6IEV2ZW50RW1pdHRlcjxhbnk+ID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICBAT3V0cHV0KCkgc2VsZWN0OiBFdmVudEVtaXR0ZXI8YW55PiA9IG5ldyBFdmVudEVtaXR0ZXIoKTtcbiAgQE91dHB1dCgpIGRldGFpbFRvZ2dsZTogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSByb3dDb250ZXh0bWVudSA9IG5ldyBFdmVudEVtaXR0ZXI8eyBldmVudDogTW91c2VFdmVudDsgcm93OiBhbnkgfT4oZmFsc2UpO1xuICBAT3V0cHV0KCkgdHJlZUFjdGlvbjogRXZlbnRFbWl0dGVyPGFueT4gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG5cbiAgQFZpZXdDaGlsZChTY3JvbGxlckNvbXBvbmVudCkgc2Nyb2xsZXI6IFNjcm9sbGVyQ29tcG9uZW50O1xuXG4gIC8qKlxuICAgKiBSZXR1cm5zIGlmIHNlbGVjdGlvbiBpcyBlbmFibGVkLlxuICAgKi9cbiAgZ2V0IHNlbGVjdEVuYWJsZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5zZWxlY3Rpb25UeXBlO1xuICB9XG5cbiAgLyoqXG4gICAqIFByb3BlcnR5IHRoYXQgd291bGQgY2FsY3VsYXRlIHRoZSBoZWlnaHQgb2Ygc2Nyb2xsIGJhclxuICAgKiBiYXNlZCBvbiB0aGUgcm93IGhlaWdodHMgY2FjaGUgZm9yIHZpcnR1YWwgc2Nyb2xsIGFuZCB2aXJ0dWFsaXphdGlvbi4gT3RoZXIgc2NlbmFyaW9zXG4gICAqIGNhbGN1bGF0ZSBzY3JvbGwgaGVpZ2h0IGF1dG9tYXRpY2FsbHkgKGFzIGhlaWdodCB3aWxsIGJlIHVuZGVmaW5lZCkuXG4gICAqL1xuICBnZXQgc2Nyb2xsSGVpZ2h0KCk6IG51bWJlciB8IHVuZGVmaW5lZCB7XG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFyViAmJiB0aGlzLnZpcnR1YWxpemF0aW9uICYmIHRoaXMucm93Q291bnQpIHtcbiAgICAgIHJldHVybiB0aGlzLnJvd0hlaWdodHNDYWNoZS5xdWVyeSh0aGlzLnJvd0NvdW50IC0gMSk7XG4gICAgfVxuICAgIC8vIGF2b2lkIFRTNzAzMDogTm90IGFsbCBjb2RlIHBhdGhzIHJldHVybiBhIHZhbHVlLlxuICAgIHJldHVybiB1bmRlZmluZWQ7XG4gIH1cblxuICByb3dIZWlnaHRzQ2FjaGU6IFJvd0hlaWdodENhY2hlID0gbmV3IFJvd0hlaWdodENhY2hlKCk7XG4gIHRlbXA6IGFueVtdID0gW107XG4gIG9mZnNldFkgPSAwO1xuICBpbmRleGVzOiBhbnkgPSB7fTtcbiAgY29sdW1uR3JvdXBXaWR0aHM6IGFueTtcbiAgY29sdW1uR3JvdXBXaWR0aHNXaXRob3V0R3JvdXA6IGFueTtcbiAgcm93VHJhY2tpbmdGbjogYW55O1xuICBsaXN0ZW5lcjogYW55O1xuICByb3dJbmRleGVzOiBhbnkgPSBuZXcgV2Vha01hcDxhbnksIHN0cmluZz4oKTtcbiAgcm93RXhwYW5zaW9uczogYW55W10gPSBbXTtcblxuICBfcm93czogYW55W107XG4gIF9ib2R5SGVpZ2h0OiBhbnk7XG4gIF9jb2x1bW5zOiBhbnlbXTtcbiAgX3Jvd0NvdW50OiBudW1iZXI7XG4gIF9vZmZzZXQ6IG51bWJlcjtcbiAgX3BhZ2VTaXplOiBudW1iZXI7XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgYW4gaW5zdGFuY2Ugb2YgRGF0YVRhYmxlQm9keUNvbXBvbmVudC5cbiAgICovXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgY2Q6IENoYW5nZURldGVjdG9yUmVmKSB7XG4gICAgLy8gZGVjbGFyZSBmbiBoZXJlIHNvIHdlIGNhbiBnZXQgYWNjZXNzIHRvIHRoZSBgdGhpc2AgcHJvcGVydHlcbiAgICB0aGlzLnJvd1RyYWNraW5nRm4gPSAoaW5kZXg6IG51bWJlciwgcm93OiBhbnkpOiBhbnkgPT4ge1xuICAgICAgY29uc3QgaWR4ID0gdGhpcy5nZXRSb3dJbmRleChyb3cpO1xuICAgICAgaWYgKHRoaXMudHJhY2tCeVByb3ApIHtcbiAgICAgICAgcmV0dXJuIHJvd1t0aGlzLnRyYWNrQnlQcm9wXTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHJldHVybiBpZHg7XG4gICAgICB9XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxsZWQgYWZ0ZXIgdGhlIGNvbnN0cnVjdG9yLCBpbml0aWFsaXppbmcgaW5wdXQgcHJvcGVydGllc1xuICAgKi9cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucm93RGV0YWlsKSB7XG4gICAgICB0aGlzLmxpc3RlbmVyID0gdGhpcy5yb3dEZXRhaWwudG9nZ2xlLnN1YnNjcmliZSgoeyB0eXBlLCB2YWx1ZSB9OiB7IHR5cGU6IHN0cmluZzsgdmFsdWU6IGFueSB9KSA9PiB7XG4gICAgICAgIGlmICh0eXBlID09PSAncm93Jykge1xuICAgICAgICAgIHRoaXMudG9nZ2xlUm93RXhwYW5zaW9uKHZhbHVlKTtcbiAgICAgICAgfVxuICAgICAgICBpZiAodHlwZSA9PT0gJ2FsbCcpIHtcbiAgICAgICAgICB0aGlzLnRvZ2dsZUFsbFJvd3ModmFsdWUpO1xuICAgICAgICB9XG5cbiAgICAgICAgLy8gUmVmcmVzaCByb3dzIGFmdGVyIHRvZ2dsZVxuICAgICAgICAvLyBGaXhlcyAjODgzXG4gICAgICAgIHRoaXMudXBkYXRlSW5kZXhlcygpO1xuICAgICAgICB0aGlzLnVwZGF0ZVJvd3MoKTtcbiAgICAgICAgdGhpcy5jZC5tYXJrRm9yQ2hlY2soKTtcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIGlmICh0aGlzLmdyb3VwSGVhZGVyKSB7XG4gICAgICB0aGlzLmxpc3RlbmVyID0gdGhpcy5ncm91cEhlYWRlci50b2dnbGUuc3Vic2NyaWJlKCh7IHR5cGUsIHZhbHVlIH06IHsgdHlwZTogc3RyaW5nOyB2YWx1ZTogYW55IH0pID0+IHtcbiAgICAgICAgaWYgKHR5cGUgPT09ICdncm91cCcpIHtcbiAgICAgICAgICB0aGlzLnRvZ2dsZVJvd0V4cGFuc2lvbih2YWx1ZSk7XG4gICAgICAgIH1cbiAgICAgICAgaWYgKHR5cGUgPT09ICdhbGwnKSB7XG4gICAgICAgICAgdGhpcy50b2dnbGVBbGxSb3dzKHZhbHVlKTtcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFJlZnJlc2ggcm93cyBhZnRlciB0b2dnbGVcbiAgICAgICAgLy8gRml4ZXMgIzg4M1xuICAgICAgICB0aGlzLnVwZGF0ZUluZGV4ZXMoKTtcbiAgICAgICAgdGhpcy51cGRhdGVSb3dzKCk7XG4gICAgICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XG4gICAgICB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogQ2FsbGVkIG9uY2UsIGJlZm9yZSB0aGUgaW5zdGFuY2UgaXMgZGVzdHJveWVkLlxuICAgKi9cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgaWYgKHRoaXMucm93RGV0YWlsIHx8IHRoaXMuZ3JvdXBIZWFkZXIpIHtcbiAgICAgIHRoaXMubGlzdGVuZXIudW5zdWJzY3JpYmUoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgWSBvZmZzZXQgZ2l2ZW4gYSBuZXcgb2Zmc2V0LlxuICAgKi9cbiAgdXBkYXRlT2Zmc2V0WShvZmZzZXQ/OiBudW1iZXIpOiB2b2lkIHtcbiAgICAvLyBzY3JvbGxlciBpcyBtaXNzaW5nIG9uIGVtcHR5IHRhYmxlXG4gICAgaWYgKCF0aGlzLnNjcm9sbGVyKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFyViAmJiB0aGlzLnZpcnR1YWxpemF0aW9uICYmIG9mZnNldCkge1xuICAgICAgLy8gRmlyc3QgZ2V0IHRoZSByb3cgSW5kZXggdGhhdCB3ZSBuZWVkIHRvIG1vdmUgdG8uXG4gICAgICBjb25zdCByb3dJbmRleCA9IHRoaXMucGFnZVNpemUgKiBvZmZzZXQ7XG4gICAgICBvZmZzZXQgPSB0aGlzLnJvd0hlaWdodHNDYWNoZS5xdWVyeShyb3dJbmRleCAtIDEpO1xuICAgIH0gZWxzZSBpZiAodGhpcy5zY3JvbGxiYXJWICYmICF0aGlzLnZpcnR1YWxpemF0aW9uKSB7XG4gICAgICBvZmZzZXQgPSAwO1xuICAgIH1cblxuICAgIHRoaXMuc2Nyb2xsZXIuc2V0T2Zmc2V0KG9mZnNldCB8fCAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBCb2R5IHdhcyBzY3JvbGxlZCwgdGhpcyBpcyBtYWlubHkgdXNlZnVsIGZvclxuICAgKiB3aGVuIGEgdXNlciBpcyBzZXJ2ZXItc2lkZSBwYWdpbmF0aW9uIHZpYSB2aXJ0dWFsIHNjcm9sbC5cbiAgICovXG4gIG9uQm9keVNjcm9sbChldmVudDogYW55KTogdm9pZCB7XG4gICAgY29uc3Qgc2Nyb2xsWVBvczogbnVtYmVyID0gZXZlbnQuc2Nyb2xsWVBvcztcbiAgICBjb25zdCBzY3JvbGxYUG9zOiBudW1iZXIgPSBldmVudC5zY3JvbGxYUG9zO1xuXG4gICAgLy8gaWYgc2Nyb2xsIGNoYW5nZSwgdHJpZ2dlciB1cGRhdGVcbiAgICAvLyB0aGlzIGlzIG1haW5seSB1c2VkIGZvciBoZWFkZXIgY2VsbCBwb3NpdGlvbnNcbiAgICBpZiAodGhpcy5vZmZzZXRZICE9PSBzY3JvbGxZUG9zIHx8IHRoaXMub2Zmc2V0WCAhPT0gc2Nyb2xsWFBvcykge1xuICAgICAgdGhpcy5zY3JvbGwuZW1pdCh7XG4gICAgICAgIG9mZnNldFk6IHNjcm9sbFlQb3MsXG4gICAgICAgIG9mZnNldFg6IHNjcm9sbFhQb3NcbiAgICAgIH0pO1xuICAgIH1cblxuICAgIHRoaXMub2Zmc2V0WSA9IHNjcm9sbFlQb3M7XG4gICAgdGhpcy5vZmZzZXRYID0gc2Nyb2xsWFBvcztcblxuICAgIHRoaXMudXBkYXRlSW5kZXhlcygpO1xuICAgIHRoaXMudXBkYXRlUGFnZShldmVudC5kaXJlY3Rpb24pO1xuICAgIHRoaXMudXBkYXRlUm93cygpO1xuICB9XG5cbiAgLyoqXG4gICAqIFVwZGF0ZXMgdGhlIHBhZ2UgZ2l2ZW4gYSBkaXJlY3Rpb24uXG4gICAqL1xuICB1cGRhdGVQYWdlKGRpcmVjdGlvbjogc3RyaW5nKTogdm9pZCB7XG4gICAgbGV0IG9mZnNldCA9IHRoaXMuaW5kZXhlcy5maXJzdCAvIHRoaXMucGFnZVNpemU7XG5cbiAgICBpZiAoZGlyZWN0aW9uID09PSAndXAnKSB7XG4gICAgICBvZmZzZXQgPSBNYXRoLmNlaWwob2Zmc2V0KTtcbiAgICB9IGVsc2UgaWYgKGRpcmVjdGlvbiA9PT0gJ2Rvd24nKSB7XG4gICAgICBvZmZzZXQgPSBNYXRoLmZsb29yKG9mZnNldCk7XG4gICAgfVxuXG4gICAgaWYgKGRpcmVjdGlvbiAhPT0gdW5kZWZpbmVkICYmICFpc05hTihvZmZzZXQpKSB7XG4gICAgICB0aGlzLnBhZ2UuZW1pdCh7IG9mZnNldCB9KTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB0aGUgcm93cyBpbiB0aGUgdmlldyBwb3J0XG4gICAqL1xuICB1cGRhdGVSb3dzKCk6IHZvaWQge1xuICAgIGNvbnN0IHsgZmlyc3QsIGxhc3QgfSA9IHRoaXMuaW5kZXhlcztcbiAgICBsZXQgcm93SW5kZXggPSBmaXJzdDtcbiAgICBsZXQgaWR4ID0gMDtcbiAgICBjb25zdCB0ZW1wOiBhbnlbXSA9IFtdO1xuXG4gICAgLy8gaWYgZ3JvdXByb3dzYnkgaGFzIGJlZW4gc3BlY2lmaWVkIHRyZWF0IHJvdyBwYWdpbmdcbiAgICAvLyBwYXJhbWV0ZXJzIGFzIGdyb3VwIHBhZ2luZyBwYXJhbWV0ZXJzIGllIGlmIGxpbWl0IDEwIGhhcyBiZWVuXG4gICAgLy8gc3BlY2lmaWVkIHRyZWF0IGl0IGFzIDEwIGdyb3VwcyByYXRoZXIgdGhhbiAxMCByb3dzXG4gICAgaWYgKHRoaXMuZ3JvdXBlZFJvd3MpIHtcbiAgICAgIGxldCBtYXhSb3dzUGVyR3JvdXAgPSAzO1xuICAgICAgLy8gaWYgdGhlcmUgaXMgb25seSBvbmUgZ3JvdXAgc2V0IHRoZSBtYXhpbXVtIG51bWJlciBvZlxuICAgICAgLy8gcm93cyBwZXIgZ3JvdXAgdGhlIHNhbWUgYXMgdGhlIHRvdGFsIG51bWJlciBvZiByb3dzXG4gICAgICBpZiAodGhpcy5ncm91cGVkUm93cy5sZW5ndGggPT09IDEpIHtcbiAgICAgICAgbWF4Um93c1Blckdyb3VwID0gdGhpcy5ncm91cGVkUm93c1swXS52YWx1ZS5sZW5ndGg7XG4gICAgICB9XG5cbiAgICAgIHdoaWxlIChyb3dJbmRleCA8IGxhc3QgJiYgcm93SW5kZXggPCB0aGlzLmdyb3VwZWRSb3dzLmxlbmd0aCkge1xuICAgICAgICAvLyBBZGQgdGhlIGdyb3VwcyBpbnRvIHRoaXMgcGFnZVxuICAgICAgICBjb25zdCBncm91cCA9IHRoaXMuZ3JvdXBlZFJvd3Nbcm93SW5kZXhdO1xuICAgICAgICB0aGlzLnJvd0luZGV4ZXMuc2V0KGdyb3VwLCByb3dJbmRleCk7XG5cbiAgICAgICAgaWYgKGdyb3VwLnZhbHVlKSB7XG4gICAgICAgICAgLy8gYWRkIGluZGV4ZXMgZm9yIGVhY2ggZ3JvdXAgaXRlbVxuICAgICAgICAgIGdyb3VwLnZhbHVlLmZvckVhY2goKGc6IGFueSwgaTogbnVtYmVyKSA9PiB7XG4gICAgICAgICAgICBjb25zdCBfaWR4ID0gYCR7cm93SW5kZXh9LSR7aX1gO1xuICAgICAgICAgICAgdGhpcy5yb3dJbmRleGVzLnNldChnLCBfaWR4KTtcbiAgICAgICAgICB9KTtcbiAgICAgICAgfVxuICAgICAgICB0ZW1wW2lkeF0gPSBncm91cDtcbiAgICAgICAgaWR4Kys7XG5cbiAgICAgICAgLy8gR3JvdXAgaW5kZXggaW4gdGhpcyBjb250ZXh0XG4gICAgICAgIHJvd0luZGV4Kys7XG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIHdoaWxlIChyb3dJbmRleCA8IGxhc3QgJiYgcm93SW5kZXggPCB0aGlzLnJvd0NvdW50KSB7XG4gICAgICAgIGNvbnN0IHJvdyA9IHRoaXMucm93c1tyb3dJbmRleF07XG5cbiAgICAgICAgaWYgKHJvdykge1xuICAgICAgICAgIC8vIGFkZCBpbmRleGVzIGZvciBlYWNoIHJvd1xuICAgICAgICAgIHRoaXMucm93SW5kZXhlcy5zZXQocm93LCByb3dJbmRleCk7XG4gICAgICAgICAgdGVtcFtpZHhdID0gcm93O1xuICAgICAgICB9XG5cbiAgICAgICAgaWR4Kys7XG4gICAgICAgIHJvd0luZGV4Kys7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy50ZW1wID0gdGVtcDtcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIHJvdyBoZWlnaHRcbiAgICovXG4gIGdldFJvd0hlaWdodChyb3c6IGFueSk6IG51bWJlciB7XG4gICAgLy8gaWYgaXRzIGEgZnVuY3Rpb24gcmV0dXJuIGl0XG4gICAgaWYgKHR5cGVvZiB0aGlzLnJvd0hlaWdodCA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgcmV0dXJuIHRoaXMucm93SGVpZ2h0KHJvdyk7XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMucm93SGVpZ2h0IGFzIG51bWJlcjtcbiAgfVxuXG4gIC8qKlxuICAgKiBAcGFyYW0gZ3JvdXAgdGhlIGdyb3VwIHdpdGggYWxsIHJvd3NcbiAgICovXG4gIGdldEdyb3VwSGVpZ2h0KGdyb3VwOiBhbnkpOiBudW1iZXIge1xuICAgIGxldCByb3dIZWlnaHQgPSAwO1xuXG4gICAgaWYgKGdyb3VwLnZhbHVlKSB7XG4gICAgICBmb3IgKGxldCBpbmRleCA9IDA7IGluZGV4IDwgZ3JvdXAudmFsdWUubGVuZ3RoOyBpbmRleCsrKSB7XG4gICAgICAgIHJvd0hlaWdodCArPSB0aGlzLmdldFJvd0FuZERldGFpbEhlaWdodChncm91cC52YWx1ZVtpbmRleF0pO1xuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByb3dIZWlnaHQ7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIHJvdyBoZWlnaHQgYmFzZWQgb24gdGhlIGV4cGFuZGVkIHN0YXRlIG9mIHRoZSByb3cuXG4gICAqL1xuICBnZXRSb3dBbmREZXRhaWxIZWlnaHQocm93OiBhbnkpOiBudW1iZXIge1xuICAgIGxldCByb3dIZWlnaHQgPSB0aGlzLmdldFJvd0hlaWdodChyb3cpO1xuICAgIGNvbnN0IGV4cGFuZGVkID0gdGhpcy5nZXRSb3dFeHBhbmRlZChyb3cpO1xuXG4gICAgLy8gQWRkaW5nIGRldGFpbCByb3cgaGVpZ2h0IGlmIGl0cyBleHBhbmRlZC5cbiAgICBpZiAoZXhwYW5kZWQpIHtcbiAgICAgIHJvd0hlaWdodCArPSB0aGlzLmdldERldGFpbFJvd0hlaWdodChyb3cpO1xuICAgIH1cblxuICAgIHJldHVybiByb3dIZWlnaHQ7XG4gIH1cblxuICAvKipcbiAgICogR2V0IHRoZSBoZWlnaHQgb2YgdGhlIGRldGFpbCByb3cuXG4gICAqL1xuICBnZXREZXRhaWxSb3dIZWlnaHQgPSAocm93PzogYW55LCBpbmRleD86IGFueSk6IG51bWJlciA9PiB7XG4gICAgaWYgKCF0aGlzLnJvd0RldGFpbCkge1xuICAgICAgcmV0dXJuIDA7XG4gICAgfVxuICAgIGNvbnN0IHJvd0hlaWdodCA9IHRoaXMucm93RGV0YWlsLnJvd0hlaWdodDtcbiAgICByZXR1cm4gdHlwZW9mIHJvd0hlaWdodCA9PT0gJ2Z1bmN0aW9uJyA/IHJvd0hlaWdodChyb3csIGluZGV4KSA6IChyb3dIZWlnaHQgYXMgbnVtYmVyKTtcbiAgfTtcblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUgc3R5bGVzIGZvciB0aGUgcm93IHNvIHRoYXQgdGhlIHJvd3MgY2FuIGJlIG1vdmVkIGluIDJEIHNwYWNlXG4gICAqIGR1cmluZyB2aXJ0dWFsIHNjcm9sbCBpbnNpZGUgdGhlIERPTS4gICBJbiB0aGUgYmVsb3cgY2FzZSB0aGUgWSBwb3NpdGlvbiBpc1xuICAgKiBtYW5pcHVsYXRlZC4gICBBcyBhbiBleGFtcGxlLCBpZiB0aGUgaGVpZ2h0IG9mIHJvdyAwIGlzIDMwIHB4IGFuZCByb3cgMSBpc1xuICAgKiAxMDAgcHggdGhlbiBmb2xsb3dpbmcgc3R5bGVzIGFyZSBnZW5lcmF0ZWQ6XG4gICAqXG4gICAqIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMHB4LCAwcHgsIDBweCk7ICAgIC0+ICByb3cwXG4gICAqIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMHB4LCAzMHB4LCAwcHgpOyAgIC0+ICByb3cxXG4gICAqIHRyYW5zZm9ybTogdHJhbnNsYXRlM2QoMHB4LCAxMzBweCwgMHB4KTsgIC0+ICByb3cyXG4gICAqXG4gICAqIFJvdyBoZWlnaHRzIGhhdmUgdG8gYmUgY2FsY3VsYXRlZCBiYXNlZCBvbiB0aGUgcm93IGhlaWdodHMgY2FjaGUgYXMgd2Ugd29udFxuICAgKiBiZSBhYmxlIHRvIGRldGVybWluZSB3aGljaCByb3cgaXMgb2Ygd2hhdCBoZWlnaHQgYmVmb3JlIGhhbmQuICBJbiB0aGUgYWJvdmVcbiAgICogY2FzZSB0aGUgcG9zaXRpb25ZIG9mIHRoZSB0cmFuc2xhdGUzZCBmb3Igcm93MiB3b3VsZCBiZSB0aGUgc3VtIG9mIGFsbCB0aGVcbiAgICogaGVpZ2h0cyBvZiB0aGUgcm93cyBiZWZvcmUgaXQgKGkuZS4gcm93MCBhbmQgcm93MSkuXG4gICAqXG4gICAqIEBwYXJhbSByb3dzIHRoZSByb3cgdGhhdCBuZWVkcyB0byBiZSBwbGFjZWQgaW4gdGhlIDJEIHNwYWNlLlxuICAgKiBAcmV0dXJucyB0aGUgQ1NTMyBzdHlsZSB0byBiZSBhcHBsaWVkXG4gICAqXG4gICAqIEBtZW1iZXJPZiBEYXRhVGFibGVCb2R5Q29tcG9uZW50XG4gICAqL1xuICBnZXRSb3dzU3R5bGVzKHJvd3M6IGFueSk6IGFueSB7XG4gICAgY29uc3Qgc3R5bGVzOiBhbnkgPSB7fTtcblxuICAgIC8vIG9ubHkgYWRkIHN0eWxlcyBmb3IgdGhlIGdyb3VwIGlmIHRoZXJlIGlzIGEgZ3JvdXBcbiAgICBpZiAodGhpcy5ncm91cGVkUm93cykge1xuICAgICAgc3R5bGVzLndpZHRoID0gdGhpcy5jb2x1bW5Hcm91cFdpZHRocy50b3RhbDtcbiAgICB9XG5cbiAgICBpZiAodGhpcy5zY3JvbGxiYXJWICYmIHRoaXMudmlydHVhbGl6YXRpb24pIHtcbiAgICAgIGxldCBpZHggPSAwO1xuXG4gICAgICBpZiAodGhpcy5ncm91cGVkUm93cykge1xuICAgICAgICAvLyBHZXQgdGhlIGxhdGVzdCByb3cgcm93aW5kZXggaW4gYSBncm91cFxuICAgICAgICBjb25zdCByb3cgPSByb3dzW3Jvd3MubGVuZ3RoIC0gMV07XG4gICAgICAgIGlkeCA9IHJvdyA/IHRoaXMuZ2V0Um93SW5kZXgocm93KSA6IDA7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICBpZHggPSB0aGlzLmdldFJvd0luZGV4KHJvd3MpO1xuICAgICAgfVxuXG4gICAgICAvLyBjb25zdCBwb3MgPSBpZHggKiByb3dIZWlnaHQ7XG4gICAgICAvLyBUaGUgcG9zaXRpb24gb2YgdGhpcyByb3cgd291bGQgYmUgdGhlIHN1bSBvZiBhbGwgcm93IGhlaWdodHNcbiAgICAgIC8vIHVudGlsIHRoZSBwcmV2aW91cyByb3cgcG9zaXRpb24uXG4gICAgICBjb25zdCBwb3MgPSB0aGlzLnJvd0hlaWdodHNDYWNoZS5xdWVyeShpZHggLSAxKTtcblxuICAgICAgdHJhbnNsYXRlWFkoc3R5bGVzLCAwLCBwb3MpO1xuICAgIH1cblxuICAgIHJldHVybiBzdHlsZXM7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlIGJvdHRvbSBzdW1tYXJ5IHJvdyBvZmZzZXQgZm9yIHNjcm9sbGJhciBtb2RlLlxuICAgKiBGb3IgbW9yZSBpbmZvcm1hdGlvbiBhYm91dCBjYWNoZSBhbmQgb2Zmc2V0IGNhbGN1bGF0aW9uXG4gICAqIHNlZSBkZXNjcmlwdGlvbiBmb3IgYGdldFJvd3NTdHlsZXNgIG1ldGhvZFxuICAgKlxuICAgKiBAcmV0dXJucyB0aGUgQ1NTMyBzdHlsZSB0byBiZSBhcHBsaWVkXG4gICAqXG4gICAqIEBtZW1iZXJPZiBEYXRhVGFibGVCb2R5Q29tcG9uZW50XG4gICAqL1xuICBnZXRCb3R0b21TdW1tYXJ5Um93U3R5bGVzKCk6IGFueSB7XG4gICAgaWYgKCF0aGlzLnNjcm9sbGJhclYgfHwgIXRoaXMucm93cyB8fCAhdGhpcy5yb3dzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3Qgc3R5bGVzID0geyBwb3NpdGlvbjogJ2Fic29sdXRlJyB9O1xuICAgIGNvbnN0IHBvcyA9IHRoaXMucm93SGVpZ2h0c0NhY2hlLnF1ZXJ5KHRoaXMucm93cy5sZW5ndGggLSAxKTtcblxuICAgIHRyYW5zbGF0ZVhZKHN0eWxlcywgMCwgcG9zKTtcblxuICAgIHJldHVybiBzdHlsZXM7XG4gIH1cblxuICAvKipcbiAgICogSGlkZXMgdGhlIGxvYWRpbmcgaW5kaWNhdG9yXG4gICAqL1xuICBoaWRlSW5kaWNhdG9yKCk6IHZvaWQge1xuICAgIHNldFRpbWVvdXQoKCkgPT4gKHRoaXMubG9hZGluZ0luZGljYXRvciA9IGZhbHNlKSwgNTAwKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHRoZSBpbmRleCBvZiB0aGUgcm93cyBpbiB0aGUgdmlld3BvcnRcbiAgICovXG4gIHVwZGF0ZUluZGV4ZXMoKTogdm9pZCB7XG4gICAgbGV0IGZpcnN0ID0gMDtcbiAgICBsZXQgbGFzdCA9IDA7XG5cbiAgICBpZiAodGhpcy5zY3JvbGxiYXJWKSB7XG4gICAgICBpZiAodGhpcy52aXJ0dWFsaXphdGlvbikge1xuICAgICAgICAvLyBDYWxjdWxhdGlvbiBvZiB0aGUgZmlyc3QgYW5kIGxhc3QgaW5kZXhlcyB3aWxsIGJlIGJhc2VkIG9uIHdoZXJlIHRoZVxuICAgICAgICAvLyBzY3JvbGxZIHBvc2l0aW9uIHdvdWxkIGJlIGF0LiAgVGhlIGxhc3QgaW5kZXggd291bGQgYmUgdGhlIG9uZVxuICAgICAgICAvLyB0aGF0IHNob3dzIHVwIGluc2lkZSB0aGUgdmlldyBwb3J0IHRoZSBsYXN0LlxuICAgICAgICBjb25zdCBoZWlnaHQgPSBwYXJzZUludCh0aGlzLmJvZHlIZWlnaHQsIDApO1xuICAgICAgICBmaXJzdCA9IHRoaXMucm93SGVpZ2h0c0NhY2hlLmdldFJvd0luZGV4KHRoaXMub2Zmc2V0WSk7XG4gICAgICAgIGxhc3QgPSB0aGlzLnJvd0hlaWdodHNDYWNoZS5nZXRSb3dJbmRleChoZWlnaHQgKyB0aGlzLm9mZnNldFkpICsgMTtcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIC8vIElmIHZpcnR1YWwgcm93cyBhcmUgbm90IG5lZWRlZFxuICAgICAgICAvLyBXZSByZW5kZXIgYWxsIGluIG9uZSBnb1xuICAgICAgICBmaXJzdCA9IDA7XG4gICAgICAgIGxhc3QgPSB0aGlzLnJvd0NvdW50O1xuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBUaGUgc2VydmVyIGlzIGhhbmRsaW5nIHBhZ2luZyBhbmQgd2lsbCBwYXNzIGFuIGFycmF5IHRoYXQgYmVnaW5zIHdpdGggdGhlXG4gICAgICAvLyBlbGVtZW50IGF0IGEgc3BlY2lmaWVkIG9mZnNldC4gIGZpcnN0IHNob3VsZCBhbHdheXMgYmUgMCB3aXRoIGV4dGVybmFsIHBhZ2luZy5cbiAgICAgIGlmICghdGhpcy5leHRlcm5hbFBhZ2luZykge1xuICAgICAgICBmaXJzdCA9IE1hdGgubWF4KHRoaXMub2Zmc2V0ICogdGhpcy5wYWdlU2l6ZSwgMCk7XG4gICAgICB9XG4gICAgICBsYXN0ID0gTWF0aC5taW4oZmlyc3QgKyB0aGlzLnBhZ2VTaXplLCB0aGlzLnJvd0NvdW50KTtcbiAgICB9XG5cbiAgICB0aGlzLmluZGV4ZXMgPSB7IGZpcnN0LCBsYXN0IH07XG4gIH1cblxuICAvKipcbiAgICogUmVmcmVzaGVzIHRoZSBmdWxsIFJvdyBIZWlnaHQgY2FjaGUuICBTaG91bGQgYmUgdXNlZFxuICAgKiB3aGVuIHRoZSBlbnRpcmUgcm93IGFycmF5IHN0YXRlIGhhcyBjaGFuZ2VkLlxuICAgKi9cbiAgcmVmcmVzaFJvd0hlaWdodENhY2hlKCk6IHZvaWQge1xuICAgIGlmICghdGhpcy5zY3JvbGxiYXJWIHx8ICh0aGlzLnNjcm9sbGJhclYgJiYgIXRoaXMudmlydHVhbGl6YXRpb24pKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuXG4gICAgLy8gY2xlYXIgdGhlIHByZXZpb3VzIHJvdyBoZWlnaHQgY2FjaGUgaWYgYWxyZWFkeSBwcmVzZW50LlxuICAgIC8vIHRoaXMgaXMgdXNlZnVsIGR1cmluZyBzb3J0cywgZmlsdGVycyB3aGVyZSB0aGUgc3RhdGUgb2YgdGhlXG4gICAgLy8gcm93cyBhcnJheSBpcyBjaGFuZ2VkLlxuICAgIHRoaXMucm93SGVpZ2h0c0NhY2hlLmNsZWFyQ2FjaGUoKTtcblxuICAgIC8vIEluaXRpYWxpemUgdGhlIHRyZWUgb25seSBpZiB0aGVyZSBhcmUgcm93cyBpbnNpZGUgdGhlIHRyZWUuXG4gICAgaWYgKHRoaXMucm93cyAmJiB0aGlzLnJvd3MubGVuZ3RoKSB7XG4gICAgICBjb25zdCByb3dFeHBhbnNpb25zID0gbmV3IFNldCgpO1xuICAgICAgZm9yIChjb25zdCByb3cgb2YgdGhpcy5yb3dzKSB7XG4gICAgICAgIGlmICh0aGlzLmdldFJvd0V4cGFuZGVkKHJvdykpIHtcbiAgICAgICAgICByb3dFeHBhbnNpb25zLmFkZChyb3cpO1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIHRoaXMucm93SGVpZ2h0c0NhY2hlLmluaXRDYWNoZSh7XG4gICAgICAgIHJvd3M6IHRoaXMucm93cyxcbiAgICAgICAgcm93SGVpZ2h0OiB0aGlzLnJvd0hlaWdodCxcbiAgICAgICAgZGV0YWlsUm93SGVpZ2h0OiB0aGlzLmdldERldGFpbFJvd0hlaWdodCxcbiAgICAgICAgZXh0ZXJuYWxWaXJ0dWFsOiB0aGlzLnNjcm9sbGJhclYgJiYgdGhpcy5leHRlcm5hbFBhZ2luZyxcbiAgICAgICAgcm93Q291bnQ6IHRoaXMucm93Q291bnQsXG4gICAgICAgIHJvd0luZGV4ZXM6IHRoaXMucm93SW5kZXhlcyxcbiAgICAgICAgcm93RXhwYW5zaW9uc1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIGluZGV4IGZvciB0aGUgdmlldyBwb3J0XG4gICAqL1xuICBnZXRBZGp1c3RlZFZpZXdQb3J0SW5kZXgoKTogbnVtYmVyIHtcbiAgICAvLyBDYXB0dXJlIHRoZSByb3cgaW5kZXggb2YgdGhlIGZpcnN0IHJvdyB0aGF0IGlzIHZpc2libGUgb24gdGhlIHZpZXdwb3J0LlxuICAgIC8vIElmIHRoZSBzY3JvbGwgYmFyIGlzIGp1c3QgYmVsb3cgdGhlIHJvdyB3aGljaCBpcyBoaWdobGlnaHRlZCB0aGVuIG1ha2UgdGhhdCBhcyB0aGVcbiAgICAvLyBmaXJzdCBpbmRleC5cbiAgICBjb25zdCB2aWV3UG9ydEZpcnN0Um93SW5kZXggPSB0aGlzLmluZGV4ZXMuZmlyc3Q7XG5cbiAgICBpZiAodGhpcy5zY3JvbGxiYXJWICYmIHRoaXMudmlydHVhbGl6YXRpb24pIHtcbiAgICAgIGNvbnN0IG9mZnNldFNjcm9sbCA9IHRoaXMucm93SGVpZ2h0c0NhY2hlLnF1ZXJ5KHZpZXdQb3J0Rmlyc3RSb3dJbmRleCAtIDEpO1xuICAgICAgcmV0dXJuIG9mZnNldFNjcm9sbCA8PSB0aGlzLm9mZnNldFkgPyB2aWV3UG9ydEZpcnN0Um93SW5kZXggLSAxIDogdmlld1BvcnRGaXJzdFJvd0luZGV4O1xuICAgIH1cblxuICAgIHJldHVybiB2aWV3UG9ydEZpcnN0Um93SW5kZXg7XG4gIH1cblxuICAvKipcbiAgICogVG9nZ2xlIHRoZSBFeHBhbnNpb24gb2YgdGhlIHJvdyBpLmUuIGlmIHRoZSByb3cgaXMgZXhwYW5kZWQgdGhlbiBpdCB3aWxsXG4gICAqIGNvbGxhcHNlIGFuZCB2aWNlIHZlcnNhLiAgIE5vdGUgdGhhdCB0aGUgZXhwYW5kZWQgc3RhdHVzIGlzIHN0b3JlZCBhc1xuICAgKiBhIHBhcnQgb2YgdGhlIHJvdyBvYmplY3QgaXRzZWxmIGFzIHdlIGhhdmUgdG8gcHJlc2VydmUgdGhlIGV4cGFuZGVkIHJvd1xuICAgKiBzdGF0dXMgaW4gY2FzZSBvZiBzb3J0aW5nIGFuZCBmaWx0ZXJpbmcgb2YgdGhlIHJvdyBzZXQuXG4gICAqL1xuICB0b2dnbGVSb3dFeHBhbnNpb24ocm93OiBhbnkpOiB2b2lkIHtcbiAgICAvLyBDYXB0dXJlIHRoZSByb3cgaW5kZXggb2YgdGhlIGZpcnN0IHJvdyB0aGF0IGlzIHZpc2libGUgb24gdGhlIHZpZXdwb3J0LlxuICAgIGNvbnN0IHZpZXdQb3J0Rmlyc3RSb3dJbmRleCA9IHRoaXMuZ2V0QWRqdXN0ZWRWaWV3UG9ydEluZGV4KCk7XG4gICAgY29uc3Qgcm93RXhwYW5kZWRJZHggPSB0aGlzLmdldFJvd0V4cGFuZGVkSWR4KHJvdywgdGhpcy5yb3dFeHBhbnNpb25zKTtcbiAgICBjb25zdCBleHBhbmRlZCA9IHJvd0V4cGFuZGVkSWR4ID4gLTE7XG5cbiAgICAvLyBJZiB0aGUgZGV0YWlsUm93SGVpZ2h0IGlzIGF1dG8gLS0+IG9ubHkgaW4gY2FzZSBvZiBub24tdmlydHVhbGl6ZWQgc2Nyb2xsXG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFyViAmJiB0aGlzLnZpcnR1YWxpemF0aW9uKSB7XG4gICAgICBjb25zdCBkZXRhaWxSb3dIZWlnaHQgPSB0aGlzLmdldERldGFpbFJvd0hlaWdodChyb3cpICogKGV4cGFuZGVkID8gLTEgOiAxKTtcbiAgICAgIC8vIGNvbnN0IGlkeCA9IHRoaXMucm93SW5kZXhlcy5nZXQocm93KSB8fCAwO1xuICAgICAgY29uc3QgaWR4ID0gdGhpcy5nZXRSb3dJbmRleChyb3cpO1xuICAgICAgdGhpcy5yb3dIZWlnaHRzQ2FjaGUudXBkYXRlKGlkeCwgZGV0YWlsUm93SGVpZ2h0KTtcbiAgICB9XG5cbiAgICAvLyBVcGRhdGUgdGhlIHRvZ2dsZWQgcm93IGFuZCB1cGRhdGUgdGhpdmUgbmV2ZXJlIGhlaWdodHMgaW4gdGhlIGNhY2hlLlxuICAgIGlmIChleHBhbmRlZCkge1xuICAgICAgdGhpcy5yb3dFeHBhbnNpb25zLnNwbGljZShyb3dFeHBhbmRlZElkeCwgMSk7XG4gICAgfSBlbHNlIHtcbiAgICAgIHRoaXMucm93RXhwYW5zaW9ucy5wdXNoKHJvdyk7XG4gICAgfVxuXG4gICAgdGhpcy5kZXRhaWxUb2dnbGUuZW1pdCh7XG4gICAgICByb3dzOiBbcm93XSxcbiAgICAgIGN1cnJlbnRJbmRleDogdmlld1BvcnRGaXJzdFJvd0luZGV4XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogRXhwYW5kL0NvbGxhcHNlIGFsbCB0aGUgcm93cyBubyBtYXR0ZXIgd2hhdCB0aGVpciBzdGF0ZSBpcy5cbiAgICovXG4gIHRvZ2dsZUFsbFJvd3MoZXhwYW5kZWQ6IGJvb2xlYW4pOiB2b2lkIHtcbiAgICAvLyBjbGVhciBwcmV2IGV4cGFuc2lvbnNcbiAgICB0aGlzLnJvd0V4cGFuc2lvbnMgPSBbXTtcblxuICAgIC8vIENhcHR1cmUgdGhlIHJvdyBpbmRleCBvZiB0aGUgZmlyc3Qgcm93IHRoYXQgaXMgdmlzaWJsZSBvbiB0aGUgdmlld3BvcnQuXG4gICAgY29uc3Qgdmlld1BvcnRGaXJzdFJvd0luZGV4ID0gdGhpcy5nZXRBZGp1c3RlZFZpZXdQb3J0SW5kZXgoKTtcblxuICAgIGlmIChleHBhbmRlZCkge1xuICAgICAgZm9yIChjb25zdCByb3cgb2YgdGhpcy5yb3dzKSB7XG4gICAgICAgIHRoaXMucm93RXhwYW5zaW9ucy5wdXNoKHJvdyk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKHRoaXMuc2Nyb2xsYmFyVikge1xuICAgICAgLy8gUmVmcmVzaCB0aGUgZnVsbCByb3cgaGVpZ2h0cyBjYWNoZSBzaW5jZSBldmVyeSByb3cgd2FzIGFmZmVjdGVkLlxuICAgICAgdGhpcy5yZWNhbGNMYXlvdXQoKTtcbiAgICB9XG5cbiAgICAvLyBFbWl0IGFsbCByb3dzIHRoYXQgaGF2ZSBiZWVuIGV4cGFuZGVkLlxuICAgIHRoaXMuZGV0YWlsVG9nZ2xlLmVtaXQoe1xuICAgICAgcm93czogdGhpcy5yb3dzLFxuICAgICAgY3VycmVudEluZGV4OiB2aWV3UG9ydEZpcnN0Um93SW5kZXhcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWNhbGN1bGF0ZXMgdGhlIHRhYmxlXG4gICAqL1xuICByZWNhbGNMYXlvdXQoKTogdm9pZCB7XG4gICAgdGhpcy5yZWZyZXNoUm93SGVpZ2h0Q2FjaGUoKTtcbiAgICB0aGlzLnVwZGF0ZUluZGV4ZXMoKTtcbiAgICB0aGlzLnVwZGF0ZVJvd3MoKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBUcmFja3MgdGhlIGNvbHVtblxuICAgKi9cbiAgY29sdW1uVHJhY2tpbmdGbihpbmRleDogbnVtYmVyLCBjb2x1bW46IGFueSk6IGFueSB7XG4gICAgcmV0dXJuIGNvbHVtbi4kJGlkO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHJvdyBwaW5uaW5nIGdyb3VwIHN0eWxlc1xuICAgKi9cbiAgc3R5bGVzQnlHcm91cChncm91cDogc3RyaW5nKSB7XG4gICAgY29uc3Qgd2lkdGhzID0gdGhpcy5jb2x1bW5Hcm91cFdpZHRocztcbiAgICBjb25zdCBvZmZzZXRYID0gdGhpcy5vZmZzZXRYO1xuXG4gICAgY29uc3Qgc3R5bGVzID0ge1xuICAgICAgd2lkdGg6IGAke3dpZHRoc1tncm91cF19cHhgXG4gICAgfTtcblxuICAgIGlmIChncm91cCA9PT0gJ2xlZnQnKSB7XG4gICAgICB0cmFuc2xhdGVYWShzdHlsZXMsIG9mZnNldFgsIDApO1xuICAgIH0gZWxzZSBpZiAoZ3JvdXAgPT09ICdyaWdodCcpIHtcbiAgICAgIGNvbnN0IGJvZHlXaWR0aCA9IHBhcnNlSW50KHRoaXMuaW5uZXJXaWR0aCArICcnLCAwKTtcbiAgICAgIGNvbnN0IHRvdGFsRGlmZiA9IHdpZHRocy50b3RhbCAtIGJvZHlXaWR0aDtcbiAgICAgIGNvbnN0IG9mZnNldERpZmYgPSB0b3RhbERpZmYgLSBvZmZzZXRYO1xuICAgICAgY29uc3Qgb2Zmc2V0ID0gb2Zmc2V0RGlmZiAqIC0xO1xuICAgICAgdHJhbnNsYXRlWFkoc3R5bGVzLCBvZmZzZXQsIDApO1xuICAgIH1cblxuICAgIHJldHVybiBzdHlsZXM7XG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyBpZiB0aGUgcm93IHdhcyBleHBhbmRlZCBhbmQgc2V0IGRlZmF1bHQgcm93IGV4cGFuc2lvbiB3aGVuIHJvdyBleHBhbnNpb24gaXMgZW1wdHlcbiAgICovXG4gIGdldFJvd0V4cGFuZGVkKHJvdzogYW55KTogYm9vbGVhbiB7XG4gICAgaWYgKHRoaXMucm93RXhwYW5zaW9ucy5sZW5ndGggPT09IDAgJiYgdGhpcy5ncm91cEV4cGFuc2lvbkRlZmF1bHQpIHtcbiAgICAgIGZvciAoY29uc3QgZ3JvdXAgb2YgdGhpcy5ncm91cGVkUm93cykge1xuICAgICAgICB0aGlzLnJvd0V4cGFuc2lvbnMucHVzaChncm91cCk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZ2V0Um93RXhwYW5kZWRJZHgocm93LCB0aGlzLnJvd0V4cGFuc2lvbnMpID4gLTE7XG4gIH1cblxuICBnZXRSb3dFeHBhbmRlZElkeChyb3c6IGFueSwgZXhwYW5kZWQ6IGFueVtdKTogbnVtYmVyIHtcbiAgICBpZiAoIWV4cGFuZGVkIHx8ICFleHBhbmRlZC5sZW5ndGgpIHJldHVybiAtMTtcblxuICAgIGNvbnN0IHJvd0lkID0gdGhpcy5yb3dJZGVudGl0eShyb3cpO1xuICAgIHJldHVybiBleHBhbmRlZC5maW5kSW5kZXgociA9PiB7XG4gICAgICBjb25zdCBpZCA9IHRoaXMucm93SWRlbnRpdHkocik7XG4gICAgICByZXR1cm4gaWQgPT09IHJvd0lkO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIEdldHMgdGhlIHJvdyBpbmRleCBnaXZlbiBhIHJvd1xuICAgKi9cbiAgZ2V0Um93SW5kZXgocm93OiBhbnkpOiBudW1iZXIge1xuICAgIHJldHVybiB0aGlzLnJvd0luZGV4ZXMuZ2V0KHJvdykgfHwgMDtcbiAgfVxuXG4gIG9uVHJlZUFjdGlvbihyb3c6IGFueSkge1xuICAgIHRoaXMudHJlZUFjdGlvbi5lbWl0KHsgcm93IH0pO1xuICB9XG59XG4iXX0=