# Изменение: change, input, cut, copy, paste На элементах формы происходят события клавиатуры и мыши, но есть и несколько других, особенных событий. ## Событие change Событие [change](http://www.w3.org/TR/html5/forms.html#event-input-change) происходит по окончании изменении значения элемента формы, когда это изменение зафиксировано. Для текстовых элементов это означает, что событие произойдёт не при каждом вводе, а при потере фокуса. Например, пока вы набираете что-то в текстовом поле ниже -- события нет. Но как только вы уведёте фокус на другой элемент, например, нажмёте кнопку -- произойдет событие `onchange`. ```html autorun height=40 ``` Для остальных же элементов: `select`, `input type=checkbox/radio` оно срабатывает сразу при выборе значения. ```warn header="Поздний `onchange` в IE8-" В IE8- `checkbox/radio` при изменении мышью не инициируют событие сразу, а ждут потери фокуса. Для того, чтобы видеть изменения `checkbox/radio` тут же -- в IE8- нужно повесить обработчик на событие `click` (оно произойдет и при изменении значения с клавиатуры) или воспользоваться событием `propertychange`, описанным далее. ``` ## Событие input Событие `input` срабатывает *тут же* при изменении значения текстового элемента и поддерживается всеми браузерами, кроме IE8-. В IE9 оно поддерживается частично, а именно -- *не возникает при удалении символов* (как и `onpropertychange`). Пример использования (не работает в IE8-): ```html autorun height=40 oninput: ``` В современных браузерах `oninput` -- самое главное событие для работы с элементом формы. Именно его, а не `keydown/keypress` следует использовать. Если бы ещё не проблемы со старыми IE... Впрочем, их можно решить при помощи события `propertychange`. ## IE10-, событие propertychange Это событие происходит только в IE10-, при любом изменении свойства. Оно позволяет отлавливать изменение тут же. Оно нестандартное, и его основная область использования -- исправление недочётов обработки событий в старых IE. Если поставить его на `checkbox` в IE8-, то получится "правильное" событие `change`: ```html autorun height=40 Чекбокс с "onchange", работающим везде одинаково ``` Это событие также срабатывает при изменении значения текстового элемента. Поэтому его можно использовать в старых IE вместо `oninput`. К сожалению, в IE9 у него недочёт: оно не срабатывает при удалении символов. Поэтому сочетания `onpropertychange` + `oninput` недостаточно, чтобы поймать любое изменение поля в старых IE. Далее мы рассмотрим пример, как это можно сделать иначе. ## События cut, copy, paste Эти события используются редко. Они происходят при вырезании/вставке/копировании значения. К сожалению, кросс-браузерного способа получить данные, которые вставляются/копируются, не существует, поэтому их основное применение -- это отмена соответствующей операции. Например, вот так: ```html autorun height=40 event: ``` ## Пример: поле с контролем СМС Как видим, событий несколько и они взаимно дополняют друг друга. Посмотрим, как их использовать, на примере. Сделаем поле для СМС, рядом с которым должно показываться число символов, обновляющееся при каждом изменении поля. Как такое реализовать? Событие `input` идеально решит задачу во всех браузерах, кроме IE9-. Собственно, если IE9- нам не нужен, то на этом можно и остановиться. ### IE9- В IE8- событие `input` не поддерживается, но, как мы видели ранее, есть `onpropertychange`, которое может заменить его. Что же касается IE9 -- там поддерживаются и `input` и `onpropertychange`, но они оба не работают при удалении символов. Поэтому мы будем отслеживать удаление при помощи `keyup` на `key:Delete` и `key:BackSpace` . А вот удаление командой "вырезать" из меню -- сможет отловить лишь `oncut`. Получается вот такая комбинация: ```html autorun run height=60 символов: ``` Здесь мы добавили вызов `showCount` на все события, которые могут приводить к изменению значения. Да, иногда изменение будет обрабатываться несколько раз, но зато с гарантией. А лишние вызовы легко убрать, например, при помощи `throttle`-декоратора, описанного в задаче . **Есть и совсем другой простой, но действенный вариант: через `setInterval` регулярно проверять значение и, если оно слишком длинное, обрезать его.** Чтобы сэкономить ресурсы браузера, мы можем начинать отслеживание по `onfocus`, а прекращать -- по `onblur`, вот так: ```html autorun height=60 символов: ``` Обратим внимание -- весь этот "танец с бубном" нужен только для поддержки IE8-, в которых не поддерживается `oninput` и IE9, где `oninput` не работает при удалении. ## Итого События изменения данных: | Событие | Описание | Особенности | |---------|----------|-------------| | `change`| Изменение значения любого элемента формы. Для текстовых элементов срабатывает при потере фокуса. | В IE8- на чекбоксах ждет потери фокуса, поэтому для мгновенной реакции ставят также onclick-обработчик или onpropertychange. | | `input` | Событие срабатывает только на текстовых элементах. Оно не ждет потери фокуса, в отличие от change. | В IE8- не поддерживается, в IE9 не работает при удалении символов. | | `propertychange` | Только для IE10-. Универсальное событие для отслеживания изменения свойств элементов. Имя изменённого свойства содержится в `event.propertyName`. Используют для мгновенной реакции на изменение значения в старых IE. | В IE9 не срабатывает при удалении символов. | | `cut/copy/paste` | Срабатывают при вставке/копировании/удалении текста. Если в их обработчиках отменить действие браузера, то вставки/копирования/удаления не произойдёт. | Вставляемое значение получить нельзя: на момент срабатывания события в элементе всё ещё *старое* значение, а новое недоступно. | Ещё особенность: в IE8- события `change`, `propertychange`, `cut` и аналогичные не всплывают. То есть, обработчики нужно назначать на сам элемент, без делегирования.