Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 6b891e3

Browse files
committed
recreated grid trash issue
* fix gridstack#2453 * make sure _setupRemoveDrop() is static since it is a shared and not per grid * also bit more optimization during destroy()
1 parent 89a120b commit 6b891e3

File tree

3 files changed

+98
-21
lines changed

3 files changed

+98
-21
lines changed

doc/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -114,6 +114,8 @@ Change log
114114
* fix: [#2584](https://github.com/gridstack/gridstack.js/issues/2584) wrong sort order during 1 column resize - Thank you [JakubEleniuk](https://github.com/JakubEleniuk) again.
115115
* fix: [#2639](https://github.com/gridstack/gridstack.js/issues/2639) load() with mix of new item without coordinates
116116
* fix: [#2633](https://github.com/gridstack/gridstack.js/issues/2633) Drop into full grid causes crash
117+
* fix: [#2559](https://github.com/gridstack/gridstack.js/issues/2559) changed angular demos (support 1 column)
118+
* fix: [#2453](https://github.com/gridstack/gridstack.js/issues/2453) recreated grid trash issue
117119

118120
## 10.1.1 (2024-03-03)
119121
* fix: [#2620](https://github.com/gridstack/gridstack.js/pull/2620) allow resizing with sizeToContent:NUMBER is uses
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
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>#2453 Recreated trash</title>
8+
9+
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
10+
<link rel="stylesheet" href="../../../demo/demo.css" />
11+
<link rel="stylesheet" href="../../../dist/gridstack-extra.css" />
12+
<script src="../../../dist/gridstack-all.js"></script>
13+
<style type="text/css">
14+
.with-lines { border: 1px dotted #777}
15+
</style>
16+
</head>
17+
<body>
18+
<div class="container-fluid">
19+
<h1>#2453 Recreated grid trash bug</h1>
20+
21+
<div class="row">
22+
<div class="col-md-3">
23+
<div class="sidebar">
24+
<!-- will size to match content -->
25+
<div class="grid-stack-item">
26+
<div class="grid-stack-item-content">Drag me</div>
27+
</div>
28+
<!-- manually force a drop size of 2x1 -->
29+
<div class="grid-stack-item" gs-w="2" gs-h="1" gs-max-w="3">
30+
<div class="grid-stack-item-content">2x1, max=3</div>
31+
</div>
32+
</div>
33+
</div>
34+
<div class="col-md-9">
35+
<div class="trash" id="trash">
36+
</div>
37+
</div>
38+
</div>
39+
40+
<div class="row" style="margin-top: 20px">
41+
<div class="col-md-12">
42+
<a onClick="recreate()" class="btn btn-primary" href="#">Destroy(false)+init()</a>
43+
<div class="grid-stack" id="left_grid"></div>
44+
</div>
45+
</div>
46+
</div>
47+
<script src="events.js"></script>
48+
<script type="text/javascript">
49+
let items = [
50+
{x: 0, y: 0, w: 2, h: 2},
51+
{x: 3, y: 1, h: 2},
52+
{x: 4, y: 1},
53+
{x: 2, y: 3, w: 3, maxW: 3, id: 'special', content: 'has maxW=3'},
54+
{x: 2, y: 5}
55+
];
56+
57+
let options = {
58+
column: 6,
59+
minRow: 1, // don't collapse when empty
60+
cellHeight: 70,
61+
float: true,
62+
removable: '.trash', // true or drag-out delete class
63+
acceptWidgets: true
64+
};
65+
let grid = GridStack.init(options).load(items);
66+
67+
GridStack.setupDragIn('.sidebar .grid-stack-item', { appendTo: 'body', helper: 'clone' });
68+
69+
function recreate() {
70+
grid.destroy(false);
71+
grid = GridStack.init(options);
72+
}
73+
</script>
74+
</body>
75+
</html>

src/gridstack.ts

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -794,8 +794,8 @@ export class GridStack {
794794
delete this._ignoreLayoutsNodeChange;
795795
delete this._insertNotAppend;
796796
prevCB ? GridStack.addRemoveCB = prevCB : delete GridStack.addRemoveCB;
797-
// delay adding animation back
798-
if (noAnim && this.opts.animate) setTimeout(() => this.setAnimation(this.opts.animate));
797+
// delay adding animation back, but check to make sure grid (opt) is still around
798+
if (noAnim && this.opts?.animate) setTimeout(() => { if (this.opts) this.setAnimation(this.opts.animate) });
799799
return this;
800800
}
801801

@@ -1245,7 +1245,7 @@ export class GridStack {
12451245
GridStack.addRemoveCB(this.el, n, false, false);
12461246
}
12471247
delete n.el.gridstackNode;
1248-
this._removeDD(n.el);
1248+
if (!this.opts.staticGrid) this._removeDD(n.el);
12491249
});
12501250
this.engine.removeAll(removeDOM, triggerEvent);
12511251
if (triggerEvent) this._triggerRemoveEvent();
@@ -2190,7 +2190,7 @@ export class GridStack {
21902190
}
21912191

21922192
// clear any marked for complete removal (Note: don't check _isAboutToRemove as that is cleared above - just do it)
2193-
this._itemRemoving(node.el, false);
2193+
GridStack._itemRemoving(node.el, false);
21942194

21952195
dd.on(el, 'drag', onDrag);
21962196
// make sure this is called at least once when going fast #1578
@@ -2289,35 +2289,35 @@ export class GridStack {
22892289
this._gsEventHandler['dropped']({ ...event, type: 'dropped' }, origNode && origNode.grid ? origNode : undefined, node);
22902290
}
22912291

2292-
// delay adding animation back
2293-
if (noAnim) setTimeout(() => this.setAnimation(this.opts.animate));
2292+
// delay adding animation back, but check to make sure grid (opt) is still around
2293+
if (noAnim) setTimeout(() => { if (this.opts) this.setAnimation(this.opts.animate) });
22942294

22952295
return false; // prevent parent from receiving msg (which may be grid as well)
22962296
});
22972297
return this;
22982298
}
22992299

23002300
/** @internal mark item for removal */
2301-
private _itemRemoving(el: GridItemHTMLElement, remove: boolean) {
2302-
let node = el ? el.gridstackNode : undefined;
2303-
if (!node || !node.grid || el.classList.contains(this.opts.removableOptions.decline)) return;
2301+
private static _itemRemoving(el: GridItemHTMLElement, remove: boolean) {
2302+
const node = el ? el.gridstackNode : undefined;
2303+
if (!node?.grid || el.classList.contains(node.grid.opts.removableOptions.decline)) return;
23042304
remove ? node._isAboutToRemove = true : delete node._isAboutToRemove;
23052305
remove ? el.classList.add('grid-stack-item-removing') : el.classList.remove('grid-stack-item-removing');
23062306
}
23072307

23082308
/** @internal called to setup a trash drop zone if the user specifies it */
23092309
protected _setupRemoveDrop(): GridStack {
2310-
if (!this.opts.staticGrid && typeof this.opts.removable === 'string') {
2311-
let trashEl = document.querySelector(this.opts.removable) as HTMLElement;
2312-
if (!trashEl) return this;
2313-
// only register ONE drop-over/dropout callback for the 'trash', and it will
2314-
// update the passed in item and parent grid because the 'trash' is a shared resource anyway,
2315-
// and Native DD only has 1 event CB (having a list and technically a per grid removableOptions complicates things greatly)
2316-
if (!dd.isDroppable(trashEl)) {
2317-
dd.droppable(trashEl, this.opts.removableOptions)
2318-
.on(trashEl, 'dropover', (event, el) => this._itemRemoving(el, true))
2319-
.on(trashEl, 'dropout', (event, el) => this._itemRemoving(el, false));
2320-
}
2310+
if (typeof this.opts.removable !== 'string') return this;
2311+
let trashEl = document.querySelector(this.opts.removable) as HTMLElement;
2312+
if (!trashEl) return this;
2313+
2314+
// only register ONE static drop-over/dropout callback for the 'trash', and it will
2315+
// update the passed in item and parent grid because the '.trash' is a shared resource anyway,
2316+
// and Native DD only has 1 event CB (having a list and technically a per grid removableOptions complicates things greatly)
2317+
if (!this.opts.staticGrid && !dd.isDroppable(trashEl)) {
2318+
dd.droppable(trashEl, this.opts.removableOptions)
2319+
.on(trashEl, 'dropover', (event, el) => GridStack._itemRemoving(el, true))
2320+
.on(trashEl, 'dropout', (event, el) => GridStack._itemRemoving(el, false));
23212321
}
23222322
return this;
23232323
}
@@ -2592,7 +2592,7 @@ export class GridStack {
25922592

25932593
if (this.opts.removable === true) { // boolean vs a class string
25942594
// item leaving us and we are supposed to remove on leave (no need to drag onto trash) mark it so
2595-
this._itemRemoving(el, true);
2595+
GridStack._itemRemoving(el, true);
25962596
}
25972597

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

0 commit comments

Comments
 (0)