* Updates widget height to match the content height to avoid vertical scrollbars or dead space. * This automatically adjusts the widget height based on its content size. * * Note: This assumes only 1 child under resizeToContentParent='.grid-stack-item-content' * (sized to gridItem minus
(el: GridItemHTMLElement)
| 1652 | * grid.resizeToContent(widget); |
| 1653 | */ |
| 1654 | public resizeToContent(el: GridItemHTMLElement) { |
| 1655 | if (!el) return; |
| 1656 | el.classList.remove('size-to-content-max'); |
| 1657 | if (!el.clientHeight) return; // 0 when hidden, skip |
| 1658 | const n = el.gridstackNode; |
| 1659 | if (!n) return; |
| 1660 | const grid = n.grid; |
| 1661 | if (!grid || el.parentElement !== grid.el) return; // skip if we are not inside a grid |
| 1662 | const cell = grid.getCellHeight(true); |
| 1663 | if (!cell) return; |
| 1664 | let height = n.h ? n.h * cell : el.clientHeight; // getBoundingClientRect().height seem to flicker back and forth |
| 1665 | let item: Element; |
| 1666 | if (n.resizeToContentParent) item = el.querySelector(n.resizeToContentParent); |
| 1667 | if (!item) item = el.querySelector(GridStack.resizeToContentParent); |
| 1668 | if (!item) return; |
| 1669 | const padding = el.clientHeight - item.clientHeight; // full - available height to our child (minus border, padding...) |
| 1670 | 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) |
| 1671 | let wantedH: number; |
| 1672 | if (n.subGrid) { |
| 1673 | // sub-grid - use their actual row count * their cell height, BUT append any content outside of the grid (eg: above text) |
| 1674 | wantedH = n.subGrid.getRow() * n.subGrid.getCellHeight(true); |
| 1675 | const subRec = n.subGrid.el.getBoundingClientRect(); |
| 1676 | const parentRec = el.getBoundingClientRect(); |
| 1677 | wantedH += subRec.top - parentRec.top; |
| 1678 | } else if (n.subGridOpts?.children?.length) { |
| 1679 | // not sub-grid just yet (case above) wait until we do |
| 1680 | return; |
| 1681 | } else { |
| 1682 | // NOTE: clientHeight & getBoundingClientRect() is undefined for text and other leaf nodes. use <div> container! |
| 1683 | const child = item.firstElementChild; |
| 1684 | if (!child) { |
| 1685 | console.error(`Error: GridStack.resizeToContent() widget id:${n.id} '${GridStack.resizeToContentParent}'.firstElementChild is null, make sure to have a div like container. Skipping sizing.`); |
| 1686 | return; |
| 1687 | } |
| 1688 | wantedH = child.getBoundingClientRect().height || itemH; |
| 1689 | } |
| 1690 | if (itemH === wantedH) return; |
| 1691 | height += wantedH - itemH; |
| 1692 | let h = Math.ceil(height / cell); |
| 1693 | // check for min/max and special sizing |
| 1694 | const softMax = Number.isInteger(n.sizeToContent) ? n.sizeToContent as number : 0; |
| 1695 | if (softMax && h > softMax) { |
| 1696 | h = softMax; |
| 1697 | el.classList.add('size-to-content-max'); // get v-scroll back |
| 1698 | } |
| 1699 | if (n.minH && h < n.minH) h = n.minH; |
| 1700 | else if (n.maxH && h > n.maxH) h = n.maxH; |
| 1701 | if (h !== n.h) { |
| 1702 | grid._ignoreLayoutsNodeChange = true; |
| 1703 | grid.moveNode(n, { h }); |
| 1704 | delete grid._ignoreLayoutsNodeChange; |
| 1705 | } |
| 1706 | } |
| 1707 | |
| 1708 | /** call the user resize (so they can do extra work) else our build in version */ |
| 1709 | private resizeToContentCBCheck(el: GridItemHTMLElement) { |
no test coverage detected