Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions demo/nested.html
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,7 @@ <h1>Nested grids demo</h1>
<a class="btn btn-primary" onClick="addNewWidget('.nested1')" href="#">Add Widget Grid1</a>
<a class="btn btn-primary" onClick="addNewWidget('.nested2')" href="#">Add Widget Grid2</a>
<br><br>

<div class="grid-stack"></div>
<!-- grid will be added here -->
</div>

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

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

addNewWidget = function(selector) {
Expand Down
61 changes: 20 additions & 41 deletions demo/serialization.html
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
<h1>Serialization demo</h1>
<a onClick="saveGrid()" class="btn btn-primary" href="#">Save</a>
<a onClick="loadGrid()" class="btn btn-primary" href="#">Load</a>
<a onClick="saveGridManual()" class="btn btn-primary" href="#">Save Manual</a>
<a onClick="loadGridManual()" class="btn btn-primary" href="#">Load Manual</a>
<a onClick="saveFullGrid()" class="btn btn-primary" href="#">Save Full</a>
<a onClick="loadFullGrid()" class="btn btn-primary" href="#">Load Full</a>
<a onClick="clearGrid()" class="btn btn-primary" href="#">Clear</a>
<br/><br/>
<div class="grid-stack"></div>
<div id="gridCont"><div class="grid-stack"></div></div>
<hr/>
<textarea id="saved-data" cols="100" rows="20" readonly="readonly"></textarea>
</div>
Expand All @@ -41,54 +41,33 @@ <h1>Serialization demo</h1>
];
serializedData.forEach((n, i) =>
n.content = `<button onClick="grid.removeWidget(this.parentNode.parentNode)">X</button><br> ${i}<br> ${n.content ? n.content : ''}`);
let serializedFull;

// NEW 2.x method
// 2.x method - just saving list of widgets with content (default)
loadGrid = function() {
grid.load(serializedData, true);
grid.load(serializedData, true); // update things
}

// NEW 2.x method
// 2.x method
saveGrid = function() {
delete serializedFull;
serializedData = grid.save();
document.querySelector('#saved-data').value = JSON.stringify(serializedData, null, ' ');
}

// old (pre 2.x) way to manually load a grid
loadGridManual = function() {
let items = GridStack.Utils.sort(serializedData);
grid.batchUpdate();

if (grid.engine.nodes.length === 0) {
// load from empty
items.forEach(function (item) {
grid.addWidget('<div class="grid-stack-item"><div class="grid-stack-item-content">' + item.id + '</div></div>', item);
});
} else {
// else update existing nodes (instead of calling grid.removeAll())
grid.engine.nodes.forEach(function (node) {
let item = items.find(function(e) { return e.id === node.id});
grid.move(node.el, item.x, item.y, item.w, item.h);
});
}

grid.commit();
};
// 3.1 full method saving the grid options + children (which is recursive for nested grids)
saveFullGrid = function() {
serializedFull = grid.save(true, true);
serializedData = serializedFull.children;
document.querySelector('#saved-data').value = JSON.stringify(serializedFull, null, ' ');
}

// old (pre 2.x) way to manually save a grid
saveGridManual = function() {
serializedData = [];
grid.engine.nodes.forEach(function(node) {
serializedData.push({
x: node.x,
y: node.y,
w: node.w,
h: node.h,
id: node.id,
custom: 'save anything here'
});
});
document.querySelector('#saved-data').value = JSON.stringify(serializedData, null, ' ');
};
// 3.1 full method to reload from scratch - delete the grid and add it back from JSON
loadFullGrid = function() {
if (!serializedFull) return;
grid.destroy(true); // nuke everything
grid = GridStack.addGrid(document.querySelector('#gridCont'), serializedFull)
}

