Я ожидал, что свойства .rows
и .cols
элемента textarea в javascript сообщат мне текущие значения, но они не сообщают мне только начальные значения атрибута разметки, даже после изменения размера textarea.
function howBigAmI(){
let el= document.getElementById("textarea")
document.getElementById("output").innerHTML=
`${el.rows} rows by ${el.cols} cols, text length=${el.value.length}`
}
howBigAmI()
<p>
How can I read the current textarea rows and cols?
</p>
<textarea oninput = "javascript:howBigAmI()" id = "textarea">
how big am I?
</textarea>
<div id = "output">size</div>
Как я могу получить текущие значения?
(На свойство lineHeight нельзя полагаться, если я не установил его явно, так что это не решение.)
(Я хочу вычислить, сколько строк необходимо, чтобы отобразить все текущее содержимое текстовой области, если ширина остается неизменной. Но я не хочу устанавливать какое-либо из свойств, чтобы иметь возможность выполнить расчет.)
Проголосовали за открытие. Связанный вопрос был задуман только как предложение и содержал только строки.
Может ли «необходимая высота» быть в пикселях или она вам абсолютно необходима в «единицах строк»?
Если возможен вариант с пикселями, используйте el.scrollHeight
, например:
function howBigAmI(){
let el= document.getElementById("textarea")
document.getElementById("output").innerHTML = 'textarea should be ' + el.scrollHeight + ' pixels high to fit all the content';
}
Наверное, лучшим вариантом было бы вычислить scrollHeight / offsetHeight
в том же <textarea>
, но с row = "1"
const getRows = textarea => {
const computedStyle = getComputedStyle(textarea);
const { offsetWidth: realOffsetWidth, scrollWidth: realScrollWidth } =
getSize(textarea);
const realScrollbarWidth = realOffsetWidth - realScrollWidth;
const tempElement = document.createElement('textarea');
tempElement.rows = 1;
tempElement.style.font = computedStyle.font;
tempElement.style.border = computedStyle.border;
tempElement.style.padding = computedStyle.padding;
tempElement.style.lineHeight = computedStyle.lineHeight;
tempElement.style.overflowY = 'scroll';
tempElement.style.position = 'absolute';
tempElement.style.visibility = 'hidden';
document.body.appendChild(tempElement);
const { offsetWidth, scrollWidth } = getSize(tempElement);
const scrollbarWidth = offsetWidth - scrollWidth;
tempElement.style.width = realScrollbarWidth
? realOffsetWidth + 'px'
: realOffsetWidth + scrollbarWidth + 'px';
tempElement.textContent = textarea.value;
const { offsetHeight, scrollHeight } = getSize(tempElement);
document.body.removeChild(tempElement);
return Math.floor(scrollHeight / offsetHeight);
};
const getSize = el => {
const computedStyle = getComputedStyle(el);
const paddingTop = parseFloat(computedStyle.paddingTop);
const paddingBottom = parseFloat(computedStyle.paddingBottom);
const paddingLeft = parseFloat(computedStyle.paddingLeft);
const paddingRight = parseFloat(computedStyle.paddingRight);
const borderTop = parseFloat(computedStyle.borderTopWidth);
const borderBottom = parseFloat(computedStyle.borderBottomWidth);
const borderLeft = parseFloat(computedStyle.borderLeftWidth);
const borderRight = parseFloat(computedStyle.borderRightWidth);
const offsetHeight =
el.offsetHeight - paddingTop - paddingBottom - borderTop - borderBottom;
const scrollHeight = el.scrollHeight - paddingTop - paddingBottom;
const offsetWidth =
el.offsetWidth - paddingLeft - paddingRight - borderLeft - borderRight;
const scrollWidth = el.scrollWidth - paddingLeft - paddingRight;
return { offsetHeight, scrollHeight, offsetWidth, scrollWidth };
};
output.textContent = getRows(textarea);
textarea.addEventListener('input', function () {
output.textContent = getRows(this);
});
const resizeObserver = new ResizeObserver(() => {
output.textContent = getRows(textarea);
});
resizeObserver.observe(textarea);
<p>
How can I read the current textarea rows and cols?
</p>
<textarea id = "textarea">how big
am I?</textarea>
<div id = "output"></div>
Мне грустно, что это так сложно, но похоже, что расчет правильный, спасибо.
Однако я изменил свой ответ, потому что первый вариант с line-height
был неточным...
Аналогичный stackoverflow.com/questions/57919005/… в решающей степени зависит от установки свойства line-height (в противном случае оно не установлено), поэтому у меня это не работает.