Skip to content
This repository was archived by the owner on Sep 7, 2025. It is now read-only.

Commit 8389fc9

Browse files
committed
Reworked to remove use of cached (potentially stale) style values. Fixes #404
1 parent 1b9c109 commit 8389fc9

File tree

5 files changed

+110
-160
lines changed

5 files changed

+110
-160
lines changed

changelog.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
## Changelog
22

33
##### v.6.0.0 - 2023-02-10
4+
* Reworked to remove use of cached (potentially stale) style values. Fixes #404
45
* Dropped support for Internet Explorer
56

67
##### v.5.0.2 - 2022-11-20

dist/autosize.esm.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

dist/autosize.js

Lines changed: 56 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -7,46 +7,7 @@
77

88
function assign(ta) {
99
if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || assignedElements.has(ta)) return;
10-
var heightOffset = null;
11-
var clientWidth = null;
12-
var cachedHeight = null;
13-
14-
function init() {
15-
var style = window.getComputedStyle(ta);
16-
17-
if (style.resize === 'vertical') {
18-
ta.style.resize = 'none';
19-
} else if (style.resize === 'both') {
20-
ta.style.resize = 'horizontal';
21-
}
22-
23-
if (style.boxSizing === 'content-box') {
24-
heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
25-
} else {
26-
heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
27-
} // Fix when a textarea is not on document body and heightOffset is Not a Number
28-
29-
30-
if (isNaN(heightOffset)) {
31-
heightOffset = 0;
32-
}
33-
34-
update();
35-
}
36-
37-
function changeOverflow(value) {
38-
{
39-
// Chrome/Safari-specific fix:
40-
// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
41-
// made available by removing the scrollbar. The following forces the necessary text reflow.
42-
var width = ta.style.width;
43-
ta.style.width = '0px'; // Force reflow:
44-
/* jshint ignore:end */
45-
46-
ta.style.width = width;
47-
}
48-
ta.style.overflowY = value;
49-
}
10+
var previousHeight = null;
5011

5112
function cacheScrollTops(el) {
5213
var arr = [];
@@ -70,78 +31,99 @@
7031
};
7132
}
7233

73-
function resize() {
34+
var computed = window.getComputedStyle(ta);
35+
36+
function update(cachedTextAlign) {
37+
if (cachedTextAlign === void 0) {
38+
cachedTextAlign = null;
39+
}
40+
41+
var initialOverflowY = computed.overflowY;
42+
7443
if (ta.scrollHeight === 0) {
7544
// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
7645
return;
7746
} // ensure the scrollTop values of parent elements are not modified as a consequence of calculating the textarea height
7847

7948

8049
var restoreScrollTops = cacheScrollTops(ta);
81-
ta.style.height = ''; // this is necessary for getting an accurate scrollHeight on the next line
50+
ta.style.height = ''; // this is necessary for to scrollHeight to accurately reflect situations where the textarea should shrink
51+
// disallow vertical resizing
8252

83-
ta.style.height = ta.scrollHeight + heightOffset + 'px'; // used to check if an update is actually necessary on window.resize
53+
if (computed.resize === 'vertical') {
54+
ta.style.resize = 'none';
55+
} else if (computed.resize === 'both') {
56+
ta.style.resize = 'horizontal';
57+
}
8458

85-
clientWidth = ta.clientWidth;
86-
restoreScrollTops();
87-
}
59+
var newHeight;
8860

89-
function update() {
90-
resize();
91-
var styleHeight = parseFloat(ta.style.height);
92-
var computed = window.getComputedStyle(ta);
93-
var actualHeight = parseFloat(computed.height); // The actual height not matching the style height (set via the resize method) indicates that
94-
// the max-height has been exceeded, in which case the overflow should be allowed.
61+
if (computed.boxSizing === 'content-box') {
62+
newHeight = ta.scrollHeight - (parseFloat(computed.paddingTop) + parseFloat(computed.paddingBottom));
63+
} else {
64+
newHeight = ta.scrollHeight + parseFloat(computed.borderTopWidth) + parseFloat(computed.borderBottomWidth);
65+
}
9566

96-
if (actualHeight < styleHeight) {
67+
if (computed.maxHeight !== 'none' && newHeight > parseFloat(computed.maxHeight)) {
9768
if (computed.overflowY === 'hidden') {
98-
changeOverflow('scroll');
99-
resize();
100-
actualHeight = parseFloat(window.getComputedStyle(ta).height);
101-
}
102-
} else {
103-
// Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands.
104-
if (computed.overflowY !== 'hidden') {
105-
changeOverflow('hidden');
106-
resize();
107-
actualHeight = parseFloat(window.getComputedStyle(ta).height);
69+
ta.style.overflow = 'scroll';
10870
}
71+
72+
newHeight = parseFloat(computed.maxHeight);
73+
} else if (computed.overflowY !== 'hidden') {
74+
ta.style.overflow = 'hidden';
75+
}
76+
77+
ta.style.height = newHeight + 'px';
78+
79+
if (cachedTextAlign) {
80+
ta.style.textAlign = cachedTextAlign;
10981
}
11082

111-
if (cachedHeight !== actualHeight) {
112-
cachedHeight = actualHeight;
83+
restoreScrollTops();
84+
85+
if (previousHeight !== newHeight) {
11386
ta.dispatchEvent(new Event('autosize:resized', {
11487
bubbles: true
11588
}));
89+
previousHeight = newHeight;
11690
}
117-
}
11891

119-
var pageResize = function pageResize() {
120-
if (ta.clientWidth !== clientWidth) {
121-
update();
92+
if (initialOverflowY !== computed.overflow && !cachedTextAlign) {
93+
var textAlign = computed.textAlign;
94+
95+
if (computed.overflow === 'hidden') {
96+
// Webkit fails to reflow text after overflow is hidden,
97+
// even if hiding overflow would allow text to fit more compactly.
98+
// The following is intended to force the necessary text reflow.
99+
ta.style.textAlign = textAlign === 'start' ? 'end' : 'start';
100+
}
101+
102+
update(textAlign);
122103
}
123-
};
104+
}
124105

125106
var destroy = function (style) {
126-
window.removeEventListener('resize', pageResize, false);
107+
window.removeEventListener('resize', update, false);
127108
ta.removeEventListener('input', update, false);
128109
ta.removeEventListener('keyup', update, false);
129110
ta.removeEventListener('autosize:destroy', destroy, false);
130111
ta.removeEventListener('autosize:update', update, false);
131112
Object.keys(style).forEach(function (key) {
132-
ta.style[key] = style[key];
113+
return ta.style[key] = style[key];
133114
});
134115
assignedElements["delete"](ta);
135116
}.bind(ta, {
136117
height: ta.style.height,
137118
resize: ta.style.resize,
119+
textAlign: ta.style.textAlign,
138120
overflowY: ta.style.overflowY,
139121
overflowX: ta.style.overflowX,
140122
wordWrap: ta.style.wordWrap
141123
});
142124

143125
ta.addEventListener('autosize:destroy', destroy, false);
144-
window.addEventListener('resize', pageResize, false);
126+
window.addEventListener('resize', update, false);
145127
ta.addEventListener('input', update, false);
146128
ta.addEventListener('autosize:update', update, false);
147129
ta.style.overflowX = 'hidden';
@@ -150,7 +132,7 @@
150132
destroy: destroy,
151133
update: update
152134
});
153-
init();
135+
update();
154136
}
155137

156138
function destroy(ta) {

dist/autosize.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)