Skip to content

Commit

Permalink
Reworked to remove use of cached (potentially stale) style values. Fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
jackmoore committed Feb 11, 2023
1 parent 1b9c109 commit 8389fc9
Show file tree
Hide file tree
Showing 5 changed files with 110 additions and 160 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
## Changelog

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

##### v.5.0.2 - 2022-11-20
Expand Down
2 changes: 1 addition & 1 deletion dist/autosize.esm.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

130 changes: 56 additions & 74 deletions dist/autosize.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,7 @@

function assign(ta) {
if (!ta || !ta.nodeName || ta.nodeName !== 'TEXTAREA' || assignedElements.has(ta)) return;
var heightOffset = null;
var clientWidth = null;
var cachedHeight = null;

function init() {
var style = window.getComputedStyle(ta);

if (style.resize === 'vertical') {
ta.style.resize = 'none';
} else if (style.resize === 'both') {
ta.style.resize = 'horizontal';
}

if (style.boxSizing === 'content-box') {
heightOffset = -(parseFloat(style.paddingTop) + parseFloat(style.paddingBottom));
} else {
heightOffset = parseFloat(style.borderTopWidth) + parseFloat(style.borderBottomWidth);
} // Fix when a textarea is not on document body and heightOffset is Not a Number


if (isNaN(heightOffset)) {
heightOffset = 0;
}

update();
}

function changeOverflow(value) {
{
// Chrome/Safari-specific fix:
// When the textarea y-overflow is hidden, Chrome/Safari do not reflow the text to account for the space
// made available by removing the scrollbar. The following forces the necessary text reflow.
var width = ta.style.width;
ta.style.width = '0px'; // Force reflow:
/* jshint ignore:end */

ta.style.width = width;
}
ta.style.overflowY = value;
}
var previousHeight = null;

function cacheScrollTops(el) {
var arr = [];
Expand All @@ -70,78 +31,99 @@
};
}

function resize() {
var computed = window.getComputedStyle(ta);

function update(cachedTextAlign) {
if (cachedTextAlign === void 0) {
cachedTextAlign = null;
}

var initialOverflowY = computed.overflowY;

if (ta.scrollHeight === 0) {
// If the scrollHeight is 0, then the element probably has display:none or is detached from the DOM.
return;
} // ensure the scrollTop values of parent elements are not modified as a consequence of calculating the textarea height


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

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

clientWidth = ta.clientWidth;
restoreScrollTops();
}
var newHeight;

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

if (actualHeight < styleHeight) {
if (computed.maxHeight !== 'none' && newHeight > parseFloat(computed.maxHeight)) {
if (computed.overflowY === 'hidden') {
changeOverflow('scroll');
resize();
actualHeight = parseFloat(window.getComputedStyle(ta).height);
}
} else {
// Normally keep overflow set to hidden, to avoid flash of scrollbar as the textarea expands.
if (computed.overflowY !== 'hidden') {
changeOverflow('hidden');
resize();
actualHeight = parseFloat(window.getComputedStyle(ta).height);
ta.style.overflow = 'scroll';
}

newHeight = parseFloat(computed.maxHeight);
} else if (computed.overflowY !== 'hidden') {
ta.style.overflow = 'hidden';
}

ta.style.height = newHeight + 'px';

if (cachedTextAlign) {
ta.style.textAlign = cachedTextAlign;
}

if (cachedHeight !== actualHeight) {
cachedHeight = actualHeight;
restoreScrollTops();

if (previousHeight !== newHeight) {
ta.dispatchEvent(new Event('autosize:resized', {
bubbles: true
}));
previousHeight = newHeight;
}
}

var pageResize = function pageResize() {
if (ta.clientWidth !== clientWidth) {
update();
if (initialOverflowY !== computed.overflow && !cachedTextAlign) {
var textAlign = computed.textAlign;

if (computed.overflow === 'hidden') {
// Webkit fails to reflow text after overflow is hidden,
// even if hiding overflow would allow text to fit more compactly.
// The following is intended to force the necessary text reflow.
ta.style.textAlign = textAlign === 'start' ? 'end' : 'start';
}

update(textAlign);
}
};
}

var destroy = function (style) {
window.removeEventListener('resize', pageResize, false);
window.removeEventListener('resize', update, false);
ta.removeEventListener('input', update, false);
ta.removeEventListener('keyup', update, false);
ta.removeEventListener('autosize:destroy', destroy, false);
ta.removeEventListener('autosize:update', update, false);
Object.keys(style).forEach(function (key) {
ta.style[key] = style[key];
return ta.style[key] = style[key];
});
assignedElements["delete"](ta);
}.bind(ta, {
height: ta.style.height,
resize: ta.style.resize,
textAlign: ta.style.textAlign,
overflowY: ta.style.overflowY,
overflowX: ta.style.overflowX,
wordWrap: ta.style.wordWrap
});

ta.addEventListener('autosize:destroy', destroy, false);
window.addEventListener('resize', pageResize, false);
window.addEventListener('resize', update, false);
ta.addEventListener('input', update, false);
ta.addEventListener('autosize:update', update, false);
ta.style.overflowX = 'hidden';
Expand All @@ -150,7 +132,7 @@
destroy: destroy,
update: update
});
init();
update();
}

function destroy(ta) {
Expand Down
2 changes: 1 addition & 1 deletion dist/autosize.min.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading

0 comments on commit 8389fc9

Please sign in to comment.