Книга: JavaScript. Подробное руководство, 6-е издание

17.8. События ввода текста

17.8. События ввода текста

Броузеры поддерживают три старых события ввода с клавиатуры. События «keydown» и «keyup» являются низкоуровневыми событиями и рассматриваются в следующем разделе. Однако событие «keypress» является высокоуровневым, сообщающим, что был введен печатаемый символ. Проект спецификации «DOM Level 3 Events» определяет более обобщенное событие «textinput», генерируемое в ответ на ввод текста, независимо от того, каким способом он был введен (например, с клавиатуры, копированием данных из буфера обмена или с помощью операции буксировки, методом ввода текста на азиатских языках или с помощью системы распознавания речи или распознавания рукописного текста). На момент написания этих строк событие «textinput» еще не поддерживалось, но броузеры на основе ядра Webkit поддерживали очень похожее событие «textInput» (с заглавной буквой «I»).

С предлагаемым событием «textinput» и реализованным в настоящее время событием «textInput» передается простой объект события, имеющий свойство data, хранящее введенный текст. (Другое предлагаемое спецификацией свойство, inputMethod, должно определять источник ввода, но оно пока не реализовано.) В случае ввода с клавиатуры свойство data обычно будет содержать единственный символ, но при вводе из других источников в нем может содержаться множество символов.

Объект события, передаваемый с событием «keypress», имеет более сложную организацию. Событие «keypress» представляет ввод единственного символа. Этот символ содержится в объекте события в виде числового значения кодового пункта Юникода и, чтобы преобразовать его в строку, необходимо использовать метод String.fromCharCode(). В большинстве броузеров кодовый пункт введенного символа сохраняется в свойстве keyCode объекта события. Однако по историческим причинам в Firefox вместо него используется свойство charCode. В большинстве броузеров событие «keypress» возбуждается только при вводе печатаемого символа. Однако в Firefox событие «keypress» возбуждается также для непечатаемых символов. Чтобы отличить эти два случая (и проигнорировать непечатаемые символы), можно проверить, существует ли свойство charCode объекта события и содержит ли оно значение 0.

События «textinput», «textinput» и «keypress» можно отменить, чтобы предотвратить ввод символа. То есть эти события можно использовать для фильтрации ввода. Например, можно предотвратить ввод алфавитных символов в поле, предназначенное для ввода числовых данных. В примере 17.6 демонстрируется модуль на языке JavaScript, реализующий такого рода фильтрацию. Он отыскивает элементы <input type=text> с дополнительным (нестандартным) атрибутом data-allowed-chars. Регистрирует обработчики событий «textinput», «textInput» и «keypress» для всех найденных элементов и ограничивает возможность ввода символами, перечисленными в атрибуте data-allowed-chars. Первый комментарий в начале примера 17.6 включает образец разметки HTML, использующей этот модуль.

Пример 17.6. Фильтрация ввода пользователя

