gridstack 12.2.2 → 12.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/LICENSE +1 -1
- package/README.md +3 -3
- package/dist/angular/README.md +2 -0
- package/dist/angular/esm2020/lib/base-widget.mjs +63 -7
- package/dist/angular/esm2020/lib/gridstack-item.component.mjs +33 -4
- package/dist/angular/esm2020/lib/gridstack.component.mjs +97 -16
- package/dist/angular/esm2020/lib/gridstack.module.mjs +25 -3
- package/dist/angular/esm2020/lib/types.mjs +2 -2
- package/dist/angular/fesm2015/gridstack-angular.mjs +191 -25
- package/dist/angular/fesm2015/gridstack-angular.mjs.map +1 -1
- package/dist/angular/fesm2020/gridstack-angular.mjs +192 -26
- package/dist/angular/fesm2020/gridstack-angular.mjs.map +1 -1
- package/dist/angular/lib/base-widget.d.ts +42 -5
- package/dist/angular/lib/gridstack-item.component.d.ts +49 -7
- package/dist/angular/lib/gridstack.component.d.ts +137 -22
- package/dist/angular/lib/gridstack.module.d.ts +23 -0
- package/dist/angular/lib/types.d.ts +32 -5
- package/dist/angular/package.json +1 -1
- package/dist/angular/src/base-widget.ts +68 -9
- package/dist/angular/src/gridstack-item.component.ts +49 -7
- package/dist/angular/src/gridstack.component.ts +154 -23
- package/dist/angular/src/gridstack.module.ts +24 -2
- package/dist/angular/src/types.ts +54 -0
- package/dist/dd-base-impl.d.ts +52 -3
- package/dist/dd-base-impl.js +41 -3
- package/dist/dd-base-impl.js.map +1 -1
- package/dist/dd-draggable.d.ts +2 -2
- package/dist/dd-draggable.js +4 -2
- package/dist/dd-draggable.js.map +1 -1
- package/dist/dd-droppable.d.ts +2 -2
- package/dist/dd-droppable.js +2 -2
- package/dist/dd-droppable.js.map +1 -1
- package/dist/dd-element.d.ts +2 -2
- package/dist/dd-element.js +2 -2
- package/dist/dd-element.js.map +1 -1
- package/dist/dd-gridstack.d.ts +54 -6
- package/dist/dd-gridstack.js +32 -2
- package/dist/dd-gridstack.js.map +1 -1
- package/dist/dd-manager.d.ts +29 -8
- package/dist/dd-manager.js +7 -3
- package/dist/dd-manager.js.map +1 -1
- package/dist/dd-resizable-handle.d.ts +2 -2
- package/dist/dd-resizable-handle.js +2 -2
- package/dist/dd-resizable-handle.js.map +1 -1
- package/dist/dd-resizable.d.ts +2 -2
- package/dist/dd-resizable.js +2 -2
- package/dist/dd-resizable.js.map +1 -1
- package/dist/dd-touch.d.ts +2 -2
- package/dist/dd-touch.js +2 -2
- package/dist/dd-touch.js.map +1 -1
- package/dist/gridstack-all.js +1 -1
- package/dist/gridstack-all.js.LICENSE.txt +2 -2
- package/dist/gridstack-all.js.map +1 -1
- package/dist/gridstack-engine.d.ts +235 -26
- package/dist/gridstack-engine.js +275 -29
- package/dist/gridstack-engine.js.map +1 -1
- package/dist/gridstack.css +2 -2
- package/dist/gridstack.d.ts +424 -82
- package/dist/gridstack.js +408 -76
- package/dist/gridstack.js.map +1 -1
- package/dist/src/gridstack.scss +2 -2
- package/dist/types.d.ts +130 -29
- package/dist/types.js +6 -3
- package/dist/types.js.map +1 -1
- package/dist/utils.d.ts +208 -29
- package/dist/utils.js +275 -61
- package/dist/utils.js.map +1 -1
- package/doc/API.md +6192 -0
- package/package.json +14 -3
- package/doc/CHANGES.md +0 -962
- package/doc/README.md +0 -642
package/dist/utils.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* utils.ts 12.
|
|
3
|
-
* Copyright (c) 2021-
|
|
2
|
+
* utils.ts 12.3.0
|
|
3
|
+
* Copyright (c) 2021-2025 Alain Dumesny - see GridStack root license
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* @internal Checks for obsolete method names and provides deprecation warnings.
|
|
7
|
+
* Creates a wrapper function that logs a deprecation warning when called.
|
|
8
|
+
*
|
|
9
|
+
* @param self the object context to apply the function to
|
|
10
|
+
* @param f the new function to call
|
|
11
|
+
* @param oldName the deprecated method name
|
|
12
|
+
* @param newName the new method name to use instead
|
|
13
|
+
* @param rev the version when the deprecation was introduced
|
|
14
|
+
* @returns a wrapper function that warns about deprecation
|
|
4
15
|
*/
|
|
5
|
-
/** checks for obsolete method names */
|
|
6
16
|
// eslint-disable-next-line
|
|
7
17
|
export function obsolete(self, f, oldName, newName, rev) {
|
|
8
18
|
const wrapper = (...args) => {
|
|
@@ -13,7 +23,15 @@ export function obsolete(self, f, oldName, newName, rev) {
|
|
|
13
23
|
wrapper.prototype = f.prototype;
|
|
14
24
|
return wrapper;
|
|
15
25
|
}
|
|
16
|
-
/**
|
|
26
|
+
/**
|
|
27
|
+
* @internal Checks for obsolete grid options and migrates them to new names.
|
|
28
|
+
* Automatically copies old option values to new option names and shows deprecation warnings.
|
|
29
|
+
*
|
|
30
|
+
* @param opts the options object to check and migrate
|
|
31
|
+
* @param oldName the deprecated option name
|
|
32
|
+
* @param newName the new option name to use instead
|
|
33
|
+
* @param rev the version when the deprecation was introduced
|
|
34
|
+
*/
|
|
17
35
|
export function obsoleteOpts(opts, oldName, newName, rev) {
|
|
18
36
|
if (opts[oldName] !== undefined) {
|
|
19
37
|
opts[newName] = opts[oldName];
|
|
@@ -21,13 +39,29 @@ export function obsoleteOpts(opts, oldName, newName, rev) {
|
|
|
21
39
|
newName + '`. It will be **removed** in a future release');
|
|
22
40
|
}
|
|
23
41
|
}
|
|
24
|
-
/**
|
|
42
|
+
/**
|
|
43
|
+
* @internal Checks for obsolete grid options that have been completely removed.
|
|
44
|
+
* Shows deprecation warnings for options that are no longer supported.
|
|
45
|
+
*
|
|
46
|
+
* @param opts the options object to check
|
|
47
|
+
* @param oldName the removed option name
|
|
48
|
+
* @param rev the version when the option was removed
|
|
49
|
+
* @param info additional information about the removal
|
|
50
|
+
*/
|
|
25
51
|
export function obsoleteOptsDel(opts, oldName, rev, info) {
|
|
26
52
|
if (opts[oldName] !== undefined) {
|
|
27
53
|
console.warn('gridstack.js: Option `' + oldName + '` is deprecated in ' + rev + info);
|
|
28
54
|
}
|
|
29
55
|
}
|
|
30
|
-
/**
|
|
56
|
+
/**
|
|
57
|
+
* @internal Checks for obsolete HTML element attributes and migrates them.
|
|
58
|
+
* Automatically copies old attribute values to new attribute names and shows deprecation warnings.
|
|
59
|
+
*
|
|
60
|
+
* @param el the HTML element to check and migrate
|
|
61
|
+
* @param oldName the deprecated attribute name
|
|
62
|
+
* @param newName the new attribute name to use instead
|
|
63
|
+
* @param rev the version when the deprecation was introduced
|
|
64
|
+
*/
|
|
31
65
|
export function obsoleteAttr(el, oldName, newName, rev) {
|
|
32
66
|
const oldAttr = el.getAttribute(oldName);
|
|
33
67
|
if (oldAttr !== null) {
|
|
@@ -37,10 +71,24 @@ export function obsoleteAttr(el, oldName, newName, rev) {
|
|
|
37
71
|
}
|
|
38
72
|
}
|
|
39
73
|
/**
|
|
40
|
-
*
|
|
74
|
+
* Collection of utility methods used throughout GridStack.
|
|
75
|
+
* These are general-purpose helper functions for DOM manipulation,
|
|
76
|
+
* positioning calculations, object operations, and more.
|
|
41
77
|
*/
|
|
42
78
|
export class Utils {
|
|
43
|
-
/**
|
|
79
|
+
/**
|
|
80
|
+
* Convert a potential selector into an actual list of HTML elements.
|
|
81
|
+
* Supports CSS selectors, element references, and special ID handling.
|
|
82
|
+
*
|
|
83
|
+
* @param els selector string, HTMLElement, or array of elements
|
|
84
|
+
* @param root optional root element to search within (defaults to document, useful for shadow DOM)
|
|
85
|
+
* @returns array of HTML elements matching the selector
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* const elements = Utils.getElements('.grid-item');
|
|
89
|
+
* const byId = Utils.getElements('#myWidget');
|
|
90
|
+
* const fromShadow = Utils.getElements('.item', shadowRoot);
|
|
91
|
+
*/
|
|
44
92
|
static getElements(els, root = document) {
|
|
45
93
|
if (typeof els === 'string') {
|
|
46
94
|
const doc = ('getElementById' in root) ? root : undefined;
|
|
@@ -62,7 +110,18 @@ export class Utils {
|
|
|
62
110
|
}
|
|
63
111
|
return [els];
|
|
64
112
|
}
|
|
65
|
-
/**
|
|
113
|
+
/**
|
|
114
|
+
* Convert a potential selector into a single HTML element.
|
|
115
|
+
* Similar to getElements() but returns only the first match.
|
|
116
|
+
*
|
|
117
|
+
* @param els selector string or HTMLElement
|
|
118
|
+
* @param root optional root element to search within (defaults to document)
|
|
119
|
+
* @returns the first HTML element matching the selector, or null if not found
|
|
120
|
+
*
|
|
121
|
+
* @example
|
|
122
|
+
* const element = Utils.getElement('#myWidget');
|
|
123
|
+
* const first = Utils.getElement('.grid-item');
|
|
124
|
+
*/
|
|
66
125
|
static getElement(els, root = document) {
|
|
67
126
|
if (typeof els === 'string') {
|
|
68
127
|
const doc = ('getElementById' in root) ? root : undefined;
|
|
@@ -90,11 +149,31 @@ export class Utils {
|
|
|
90
149
|
}
|
|
91
150
|
return els;
|
|
92
151
|
}
|
|
93
|
-
/**
|
|
152
|
+
/**
|
|
153
|
+
* Check if a widget should be lazy loaded based on node or grid settings.
|
|
154
|
+
*
|
|
155
|
+
* @param n the grid node to check
|
|
156
|
+
* @returns true if the item should be lazy loaded
|
|
157
|
+
*
|
|
158
|
+
* @example
|
|
159
|
+
* if (Utils.lazyLoad(node)) {
|
|
160
|
+
* // Set up intersection observer for lazy loading
|
|
161
|
+
* }
|
|
162
|
+
*/
|
|
94
163
|
static lazyLoad(n) {
|
|
95
164
|
return n.lazyLoad || n.grid?.opts?.lazyLoad && n.lazyLoad !== false;
|
|
96
165
|
}
|
|
97
|
-
/**
|
|
166
|
+
/**
|
|
167
|
+
* Create a div element with the specified CSS classes.
|
|
168
|
+
*
|
|
169
|
+
* @param classes array of CSS class names to add
|
|
170
|
+
* @param parent optional parent element to append the div to
|
|
171
|
+
* @returns the created div element
|
|
172
|
+
*
|
|
173
|
+
* @example
|
|
174
|
+
* const div = Utils.createDiv(['grid-item', 'draggable']);
|
|
175
|
+
* const nested = Utils.createDiv(['content'], parentDiv);
|
|
176
|
+
*/
|
|
98
177
|
static createDiv(classes, parent) {
|
|
99
178
|
const el = document.createElement('div');
|
|
100
179
|
classes.forEach(c => { if (c)
|
|
@@ -102,21 +181,68 @@ export class Utils {
|
|
|
102
181
|
parent?.appendChild(el);
|
|
103
182
|
return el;
|
|
104
183
|
}
|
|
105
|
-
/**
|
|
184
|
+
/**
|
|
185
|
+
* Check if a widget should resize to fit its content.
|
|
186
|
+
*
|
|
187
|
+
* @param n the grid node to check (can be undefined)
|
|
188
|
+
* @param strict if true, only returns true for explicit sizeToContent:true (not numbers)
|
|
189
|
+
* @returns true if the widget should resize to content
|
|
190
|
+
*
|
|
191
|
+
* @example
|
|
192
|
+
* if (Utils.shouldSizeToContent(node)) {
|
|
193
|
+
* // Trigger content-based resizing
|
|
194
|
+
* }
|
|
195
|
+
*/
|
|
106
196
|
static shouldSizeToContent(n, strict = false) {
|
|
107
197
|
return n?.grid && (strict ?
|
|
108
198
|
(n.sizeToContent === true || (n.grid.opts.sizeToContent === true && n.sizeToContent === undefined)) :
|
|
109
199
|
(!!n.sizeToContent || (n.grid.opts.sizeToContent && n.sizeToContent !== false)));
|
|
110
200
|
}
|
|
111
|
-
/**
|
|
201
|
+
/**
|
|
202
|
+
* Check if two grid positions overlap/intersect.
|
|
203
|
+
*
|
|
204
|
+
* @param a first position with x, y, w, h properties
|
|
205
|
+
* @param b second position with x, y, w, h properties
|
|
206
|
+
* @returns true if the positions overlap
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* const overlaps = Utils.isIntercepted(
|
|
210
|
+
* {x: 0, y: 0, w: 2, h: 1},
|
|
211
|
+
* {x: 1, y: 0, w: 2, h: 1}
|
|
212
|
+
* ); // true - they overlap
|
|
213
|
+
*/
|
|
112
214
|
static isIntercepted(a, b) {
|
|
113
215
|
return !(a.y >= b.y + b.h || a.y + a.h <= b.y || a.x + a.w <= b.x || a.x >= b.x + b.w);
|
|
114
216
|
}
|
|
115
|
-
/**
|
|
217
|
+
/**
|
|
218
|
+
* Check if two grid positions are touching (edges or corners).
|
|
219
|
+
*
|
|
220
|
+
* @param a first position
|
|
221
|
+
* @param b second position
|
|
222
|
+
* @returns true if the positions are touching
|
|
223
|
+
*
|
|
224
|
+
* @example
|
|
225
|
+
* const touching = Utils.isTouching(
|
|
226
|
+
* {x: 0, y: 0, w: 2, h: 1},
|
|
227
|
+
* {x: 2, y: 0, w: 1, h: 1}
|
|
228
|
+
* ); // true - they share an edge
|
|
229
|
+
*/
|
|
116
230
|
static isTouching(a, b) {
|
|
117
231
|
return Utils.isIntercepted(a, { x: b.x - 0.5, y: b.y - 0.5, w: b.w + 1, h: b.h + 1 });
|
|
118
232
|
}
|
|
119
|
-
/**
|
|
233
|
+
/**
|
|
234
|
+
* Calculate the overlapping area between two grid positions.
|
|
235
|
+
*
|
|
236
|
+
* @param a first position
|
|
237
|
+
* @param b second position
|
|
238
|
+
* @returns the area of overlap (0 if no overlap)
|
|
239
|
+
*
|
|
240
|
+
* @example
|
|
241
|
+
* const overlap = Utils.areaIntercept(
|
|
242
|
+
* {x: 0, y: 0, w: 3, h: 2},
|
|
243
|
+
* {x: 1, y: 0, w: 3, h: 2}
|
|
244
|
+
* ); // returns 4 (2x2 overlap)
|
|
245
|
+
*/
|
|
120
246
|
static areaIntercept(a, b) {
|
|
121
247
|
const x0 = (a.x > b.x) ? a.x : b.x;
|
|
122
248
|
const x1 = (a.x + a.w < b.x + b.w) ? a.x + a.w : b.x + b.w;
|
|
@@ -128,15 +254,29 @@ export class Utils {
|
|
|
128
254
|
return 0; // no overlap
|
|
129
255
|
return (x1 - x0) * (y1 - y0);
|
|
130
256
|
}
|
|
131
|
-
/**
|
|
257
|
+
/**
|
|
258
|
+
* Calculate the total area of a grid position.
|
|
259
|
+
*
|
|
260
|
+
* @param a position with width and height
|
|
261
|
+
* @returns the total area (width * height)
|
|
262
|
+
*
|
|
263
|
+
* @example
|
|
264
|
+
* const area = Utils.area({x: 0, y: 0, w: 3, h: 2}); // returns 6
|
|
265
|
+
*/
|
|
132
266
|
static area(a) {
|
|
133
267
|
return a.w * a.h;
|
|
134
268
|
}
|
|
135
269
|
/**
|
|
136
|
-
*
|
|
137
|
-
*
|
|
138
|
-
* @param
|
|
139
|
-
|
|
270
|
+
* Sort an array of grid nodes by position (y first, then x).
|
|
271
|
+
*
|
|
272
|
+
* @param nodes array of nodes to sort
|
|
273
|
+
* @param dir sort direction: 1 for ascending (top-left first), -1 for descending
|
|
274
|
+
* @returns the sorted array (modifies original)
|
|
275
|
+
*
|
|
276
|
+
* @example
|
|
277
|
+
* const sorted = Utils.sort(nodes); // Sort top-left to bottom-right
|
|
278
|
+
* const reverse = Utils.sort(nodes, -1); // Sort bottom-right to top-left
|
|
279
|
+
*/
|
|
140
280
|
static sort(nodes, dir = 1) {
|
|
141
281
|
const und = 10000;
|
|
142
282
|
return nodes.sort((a, b) => {
|
|
@@ -146,10 +286,33 @@ export class Utils {
|
|
|
146
286
|
return diffY;
|
|
147
287
|
});
|
|
148
288
|
}
|
|
149
|
-
/**
|
|
289
|
+
/**
|
|
290
|
+
* Find a grid node by its ID.
|
|
291
|
+
*
|
|
292
|
+
* @param nodes array of nodes to search
|
|
293
|
+
* @param id the ID to search for
|
|
294
|
+
* @returns the node with matching ID, or undefined if not found
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* const node = Utils.find(nodes, 'widget-1');
|
|
298
|
+
* if (node) console.log('Found node at:', node.x, node.y);
|
|
299
|
+
*/
|
|
150
300
|
static find(nodes, id) {
|
|
151
301
|
return id ? nodes.find(n => n.id === id) : undefined;
|
|
152
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Convert various value types to boolean.
|
|
305
|
+
* Handles strings like 'false', 'no', '0' as false.
|
|
306
|
+
*
|
|
307
|
+
* @param v value to convert
|
|
308
|
+
* @returns boolean representation
|
|
309
|
+
*
|
|
310
|
+
* @example
|
|
311
|
+
* Utils.toBool('true'); // true
|
|
312
|
+
* Utils.toBool('false'); // false
|
|
313
|
+
* Utils.toBool('no'); // false
|
|
314
|
+
* Utils.toBool('1'); // true
|
|
315
|
+
*/
|
|
153
316
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
154
317
|
static toBool(v) {
|
|
155
318
|
if (typeof v === 'boolean') {
|
|
@@ -161,9 +324,32 @@ export class Utils {
|
|
|
161
324
|
}
|
|
162
325
|
return Boolean(v);
|
|
163
326
|
}
|
|
327
|
+
/**
|
|
328
|
+
* Convert a string value to a number, handling null and empty strings.
|
|
329
|
+
*
|
|
330
|
+
* @param value string or null value to convert
|
|
331
|
+
* @returns number value, or undefined for null/empty strings
|
|
332
|
+
*
|
|
333
|
+
* @example
|
|
334
|
+
* Utils.toNumber('42'); // 42
|
|
335
|
+
* Utils.toNumber(''); // undefined
|
|
336
|
+
* Utils.toNumber(null); // undefined
|
|
337
|
+
*/
|
|
164
338
|
static toNumber(value) {
|
|
165
339
|
return (value === null || value.length === 0) ? undefined : Number(value);
|
|
166
340
|
}
|
|
341
|
+
/**
|
|
342
|
+
* Parse a height value with units into numeric value and unit string.
|
|
343
|
+
* Supports px, em, rem, vh, vw, %, cm, mm units.
|
|
344
|
+
*
|
|
345
|
+
* @param val height value as number or string with units
|
|
346
|
+
* @returns object with h (height) and unit properties
|
|
347
|
+
*
|
|
348
|
+
* @example
|
|
349
|
+
* Utils.parseHeight('100px'); // {h: 100, unit: 'px'}
|
|
350
|
+
* Utils.parseHeight('2rem'); // {h: 2, unit: 'rem'}
|
|
351
|
+
* Utils.parseHeight(50); // {h: 50, unit: 'px'}
|
|
352
|
+
*/
|
|
167
353
|
static parseHeight(val) {
|
|
168
354
|
let h;
|
|
169
355
|
let unit = 'px';
|
|
@@ -184,7 +370,19 @@ export class Utils {
|
|
|
184
370
|
}
|
|
185
371
|
return { h, unit };
|
|
186
372
|
}
|
|
187
|
-
/**
|
|
373
|
+
/**
|
|
374
|
+
* Copy unset fields from source objects to target object (shallow merge with defaults).
|
|
375
|
+
* Similar to Object.assign but only sets undefined/null fields.
|
|
376
|
+
*
|
|
377
|
+
* @param target the object to copy defaults into
|
|
378
|
+
* @param sources one or more source objects to copy defaults from
|
|
379
|
+
* @returns the modified target object
|
|
380
|
+
*
|
|
381
|
+
* @example
|
|
382
|
+
* const config = { width: 100 };
|
|
383
|
+
* Utils.defaults(config, { width: 200, height: 50 });
|
|
384
|
+
* // config is now { width: 100, height: 50 }
|
|
385
|
+
*/
|
|
188
386
|
// eslint-disable-next-line
|
|
189
387
|
static defaults(target, ...sources) {
|
|
190
388
|
sources.forEach(source => {
|
|
@@ -196,13 +394,24 @@ export class Utils {
|
|
|
196
394
|
}
|
|
197
395
|
else if (typeof source[key] === 'object' && typeof target[key] === 'object') {
|
|
198
396
|
// property is an object, recursively add it's field over... #1373
|
|
199
|
-
|
|
397
|
+
Utils.defaults(target[key], source[key]);
|
|
200
398
|
}
|
|
201
399
|
}
|
|
202
400
|
});
|
|
203
401
|
return target;
|
|
204
402
|
}
|
|
205
|
-
/**
|
|
403
|
+
/**
|
|
404
|
+
* Compare two objects for equality (shallow comparison).
|
|
405
|
+
* Checks if objects have the same fields and values at one level deep.
|
|
406
|
+
*
|
|
407
|
+
* @param a first object to compare
|
|
408
|
+
* @param b second object to compare
|
|
409
|
+
* @returns true if objects have the same values
|
|
410
|
+
*
|
|
411
|
+
* @example
|
|
412
|
+
* Utils.same({x: 1, y: 2}, {x: 1, y: 2}); // true
|
|
413
|
+
* Utils.same({x: 1}, {x: 1, y: 2}); // false
|
|
414
|
+
*/
|
|
206
415
|
static same(a, b) {
|
|
207
416
|
if (typeof a !== 'object')
|
|
208
417
|
return a == b;
|
|
@@ -217,7 +426,19 @@ export class Utils {
|
|
|
217
426
|
}
|
|
218
427
|
return true;
|
|
219
428
|
}
|
|
220
|
-
/**
|
|
429
|
+
/**
|
|
430
|
+
* Copy position and size properties from one widget to another.
|
|
431
|
+
* Copies x, y, w, h and optionally min/max constraints.
|
|
432
|
+
*
|
|
433
|
+
* @param a target widget to copy to
|
|
434
|
+
* @param b source widget to copy from
|
|
435
|
+
* @param doMinMax if true, also copy min/max width/height constraints
|
|
436
|
+
* @returns the target widget (a)
|
|
437
|
+
*
|
|
438
|
+
* @example
|
|
439
|
+
* Utils.copyPos(widget1, widget2); // Copy position/size
|
|
440
|
+
* Utils.copyPos(widget1, widget2, true); // Also copy constraints
|
|
441
|
+
*/
|
|
221
442
|
static copyPos(a, b, doMinMax = false) {
|
|
222
443
|
if (b.x !== undefined)
|
|
223
444
|
a.x = b.x;
|
|
@@ -346,46 +567,39 @@ export class Utils {
|
|
|
346
567
|
return el;
|
|
347
568
|
}
|
|
348
569
|
else {
|
|
349
|
-
return
|
|
570
|
+
return Utils.getScrollElement(el.parentElement);
|
|
350
571
|
}
|
|
351
572
|
}
|
|
352
573
|
/** @internal */
|
|
353
574
|
static updateScrollPosition(el, position, distance) {
|
|
354
|
-
|
|
355
|
-
|
|
575
|
+
const scrollEl = Utils.getScrollElement(el);
|
|
576
|
+
if (!scrollEl)
|
|
577
|
+
return;
|
|
578
|
+
const elRect = el.getBoundingClientRect();
|
|
579
|
+
const scrollRect = scrollEl.getBoundingClientRect();
|
|
356
580
|
const innerHeightOrClientHeight = (window.innerHeight || document.documentElement.clientHeight);
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
//
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
else if (distance > 0) {
|
|
377
|
-
// moving down
|
|
378
|
-
if (el.offsetHeight > innerHeightOrClientHeight) {
|
|
379
|
-
scrollEl.scrollTop += distance;
|
|
380
|
-
}
|
|
381
|
-
else {
|
|
382
|
-
scrollEl.scrollTop += offsetDiffDown > distance ? distance : offsetDiffDown;
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
// move widget y by amount scrolled
|
|
386
|
-
position.top += scrollEl.scrollTop - prevScroll;
|
|
581
|
+
const offsetDiffDown = elRect.bottom - Math.min(scrollRect.bottom, innerHeightOrClientHeight);
|
|
582
|
+
const offsetDiffUp = elRect.top - Math.max(scrollRect.top, 0);
|
|
583
|
+
const prevScroll = scrollEl.scrollTop;
|
|
584
|
+
if (offsetDiffUp < 0 && distance < 0) {
|
|
585
|
+
// scroll up
|
|
586
|
+
if (el.offsetHeight > scrollRect.height) {
|
|
587
|
+
scrollEl.scrollTop += distance;
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
scrollEl.scrollTop += Math.abs(offsetDiffUp) > Math.abs(distance) ? distance : offsetDiffUp;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
else if (offsetDiffDown > 0 && distance > 0) {
|
|
594
|
+
// scroll down
|
|
595
|
+
if (el.offsetHeight > scrollRect.height) {
|
|
596
|
+
scrollEl.scrollTop += distance;
|
|
597
|
+
}
|
|
598
|
+
else {
|
|
599
|
+
scrollEl.scrollTop += offsetDiffDown > distance ? distance : offsetDiffDown;
|
|
387
600
|
}
|
|
388
601
|
}
|
|
602
|
+
position.top += scrollEl.scrollTop - prevScroll;
|
|
389
603
|
}
|
|
390
604
|
/**
|
|
391
605
|
* @internal Function used to scroll the page.
|
|
@@ -395,13 +609,13 @@ export class Utils {
|
|
|
395
609
|
* @param distance Distance from the V edges to start scrolling
|
|
396
610
|
*/
|
|
397
611
|
static updateScrollResize(event, el, distance) {
|
|
398
|
-
const scrollEl =
|
|
612
|
+
const scrollEl = Utils.getScrollElement(el);
|
|
399
613
|
const height = scrollEl.clientHeight;
|
|
400
614
|
// #1727 event.clientY is relative to viewport, so must compare this against position of scrollEl getBoundingClientRect().top
|
|
401
615
|
// #1745 Special situation if scrollEl is document 'html': here browser spec states that
|
|
402
616
|
// clientHeight is height of viewport, but getBoundingClientRect() is rectangle of html element;
|
|
403
617
|
// this discrepancy arises because in reality scrollbar is attached to viewport, not html element itself.
|
|
404
|
-
const offsetTop = (scrollEl ===
|
|
618
|
+
const offsetTop = (scrollEl === Utils.getScrollElement()) ? 0 : scrollEl.getBoundingClientRect().top;
|
|
405
619
|
const pointerPosY = event.clientY - offsetTop;
|
|
406
620
|
const top = pointerPosY < distance;
|
|
407
621
|
const bottom = pointerPosY > height - distance;
|
|
@@ -555,7 +769,7 @@ export class Utils {
|
|
|
555
769
|
}
|
|
556
770
|
/** returns true if event is inside the given element rectangle */
|
|
557
771
|
// Note: Safari Mac has null event.relatedTarget which causes #1684 so check if DragEvent is inside the coordinates instead
|
|
558
|
-
//
|
|
772
|
+
// Utils.el.contains(event.relatedTarget as HTMLElement)
|
|
559
773
|
// public static inside(e: MouseEvent, el: HTMLElement): boolean {
|
|
560
774
|
// // srcElement, toElement, target: all set to placeholder when leaving simple grid, so we can't use that (Chrome)
|
|
561
775
|
// const target: HTMLElement = e.relatedTarget || (e as any).fromElement;
|