Skip to content

Commit 5bc3a42

Browse files
committed
collision: row / maxRow drag 2 grids
* fix #1687 * broken in 4.x - dragging between 2 grids with maxRow/row set * willItFit() could modify the passed in node (with new algorithm) instead of making a clone copy to check if it fits. * added a new vertical grid demo (which has known issues documented) * added unit test
1 parent 5a42d09 commit 5bc3a42

File tree

7 files changed

+62
-9
lines changed

7 files changed

+62
-9
lines changed

demo/index.html

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ <h1>Demos</h1>
2020
<li><a href="serialization.html">Serialization</a></li>
2121
<li><a href="static.html">Static</a></li>
2222
<li><a href="two.html">Two grids</a></li>
23+
<li><a href="two_vertical.html">Two grids Vertical</a></li>
2324
<li><a href="mobile.html">Mobile touch (JQ)</a></li>
2425
<li><a href="vue3js.html">Vue3.js</a></li>
2526
<li><a href="vue2js.html">Vue2.js</a></li>

demo/two_vertical.html

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
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>Two vertical grids demo</title>
8+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
9+
<link rel="stylesheet" href="demo.css"/>
10+
<script src="../dist/gridstack-h5.js"></script>
11+
</head>
12+
<body>
13+
<div class="container-fluid">
14+
<h1>Two vertical grids demo - with maxRow</h1>
15+
<p>special care is needed to prevent top grid from growing and causing shifts while you are dragging (which is a know issue).<br>
16+
You can either set a fix row, or have enough padding on a parent div to allow for an extra row to be created as needed), or....</p>
17+
<div class="grid-stack" id="grid1"></div>
18+
<br>
19+
<div class="grid-stack" id="grid2"></div>
20+
</div>
21+
<script src="events.js"></script>
22+
<script type="text/javascript">
23+
let opts = {
24+
row: 1, // set min and max row to freeze the height
25+
dragOut: true,
26+
acceptWidgets: true
27+
}
28+
GridStack.init(opts, document.getElementById('grid1'))
29+
.load([{x:0, y:0, content: '0'}, {x:1, y:0, content: '1'}]);
30+
GridStack.init(opts, document.getElementById('grid2'))
31+
.load([{x:0, y:0, content: '2'}, {x:2, y:0, content: '3'}]);
32+
</script>
33+
</body>
34+
</html>

doc/CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ Change log
5454
## 4.0.2-dev
5555

5656
- fix [#1693](https://github.com/gridstack/gridstack.js/issues/1693) `load` after `init()` broken in 4.x
57+
- fix [#1687](https://github.com/gridstack/gridstack.js/issues/1687) drag between 2 grids with `row / maxRow` broken in 4.x
5758

5859
## 4.0.2 (2021-3-27)
5960

spec/gridstack-spec.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { GridStack } from '../src/gridstack';
1+
import { GridStack, GridStackNode } from '../src/gridstack';
22
import { GridStackDD } from '../src/gridstack-dd'; // html5 vs Jquery set when including all file above
33
import { Utils } from '../src/utils';
44

@@ -585,6 +585,14 @@ describe('gridstack', function() {
585585
expect(grid.willItFit({x:0, y:0, w:12, h:1})).toBe(true);
586586
expect(grid.willItFit({x:0, y:0, w:12, h:2})).toBe(false);
587587
});
588+
it('willItFit() not modifying node #1687', function() {
589+
// default 4x2 and 4x4 so anything pushing more than 1 will fail
590+
let grid = GridStack.init({maxRow: 5});
591+
let node: GridStackNode = {x:0, y:0, w:1, h:1, _id: 1, _temporaryRemoved: true};
592+
expect(grid.willItFit(node)).toBe(true);
593+
expect(node._temporaryRemoved).toBe(true);
594+
expect(node._id).toBe(1);
595+
});
588596

589597
});
590598

