- Изменение: change, input, cut, copy, paste
- Событие change
- Событие input
- IE10-, событие propertychange
- События cut, copy, paste
- Пример: поле с контролем СМС
- IE9-
- Итого
- Задачи
- Автовычисление процентов по вкладу
- Комментарии
- Javascript file input on change
- # File input change event not working in JavaScript [Solved]
- # Additional Resources
Изменение: change, input, cut, copy, paste
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/events-change-input.
На элементах формы происходят события клавиатуры и мыши, но есть и несколько других, особенных событий.
Событие change
Событие change происходит по окончании изменения значения элемента формы, когда это изменение зафиксировано.
Для текстовых элементов это означает, что событие произойдёт не при каждом вводе, а при потере фокуса.
Например, пока вы набираете что-то в текстовом поле ниже – события нет. Но как только вы уведёте фокус на другой элемент, например, нажмёте кнопку – произойдёт событие onchange .
Для остальных же элементов: select , input type=checkbox/radio оно срабатывает сразу при выборе значения.
В IE8- checkbox/radio при изменении мышью не инициируют событие сразу, а ждут потери фокуса.
Для того, чтобы видеть изменения checkbox/radio тут же – в IE8- нужно повесить обработчик на событие click (оно произойдёт и при изменении значения с клавиатуры) или воспользоваться событием propertychange , описанным далее.
Событие input
Событие input срабатывает тут же при изменении значения текстового элемента и поддерживается всеми браузерами, кроме IE8-.
В IE9 оно поддерживается частично, а именно – не возникает при удалении символов (как и onpropertychange ).
Пример использования (не работает в IE8-):
В современных браузерах oninput – самое главное событие для работы с элементом формы. Именно его, а не keydown/keypress следует использовать.
Если бы ещё не проблемы со старыми IE… Впрочем, их можно решить при помощи события propertychange .
IE10-, событие propertychange
Это событие происходит только в IE10-, при любом изменении свойства. Оно позволяет отлавливать изменение тут же. Оно нестандартное, и его основная область использования – исправление недочётов обработки событий в старых IE.
Если поставить его на checkbox в IE8-, то получится «правильное» событие change :
Чекбокс с "onchange", работающим везде одинаково
Это событие также срабатывает при изменении значения текстового элемента. Поэтому его можно использовать в старых IE вместо oninput .
К сожалению, в IE9 у него недочёт: оно не срабатывает при удалении символов. Поэтому сочетания onpropertychange + oninput недостаточно, чтобы поймать любое изменение поля в старых IE. Далее мы рассмотрим пример, как это можно сделать иначе.
События cut, copy, paste
Эти события используются редко. Они происходят при вырезании/вставке/копировании значения.
К сожалению, кросс-браузерного способа получить данные, которые вставляются/копируются, не существует, поэтому их основное применение – это отмена соответствующей операции.
Пример: поле с контролем СМС
Как видим, событий несколько и они взаимно дополняют друг друга.
Посмотрим, как их использовать, на примере.
Сделаем поле для СМС, рядом с которым должно показываться число символов, обновляющееся при каждом изменении поля.
Событие input идеально решит задачу во всех браузерах, кроме IE9-. Собственно, если IE9- нам не нужен, то на этом можно и остановиться.
IE9-
В IE8- событие input не поддерживается, но, как мы видели ранее, есть onpropertychange , которое может заменить его.
Что же касается IE9 – там поддерживаются и input и onpropertychange , но они оба не работают при удалении символов. Поэтому мы будем отслеживать удаление при помощи keyup на Delete и BackSpace . А вот удаление командой «вырезать» из меню – сможет отловить лишь oncut .
Получается вот такая комбинация:
sms.onkeyup = sms.oninput = showCount; sms.onpropertychange = function() < if (event.propertyName == "value") showCount(); >sms.oncut = function() < setTimeout(showCount, 0); // на момент oncut значение ещё старое >;
Здесь мы добавили вызов showCount на все события, которые могут приводить к изменению значения. Да, иногда изменение будет обрабатываться несколько раз, но зато с гарантией. А лишние вызовы легко убрать, например, при помощи throttle -декоратора, описанного в задаче Тормозящий (throttling) декоратор.
Есть и совсем другой простой, но действенный вариант: через setInterval регулярно проверять значение и, если оно слишком длинное, обрезать его.
Чтобы сэкономить ресурсы браузера, мы можем начинать отслеживание по onfocus , а прекращать – по onblur , вот так:
>, 20); >; sms.onblur = function() < clearInterval(timerId); >; function showCount()
Обратим внимание – весь этот «танец с бубном» нужен только для поддержки 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 и аналогичные не всплывают. То есть, обработчики нужно назначать на сам элемент, без делегирования.
Задачи
Автовычисление процентов по вкладу
Создайте интерфейс для автоматического вычисления процентов по вкладу.
Ставка фиксирована: 12% годовых. При включённом поле «капитализация» – проценты приплюсовываются к сумме вклада каждый месяц (сложный процент).
- В поле с суммой должно быть нельзя ввести не-цифру. При этом пусть в нём работают специальные клавиши и сочетания Ctrl-X/Ctrl-V.
- Изменения в форме отражаются в результатах сразу.
Только численный ввод в поле с суммой разрешаем, повесив обработчик на keypress .
Отслеживаем события изменения для перевычисления результатов:
- На input : событие input и дополнительно propertychange/keyup для совместимости со старыми IE.
- На checkbox : событие click вместо change для совместимости с IE8-.
- На select : событие change .
Комментарии
- Если вам кажется, что в статье что-то не так — вместо комментария напишите на GitHub.
- Для одной строки кода используйте тег , для нескольких строк кода — тег , если больше 10 строк — ссылку на песочницу (plnkr, JSBin, codepen…)
- Если что-то непонятно в статье — пишите, что именно и с какого места.
Javascript file input on change
Last updated: May 16, 2023
Reading time · 3 min
# File input change event not working in JavaScript [Solved]
The issue where the change event of a file input doesn’t work most commonly occurs when you specify the same file multiple times.
To resolve the issue, add a click event listener to the input element and set its value to null every time the file input is clicked.
Here is the HTML for the example.
Copied!DOCTYPE html> html lang="en"> head> meta charset="UTF-8" /> head> body> h2>bobbyhadz.comh2> div> input type="file" id="file-input" /> div> script src="index.js"> script> body> html>
Here is the initial JavaScript that doesn’t yet resolve the issue.
Copied!const fileInput = document.getElementById('file-input'); fileInput.addEventListener('change', event => const files = event.target.files; const file = files[0]; console.log(`filename: $file.name>`); console.log(`file size: $file.size> bytes`); console.log(`file type: $file.type>`); >);
Notice that the change event of the input type file element is not triggered when trying to upload the same file multiple times in a row.
To resolve the issue, attach a click event listener to the element where you set the value of the input to null .
Copied!const fileInput = document.getElementById('file-input'); fileInput.addEventListener('change', event => const files = event.target.files; const file = files[0]; console.log(`filename: $file.name>`); console.log(`file size: $file.size> bytes`); console.log(`file type: $file.type>`); >); fileInput.addEventListener('click', () => fileInput.value = null; >);
We used the document.getElementById method to select the file input element by its ID.
Copied!const fileInput = document.getElementById('file-input');
We then used the addEventListener method to attach a change event listener to the file input element.
Copied!fileInput.addEventListener('change', event => const files = event.target.files; const file = files[0]; console.log(`filename: $file.name>`); console.log(`file size: $file.size> bytes`); console.log(`file type: $file.type>`); >);
The change event is triggered every time the value of the file input changes.
However, if the user uploads the same file multiple times in a row, the value of the value of the file input doesn’t change, so the change event isn’t triggered.
In the event handler function, we simply accessed the first file (index 0 ) and logged some of its properties to the console.
In order to resolve the issue, we also added a click event listener.
Copied!fileInput.addEventListener('click', () => fileInput.value = null; >);
The click event listener is triggered every time the user clicks on the file input element.
In the event handler function, we simply set the value property of the file input to null to reset it.
This way, the change event is triggered event if the user uploads the same file multiple times in a row.
An alternative approach is to reset the value of the file input at the end of the change event handler.
Copied!const fileInput = document.getElementById('file-input'); fileInput.addEventListener('change', event => const files = event.target.files; const file = files[0]; console.log(`filename: $file.name>`); console.log(`file size: $file.size> bytes`); console.log(`file type: $file.type>`); fileInput.value = null; >);
The code sample sets the value property of the file input to null as the last line in the change event handler.
You can also use event.target to get access to the file input element.
Copied!const fileInput = document.getElementById('file-input'); fileInput.addEventListener('change', event => const files = event.target.files; const file = files[0]; console.log(`filename: $file.name>`); console.log(`file size: $file.size> bytes`); console.log(`file type: $file.type>`); console.log(event.target); event.target.value = null; >);
The event.target property gives us a reference to the file input element, so we can set the value property of the element to null .
# Additional Resources
You can learn more about the related topics by checking out the following tutorials:
I wrote a book in which I share everything I know about how to become a better, more efficient programmer.