Автоматическое растягивание 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: https://amaury.carrade.eu/projects/jquery/autoResize.html
Поделюсь сразу сжатой версией кода плагина:
/* * 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 миллисекунд (пол секунды). Интервал можно увеличить, если наблюдаются тормоза. В вариантах, когда подсчет высоты вешается на нажатие клавиши, везде наблюдаются тормоза, особенно на слабых компах и при быстром печатание.
Если возникнут вопросы задавайте в комментариях!