Skip to content

Commit c2ddeec

Browse files
authored
Merge pull request #1646 from adumesny/develop
collision: fix constrain put outside of grid
2 parents 064a79f + aac4170 commit c2ddeec

File tree

6 files changed

+50
-47
lines changed

6 files changed

+50
-47
lines changed

demo/events.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ function addEvents(grid, id) {
2828
let node = el.gridstackNode;
2929
let x = el.getAttribute('gs-x'); // verify node (easiest) and attr are the same
3030
let y = el.getAttribute('gs-y');
31-
console.log(g + 'drag ' + el.textContent + ' pos: (' + node.x + ',' + node.y + ') = (' + x + ',' + y + ')');
31+
// console.log(g + 'drag ' + el.textContent + ' pos: (' + node.x + ',' + node.y + ') = (' + x + ',' + y + ')');
3232
});
3333

3434
grid.on('dragstop', function(event, el) {
@@ -58,7 +58,7 @@ function addEvents(grid, id) {
5858
let node = el.gridstackNode;
5959
let w = el.getAttribute('gs-w'); // verify node (easiest) and attr are the same
6060
let h = el.getAttribute('gs-h');
61-
console.log(g + 'resize ' + el.textContent + ' size: (' + node.w + 'x' + node.h + ') = (' + w + 'x' + h + ')');
61+
// console.log(g + 'resize ' + el.textContent + ' size: (' + node.w + 'x' + node.h + ') = (' + w + 'x' + h + ')');
6262
});
6363

6464
grid.on('resizestop', function(event, el) {

spec/e2e/html/141_1534_swap.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ <h1>Swap collision demo</h1>
3939
addEvents(grid);
4040

4141
let items = [[
42-
{x:0, y:0}, {x:0, y:1}, {x:0, y:2},{x:1, y:0}, {x:1, y:1}, {x:1, y:2, h:2, w:2},
42+
{x:0, y:0}, {x:0, y:1}, {x:0, y:2},{x:1, y:0}, {x:1, y:1}, {x:1, y:2, /*h:2, w:2*/},
4343
{x:5, y:0}, {x:4, y:1, w:3, locked: false, _content: 'locked'}, {x:5, y:2},
4444
{x:7, y:0}, {x:8, y:0}, {x:9, y:0}, {x:7, y:1, w:3}, {x:8, y:2},
4545
{x:11, y:0}, {x:11, y:1, h:2},

src/gridstack-dd.ts

Lines changed: 16 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,9 @@ GridStack.prototype._setupAcceptWidget = function(): GridStack {
149149
return canAccept;
150150
}
151151
})
152+
/**
153+
* entering our grid area
154+
*/
152155
.on(this.el, 'dropover', (event: Event, el: GridItemHTMLElement, helper: GridItemHTMLElement) => {
153156

154157
// ignore drop enter on ourself, and prevent parent from receiving event
@@ -188,6 +191,9 @@ GridStack.prototype._setupAcceptWidget = function(): GridStack {
188191
GridStackDD.get().on(el, 'drag', onDrag);
189192
return false; // prevent parent from receiving msg (which may be grid as well)
190193
})
194+
/**
195+
* Leaving our grid area...
196+
*/
191197
.on(this.el, 'dropout', (event, el: GridItemHTMLElement) => {
192198
let node = el.gridstackNode;
193199
if (!node) return;
@@ -211,6 +217,9 @@ GridStack.prototype._setupAcceptWidget = function(): GridStack {
211217
el.gridstackNode = el._gridstackNodeOrig;
212218
return false; // prevent parent from receiving msg (which may be grid as well)
213219
})
220+
/**
221+
* end - releasing the mouse
222+
*/
214223
.on(this.el, 'drop', (event, el: GridItemHTMLElement, helper: GridItemHTMLElement) => {
215224
let node = el.gridstackNode;
216225
let wasAdded = !!this.placeholder.parentElement; // skip items not actually added to us because of constrains, but do cleanup #1419
@@ -435,10 +444,10 @@ GridStack.prototype._prepareDragDropByNode = function(node: GridStackNode): Grid
435444
this._clearRemovingTimeout(el);
436445
if (!node._temporaryRemoved) {
437446
Utils.removePositioningStyles(target);
438-
this._writePosAttr(target, node.x, node.y, node.w, node.h);
447+
this._writePosAttr(target, node);
439448
} else {
440449
Utils.removePositioningStyles(target);
441-
this._writePosAttr(target, node._beforeDrag.x, node._beforeDrag.y, node.w, node.h);
450+
this._writePosAttr(target, {...node._beforeDrag, w: node.w, h: node.h});
442451
node.x = node._beforeDrag.x;
443452
node.y = node._beforeDrag.y;
444453
delete node._temporaryRemoved;
@@ -490,7 +499,7 @@ GridStack.prototype._onStartMoving = function(event: Event, ui: DDUIData, node:
490499
this.engine.cleanNodes()
491500
.beginUpdate(node);
492501

493-
this._writePosAttr(this.placeholder, node.x, node.y, node.w, node.h)
502+
this._writePosAttr(this.placeholder, node)
494503
this.el.append(this.placeholder);
495504

496505
node.el = this.placeholder;
@@ -502,7 +511,7 @@ GridStack.prototype._onStartMoving = function(event: Event, ui: DDUIData, node:
502511
if (event.type === 'dropover' && !node._added) {
503512
node._added = true;
504513
this.engine.addNode(node);
505-
this._writePosAttr(this.placeholder, node.x, node.y, node.w, node.h);
514+
this._writePosAttr(this.placeholder, node);
506515
node._moving = true; // lastly mark as moving object
507516
}
508517

@@ -520,7 +529,7 @@ GridStack.prototype._onStartMoving = function(event: Event, ui: DDUIData, node:
520529

521530
/** @internal called when item is being dragged/resized */
522531
GridStack.prototype._dragOrResize = function(event: Event, ui: DDUIData, node: GridStackNode, cellWidth: number, cellHeight: number): void {
523-
let el = node.el;
532+
let el = node.el || event.target as GridItemHTMLElement;
524533
// calculate the place where we're landing by offsetting margin so actual edge crosses mid point
525534
let left = ui.position.left + (ui.position.left > node._lastUiPosition.left ? -this.opts.marginRight : this.opts.marginLeft);
526535
let top = ui.position.top + (ui.position.top > node._lastUiPosition.top ? -this.opts.marginBottom : this.opts.marginTop);
@@ -561,10 +570,9 @@ GridStack.prototype._dragOrResize = function(event: Event, ui: DDUIData, node: G
561570
if (node._removeTimeout) this._clearRemovingTimeout(el);
562571

563572
if (node._temporaryRemoved) {
573+
node.el = this.placeholder;
564574
this.engine.addNode(node);
565-
this._writePosAttr(this.placeholder, x, y, w, h);
566575
this.el.appendChild(this.placeholder);
567-
node.el = this.placeholder;
568576
delete node._temporaryRemoved;
569577
}
570578
}
@@ -597,7 +605,7 @@ GridStack.prototype._dragOrResize = function(event: Event, ui: DDUIData, node: G
597605
this._updateContainerHeight();
598606

599607
let target = event.target as GridItemHTMLElement;
600-
this._writePosAttr(target, node.x, node.y, node.w, node.h);
608+
this._writePosAttr(target, node);
601609
if (this._gsEventHandler[event.type]) {
602610
this._gsEventHandler[event.type](event, target);
603611
}

src/gridstack-engine.ts

Lines changed: 23 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ export class GridStackEngine {
8484

8585
let didMove = false;
8686
let yOffset = 0;
87-
let newOpt: GridStackMoveOpts = {nested: true, pack: false, sanitize: false};
87+
let newOpt: GridStackMoveOpts = {nested: true, pack: false};
8888
while (collide = collide || this.collide(node, nn)) { // could collide with more than 1 item... so repeat for each
8989
let moved: boolean;
9090
// if colliding with locked item, OR moving down to a different sized item
@@ -328,16 +328,17 @@ export class GridStackEngine {
328328
if (isNaN(node.w)) { node.w = defaults.w; }
329329
if (isNaN(node.h)) { node.h = defaults.h; }
330330

331-
if (node.maxW) { node.w = Math.min(node.w, node.maxW); }
332-
if (node.maxH) { node.h = Math.min(node.h, node.maxH); }
333-
if (node.minW) { node.w = Math.max(node.w, node.minW); }
334-
if (node.minH) { node.h = Math.max(node.h, node.minH); }
335-
336331
return this.nodeBoundFix(node, resizing);
337332
}
338333

339334
/** part2 of preparing a node to fit inside our grid - checks for x,y from grid dimensions */
340335
public nodeBoundFix(node: GridStackNode, resizing?: boolean): GridStackNode {
336+
337+
if (node.maxW) { node.w = Math.min(node.w, node.maxW); }
338+
if (node.maxH) { node.h = Math.min(node.h, node.maxH); }
339+
if (node.minW) { node.w = Math.max(node.w, node.minW); }
340+
if (node.minH) { node.h = Math.max(node.h, node.minH); }
341+
341342
if (node.w > this.column) {
342343
node.w = this.column;
343344
} else if (node.w < 1) {
@@ -413,7 +414,8 @@ export class GridStackEngine {
413414

414415
/** call to add the given node to our list, fixing collision and re-packing */
415416
public addNode(node: GridStackNode, triggerAddEvent = false): GridStackNode {
416-
if (this.nodes.find(n => n._id === node._id)) return; // prevent inserting twice!
417+
let dup: GridStackNode;
418+
if (dup = this.nodes.find(n => n._id === node._id)) return dup; // prevent inserting twice! return it instead.
417419
node = this.prepareNode(node);
418420

419421
if (node.autoPosition) {
@@ -471,7 +473,6 @@ export class GridStackEngine {
471473
if (node.locked) return false;
472474
if (!this.changedPosConstrain(node, o)) return false;
473475
o.pack = true;
474-
o.sanitize = false;
475476

476477
// simpler case: move item directly...
477478
if (!this.maxRow/* && !this.nodes.some(n => n.locked)*/) {
@@ -577,23 +578,19 @@ export class GridStackEngine {
577578
public moveNode(node: GridStackNode, o: GridStackMoveOpts): boolean {
578579
if (!node || node.locked || !o) return false;
579580
if (o.pack === undefined) o.pack = true;
580-
if (o.sanitize === undefined) o.sanitize = true;
581-
let nn: GridStackNode;
582-
if (o.sanitize) {
583-
if (typeof o.x !== 'number') { o.x = node.x; }
584-
if (typeof o.y !== 'number') { o.y = node.y; }
585-
if (typeof o.w !== 'number') { o.w = node.w; }
586-
if (typeof o.h !== 'number') { o.h = node.h; }
587-
588-
// constrain the passed in values and check if we're still changing our node
589-
let resizing = (node.w !== o.w || node.h !== o.h);
590-
nn = {maxW: node.maxW, maxH: node.maxH, minW: node.minW, minH: node.minH};
591-
Utils.copyPos(nn, o);
592-
nn = this.prepareNode(nn, resizing);
593-
Utils.copyPos(o, nn);
594-
}
595-
nn = nn || o;
596-
if (Utils.samePos(node, nn)) return false;
581+
582+
// constrain the passed in values and check if we're still changing our node
583+
if (typeof o.x !== 'number') { o.x = node.x; }
584+
if (typeof o.y !== 'number') { o.y = node.y; }
585+
if (typeof o.w !== 'number') { o.w = node.w; }
586+
if (typeof o.h !== 'number') { o.h = node.h; }
587+
let resizing = (node.w !== o.w || node.h !== o.h);
588+
let nn: GridStackNode = {maxW: node.maxW, maxH: node.maxH, minW: node.minW, minH: node.minH};
589+
Utils.copyPos(nn, o);
590+
nn = this.nodeBoundFix(nn, resizing);
591+
Utils.copyPos(o, nn);
592+
593+
if (Utils.samePos(node, o)) return false;
597594
let prevPos: GridStackPosition = Utils.copyPos({}, node);
598595

599596
// check if we will need to fix collision at our new location
@@ -628,7 +625,7 @@ export class GridStackEngine {
628625
public beginUpdate(node: GridStackNode): GridStackEngine {
629626
if (node._updating) return this;
630627
node._updating = true;
631-
node._beforeDrag = {x: node.x, y: node.y, w: node.w, h: node.h};
628+
node._beforeDrag = Utils.copyPos({}, node);
632629
delete node._skipDown;
633630
this.nodes.forEach(n => n._packY = n.y);
634631
return this;

src/gridstack.ts

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import { GridStackEngine } from './gridstack-engine';
1010
import { obsoleteOpts, obsoleteAttr, Utils, HeightData } from './utils';
1111
import { ColumnOptions, GridItemHTMLElement, GridStackElement, GridStackEventHandlerCallback,
12-
GridStackNode, GridStackOptions, GridStackWidget, numberOrString, DDUIData, DDDragInOpt } from './types';
12+
GridStackNode, GridStackOptions, GridStackWidget, numberOrString, DDUIData, DDDragInOpt, GridStackPosition } from './types';
1313
import { GridStackDDI } from './gridstack-ddi';
1414

1515
// export all dependent file as well to make it easier for users to just import the main file
@@ -320,7 +320,7 @@ export class GridStack {
320320
if (removeDOM && n._id === null) {
321321
if (el && el.parentNode) { el.parentNode.removeChild(el) }
322322
} else {
323-
this._writePosAttr(el, n.x, n.y, n.w, n.h);
323+
this._writePosAttr(el, n);
324324
}
325325
});
326326
this._updateStyles(false, maxH); // false = don't recreate, just append if need be
@@ -1241,18 +1241,18 @@ export class GridStack {
12411241
}
12421242

12431243
/** @internal call to write position x,y,w,h attributes back to element */
1244-
private _writePosAttr(el: HTMLElement, x?: number, y?: number, w?: number, h?: number): GridStack {
1245-
if (x !== undefined && x !== null) { el.setAttribute('gs-x', String(x)); }
1246-
if (y !== undefined && y !== null) { el.setAttribute('gs-y', String(y)); }
1247-
if (w) { el.setAttribute('gs-w', String(w)); }
1248-
if (h) { el.setAttribute('gs-h', String(h)); }
1244+
private _writePosAttr(el: HTMLElement, n: GridStackPosition): GridStack {
1245+
if (n.x !== undefined && n.x !== null) { el.setAttribute('gs-x', String(n.x)); }
1246+
if (n.y !== undefined && n.y !== null) { el.setAttribute('gs-y', String(n.y)); }
1247+
if (n.w) { el.setAttribute('gs-w', String(n.w)); }
1248+
if (n.h) { el.setAttribute('gs-h', String(n.h)); }
12491249
return this;
12501250
}
12511251

12521252
/** @internal call to write any default attributes back to element */
12531253
private _writeAttr(el: HTMLElement, node: GridStackWidget): GridStack {
12541254
if (!node) return this;
1255-
this._writePosAttr(el, node.x, node.y, node.w, node.h);
1255+
this._writePosAttr(el, node);
12561256

12571257
let attrs /*: GridStackWidget but strings */ = { // remaining attributes
12581258
autoPosition: 'gs-auto-position',

src/types.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -200,8 +200,6 @@ export interface GridStackOptions {
200200
export interface GridStackMoveOpts extends GridStackPosition {
201201
/** do we pack (default true) */
202202
pack?: boolean;
203-
/** do we verify for bad or > max/min values (default true) */
204-
sanitize?: boolean;
205203
/** true if we are calling this recursively to prevent simple swap or coverage collision - default false*/
206204
nested?: boolean;
207205
/* vars to calculate other cells coordinates */

0 commit comments

Comments
 (0)