Skip to content

more nested grid reflow #2867

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 18, 2024
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
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