Skip to content

Commit 443905d

Browse files
committed
update(el, opts) re-write to take all options
* fix #1235 * `update(el, opts)` re-write to take all `GridStackWidget` options (not just x,y,width,height) and do everything efficiently. * Fixed `locked()`, `move()`, `resize()`, `minWidth()`,etc... to call update() instead which does all the constrain, not just update attributes! * update spec to test, and serialize demo to show improved feature * OLD api to pass 4 params will work for now (console warning)
1 parent 1a0ba3f commit 443905d

File tree

5 files changed

+219
-155
lines changed

5 files changed

+219
-155
lines changed

demo/serialization.html

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,14 @@ <h1>Serialization demo</h1>
3333
});
3434

3535
let serializedData = [
36-
{x: 0, y: 0, width: 2, height: 2, id: '0', content: "big 2x2"},
36+
{x: 0, y: 0, width: 2, height: 2, id: '0'},
3737
{x: 3, y: 1, width: 1, height: 2, id: '1', content: "<button onclick=\"alert('clicked!')\">Press me</button>"},
3838
{x: 4, y: 1, width: 1, height: 1, id: '2'},
3939
{x: 2, y: 3, width: 3, height: 1, id: '3'},
4040
{x: 1, y: 3, width: 1, height: 1, id: '4'}
4141
];
42+
serializedData.forEach((n, i) =>
43+
n.content = `<button onClick="grid.removeWidget(this.parentNode.parentNode)">X</button><br> ${i}<br> ${n.content ? n.content : ''}`);
4244

4345
// NEW 2.x method
4446
loadGrid = function() {
@@ -65,7 +67,7 @@ <h1>Serialization demo</h1>
6567
// else update existing nodes (instead of calling grid.removeAll())
6668
grid.engine.nodes.forEach(function (node) {
6769
let item = items.find(function(e) { return e.id === node.id});
68-
grid.update(node.el, item.x, item.y, item.width, item.height);
70+
grid.move(node.el, item.x, item.y, item.width, item.height);
6971
});
7072
}
7173

