Skip to content

Commit 57c3762

Browse files
authored
Merge pull request #1509 from adumesny/develop
save() works on nested grids
2 parents cdd74dd + bda85c2 commit 57c3762

File tree

10 files changed

+177
-126
lines changed

10 files changed

+177
-126
lines changed

demo/nested.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,7 @@ <h1>Nested grids demo</h1>
2424
<a class="btn btn-primary" onClick="addNewWidget('.nested1')" href="#">Add Widget Grid1</a>
2525
<a class="btn btn-primary" onClick="addNewWidget('.nested2')" href="#">Add Widget Grid2</a>
2626
<br><br>
27-
28-
<div class="grid-stack"></div>
27+
<!-- grid will be added here -->
2928
</div>
3029

3130
<script type="text/javascript">
@@ -45,6 +44,7 @@ <h1>Nested grids demo</h1>
4544
{x:5, w:4, h:4, content: 'nested 2 - constrained to parent (default)', subGrid: {children: sub2, dragOut: false, class: 'nested2', ...subOptions}},
4645
]};
4746

47+
// create and load it all from JSON above
4848
GridStack.addGrid(document.querySelector('.container-fluid'), layout);
4949

5050
addNewWidget = function(selector) {

demo/serialization.html

Lines changed: 20 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,11 @@
1414
<h1>Serialization demo</h1>
1515
<a onClick="saveGrid()" class="btn btn-primary" href="#">Save</a>
1616
<a onClick="loadGrid()" class="btn btn-primary" href="#">Load</a>
17-
<a onClick="saveGridManual()" class="btn btn-primary" href="#">Save Manual</a>
18-
<a onClick="loadGridManual()" class="btn btn-primary" href="#">Load Manual</a>
17+
<a onClick="saveFullGrid()" class="btn btn-primary" href="#">Save Full</a>
18+
<a onClick="loadFullGrid()" class="btn btn-primary" href="#">Load Full</a>
1919
<a onClick="clearGrid()" class="btn btn-primary" href="#">Clear</a>
2020
<br/><br/>
21-
<div class="grid-stack"></div>
21+
<div id="gridCont"><div class="grid-stack"></div></div>
2222
<hr/>
2323
<textarea id="saved-data" cols="100" rows="20" readonly="readonly"></textarea>
2424
</div>
@@ -41,54 +41,33 @@ <h1>Serialization demo</h1>
4141
];
4242
serializedData.forEach((n, i) =>
4343
n.content = `<button onClick="grid.removeWidget(this.parentNode.parentNode)">X</button><br> ${i}<br> ${n.content ? n.content : ''}`);
44+
let serializedFull;
4445

45-
// NEW 2.x method
46+
// 2.x method - just saving list of widgets with content (default)
4647
loadGrid = function() {
47-
grid.load(serializedData, true);
48+
grid.load(serializedData, true); // update things
4849
}
4950

50-
// NEW 2.x method
51+
// 2.x method
5152
saveGrid = function() {
53+
delete serializedFull;
5254
serializedData = grid.save();
5355
document.querySelector('#saved-data').value = JSON.stringify(serializedData, null, ' ');
5456
}
5557

56-
// old (pre 2.x) way to manually load a grid
57-
loadGridManual = function() {
58-
let items = GridStack.Utils.sort(serializedData);
59-
grid.batchUpdate();
60-
61-
if (grid.engine.nodes.length === 0) {
62-
// load from empty
63-
items.forEach(function (item) {
64-
grid.addWidget('<div class="grid-stack-item"><div class="grid-stack-item-content">' + item.id + '</div></div>', item);
65-
});
66-
} else {
67-
// else update existing nodes (instead of calling grid.removeAll())
68-
grid.engine.nodes.forEach(function (node) {
69-
let item = items.find(function(e) { return e.id === node.id});
70-
grid.move(node.el, item.x, item.y, item.w, item.h);
71-
});
72-
}
73-
74-
grid.commit();
75-
};
58+
// 3.1 full method saving the grid options + children (which is recursive for nested grids)
59+
saveFullGrid = function() {
60+
serializedFull = grid.save(true, true);
61+
serializedData = serializedFull.children;
62+
document.querySelector('#saved-data').value = JSON.stringify(serializedFull, null, ' ');
63+
}
7664

77-
// old (pre 2.x) way to manually save a grid
78-
saveGridManual = function() {
79-
serializedData = [];
80-
grid.engine.nodes.forEach(function(node) {
81-
serializedData.push({
82-
x: node.x,
83-
y: node.y,
84-
w: node.w,
85-
h: node.h,
86-
id: node.id,
87-
custom: 'save anything here'
88-
});
89-
});
90-
document.querySelector('#saved-data').value = JSON.stringify(serializedData, null, ' ');
91-
};
65+
// 3.1 full method to reload from scratch - delete the grid and add it back from JSON
66+
loadFullGrid = function() {
67+
if (!serializedFull) return;
68+
grid.destroy(true); // nuke everything
69+
grid = GridStack.addGrid(document.querySelector('#gridCont'), serializedFull)
70+
}
9271

