Так сложилось, что первая версия скрипта для автоматического растягивания поля комментария в WordPress оказалась немного бракованной
. Когда я её тестировал почему то не заметил бага. Баг заключался в том, что при сильном растягивании поля, экран начинал прыгать наверх при нажатии на любую клавишу, в результате большой комментарий оставить вообще не представлялось возможным, а это непростительный баг. Кроме этого, в ИЕ8 скрипт немного или сильно тормозил (зависит от компа и других подключенных скриптов).
В общем, проведя не один час в попытках починить скрипт, я понял что сделать это невозможно (нужно было что-то менять кардинально). В результате, я начал искать альтернативное решение. Попадались решения основанные на jQuery, но по отзывам они тоже были грузовые и требовали подключение библиотеки jQuery. Решение с jQuery, для меня это был последний вариант.
Серфинг вывел меня на решение, которое мне показалось очень даже приемлемым с точки зрения удобства. Посмотреть на это решение можете в этой демке (может кому пригодится). Немного поковырявшись со скриптом, я понял что сделать простую интеграцию в WordPress не получится (придется дополнять форму комментирования, добавлять CSS и конечно подключать сам Скрипт), а мне хотелось именно этого, чтобы просто вставил скрипт и готово. Такое сомнительное юзабилити все же не стоит больших усилий.
Поэтому я пошел сёрфить дальше и нашел интересную функцию подсчета строк, которую пришлось доделывать. Но результат меня вполне устроил. Кстати, результат можете посмотреть на этом блоге или взгляните на эту ДЕМО версию.
Из плюсов этого варианта изменения размеров поля комментирования, можно выделить:
- простая интеграция в шаблон;
- автоматическое растягивание поля, т.е. без лишних телодвижений;
- нет тормозов в ИЕ.
А вот собственно скрипт, который у меня получился:
Новый вариант скрипта (от 9 марта 2011) (старый см. ниже). Подсчет высоты принципиально другой, придуман и реализован мной лично. Скрипт кросс-браузерный и не грузит, в отличии от аналогов, комп.
/** Скрипт для автоматического растягивания поля (Textarea) по вертикали (вариант 3). Автор: wp-kama.ru
-----------------------------------------------------------------------------
# Для работы скрипта высота textarea не должна быть определена жёстко (НЕ должно быть определено CSS свойство height),
# вместо height можно использовать min-height:200px; или лучше задать высоту через rows=''.
# Также, можно ограничить максимальную высоту растяжки через CSS свойством max-height:800px;
*/
function _resizer(){
var textarea = 'comment'; // id атрибут тега textarea
var repeat = 500; // время пересчета (1000=1сек).
var cof = 55; // коэффициент. Увеличте, если появляеться прокрутка.
textarea = document.getElementById(textarea);
textarea.onfocus = do_resize;
textarea.onblur = stop_resize;
//функция подсчета строк
function countLines(strtocount) {
var hard_lines = 0;
var str = strtocount.split("\n");
hard_lines = str.length;
var letter_width = textarea.clientHeight/textarea.rows*cof/100; // приблизительная ширина одной буквы в пикселях
var chars_in_line = textarea.clientWidth/letter_width; //сколько букв в строке
var lines = 0;
var temp = 0;
for(i=0; i<=(hard_lines-1); i++){ //hard_lines-1 = количество элементов в массиве
temp = str[i].length / chars_in_line;
if(temp>0) lines += temp;
}
return lines+hard_lines;
}
// Ресайз поля
function do_resize() {
if(!textarea){ return; }
var new_rows = countLines(textarea.value);
if( textarea.rows!=new_rows+1 ) textarea.rows = new_rows;//чтобы не прыгало
timeout_resize = setTimeout(function(){ do_resize(); }, repeat);
}
function stop_resize(){ clearTimeout(timeout_resize); }
}
if (window.addEventListener)
window.addEventListener("load", _resizer, false);
else if (window.attachEvent)
window.attachEvent("onload", _resizer);
Старый вариант функции (считал высоту не точно. Посмотреть СТАРУЮ ДЕМО версию):
/** Скрипт для автоматического растягивания поля (Textarea) по вертикали
-----------------------------------------------------------------------------
Для работы скрипта высота textarea не должна быть определена жёстко (НЕ должен быть определен CSS аргумент height),
вместо height можно использовать min-height или просто задать высоту через rows=''.
Также, можно ограничить максимальную высоту растяжки через CSS аргумент max-height
*/
function _resizer(){
var textareaID = 'comment'; // Иденнтификатор поля textarea
var repeat = 500; // интервал пересчета строк (1000 = 1 секунда)
var the_form = document.getElementById(textareaID);
the_form.onfocus = cleanForm;
function countLines(strtocount, cols) { //функция подсчета строк
var hard_lines = 0;
var last = 0;
while ( true ) {
last = strtocount.indexOf("\n", last+1);
hard_lines ++;
if ( last == -1 ) break;
}
var soft_lines = Math.ceil(strtocount.length / (cols-1));
var hard = eval("hard_lines " + unescape(">") + "soft_lines;");
if ( hard ) soft_lines = hard_lines;
return soft_lines;
}
function cleanForm() { //инициализация подсчета строк
if(the_form){
the_form.rows = countLines(the_form.value,the_form.cols) +1;
setTimeout(function(){ cleanForm(); }, repeat);
}
}
}
if (window.addEventListener)
window.addEventListener("load", _resizer, false);
else if (window.attachEvent)
window.attachEvent("onload", _resizer);
Установка скрипта
1. Скопируйте вышеописанный код в любой уже имеющийся в шаблоне javascript файл;
2. Установите полю textarea CSS свойство min-height (как это сделать см. ниже);
3. (необязательно) Если не хотите чтобы поле тянулось до бесконечности установите ему 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 миллисекунд (пол секунды). Интервал можно увеличить, если наблюдаются тормоза. В вариантах, когда подсчет высоты вешается на нажатие клавиши, везде наблюдаются тормоза, особенно на слабых компах и при быстром печатание.
Если возникнут вопросы задавайте в комментариях!
Вариант авторесайза textarea на jQuery
Для тех у кого установлена библиотека jQuery есть такой вариант авторесайза. Глюков в работе я не заметил, тоже кросс-браузерный. Подробнее о варианте на jQuery смотрите здесь.
А если коротко, то используйте этот код:
/*
* jQuery autoResize (textarea auto-resizer)
* @copyright James Padolsey http://james.padolsey.com
* @version 1.04
*/
(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({resize:'none','overflow-y':'hidden'}),
// 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;
};
/* инициализируем растягивание textarea */
$(function(){
$('textarea').autoResize({
extraSpace:0
});
})
})(jQuery);
Вставьте этот код в имеющийся .js файл или создайте новый .js файл, скопируйте этот код туда и подключите его к сайту.
Код будет работать для всех textarea на сайте. Ручное изменение размеров в Chrome и Safary будет отключено.
- Предыдущие по меткам
- Предыдущие записи
- Как запустить обработку формы используя JavaScript ← 10.Май.2010 // 4
- Если не работает пагинация на странице поиска ← 16 Июль 2010 // 2
- Функция вывода записей по количеству просмотров ← 5 Июль 2010 // 118
- Отключаем уведомления (пинги) на свои же посты ← 5 Июнь 2010 // 8
Снова спасибо за скрипт. Проверил также на Chrome и IE - всё работает отлично.
Но такое одно маленькое замечание. Параметр min-height указывается обязательно, иначе поле будет сжиматься до минимального после полной загрузки страницы и когда по ней нажимаешь. Для примера попробуйте у себя в стилях min-height вырезать и посмотрите что будет.
P.S. По крайней мере, у себя заметил этот косяк. Параметр rows не спасает никак.
Вы правы, черт возьми
А я подумал, что мне показалось. Обновил пост.
Тимур, просто поразительно удобное и невыносимо простое решение (как и все гениальное) После того, как этот скрипт распространится в народе, полосы прокрутки уйдут в небытие.
Я в последнее время просто живу на твоем блоге и мне не хочется отсюда уходить. Каждый вновь открытый пост открывает для меня новое решение давно мозолящей глаза проблемы.
Спасбо! Какие громкие слова, что кажутся они мне лестью. Нет, нет, я не буду брать все это на свой счет, это не совсем про меня пожалуй
Ну какой смысл, Тимур, мне льстить тебе? Я вовсе не хотел этого. Я передавал свои ощущения и абсолютно искренне.
Я ж написал, "что кажутся". В общем, на самом деле я не имел это ввиду.
Я в JS полный ноль, по этому сразу написать изменение в скрипте не смогу, но у меня возник вопрос: а нельзя ли как-нибудь пересчет делать не через каждые пол секунды а по событиям (onMouseOut, onMouseOver, onkeyup) т.е. повесить слушателя на эти события, мне кажется это меньше будет грузить браузер
Можно, изначально так и было на
onkeyupповешено это грузит браузер чувствительно - жмешь любую кнопку и идет пересчет, если быстро пишешь тогда начинаются глюки...На onMouseOut, onMouseOver нелогично как-то совсем уж. Ну, навел мышку скрипт один раз пересчитал поле и все и пишешь коммент уже без растягивания...
в любом случае спс , применил скрипт в работе,
порыскав в инете нашел еще один скриптик:
<textarea style="width:600px; font-size:14px; height:100px;" onkeyup="this.style.height=(a=(e=parseInt(this.style.fontSize)*(this.value.split('\n').length+2)) >(e2=700)?e2:e)<100?100:a;"></textarea>который мне понравился тем что он ну уж очень маленький небольшой скролл не мешает, работает от события onkeyup, был баг на копирование туда текста при помощи клика мыши, легко его устранил добавив событие onMouseOut. Проблема в том что он не работает в IE и в GoogleChrome. Может кто знает как решить эту проблемку?
Интересный пример, я его вроде тоже пробовал, когда этот скрипт делал.
Точно не помню сейчас, но вроде
style.heightв разных браузерах понимается по-разному, поэтому опираясь на это число невозможно сделать такой скрипт кроссбраузерным.У меня в последнем IE и в GoogleChrome 8+, все работает.
лан, тогда кидаю ссылку на сайтик с ним:
http://web-master.tom.ru/view_articles.php?id=29
Во всех вышеуказанных скриптах когда вставляешь большой текст из буфера textarea не растягивается.
Дополнил статью вариантом на jQuery, который подключил к этому блогу. Все работает на ура!
Точно.
Точно, да не точно. Пришлось отказаться от варианта на jQuery. Превью в комментариях отказывалось работать.
Посидел пару часиков изменил свой старый скрипт, причем кардинально поменял функцию подсчета строк. Теперь работает как нужно и кроссбраузерно!
П.С. Обновил пост, думаю теперь он точно заслуживает внимания
А говоришь javascript плохо знаешь.
Так я его плохо знаю. Пока сделал замучился. Там даже не столько javascript сколько идея как реализовать, впрочем, так везде: язык - лишь средство.
сРипт не создает практически...
А что это?
Отловился.
Мне показалось, что была опечатка в демке.
В новой демке в тексте в textarea было написано "Срипт не создает практически..." вместо "Скрипт не создает практически...", но это уже не актуально.
Развитие скрипта
* jQuery autoResize (textarea auto-resizer)
* @copyright James Padolsey http://james.padolsey.com
* @version 1.04
https://github.com/padolsey/jQuery.fn.autoResize
В отличии от упомянутой версии 1.04 как минимум умеет распахивать высоту с учетом ЗАРАНЕЕ введенного содержимого textarea.
То есть
.