在用一個簡單的Web端的 Markdown 編輯器時,我需要一個能讓使用者輸入文字的東西。我首先想到的是使用一個具有可編輯屬性的DIV。但是這種方式引入了許多我不想去解決的問題。我僅僅需要一種簡單傻瓜式的方案——美好的TEXTAREA。
但是文字域同樣也有一個大問題:它們會有一個預設的固定高度。你可以設定 rows 屬性來告訴頁面該展示多少行,也可以設定文字域的 style.height 屬性。但不幸的是,文字域沒有自動設定高度(auto-height)的屬性。
我的想法
在每次改變文字時,我們必須計算內容的高度是多少。幸運的是,有個辦法可以實現。element.scrollHeight可以忽略可見捲軸,得到內容的高度。為了減小(文字域)尺寸我們每次將高度設定為0,這樣scrollHeight就傳回所需要的最小高度而不會多餘。例如:當使用者刪除一行的時候。
同樣我們需要計算邊框(border)和輪廓(outline)的尺寸,這樣文字就不會被截斷,也不會出現捲軸。
然後我們設定style.height屬性為已經計算好的高度。
為了每次都執行上面的動作,我們使用oninput事件,這個事件在每次文字內容改變時被觸發。這與onchange事件相反,onchange只會在使用者點選時觸發。
看看程式碼
style=”padding: 16px; line-height: 1.5;”>
(function() {
function adjustHeight(textareaElement, minHeight) {
// compute the height difference which is caused by border and outline
// 計算因邊框和輪廓產生的高度差異
var outerHeight = parseInt(window.getComputedStyle(el).height, 10);
var diff = outerHeight – el.clientHeight;
// set the height to 0 in case of it has to be shrinked
// 設定高度為0以防需要收縮(高度)
el.style.height = 0;
// set the correct height
// el.scrollHeight is the full height of the content, not just the visible part
// 設定正確的高度
// el.scrollHeight 是文字內容的全部高度,而不僅僅是可見部分的。
el.style.height = Math.max(minHeight, el.scrollHeight + diff) + ‘px’;
}
// we use the “data-adaptheight” attribute as a marker
// 我們使用”data-adaptheight”屬性作為一個標記
var textAreas = document.querySelectorAll(‘textarea[data-adaptheight]’);
// iterate through all the textareas on the page
// 迭代本頁所有的文字域
for (var i = 0, l = textAreas.length; i < l; i++) {
var el = textAreas[i];
// we need box-sizing: border-box, if the textarea has padding
// 如果文字域有邊距,我們需要設定box-sizing: border-box
el.style.boxSizing = el.style.mozBoxSizing = ‘border-box’;
// we don’t need any scrollbars, do we?
// 我們不需要捲軸,不是麼?
el.style.overflowY = ‘hidden’;
// the minimum height initiated through the “rows” attribute
// 透過”rows”屬性初始化的最小高度
var minHeight = el.scrollHeight;
el.addEventListener(‘input’, function() {
adjustHeight(el, minHeight);
});
// we have to readjust when window size changes (e.g. orientation change)
// 當視窗大小改變時,我們需要重新調整高度(例如方向變化)
window.addEventListener(‘resize’, function() {
adjustHeight(el, minHeight);
});
// we adjust height to the initial content
// 我們調整初始內容的高度
adjustHeight(el, minHeight);
}
}());
示例
輸入一些文字體驗下。初始高度為3行。
http://jsfiddle.net/5h4fauq8/1/
權衡
每次鍵盤事件都會造成頁面重繪。因為我們會設定文字域的高度為0然後設定為計算的值。然而這是可以忽略的,因為大多數使用者在一秒之內最多隻能打幾個字。因此這不會造成任何明顯的效能缺陷。
在何處使用?
在許多場景下這個都是有用的。其中包括:
-
文字編輯器
-
程式碼編輯器
-
評論框
原文出處: bdadam.com
譯文出處:伯樂線上 – 袁璋