Skip to content

Commit 1804dd5

Browse files
author
Alain Dumesny
authored
Merge pull request #2445 from adumesny/master
tweaks to resizeToContent()
2 parents 763366c + 75a7fac commit 1804dd5

File tree

3 files changed

+53
-52
lines changed

3 files changed

+53
-52
lines changed

doc/CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ Change log
9999

100100
## 9.1.0-dev (TBD)
101101
* fix [#2435](https://github.com/gridstack/gridstack.js/issues/2435) directionCollideCoverage() tweaks
102+
* fix resizeToContent() to handle node.h (using when cellHeight changes or we resize) vs DOM sizing (rest of the time)
102103

103104
## 9.1.0 (2023-09-04)
104105
* renamed fitToContent to sizeToContent (API BREAK)

src/gridstack.scss

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ $animation_speed: .3s !default;
5151
overflow-x: hidden;
5252
overflow-y: auto;
5353
}
54-
&.size-to-content > .grid-stack-item-content {
54+
&.size-to-content:not(.size-to-content-max) > .grid-stack-item-content {
5555
overflow-y: hidden;
5656
}
5757
}

src/gridstack.ts

Lines changed: 51 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -798,7 +798,7 @@ export class GridStack {
798798
this.opts.cellHeightUnit = data.unit;
799799
this.opts.cellHeight = data.h;
800800

801-
this.doContentResize(false);
801+
this.doContentResize(false, true); // no anim wait, but use attributes since we only change row height
802802

803803
if (update) {
804804
this._updateStyles(true); // true = force re-create for current # of rows
@@ -1002,7 +1002,7 @@ export class GridStack {
10021002

10031003
this._updateContainerHeight();
10041004

1005-
this.doContentResize(false, node);
1005+
this.doContentResize(false, false, node);
10061006

10071007
// see if there is a sub-grid to create
10081008
if (node.subGridOpts) {
@@ -1262,54 +1262,54 @@ export class GridStack {
12621262
this.engine.endUpdate();
12631263
}
12641264

1265-
/** Updates widget height to match the content height to avoid v-scrollbar or dead space.
1266-
Note: this assumes only 1 child under '.grid-stack-item-content' (sized to gridItem minus padding) that is at the entire content size wanted */
1267-
public resizeToContent(els: GridStackElement) {
1268-
GridStack.getElements(els).forEach(el => {
1269-
if (!el.clientHeight) return; // 0 when hidden, skip
1270-
let n = el?.gridstackNode;
1271-
if (!n) return;
1272-
const grid = n.grid;
1273-
if (grid !== this) return grid?.resizeToContent(el);
1274-
if (el.parentElement !== this.el) return; // skip if we are not inside a grid
1275-
const cell = this.getCellHeight();
1276-
if (!cell) return;
1277-
let height = n.h ? n.h * cell : el.clientHeight; // getBoundingClientRect().height seem to flicker back and forth
1278-
let item: Element;
1279-
if (n.resizeToContentParent) item = el.querySelector(n.resizeToContentParent);
1280-
if (!item) item = el.querySelector(GridStack.resizeToContentParent);
1281-
if (!item) return;
1282-
const child = item.firstElementChild;
1283-
// NOTE: clientHeight & getBoundingClientRect() is undefined for text and other leaf nodes. use <div> container!
1284-
if (!child) { console.log(`Error: resizeToContent() '${GridStack.resizeToContentParent}'.firstElementChild is null, make sure to have a div like container. Skipping sizing.`); return; }
1285-
const padding = el.clientHeight - item.clientHeight; // full - available height to our child (minus border, padding...)
1286-
const itemH = n.h ? n.h * cell - padding : item.clientHeight; // calculated to what cellHeight is or will become (rather than actual to prevent waiting for animation to finish)
1287-
const wantedH = child.getBoundingClientRect().height || itemH;
1288-
if (itemH === wantedH) return;
1289-
height += wantedH - itemH;
1290-
let h = Math.ceil(height / cell);
1291-
// check for min/max and special sizing
1292-
const softMax = Number.isInteger(n.sizeToContent) ? n.sizeToContent as number : 0;
1293-
if (softMax) {
1294-
if (h > softMax) {
1295-
h = softMax;
1296-
el.classList.remove('size-to-content'); // get v-scroll back
1297-
} else el.classList.add('size-to-content');
1298-
}
1299-
if (n.minH && h < n.minH) h = n.minH;
1300-
else if (n.maxH && h > n.maxH) h = n.maxH;
1301-
if (h !== n.h) {
1302-
this._ignoreLayoutsNodeChange = true;
1303-
this.moveNode(n, {h});
1304-
delete this._ignoreLayoutsNodeChange;
1305-
}
1306-
});
1265+
/**
1266+
* Updates widget height to match the content height to avoid v-scrollbar or dead space.
1267+
* Note: this assumes only 1 child under resizeToContentParent='.grid-stack-item-content' (sized to gridItem minus padding) that is at the entire content size wanted.
1268+
* useAttrSize set to true if GridStackNode.h should be used instead of actual container height when we don't need to wait for animation to finish to get actual DOM heights
1269+
**/
1270+
public resizeToContent(el: GridItemHTMLElement, useAttrSize = false) {
1271+
el?.classList.remove('size-to-content-max');
1272+
if (!el?.clientHeight) return; // 0 when hidden, skip
1273+
let n = el.gridstackNode;
1274+
if (!n) return;
1275+
const grid = n.grid;
1276+
if (!grid) return;
1277+
if (el.parentElement !== grid.el) return; // skip if we are not inside a grid
1278+
const cell = grid.getCellHeight();
1279+
if (!cell) return;
1280+
let height = useAttrSize && n.h ? n.h * cell : el.clientHeight; // getBoundingClientRect().height seem to flicker back and forth
1281+
let item: Element;
1282+
if (n.resizeToContentParent) item = el.querySelector(n.resizeToContentParent);
1283+
if (!item) item = el.querySelector(GridStack.resizeToContentParent);
1284+
if (!item) return;
1285+
const child = item.firstElementChild;
1286+
// NOTE: clientHeight & getBoundingClientRect() is undefined for text and other leaf nodes. use <div> container!
1287+
if (!child) { console.log(`Error: resizeToContent() '${GridStack.resizeToContentParent}'.firstElementChild is null, make sure to have a div like container. Skipping sizing.`); return; }
1288+
const padding = el.clientHeight - item.clientHeight; // full - available height to our child (minus border, padding...)
1289+
const itemH = useAttrSize && n.h ? n.h * cell - padding : item.clientHeight; // calculated to what cellHeight is or will become (rather than actual to prevent waiting for animation to finish)
1290+
const wantedH = child.getBoundingClientRect().height || itemH;
1291+
if (itemH === wantedH) return;
1292+
height += wantedH - itemH;
1293+
let h = Math.ceil(height / cell);
1294+
// check for min/max and special sizing
1295+
const softMax = Number.isInteger(n.sizeToContent) ? n.sizeToContent as number : 0;
1296+
if (softMax && h > softMax) {
1297+
h = softMax;
1298+
el.classList.add('size-to-content-max'); // get v-scroll back
1299+
}
1300+
if (n.minH && h < n.minH) h = n.minH;
1301+
else if (n.maxH && h > n.maxH) h = n.maxH;
1302+
if (h !== n.h) {
1303+
grid._ignoreLayoutsNodeChange = true;
1304+
grid.moveNode(n, {h});
1305+
delete grid._ignoreLayoutsNodeChange;
1306+
}
13071307
}
13081308

13091309
/** call the user resize (so we can do extra work) else our build in version */
1310-
protected resizeToContentCheck(el: GridItemHTMLElement) {
1310+
protected resizeToContentCheck(el: GridItemHTMLElement, useAttr = false) {
13111311
if (GridStack.resizeToContentCB) GridStack.resizeToContentCB(el);
1312-
else this.resizeToContent(el);
1312+
else this.resizeToContent(el, useAttr);
13131313
}
13141314

13151315
/**
@@ -1647,24 +1647,24 @@ export class GridStack {
16471647
this.engine.nodes.forEach(n => {
16481648
if (n.subGrid) n.subGrid.onResize()
16491649
});
1650-
this.doContentResize(columnChanged);
1650+
this.doContentResize(columnChanged); // wait for anim of column changed (DOM reflow before we can size correctly)
16511651

16521652
this.batchUpdate(false);
16531653

16541654
return this;
16551655
}
16561656

1657-
private doContentResize(delay = true, n: GridStackNode = undefined) {
1657+
private doContentResize(delay = true, useAttr = false, n: GridStackNode = undefined) {
16581658
// update any gridItem height with sizeToContent, but wait for DOM $animation_speed to settle if we changed column count
16591659
// 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 ?
16601660
setTimeout(() => {
16611661
if (n) {
1662-
if (Utils.shouldSizeToContent(n)) this.resizeToContentCheck(n.el);
1662+
if (Utils.shouldSizeToContent(n)) this.resizeToContentCheck(n.el, useAttr);
16631663
} else {
16641664
const nodes = [...this.engine.nodes]; // in case order changes while resizing one
16651665
this.batchUpdate();
16661666
nodes.forEach(n => {
1667-
if (Utils.shouldSizeToContent(n)) this.resizeToContentCheck(n.el);
1667+
if (Utils.shouldSizeToContent(n)) this.resizeToContentCheck(n.el, useAttr);
16681668
});
16691669
this.batchUpdate(false);
16701670
}
@@ -2247,7 +2247,7 @@ export class GridStack {
22472247

22482248
if (event.type === 'resizestop') {
22492249
if (Number.isInteger(node.sizeToContent)) node.sizeToContent = node.h; // new soft limit
2250-
this.doContentResize(false, node);
2250+
this.doContentResize(false, true, node); // no amin wait as will use the actual sized coordinate attr
22512251
}
22522252
}
22532253

0 commit comments

Comments
 (0)