@neovici/cosmoz-omnitable 7.1.0 → 7.3.0
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.
- package/cosmoz-omnitable-column-range-mixin.js +5 -11
- package/cosmoz-omnitable-group-row.js +11 -86
- package/cosmoz-omnitable-item-row.js +21 -127
- package/cosmoz-omnitable-styles.js +24 -3
- package/cosmoz-omnitable.js +13 -61
- package/lib/cosmoz-omnitable-settings.js +18 -3
- package/lib/generic-sorter.js +35 -0
- package/lib/use-omnitable.js +17 -2
- package/lib/use-saved-settings.js +12 -3
- package/package.json +1 -2
- package/cosmoz-omnitable-repeater-mixin.js +0 -294
|
@@ -248,19 +248,13 @@ export const rangeColumnMixin = dedupingMixin(base => // eslint-disable-line max
|
|
|
248
248
|
}
|
|
249
249
|
|
|
250
250
|
_applySingleFilter(filter, item) {
|
|
251
|
-
const value = this.getComparableValue(item, this.valuePath)
|
|
252
|
-
|
|
253
|
-
maxValue = this.getComparableValue(filter, 'max');
|
|
254
|
-
|
|
255
|
-
if (value < minValue) {
|
|
256
|
-
return false;
|
|
257
|
-
}
|
|
258
|
-
|
|
259
|
-
if (value > maxValue) {
|
|
251
|
+
const value = this.getComparableValue(item, this.valuePath);
|
|
252
|
+
if (value == null) {
|
|
260
253
|
return false;
|
|
261
254
|
}
|
|
262
|
-
|
|
263
|
-
|
|
255
|
+
const min = this.getComparableValue(filter, 'min'),
|
|
256
|
+
max = this.getComparableValue(filter, 'max');
|
|
257
|
+
return !(value < min || value > max);
|
|
264
258
|
}
|
|
265
259
|
|
|
266
260
|
_computeFilterText(change) {
|
|
@@ -1,91 +1,16 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import { component, useMemo } from 'haunted';
|
|
2
|
+
import { nothing } from 'lit-html';
|
|
3
|
+
import { useRenderOnColumnUpdates } from './lib/use-render-on-column-updates';
|
|
3
4
|
|
|
4
|
-
|
|
5
|
+
const GroupRow = ({ column, item, selected, folded }) => {
|
|
6
|
+
const columns = useMemo(() => column ? [column] : [], [column]);
|
|
7
|
+
useRenderOnColumnUpdates(columns);
|
|
5
8
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
* @customElement
|
|
9
|
-
* @appliesMixin repeaterMixin
|
|
10
|
-
*/
|
|
11
|
-
class OmnitableGroupRow extends repeaterMixin(PolymerElement) {
|
|
12
|
-
static get template() {
|
|
13
|
-
return html`
|
|
14
|
-
<slot name="group-row"></slot>
|
|
15
|
-
`;
|
|
9
|
+
if (!column) {
|
|
10
|
+
return nothing;
|
|
16
11
|
}
|
|
17
12
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
static get properties() {
|
|
23
|
-
return {
|
|
24
|
-
column: {
|
|
25
|
-
type: Object,
|
|
26
|
-
observer: '_columnChanged'
|
|
27
|
-
},
|
|
28
|
-
|
|
29
|
-
item: {
|
|
30
|
-
type: Object
|
|
31
|
-
},
|
|
32
|
-
|
|
33
|
-
selected: {
|
|
34
|
-
type: Boolean,
|
|
35
|
-
observer: '_selectedChanged'
|
|
36
|
-
},
|
|
37
|
-
|
|
38
|
-
folded: {
|
|
39
|
-
type: Boolean,
|
|
40
|
-
observer: '_foldedChanged'
|
|
41
|
-
}
|
|
42
|
-
};
|
|
43
|
-
}
|
|
44
|
-
|
|
45
|
-
static get observers() {
|
|
46
|
-
return [
|
|
47
|
-
'_itemUpdated(item.*)'
|
|
48
|
-
];
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
get _elementType() {
|
|
52
|
-
return 'div';
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
get _slotName() {
|
|
56
|
-
return 'group-row';
|
|
57
|
-
}
|
|
13
|
+
return (column.renderGroup ?? column.renderCell)(column, { item, selected, folded });
|
|
14
|
+
};
|
|
58
15
|
|
|
59
|
-
|
|
60
|
-
super();
|
|
61
|
-
this.trackColumns();
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
_columnChanged(newColumn) {
|
|
65
|
-
if (!newColumn) {
|
|
66
|
-
return;
|
|
67
|
-
}
|
|
68
|
-
if (this.columns && this.columns.length > 0) {
|
|
69
|
-
this.splice('columns', 0, 1, newColumn);
|
|
70
|
-
return;
|
|
71
|
-
}
|
|
72
|
-
this.columns = [newColumn];
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
_getRenderFn(column) {
|
|
76
|
-
return column.renderGroup ?? column.renderCell;
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
_itemUpdated(changeRecord) {
|
|
80
|
-
this.forwardPathChange(changeRecord);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
_selectedChanged(selected) {
|
|
84
|
-
this.forwardChange('selected', selected);
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
_foldedChanged(folded) {
|
|
88
|
-
this.forwardChange('folded', folded);
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
customElements.define(OmnitableGroupRow.is, OmnitableGroupRow);
|
|
16
|
+
customElements.define('cosmoz-omnitable-group-row', component(GroupRow, { useShadowDOM: false }));
|
|
@@ -1,129 +1,23 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
:host > ::slotted(*) {
|
|
21
|
-
display: block;
|
|
22
|
-
flex: none;
|
|
23
|
-
padding: 0 3px;
|
|
24
|
-
white-space: nowrap;
|
|
25
|
-
overflow: hidden;
|
|
26
|
-
text-overflow: ellipsis;
|
|
27
|
-
box-sizing: border-box;
|
|
28
|
-
align-self: center;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
:host > ::slotted([hidden]),
|
|
32
|
-
:host [hidden] {
|
|
33
|
-
display: none !important;
|
|
34
|
-
}
|
|
35
|
-
</style>
|
|
36
|
-
<slot name="item-cell"></slot>
|
|
37
|
-
`;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
static get is() {
|
|
41
|
-
return 'cosmoz-omnitable-item-row';
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
static get properties() {
|
|
45
|
-
return {
|
|
46
|
-
item: {
|
|
47
|
-
type: Object
|
|
48
|
-
},
|
|
49
|
-
|
|
50
|
-
selected: {
|
|
51
|
-
type: Boolean,
|
|
52
|
-
observer: '_selectedChanged'
|
|
53
|
-
},
|
|
54
|
-
|
|
55
|
-
expanded: {
|
|
56
|
-
type: Boolean,
|
|
57
|
-
observer: '_expandedChanged'
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
static get observers() {
|
|
63
|
-
return [
|
|
64
|
-
'_itemUpdated(item.*)'
|
|
65
|
-
];
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
get _elementType() {
|
|
69
|
-
return 'div';
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
get _slotName() {
|
|
73
|
-
return 'item-cell';
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
constructor() {
|
|
77
|
-
super();
|
|
78
|
-
this.trackColumns();
|
|
79
|
-
}
|
|
80
|
-
|
|
81
|
-
_getRenderFn(column) {
|
|
82
|
-
return column.editable
|
|
83
|
-
? column.renderEditCell
|
|
84
|
-
: column.renderCell;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* @inheritdoc
|
|
89
|
-
*/
|
|
90
|
-
_configureElement(element, column, instance) {
|
|
91
|
-
super._configureElement(element, column, instance);
|
|
92
|
-
element.style.minHeight = '0.5px';
|
|
93
|
-
element.toggleAttribute('editable', !!column.editable);
|
|
94
|
-
element.setAttribute('title', this._getCellTitle(column, this.item));
|
|
95
|
-
element.setAttribute('class', this._computeItemRowCellClasses(column));
|
|
96
|
-
element.setAttribute('name', column.name);
|
|
97
|
-
}
|
|
98
|
-
|
|
99
|
-
_itemUpdated(changeRecord) {
|
|
100
|
-
this.forwardPathChange(changeRecord);
|
|
101
|
-
this.forEachElement((element, column) => {
|
|
102
|
-
element.setAttribute('title', this._getCellTitle(column, this.item));
|
|
1
|
+
import { component, html } from 'haunted';
|
|
2
|
+
import { repeat } from 'lit-html/directives/repeat';
|
|
3
|
+
import { useRenderOnColumnUpdates } from './lib/use-render-on-column-updates';
|
|
4
|
+
|
|
5
|
+
const
|
|
6
|
+
renderCell = (column, data) => column.editable
|
|
7
|
+
? column.renderEditCell(column, data)
|
|
8
|
+
: column.renderCell(column, data),
|
|
9
|
+
ItemRow = ({ columns, groupOnColumn, item, selected, expanded }) => {
|
|
10
|
+
useRenderOnColumnUpdates(columns);
|
|
11
|
+
|
|
12
|
+
return repeat(columns, column => column.name, column => {
|
|
13
|
+
return html`<div
|
|
14
|
+
class="cell itemRow-cell ${ column.cellClass ?? '' }"
|
|
15
|
+
?hidden=${ column === groupOnColumn }
|
|
16
|
+
?editable=${ column.editable }
|
|
17
|
+
title=${ column.cellTitleFn(item, column.valuePath) }
|
|
18
|
+
name=${ column.name }
|
|
19
|
+
>${ renderCell(column, { item, selected, expanded }) }</div>`;
|
|
103
20
|
});
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
_selectedChanged(selected) {
|
|
107
|
-
this.forwardChange('selected', selected);
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
_expandedChanged(expanded) {
|
|
111
|
-
this.forwardChange('expanded', expanded);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Get cell title displayed when hovering on the cell.
|
|
116
|
-
* @param {object} column Column data.
|
|
117
|
-
* @param {object} item Row item.
|
|
118
|
-
* @returns {string} Cell title.
|
|
119
|
-
*/
|
|
120
|
-
_getCellTitle(column, item) {
|
|
121
|
-
return column && column.cellTitleFn(item, column.valuePath);
|
|
122
|
-
}
|
|
21
|
+
};
|
|
123
22
|
|
|
124
|
-
|
|
125
|
-
return 'cell itemRow-cell'
|
|
126
|
-
+ (column.cellClass ? ' ' + column.cellClass + ' ' : '');
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
customElements.define(OmnitableItemRow.is, OmnitableItemRow);
|
|
23
|
+
customElements.define('cosmoz-omnitable-item-row', component(ItemRow, { useShadowDOM: false }));
|
|
@@ -21,7 +21,7 @@ const checkbox = `
|
|
|
21
21
|
}
|
|
22
22
|
|
|
23
23
|
.checkbox:checked {
|
|
24
|
-
background-color: var(--
|
|
24
|
+
background-color: var(--cosmoz-omnitable-checkbox-checked-color, var(--primary-color));
|
|
25
25
|
box-shadow: none;
|
|
26
26
|
}
|
|
27
27
|
|
|
@@ -62,7 +62,7 @@ const checkbox = `
|
|
|
62
62
|
height: 2px;
|
|
63
63
|
left: 4px;
|
|
64
64
|
top: 8px;
|
|
65
|
-
|
|
65
|
+
background-color: var(--cosmoz-omnitable-checkbox-checked-color, var(--primary-color));
|
|
66
66
|
}
|
|
67
67
|
`;
|
|
68
68
|
|
|
@@ -160,6 +160,27 @@ export default `<style>
|
|
|
160
160
|
position: relative;
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
|
|
164
|
+
cosmoz-omnitable-item-row {
|
|
165
|
+
display: flex;
|
|
166
|
+
white-space: nowrap;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
cosmoz-omnitable-item-row > div {
|
|
170
|
+
display: block;
|
|
171
|
+
flex: none;
|
|
172
|
+
padding: 0 3px;
|
|
173
|
+
white-space: nowrap;
|
|
174
|
+
overflow: hidden;
|
|
175
|
+
text-overflow: ellipsis;
|
|
176
|
+
box-sizing: border-box;
|
|
177
|
+
align-self: center;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
cosmoz-omnitable-item-row > div[hidden] {
|
|
181
|
+
display: none !important;
|
|
182
|
+
}
|
|
183
|
+
|
|
163
184
|
.tableContent {
|
|
164
185
|
overflow-y: auto;
|
|
165
186
|
min-height: 90px;
|
|
@@ -260,7 +281,7 @@ export default `<style>
|
|
|
260
281
|
display: flex;
|
|
261
282
|
align-items: center;
|
|
262
283
|
border-top: solid 1px #e8e8e8;
|
|
263
|
-
background-color: #f5f5f5;
|
|
284
|
+
background-color: var(--cosmoz-omnitable-footer-bg-color, #f5f5f5);
|
|
264
285
|
min-height: 25px;
|
|
265
286
|
height: 63px;
|
|
266
287
|
margin-bottom: 1px; /* Chrome overflow rendering bug? When only component in a view */
|
package/cosmoz-omnitable.js
CHANGED
|
@@ -3,7 +3,6 @@ import '@polymer/iron-icons/iron-icons';
|
|
|
3
3
|
import '@polymer/iron-icon/iron-icon';
|
|
4
4
|
import '@polymer/iron-label/iron-label';
|
|
5
5
|
import '@polymer/paper-button/paper-button';
|
|
6
|
-
import '@polymer/paper-checkbox/paper-checkbox';
|
|
7
6
|
import '@polymer/paper-dropdown-menu/paper-dropdown-menu';
|
|
8
7
|
import '@polymer/paper-icon-button/paper-icon-button';
|
|
9
8
|
import '@polymer/paper-item/paper-item';
|
|
@@ -37,6 +36,7 @@ import { mixin, hauntedPolymer } from '@neovici/cosmoz-utils';
|
|
|
37
36
|
import { isEmpty } from '@neovici/cosmoz-utils/lib/template.js';
|
|
38
37
|
import { useOmnitable } from './lib/use-omnitable';
|
|
39
38
|
import './lib/cosmoz-omnitable-settings';
|
|
39
|
+
import { genericSorter } from './lib/generic-sorter';
|
|
40
40
|
|
|
41
41
|
const PROPERTY_HASH_PARAMS = ['sortOn', 'groupOn', 'descending', 'groupOnDescending'];
|
|
42
42
|
|
|
@@ -64,7 +64,7 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
64
64
|
<cosmoz-omnitable-header-row
|
|
65
65
|
columns="[[ normalizedColumns ]]"
|
|
66
66
|
group-on-column="[[ groupOnColumn ]]"
|
|
67
|
-
content="[[ _renderSettings(normalizedSettings, collapsedColumns, settingsId, hasChangedSettings) ]]"
|
|
67
|
+
content="[[ _renderSettings(normalizedSettings, collapsedColumns, settingsId, hasChangedSettings, hasHiddenFilter) ]]"
|
|
68
68
|
>
|
|
69
69
|
</div>
|
|
70
70
|
<div class="tableContent" id="tableContent">
|
|
@@ -377,7 +377,8 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
377
377
|
*/
|
|
378
378
|
columns: {
|
|
379
379
|
type: Array,
|
|
380
|
-
notify: true
|
|
380
|
+
notify: true,
|
|
381
|
+
value: () => []
|
|
381
382
|
},
|
|
382
383
|
|
|
383
384
|
settings: {
|
|
@@ -455,6 +456,7 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
455
456
|
window.addEventListener('keydown', this._onKey);
|
|
456
457
|
window.addEventListener('keyup', this._onKey);
|
|
457
458
|
this._resizeObserver.observe(this);
|
|
459
|
+
this._updateParamsFromHash();
|
|
458
460
|
}
|
|
459
461
|
|
|
460
462
|
disconnectedCallback() {
|
|
@@ -521,7 +523,6 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
521
523
|
}
|
|
522
524
|
|
|
523
525
|
_onColumnTitleChanged(event) {
|
|
524
|
-
|
|
525
526
|
event.stopPropagation();
|
|
526
527
|
|
|
527
528
|
if (!Array.isArray(this.columns)) {
|
|
@@ -729,16 +730,11 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
729
730
|
* @param {String} attribute The attribute name of the column.
|
|
730
731
|
* @returns {Object} The found column.
|
|
731
732
|
*/
|
|
732
|
-
_getColumn(attributeValue, attribute = 'name', columns
|
|
733
|
+
_getColumn(attributeValue, attribute = 'name', columns) {
|
|
733
734
|
if (!attributeValue || !columns) {
|
|
734
735
|
return;
|
|
735
736
|
}
|
|
736
|
-
|
|
737
|
-
if (!column) {
|
|
738
|
-
// eslint-disable-next-line no-console
|
|
739
|
-
console.warn(`Cannot find column with ${ attribute } ${ attributeValue }`);
|
|
740
|
-
}
|
|
741
|
-
return column;
|
|
737
|
+
return columns.find(column => column[attribute] === attributeValue);
|
|
742
738
|
}
|
|
743
739
|
|
|
744
740
|
_filterChanged({ detail }) {
|
|
@@ -749,12 +745,8 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
749
745
|
this._filterForRouteChanged(detail.column);
|
|
750
746
|
}
|
|
751
747
|
|
|
752
|
-
_groupOnColumnChanged(
|
|
753
|
-
|
|
754
|
-
column.resetFilter();
|
|
755
|
-
} else {
|
|
756
|
-
this._debounceProcessItems();
|
|
757
|
-
}
|
|
748
|
+
_groupOnColumnChanged() {
|
|
749
|
+
this._debounceProcessItems();
|
|
758
750
|
}
|
|
759
751
|
|
|
760
752
|
_debounceProcessItems() {
|
|
@@ -837,7 +829,7 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
837
829
|
const v1 = groupOnColumn.getComparableValue(a.items[0], groupOnColumn.groupOn),
|
|
838
830
|
v2 = groupOnColumn.getComparableValue(b.items[0], groupOnColumn.groupOn);
|
|
839
831
|
|
|
840
|
-
return
|
|
832
|
+
return genericSorter(v1, v2);
|
|
841
833
|
});
|
|
842
834
|
|
|
843
835
|
if (this.groupOnDescending) {
|
|
@@ -848,42 +840,6 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
848
840
|
this.filteredGroupedItems = groups;
|
|
849
841
|
}
|
|
850
842
|
|
|
851
|
-
/* eslint-disable-next-line max-statements */
|
|
852
|
-
_genericSorter(a, b) {
|
|
853
|
-
if (a === b) {
|
|
854
|
-
return 0;
|
|
855
|
-
}
|
|
856
|
-
|
|
857
|
-
if (a === undefined) {
|
|
858
|
-
return -1;
|
|
859
|
-
}
|
|
860
|
-
|
|
861
|
-
if (b === undefined) {
|
|
862
|
-
return 1;
|
|
863
|
-
}
|
|
864
|
-
|
|
865
|
-
if (typeof a === 'object' && typeof b === 'object') {
|
|
866
|
-
// HACK(pasleq): worst case, compare using values converted to string
|
|
867
|
-
return a.toString() < b.toString() ? -1 : 1;
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
if (typeof a === 'number' && typeof b === 'number') {
|
|
871
|
-
return a - b;
|
|
872
|
-
}
|
|
873
|
-
|
|
874
|
-
if (typeof a === 'string' && typeof b === 'string') {
|
|
875
|
-
return a < b ? -1 : 1;
|
|
876
|
-
}
|
|
877
|
-
|
|
878
|
-
if (typeof a === 'boolean' && typeof b === 'boolean') {
|
|
879
|
-
return a ? -1 : 1;
|
|
880
|
-
}
|
|
881
|
-
|
|
882
|
-
// eslint-disable-next-line no-console
|
|
883
|
-
console.warn('unsupported sort', typeof a, a, typeof b, b);
|
|
884
|
-
return 0;
|
|
885
|
-
}
|
|
886
|
-
|
|
887
843
|
/**
|
|
888
844
|
* compareFunction for sort(), can be overridden
|
|
889
845
|
* @see Array.prototype.sort()
|
|
@@ -896,7 +852,7 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
896
852
|
const v1 = this.sortOnColumn.getComparableValue(a, this.sortOnColumn.sortOn),
|
|
897
853
|
v2 = this.sortOnColumn.getComparableValue(b, this.sortOnColumn.sortOn);
|
|
898
854
|
|
|
899
|
-
return
|
|
855
|
+
return genericSorter(v1, v2);
|
|
900
856
|
}
|
|
901
857
|
|
|
902
858
|
/* eslint-disable-next-line max-statements */
|
|
@@ -1173,14 +1129,9 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
1173
1129
|
const column = this.columns.find(c => c.name === key);
|
|
1174
1130
|
|
|
1175
1131
|
if (!column) {
|
|
1176
|
-
// eslint-disable-next-line no-console
|
|
1177
|
-
console.warn('column with name', name, 'for param', key, 'not found!');
|
|
1178
1132
|
return;
|
|
1179
1133
|
}
|
|
1180
1134
|
|
|
1181
|
-
if (column === this.groupOnColumn) {
|
|
1182
|
-
return;
|
|
1183
|
-
}
|
|
1184
1135
|
if (value === column._serializeFilter()) {
|
|
1185
1136
|
return;
|
|
1186
1137
|
}
|
|
@@ -1285,7 +1236,7 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
1285
1236
|
};
|
|
1286
1237
|
}
|
|
1287
1238
|
|
|
1288
|
-
_renderSettings(normalizedSettings, collapsed, settingsId, hasChangedSettings) {
|
|
1239
|
+
_renderSettings(normalizedSettings, collapsed, settingsId, hasChangedSettings, hasHiddenFilter) {
|
|
1289
1240
|
return litHtml`<cosmoz-omnitable-settings
|
|
1290
1241
|
.settings=${ normalizedSettings }
|
|
1291
1242
|
.onSettings=${ this.setSettings }
|
|
@@ -1294,6 +1245,7 @@ class Omnitable extends hauntedPolymer(useOmnitable)(mixin({ isEmpty }, translat
|
|
|
1294
1245
|
.hasChanges=${ hasChangedSettings }
|
|
1295
1246
|
.onSave=${ this.onSettingsSave }
|
|
1296
1247
|
.onReset=${ this.onSettingsReset }
|
|
1248
|
+
.badge=${ hasHiddenFilter }
|
|
1297
1249
|
>`;
|
|
1298
1250
|
}
|
|
1299
1251
|
}
|
|
@@ -5,6 +5,7 @@ import { portal } from '@neovici/cosmoz-utils/lib/directives/portal';
|
|
|
5
5
|
import { useMeta } from '@neovici/cosmoz-utils/lib/hooks/use-meta';
|
|
6
6
|
import { checkbox } from '../cosmoz-omnitable-styles';
|
|
7
7
|
import { nothing } from 'lit-html';
|
|
8
|
+
import { columnSymbol } from './normalize-settings';
|
|
8
9
|
const settingsStyles = `
|
|
9
10
|
:host {
|
|
10
11
|
position: fixed;
|
|
@@ -54,6 +55,9 @@ const settingsStyles = `
|
|
|
54
55
|
.title {
|
|
55
56
|
flex: 1;
|
|
56
57
|
}
|
|
58
|
+
.title[has-filter] {
|
|
59
|
+
font-weight: bold;
|
|
60
|
+
}
|
|
57
61
|
${ checkbox }
|
|
58
62
|
.footer {
|
|
59
63
|
display: flex;
|
|
@@ -177,7 +181,7 @@ const settingsStyles = `
|
|
|
177
181
|
<button class="sort" mousedown="">
|
|
178
182
|
<svg viewBox="0 0 24 24" width="24"><path d="M20 9H4v2h16V9zM4 15h16v-2H4v2z"></path></svg>
|
|
179
183
|
</button>
|
|
180
|
-
<label class="title">${ column.title }</label>
|
|
184
|
+
<label class="title" ?has-filter=${ !!column[columnSymbol].getFilterFn() }>${ column.title }</label>
|
|
181
185
|
<input class="checkbox" type="checkbox" .checked=${ checked } @click=${ onToggle }
|
|
182
186
|
.indeterminate=${ indeterminate } .windeterminate=${ indeterminate }
|
|
183
187
|
>
|
|
@@ -201,7 +205,7 @@ const settingsStyles = `
|
|
|
201
205
|
},
|
|
202
206
|
|
|
203
207
|
Settings = host => {
|
|
204
|
-
const { settings, onSettings, onSave, onReset, collapsed, settingsId, hasChanges } = host,
|
|
208
|
+
const { settings, onSettings, onSave, onReset, collapsed, settingsId, hasChanges, badge } = host,
|
|
205
209
|
{ active, onFocus, onToggle } = useFocus(host),
|
|
206
210
|
anchor = useCallback(() => host.shadowRoot.querySelector('.anchor'), []);
|
|
207
211
|
|
|
@@ -216,14 +220,25 @@ const settingsStyles = `
|
|
|
216
220
|
outline: none;
|
|
217
221
|
background: transparent;
|
|
218
222
|
cursor: pointer;
|
|
223
|
+
position: relative;
|
|
219
224
|
}
|
|
220
225
|
.anchor * { pointer-events: none; }
|
|
221
226
|
.anchor:hover {
|
|
222
227
|
background: #eee;
|
|
223
228
|
}
|
|
229
|
+
.badge {
|
|
230
|
+
position: absolute;
|
|
231
|
+
top: 1px;
|
|
232
|
+
right: -4px;
|
|
233
|
+
background-color: var(--cosmoz-omnitable-checkbox-checked-color, var(--primary-color));
|
|
234
|
+
width: 8px;
|
|
235
|
+
height: 8px;
|
|
236
|
+
border-radius: 100%;
|
|
237
|
+
}
|
|
224
238
|
</style>
|
|
225
|
-
|
|
239
|
+
<button class="anchor" @focus=${ onFocus } @blur=${ onFocus } @click=${ onToggle } @mousedown=${ preventDefault }>
|
|
226
240
|
<svg viewBox="0 0 24 24" width="24"><path d="M10 18h5V5h-5v13zm-6 0h5V5H4v13zM16 5v13h5V5h-5z"></path></svg>
|
|
241
|
+
${ badge ? html`<div class="badge"></div>` : nothing }
|
|
227
242
|
</button>
|
|
228
243
|
${ active
|
|
229
244
|
? portal(html`<cosmoz-omnitable-settings-ui
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// eslint-disable-next-line max-statements
|
|
2
|
+
export const genericSorter = (a, b) => {
|
|
3
|
+
if (a === b) {
|
|
4
|
+
return 0;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
if (a === undefined) {
|
|
8
|
+
return -1;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
if (b === undefined) {
|
|
12
|
+
return 1;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
if (typeof a === 'object' && typeof b === 'object') {
|
|
16
|
+
// HACK(pasleq): worst case, compare using values converted to string
|
|
17
|
+
return a.toString() < b.toString() ? -1 : 1;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (typeof a === 'number' && typeof b === 'number') {
|
|
21
|
+
return a - b;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (typeof a === 'string' && typeof b === 'string') {
|
|
25
|
+
return a < b ? -1 : 1;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (typeof a === 'boolean' && typeof b === 'boolean') {
|
|
29
|
+
return a ? -1 : 1;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// eslint-disable-next-line no-console
|
|
33
|
+
console.warn('unsupported sort', typeof a, a, typeof b, b);
|
|
34
|
+
return 0;
|
|
35
|
+
};
|
package/lib/use-omnitable.js
CHANGED
|
@@ -6,12 +6,26 @@ import { useSavedSettings } from './use-saved-settings';
|
|
|
6
6
|
// eslint-disable-next-line max-lines-per-function
|
|
7
7
|
export const useOmnitable = host => {
|
|
8
8
|
const
|
|
9
|
-
{ columns, groupOnColumn, resizeSpeedFactor, settingsId } = host,
|
|
9
|
+
{ columns, groupOnColumn, resizeSpeedFactor, settingsId, sortedFilteredGroupedItems } = host,
|
|
10
10
|
[settings, setSettings] = useState([]),
|
|
11
11
|
{ savedSettings, onSettingsSave, onSettingsReset, hasChangedSettings } = useSavedSettings(settingsId, settings, setSettings),
|
|
12
12
|
normalizedSettings = useMemo(() => normalizeSettings(columns, settings, savedSettings), [columns, settings, savedSettings]),
|
|
13
13
|
normalizedColumns = useMemo(() => normalizedSettings.map(s => s[columnSymbol]), [columns, ...normalizedSettings.map(s => s.name)]),
|
|
14
|
-
{ layoutCss, collapsedColumns } = useFastLayout({ host, settings: normalizedSettings, setSettings, groupOnColumn, resizeSpeedFactor })
|
|
14
|
+
{ layoutCss, collapsedColumns } = useFastLayout({ host, settings: normalizedSettings, setSettings, groupOnColumn, resizeSpeedFactor }),
|
|
15
|
+
filterFunctions = useMemo(() => {
|
|
16
|
+
if (!columns) {
|
|
17
|
+
return {};
|
|
18
|
+
}
|
|
19
|
+
return Object.fromEntries(columns
|
|
20
|
+
.map(col => [col.name, col.getFilterFn()])
|
|
21
|
+
.filter(([, fn]) => fn !== undefined));
|
|
22
|
+
}, [sortedFilteredGroupedItems]),
|
|
23
|
+
columnsWithFilters = useMemo(() => Object.keys(filterFunctions), [filterFunctions]),
|
|
24
|
+
hasHiddenFilter = useMemo(
|
|
25
|
+
() => [groupOnColumn, ...collapsedColumns, ...normalizedSettings.filter(s => s.disabled)]
|
|
26
|
+
.some(column => column && columnsWithFilters.includes(column.name)),
|
|
27
|
+
[columnsWithFilters, normalizedSettings, collapsedColumns]
|
|
28
|
+
);
|
|
15
29
|
|
|
16
30
|
return {
|
|
17
31
|
layoutCss,
|
|
@@ -19,6 +33,7 @@ export const useOmnitable = host => {
|
|
|
19
33
|
normalizedSettings,
|
|
20
34
|
normalizedColumns,
|
|
21
35
|
collapsedColumns,
|
|
36
|
+
hasHiddenFilter,
|
|
22
37
|
onSettingsSave,
|
|
23
38
|
onSettingsReset,
|
|
24
39
|
hasChangedSettings
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { useCallback, useMemo, useState } from 'haunted';
|
|
2
|
-
import {
|
|
2
|
+
import { props } from '@neovici/cosmoz-utils/lib/object';
|
|
3
3
|
|
|
4
4
|
const storagePrefix = 'omnitable-';
|
|
5
5
|
|
|
@@ -27,7 +27,7 @@ export const useSavedSettings = (settingsId, settings, setSettings) => {
|
|
|
27
27
|
}
|
|
28
28
|
|
|
29
29
|
try {
|
|
30
|
-
localStorage.setItem(storagePrefix + settingsId, JSON.stringify(settings.map(
|
|
30
|
+
localStorage.setItem(storagePrefix + settingsId, JSON.stringify(settings.map(props(['name', 'priority', 'width', 'flex', 'disabled']))));
|
|
31
31
|
setSettings([]);
|
|
32
32
|
setCounter(counter => counter + 1);
|
|
33
33
|
} catch (e) {
|
|
@@ -36,8 +36,17 @@ export const useSavedSettings = (settingsId, settings, setSettings) => {
|
|
|
36
36
|
}
|
|
37
37
|
}, [settings]),
|
|
38
38
|
|
|
39
|
-
onSettingsReset:
|
|
39
|
+
onSettingsReset: e => {
|
|
40
40
|
setSettings([]);
|
|
41
|
+
|
|
42
|
+
if (e.shiftKey) {
|
|
43
|
+
try {
|
|
44
|
+
localStorage.removeItem(storagePrefix + settingsId);
|
|
45
|
+
setCounter(counter => counter + 1);
|
|
46
|
+
} catch (err) {
|
|
47
|
+
// ignore error
|
|
48
|
+
}
|
|
49
|
+
}
|
|
41
50
|
},
|
|
42
51
|
|
|
43
52
|
hasChangedSettings: settings.length !== 0
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@neovici/cosmoz-omnitable",
|
|
3
|
-
"version": "7.
|
|
3
|
+
"version": "7.3.0",
|
|
4
4
|
"description": "[](https://travis-ci.org/Neovici/cosmoz-omnitable)",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"web-components"
|
|
@@ -64,7 +64,6 @@
|
|
|
64
64
|
"@polymer/iron-icons": "^3.0.0",
|
|
65
65
|
"@polymer/iron-label": "^3.0.0",
|
|
66
66
|
"@polymer/paper-button": "^3.0.0",
|
|
67
|
-
"@polymer/paper-checkbox": "^3.0.0",
|
|
68
67
|
"@polymer/paper-dropdown-menu": "^3.2.0",
|
|
69
68
|
"@polymer/paper-icon-button": "^3.0.0",
|
|
70
69
|
"@polymer/paper-input": "^3.2.0",
|
|
@@ -1,294 +0,0 @@
|
|
|
1
|
-
import { dedupingMixin } from '@polymer/polymer/lib/utils/mixin';
|
|
2
|
-
import { render } from 'lit-html';
|
|
3
|
-
import { set } from '@polymer/polymer/lib/utils/path';
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Allows manipulation of elements.
|
|
7
|
-
* @callback OmnitableRepeaterMixin~forEachElementCallback
|
|
8
|
-
* @param {HTMLElement} element
|
|
9
|
-
* @param {OmnitableColumn} column
|
|
10
|
-
* @param {TemplateInstance} instance
|
|
11
|
-
* @return {void}
|
|
12
|
-
*/
|
|
13
|
-
|
|
14
|
-
const editableRegex = /columns\.(\d*)\.editable/iu;
|
|
15
|
-
|
|
16
|
-
/**
|
|
17
|
-
*
|
|
18
|
-
* @polymer
|
|
19
|
-
* @mixinFunction
|
|
20
|
-
*/
|
|
21
|
-
export const repeaterMixin = dedupingMixin(base => class extends base { // eslint-disable-line max-lines-per-function
|
|
22
|
-
static get properties() {
|
|
23
|
-
return {
|
|
24
|
-
columns: {
|
|
25
|
-
type: Array
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
groupOnColumn: {
|
|
29
|
-
type: Object,
|
|
30
|
-
observer: '_groupOnColumnChanged'
|
|
31
|
-
}
|
|
32
|
-
};
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
constructor() {
|
|
36
|
-
super();
|
|
37
|
-
this._elements = [];
|
|
38
|
-
this._columnsObserver = null;
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
/**
|
|
42
|
-
* Adds an observer to render the cells when the columns are changed.
|
|
43
|
-
* @return {void}
|
|
44
|
-
*/
|
|
45
|
-
trackColumns() {
|
|
46
|
-
if (this._columnsObserver) {
|
|
47
|
-
throw new Error('The columns are already tracked.');
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
this._createMethodObserver('_columnsChanged(columns.*)');
|
|
51
|
-
|
|
52
|
-
// HACK we have to muck around with the property effect references because
|
|
53
|
-
// _createMethodObserver does not provide any reference to the property
|
|
54
|
-
// effect so we can easily remove it
|
|
55
|
-
this._columnsObserver = this[this.PROPERTY_EFFECT_TYPES.OBSERVE]['columns']
|
|
56
|
-
.find(fx => fx.info.methodName === '_columnsChanged');
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Stops reacting to column changes.
|
|
61
|
-
* @return {void}
|
|
62
|
-
*/
|
|
63
|
-
stopTrackingColumns() {
|
|
64
|
-
if (!this._columnsObserver) {
|
|
65
|
-
throw new Error('The columns are not tracked.');
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
this._removePropertyEffect('columns', this.PROPERTY_EFFECT_TYPES.OBSERVE, this._columnsObserver);
|
|
69
|
-
this._columnsObserver = null;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
/**
|
|
73
|
-
* Renders all cells.
|
|
74
|
-
* @return {void}
|
|
75
|
-
*/
|
|
76
|
-
renderCells() {
|
|
77
|
-
this._addElements(0, this.columns.length);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Destroys all cells.
|
|
82
|
-
* @return {void}
|
|
83
|
-
*/
|
|
84
|
-
destroyCells() {
|
|
85
|
-
this._removeElements(0, this.columns);
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
/**
|
|
89
|
-
* Forwards a property change to all cells.
|
|
90
|
-
* @param {String} property the property
|
|
91
|
-
* @param {any} value the new value
|
|
92
|
-
* @return {void}
|
|
93
|
-
*/
|
|
94
|
-
forwardChange(property, value) {
|
|
95
|
-
this.forwardPathChange({
|
|
96
|
-
path: property,
|
|
97
|
-
value
|
|
98
|
-
});
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
/**
|
|
102
|
-
* Forwards a path change to all cells.
|
|
103
|
-
* @param {Object} changeRecord the change record
|
|
104
|
-
* @return {void}
|
|
105
|
-
*/
|
|
106
|
-
forwardPathChange(changeRecord) {
|
|
107
|
-
this._elements.forEach(element =>
|
|
108
|
-
this._forwardNotifyPath(element.__instance, changeRecord.path, changeRecord.value, true)
|
|
109
|
-
);
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
/**
|
|
113
|
-
* Runs a callback on each element.
|
|
114
|
-
* @param {OmnitableRepeaterMixin~forEachElementCallback} callback the callback
|
|
115
|
-
* @return {void}
|
|
116
|
-
*/
|
|
117
|
-
forEachElement(callback) {
|
|
118
|
-
this._elements.forEach(element => callback(element, element.__column, element.__instance));
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/* eslint-disable no-empty-function, no-unused-vars */
|
|
122
|
-
|
|
123
|
-
/**
|
|
124
|
-
* The type of element to be repeated.
|
|
125
|
-
* Must be defined in implementors.
|
|
126
|
-
* @return {String} The type of element to be repeated.
|
|
127
|
-
*/
|
|
128
|
-
get _elementType() {
|
|
129
|
-
return null;
|
|
130
|
-
}
|
|
131
|
-
|
|
132
|
-
/**
|
|
133
|
-
* Slot name assigned to the repeated elements.
|
|
134
|
-
* Must be defined in implementors.
|
|
135
|
-
* @return {String} Slot name assigned to the repeated elements.
|
|
136
|
-
*/
|
|
137
|
-
get _slotName() {
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Get a render function for the specified column
|
|
143
|
-
* Must be defined in implementors.
|
|
144
|
-
* @abstract
|
|
145
|
-
* @param {OmnitableColumnMixin} column - The column.
|
|
146
|
-
* @return {Function} - The render function.
|
|
147
|
-
*/
|
|
148
|
-
_getRenderFn(column) {}
|
|
149
|
-
|
|
150
|
-
/* eslint-enable no-empty-function, no-unused-vars */
|
|
151
|
-
|
|
152
|
-
/**
|
|
153
|
-
* Configure a newly created repeated element
|
|
154
|
-
*
|
|
155
|
-
* @param {HTMLElement} element the root cell element
|
|
156
|
-
* @param {OmnitableColumnMixin} column the column
|
|
157
|
-
* @param {TemplateInstance} instance the template instance
|
|
158
|
-
* @return {void}
|
|
159
|
-
*/
|
|
160
|
-
_configureElement(element, column, instance) {
|
|
161
|
-
element.__instance = instance;
|
|
162
|
-
element.__column = column;
|
|
163
|
-
|
|
164
|
-
if (column === this.groupOnColumn) {
|
|
165
|
-
element.setAttribute('hidden', true);
|
|
166
|
-
}
|
|
167
|
-
|
|
168
|
-
element.setAttribute('slot', this._slotName);
|
|
169
|
-
|
|
170
|
-
column.addEventListener('cosmoz-column-prop-changed', instance.render);
|
|
171
|
-
|
|
172
|
-
element.__cleanup = () => {
|
|
173
|
-
element.__instance = element.__column = element.column = null;
|
|
174
|
-
column.removeEventListener('cosmoz-column-prop-changed', instance.render);
|
|
175
|
-
};
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
_columnsChanged({
|
|
179
|
-
path, base, value
|
|
180
|
-
}) {
|
|
181
|
-
const reMatch = editableRegex.exec(path);
|
|
182
|
-
|
|
183
|
-
if (path === 'columns') {
|
|
184
|
-
if (this._elements && this._elements.length) {
|
|
185
|
-
const removedColumns = this._elements.map(element => {
|
|
186
|
-
return element.__column;
|
|
187
|
-
});
|
|
188
|
-
this._removeElements(0, removedColumns);
|
|
189
|
-
} else {
|
|
190
|
-
this._elements = [];
|
|
191
|
-
}
|
|
192
|
-
this._addElements(0, this.columns.length);
|
|
193
|
-
} else if (path === 'columns.splices') {
|
|
194
|
-
this._renderSplices(value.indexSplices);
|
|
195
|
-
} else if (reMatch) {
|
|
196
|
-
// eslint-disable-next-line no-bitwise
|
|
197
|
-
const index = reMatch[1] >> 0,
|
|
198
|
-
column = base[index];
|
|
199
|
-
this._removeElements(index, [column]);
|
|
200
|
-
this._addElements(index, 1);
|
|
201
|
-
} else if (path !== 'columns.length') {
|
|
202
|
-
// column property change
|
|
203
|
-
// eslint-disable-next-line no-console
|
|
204
|
-
console.warn('column property change', path);
|
|
205
|
-
}
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
_renderSplices(splices) {
|
|
209
|
-
splices.forEach(splice => {
|
|
210
|
-
if (splice.removed.length) {
|
|
211
|
-
this._removeElements(splice.index, splice.removed);
|
|
212
|
-
}
|
|
213
|
-
if (splice.addedCount > 0) {
|
|
214
|
-
this._addElements(splice.index, splice.addedCount);
|
|
215
|
-
}
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
_getInstance(updateFn) {
|
|
220
|
-
const state = {
|
|
221
|
-
item: this.item,
|
|
222
|
-
selected: this.selected,
|
|
223
|
-
expanded: this.expanded,
|
|
224
|
-
folded: this.folded
|
|
225
|
-
};
|
|
226
|
-
updateFn(state);
|
|
227
|
-
|
|
228
|
-
return {
|
|
229
|
-
_setPendingPropertyOrPath(path, value) {
|
|
230
|
-
set(state, path, value);
|
|
231
|
-
},
|
|
232
|
-
_flushProperties() {
|
|
233
|
-
updateFn(state);
|
|
234
|
-
},
|
|
235
|
-
render() {
|
|
236
|
-
updateFn(state);
|
|
237
|
-
}
|
|
238
|
-
};
|
|
239
|
-
}
|
|
240
|
-
|
|
241
|
-
_addElements(start, count) {
|
|
242
|
-
const end = start + count;
|
|
243
|
-
for (let i = start; i < end; i++) {
|
|
244
|
-
const element = document.createElement(this._elementType),
|
|
245
|
-
column = this.columns[i],
|
|
246
|
-
renderFn = this._getRenderFn(column),
|
|
247
|
-
instance = this._getInstance(state => render(renderFn(column, state), element));
|
|
248
|
-
|
|
249
|
-
this._configureElement(element, column, instance);
|
|
250
|
-
|
|
251
|
-
if (i < this._elements.length) {
|
|
252
|
-
this.insertBefore(element, this._elements[i]);
|
|
253
|
-
} else {
|
|
254
|
-
this.appendChild(element);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
this._elements.splice(i, 0, element);
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
_removeElements(start, removedColumns) {
|
|
262
|
-
this._elements
|
|
263
|
-
.splice(start, removedColumns.length)
|
|
264
|
-
.forEach(element => {
|
|
265
|
-
element.__cleanup();
|
|
266
|
-
this.removeChild(element);
|
|
267
|
-
});
|
|
268
|
-
}
|
|
269
|
-
|
|
270
|
-
_groupOnColumnChanged(column, previousColumn) {
|
|
271
|
-
if (!this._elements || !this._elements.length) {
|
|
272
|
-
return;
|
|
273
|
-
}
|
|
274
|
-
if (previousColumn) {
|
|
275
|
-
const previousElement = this._elements.find(e => e.__column === previousColumn);
|
|
276
|
-
if (previousElement) {
|
|
277
|
-
previousElement.removeAttribute('hidden');
|
|
278
|
-
}
|
|
279
|
-
}
|
|
280
|
-
if (column) {
|
|
281
|
-
const element = this._elements.find(e => e.__column === column);
|
|
282
|
-
if (element) {
|
|
283
|
-
element.setAttribute('hidden', '');
|
|
284
|
-
}
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
|
|
288
|
-
_forwardNotifyPath(instance, path, value, flush = false) {
|
|
289
|
-
instance._setPendingPropertyOrPath(path, value, false, true);
|
|
290
|
-
if (flush) {
|
|
291
|
-
instance._flushProperties(true);
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
});
|