UNPKG

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