Ограничение количества символов в textarea

Предположим, нам захотелось ограничить длину текста, вводимого пользователем в текстовое поле нашей формы (да-да, примерно как в Твиттере). «Из коробки» Друпал такой возможности нам не предоставляет, свойства элемента формы, задающего максимальную длину текста в 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(), поскольку с его помощью тоже можно создавать собственные свойства для элементов форм.

На этом пока все.

Комментарии