calcTextareaHeight.js 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /**
  2. * fork from element-ui
  3. * https://github.com/ElemeFE/element/blob/master/packages/input/src/calcTextareaHeight.js
  4. */
  5. let hiddenTextarea;
  6. const HIDDEN_STYLE = `
  7. height:0 !important;
  8. visibility:hidden !important;
  9. overflow:hidden !important;
  10. position:absolute !important;
  11. z-index:-1000 !important;
  12. top:0 !important;
  13. right:0 !important
  14. `;
  15. const CONTEXT_STYLE = [
  16. "letter-spacing",
  17. "line-height",
  18. "padding-top",
  19. "padding-bottom",
  20. "font-family",
  21. "font-weight",
  22. "font-size",
  23. "text-rendering",
  24. "text-transform",
  25. "width",
  26. "text-indent",
  27. "padding-left",
  28. "padding-right",
  29. "border-width",
  30. "box-sizing",
  31. ];
  32. function calculateNodeStyling(targetElement) {
  33. const style = window.getComputedStyle(targetElement);
  34. const boxSizing = style.getPropertyValue("box-sizing");
  35. const paddingSize =
  36. parseFloat(style.getPropertyValue("padding-bottom")) +
  37. parseFloat(style.getPropertyValue("padding-top"));
  38. const borderSize =
  39. parseFloat(style.getPropertyValue("border-bottom-width")) +
  40. parseFloat(style.getPropertyValue("border-top-width"));
  41. const contextStyle = CONTEXT_STYLE.map(
  42. (name) => `${name}:${style.getPropertyValue(name)}`,
  43. ).join(";");
  44. return { contextStyle, paddingSize, borderSize, boxSizing };
  45. }
  46. export default function calcTextareaHeight(
  47. targetElement,
  48. minRows = 2,
  49. maxRows = 4,
  50. ) {
  51. if (!hiddenTextarea) {
  52. hiddenTextarea = document.createElement("textarea");
  53. document.body.appendChild(hiddenTextarea);
  54. }
  55. let { paddingSize, borderSize, boxSizing, contextStyle } =
  56. calculateNodeStyling(targetElement);
  57. hiddenTextarea.setAttribute("style", `${contextStyle};${HIDDEN_STYLE}`);
  58. hiddenTextarea.value = targetElement.value || targetElement.placeholder || "";
  59. let height = hiddenTextarea.scrollHeight;
  60. const result = {};
  61. if (boxSizing === "border-box") {
  62. height = height + borderSize;
  63. } else if (boxSizing === "content-box") {
  64. height = height - paddingSize;
  65. }
  66. hiddenTextarea.value = "";
  67. let singleRowHeight = hiddenTextarea.scrollHeight - paddingSize;
  68. if (minRows !== null) {
  69. let minHeight = singleRowHeight * minRows;
  70. if (boxSizing === "border-box") {
  71. minHeight = minHeight + paddingSize + borderSize;
  72. }
  73. height = Math.max(minHeight, height);
  74. result.minHeight = `${minHeight}px`;
  75. }
  76. if (maxRows !== null) {
  77. let maxHeight = singleRowHeight * maxRows;
  78. if (boxSizing === "border-box") {
  79. maxHeight = maxHeight + paddingSize + borderSize;
  80. }
  81. height = Math.min(maxHeight, height);
  82. }
  83. result.height = `${height}px`;
  84. hiddenTextarea.parentNode &&
  85. hiddenTextarea.parentNode.removeChild(hiddenTextarea);
  86. hiddenTextarea = null;
  87. return result;
  88. }