На элементах формы происходят события клавиатуры и мыши, но есть и несколько других, особенных событий.
Событие change
Событие change происходит по окончании изменения значения элемента формы, когда это изменение зафиксировано.
Для текстовых элементов это означает, что событие произойдёт не при каждом вводе, а при потере фокуса.
Например, пока вы набираете что-то в текстовом поле ниже – события нет. Но как только вы уведёте фокус на другой элемент, например, нажмёте кнопку – произойдёт событие onchange
.
<input type="text" onchange="alert(this.value)">
<input type="button" value="Кнопка">
Для остальных же элементов: select
, input type=checkbox/radio
оно срабатывает сразу при выборе значения.
onchange
в IE8-В IE8- checkbox/radio
при изменении мышью не инициируют событие сразу, а ждут потери фокуса.
Для того, чтобы видеть изменения checkbox/radio
тут же – в IE8- нужно повесить обработчик на событие click
(оно произойдёт и при изменении значения с клавиатуры) или воспользоваться событием propertychange
, описанным далее.
Событие input
Событие input
срабатывает тут же при изменении значения текстового элемента и поддерживается всеми браузерами, кроме IE8-.
В IE9 оно поддерживается частично, а именно – не возникает при удалении символов (как и onpropertychange
).
Пример использования (не работает в IE8-):
<input type="text"> oninput: <span id="result"></span>
<script>
var input = document.body.children[0];
input.oninput = function() {
document.getElementById('result').innerHTML = input.value;
};
</script>
В современных браузерах oninput
– самое главное событие для работы с элементом формы. Именно его, а не keydown/keypress
следует использовать.
Если бы ещё не проблемы со старыми IE… Впрочем, их можно решить при помощи события propertychange
.
IE10-, событие propertychange
Это событие происходит только в IE10-, при любом изменении свойства. Оно позволяет отлавливать изменение тут же. Оно нестандартное, и его основная область использования – исправление недочётов обработки событий в старых IE.
Если поставить его на checkbox
в IE8-, то получится «правильное» событие change
:
<input type="checkbox"> Чекбокс с "onchange", работающим везде одинаково
<script>
var checkbox = document.body.children[0];
if ("onpropertychange" in checkbox) {
// старый IE
checkbox.onpropertychange = function() {
// проверим имя изменённого свойства
if (event.propertyName == "checked") {
alert( checkbox.checked );
}
};
} else {
// остальные браузеры
checkbox.onchange = function() {
alert( checkbox.checked );
};
}
</script>
Это событие также срабатывает при изменении значения текстового элемента. Поэтому его можно использовать в старых IE вместо oninput
.
К сожалению, в IE9 у него недочёт: оно не срабатывает при удалении символов. Поэтому сочетания onpropertychange
+ oninput
недостаточно, чтобы поймать любое изменение поля в старых IE. Далее мы рассмотрим пример, как это можно сделать иначе.
События cut, copy, paste
Эти события используются редко. Они происходят при вырезании/вставке/копировании значения.
К сожалению, кросс-браузерного способа получить данные, которые вставляются/копируются, не существует, поэтому их основное применение – это отмена соответствующей операции.
Например, вот так:
<input type="text" id="input"> event: <span id="result"></span>
<script>
input.oncut = input.oncopy = input.onpaste = function(event) {
result.innerHTML = event.type + ' ' + input.value;
return false;
};
</script>
Пример: поле с контролем СМС
Как видим, событий несколько и они взаимно дополняют друг друга.
Посмотрим, как их использовать, на примере.
Сделаем поле для СМС, рядом с которым должно показываться число символов, обновляющееся при каждом изменении поля.
Как такое реализовать?
Событие input
идеально решит задачу во всех браузерах, кроме IE9-. Собственно, если IE9- нам не нужен, то на этом можно и остановиться.
IE9-
В IE8- событие input
не поддерживается, но, как мы видели ранее, есть onpropertychange
, которое может заменить его.
Что же касается IE9 – там поддерживаются и input
и onpropertychange
, но они оба не работают при удалении символов. Поэтому мы будем отслеживать удаление при помощи keyup
на Delete и BackSpace . А вот удаление командой «вырезать» из меню – сможет отловить лишь oncut
.
Получается вот такая комбинация:
<input type="text" id="sms"> символов: <span id="result"></span>
<script>
function showCount() {
result.innerHTML = sms.value.length;
}
sms.onkeyup = sms.oninput = showCount;
sms.onpropertychange = function() {
if (event.propertyName == "value") showCount();
}
sms.oncut = function() {
setTimeout(showCount, 0); // на момент oncut значение ещё старое
};
</script>
Здесь мы добавили вызов showCount
на все события, которые могут приводить к изменению значения. Да, иногда изменение будет обрабатываться несколько раз, но зато с гарантией. А лишние вызовы легко убрать, например, при помощи throttle
-декоратора, описанного в задаче Тормозящий (throttling) декоратор.
Есть и совсем другой простой, но действенный вариант: через setInterval
регулярно проверять значение и, если оно слишком длинное, обрезать его.
Чтобы сэкономить ресурсы браузера, мы можем начинать отслеживание по onfocus
, а прекращать – по onblur
, вот так:
<input type="text" id="sms"> символов: <span id="result"></span>
<script>
var timerId;
sms.onfocus = function() {
var lastValue = sms.value;
timerId = setInterval(function() {
if (sms.value != lastValue) {
showCount();
lastValue = sms.value;
}
}, 20);
};
sms.onblur = function() {
clearInterval(timerId);
};
function showCount() {
result.innerHTML = sms.value.length;
}
</script>
Обратим внимание – весь этот «танец с бубном» нужен только для поддержки 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
и аналогичные не всплывают. То есть, обработчики нужно назначать на сам элемент, без делегирования.