clearGrid = function() {
grid.removeAll();
Expand Down
5 changes: 4 additions & 1 deletion doc/CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,10 @@ Change log

## 3.3.0-dev

- 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.
- 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.
see [nested.html](https://github.com/gridstack/gridstack.js/blob/develop/demo/nested.html) demo.
- `save()` will now work on nested grids, recursively saving info. added flag to also allow saving the current grid options + children
(needed for nested grids) so you can now call new `adddGrid()` to re-create everything from JSON.

## 3.3.0 (2020-11-29)

Expand Down
6 changes: 6 additions & 0 deletions doc/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ gridstack.js API
- [resizestart(event, el)](#resizestartevent-el)
- [resizestop(event, el)](#resizestopevent-el)
- [API](#api)
- [addGrid(parent: HTMLElement, opt: GridStackOptions)](#addgridparent-htmlelement-opt-gridstackoptions)
- [addWidget(el?: GridStackWidget | GridStackElement, options?: GridStackWidget)](#addwidgetel-gridstackwidget--gridstackelement-options-gridstackwidget)
- [batchUpdate()](#batchupdate)
- [compact()](#compact)
Expand Down Expand Up @@ -249,6 +250,11 @@ grid.on('resizestop', function(event: Event, el: GridItemHTMLElement) {

## API

### addGrid(parent: HTMLElement, opt: GridStackOptions)

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.
see [nested.html](https://github.com/gridstack/gridstack.js/blob/develop/demo/nested.html) demo

### addWidget(el?: GridStackWidget | GridStackElement, options?: GridStackWidget)

Creates new widget and returns it. Options is an object containing the fields x,y,width,height,etc...
Expand Down
16 changes: 11 additions & 5 deletions spec/gridstack-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1036,16 +1036,18 @@ describe('gridstack', function() {
document.body.insertAdjacentHTML('afterbegin', gridstackHTML);
});
afterEach(function() {
//document.body.removeChild(document.getElementsByClassName('grid-stack')[0]);
document.getElementById('gs-cont').remove();
});
it('should cleanup gridstack', function() {
let options = {
cellHeight: 80,
margin: 5
};
let grid = GridStack.init(options);
let gridEl = grid.el;
grid.destroy();
expect(grid.el.parentElement).toBe(null);
expect(gridEl.parentElement).toBe(null);
expect(grid.el).toBe(undefined);
expect(grid.engine).toBe(undefined);
});
it('should cleanup gridstack but leave elements', function() {
Expand All @@ -1054,11 +1056,13 @@ describe('gridstack', function() {
margin: 5
};
let grid = GridStack.init(options);
let gridEl = grid.el;
grid.destroy(false);
expect(grid.el.parentElement).not.toBe(null);
expect(gridEl.parentElement).not.toBe(null);
expect(Utils.getElements('.grid-stack-item').length).toBe(2);
expect(grid.el).toBe(undefined);
expect(grid.engine).toBe(undefined);
grid.destroy();
grid.destroy(); // sanity check for call twice!
});
});

Expand Down Expand Up @@ -1661,7 +1665,9 @@ describe('gridstack', function() {
document.body.insertAdjacentHTML('afterbegin', gridHTML);
});
afterEach(function() {
document.body.removeChild(document.getElementById('gs-cont'));
let els = document.body.querySelectorAll('.grid-stack');
expect(els.length).toBe(2);
els.forEach(g => g.remove());
});
it('should not remove incorrect child', function() {
let grids = GridStack.initAll();
Expand Down
12 changes: 0 additions & 12 deletions spec/utils-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -111,18 +111,6 @@ describe('gridstack utils', function() {
});
});

describe('clone', function() {
it('should match content', function() {
let a = [1,2,3];
let v1 = {one: 1, two: 'two', three: a};
let v2: any = Utils.clone(v1);
expect(v1 === v2).toBeFalse();
expect(v1.one).toEqual(v2.one);
expect(v1.two).toEqual(v2.two);
expect(v1.three).toEqual(v2.three);
});
});

describe('removePositioningStyles', function() {
it('should remove styles', function() {
let doc = document.implementation.createHTMLDocument();
Expand Down
8 changes: 4 additions & 4 deletions src/gridstack-engine.ts
Original file line number Diff line number Diff line change
Expand Up @@ -368,13 +368,13 @@ export class GridStackEngine {
0,
this.nodes.map(n => {
if (n === node) {
clonedNode = Utils.clone(n);
clonedNode = {...n};
return clonedNode;
}
return Utils.clone(n);
return {...n};
}));

if (!clonedNode) { return true;}
if (!clonedNode) {return true}

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

Expand All @@ -401,7 +401,7 @@ export class GridStackEngine {
null,
this.float,
0,
this.nodes.map(n => Utils.clone(n)));
this.nodes.map(n => {return {...n}}));
clone.addNode(node);
return clone.getRow() <= this.maxRow;
}
Expand Down
Loading