9372
clearGrid = function() {
9473
grid.removeAll();

doc/CHANGES.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,10 @@ Change log
4444

4545
## 3.3.0-dev
4646

47-
- add new `addGrid(parent, opts)` to create a grid and load children, which is used by `load()` to supports nested grids creation. see [nested.html](https://github.com/gridstack/gridstack.js/blob/develop/demo/nested.html) demo.
47+
- add new `addGrid(parent, opts)` to create a grid and load children instead of `init() + load()`, which is used by `load()` to supports nested grids creation.
48+
see [nested.html](https://github.com/gridstack/gridstack.js/blob/develop/demo/nested.html) demo.
49+
- `save()` will now work on nested grids, recursively saving info. added flag to also allow saving the current grid options + children
50+
(needed for nested grids) so you can now call new `adddGrid()` to re-create everything from JSON.
4851

4952
## 3.3.0 (2020-11-29)
5053

doc/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ gridstack.js API
2121
- [resizestart(event, el)](#resizestartevent-el)
2222
- [resizestop(event, el)](#resizestopevent-el)
2323
- [API](#api)
24+
- [addGrid(parent: HTMLElement, opt: GridStackOptions)](#addgridparent-htmlelement-opt-gridstackoptions)
2425
- [addWidget(el?: GridStackWidget | GridStackElement, options?: GridStackWidget)](#addwidgetel-gridstackwidget--gridstackelement-options-gridstackwidget)
2526
- [batchUpdate()](#batchupdate)
2627
- [compact()](#compact)
@@ -249,6 +250,11 @@ grid.on('resizestop', function(event: Event, el: GridItemHTMLElement) {
249250

250251
## API
251252

253+
### addGrid(parent: HTMLElement, opt: GridStackOptions)
254+
255+
create a grid under given parent, with given options and loading children recursively (for nested grids), instead of `init() + load()`. Used by `load()` to supports nested grids creation.
256+
see [nested.html](https://github.com/gridstack/gridstack.js/blob/develop/demo/nested.html) demo
257+
252258
### addWidget(el?: GridStackWidget | GridStackElement, options?: GridStackWidget)
253259

254260
Creates new widget and returns it. Options is an object containing the fields x,y,width,height,etc...

spec/gridstack-spec.ts

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,16 +1036,18 @@ describe('gridstack', function() {
10361036
document.body.insertAdjacentHTML('afterbegin', gridstackHTML);
10371037
});
10381038
afterEach(function() {
1039-
//document.body.removeChild(document.getElementsByClassName('grid-stack')[0]);
1039+
document.getElementById('gs-cont').remove();
10401040
});
10411041
it('should cleanup gridstack', function() {
10421042
let options = {
10431043
cellHeight: 80,
10441044
margin: 5
10451045
};
10461046
let grid = GridStack.init(options);
1047+
let gridEl = grid.el;
10471048
grid.destroy();
1048-
expect(grid.el.parentElement).toBe(null);
1049+
expect(gridEl.parentElement).toBe(null);
1050+
expect(grid.el).toBe(undefined);
10491051
expect(grid.engine).toBe(undefined);
10501052
});
10511053
it('should cleanup gridstack but leave elements', function() {
@@ -1054,11 +1056,13 @@ describe('gridstack', function() {
10541056
margin: 5
10551057
};
10561058
let grid = GridStack.init(options);
1059+
let gridEl = grid.el;
10571060
grid.destroy(false);
1058-
expect(grid.el.parentElement).not.toBe(null);
1061+
expect(gridEl.parentElement).not.toBe(null);
10591062
expect(Utils.getElements('.grid-stack-item').length).toBe(2);
1063+
expect(grid.el).toBe(undefined);
10601064
expect(grid.engine).toBe(undefined);
1061-
grid.destroy();
1065+
grid.destroy(); // sanity check for call twice!
10621066
});
10631067
});
10641068

@@ -1661,7 +1665,9 @@ describe('gridstack', function() {
16611665
document.body.insertAdjacentHTML('afterbegin', gridHTML);
16621666
});
16631667
afterEach(function() {
1664-
document.body.removeChild(document.getElementById('gs-cont'));
1668+
let els = document.body.querySelectorAll('.grid-stack');
1669+
expect(els.length).toBe(2);
1670+
els.forEach(g => g.remove());
16651671
});
16661672
it('should not remove incorrect child', function() {
16671673
let grids = GridStack.initAll();

spec/utils-spec.ts

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -111,18 +111,6 @@ describe('gridstack utils', function() {
111111
});
112112
});
113113

114-
describe('clone', function() {
115-
it('should match content', function() {
116-
let a = [1,2,3];
117-
let v1 = {one: 1, two: 'two', three: a};
118-
let v2: any = Utils.clone(v1);
119-
expect(v1 === v2).toBeFalse();
120-
expect(v1.one).toEqual(v2.one);
121-
expect(v1.two).toEqual(v2.two);
122-
expect(v1.three).toEqual(v2.three);
123-
});
124-
});
125-
126114
describe('removePositioningStyles', function() {
127115
it('should remove styles', function() {
128116
let doc = document.implementation.createHTMLDocument();

src/gridstack-engine.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -368,13 +368,13 @@ export class GridStackEngine {
368368
0,
369369
this.nodes.map(n => {
370370
if (n === node) {
371-
clonedNode = Utils.clone(n);
371+
clonedNode = {...n};
372372
return clonedNode;
373373
}
374-
return Utils.clone(n);
374+
return {...n};
375375
}));
376376

377-
if (!clonedNode) { return true;}
377+
if (!clonedNode) {return true}
378378

379379
clone.moveNode(clonedNode, x, y, w, h);
380380

@@ -401,7 +401,7 @@ export class GridStackEngine {
401401
null,
402402
this.float,
403403
0,
404-
this.nodes.map(n => Utils.clone(n)));
404+
this.nodes.map(n => {return {...n}}));
405405
clone.addNode(node);
406406
return clone.getRow() <= this.maxRow;
407407
}

0 commit comments

Comments
 (0)