/**
* InputFilter.js: фильтрация ввода для элементов <input>
*
* Этот модуль отыскивает все элементы <input type="text"> в документе, имеющие
* атрибут "data-allowed-chars". Регистрирует обработчики событий keypress, textinput
* и textinput для этих элементов, чтобы ограничить набор допустимых для ввода символов,
* чтобы разрешить вводить только символы, указанные в атрибуте. Если элемент <input>
* также имеет атрибут "data-messageid", значение этого атрибута интерпретируется как id
* другого элемента документа. Если пользователь вводит недопустимый символ, элемент
* с указанным id делается видимым. Если пользователь вводит допустимый символ, элемент
* с сообщением скрывается. Данный элемент с сообщением предназначается для вывода
* пояснений, почему ввод пользователя был отвергнут. Его оформление необходимо
* реализовать с помощью CSS так, чтобы изначально он был невидим.
*
* Ниже приводится образец разметки HTML, использующей этот модуль.
* Zipcode: <inputtext"
* data-allowed-chars="0123456789" data-messageid="zipwarn">
* <span>TonbKo цифры</зрап>
*
* Этот модуль полностью реализован в ненавязчивом стиле: он не определяет
* никаких переменных в глобальном пространстве имен.
*/
whenReady(function () { // Вызовет эту функцию, когда документ будет загружен
  // Отыскать все элементы <input>
  var inputelts = document.getElementsByTagName("input");
  // Обойти их в цикле
  for(var і = 0 ; і < inputelts.length; i++) {
    var elt = inputelts[i];
    // Пропустить элементы, не являющиеся текстовыми полями ввода
    // и не имеющие атрибута data-allowed-chars.
    if (elt.type != "text" || !elt.getAttribute(”data-allowed-chars")) continue;
    // Зарегистрировать наш обработчик события в этом элементе input
    // keypress - старое событие и реализовано во всех броузерах.
    // textInput (смешанный регистр символов) поддерживается в Safari
    // и Chrome с 2010 года.
    // textinput (все символы строчные) - версия проекта
    // стандарта "DOM Level 3 Events",
    if (elt.addEventListener) {
      elt.addEventListener("keypress", filter, false);
      elt.addEventListener("textlnput", filter, false);
      elt.addEventListened"textinput", filter, false);
    }
    // textinput не поддерживается версиями IE, в которых не реализован
    // метод addEventListener()
    else {
     elt.attachEvent("onkeypress", filter);
    }
  }
  // Обработчик событий keypress и textlnput, фильтрующий ввод пользователя
  function filter(event) {
    // Получить объект события и целевой элемент target
    var е = event || window.event; // Модель стандартная или IE
    var target = e.target || e.srcElement; // Модель стандартная или IE
    var text = null; // Введенный текст
    // Получить введенный символ или текст
    if (e.type === "textinput" || e.type === "textlnput")
      text = e.data;
    else { // Это было событие keypress
      // Введенный печатаемый символ в Firefox сохраняется в свойстве charCode
      var code = е.charCode || e.keyCode;
      // Если была нажата какая-либо функциональная клавиша, не фильтровать ее
      if (code < 32 || // Управляющий символ ASCII
             е.charCode == 0 || // Функциональная клавиша (в Firefox)
             e.ctrlKey || e.altKey) // Удерживаемая клавиша-модификатор
        return; // Не фильтровать это событие
      // Преобразовать код символа в строку
      var text = String.fromCharCode(code);
    }
    // Отыскать необходимую нам информацию в этом элементе input
    var allowed = target.getAttribute("data-allowed-chars");// Допустимые символы
    var messageid = target.getAttribute("data-messageid"); // Сообщение id
    if (messageid) // Если указано значение id, получить элемент
      var messageElement = document.getElementByld(messageid);
    // Обойти в цикле символы во введенном тексте
    for(var і = 0; і < text.length; i++) {
      var c = text.charAt(i);
      if (allowed.indexOf(c) == -1) { // Недопустимый символ?
        // Отобразить элемент с сообщением, если указан
        if (messageElement) messageElement.style.visibility="visible";
        // Отменить действия по умолчанию, чтобы предотвратить вставку текста
        if (е.preventDefault) е.preventDefault();
        if (е.returnValue) е.returnValue = false;
        return false;
      }
    }
    // Если все символы оказались допустимыми, скрыть элемент
    // с сообщением, если он был указан.
    if (messageElement) messageElement.style.visibility = "hidden";
  }
}):

События «keypress» и «textinput» генерируются непосредственно перед фактической вставкой нового текста в элемент документа, обладающий фокусом ввода, благодаря чему обработчики этих событий могут предотвратить вставку текста, отменив событие. Броузеры также реализуют событие «input», которое возбуждается после вставки текста в элемент. Это событие нельзя отменить и соответствующий ему объект события не содержит информации о вставленном тексте - оно просто извещает о том, что текстовое содержимое элемента изменилось. Если, к примеру, потребуется обеспечить ввод только символов в верхнем регистре, можно определить обработчик события «input», как показано ниже:

SURNAME: <input type="text">

Событие «input» стандартизовано в спецификации HTML5 и поддерживается всеми современными броузерами, кроме IE. Похожего эффекта в IE можно добиться, обнаруживая изменение значения свойства value текстового элемента ввода с помощью нестандартного события «propertychange*. В примере 17.7 демонстрируется, как можно реализовать преобразование всех вводимых символов в верхний регистр переносимым образом.

Пример 17.7. Использование события «propertychange» для определения факта ввода текста

function forceToUpperCase(element) {
  if (typeof element === "string") element=document.getElementByld(element);
  element.oninput = upcase;
  element.onpropertychange = upcaseOnPropertyChange;
  // Простой случай: обработчик события input
  function upcase(event) { this.value = this.value.toUpperCase(): }
  // Сложный случай: обработчик события propertychange
  function upcaseOnPropertyChange(event) {
    var e = event || window.event;
    // Если значение свойства value изменилось
    if (e.propertyName === "value") {
      // Удалить обработчик onpropertychange, чтобы избежать рекурсии
      this.onpropertychange = null;
      // Преобразовать все символы в верхний регистр
      this.value = this.value.toUpperCase();
      // И восстановить обработчик события propertychange
      this.onpropertychange = upcaseOnPropertyChange;
    }
  }
}

Оглавление книги


Генерация: 1.931. Запросов К БД/Cache: 3 / 0
поделиться
Вверх Вниз