Казалось бы тривиальная задача: поле, которое бы автоматически меняло свою высоту в зависимости от внутреннего текста. Нечто подобное есть в редакторе, в котором я сейчас пишу этот текст ckeditor. Называется оно здесь autogrow и реализуется отдельным плагином.
Да, разумеется и для нативных инпутов есть множество jQuery плагинов, которые выполняют возложенную на них функцию.
Так сложилось, что мой блог - это не набор простых решений, типа берете такой плагин, подключаете и у Вас все работает. Нет. Я из тех людей, которых результаты запроса в гугле: "Как объединить два массива в, вызывают по меньшей мере негодование.
Плеяда статей и вопросов на stackoverflow, с ответом: $.extend
У большинства сегодняшних web-developerov, нет ни тени сомнения, что jQuery подключен к любому проекту.
Я не из таких программистов. Есть такие области, в которых нет и не будет jQuery. К примеру, написание плагинов на другие библиотеки или программы. К примеру плагин на ckeditor, допускает использование лишь API самого редактора, потому, как само оно вести порядка 0.5Mb и библиотека в 0.09Mb будет излишней нагрузкой.
В таких ситуациях есть два пути: первый, написать все на API библиотеки, и второй сделать все на vanila.js
При втором варианте, наш код будет легко портировать на любую другую библиотеку. Все заработает даже вовсе без нее.
Собственно ради чего это отступление - не стоит использовать плагин там, где все и так пишется в несколько строк кода.
Теперь к делу
Все готовые плагины, которые я встретил изучая этот вопрос, работают по одному принципу: создают div элемент, делают все его стили, размеры, шрифты и отступы идентичными textarea. Затем, прячут его, при этом делают это не при помощи display:none а с помощью visibility:hidden
Отличает одно от другого то, что у display:none нельзя выяснить размер. А у visibility:hidden можно. Чтобы он не мешался, ему делают position:absolute;
Потом на textarea вешается обработчик keyup,mouseup и change, который синхронизируется содержимое textarea и нашего div'а. Затем, в обратную сторону синхронизируется размер textarea с размером div'a.
HTML
<div id="dummy"></div> <textarea id="editor"></textarea>
CSS
#dummy{ visibility:hidden; font-size:14px; line-height:14px; position:absolute; white-space: pre; word-break: break-all; padding:5px; } textarea{ font-size:14px; line-height:14px; padding:5px; }
var editor = document.getElementById('editor'), dummy = document.getElementById('dummy') editor.addEventListener('keyup',function(){ dummy.innerText = this.value; dummy.style.width = this.offsetWidth+'px'; this.style.height = dummy.offsetHeight+'px'; },false)
Результат
//
Так работают эти плагины. Писал код прямо тут, поэтому за работоспособность не ручаюсь. Но я и не претендую, важно понимать сам процесс. Этот способ самый действенный, и рабочий из предложенных мной.
На мой взгляд код подобного рода должен работать в любом виде, не используя библиотек. Его можно взять в другой проект и не думать о совместимости, подобно тому, как вы берете переносной холодильник в дорогу или на дачу, не думая о проводах и питании.
Однако он очевидно «грязный», лишний элемент на странице, к тому же стили поля и блока не так уж и просто синхронизировать в реальном проекте.
Есть еще два способа. Первый: каждый раз, при редактировании поля, смотреть его scrollHeight и увеличивать его размер на эту длину.
var editor = document.getElementById('editor'); editor.addEventListener('keyup',function(){ this.style.height = this.scrollHeight+this.offsetHeight+'px'; },false)
Результат
// 0) this.style.height = (this.clientHeight+olh)+'px'; },false) // ]]>
Из минусов данного решения, то что при удалении текста из блока, к исходному состоянию его уже не вернуть.
И наконец самое просто решение. Разбивать содержимое поля по /n/r и умножать на высоту строки. Полученную величину присваивать высоте поля.
var editor = document.getElementById('editor'); editor.addEventListener('keyup',function(){ this.style.height = parseInt(this.value.split(/[\n\r]/))*14+'px'; },false)
и css
teaxtarea{ line-height:14px; font-size:14px; white-space: nowrap;// для того чтобы строки не переносились }
Результат
//
этот способ тоже имеет один недостаток. Если строка по ширине больше чем поле, что она не переносится а уходит за его пределы. При этом появляется полоса прокрутки.
Комментарии
не работает ни хрена, вот и не понимай процесс и не ручайся за работу. а ещё лучше не пиши больше