Skip to content

Commit 624968d

Browse files
committed
fix autoPlacement from DOM reading
fix #2232 * reading from DOM will now place missing x,y items first available spot again (broke recently) * added support to save original info including autoPlacement so if you laod into 1 column then go back to 12 it's the same as loading into 12 directly. * added sample showing issue.
1 parent 0c26c63 commit 624968d

File tree

4 files changed

+64
-29
lines changed

4 files changed

+64
-29
lines changed

doc/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,9 @@ Change log
8383
<!-- END doctoc generated TOC please keep comment here to allow auto update -->
8484

8585
## 7.2.3-dev (TBD)
86+
* feat [#2229](https://github.com/gridstack/gridstack.js/pull/2229) support nonce for CSP
8687
* fix [#2206](https://github.com/gridstack/gridstack.js/issues/2206) `load()` with collision fix
88+
* fix [#2232](https://github.com/gridstack/gridstack.js/issues/2232) `autoPosition` bug loading from DOM
8789

8890
## 7.2.3 (2023-02-02)
8991
* fix `addWidget()` to handle passing just {el} which was needed for Angular HMTL template demo
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="utf-8">
5+
<meta http-equiv="X-UA-Compatible" content="IE=edge">
6+
<meta name="viewport" content="width=device-width, initial-scale=1">
7+
<title>DOM reading</title>
8+
9+
<link rel="stylesheet" href="../../../demo.css"/>
10+
<script src="../../../dist/gridstack-all.js"></script>
11+
12+
</head>
13+
<body>
14+
<div class="container-fluid">
15+
<h1>DOM reading, with auto placement mix (1&2 set, others not)</h1>
16+
<div class="grid-stack">
17+
<div class="grid-stack-item" gs-w="12" gs-x="0" gs-y="0">
18+
<div class="grid-stack-item-content">1</div>
19+
</div>
20+
<div class="grid-stack-item" gs-w="4" gs-x="0" gs-y="1">
21+
<div class="grid-stack-item-content">2</div>
22+
</div>
23+
<div class="grid-stack-item" gs-w="4">
24+
<div class="grid-stack-item-content">3</div>
25+
</div>
26+
<div class="grid-stack-item">
27+
<div class="grid-stack-item-content">4</div>
28+
</div>
29+
</div>
30+
</div>
31+
<script type="text/javascript">
32+
let grid = GridStack.init({cellHeight: 70});
33+
</script>
34+
</body>
35+
</html>

src/gridstack-engine.ts

Lines changed: 26 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -376,9 +376,10 @@ export class GridStackEngine {
376376
// remember it's position & width so we can restore back (1 -> 12 column) #1655 #1985
377377
// IFF we're not in the middle of column resizing!
378378
const saveOrig = this.column === 1 || node.x + node.w > this.column;
379-
if (saveOrig && this.column < 12 && !this._inColumnResize && !node.autoPosition && node._id && this.findCacheLayout(node, 12) === -1) {
379+
if (saveOrig && this.column < 12 && !this._inColumnResize && node._id && this.findCacheLayout(node, 12) === -1) {
380380
let copy = {...node}; // need _id + positions
381-
copy.x = Math.min(11, copy.x);
381+
if (copy.autoPosition) { delete copy.x; delete copy.y; }
382+
else copy.x = Math.min(11, copy.x);
382383
copy.w = Math.min(12, copy.w);
383384
this.cacheOneLayout(copy, 12);
384385
}
@@ -474,20 +475,23 @@ export class GridStackEngine {
474475
return this;
475476
}
476477

477-
/** find the first available empty spot for the given node width/height, updating the x,y attributes. return true if found */
478-
public findEmptyPosition(node: GridStackNode): boolean {
479-
this.sortNodes();
478+
/** find the first available empty spot for the given node width/height, updating the x,y attributes. return true if found.
479+
* optionally you can pass your own existing node list and column count, otherwise defaults to that engine data.
480+
*/
481+
public findEmptyPosition(node: GridStackNode, nodeList = this.nodes, column = this.column): boolean {
482+
nodeList = Utils.sort(nodeList, -1, column);
480483
let found = false;
481484
for (let i = 0; !found; ++i) {
482-
let x = i % this.column;
483-
let y = Math.floor(i / this.column);
484-
if (x + node.w > this.column) {
485+
let x = i % column;
486+
let y = Math.floor(i / column);
487+
if (x + node.w > column) {
485488
continue;
486489
}
487490
let box = {x, y, w: node.w, h: node.h};
488-
if (!this.nodes.find(n => Utils.isIntercepted(box, n))) {
491+
if (!nodeList.find(n => Utils.isIntercepted(box, n))) {
489492
node.x = x;
490493
node.y = y;
494+
delete node.autoPosition;
491495
found = true;
492496
}
493497
}
@@ -829,10 +833,15 @@ export class GridStackEngine {
829833
let j = nodes.findIndex(n => n._id === cacheNode._id);
830834
if (j !== -1) {
831835
// still current, use cache info positions
832-
nodes[j].x = cacheNode.x;
833-
nodes[j].y = cacheNode.y;
834-
nodes[j].w = cacheNode.w;
835-
newNodes.push(nodes[j]);
836+
if (cacheNode.autoPosition || isNaN(cacheNode.x) || isNaN(cacheNode.y)) {
837+
this.findEmptyPosition(cacheNode, newNodes);
838+
}
839+
if (!cacheNode.autoPosition) {
840+
nodes[j].x = cacheNode.x;
841+
nodes[j].y = cacheNode.y;
842+
nodes[j].w = cacheNode.w;
843+
newNodes.push(nodes[j]);
844+
}
836845
nodes.splice(j, 1);
837846
}
838847
});
@@ -892,14 +901,15 @@ export class GridStackEngine {
892901
*/
893902
public cacheOneLayout(n: GridStackNode, column: number): GridStackEngine {
894903
n._id = n._id || GridStackEngine._idSeq++;
895-
let layout: GridStackNode = {x: n.x, y: n.y, w: n.w, _id: n._id}
904+
let l: GridStackNode = {x: n.x, y: n.y, w: n.w, _id: n._id}
905+
if (n.autoPosition) { delete l.x; delete l.y; l.autoPosition = true; }
896906
this._layouts = this._layouts || [];
897907
this._layouts[column] = this._layouts[column] || [];
898908
let index = this.findCacheLayout(n, column);
899909
if (index === -1)
900-
this._layouts[column].push(layout);
910+
this._layouts[column].push(l);
901911
else
902-
this._layouts[column][index] = layout;
912+
this._layouts[column][index] = l;
903913
return this;
904914
}
905915

src/gridstack.ts

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -346,19 +346,7 @@ export class GridStack {
346346

347347
if (this.opts.auto) {
348348
this.batchUpdate(); // prevent in between re-layout #1535 TODO: this only set float=true, need to prevent collision check...
349-
let elements: {el: HTMLElement; i: number}[] = [];
350-
let column = this.getColumn();
351-
if (column === 1 && this._prevColumn) column = this._prevColumn; // do 12 column when reading into 1 column mode
352-
this.getGridItems().forEach(el => { // get dom elements (not nodes yet)
353-
let x = parseInt(el.getAttribute('gs-x'));
354-
let y = parseInt(el.getAttribute('gs-y'));
355-
elements.push({
356-
el,
357-
// if x,y are missing (autoPosition) add them to end of list - but keep their respective DOM order
358-
i: (Number.isNaN(x) ? 1000 : x) + (Number.isNaN(y) ? 1000 : y) * column
359-
});
360-
});
361-
elements.sort((a, b) => b.i - a.i).forEach(e => this._prepareElement(e.el)); // revert sort so lowest item wins
349+
this.getGridItems().forEach(el => this._prepareElement(el));
362350
this.batchUpdate(false);
363351
}
364352

0 commit comments

Comments
 (0)