src/gridstack-dd.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@ GridStack.prototype._setupAcceptWidget = function(): GridStack {
193193
// restore some internal fields we need after clearing them all
194194
node._initDD =
195195
node._isExternal = // DOM needs to be re-parented on a drop
196-
node._temporaryRemoved = true; // so it can be insert onDrag below
196+
node._temporaryRemoved = true; // so it can be inserted onDrag below
197197
} else {
198198
node.w = w; node.h = h;
199199
node._temporaryRemoved = true; // so we can insert it
@@ -512,7 +512,7 @@ GridStack.prototype._leave = function(node: GridStackNode, el: GridItemHTMLEleme
512512
if (node._temporaryRemoved) return;
513513
node._temporaryRemoved = true;
514514

515-
this.engine.removeNode(node); // remove placeholder as well
515+
this.engine.removeNode(node); // remove placeholder as well, otherwise it's a sign node is not in our list, which is a bigger issue
516516
node.el = node._isExternal && helper ? helper : el; // point back to real item being dragged
517517

518518
// finally if item originally came from another grid, but left us, restore things back to prev info

src/gridstack-engine.ts

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,10 @@ export class GridStackEngine {
473473
}
474474

475475
public removeNode(node: GridStackNode, removeDOM = true, triggerEvent = false): GridStackEngine {
476-
if (!this.nodes.find(n => n === node)) return; // not in our list
476+
if (!this.nodes.find(n => n === node)) {
477+
// TEST console.log(`Error: GridStackEngine.removeNode() node._id=${node._id} not found!`)
478+
return this;
479+
}
477480
if (triggerEvent) { // we wait until final drop to manually track removed items (rather than during drag)
478481
this.removedNodes.push(node);
479482
}
@@ -557,7 +560,8 @@ export class GridStackEngine {
557560
float: this.float,
558561
nodes: this.nodes.map(n => {return {...n}})
559562
});
560-
clone.addNode(node);
563+
let n = Utils.copyPos({}, node, true); // clone node so we don't mod any settings on it! #1687
564+
clone.addNode(n);
561565
return clone.getRow() <= this.maxRow;
562566
}
563567

@@ -612,7 +616,7 @@ export class GridStackEngine {
612616
if (typeof o.w !== 'number') { o.w = node.w; }
613617
if (typeof o.h !== 'number') { o.h = node.h; }
614618
let resizing = (node.w !== o.w || node.h !== o.h);
615-
let nn: GridStackNode = {maxW: node.maxW, maxH: node.maxH, minW: node.minW, minH: node.minH};
619+
let nn: GridStackNode = Utils.copyPos({}, node, true); // get min/max out first, then opt positions next
616620
Utils.copyPos(nn, o);
617621
nn = this.nodeBoundFix(nn, resizing);
618622
Utils.copyPos(o, nn);

src/utils.ts

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
* Copyright (c) 2021 Alain Dumesny - see GridStack root license
44
*/
55

6-
import { GridStackElement, GridStackNode, GridStackOptions, numberOrString, GridStackPosition } from './types';
6+
import { GridStackElement, GridStackNode, GridStackOptions, numberOrString, GridStackPosition, GridStackWidget } from './types';
77

88
export interface HeightData {
99
h: number;
@@ -219,12 +219,17 @@ export class Utils {
219219
return true;
220220
}
221221

222-
/* copies over b size & position */
223-
static copyPos(a: GridStackPosition, b: GridStackPosition): GridStackPosition {
222+
/* copies over b size & position (GridStackPosition), and possibly min/max as well */
223+
static copyPos(a: GridStackWidget, b: GridStackWidget, minMax = false): GridStackWidget {
224224
a.x = b.x;
225225
a.y = b.y;
226226
a.w = b.w;
227227
a.h = b.h;
228+
if (!minMax) return a;
229+
if (b.minW) a.minW = b.minW;
230+
if (b.minH) a.minH = b.minH;
231+
if (b.maxW) a.maxW = b.maxW;
232+
if (b.maxH) a.maxH = b.maxH;
228233
return a;
229234
}
230235

0 commit comments

Comments
 (0)