Предположим, нам захотелось ограничить длину текста, вводимого пользователем в текстовое поле нашей формы (да-да, примерно как в Твиттере). «Из коробки» Друпал такой возможности нам не предоставляет, свойства элемента формы, задающего максимальную длину текста в textarea — нет. Однако сделать ограничение руками оказывается довольно просто.
Для определенности озвучим задачу: мы хотим, чтобы для текстового поля note длина текста была ограничена заданным числом. При этом пользователю при вводе выводилось бы оставшееся число символов, а текст, введенный сверх этого числа — беспощадно удалялся (для чего задействуем jQuery).
Начнем с описания формы:
$form['note'] = array(
'#type' => 'textarea',
'#title' => t("Note"),
'#description' => '' .t('Note length is limited to @length characters.', array('@length' => $length,)) .'',
'#attributes' => array('class' => 'length-limited'),
);
Здесь в переменной $length
содержится значение максимального количества символов. Выводить его мы будем в описании текстового поля, показывать оставшееся число символов будем там же.
Теперь добавим на страницу с формой небольшой яваскрипт:
Drupal.behaviors.noteBehaviour = function (context) {
var lengthMsg = $("div.note-length-limit-msg");
//будем ограничивать длину только если найдены формы с классом div.note-length-limit-msg
if (lengthMsg.length > 0) {
//определим максимальную длину прямо из текста
var lengthVal = lengthMsg.find("span.note-char-length").text();
lengthVal = (lengthVal - 0); //toInt
//обновим сообщение (а кто выключил JS - будет видеть старое сообщение)
lengthMsg.html(Drupal.t('There are @count characters left', {'@count': lengthVal}));
$("textarea.length-limited").keyup( function() {
var newValue = $(this).val();
if (newValue.length
//еще есть символы, обновим сообщение
lengthMsg.html(Drupal.t('There are @count characters left', {'@count': (lengthVal-newValue.length)}));
lengthMsg.find("span.note-char-length").css("font-weight","normal");
} else {
//лимит превышен, обрезаем текст
$(this).val($(this).val().substr(0,lengthVal));
//выделим нуль, чтобы пользователь заметил
lengthMsg.find("span.note-char-length").css("font-weight","bold");
}
});
}
Вот и все, теперь каждый пользователь с включенным JavaScript-ом сможет уложить свою мысль в выделенные ему $length
символов, а если у него не будет получаться — скрипт поможет (автоматически удалит лишний текст при наборе). Замечу только, что если на одной странице планируется разместить сразу несколько текстовых полей с ограниченной длиной, скрипт придется слегка причесать.
Напоследок не забудем добавить аналогичное ограничение и в валидацию формы, ведь выключившие JS граждане смогут ввести в форму столько символов, сколько им хочется:
if (strlen($form_state['values']['note']) > $length) {
form_set_error('note', t('Maximum note length exceeded.'));
}
Таким образом, получается, что для решения задачи нам необходимо вставить код в трех местах — в описании формы, в валидаторе и в скрипте обработки текстового поля. Ах да, еще и вставить скрипт с помощью drupal_add_js()
. И это придется делать всякий раз, когда мы захотим создать очередное текстовое поле с описанными свойствами. Ситуация неидеальная, имеет смысл ее улучшить. Например, сделать так, чтобы для каждого элемента textarea можно было просто указать свойство, называющееся, скажем, '#max_length', а все остальное делалось автоматически. И три недели назад на горизонте появилось решение в виде модуля Form Extended. Данный модуль как раз задуман для облегчения создания новых свойств элементов форм и их интеграции с существующими формами Друпала (как через API, так и через UI). Правда, в настоящий момент единственный релиз модуля — 'dev', а описание API отсутствует. Можно посмотреть демку, в которой показано текстовое поле с автоподстройкой размера (симпатишное), но про API там тоже ничего нет.
А поскольку изучение API по одному только коду dev-релиза я считаю излишним героизмом, придется применение Form Extended отложить до выхода стабильной версии или хотя бы документации. Как выйдет — постараюсь исследовать API модуля в отдельной заметке. И заодно сравнить его с уже существующим в Друпале хуком hook_elements()
, поскольку с его помощью тоже можно создавать собственные свойства для элементов форм.
На этом пока все.