Мастер-классы по Javascript Екатеринбург Ростов-на-Дону Москва Узнать больше...
Содержание (скрыть) Содержание (показать)

События "change", "input", "propertychange"

  1. Событие change
  2. Событие propertychange
  3. Событие input
  4. События cut, copy, paste
  5. Пример: поле для СМС
  6. Итого

На элементах формы происходят события клавиатуры и мыши, но есть и несколько других, особенных событий.

Событие change

Событие change происходит при изменении значения элемента формы. По стандарту, оно должно происходить после того, как элемент теряет фокус.

В реальности оно так и происходит для текстовых элементов.

Например, пока вы набираете что-то в текстовом поле ниже — события нет. Но как только вы уведёте фокус на другой элемент, например, нажмёте кнопку — произойдет событие onchange.

<input type="text" onchange="alert(this.value)">
<input type="button" value="Кнопка">

Для остальных же элементов: select, input type=checkbox/radio наблюдается кросс-браузерный зоопарк. Браузеры стараются генерировать событие при выборе значения, еще до потери фокуса элементом.

Зоопарк для change на input type=checkbox/radio
  • Элементы checkbox/radio при изменении мышью инициируют событие тут же везде, кроме IE<9.
    В IE<9 они ждут потери фокуса.
  • Элемент select также генерирует событие тут же при выборе значения везде, кроме Opera и IE<9.
    В Opera/IE<9 они также генерируются при переборе значений с клавиатуры клавишами вверх-вниз.

Вы можете увидеть это самостоятельно в примере ниже:

<select onchange="alert(this.value)">
  <option value="1">1</option>
  <option value="2">2</option>
  <option value="3">3</option>
</select>
<input type="checkbox" onchange="alert(this.checked)">
<input type="button" value="Кнопка">

Выводы:

  • Для того, чтобы видеть изменение checkbox/radio тут же — в IE<9 нужно повесить обработчик на событие click (оно произойдет и при изменении значения с клавиатуры) или воспользоваться событием propertychange, описанным ниже.
  • С select обычно ничего такого не делают. В Opera/IE<9 будет работать немного по-другому при использовании клавиатуры для выбора.

Событие propertychange

Это событие происходит только в IE, при любом изменении свойства. Оно позволяет отлавливать изменение тут же.

Если поставить его на checkbox в IE<9, то получится «правильное» событие 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>

Это событие также срабатывает при изменении значения текстового элемента, но по каким-то причинам, известным лишь в Индии - кроме удаления символов.

Попробуйте набрать что-то в текстовом поле, а затем удалить. При удалении значение в span не будет обновляться.

Пример — только для IE:

<input type="text"> onpropertychange: <span id="result"></span>
<script>
var input = document.body.children[0];

input.onpropertychange = function() {
  if (event.propertyName == "value") {
      document.getElementById('result').innerHTML = input.value;
  }
}
</script>

События изменения DOM

В браузерах, за исключением IE<9 и Safari/Chrome, существует аналогичное событие DOMAttrModified, а также ряд других событий на изменение и добавление узлов.

Они описаны в стандарте Mutation Events. Но эта часть стандарта реализована в браузерах частично, с многочисленными ошибками, и объявлена устаревшей.

На практике такие события нужны, в основном, при отладке. А современные отладчики (Chrome/Safari, Firefox) позволяют вставить точку останова при изменении DOM и без этих событий.

Событие input

Событие input срабатывает тут же при изменении значения текстового элемента и поддерживается всеми браузерами, кроме IE<9.

В IE9 оно поддерживается частично, а именно — не возникает при удалении символов.

Пример использования (не работает в IE<9):

<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>

События cut, copy, paste

Эти события используются редко, но иногда бывают полезны. Они происходят при вырезании/вставке/копировании значения в поле.

При этом действие браузера можно отменить, как это сделано в примере ниже:

<input type="text"> event: <span id="result"></span>
<script>
var input = document.body.children[0];

input.oncut = input.oncopy = input.onpaste = function(e) {
  e = e || event;
  document.getElementById('result').innerHTML = e.type +' '+input.value;
  return false;
}
</script>

Эти события не дают доступ к данным, которые вставляются.

Также существуют события beforecut/beforecopy/beforepaste. Они интересны тем, что return false из beforecut/beforepaste позволяет включить вырезание/вставку для нередактируемых элементов. В дальнейшем эти действия можно будет обработать в событиях cut/paste

К сожалению, они нормально работают только в IE.

<div onbeforecut="return false" onbeforepaste="return false">
Для этого DIV включены команды меню Вырезать/Вставить (IE)
</div>

