diff --git a/demo/column.html b/demo/column.html
index 40c6f5c2f..01448f335 100644
--- a/demo/column.html
+++ b/demo/column.html
@@ -53,6 +53,11 @@
setColumn() grid demo
}
var items = [
+ /* match karma testing
+ {x: 0, y: 0, width: 4, height: 2},
+ {x: 4, y: 0, width: 4, height: 4},
+ {text: ' auto'},
+ */
{x: 0, y: 0, width: 2, height: 2},
{x: 2, y: 0, width: 2, height: 1},
{x: 5, y: 1, width: 1, height: 1},
@@ -63,22 +68,21 @@ setColumn() grid demo
];
var count = 0;
grid.batchUpdate();
- for (count=0; count<4;) {
- var n = items[count];
- grid.addWidget($('' + count++ + (n.text ? n.text : '') + '
'), n);
- };
+ addWidget(); addWidget(); addWidget(); addWidget();
grid.commit();
- $('#add-widget').click(function() {
+ function addWidget() {
var n = items[count] || {
x: Math.round(12 * Math.random()),
y: Math.round(5 * Math.random()),
width: Math.round(1 + 3 * Math.random()),
height: Math.round(1 + 3 * Math.random())
};
- grid.addWidget($('' + count++ + (n.text ? n.text : '') + '
'), n);
- });
+ grid.addWidget($('
'
+ + count++ + (n.text ? n.text : '') + '
'), n);
+ };
+ $('#add-widget').click(function() { addWidget() });
$('#1column').click(function() { delete grid.opts.oneColumnModeDomSort; grid.setColumn(1); $text.text(1);});
$('#1columnDOM').click(function() { grid.opts.oneColumnModeDomSort = true; grid.setColumn(1); $text.text('1 DOM');});
$('#2column').click(function() { grid.setColumn(2); $text.text(2);});
diff --git a/doc/CHANGES.md b/doc/CHANGES.md
index 0d27e40f4..113707bb3 100644
--- a/doc/CHANGES.md
+++ b/doc/CHANGES.md
@@ -31,6 +31,8 @@ Change log
- add `oneColumnModeDomSort` true|false to let you specify a custom layout (use dom order instead of x,y) for oneColumnMode `setColumn(1)` [#713](https://github.com/gridstack/gridstack.js/issues/713)
- fix oneColumnMode to only restore if we auto went to it as window sizes up [#1125](https://github.com/gridstack/gridstack.js/pull/1125)
+- editing in 1 column (or few columns) does a better job updating higher layout (track before and after and move items accordingly).
+Tracking item swap would be even better still. [#1127](https://github.com/gridstack/gridstack.js/pull/1127)
## v0.6.1 (2020-02-02)
diff --git a/spec/gridstack-spec.js b/spec/gridstack-spec.js
index 19170776f..6f317278e 100644
--- a/spec/gridstack-spec.js
+++ b/spec/gridstack-spec.js
@@ -383,7 +383,7 @@ describe('gridstack', function() {
expect(parseInt(el2.attr('data-gs-height'))).toBe(4);
expect(parseInt(el3.attr('data-gs-x'))).toBe(0);
- expect(parseInt(el3.attr('data-gs-y'))).toBe(6);
+ expect(parseInt(el3.attr('data-gs-y'))).toBe(6); // ??? keep same row, but might more intuitive higher
expect(parseInt(el3.attr('data-gs-width'))).toBe(1); // ??? could take entire width if it did above
expect(parseInt(el3.attr('data-gs-height'))).toBe(1);
@@ -397,6 +397,7 @@ describe('gridstack', function() {
expect(parseInt(el3.attr('data-gs-width'))).toBe(1);
expect(parseInt(el3.attr('data-gs-height'))).toBe(1);
+ expect(parseInt(el1.attr('data-gs-x'))).toBe(0);
expect(parseInt(el1.attr('data-gs-y'))).toBe(1);
expect(parseInt(el1.attr('data-gs-width'))).toBe(1);
expect(parseInt(el1.attr('data-gs-height'))).toBe(2);
@@ -420,8 +421,8 @@ describe('gridstack', function() {
expect(parseInt(el1.attr('data-gs-width'))).toBe(4);
expect(parseInt(el1.attr('data-gs-height'))).toBe(2);
- expect(parseInt(el2.attr('data-gs-x'))).toBe(0);
- expect(parseInt(el2.attr('data-gs-y'))).toBe(3);
+ expect(parseInt(el2.attr('data-gs-x'))).toBe(4);
+ expect(parseInt(el2.attr('data-gs-y'))).toBe(1);
expect(parseInt(el2.attr('data-gs-width'))).toBe(4);
expect(parseInt(el2.attr('data-gs-height'))).toBe(4);
@@ -440,8 +441,8 @@ describe('gridstack', function() {
expect(parseInt(el1.attr('data-gs-width'))).toBe(1);
expect(parseInt(el1.attr('data-gs-height'))).toBe(2);
- expect(parseInt(el2.attr('data-gs-x'))).toBe(0);
- expect(parseInt(el2.attr('data-gs-y'))).toBe(3);
+ expect(parseInt(el2.attr('data-gs-x'))).toBe(1);
+ expect(parseInt(el2.attr('data-gs-y'))).toBe(1);
expect(parseInt(el2.attr('data-gs-width'))).toBe(1);
expect(parseInt(el2.attr('data-gs-height'))).toBe(4);
});
diff --git a/src/gridstack.js b/src/gridstack.js
index 1e06a8aff..88cef7bf1 100644
--- a/src/gridstack.js
+++ b/src/gridstack.js
@@ -355,12 +355,12 @@
if (this.float) {
this.nodes.forEach(function(n, i) {
- if (n._updating || n._origY === undefined || n.y === n._origY) {
+ if (n._updating || n._packY === undefined || n.y === n._packY) {
return;
}
var newY = n.y;
- while (newY >= n._origY) {
+ while (newY >= n._packY) {
var collisionNode = this.nodes
.slice(0, i)
.find(Utils._didCollide, {n: n, newY: newY});
@@ -653,14 +653,14 @@
GridStackEngine.prototype.beginUpdate = function(node) {
if (node._updating) return;
node._updating = true;
- this.nodes.forEach(function(n) { n._origY = n.y; });
+ this.nodes.forEach(function(n) { n._packY = n.y; });
};
GridStackEngine.prototype.endUpdate = function() {
var n = this.nodes.find(function(n) { return n._updating; });
if (n) {
n._updating = false;
- this.nodes.forEach(function(n) { delete n._origY; });
+ this.nodes.forEach(function(n) { delete n._packY; });
}
};
@@ -1801,23 +1801,37 @@
GridStackEngine.prototype._layoutsNodesChange = function(nodes) {
if (!this._layouts || this._ignoreLayoutsNodeChange) return;
// remove smaller layouts - we will re-generate those on the fly... larger ones need to update
- this._layouts.forEach(function(layout, i) {
- if (!layout || i === this.column) return;
- if (i < this.column) {
- this._layouts[i] = undefined;
+ this._layouts.forEach(function(layout, column) {
+ if (!layout || column === this.column) return;
+ if (column < this.column) {
+ this._layouts[column] = undefined;
}
else {
- // TODO: save the original x,y,w (h isn't cached) and see what actually changed to propagate correctly ?
+ // we save the original x,y,w (h isn't cached) to see what actually changed to propagate better.
+ // Note: we don't need to check against out of bound scaling/moving as that will be done when using those cache values.
nodes.forEach(function(node) {
var n = layout.find(function(l) { return l._id === node._id });
- if (!n) return;
- var ratio = i / this.column;
- n.y = node.y;
- n.x = Math.round(node.x * ratio);
- // width ???
+ if (!n) return; // no cache for new nodes. Will use those values.
+ var ratio = column / this.column;
+ // Y changed, push down same amount
+ // TODO: detect doing item 'swaps' will help instead of move (especially in 1 column mode)
+ if (node.y !== node._origY) {
+ n.y += (node.y - node._origY);
+ }
+ // X changed, scale from new position
+ if (node.x !== node._origX) {
+ n.x = Math.round(node.x * ratio);
+ }
+ // width changed, scale from new width
+ if (node.width !== node._origW) {
+ n.width = Math.round(node.width * ratio);
+ }
+ // ...height always carries over from cache
}, this);
}
}, this);
+
+ this._saveInitial(); // reset current value now that we diffed.
}
/**
@@ -1906,6 +1920,19 @@
}, this);
this.commit();
delete this._ignoreLayoutsNodeChange;
+
+ // save this initial layout so we can see what changed and apply changes to other layouts better (diff)
+ this._saveInitial();
+ }
+
+ /** called to save initial position/size */
+ GridStackEngine.prototype._saveInitial = function() {
+ this.nodes.forEach(function(n) {
+ n._origX = n.x;
+ n._origY = n.y;
+ n._origW = n.width;
+ n._origH = n.height;
+ });
}
/**