doc/CHANGES.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,8 @@ Change log
4747
- fix placeholder not having custom `GridStackOptions.itemClass`. thanks [@pablosichert](https://github.com/pablosichert)
4848
- fix [1484](https://github.com/gridstack/gridstack.js/issues/1484) dragging between 2 grids and back (regression in 2.0.1)
4949
- fix [1471](https://github.com/gridstack/gridstack.js/issues/1471) `load()` into 1 column mode doesn't resize back to 12 correctly
50+
- fix [1235](https://github.com/gridstack/gridstack.js/issues/1235) `update(el, opts)` re-write to take all `GridStackWidget` options (not just x,y,width,height) and do everything efficiently.
51+
Fixed `locked()`, `move()`, `resize()`, `minWidth()`,etc... to call update() instead which does all the constrain, not just update attributes!
5052
- del `ddPlugin` grid option as we only have one drag&drop plugin at runtime, which is defined by the include you use (HTML5 vs jquery vs none)
5153

5254
## 2.2.0 (2020-11-7)

spec/gridstack-spec.ts

Lines changed: 99 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import { GridStack } from '../src/gridstack';
2-
import { GridStackDD } from '../src/gridstack-dd';
2+
import { GridStackDD } from '../src/gridstack-dd'; // html5 vs Jquery set when including all file above
33
import { Utils } from '../src/utils';
44

55
describe('gridstack', function() {
@@ -8,10 +8,10 @@ describe('gridstack', function() {
88
// grid has 4x2 and 4x4 top-left aligned - used on most test cases
99
let gridHTML =
1010
'<div class="grid-stack">' +
11-
' <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2" data-gs-id="item1" id="item1">' +
11+
' <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2" data-gs-id="gsItem1" id="item1">' +
1212
' <div class="grid-stack-item-content">item 1 text</div>' +
1313
' </div>' +
14-
' <div class="grid-stack-item" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="4" data-gs-id="item2" id="item2">' +
14+
' <div class="grid-stack-item" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="4" data-gs-id="gsItem2" id="item2">' +
1515
' <div class="grid-stack-item-content">item 2 text</div>' +
1616
' </div>' +
1717
'</div>';
@@ -1103,56 +1103,104 @@ describe('gridstack', function() {
11031103
});
11041104
});
11051105

1106-
describe('grid.moveNode', function() {
1106+
describe('grid.update', function() {
11071107
beforeEach(function() {
11081108
document.body.insertAdjacentHTML('afterbegin', gridstackHTML);
11091109
});
11101110
afterEach(function() {
11111111
document.body.removeChild(document.getElementById('gs-cont'));
11121112
});
1113-
it('should do nothing and return NULL to mean nothing happened', function() {
1114-
let grid:any = GridStack.init();
1115-
let items = Utils.getElements('.grid-stack-item');
1116-
grid._updateElement(items[0], function(el, node) {
1117-
let hasMoved = grid.engine.moveNode(node);
1118-
expect(hasMoved).toBe(null);
1119-
});
1113+
it('should move and resize widget', function() {
1114+
let grid = GridStack.init({float: true});
1115+
let el = Utils.getElements('.grid-stack-item')[1];
1116+
expect(parseInt(el.getAttribute('data-gs-width'), 10)).toBe(4);
1117+
1118+
grid.update(el, {x: 5, y: 4, height: 2});
1119+
expect(parseInt(el.getAttribute('data-gs-x'), 10)).toBe(5);
1120+
expect(parseInt(el.getAttribute('data-gs-y'), 10)).toBe(4);
1121+
expect(parseInt(el.getAttribute('data-gs-width'), 10)).toBe(4);
1122+
expect(parseInt(el.getAttribute('data-gs-height'), 10)).toBe(2);
11201123
});
1121-
it('should do nothing and return node', function() {
1122-
let grid: any = GridStack.init();
1124+
it('should change noMove', function() {
1125+
let grid = GridStack.init({float: true});
11231126
let items = Utils.getElements('.grid-stack-item');
1124-
grid.minWidth(items[0], 1);
1125-
grid.maxWidth(items[0], 2);
1126-
grid.minHeight(items[0], 1);
1127-
grid.maxHeight(items[0], 2);
1128-
grid._updateElement(items[0], function(el, node) {
1129-
let newNode = grid.engine.moveNode(node);
1130-
expect(newNode).toBe(node);
1131-
});
1132-
});
1133-
});
1127+
let el = items[1];
1128+
let dd = GridStackDD.get();
1129+
1130+
grid.update(el, {noMove: true, noResize: false});
1131+
expect(el.getAttribute('data-gs-no-move')).toBe('true');
1132+
expect(el.getAttribute('data-gs-no-resize')).toBe(null); // false is no-op
1133+
expect(dd.isResizable(el)).toBe(true);
1134+
expect(dd.isDraggable(el)).toBe(false);
1135+
expect(dd.isResizable(items[0])).toBe(true);
1136+
expect(dd.isDraggable(items[0])).toBe(true);
1137+
1138+
expect(parseInt(el.getAttribute('data-gs-x'), 10)).toBe(4);
1139+
expect(parseInt(el.getAttribute('data-gs-y'), 10)).toBe(0);
1140+
expect(parseInt(el.getAttribute('data-gs-width'), 10)).toBe(4);
1141+
expect(parseInt(el.getAttribute('data-gs-height'), 10)).toBe(4);
1142+
});
1143+
it('should change content and id, and move', function() {
1144+
let grid = GridStack.init({float: true});
1145+
let items = Utils.getElements('.grid-stack-item');
1146+
let el = items[1];
1147+
let sub = el.querySelector('.grid-stack-item-content');
1148+
1149+
grid.update(el, {id: 'newID', y: 1, content: 'new content'});
1150+
expect(el.getAttribute('data-gs-id')).toBe('newID');
1151+
expect(sub.innerHTML).toBe('new content');
1152+
expect(parseInt(el.getAttribute('data-gs-x'), 10)).toBe(4);
1153+
expect(parseInt(el.getAttribute('data-gs-y'), 10)).toBe(1);
1154+
expect(parseInt(el.getAttribute('data-gs-width'), 10)).toBe(4);
1155+
expect(parseInt(el.getAttribute('data-gs-height'), 10)).toBe(4);
1156+
});
1157+
it('should change max and constrain a wanted resize', function() {
1158+
let grid = GridStack.init({float: true});
1159+
let items = Utils.getElements('.grid-stack-item');
1160+
let el = items[1];
1161+
expect(el.getAttribute('data-gs-max-width')).toBe(null);
11341162

1135-
describe('grid.update', function() {
1136-
beforeEach(function() {
1137-
document.body.insertAdjacentHTML('afterbegin', gridstackHTML);
1163+
grid.update(el, {maxWidth: 2, width: 5});
1164+
expect(parseInt(el.getAttribute('data-gs-x'), 10)).toBe(4);
1165+
expect(parseInt(el.getAttribute('data-gs-y'), 10)).toBe(0);
1166+
expect(parseInt(el.getAttribute('data-gs-width'), 10)).toBe(2);
1167+
expect(parseInt(el.getAttribute('data-gs-height'), 10)).toBe(4);
1168+
expect(parseInt(el.getAttribute('data-gs-max-width'), 10)).toBe(2);
11381169
});
1139-
afterEach(function() {
1140-
document.body.removeChild(document.getElementById('gs-cont'));
1170+
it('should change max and constrain existing', function() {
1171+
let grid = GridStack.init({float: true});
1172+
let items = Utils.getElements('.grid-stack-item');
1173+
let el = items[1];
1174+
expect(el.getAttribute('data-gs-max-width')).toBe(null);
1175+
1176+
grid.update(el, {maxWidth: 2});
1177+
expect(parseInt(el.getAttribute('data-gs-x'), 10)).toBe(4);
1178+
expect(parseInt(el.getAttribute('data-gs-y'), 10)).toBe(0);
1179+
expect(parseInt(el.getAttribute('data-gs-height'), 10)).toBe(4);
1180+
expect(parseInt(el.getAttribute('data-gs-max-width'), 10)).toBe(2);
1181+
expect(parseInt(el.getAttribute('data-gs-width'), 10)).toBe(2);
11411182
});
1142-
it('should move and resize widget', function() {
1143-
let options = {
1144-
cellHeight: 80,
1145-
margin: 5,
1146-
float: true
1147-
};
1148-
let grid = GridStack.init(options);
1183+
it('should change all max and move', function() {
1184+
let grid = GridStack.init({float: true});
11491185
let items = Utils.getElements('.grid-stack-item');
1150-
grid.update(items[0], 5, 5, 5 ,5);
1151-
expect(parseInt(items[0].getAttribute('data-gs-width'), 10)).toBe(5);
1152-
expect(parseInt(items[0].getAttribute('data-gs-height'), 10)).toBe(5);
1153-
expect(parseInt(items[0].getAttribute('data-gs-x'), 10)).toBe(5);
1154-
expect(parseInt(items[0].getAttribute('data-gs-y'), 10)).toBe(5);
1186+
1187+
items.forEach(item => {
1188+
expect(item.getAttribute('data-gs-max-width')).toBe(null);
1189+
expect(item.getAttribute('data-gs-max-height')).toBe(null);
1190+
});
1191+
1192+
grid.update('.grid-stack-item', {maxWidth: 2, maxHeight: 2});
1193+
expect(parseInt(items[0].getAttribute('data-gs-x'), 10)).toBe(0);
1194+
expect(parseInt(items[1].getAttribute('data-gs-x'), 10)).toBe(4);
1195+
items.forEach(item => {
1196+
expect(parseInt(item.getAttribute('data-gs-y'), 10)).toBe(0);
1197+
expect(parseInt(item.getAttribute('data-gs-height'), 10)).toBe(2);
1198+
expect(parseInt(item.getAttribute('data-gs-width'), 10)).toBe(2);
1199+
expect(parseInt(item.getAttribute('data-gs-max-width'), 10)).toBe(2);
1200+
expect(parseInt(item.getAttribute('data-gs-max-height'), 10)).toBe(2);
1201+
});
11551202
});
1203+
11561204
});
11571205

11581206
describe('grid.margin', function() {
@@ -1679,35 +1727,35 @@ describe('gridstack', function() {
16791727
it('save layout', function() {
16801728
let grid = GridStack.init();
16811729
let layout = grid.save(false);
1682-
expect(layout).toEqual([{x:0, y:0, width:4, height:2, id:'item1'}, {x:4, y:0, width:4, height:4, id:'item2'}]);
1730+
expect(layout).toEqual([{x:0, y:0, width:4, height:2, id:'gsItem1'}, {x:4, y:0, width:4, height:4, id:'gsItem2'}]);
16831731
layout = grid.save();
1684-
expect(layout).toEqual([{x:0, y:0, width:4, height:2, id:'item1', content:'item 1 text'}, {x:4, y:0, width:4, height:4, id:'item2', content:'item 2 text'}]);
1732+
expect(layout).toEqual([{x:0, y:0, width:4, height:2, id:'gsItem1', content:'item 1 text'}, {x:4, y:0, width:4, height:4, id:'gsItem2', content:'item 2 text'}]);
16851733
layout = grid.save(true);
1686-
expect(layout).toEqual([{x:0, y:0, width:4, height:2, id:'item1', content:'item 1 text'}, {x:4, y:0, width:4, height:4, id:'item2', content:'item 2 text'}]);
1734+
expect(layout).toEqual([{x:0, y:0, width:4, height:2, id:'gsItem1', content:'item 1 text'}, {x:4, y:0, width:4, height:4, id:'gsItem2', content:'item 2 text'}]);
16871735
});
16881736
it('load move 1 item, delete others', function() {
16891737
let grid = GridStack.init();
1690-
grid.load([{x:2, height:1, id:'item2'}]);
1738+
grid.load([{x:2, height:1, id:'gsItem2'}]);
16911739
let layout = grid.save(false);
1692-
expect(layout).toEqual([{x:2, y:0, width:4, height:1, id:'item2'}]);
1740+
expect(layout).toEqual([{x:2, y:0, width:4, height:1, id:'gsItem2'}]);
16931741
});
16941742
it('load add new, delete others', function() {
16951743
let grid = GridStack.init();
1696-
grid.load([{width:2, height:1, id:'item3'}], true);
1744+
grid.load([{width:2, height:1, id:'gsItem3'}], true);
16971745
let layout = grid.save(false);
1698-
expect(layout).toEqual([{x:0, y:0, width:2, height:1, id:'item3'}]);
1746+
expect(layout).toEqual([{x:0, y:0, width:2, height:1, id:'gsItem3'}]);
16991747
});
17001748
it('load size 1 item only', function() {
17011749
let grid = GridStack.init();
1702-
grid.load([{height:3, id:'item1'}], false);
1750+
grid.load([{height:3, id:'gsItem1'}], false);
17031751
let layout = grid.save(false);
1704-
expect(layout).toEqual([{x:0, y:0, width:4, height:3, id:'item1'}, {x:4, y:0, width:4, height:4, id:'item2'}]);
1752+
expect(layout).toEqual([{x:0, y:0, width:4, height:3, id:'gsItem1'}, {x:4, y:0, width:4, height:4, id:'gsItem2'}]);
17051753
});
17061754
it('load size 1 item only with callback', function() {
17071755
let grid = GridStack.init();
1708-
grid.load([{height:3, id:'item1'}], () => {});
1756+
grid.load([{height:3, id:'gsItem1'}], () => {});
17091757
let layout = grid.save(false);
1710-
expect(layout).toEqual([{x:0, y:0, width:4, height:3, id:'item1'}, {x:4, y:0, width:4, height:4, id:'item2'}]);
1758+
expect(layout).toEqual([{x:0, y:0, width:4, height:3, id:'gsItem1'}, {x:4, y:0, width:4, height:4, id:'gsItem2'}]);
17111759
});
17121760
});
17131761

src/gridstack-dd.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,8 @@ GridStack.prototype._setupDragIn = function(): GridStack {
299299

300300
/** @internal prepares the element for drag&drop **/
301301
GridStack.prototype._prepareDragDropByNode = function(node: GridStackNode): GridStack {
302+
let el = node.el;
303+
302304
// check for disabled grid first
303305
if (this.opts.staticGrid || node.locked ||
304306
((node.noMove || this.opts.disableDrag) && (node.noResize || this.opts.disableResize))) {
@@ -311,6 +313,13 @@ GridStack.prototype._prepareDragDropByNode = function(node: GridStackNode): Grid
311313
}
312314
// check if init already done
313315
if (node._initDD) {
316+
// fine tune drag vs move by disabling any part...
317+
if (node.noMove || this.opts.disableDrag) {
318+
GridStackDD.get().draggable(el, 'disable');
319+
}
320+
if (node.noResize || this.opts.disableResize) {
321+
GridStackDD.get().resizable(el, 'disable');
322+
}
314323
return this;
315324
}
316325

@@ -320,7 +329,6 @@ GridStack.prototype._prepareDragDropByNode = function(node: GridStackNode): Grid
320329
// variables used/cashed between the 3 start/move/end methods, in addition to node passed above
321330
let cellWidth: number;
322331
let cellHeight: number;
323-
let el = node.el;
324332

325333
/** called when item starts moving/resizing */
326334
let onStartMoving = (event: Event, ui: DDUIData): void => {

0 commit comments

Comments
 (0)