Skip to content

Commit

Permalink
Merge pull request #2867 from adumesny/master
Browse files Browse the repository at this point in the history
more nested grid reflow
  • Loading branch information
adumesny authored Nov 18, 2024
2 parents f5f7c9a + 33bcc6c commit d2d94f9
Show file tree
Hide file tree
Showing 4 changed files with 121 additions and 13 deletions.
42 changes: 42 additions & 0 deletions spec/e2e/html/2864_nested_resize_reflow.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>2864 nest grid resize</title>
<link rel="stylesheet" href="../../../demo/demo.css"/>
<link rel="stylesheet" href="../../../dist/gridstack-extra.css"/>
<script src="../../../dist/gridstack-all.js"></script>
</head>
<body>
<h1>2864 nest grid resize</h1>
<p>Test for nested grid resize reflowing content (manually and API)</p>
<a class="btn btn-primary" onClick="step1()" href="#">resize</a>
<div class="grid-stack">
<!-- <div class="grid-stack-item" gs-x="0" gs-y="0" gs-w="4" gs-h="2" gs-id="gsItem1" id="item1">
<div class="grid-stack-item-content">item 1 text</div>
</div>
<div class="grid-stack-item" gs-x="4" gs-y="0" gs-w="4" gs-h="4" gs-id="gsItem2" id="item2">
<div class="grid-stack-item-content">item 2 text</div>
</div> -->
</div>
<script type="text/javascript">
// test for spec file debugging
let margin = 5;
let cellHeight = 70;
let children = [{},{},{}];
let items = [
{x: 0, y: 0, w:3, h:3, sizeToContent: true,
subGridOpts: {children, column: 'auto', margin, cellHeight}}
];
let count = 0;
[...items, ...children].forEach(n => { n.id = String(count++); if (count>1) n.content=n.id});
grid = GridStack.init({cellHeight: cellHeight+20, margin, children: items});

step1 = function() {
grid.update(grid.engine.nodes[0].el, {w:2});
}
</script>
</body>
</html>
51 changes: 51 additions & 0 deletions spec/regression-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,10 @@ describe('regression >', function() {
let findEl = function(id: string): GridItemHTMLElement {
return grid.engine.nodes.find(n => n.id === id)!.el!;
};
let findSubEl = function(id: string, index = 0): GridItemHTMLElement {
return grid.engine.nodes[index].subGrid?.engine.nodes.find(n => n.id === id)!.el!;
};


// empty grid
let gridstackEmptyHTML =
Expand Down Expand Up @@ -55,4 +59,51 @@ describe('regression >', function() {
expect(parseInt(el2.getAttribute('gs-y'), 10)).toBe(0);
});
});

describe('2865 nested grid resize >', function() {
beforeEach(function() {
document.body.insertAdjacentHTML('afterbegin', gridstackEmptyHTML);
});
afterEach(function() {
document.body.removeChild(document.getElementById('gs-cont'));
});
it('', function() {
let children: GridStackWidget[] = [{},{},{}];
let items: GridStackWidget[] = [
{x: 0, y: 0, w:3, h:3, sizeToContent: true, subGridOpts: {children, column: 'auto'}}
];
let count = 0;
[...items, ...children].forEach(n => n.id = String(count++));
grid = GridStack.init({cellHeight: 70, margin: 5, children: items});

let nested = findEl('0');
let el1 = findSubEl('1');
let el2 = findSubEl('2');
let el3 = findSubEl('3');
expect(parseInt(nested.getAttribute('gs-x'), 10)).toBe(0);
expect(parseInt(nested.getAttribute('gs-y'), 10)).toBe(0);
expect(parseInt(nested.getAttribute('gs-w'), 10)).toBe(3);
expect(nested.getAttribute('gs-h')).toBe(null); // sizeToContent 3 -> 1 which is null
expect(parseInt(el1.getAttribute('gs-x'), 10)).toBe(0);
expect(parseInt(el1.getAttribute('gs-y'), 10)).toBe(0);
expect(parseInt(el2.getAttribute('gs-x'), 10)).toBe(1);
expect(parseInt(el2.getAttribute('gs-y'), 10)).toBe(0);
expect(parseInt(el3.getAttribute('gs-x'), 10)).toBe(2);
expect(parseInt(el3.getAttribute('gs-y'), 10)).toBe(0);

// now resize the nested grid to 2 -> should reflow el3
grid.update(nested, {w:2});
expect(parseInt(nested.getAttribute('gs-x'), 10)).toBe(0);
expect(parseInt(nested.getAttribute('gs-y'), 10)).toBe(0);
expect(parseInt(nested.getAttribute('gs-w'), 10)).toBe(2);
expect(nested.getAttribute('gs-h')).toBe(null); // sizeToContent not called until some delay
expect(parseInt(el1.getAttribute('gs-x'), 10)).toBe(0);
expect(parseInt(el1.getAttribute('gs-y'), 10)).toBe(0);
expect(parseInt(el2.getAttribute('gs-x'), 10)).toBe(1);
expect(parseInt(el2.getAttribute('gs-y'), 10)).toBe(0);
// 3rd item pushed to next row
expect(parseInt(el3.getAttribute('gs-x'), 10)).toBe(0);
expect(parseInt(el3.getAttribute('gs-y'), 10)).toBe(1);
});
});
});
17 changes: 12 additions & 5 deletions spec/test.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Grid Spec test</title>
<link rel="stylesheet" href="../demo/demo.css"/>
<link rel="stylesheet" href="../dist/gridstack-extra.css"/>
<script src="../dist/gridstack-all.js"></script>
</head>
<body>
Expand All @@ -22,15 +23,21 @@ <h1>Grid Spec test</h1>
</div>
<script type="text/javascript">
// test for spec file debugging
let items = [{ x:0, y:0, w:12, h:1, id:'left', content:'left' }, { x:12, y:0, w:12, h:1, id:'right', content:'right' }];

