From bce020fc8e701dfcb229d26581e6c03e0ed308c3 Mon Sep 17 00:00:00 2001 From: leedom Date: Sun, 2 Apr 2023 02:42:00 +0800 Subject: [PATCH] feat: add calcTextareaHeight.js from element-ui --- app/calcTextareaHeight.js | 103 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) create mode 100644 app/calcTextareaHeight.js diff --git a/app/calcTextareaHeight.js b/app/calcTextareaHeight.js new file mode 100644 index 0000000..4607f2c --- /dev/null +++ b/app/calcTextareaHeight.js @@ -0,0 +1,103 @@ +/** + * fork from element-ui + */ + +let hiddenTextarea; + +const HIDDEN_STYLE = ` + height:0 !important; + visibility:hidden !important; + overflow:hidden !important; + position:absolute !important; + z-index:-1000 !important; + top:0 !important; + right:0 !important +`; + +const CONTEXT_STYLE = [ + "letter-spacing", + "line-height", + "padding-top", + "padding-bottom", + "font-family", + "font-weight", + "font-size", + "text-rendering", + "text-transform", + "width", + "text-indent", + "padding-left", + "padding-right", + "border-width", + "box-sizing", +]; + +function calculateNodeStyling(targetElement) { + const style = window.getComputedStyle(targetElement); + + const boxSizing = style.getPropertyValue("box-sizing"); + + const paddingSize = + parseFloat(style.getPropertyValue("padding-bottom")) + + parseFloat(style.getPropertyValue("padding-top")); + + const borderSize = + parseFloat(style.getPropertyValue("border-bottom-width")) + + parseFloat(style.getPropertyValue("border-top-width")); + + const contextStyle = CONTEXT_STYLE.map( + (name) => `${name}:${style.getPropertyValue(name)}`, + ).join(";"); + + return { contextStyle, paddingSize, borderSize, boxSizing }; +} + +export default function calcTextareaHeight( + targetElement, + minRows = 2, + maxRows = 4, +) { + if (!hiddenTextarea) { + hiddenTextarea = document.createElement("textarea"); + document.body.appendChild(hiddenTextarea); + } + + let { paddingSize, borderSize, boxSizing, contextStyle } = + calculateNodeStyling(targetElement); + + hiddenTextarea.setAttribute("style", `${contextStyle};${HIDDEN_STYLE}`); + hiddenTextarea.value = targetElement.value || targetElement.placeholder || ""; + + let height = hiddenTextarea.scrollHeight; + const result = {}; + + if (boxSizing === "border-box") { + height = height + borderSize; + } else if (boxSizing === "content-box") { + height = height - paddingSize; + } + + hiddenTextarea.value = ""; + let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize; + + if (minRows !== null) { + let minHeight = singleRowHeight * minRows; + if (boxSizing === "border-box") { + minHeight = minHeight + paddingSize + borderSize; + } + height = Math.max(minHeight, height); + result.minHeight = `${minHeight}px`; + } + if (maxRows !== null) { + let maxHeight = singleRowHeight * maxRows; + if (boxSizing === "border-box") { + maxHeight = maxHeight + paddingSize + borderSize; + } + height = Math.min(maxHeight, height); + } + result.height = `${height}px`; + hiddenTextarea.parentNode && + hiddenTextarea.parentNode.removeChild(hiddenTextarea); + hiddenTextarea = null; + return result; +}