neo.mjs 8.14.2 → 8.15.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/apps/ServiceWorker.mjs +2 -2
- package/apps/portal/index.html +1 -1
- package/apps/portal/view/home/FooterContainer.mjs +1 -1
- package/apps/shareddialog/view/MainContainerController.mjs +7 -7
- package/examples/ServiceWorker.mjs +2 -2
- package/package.json +1 -1
- package/src/DefaultConfig.mjs +2 -2
- package/src/collection/Base.mjs +20 -0
- package/src/container/Base.mjs +5 -3
- package/src/draggable/DragZone.mjs +14 -3
- package/src/draggable/grid/header/toolbar/SortZone.mjs +29 -25
- package/src/draggable/toolbar/DragZone.mjs +21 -7
- package/src/draggable/toolbar/SortZone.mjs +50 -25
- package/src/grid/Container.mjs +5 -2
- package/src/grid/View.mjs +56 -36
- package/src/grid/header/Toolbar.mjs +41 -6
- package/src/main/DomAccess.mjs +13 -16
- package/src/main/addon/DragDrop.mjs +23 -11
- package/src/util/Rectangle.mjs +15 -21
package/apps/ServiceWorker.mjs
CHANGED
package/apps/portal/index.html
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import Component from '../../../src/component/Base.mjs';
|
2
1
|
import ComponentController from '../../../src/controller/Component.mjs';
|
3
2
|
import ComponentManager from '../../../src/manager/Component.mjs';
|
4
3
|
import DemoDialog from './DemoDialog.mjs';
|
@@ -127,14 +126,15 @@ class MainContainerController extends ComponentController {
|
|
127
126
|
* @param {Object} proxyRect
|
128
127
|
*/
|
129
128
|
dropDialogBetweenWindows(proxyRect) {
|
130
|
-
let me
|
131
|
-
dialog
|
132
|
-
intersection
|
133
|
-
|
134
|
-
|
129
|
+
let me = this,
|
130
|
+
dialog = me.dialog,
|
131
|
+
intersection = Rectangle.getIntersection(me.dragStartWindowRect, proxyRect),
|
132
|
+
intersectionSize = intersection?.height * intersection?.width,
|
133
|
+
side = me.dockedWindowSide,
|
134
|
+
size = proxyRect.height * proxyRect.width,
|
135
135
|
wrapperStyle;
|
136
136
|
|
137
|
-
if (
|
137
|
+
if (intersectionSize > size / 2) { // drop the dialog fully into the dragStart window
|
138
138
|
me.destroyDockedWindowProxy();
|
139
139
|
|
140
140
|
wrapperStyle = dialog.wrapperStyle;
|
package/package.json
CHANGED
package/src/DefaultConfig.mjs
CHANGED
@@ -262,12 +262,12 @@ const DefaultConfig = {
|
|
262
262
|
useVdomWorker: true,
|
263
263
|
/**
|
264
264
|
* buildScripts/injectPackageVersion.mjs will update this value
|
265
|
-
* @default '8.
|
265
|
+
* @default '8.15.0'
|
266
266
|
* @memberOf! module:Neo
|
267
267
|
* @name config.version
|
268
268
|
* @type String
|
269
269
|
*/
|
270
|
-
version: '8.
|
270
|
+
version: '8.15.0'
|
271
271
|
};
|
272
272
|
|
273
273
|
Object.assign(DefaultConfig, {
|
package/src/collection/Base.mjs
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
import Base from '../core/Base.mjs';
|
2
2
|
import Filter from './Filter.mjs';
|
3
3
|
import Logger from '../util/Logger.mjs';
|
4
|
+
import NeoArray from '../util/Array.mjs';
|
4
5
|
import Observable from '../core/Observable.mjs';
|
5
6
|
import Sorter from './Sorter.mjs';
|
6
7
|
|
@@ -1015,6 +1016,25 @@ class Collection extends Base {
|
|
1015
1016
|
return this._items[this.getCount() -1]
|
1016
1017
|
}
|
1017
1018
|
|
1019
|
+
/**
|
1020
|
+
* Moves an item from fromIndex to toIndex
|
1021
|
+
* @param {Number} fromIndex
|
1022
|
+
* @param {Number} toIndex
|
1023
|
+
*/
|
1024
|
+
move(fromIndex, toIndex) {
|
1025
|
+
if (fromIndex === toIndex) {
|
1026
|
+
return
|
1027
|
+
}
|
1028
|
+
|
1029
|
+
let {items} = this;
|
1030
|
+
|
1031
|
+
if (fromIndex >= items.length) {
|
1032
|
+
fromIndex = items.length - 1
|
1033
|
+
}
|
1034
|
+
|
1035
|
+
items.splice(toIndex, 0, items.splice(fromIndex, 1)[0])
|
1036
|
+
}
|
1037
|
+
|
1018
1038
|
/**
|
1019
1039
|
* @param {Object} opts
|
1020
1040
|
* @protected
|
package/src/container/Base.mjs
CHANGED
@@ -272,11 +272,11 @@ class Container extends Component {
|
|
272
272
|
|
273
273
|
item.reference = ref;
|
274
274
|
result.push(item);
|
275
|
-
hasWeight ||= ('weight' in item)
|
275
|
+
hasWeight ||= ('weight' in item)
|
276
276
|
}
|
277
277
|
|
278
278
|
if (hasWeight) {
|
279
|
-
result.sort(byWeight)
|
279
|
+
result.sort(byWeight)
|
280
280
|
}
|
281
281
|
|
282
282
|
value = result
|
@@ -413,7 +413,9 @@ class Container extends Component {
|
|
413
413
|
|
414
414
|
// We need to add items into the vdom
|
415
415
|
me.updateDepth = -1;
|
416
|
-
me.update()
|
416
|
+
me.update();
|
417
|
+
|
418
|
+
me.fire('itemsCreated', {id: me.id, items})
|
417
419
|
}
|
418
420
|
|
419
421
|
/**
|
@@ -50,9 +50,18 @@ class DragZone extends Base {
|
|
50
50
|
*/
|
51
51
|
bodyCursorStyle: null,
|
52
52
|
/**
|
53
|
-
*
|
53
|
+
* Limit the zone in which you can drag an element.
|
54
|
+
* You can pass a node id, or an array of 2 node ids, in case you need an intersection.
|
55
|
+
* Example for 2 ids: grid.header.Toolbar => boundaryContainerId: [id, me.parent.id]
|
56
|
+
* @member {String|String[]|null} boundaryContainerId=null
|
54
57
|
*/
|
55
58
|
boundaryContainerId: null,
|
59
|
+
/**
|
60
|
+
* Stores the DOMRect matching this.boundaryContainerId
|
61
|
+
* @member {DOMRect|null} data=null
|
62
|
+
* @protected
|
63
|
+
*/
|
64
|
+
boundaryContainerRect: null,
|
56
65
|
/**
|
57
66
|
* Store data which you want to pass to drop related events here
|
58
67
|
* @member {Object|null} data=null
|
@@ -315,16 +324,18 @@ class DragZone extends Base {
|
|
315
324
|
{appName, owner, windowId} = me,
|
316
325
|
{cls} = owner,
|
317
326
|
rect = me.getDragElementRect(data),
|
318
|
-
offsetX, offsetY;
|
327
|
+
mainData, offsetX, offsetY;
|
319
328
|
|
320
329
|
me.setData();
|
321
330
|
|
322
|
-
Neo.main.addon.DragDrop.setConfigs({
|
331
|
+
mainData = await Neo.main.addon.DragDrop.setConfigs({
|
323
332
|
appName,
|
324
333
|
windowId,
|
325
334
|
...me.getMainThreadConfigs()
|
326
335
|
});
|
327
336
|
|
337
|
+
me.boundaryContainerRect = mainData.boundaryContainerRect
|
338
|
+
|
328
339
|
NeoArray.add(cls, 'neo-is-dragging');
|
329
340
|
owner.cls = cls;
|
330
341
|
|
@@ -57,7 +57,7 @@ class SortZone extends BaseSortZone {
|
|
57
57
|
{view} = grid,
|
58
58
|
gridRows = view.getVdomRoot().cn,
|
59
59
|
columnIndex = me.dragElement['aria-colindex'] - 1,
|
60
|
-
{dataField} = view.columnPositions
|
60
|
+
{dataField} = view.columnPositions.getAt(columnIndex),
|
61
61
|
cells = view.getColumnCells(dataField),
|
62
62
|
rows = [],
|
63
63
|
config = await super.createDragProxy(data, false),
|
@@ -95,10 +95,9 @@ class SortZone extends BaseSortZone {
|
|
95
95
|
config.listeners = {
|
96
96
|
mounted() {
|
97
97
|
Neo.main.DomAccess.scrollTo({
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
windowId : this.windowId
|
98
|
+
id : viewWrapperId,
|
99
|
+
value : view.scrollPosition.y,
|
100
|
+
windowId: this.windowId
|
102
101
|
})
|
103
102
|
}
|
104
103
|
};
|
@@ -150,14 +149,17 @@ class SortZone extends BaseSortZone {
|
|
150
149
|
await super.onDragStart(data);
|
151
150
|
|
152
151
|
if (this.moveColumnContent) {
|
153
|
-
let me
|
154
|
-
{view}
|
155
|
-
columnIndex
|
156
|
-
|
157
|
-
|
152
|
+
let me = this,
|
153
|
+
{view} = me.owner.parent,
|
154
|
+
columnIndex = me.dragElement['aria-colindex'] - 1,
|
155
|
+
columnPosition = view.columnPositions.getAt(columnIndex),
|
156
|
+
{dataField} = columnPosition,
|
157
|
+
cells = view.getColumnCells(dataField);
|
158
|
+
|
159
|
+
columnPosition.hidden = true;
|
158
160
|
|
159
161
|
cells.forEach(cell => {
|
160
|
-
cell.style.
|
162
|
+
cell.style.visibility = 'hidden'
|
161
163
|
});
|
162
164
|
|
163
165
|
view.update()
|
@@ -172,33 +174,35 @@ class SortZone extends BaseSortZone {
|
|
172
174
|
super.switchItems(index1, index2);
|
173
175
|
|
174
176
|
if (this.moveColumnContent) {
|
175
|
-
let me
|
176
|
-
{itemRects}
|
177
|
-
{view}
|
178
|
-
columnPositions = view
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
177
|
+
let me = this,
|
178
|
+
{itemRects} = me,
|
179
|
+
{view} = me.owner.parent,
|
180
|
+
{columnPositions} = view,
|
181
|
+
column1Position = columnPositions.getAt(index1),
|
182
|
+
column2Position = columnPositions.getAt(index2),
|
183
|
+
column1Cells = view.getColumnCells(column1Position.dataField),
|
184
|
+
column2Cells = view.getColumnCells(column2Position.dataField);
|
185
|
+
|
186
|
+
Object.assign(column1Position, {
|
183
187
|
width: itemRects[index2].width,
|
184
188
|
x : itemRects[index2].x + 1
|
185
189
|
});
|
186
190
|
|
187
|
-
Object.assign(
|
191
|
+
Object.assign(column2Position, {
|
188
192
|
width: itemRects[index1].width,
|
189
193
|
x : itemRects[index1].x + 1
|
190
194
|
});
|
191
195
|
|
192
|
-
|
196
|
+
columnPositions.move(index1, index2);
|
193
197
|
|
194
198
|
column1Cells.forEach(node => {
|
195
|
-
node.style.left =
|
196
|
-
node.style.width =
|
199
|
+
node.style.left = column1Position.x + 'px';
|
200
|
+
node.style.width = column1Position.width + 'px'
|
197
201
|
});
|
198
202
|
|
199
203
|
column2Cells.forEach(node => {
|
200
|
-
node.style.left =
|
201
|
-
node.style.width =
|
204
|
+
node.style.left = column2Position.x + 'px';
|
205
|
+
node.style.width = column2Position.width + 'px'
|
202
206
|
});
|
203
207
|
|
204
208
|
view.update()
|
@@ -36,8 +36,13 @@ class DragZone extends BaseDragZone {
|
|
36
36
|
{'drag:start': me.onDragStart, ...opts}
|
37
37
|
]);
|
38
38
|
|
39
|
-
owner.on(
|
39
|
+
owner.on({
|
40
|
+
insert : me.onItemInsert,
|
41
|
+
itemsCreated: me.onItemsCreated,
|
42
|
+
scope : me
|
43
|
+
});
|
40
44
|
|
45
|
+
// The toolbar items can already be created
|
41
46
|
me.adjustToolbarItemCls(true)
|
42
47
|
}
|
43
48
|
|
@@ -98,16 +103,25 @@ class DragZone extends BaseDragZone {
|
|
98
103
|
}
|
99
104
|
|
100
105
|
/**
|
101
|
-
* @param {Object}
|
102
|
-
* @param {Number}
|
106
|
+
* @param {Object} data
|
107
|
+
* @param {Number} data.index
|
103
108
|
* @param {Neo.component.Base} data.item
|
104
109
|
*/
|
105
110
|
onItemInsert(data) {
|
106
|
-
let {item}
|
107
|
-
|
111
|
+
let {item} = data,
|
112
|
+
wrapperCls = item.wrapperCls || [];
|
113
|
+
|
114
|
+
NeoArray.add(wrapperCls, 'neo-draggable');
|
115
|
+
item.wrapperCls = wrapperCls
|
116
|
+
}
|
108
117
|
|
109
|
-
|
110
|
-
|
118
|
+
/**
|
119
|
+
* @param {Object} data
|
120
|
+
* @param {String} data.id
|
121
|
+
* @param {Neo.component.Base[]} data.items
|
122
|
+
*/
|
123
|
+
onItemsCreated(data) {console.log('onItemsCreated');
|
124
|
+
this.adjustToolbarItemCls(true)
|
111
125
|
}
|
112
126
|
}
|
113
127
|
|
@@ -61,6 +61,14 @@ class SortZone extends DragZone {
|
|
61
61
|
* @protected
|
62
62
|
*/
|
63
63
|
reversedLayoutDirection: false,
|
64
|
+
/**
|
65
|
+
* @member {Number} scrollLeft=0
|
66
|
+
*/
|
67
|
+
scrollLeft: 0,
|
68
|
+
/**
|
69
|
+
* @member {Number} scrollTop=0
|
70
|
+
*/
|
71
|
+
scrollTop: 0,
|
64
72
|
/**
|
65
73
|
* Internal flag: onDragStart() will set the value to horizontal or vertical, depending on the current layout.
|
66
74
|
* @member {String} sortDirection='horizontal'
|
@@ -141,36 +149,53 @@ class SortZone extends DragZone {
|
|
141
149
|
/**
|
142
150
|
* @param {Object} data
|
143
151
|
*/
|
144
|
-
onDragMove(data) {
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
152
|
+
async onDragMove(data) {
|
153
|
+
// the method can trigger before we got the client rects from the main thread
|
154
|
+
if (!this.itemRects || this.isScrolling) {
|
155
|
+
return
|
156
|
+
}
|
157
|
+
|
158
|
+
let me = this,
|
159
|
+
moveFactor = 0.55, // we can not use 0.5, since items would jump back & forth
|
160
|
+
index = me.currentIndex,
|
161
|
+
{itemRects} = me,
|
162
|
+
maxItems = itemRects.length - 1,
|
163
|
+
reversed = me.reversedLayoutDirection,
|
164
|
+
delta, itemWidth;
|
165
|
+
|
166
|
+
if (me.sortDirection === 'horizontal') {
|
167
|
+
delta = data.clientX + me.scrollLeft - me.offsetX - itemRects[index].left;
|
168
|
+
itemWidth = 'width'
|
169
|
+
} else {
|
170
|
+
delta = data.clientY + me.scrollTop - me.offsetY - itemRects[index].top;
|
171
|
+
itemWidth = 'height'
|
172
|
+
}
|
173
|
+
|
174
|
+
if (index > 0 && (!reversed && delta < 0 || reversed && delta > 0)) {
|
175
|
+
if (Math.abs(delta) > itemRects[index - 1][itemWidth] * moveFactor) {
|
176
|
+
me.currentIndex--;
|
161
177
|
|
162
|
-
|
163
|
-
|
164
|
-
me.currentIndex
|
165
|
-
me.
|
178
|
+
if (data.clientX < me.boundaryContainerRect.left) {
|
179
|
+
me.isScrolling = true;
|
180
|
+
await me.owner.scrollToIndex?.(me.currentIndex, itemRects[me.currentIndex]);
|
181
|
+
me.isScrolling = false
|
166
182
|
}
|
183
|
+
|
184
|
+
me.switchItems(index, me.currentIndex)
|
167
185
|
}
|
186
|
+
}
|
168
187
|
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
188
|
+
else if (index < maxItems && (!reversed && delta > 0 || reversed && delta < 0)) {
|
189
|
+
if (Math.abs(delta) > itemRects[index + 1][itemWidth] * moveFactor) {
|
190
|
+
me.currentIndex++;
|
191
|
+
|
192
|
+
if (data.clientX > me.boundaryContainerRect.right) {
|
193
|
+
me.isScrolling = true;
|
194
|
+
await me.owner.scrollToIndex?.(me.currentIndex, itemRects[me.currentIndex]);
|
195
|
+
me.isScrolling = false
|
173
196
|
}
|
197
|
+
|
198
|
+
me.switchItems(index, me.currentIndex)
|
174
199
|
}
|
175
200
|
}
|
176
201
|
}
|
package/src/grid/Container.mjs
CHANGED
@@ -506,8 +506,11 @@ class GridContainer extends BaseContainer {
|
|
506
506
|
/**
|
507
507
|
* @param {Object} data
|
508
508
|
*/
|
509
|
-
onScroll(
|
510
|
-
|
509
|
+
onScroll({scrollLeft}) {
|
510
|
+
let me = this;
|
511
|
+
|
512
|
+
me.headerToolbar.scrollLeft = scrollLeft;
|
513
|
+
me.view.scrollPosition = {x: scrollLeft, y: me.view.scrollPosition.y}
|
511
514
|
}
|
512
515
|
|
513
516
|
/**
|
package/src/grid/View.mjs
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
import ClassSystemUtil from '../util/ClassSystem.mjs';
|
2
|
+
import Collection from '../collection/Base.mjs';
|
2
3
|
import Component from '../component/Base.mjs';
|
3
4
|
import NeoArray from '../util/Array.mjs';
|
4
5
|
import RowModel from '../selection/grid/RowModel.mjs';
|
@@ -63,10 +64,10 @@ class GridView extends Component {
|
|
63
64
|
*/
|
64
65
|
containerWidth_: 0,
|
65
66
|
/**
|
66
|
-
* @member {
|
67
|
+
* @member {Neo.collection.Base|null} columnPositions_=null
|
67
68
|
* @protected
|
68
69
|
*/
|
69
|
-
columnPositions_:
|
70
|
+
columnPositions_: null,
|
70
71
|
/**
|
71
72
|
* @member {Boolean} highlightModifiedCells_=false
|
72
73
|
*/
|
@@ -238,19 +239,7 @@ class GridView extends Component {
|
|
238
239
|
* @protected
|
239
240
|
*/
|
240
241
|
afterSetContainerWidth(value, oldValue) {
|
241
|
-
if (value > 0
|
242
|
-
this.updateVisibleColumns()
|
243
|
-
}
|
244
|
-
}
|
245
|
-
|
246
|
-
/**
|
247
|
-
* Triggered after the columnPositions config got changed
|
248
|
-
* @param {Object[]} value
|
249
|
-
* @param {Object[]} oldValue
|
250
|
-
* @protected
|
251
|
-
*/
|
252
|
-
afterSetColumnPositions(value, oldValue) {
|
253
|
-
if (value.length > 0 && this.containerWidth > 0) {
|
242
|
+
if (value > 0) {
|
254
243
|
this.updateVisibleColumns()
|
255
244
|
}
|
256
245
|
}
|
@@ -299,7 +288,7 @@ class GridView extends Component {
|
|
299
288
|
{bufferRowRange} = me,
|
300
289
|
newStartIndex;
|
301
290
|
|
302
|
-
if (value.x !== oldValue?.x
|
291
|
+
if (value.x !== oldValue?.x) {
|
303
292
|
me.updateVisibleColumns()
|
304
293
|
}
|
305
294
|
|
@@ -461,6 +450,22 @@ class GridView extends Component {
|
|
461
450
|
return cellConfig
|
462
451
|
}
|
463
452
|
|
453
|
+
/**
|
454
|
+
* Triggered when accessing the columnPositions config
|
455
|
+
* @param {Object} value
|
456
|
+
* @protected
|
457
|
+
*/
|
458
|
+
beforeGetColumnPositions(value) {
|
459
|
+
if (!value) {
|
460
|
+
this._columnPositions = value = Neo.create({
|
461
|
+
module : Collection,
|
462
|
+
keyProperty: 'dataField'
|
463
|
+
})
|
464
|
+
}
|
465
|
+
|
466
|
+
return value
|
467
|
+
}
|
468
|
+
|
464
469
|
/**
|
465
470
|
* Triggered before the selectionModel config gets changed.
|
466
471
|
* @param {Neo.selection.Model} value
|
@@ -490,7 +495,7 @@ class GridView extends Component {
|
|
490
495
|
columns = gridContainer.headerToolbar.items,
|
491
496
|
id = me.getRowId(record, rowIndex),
|
492
497
|
trCls = me.getTrClass(record, rowIndex),
|
493
|
-
config, column, endIndex, gridRow, i, startIndex;
|
498
|
+
config, column, columnPosition, endIndex, gridRow, i, startIndex;
|
494
499
|
|
495
500
|
if (rowIndex % 2 !== 0) {
|
496
501
|
trCls.push('neo-even')
|
@@ -529,10 +534,17 @@ class GridView extends Component {
|
|
529
534
|
config.cls = ['neo-locked', ...config.cls || []]
|
530
535
|
}
|
531
536
|
|
537
|
+
columnPosition = me.columnPositions.get(column.dataField);
|
538
|
+
|
532
539
|
config.style = {
|
533
540
|
...config.style,
|
534
|
-
left :
|
535
|
-
width:
|
541
|
+
left : columnPosition.x + 'px',
|
542
|
+
width: columnPosition.width + 'px'
|
543
|
+
}
|
544
|
+
|
545
|
+
// Happens during a column header drag OP, when leaving the painted range
|
546
|
+
if (columnPosition.hidden) {
|
547
|
+
config.style.visibility = 'hidden'
|
536
548
|
}
|
537
549
|
|
538
550
|
gridRow.cn.push(config)
|
@@ -552,11 +564,11 @@ class GridView extends Component {
|
|
552
564
|
endIndex, i;
|
553
565
|
|
554
566
|
if (
|
555
|
-
countRecords
|
556
|
-
me.availableRows
|
557
|
-
me._containerWidth
|
558
|
-
me.columnPositions.
|
559
|
-
me.visibleColumns[1]
|
567
|
+
countRecords < 1 ||
|
568
|
+
me.availableRows < 1 ||
|
569
|
+
me._containerWidth < 1 || // we are not checking me.containerWidth, since we want to ignore the config symbol
|
570
|
+
me.columnPositions.getCount() < 1 ||
|
571
|
+
me.visibleColumns[1] < 1
|
560
572
|
) {
|
561
573
|
return
|
562
574
|
}
|
@@ -652,13 +664,14 @@ class GridView extends Component {
|
|
652
664
|
* @returns {Object[]}
|
653
665
|
*/
|
654
666
|
getColumnCells(dataField) {
|
655
|
-
let me
|
656
|
-
cells
|
657
|
-
|
658
|
-
|
659
|
-
|
660
|
-
|
661
|
-
|
667
|
+
let me = this,
|
668
|
+
cells = [],
|
669
|
+
columnIndex = -1,
|
670
|
+
vdomRoot = me.getVdomRoot(),
|
671
|
+
firstRow = vdomRoot.cn[0],
|
672
|
+
i = 0,
|
673
|
+
len = firstRow.cn.length,
|
674
|
+
cell;
|
662
675
|
|
663
676
|
// Columns might get moved via drag&drop, so let's check for the current match
|
664
677
|
for (; i < len; i++) {
|
@@ -668,9 +681,12 @@ class GridView extends Component {
|
|
668
681
|
}
|
669
682
|
}
|
670
683
|
|
671
|
-
|
672
|
-
|
673
|
-
|
684
|
+
if (columnIndex > -1) {
|
685
|
+
vdomRoot.cn.forEach(row => {
|
686
|
+
cell = row.cn[columnIndex];
|
687
|
+
cell && cells.push(cell)
|
688
|
+
})
|
689
|
+
}
|
674
690
|
|
675
691
|
return cells
|
676
692
|
}
|
@@ -900,12 +916,16 @@ class GridView extends Component {
|
|
900
916
|
{columnPositions} = me,
|
901
917
|
{x} = me.scrollPosition,
|
902
918
|
i = 0,
|
903
|
-
len = columnPositions.
|
919
|
+
len = columnPositions.getCount(),
|
904
920
|
endIndex = len - 1,
|
905
921
|
column, startIndex;
|
906
922
|
|
923
|
+
if (len < 1) {
|
924
|
+
return
|
925
|
+
}
|
926
|
+
|
907
927
|
for (; i < len; i++) {
|
908
|
-
column = columnPositions
|
928
|
+
column = columnPositions.getAt(i);
|
909
929
|
|
910
930
|
if (x >= column.x && x <= column.x + column.width) {
|
911
931
|
startIndex = i
|
@@ -34,6 +34,10 @@ class Toolbar extends BaseToolbar {
|
|
34
34
|
* @member {String} role='row'
|
35
35
|
*/
|
36
36
|
role: 'row',
|
37
|
+
/**
|
38
|
+
* @member {Number} scrollLeft_=0
|
39
|
+
*/
|
40
|
+
scrollLeft_: 0,
|
37
41
|
/**
|
38
42
|
* @member {Boolean} showHeaderFilters_=false
|
39
43
|
*/
|
@@ -62,13 +66,14 @@ class Toolbar extends BaseToolbar {
|
|
62
66
|
|
63
67
|
if (value && !me.sortZone) {
|
64
68
|
import('../../draggable/grid/header/toolbar/SortZone.mjs').then(module => {
|
65
|
-
let {appName, id, windowId} = me;
|
69
|
+
let {appName, id, scrollLeft, windowId} = me;
|
66
70
|
|
67
71
|
me.sortZone = Neo.create({
|
68
72
|
module : module.default,
|
69
73
|
appName,
|
70
|
-
boundaryContainerId: id,
|
74
|
+
boundaryContainerId: [id, me.parent.id],
|
71
75
|
owner : me,
|
76
|
+
scrollLeft,
|
72
77
|
windowId,
|
73
78
|
...me.sortZoneConfig
|
74
79
|
})
|
@@ -108,6 +113,18 @@ class Toolbar extends BaseToolbar {
|
|
108
113
|
}
|
109
114
|
}
|
110
115
|
|
116
|
+
/**
|
117
|
+
* Triggered after the scrollLeft config got changed
|
118
|
+
* @param {Number} value
|
119
|
+
* @param {Number} oldValue
|
120
|
+
* @protected
|
121
|
+
*/
|
122
|
+
afterSetScrollLeft(value, oldValue) {
|
123
|
+
if (oldValue !== undefined && this.sortZone) {
|
124
|
+
this.sortZone.scrollLeft = value
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
111
128
|
/**
|
112
129
|
* Triggered after the sortable config got changed
|
113
130
|
* @param {Boolean} value
|
@@ -184,6 +201,7 @@ class Toolbar extends BaseToolbar {
|
|
184
201
|
async passSizeToView(silent=false) {
|
185
202
|
let me = this,
|
186
203
|
{items} = me,
|
204
|
+
{view} = me.parent,
|
187
205
|
rects = await me.getDomRect(items.map(item => item.id)),
|
188
206
|
lastItem = rects[rects.length - 1],
|
189
207
|
columnPositions = rects.map((item, index) => ({dataField: items[index].dataField, width: item.width, x: item.x - rects[0].x})),
|
@@ -204,12 +222,29 @@ class Toolbar extends BaseToolbar {
|
|
204
222
|
await me.timeout(100);
|
205
223
|
await me.passSizeToView(silent)
|
206
224
|
} else {
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
225
|
+
view.columnPositions.clear();
|
226
|
+
view.columnPositions.add(columnPositions);
|
227
|
+
|
228
|
+
view[silent ? 'setSilent' : 'set']({
|
229
|
+
availableWidth: lastItem.x + lastItem.width - rects[0].x
|
230
|
+
});
|
231
|
+
|
232
|
+
!silent && view.updateVisibleColumns()
|
211
233
|
}
|
212
234
|
}
|
235
|
+
|
236
|
+
/**
|
237
|
+
* @param {Number} index
|
238
|
+
* @param {DOMRect} itemRect
|
239
|
+
* @returns {Promise<void>}
|
240
|
+
*/
|
241
|
+
async scrollToIndex(index, itemRect) {
|
242
|
+
await Neo.main.DomAccess.scrollIntoView({
|
243
|
+
delay : 125,
|
244
|
+
id : this.items[index].id,
|
245
|
+
windowId: this.windowId
|
246
|
+
})
|
247
|
+
}
|
213
248
|
}
|
214
249
|
|
215
250
|
export default Neo.setupClass(Toolbar);
|
package/src/main/DomAccess.mjs
CHANGED
@@ -464,7 +464,7 @@ class DomAccess extends Base {
|
|
464
464
|
returnData;
|
465
465
|
|
466
466
|
if (Array.isArray(data.id)) {
|
467
|
-
return data.id.map(id => me.getBoundingClientRect({
|
467
|
+
return data.id.map(id => me.getBoundingClientRect({id}))
|
468
468
|
} else {
|
469
469
|
let node = me.getElementOrBody(data.nodeType ? data : data.id),
|
470
470
|
rect = {},
|
@@ -897,19 +897,16 @@ class DomAccess extends Base {
|
|
897
897
|
* @param {String} [data.id]
|
898
898
|
* @param {String} data.behavior='smooth'
|
899
899
|
* @param {String} data.block='start'
|
900
|
+
* @param {Number} data.delay=500
|
900
901
|
* @param {String} data.inline='nearest'
|
901
902
|
* @param {String} [data.querySelector]
|
902
903
|
* @returns {Promise<any>}
|
903
904
|
*/
|
904
|
-
scrollIntoView(
|
905
|
-
let node =
|
906
|
-
opts = {
|
907
|
-
behavior: data.behavior || 'smooth',
|
908
|
-
block : data.block || 'start',
|
909
|
-
inline : data.inline || 'nearest'
|
910
|
-
};
|
905
|
+
scrollIntoView({id, behavior='smooth', block='start', delay=500, inline='nearest', querySelector}) {
|
906
|
+
let node = id ? this.getElement(id) : document.querySelector(querySelector),
|
907
|
+
opts = {behavior, block, inline};
|
911
908
|
|
912
|
-
if (
|
909
|
+
if (behavior !== 'smooth') {
|
913
910
|
node.scrollIntoView(opts)
|
914
911
|
} else {
|
915
912
|
// scrollIntoView() does not provide a callback yet.
|
@@ -918,11 +915,11 @@ class DomAccess extends Base {
|
|
918
915
|
if (node) {
|
919
916
|
let hasListener = 'scrollend' in window;
|
920
917
|
|
921
|
-
hasListener && document.addEventListener('scrollend', () =>resolve(), {capture
|
918
|
+
hasListener && document.addEventListener('scrollend', () =>resolve(), {capture: true, once: true});
|
922
919
|
|
923
920
|
node.scrollIntoView(opts);
|
924
921
|
|
925
|
-
!hasListener && this.timeout(
|
922
|
+
!hasListener && this.timeout(delay).then(() => {resolve()})
|
926
923
|
} else {
|
927
924
|
resolve()
|
928
925
|
}
|
@@ -932,19 +929,19 @@ class DomAccess extends Base {
|
|
932
929
|
|
933
930
|
/**
|
934
931
|
* @param {Object} data
|
935
|
-
* @param {String} data.direction left, top
|
932
|
+
* @param {String} data.direction='top' left, top
|
936
933
|
* @param {String} data.id
|
937
934
|
* @param {Number} data.value
|
938
935
|
* @returns {Object} obj.id => the passed id
|
939
936
|
*/
|
940
|
-
scrollTo(
|
941
|
-
let node = this.getElement(
|
937
|
+
scrollTo({direction='top', id, value}) {
|
938
|
+
let node = this.getElement(id);
|
942
939
|
|
943
940
|
if (node) {
|
944
|
-
node[`scroll${Neo.capitalize(
|
941
|
+
node[`scroll${Neo.capitalize(direction)}`] = value
|
945
942
|
}
|
946
943
|
|
947
|
-
return {id
|
944
|
+
return {id}
|
948
945
|
}
|
949
946
|
|
950
947
|
/**
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import Base from './Base.mjs';
|
2
2
|
import DomAccess from '../DomAccess.mjs';
|
3
3
|
import DomEvents from '../DomEvents.mjs';
|
4
|
+
import Rectangle from '../../util/Rectangle.mjs';
|
4
5
|
|
5
6
|
/**
|
6
7
|
* @class Neo.main.addon.DragDrop
|
@@ -438,23 +439,30 @@ class DragDrop extends Base {
|
|
438
439
|
/**
|
439
440
|
* DragZones will set these configs inside their dragStart() method.
|
440
441
|
* They only persist until the end of a drag OP.
|
441
|
-
* @param {Object}
|
442
|
-
* @param {Boolean}
|
443
|
-
* @param {String}
|
444
|
-
* @param {String}
|
445
|
-
* @param {Number}
|
446
|
-
* @param {Number}
|
442
|
+
* @param {Object} data
|
443
|
+
* @param {Boolean} data.alwaysFireDragMove
|
444
|
+
* @param {String|String[]|null} data.boundaryContainerId
|
445
|
+
* @param {String|null} data.scrollContainerId
|
446
|
+
* @param {Number} data.scrollFactorLeft
|
447
|
+
* @param {Number} data.scrollFactorTop
|
448
|
+
* @returns {Object} return the boundaryContainerRect
|
447
449
|
*/
|
448
450
|
setConfigs(data) {
|
449
|
-
let me
|
450
|
-
|
451
|
+
let me = this,
|
452
|
+
{boundaryContainerId} = data,
|
453
|
+
node, rects;
|
451
454
|
|
452
455
|
delete data.appName;
|
453
456
|
delete data.windowId;
|
454
457
|
|
455
|
-
if (
|
456
|
-
|
457
|
-
|
458
|
+
if (boundaryContainerId) {
|
459
|
+
rects = DomAccess.getBoundingClientRect({id: boundaryContainerId});
|
460
|
+
|
461
|
+
if (Array.isArray(boundaryContainerId)) {
|
462
|
+
me.boundaryContainerRect = Rectangle.getIntersection(...rects)
|
463
|
+
} else {
|
464
|
+
me.boundaryContainerRect = rects
|
465
|
+
}
|
458
466
|
}
|
459
467
|
|
460
468
|
delete data.boundaryContainerId;
|
@@ -489,6 +497,10 @@ class DragDrop extends Base {
|
|
489
497
|
}
|
490
498
|
})
|
491
499
|
}
|
500
|
+
|
501
|
+
return {
|
502
|
+
boundaryContainerRect: me.boundaryContainerRect || null
|
503
|
+
}
|
492
504
|
}
|
493
505
|
|
494
506
|
/**
|
package/src/util/Rectangle.mjs
CHANGED
@@ -111,30 +111,24 @@ export default class Rectangle extends DOMRect {
|
|
111
111
|
}
|
112
112
|
|
113
113
|
/**
|
114
|
-
* Returns the overlapping area of rect1 & rect2
|
115
|
-
* @param {
|
116
|
-
* @param {
|
117
|
-
* @returns {
|
114
|
+
* Returns the overlapping area of rect1 & rect2 as a new Rectangle
|
115
|
+
* @param {DOMRect|Neo.util.Rectangle} rect1
|
116
|
+
* @param {DOMRect|Neo.util.Rectangle} rect2
|
117
|
+
* @returns {Neo.util.Rectangle|null} The intersecting rect
|
118
118
|
*/
|
119
119
|
static getIntersection(rect1, rect2) {
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
let width = Math.max(0, Math.min(rect1.right, rect2.right) - Math.max(rect1.left, rect2.left)),
|
131
|
-
height = Math.max(0, Math.min(rect1.bottom, rect2.bottom) - Math.max(rect1.top, rect2.top));
|
120
|
+
let x = Math.max(rect1.x, rect2.x),
|
121
|
+
y = Math.max(rect1.y, rect2.y),
|
122
|
+
right = Math.min(rect1.right, rect2.right),
|
123
|
+
bottom = Math.min(rect1.bottom, rect2.bottom),
|
124
|
+
width = Math.max(0, right - x),
|
125
|
+
height = Math.max(0, bottom - y);
|
126
|
+
|
127
|
+
if (height < 1 || width < 1) {
|
128
|
+
return null
|
129
|
+
}
|
132
130
|
|
133
|
-
return
|
134
|
-
area: height * width,
|
135
|
-
height,
|
136
|
-
width
|
137
|
-
};
|
131
|
+
return new Rectangle(x, y, width, height)
|
138
132
|
}
|
139
133
|
|
140
134
|
/**
|