Пример: поле для СМС

Сделаем поле для СМС, рядом с которым должно показываться число символов, обновляющееся при каждом изменении поля.

Как такое реализовать?

Событие input придумано специально для таких случаев. И оно идеально решает задачу во всех браузерах, кроме IE.

Но в IE<9 это событие не поддерживается, а в IE9 не работает при удалении. Что делать?

Вместо input для IE можно использовать propertychange, но оно не работает при удалении символов.

Впрочем, это не так страшно. Удаление нажатием Delete/BackSpace замечательно поймает keyup. А вот удаление командой «вырезать» из меню — сможет лишь отловить oncut.

Получается вот такая комбинация:

<input type="text"> символов: <span id="result"></span>
<script>
var input = document.body.children[0];

function showCount() {
  document.getElementById('result').innerHTML = input.value.length;
}

input.oncut = input.onkeyup = input.oninput = showCount;
input.onpropertychange = function() {
  if (event.propertyName == "value") showCount();
}
</script>

Теперь всё отлично, только вот событие cut срабатывает до вырезания, поэтому значение поля в нём еще не обновлено. В результате при вырезании мышью в IE количество символов не изменится. Как исправить этот маленький недостаток, мы увидим далее, при рассмотрении трюка setTimeout(.., 0).

Итого

События изменения данных:

Событие Описание Особенности
change Изменение значения любого элемента формы. Для текстовых элементов срабатывает при потере фокуса.

Для select/checkbox/radio браузеры инициируют его при выборе.

Для Opera/IE<9 срабатывает при переборе значений select с клавиатуры.

Для IE<9 на чекбоксах ждёт потери фокуса.

input Событие срабатывает только на текстовых элементах. Оно не ждет потери фокуса в отличие от change. В IE<9 не поддерживается, в IE9 не работает при удалении.
propertychange Только для IE. Универсальное событие для отслеживания изменения свойств элементов. Имя изменённого свойства содержится в event.propertyName.

Аналог в других браузерах, кроме Safari/Chrome — DOMAttrModified.

Не срабатывает при удалении символов из текстового поля.
cut/copy/paste Срабатывают при вставке/копировании/удалении текста. В них отменить действие браузера. Вставляемое значение получить нельзя. На момент срабатывания события в элементе всё ещё старое значение.

Для того, чтобы на чекбоксах в IE<9 отлавливать изменение тут же — можно повесить обработчик на click или использовать событие propertychange в дополнение к change.

В IE<9 события change(и аналогичные) не всплывают.

Можно увидеть это на следующем примере:

<form oninput="log(event)" onchange="log(event)" onpropertychange="log(event)" oncut="log(event)">
<input type="text"> <span id="log"></span>
</form>

<script>
function log(event) {
  document.getElementById('log').innerHTML += ' '+event.type;
}
</script>
Для всех браузеров, кроме IE<9 события будут ловиться на FORM и отображаться справа от INPUT.

Создайте интерфейс для автоматического вычисления процентов по вкладу.

Ставка фиксирована: 12% годовых. При включённом поле «капитализация» — проценты приплюсовываются к сумме вклада каждый месяц (сложный процент).

Пример:

Технические требования:

  • В поле с суммой должно быть нельзя ввести не-цифру. При этом пусть в нём работают специальные клавиши и сочетания Ctrl-X/Ctrl-V.
  • Изменения в форме отражаются в результатах сразу.

Исходный документ: tutorial/form/percent-src.html.

Решение, шаг 1
Решение
Решение, шаг 1

Алгоритм решения такой.

Только численный ввод в поле с суммой разрешаем, повесив обработчик на keypress.

Отслеживаем события изменения для перевычисления результатов:

  • На input: событие input и дополнительно propertychange/keyup для совместимости со старыми IE.
  • На checkbox: событие click вместо change для совместимости с IE<9.
  • На select: событие change.
Решение, шаг 2
Решение, шаг 2

Решение: tutorial/form/percent.html.


Комментарии

  1. Приветствуются комментарии, содержащие дополнения и вопросы по статье, и ответы на них.
  2. Если ваш комментарий касается задачи -- откройте её в отдельном окне и напишите там.
  3. Комментарии без смысла, с рекламой или не о статье вообще - удаляются.
Наверх

Содержание

Реклама

Нашли опечатку?

Нашли опечатку на сайте? Что-то кажется странным?
Выделите соответствующий текст и нажмите Ctrl+Enter!

Последние Комментарии

Помоги другим!

Помоги другим узнать о хорошей статье!