@vaadin/grid 22.0.0-alpha7
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/LICENSE +190 -0
- package/README.md +79 -0
- package/all-imports.js +1 -0
- package/package.json +58 -0
- package/src/all-imports.js +14 -0
- package/src/array-data-provider.js +145 -0
- package/src/interfaces.d.ts +75 -0
- package/src/vaadin-grid-a11y-mixin.js +158 -0
- package/src/vaadin-grid-active-item-mixin.d.ts +19 -0
- package/src/vaadin-grid-active-item-mixin.js +117 -0
- package/src/vaadin-grid-array-data-provider-mixin.d.ts +16 -0
- package/src/vaadin-grid-array-data-provider-mixin.js +75 -0
- package/src/vaadin-grid-column-group.d.ts +54 -0
- package/src/vaadin-grid-column-group.js +320 -0
- package/src/vaadin-grid-column-reordering-mixin.d.ts +19 -0
- package/src/vaadin-grid-column-reordering-mixin.js +387 -0
- package/src/vaadin-grid-column-resizing-mixin.js +111 -0
- package/src/vaadin-grid-column.d.ts +133 -0
- package/src/vaadin-grid-column.js +745 -0
- package/src/vaadin-grid-data-provider-mixin.d.ts +108 -0
- package/src/vaadin-grid-data-provider-mixin.js +520 -0
- package/src/vaadin-grid-drag-and-drop-mixin.d.ts +69 -0
- package/src/vaadin-grid-drag-and-drop-mixin.js +433 -0
- package/src/vaadin-grid-dynamic-columns-mixin.js +180 -0
- package/src/vaadin-grid-event-context-mixin.d.ts +33 -0
- package/src/vaadin-grid-event-context-mixin.js +57 -0
- package/src/vaadin-grid-filter-column.d.ts +35 -0
- package/src/vaadin-grid-filter-column.js +120 -0
- package/src/vaadin-grid-filter-mixin.js +76 -0
- package/src/vaadin-grid-filter.d.ts +67 -0
- package/src/vaadin-grid-filter.js +125 -0
- package/src/vaadin-grid-helpers.js +23 -0
- package/src/vaadin-grid-keyboard-navigation-mixin.js +891 -0
- package/src/vaadin-grid-row-details-mixin.d.ts +44 -0
- package/src/vaadin-grid-row-details-mixin.js +200 -0
- package/src/vaadin-grid-scroll-mixin.d.ts +18 -0
- package/src/vaadin-grid-scroll-mixin.js +202 -0
- package/src/vaadin-grid-selection-column.d.ts +71 -0
- package/src/vaadin-grid-selection-column.js +285 -0
- package/src/vaadin-grid-selection-mixin.d.ts +30 -0
- package/src/vaadin-grid-selection-mixin.js +93 -0
- package/src/vaadin-grid-sort-column.d.ts +63 -0
- package/src/vaadin-grid-sort-column.js +118 -0
- package/src/vaadin-grid-sort-mixin.d.ts +15 -0
- package/src/vaadin-grid-sort-mixin.js +139 -0
- package/src/vaadin-grid-sorter.d.ts +94 -0
- package/src/vaadin-grid-sorter.js +230 -0
- package/src/vaadin-grid-styles.js +297 -0
- package/src/vaadin-grid-styling-mixin.d.ts +37 -0
- package/src/vaadin-grid-styling-mixin.js +71 -0
- package/src/vaadin-grid-tree-column.d.ts +36 -0
- package/src/vaadin-grid-tree-column.js +119 -0
- package/src/vaadin-grid-tree-toggle.d.ts +104 -0
- package/src/vaadin-grid-tree-toggle.js +205 -0
- package/src/vaadin-grid.d.ts +397 -0
- package/src/vaadin-grid.js +1004 -0
- package/theme/lumo/all-imports.js +11 -0
- package/theme/lumo/vaadin-grid-column-group.js +1 -0
- package/theme/lumo/vaadin-grid-column.js +1 -0
- package/theme/lumo/vaadin-grid-filter-column.js +2 -0
- package/theme/lumo/vaadin-grid-filter.js +2 -0
- package/theme/lumo/vaadin-grid-selection-column.js +2 -0
- package/theme/lumo/vaadin-grid-sort-column.js +2 -0
- package/theme/lumo/vaadin-grid-sorter-styles.js +53 -0
- package/theme/lumo/vaadin-grid-sorter.js +2 -0
- package/theme/lumo/vaadin-grid-styles.js +378 -0
- package/theme/lumo/vaadin-grid-tree-column.js +2 -0
- package/theme/lumo/vaadin-grid-tree-toggle-styles.js +112 -0
- package/theme/lumo/vaadin-grid-tree-toggle.js +2 -0
- package/theme/lumo/vaadin-grid.js +9 -0
- package/theme/material/all-imports.js +11 -0
- package/theme/material/vaadin-grid-column-group.js +1 -0
- package/theme/material/vaadin-grid-column.js +1 -0
- package/theme/material/vaadin-grid-filter-column.js +2 -0
- package/theme/material/vaadin-grid-filter.js +2 -0
- package/theme/material/vaadin-grid-selection-column.js +2 -0
- package/theme/material/vaadin-grid-sort-column.js +2 -0
- package/theme/material/vaadin-grid-sorter-styles.js +72 -0
- package/theme/material/vaadin-grid-sorter.js +2 -0
- package/theme/material/vaadin-grid-styles.js +252 -0
- package/theme/material/vaadin-grid-tree-column.js +2 -0
- package/theme/material/vaadin-grid-tree-toggle-styles.js +42 -0
- package/theme/material/vaadin-grid-tree-toggle.js +2 -0
- package/theme/material/vaadin-grid.js +2 -0
- package/vaadin-grid-column-group.d.ts +1 -0
- package/vaadin-grid-column-group.js +3 -0
- package/vaadin-grid-column.d.ts +1 -0
- package/vaadin-grid-column.js +3 -0
- package/vaadin-grid-filter-column.d.ts +1 -0
- package/vaadin-grid-filter-column.js +3 -0
- package/vaadin-grid-filter.d.ts +1 -0
- package/vaadin-grid-filter.js +3 -0
- package/vaadin-grid-selection-column.d.ts +1 -0
- package/vaadin-grid-selection-column.js +3 -0
- package/vaadin-grid-sort-column.d.ts +1 -0
- package/vaadin-grid-sort-column.js +3 -0
- package/vaadin-grid-sorter.d.ts +1 -0
- package/vaadin-grid-sorter.js +3 -0
- package/vaadin-grid-tree-column.d.ts +1 -0
- package/vaadin-grid-tree-column.js +3 -0
- package/vaadin-grid-tree-toggle.d.ts +1 -0
- package/vaadin-grid-tree-toggle.js +3 -0
- package/vaadin-grid.d.ts +3 -0
- package/vaadin-grid.js +4 -0
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
import { GridDataProvider } from './interfaces';
|
|
2
|
+
|
|
3
|
+
declare class ItemCache<TItem> {
|
|
4
|
+
grid: HTMLElement;
|
|
5
|
+
parentCache: ItemCache<TItem> | undefined;
|
|
6
|
+
parentItem: TItem | undefined;
|
|
7
|
+
itemCaches: object | null;
|
|
8
|
+
items: object | null;
|
|
9
|
+
effectiveSize: number;
|
|
10
|
+
size: number;
|
|
11
|
+
pendingRequests: object | null;
|
|
12
|
+
|
|
13
|
+
constructor(grid: HTMLElement, parentCache: ItemCache<TItem> | undefined, parentItem: TItem | undefined);
|
|
14
|
+
|
|
15
|
+
isLoading(): boolean;
|
|
16
|
+
|
|
17
|
+
getItemForIndex(index: number): TItem | undefined;
|
|
18
|
+
|
|
19
|
+
updateSize(): void;
|
|
20
|
+
|
|
21
|
+
ensureSubCacheForScaledIndex(scaledIndex: number): void;
|
|
22
|
+
|
|
23
|
+
getCacheAndIndex(index: number): { cache: ItemCache<TItem>; scaledIndex: number };
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
declare function DataProviderMixin<TItem, T extends new (...args: any[]) => {}>(
|
|
27
|
+
base: T
|
|
28
|
+
): T & DataProviderMixinConstructor<TItem>;
|
|
29
|
+
|
|
30
|
+
interface DataProviderMixinConstructor<TItem> {
|
|
31
|
+
new (...args: any[]): DataProviderMixin<TItem>;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface DataProviderMixin<TItem> {
|
|
35
|
+
/**
|
|
36
|
+
* Number of items fetched at a time from the dataprovider.
|
|
37
|
+
* @attr {number} page-size
|
|
38
|
+
*/
|
|
39
|
+
pageSize: number;
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The number of root-level items in the grid.
|
|
43
|
+
* @attr {number} size
|
|
44
|
+
*/
|
|
45
|
+
size: number;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Function that provides items lazily. Receives arguments `params`, `callback`
|
|
49
|
+
*
|
|
50
|
+
* `params.page` Requested page index
|
|
51
|
+
*
|
|
52
|
+
* `params.pageSize` Current page size
|
|
53
|
+
*
|
|
54
|
+
* `params.filters` Currently applied filters
|
|
55
|
+
*
|
|
56
|
+
* `params.sortOrders` Currently applied sorting orders
|
|
57
|
+
*
|
|
58
|
+
* `params.parentItem` When tree is used, and sublevel items
|
|
59
|
+
* are requested, reference to parent item of the requested sublevel.
|
|
60
|
+
* Otherwise `undefined`.
|
|
61
|
+
*
|
|
62
|
+
* `callback(items, size)` Callback function with arguments:
|
|
63
|
+
* - `items` Current page of items
|
|
64
|
+
* - `size` Total number of items. When tree sublevel items
|
|
65
|
+
* are requested, total number of items in the requested sublevel.
|
|
66
|
+
* Optional when tree is not used, required for tree.
|
|
67
|
+
*/
|
|
68
|
+
dataProvider: GridDataProvider<TItem> | null | undefined;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* `true` while data is being requested from the data provider.
|
|
72
|
+
*/
|
|
73
|
+
readonly loading: boolean | null | undefined;
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Path to an item sub-property that identifies the item.
|
|
77
|
+
* @attr {string} item-id-path
|
|
78
|
+
*/
|
|
79
|
+
itemIdPath: string | null | undefined;
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* An array that contains the expanded items.
|
|
83
|
+
*/
|
|
84
|
+
expandedItems: TItem[];
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Returns a value that identifies the item. Uses `itemIdPath` if available.
|
|
88
|
+
* Can be customized by overriding.
|
|
89
|
+
*/
|
|
90
|
+
getItemId(item: TItem): TItem | unknown;
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Expands the given item tree.
|
|
94
|
+
*/
|
|
95
|
+
expandItem(item: TItem): void;
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Collapses the given item tree.
|
|
99
|
+
*/
|
|
100
|
+
collapseItem(item: TItem): void;
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Clears the cached pages and reloads data from dataprovider when needed.
|
|
104
|
+
*/
|
|
105
|
+
clearCache(): void;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
export { DataProviderMixin, DataProviderMixinConstructor, ItemCache };
|
|
@@ -0,0 +1,520 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright (c) 2021 Vaadin Ltd.
|
|
4
|
+
* This program is available under Apache License Version 2.0, available at https://vaadin.com/license/
|
|
5
|
+
*/
|
|
6
|
+
import { Debouncer } from '@vaadin/component-base/src/debounce.js';
|
|
7
|
+
import { timeOut } from '@vaadin/component-base/src/async.js';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* @private
|
|
11
|
+
*/
|
|
12
|
+
export const ItemCache = class ItemCache {
|
|
13
|
+
/**
|
|
14
|
+
* @param {!HTMLElement} grid
|
|
15
|
+
* @param {!ItemCache | undefined} parentCache
|
|
16
|
+
* @param {!GridItem | undefined} parentItem
|
|
17
|
+
*/
|
|
18
|
+
constructor(grid, parentCache, parentItem) {
|
|
19
|
+
/** @type {!HTMLElement} */
|
|
20
|
+
this.grid = grid;
|
|
21
|
+
/** @type {!ItemCache | undefined} */
|
|
22
|
+
this.parentCache = parentCache;
|
|
23
|
+
/** @type {!GridItem | undefined} */
|
|
24
|
+
this.parentItem = parentItem;
|
|
25
|
+
/** @type {object} */
|
|
26
|
+
this.itemCaches = {};
|
|
27
|
+
/** @type {object} */
|
|
28
|
+
this.items = {};
|
|
29
|
+
/** @type {number} */
|
|
30
|
+
this.effectiveSize = 0;
|
|
31
|
+
/** @type {number} */
|
|
32
|
+
this.size = 0;
|
|
33
|
+
/** @type {object} */
|
|
34
|
+
this.pendingRequests = {};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* @return {boolean}
|
|
39
|
+
*/
|
|
40
|
+
isLoading() {
|
|
41
|
+
return Boolean(
|
|
42
|
+
Object.keys(this.pendingRequests).length ||
|
|
43
|
+
Object.keys(this.itemCaches).filter((index) => {
|
|
44
|
+
return this.itemCaches[index].isLoading();
|
|
45
|
+
})[0]
|
|
46
|
+
);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* @param {number} index
|
|
51
|
+
* @return {!GridItem | undefined}
|
|
52
|
+
*/
|
|
53
|
+
getItemForIndex(index) {
|
|
54
|
+
const { cache, scaledIndex } = this.getCacheAndIndex(index);
|
|
55
|
+
return cache.items[scaledIndex];
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
updateSize() {
|
|
59
|
+
this.effectiveSize =
|
|
60
|
+
!this.parentItem || this.grid._isExpanded(this.parentItem)
|
|
61
|
+
? this.size +
|
|
62
|
+
Object.keys(this.itemCaches).reduce((prev, curr) => {
|
|
63
|
+
const subCache = this.itemCaches[curr];
|
|
64
|
+
subCache.updateSize();
|
|
65
|
+
return prev + subCache.effectiveSize;
|
|
66
|
+
}, 0)
|
|
67
|
+
: 0;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* @param {number} scaledIndex
|
|
72
|
+
*/
|
|
73
|
+
ensureSubCacheForScaledIndex(scaledIndex) {
|
|
74
|
+
if (!this.itemCaches[scaledIndex]) {
|
|
75
|
+
const subCache = new ItemCache(this.grid, this, this.items[scaledIndex]);
|
|
76
|
+
this.itemCaches[scaledIndex] = subCache;
|
|
77
|
+
this.grid._loadPage(0, subCache);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* @param {number} index
|
|
83
|
+
* @return {{cache: !ItemCache, scaledIndex: number}}
|
|
84
|
+
*/
|
|
85
|
+
getCacheAndIndex(index) {
|
|
86
|
+
let thisLevelIndex = index;
|
|
87
|
+
const keys = Object.keys(this.itemCaches);
|
|
88
|
+
for (let i = 0; i < keys.length; i++) {
|
|
89
|
+
const expandedIndex = Number(keys[i]);
|
|
90
|
+
const subCache = this.itemCaches[expandedIndex];
|
|
91
|
+
if (thisLevelIndex <= expandedIndex) {
|
|
92
|
+
return { cache: this, scaledIndex: thisLevelIndex };
|
|
93
|
+
} else if (thisLevelIndex <= expandedIndex + subCache.effectiveSize) {
|
|
94
|
+
return subCache.getCacheAndIndex(thisLevelIndex - expandedIndex - 1);
|
|
95
|
+
}
|
|
96
|
+
thisLevelIndex -= subCache.effectiveSize;
|
|
97
|
+
}
|
|
98
|
+
return { cache: this, scaledIndex: thisLevelIndex };
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* @polymerMixin
|
|
104
|
+
*/
|
|
105
|
+
export const DataProviderMixin = (superClass) =>
|
|
106
|
+
class DataProviderMixin extends superClass {
|
|
107
|
+
static get properties() {
|
|
108
|
+
return {
|
|
109
|
+
/**
|
|
110
|
+
* The number of root-level items in the grid.
|
|
111
|
+
* @attr {number} size
|
|
112
|
+
* @type {number}
|
|
113
|
+
*/
|
|
114
|
+
size: {
|
|
115
|
+
type: Number,
|
|
116
|
+
notify: true
|
|
117
|
+
},
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Number of items fetched at a time from the dataprovider.
|
|
121
|
+
* @attr {number} page-size
|
|
122
|
+
* @type {number}
|
|
123
|
+
*/
|
|
124
|
+
pageSize: {
|
|
125
|
+
type: Number,
|
|
126
|
+
value: 50,
|
|
127
|
+
observer: '_pageSizeChanged'
|
|
128
|
+
},
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* Function that provides items lazily. Receives arguments `params`, `callback`
|
|
132
|
+
*
|
|
133
|
+
* `params.page` Requested page index
|
|
134
|
+
*
|
|
135
|
+
* `params.pageSize` Current page size
|
|
136
|
+
*
|
|
137
|
+
* `params.filters` Currently applied filters
|
|
138
|
+
*
|
|
139
|
+
* `params.sortOrders` Currently applied sorting orders
|
|
140
|
+
*
|
|
141
|
+
* `params.parentItem` When tree is used, and sublevel items
|
|
142
|
+
* are requested, reference to parent item of the requested sublevel.
|
|
143
|
+
* Otherwise `undefined`.
|
|
144
|
+
*
|
|
145
|
+
* `callback(items, size)` Callback function with arguments:
|
|
146
|
+
* - `items` Current page of items
|
|
147
|
+
* - `size` Total number of items. When tree sublevel items
|
|
148
|
+
* are requested, total number of items in the requested sublevel.
|
|
149
|
+
* Optional when tree is not used, required for tree.
|
|
150
|
+
*
|
|
151
|
+
* @type {GridDataProvider | null | undefined}
|
|
152
|
+
*/
|
|
153
|
+
dataProvider: {
|
|
154
|
+
type: Object,
|
|
155
|
+
notify: true,
|
|
156
|
+
observer: '_dataProviderChanged'
|
|
157
|
+
},
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* `true` while data is being requested from the data provider.
|
|
161
|
+
*/
|
|
162
|
+
loading: {
|
|
163
|
+
type: Boolean,
|
|
164
|
+
notify: true,
|
|
165
|
+
readOnly: true,
|
|
166
|
+
reflectToAttribute: true
|
|
167
|
+
},
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* @type {!ItemCache}
|
|
171
|
+
* @protected
|
|
172
|
+
*/
|
|
173
|
+
_cache: {
|
|
174
|
+
type: Object,
|
|
175
|
+
value: function () {
|
|
176
|
+
const cache = new ItemCache(this);
|
|
177
|
+
return cache;
|
|
178
|
+
}
|
|
179
|
+
},
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* @protected
|
|
183
|
+
*/
|
|
184
|
+
_hasData: {
|
|
185
|
+
type: Boolean,
|
|
186
|
+
value: false
|
|
187
|
+
},
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* Path to an item sub-property that identifies the item.
|
|
191
|
+
* @attr {string} item-id-path
|
|
192
|
+
*/
|
|
193
|
+
itemIdPath: {
|
|
194
|
+
type: String,
|
|
195
|
+
value: null
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
/**
|
|
199
|
+
* An array that contains the expanded items.
|
|
200
|
+
* @type {!Array<!GridItem>}
|
|
201
|
+
*/
|
|
202
|
+
expandedItems: {
|
|
203
|
+
type: Object,
|
|
204
|
+
notify: true,
|
|
205
|
+
value: () => []
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* @private
|
|
210
|
+
*/
|
|
211
|
+
__expandedKeys: {
|
|
212
|
+
type: Object,
|
|
213
|
+
value: () => new Set()
|
|
214
|
+
}
|
|
215
|
+
};
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
static get observers() {
|
|
219
|
+
return ['_sizeChanged(size)', '_itemIdPathChanged(itemIdPath)', '_expandedItemsChanged(expandedItems.*)'];
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
/** @private */
|
|
223
|
+
_sizeChanged(size) {
|
|
224
|
+
const delta = size - this._cache.size;
|
|
225
|
+
this._cache.size += delta;
|
|
226
|
+
this._cache.effectiveSize += delta;
|
|
227
|
+
this._effectiveSize = this._cache.effectiveSize;
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
/**
|
|
231
|
+
* @param {number} index
|
|
232
|
+
* @param {HTMLElement} el
|
|
233
|
+
* @protected
|
|
234
|
+
*/
|
|
235
|
+
_getItem(index, el) {
|
|
236
|
+
if (index >= this._effectiveSize) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
el.index = index;
|
|
241
|
+
const { cache, scaledIndex } = this._cache.getCacheAndIndex(index);
|
|
242
|
+
const item = cache.items[scaledIndex];
|
|
243
|
+
if (item) {
|
|
244
|
+
el.toggleAttribute('loading', false);
|
|
245
|
+
this._updateItem(el, item);
|
|
246
|
+
if (this._isExpanded(item)) {
|
|
247
|
+
cache.ensureSubCacheForScaledIndex(scaledIndex);
|
|
248
|
+
}
|
|
249
|
+
} else {
|
|
250
|
+
el.toggleAttribute('loading', true);
|
|
251
|
+
this._loadPage(this._getPageForIndex(scaledIndex), cache);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
/**
|
|
256
|
+
* Returns a value that identifies the item. Uses `itemIdPath` if available.
|
|
257
|
+
* Can be customized by overriding.
|
|
258
|
+
* @param {!GridItem} item
|
|
259
|
+
* @return {!GridItem | !unknown}
|
|
260
|
+
*/
|
|
261
|
+
getItemId(item) {
|
|
262
|
+
return this.itemIdPath ? this.get(this.itemIdPath, item) : item;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
/**
|
|
266
|
+
* @param {!GridItem} item
|
|
267
|
+
* @return {boolean}
|
|
268
|
+
* @protected
|
|
269
|
+
*/
|
|
270
|
+
_isExpanded(item) {
|
|
271
|
+
return this.__expandedKeys.has(this.getItemId(item));
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/** @private */
|
|
275
|
+
_expandedItemsChanged() {
|
|
276
|
+
this.__cacheExpandedKeys();
|
|
277
|
+
this._cache.updateSize();
|
|
278
|
+
this._effectiveSize = this._cache.effectiveSize;
|
|
279
|
+
this.__updateVisibleRows();
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** @private */
|
|
283
|
+
_itemIdPathChanged() {
|
|
284
|
+
this.__cacheExpandedKeys();
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/** @private */
|
|
288
|
+
__cacheExpandedKeys() {
|
|
289
|
+
if (this.expandedItems) {
|
|
290
|
+
this.__expandedKeys = new Set();
|
|
291
|
+
this.expandedItems.forEach((item) => {
|
|
292
|
+
this.__expandedKeys.add(this.getItemId(item));
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Expands the given item tree.
|
|
299
|
+
* @param {!GridItem} item
|
|
300
|
+
*/
|
|
301
|
+
expandItem(item) {
|
|
302
|
+
if (!this._isExpanded(item)) {
|
|
303
|
+
this.expandedItems = [...this.expandedItems, item];
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Collapses the given item tree.
|
|
309
|
+
* @param {!GridItem} item
|
|
310
|
+
*/
|
|
311
|
+
collapseItem(item) {
|
|
312
|
+
if (this._isExpanded(item)) {
|
|
313
|
+
this.expandedItems = this.expandedItems.filter((i) => !this._itemsEqual(i, item));
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
/**
|
|
318
|
+
* @param {number} index
|
|
319
|
+
* @return {number}
|
|
320
|
+
* @protected
|
|
321
|
+
*/
|
|
322
|
+
_getIndexLevel(index) {
|
|
323
|
+
let { cache } = this._cache.getCacheAndIndex(index);
|
|
324
|
+
let level = 0;
|
|
325
|
+
while (cache.parentCache) {
|
|
326
|
+
cache = cache.parentCache;
|
|
327
|
+
level++;
|
|
328
|
+
}
|
|
329
|
+
return level;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
/**
|
|
333
|
+
* @param {number} page
|
|
334
|
+
* @param {ItemCache} cache
|
|
335
|
+
* @protected
|
|
336
|
+
*/
|
|
337
|
+
_loadPage(page, cache) {
|
|
338
|
+
// make sure same page isn't requested multiple times.
|
|
339
|
+
if (!cache.pendingRequests[page] && this.dataProvider) {
|
|
340
|
+
this._setLoading(true);
|
|
341
|
+
cache.pendingRequests[page] = true;
|
|
342
|
+
const params = {
|
|
343
|
+
page,
|
|
344
|
+
pageSize: this.pageSize,
|
|
345
|
+
sortOrders: this._mapSorters(),
|
|
346
|
+
filters: this._mapFilters(),
|
|
347
|
+
parentItem: cache.parentItem
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
this.dataProvider(params, (items, size) => {
|
|
351
|
+
if (size !== undefined) {
|
|
352
|
+
cache.size = size;
|
|
353
|
+
} else {
|
|
354
|
+
if (params.parentItem) {
|
|
355
|
+
cache.size = items.length;
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const currentItems = Array.from(this.$.items.children).map((row) => row._item);
|
|
360
|
+
|
|
361
|
+
// Populate the cache with new items
|
|
362
|
+
items.forEach((item, itemsIndex) => {
|
|
363
|
+
const itemIndex = page * this.pageSize + itemsIndex;
|
|
364
|
+
cache.items[itemIndex] = item;
|
|
365
|
+
if (this._isExpanded(item) && currentItems.indexOf(item) > -1) {
|
|
366
|
+
// Force synchronous data request for expanded item sub-cache
|
|
367
|
+
cache.ensureSubCacheForScaledIndex(itemIndex);
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
|
|
371
|
+
this._hasData = true;
|
|
372
|
+
|
|
373
|
+
delete cache.pendingRequests[page];
|
|
374
|
+
|
|
375
|
+
this._debouncerApplyCachedData = Debouncer.debounce(this._debouncerApplyCachedData, timeOut.after(0), () => {
|
|
376
|
+
this._setLoading(false);
|
|
377
|
+
this._cache.updateSize();
|
|
378
|
+
this._effectiveSize = this._cache.effectiveSize;
|
|
379
|
+
|
|
380
|
+
Array.from(this.$.items.children)
|
|
381
|
+
.filter((row) => !row.hidden)
|
|
382
|
+
.forEach((row) => {
|
|
383
|
+
const cachedItem = this._cache.getItemForIndex(row.index);
|
|
384
|
+
if (cachedItem) {
|
|
385
|
+
this._getItem(row.index, row);
|
|
386
|
+
}
|
|
387
|
+
});
|
|
388
|
+
|
|
389
|
+
this.__scrollToPendingIndex();
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
if (!this._cache.isLoading()) {
|
|
393
|
+
this._debouncerApplyCachedData.flush();
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
this.__itemsReceived();
|
|
397
|
+
});
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* @param {number} index
|
|
403
|
+
* @return {number}
|
|
404
|
+
* @private
|
|
405
|
+
*/
|
|
406
|
+
_getPageForIndex(index) {
|
|
407
|
+
return Math.floor(index / this.pageSize);
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
/**
|
|
411
|
+
* Clears the cached pages and reloads data from dataprovider when needed.
|
|
412
|
+
*/
|
|
413
|
+
clearCache() {
|
|
414
|
+
this._cache = new ItemCache(this);
|
|
415
|
+
this._cache.size = this.size || 0;
|
|
416
|
+
this._cache.updateSize();
|
|
417
|
+
this._hasData = false;
|
|
418
|
+
this.__updateVisibleRows();
|
|
419
|
+
|
|
420
|
+
if (!this._effectiveSize) {
|
|
421
|
+
this._loadPage(0, this._cache);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
/** @private */
|
|
426
|
+
_pageSizeChanged(pageSize, oldPageSize) {
|
|
427
|
+
if (oldPageSize !== undefined && pageSize !== oldPageSize) {
|
|
428
|
+
this.clearCache();
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
/** @protected */
|
|
433
|
+
_checkSize() {
|
|
434
|
+
if (this.size === undefined && this._effectiveSize === 0) {
|
|
435
|
+
console.warn(
|
|
436
|
+
'The <vaadin-grid> needs the total number of items' +
|
|
437
|
+
' in order to display rows. Set the total number of items' +
|
|
438
|
+
' to the `size` property, or provide the total number of items' +
|
|
439
|
+
' in the second argument of the `dataProvider`’s `callback` call.'
|
|
440
|
+
);
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
/** @private */
|
|
445
|
+
_dataProviderChanged(dataProvider, oldDataProvider) {
|
|
446
|
+
if (oldDataProvider !== undefined) {
|
|
447
|
+
this.clearCache();
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
this._ensureFirstPageLoaded();
|
|
451
|
+
|
|
452
|
+
this._debouncerCheckSize = Debouncer.debounce(
|
|
453
|
+
this._debouncerCheckSize,
|
|
454
|
+
timeOut.after(2000),
|
|
455
|
+
this._checkSize.bind(this)
|
|
456
|
+
);
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
/** @protected */
|
|
460
|
+
_ensureFirstPageLoaded() {
|
|
461
|
+
if (!this._hasData) {
|
|
462
|
+
// load data before adding rows to make sure they have content when
|
|
463
|
+
// rendered for the first time.
|
|
464
|
+
this._loadPage(0, this._cache);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* @param {!GridItem} item1
|
|
470
|
+
* @param {!GridItem} item2
|
|
471
|
+
* @return {boolean}
|
|
472
|
+
* @protected
|
|
473
|
+
*/
|
|
474
|
+
_itemsEqual(item1, item2) {
|
|
475
|
+
return this.getItemId(item1) === this.getItemId(item2);
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* @param {!GridItem} item
|
|
480
|
+
* @param {!Array<!GridItem>} array
|
|
481
|
+
* @return {number}
|
|
482
|
+
* @protected
|
|
483
|
+
*/
|
|
484
|
+
_getItemIndexInArray(item, array) {
|
|
485
|
+
let result = -1;
|
|
486
|
+
array.forEach((i, idx) => {
|
|
487
|
+
if (this._itemsEqual(i, item)) {
|
|
488
|
+
result = idx;
|
|
489
|
+
}
|
|
490
|
+
});
|
|
491
|
+
return result;
|
|
492
|
+
}
|
|
493
|
+
|
|
494
|
+
scrollToIndex(index) {
|
|
495
|
+
super.scrollToIndex(index);
|
|
496
|
+
if (!isNaN(index) && (this._cache.isLoading() || !this.clientHeight)) {
|
|
497
|
+
this.__pendingScrollToIndex = index;
|
|
498
|
+
}
|
|
499
|
+
}
|
|
500
|
+
|
|
501
|
+
__scrollToPendingIndex() {
|
|
502
|
+
if (this.__pendingScrollToIndex && this.$.items.children.length) {
|
|
503
|
+
const index = this.__pendingScrollToIndex;
|
|
504
|
+
delete this.__pendingScrollToIndex;
|
|
505
|
+
this.scrollToIndex(index);
|
|
506
|
+
}
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
/**
|
|
510
|
+
* Fired when the `expandedItems` property changes.
|
|
511
|
+
*
|
|
512
|
+
* @event expanded-items-changed
|
|
513
|
+
*/
|
|
514
|
+
|
|
515
|
+
/**
|
|
516
|
+
* Fired when the `loading` property changes.
|
|
517
|
+
*
|
|
518
|
+
* @event loading-changed
|
|
519
|
+
*/
|
|
520
|
+
};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
import { GridDragAndDropFilter, GridDropMode } from './interfaces';
|
|
2
|
+
|
|
3
|
+
declare function DragAndDropMixin<TItem, T extends new (...args: any[]) => {}>(
|
|
4
|
+
base: T
|
|
5
|
+
): T & DragAndDropMixinConstructor<TItem>;
|
|
6
|
+
|
|
7
|
+
interface DragAndDropMixinConstructor<TItem> {
|
|
8
|
+
new (...args: any[]): DragAndDropMixin<TItem>;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
interface DragAndDropMixin<TItem> {
|
|
12
|
+
/**
|
|
13
|
+
* Defines the locations within the Grid row where an element can be dropped.
|
|
14
|
+
*
|
|
15
|
+
* Possible values are:
|
|
16
|
+
* - `between`: The drop event can happen between Grid rows.
|
|
17
|
+
* - `on-top`: The drop event can happen on top of Grid rows.
|
|
18
|
+
* - `on-top-or-between`: The drop event can happen either on top of or between Grid rows.
|
|
19
|
+
* - `on-grid`: The drop event will not happen on any specific row, it will show the drop target outline around the whole grid.
|
|
20
|
+
* @attr {between|on-top|on-top-or-between|on-grid} drop-mode
|
|
21
|
+
*/
|
|
22
|
+
dropMode: GridDropMode | null | undefined;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Marks the grid's rows to be available for dragging.
|
|
26
|
+
* @attr {boolean} rows-draggable
|
|
27
|
+
*/
|
|
28
|
+
rowsDraggable: boolean | null | undefined;
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* A function that filters dragging of specific grid rows. The return value should be false
|
|
32
|
+
* if dragging of the row should be disabled.
|
|
33
|
+
*
|
|
34
|
+
* Receives one argument:
|
|
35
|
+
* - `model` The object with the properties related with
|
|
36
|
+
* the rendered item, contains:
|
|
37
|
+
* - `model.index` The index of the item.
|
|
38
|
+
* - `model.item` The item.
|
|
39
|
+
* - `model.expanded` Sublevel toggle state.
|
|
40
|
+
* - `model.level` Level of the tree represented with a horizontal offset of the toggle button.
|
|
41
|
+
* - `model.selected` Selected state.
|
|
42
|
+
*/
|
|
43
|
+
dragFilter: GridDragAndDropFilter<TItem> | null | undefined;
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* A function that filters dropping on specific grid rows. The return value should be false
|
|
47
|
+
* if dropping on the row should be disabled.
|
|
48
|
+
*
|
|
49
|
+
* Receives one argument:
|
|
50
|
+
* - `model` The object with the properties related with
|
|
51
|
+
* the rendered item, contains:
|
|
52
|
+
* - `model.index` The index of the item.
|
|
53
|
+
* - `model.item` The item.
|
|
54
|
+
* - `model.expanded` Sublevel toggle state.
|
|
55
|
+
* - `model.level` Level of the tree represented with a horizontal offset of the toggle button.
|
|
56
|
+
* - `model.selected` Selected state.
|
|
57
|
+
*/
|
|
58
|
+
dropFilter: GridDragAndDropFilter<TItem> | null | undefined;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Runs the `dragFilter` and `dropFilter` hooks for the visible cells.
|
|
62
|
+
* If the filter depends on varying conditions, you may need to
|
|
63
|
+
* call this function manually in order to update the draggability when
|
|
64
|
+
* the conditions change.
|
|
65
|
+
*/
|
|
66
|
+
filterDragAndDrop(): void;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
export { DragAndDropMixin, DragAndDropMixinConstructor };
|