Автоматическое растягивание textarea на javascript и jQuery
Очень удобно, когда поле для ввода текста растягивается в высоту по мере ввода текста. Для этого в современных бразуерах есть возможность растянуть поле. А в этой заметке мы поговорим о том, как сделать так, чтобы поле textarea растягивалось автоматически когда текста в нем больше чем оно может поместить.
Вариант 1: авто-растягивания textarea (на чистом javascript)
Пожалуй это лучшее решение.
Скрипт находится по этой ссылке: https://github.com/jackmoore/autosize
А это прямая ссылка на сам javascript код, который нужно подключить к html: https://github.com/jackmoore/autosize/blob/master/src/autosize.js
Установка проста: подключаете файл скрипта с помощью wp_enqueue_script(). Затем подключаете растягивание к элементу textarea одним из следующих вариантов:
// список элементов
autosize( document.querySelectorAll('textarea') );
// один элемент
autosize( document.querySelector('textarea') );
// jQuery элементы
autosize( $('textarea') );
Поддержка браузеров:
| Chrome | Firefox | IE | Safari | iOS Safari | Android | Opera Mini |
|---|---|---|---|---|---|---|
| yes | yes | 9 | yes | yes | 4 | ? |
Вариант 2: авто-растягивания textarea (jQuery плагин)
Если у вас на сайте установлена библиотека jQuery, то рекомендую хороший плагин для автоматического растягивания textarea:
Сжатая версия кода плагина:
/*
* jQuery autoResize (textarea auto-resizer)
* @copyright James Padolsey http://james.padolsey.com
* @version 1.04.1 (kama fix)
*/
(function(b){b.fn.autoResize=function(f){var a=b.extend({onResize:function(){},animate:!0,animateDuration:150,animateCallback:function(){},extraSpace:20,limit:1E3},f);this.filter("textarea").each(function(){var d=b(this).css({"overflow-y":"hidden",display:"block"}),f=d.height(),g=function(){var c={};b.each(["height","width","lineHeight","textDecoration","letterSpacing"],function(b,a){c[a]=d.css(a)});return d.clone().removeAttr("id").removeAttr("name").css({position:"absolute",top:0,left:-9999}).css(c).attr("tabIndex","-1").insertBefore(d)}(),h=null,e=function(){g.height(0).val(b(this).val()).scrollTop(1E4);var c=Math.max(g.scrollTop(),f)+a.extraSpace,e=b(this).add(g);h!==c&&(h=c,c>=a.limit?b(this).css("overflow-y",""):(a.onResize.call(this),a.animate&&"block"===d.css("display")?e.stop().animate({height:c},a.animateDuration,a.animateCallback):e.height(c)))};d.unbind(".dynSiz").bind("keyup.dynSiz",e).bind("keydown.dynSiz",e).bind("change.dynSiz",e)});return this}})(jQuery);
// инициализация
jQuery(function(){
jQuery('textarea').autoResize();
});
После установки этого кода, все textarea должны автоматически растягиваться.
Поддержка браузеров:
- IE 6-8
- Firefox 3.5
- Opera 9.5-10
- Safari 3
- Chrome 10
Во время тестирования выяснил, что у textarea обязательно должно быть установлено css свойство display:block, иначе никакая анимация в плагине не работала (браузер chrome). Поэтому добавил в плагин пару строк кода, чтобы он сам устанавливал это свойство. Также, в некоторых браузерах есть возможность изменять размер поля вручную (в углу треугольничек), плагин эту возможность зачем-то убирал, я её вернул. Поэтому в заголовке @version 1.04.1 (kama fix)
Несжатая версия кода плагина:
/*
* jQuery autoResize (textarea auto-resizer)
* @copyright James Padolsey http://james.padolsey.com
* @version 1.04.1 (kama fix)
*/
(function($){
$.fn.autoResize = function(options) {
// Just some abstracted details,
// to make plugin users happy:
var settings = $.extend({
onResize : function(){
},
animate : true,
animateDuration : 150,
animateCallback : function(){},
extraSpace : 20,
limit: 1000
}, options);
// Only textarea's auto-resize:
this.filter('textarea').each(function(){
// Get rid of scrollbars and disable WebKit resizing:
var textarea = $(this).css({'overflow-y':'hidden', display:'block'}),
// Cache original height, for use later:
origHeight = textarea.height(),
// Need clone of textarea, hidden off screen:
clone = (function(){
// Properties which may effect space taken up by chracters:
var props = ['height','width','lineHeight','textDecoration','letterSpacing'],
propOb = {};
// Create object of styles to apply:
$.each(props, function(i, prop){
propOb[prop] = textarea.css(prop);
});
// Clone the actual textarea removing unique properties
// and insert before original textarea:
return textarea.clone().removeAttr('id').removeAttr('name').css({
position: 'absolute',
top: 0,
left: -9999
}).css(propOb).attr('tabIndex','-1').insertBefore(textarea);
})(),
lastScrollTop = null,
updateSize = function() {
// Prepare the clone:
clone.height(0).val($(this).val()).scrollTop(10000);
// Find the height of text:
var scrollTop = Math.max(clone.scrollTop(), origHeight) + settings.extraSpace,
toChange = $(this).add(clone);
// Don't do anything if scrollTip hasen't changed:
if (lastScrollTop === scrollTop) { return; }
lastScrollTop = scrollTop;
// Check for limit:
if ( scrollTop >= settings.limit ) {
$(this).css('overflow-y','');
return;
}
// Fire off callback:
settings.onResize.call(this);
// Either animate or directly apply height:
settings.animate && textarea.css('display') === 'block' ?
toChange.stop().animate({height:scrollTop}, settings.animateDuration, settings.animateCallback)
: toChange.height(scrollTop);
};
// Bind namespaced handlers to appropriate events:
textarea
.unbind('.dynSiz')
.bind('keyup.dynSiz', updateSize)
.bind('keydown.dynSiz', updateSize)
.bind('change.dynSiz', updateSize);
});
// Chain:
return this;
};
})(jQuery);
Настройка плагина
Во время инициализации плагину можно установить некоторые параметры.
1. Уберем отступ снизу, по умолчанию он равен 20 пикселей:
jQuery('textarea').autoResize({
extraSpace : 0
});
2. Вешаем действия на события в момент ресайза и после него - настройки onResize и animateCallback:
jQuery('textarea').autoResize({
// Во время ресайза:
onResize : function() {
jQuery(this).css({ color:'#666', background:'#eee' });
},
// После ресайза:
animateCallback : function() {
jQuery(this).css({ color:'#222', background:'#fff' });
}
});
Все настройки
- onResize(функция)
- Функция вызывается в момент изменения размера textarea. Передает объект textarea, т.е. в функции "this" будет рабочий textarea.
- animate(логический)
- Включена ли анимация изменения высоты. true - включена.
По умолчанию: true - animateDuration(число)
- Время, которое занимает анимация в миллисекундах.
По умолчанию: 150 - animateCallback(функция)
- Вызывается при окончании анимации.
- extraSpace(число)
- Отступ у textarea снизу в пикселях.
По умолчанию: 20 - limit(число)
- Максимальная высота textarea в пикселях. Выше появится скролл.
По умолчанию: 1000
Вариант 3: авто-растягивания textarea (мой старый скрипт)
Так сложилось, что первая версия скрипта для автоматического растягивания поля комментария в WordPress оказалась не самой лучшей
. Когда я её тестировал почему то не заметил баг, который заключался в том, что при сильном растягивании поля, экран начинал прыгать наверх при нажатии на любую клавишу, в результате большой комментарий оставить вообще не представлялось возможным
. Кроме этого, в IE 8 скрипт тормозил.
В общем, проведя не один час в попытках починить скрипт, я понял, что сделать это невозможно - нужно что-то кардинально менять. В результате, начал искать альтернативное решение. Попадались решения основанные на jQuery, но мне хотелось сделать на чистом JS. Решение с jQuery я оставил на крайний случай.
Серфинг вывел меня на решение, которое мне показалось приемлемым с точки зрения удобства. Посмотреть на это решение можете в этой демке (может кому пригодится). Немного поковырявшись со скриптом, я понял что сделать простую интеграцию в WordPress не получится (придется дополнять форму комментирования, добавлять CSS и конечно подключать сам Скрипт), а мне хотелось, чтобы было так: вставил скрипт и готово. Ведь, такое сомнительное юзабилити не стоит лишних усилий.
Поэтому я пошел сёрфить дальше и нашел интересную функцию подсчета строк, которую и доделал. Результат меня вполне устроил: взгляните на эту ДЕМО версию.
Из плюсов этого варианта изменения размеров поля комментирования, можно выделить:
- простая интеграция в шаблон;
- хороший подсчет высоты;
- не тормозит.
Очередной новый вариант, от 16 декабря 2013 года. Подправил код, исправил баг - код был написан немного не корректно и мог нагружать компьютер. Теперь этого нет.
Установка скрипта
-
Скопируйте вышеописанный код в любой уже имеющийся в шаблоне javascript файл;
-
Установите полю textarea CSS свойство min-height (как это сделать см. ниже);
- (необязательно) Если не хотите, чтобы поле тянулось до бесконечности установите ему CSS свойство max-height;
Как вставить скрипт прямо в файл темы:
Если js файла у вас в шаблоне нет, то можно его создать, скопировать туда код, а затем подключить файл к шаблону.
Или можно просто подключить выше написанный код в ваш файл шаблона single.php, вставив такую конструкцию в файл:
<script type="text/javascript">/* <![CDATA[ */ Здесь код /* ]]> */</script>
Как установить полю textarea css свойство min-height
Вариант 1: Откройте файл comments.php найдите там HTML тег textarea и добавьте к нему style='min-height:200px; max-height:700px;'. На вид примерно так:
<textarea style="min-height:200px; max-height:700px;" rows="58" name="comment" id="comment" tabindex="4"></textarea>
max-height:700px; можно не добавлять - это максимальная длинна до которой будет растягиваться поле.
Вариант 2: Найдите в вашем файле стилей (style.css) класс, который отвечает за поле textarea и добавьте к нему CSS свойство min-height:200px;. Если там присутствует свойство height:XXXpx, то его нужно удалить.
Несколько вариантов как может называться класс который отвечает за поле:
#commentform textarea{}
#respond textarea{}
#comment{}
textarea#comment{}
Тех. подробности: как работает скрипт
Принцип работы кода заключается в следующем: когда курсор попадает в поле комментирования включается периодический подсчет строк (каждые пол секунды), когда курсор выходит из поля, подсчет строк останавливается. Строки считаются путем суммы количества явных переносов строки (\n) и вычисление неявных переносов (когда строка переводится на новую из-за нехватки ширины поля, над этим моментом пришлось биться долго и муторно).
Принципиальная разница с прошлым вариантом в том, что применяется другая технология подсчета строк и строки считаются не по нажатию клавиши а спустя какое-то время, в нашем случае 500 миллисекунд (пол секунды). Интервал можно увеличить, если наблюдаются тормоза. В вариантах, когда подсчет высоты вешается на нажатие клавиши, везде наблюдаются тормоза, особенно на слабых компах и при быстром печатание.
Если возникнут вопросы задавайте в комментариях!