let grid = GridStack.init({cellHeight:50, margin:5, children:items});
let margin = 5;
let cellHeight = 70;
let children = [{},{},{}];
let items = [
{x: 0, y: 0, w:3, h:3, sizeToContent: true,
subGridOpts: {children, column: 'auto', margin, cellHeight}}
];
let count = 0;
[...items, ...children].forEach(n => { n.id = String(count++); if (count>1) n.content=n.id});
grid = GridStack.init({cellHeight: cellHeight+20, margin, children: items});

step1 = function() {
grid.column(1);
grid.update(grid.engine.nodes[0].el, {w:2});
}
step2 = function() {
grid.column(12);
}
</script>
</body>
Expand Down
24 changes: 16 additions & 8 deletions src/gridstack.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ export class GridStack {
/** point to a parent grid item if we're nested (inside a grid-item in between 2 Grids) */
public parentGridNode?: GridStackNode;

/** time to wait for animation (if enabled) to be done so content sizing can happen */
public animationDelay = 300 + 10;

protected static engineClass: typeof GridStackEngine;
protected resizeObserver: ResizeObserver;

Expand Down Expand Up @@ -1345,7 +1348,12 @@ export class GridStack {
if (m) {
const widthChanged = (m.w !== undefined && m.w !== n.w);
this.moveNode(n, m);
this.resizeToContentCheck(widthChanged, n); // wait for animation if we changed width
if (widthChanged && n.subGrid) {
// if we're animating the client size hasn't changed yet, so force a change (not exact size)
n.subGrid.onResize(this.hasAnimationCSS() ? n.w : undefined);
} else {
this.resizeToContentCheck(widthChanged, n);
}
delete n._orig; // clear out original position now that we moved #2669
}
if (m || changed) {
Expand Down Expand Up @@ -1774,19 +1782,19 @@ export class GridStack {
* and remember the prev columns we used, or get our count from parent, as well as check for cellHeight==='auto' (square)
* or `sizeToContent` gridItem options.
*/
public onResize(): GridStack {
if (!this.el?.clientWidth) return; // return if we're gone or no size yet (will get called again)
if (this.prevWidth === this.el.clientWidth) return; // no-op
this.prevWidth = this.el.clientWidth
// console.log('onResize ', this.el.clientWidth);
public onResize(clientWidth = this.el?.clientWidth): GridStack {
if (!clientWidth) return; // return if we're gone or no size yet (will get called again)
if (this.prevWidth === clientWidth) return; // no-op
this.prevWidth = clientWidth
// console.log('onResize ', clientWidth);

this.batchUpdate();

// see if we're nested and take our column count from our parent....
let columnChanged = false;
if (this._autoColumn && this.parentGridNode) {
if (this.opts.column !== this.parentGridNode.w) {
this.column(this.parentGridNode.w, this.opts.layout || 'none');
this.column(this.parentGridNode.w, this.opts.layout || 'list');
columnChanged = true;
}
} else {
Expand Down Expand Up @@ -1816,7 +1824,7 @@ export class GridStack {

// update any gridItem height with sizeToContent, but wait for DOM $animation_speed to settle if we changed column count
// TODO: is there a way to know what the final (post animation) size of the content will be so we can animate the column width and height together rather than sequentially ?
if (delay && this.hasAnimationCSS()) return setTimeout(() => this.resizeToContentCheck(false, n), 300 + 10);
if (delay && this.hasAnimationCSS()) return setTimeout(() => this.resizeToContentCheck(false, n), this.animationDelay);

if (n) {
if (Utils.shouldSizeToContent(n)) this.resizeToContentCBCheck(n.el);
Expand Down

0 comments on commit d2d94f9

Please sign in to comment.