From 404c3e5708b5d0132eb44a27e4d22667e58a8b06 Mon Sep 17 00:00:00 2001 From: Alain Dumesny Date: Tue, 29 Aug 2023 16:35:37 -0700 Subject: [PATCH] fitToContent when calling cellHeight()/addWidget/MakeWidget * partial fix for #2427 * when changing cellHeight, or calling addWidget() | makeWidget() we now call doContentResize() * fixed doContentResize logic to use expected size (using cellHeight) instead of actual DOM values so we don't need to delay until animation is done (unlike column width which does affect calc height for content reflow) TODO: support 1rem type of cellHeight. --- demo/fitToContent.html | 30 ++++++++++++++++++++++++++---- doc/CHANGES.md | 1 + src/gridstack.ts | 16 +++++++++++----- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/demo/fitToContent.html b/demo/fitToContent.html index d87937206..e501e3100 100644 --- a/demo/fitToContent.html +++ b/demo/fitToContent.html @@ -18,11 +18,19 @@

Cell FitToContent options demo

-

new 9.x feature that size the items to fit their content height as to not have scroll bars (unless `fitToContent:false` in C: case)

+

new 9.x feature that size the items to fit their content height as to not have scroll bars + (unless `fitToContent:false` in C: case). Defaulting to different initial size (see code) to show grow/shrink behavior.

column: 8 12 + cellHeight: + 25 + 50 + 75 + Widget: + Add + Make

@@ -32,22 +40,36 @@

Cell FitToContent options demo

margin: 5, cellHeight: 50, fitToContent: true, // default to make them all fit + resizable: { handles: 'all'} // do all sides for testing // cellHeightThrottle: 100, // ms before fitToContent happens } let grid = GridStack.init(opts); let text ='some very large content that will normally not fit in the window.' text = text + text; let items = [ - {x:0, y:0, w:2, content: `
A: ${text}
`}, - {x:2, y:0, w:1, h:2, content: '
B: shrink
'}, // make taller than needed upfront + {x:0, y:0, w:2, content: `
A no h: ${text}
`}, + {x:2, y:0, w:1, h:2, content: '
B: shrink h=2
'}, // make taller than needed upfront {x:3, y:0, w:2, fitToContent: false, content: `
C: WILL SCROLL. ${text}
`}, // prevent this from fitting testing - {x:0, y:1, w:3, content: `
D: ${text} ${text}
`}, + {x:0, y:1, w:3, content: `
D no h: ${text} ${text}
`}, ]; grid.load(items); function column(n) { grid.column(n, 'none'); } + function cellHeight(n) { + grid.cellHeight(n); + } + function addWidget() { + grid.addWidget({content: `
New: ${text}
`}); + } + function makeWidget() { + let doc = document.implementation.createHTMLDocument(); + doc.body.innerHTML = `
New Make: ${text}
`; + let el = doc.body.children[0]; + grid.el.appendChild(el); + grid.makeWidget(el); + } diff --git a/doc/CHANGES.md b/doc/CHANGES.md index f804bd042..e41bd436a 100644 --- a/doc/CHANGES.md +++ b/doc/CHANGES.md @@ -97,6 +97,7 @@ Change log ## 9.0.1-dev (TBD) * fix 'resizecontent' event fix not called. +* partial fix [#2427](https://github.com/gridstack/gridstack.js/issues/2427) fitToContent when calling cellHeight()/addWidget()/MakeWidget() ## 9.0.1 (2023-08-27) * fix [#2413](https://github.com/gridstack/gridstack.js/issues/2413) support touchscreen+mouse devices. Thank you [@Ruslan207](https://github.com/Ruslan207) diff --git a/src/gridstack.ts b/src/gridstack.ts index 1cbeb362e..184d9914c 100644 --- a/src/gridstack.ts +++ b/src/gridstack.ts @@ -798,6 +798,8 @@ export class GridStack { this.opts.cellHeightUnit = data.unit; this.opts.cellHeight = data.h; + this.doContentResize(false); + if (update) { this._updateStyles(true); // true = force re-create for current # of rows } @@ -996,10 +998,13 @@ export class GridStack { public makeWidget(els: GridStackElement, options?: GridStackWidget): GridItemHTMLElement { let el = GridStack.getElement(els); this._prepareElement(el, true, options); + const node = el.gridstackNode; + this._updateContainerHeight(); + this.doContentResize(false, node); + // see if there is a sub-grid to create - const node = el.gridstackNode; if (node.subGridOpts) { this.makeSubGrid(el, node.subGridOpts, undefined, false); // node.subGrid will be used as option in method, no need to pass } @@ -1266,19 +1271,20 @@ export class GridStack { const grid = n.grid; if (grid !== this) return grid?.resizeToContent(el); if (el.parentElement !== this.el) return; // skip if we are not inside a grid - let height = el.clientHeight; // getBoundingClientRect().height seem to flicker back and forth + const cell = this.getCellHeight(); + if (!cell) return; + let height = n.h ? n.h * cell : el.clientHeight; // getBoundingClientRect().height seem to flicker back and forth if (!height) return; // 0 when hidden, skip const item = el.querySelector(GridStack.resizeToContentParent); if (!item) return; const child = item.firstElementChild; // NOTE: clientHeight & getBoundingClientRect() is undefined for text and other leaf nodes. use
container! if (!child) { console.log(`Error: resizeToContent() '${GridStack.resizeToContentParent}'.firstElementChild is null, make sure to have a div like container. Skipping sizing.`); return; } - const itemH = item.clientHeight; // available height to our child (minus border, padding...) + const padding = el.clientHeight - item.clientHeight; // full - available height to our child (minus border, padding...) + 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) const wantedH = child.getBoundingClientRect().height || itemH; if (itemH === wantedH) return; height += wantedH - itemH; - const cell = this.getCellHeight(); - if (!cell) return; let h = Math.ceil(height / cell); if (n.minH && h < n.minH) h = n.minH; else if (n.maxH && h > n.maxH) h = n.maxH;