Skip to content

Все для WordPress, веб-розробки — і не тільки

⚙️ Як заборонити введення непотрібних символів в INPUT на JavaScript

⚙️ Як заборонити введення непотрібних символів в INPUT на JavaScript

Форма реєстрації, поле телефону, пошук за каталогом, користувач тицяє в INPUT і друкує що завгодно. Літери там, де очікуєш цифри. Спецсимволи в номері замовлення. Емодзі в полі email'у. Результат, сміття в базі, биті запити, валідація на бекенді падає з помилкою.

Проблема вирішується на фронті за 15 рядків коду. Без плагінів, без бібліотек, чистим JavaScript або парою HTML-атрибутів. Далі, три робочі підходи: від швидкого HTML5 до тонкої фільтрації на keydown, з готовими прикладами під типові сценарії.

💡 Швидкий огляд:

  • Розбираємо, коли вистачає HTML-атрибутів pattern, inputmode і type, а коли потрібен JavaScript
  • Пишемо фільтр «тільки цифри» на jQuery і чистому JS, обидва варіанти з порядковим розбором
  • Додаємо захист від вставлення через Ctrl+V і контекстне меню
  • Збираємо універсальну функцію-шаблон під будь-які обмеження: літери, латиниця, кастомна маска

HTML5: що можна зробити без жодного рядка JavaScript

Найпростіший і найнадійніший спосіб обмежити введення: сказати браузеру, що саме ви очікуєте в полі. Сучасні браузери розуміють три ключові атрибути, які закривають більшість типових задач.

type, первинний фільтр. type="number" дозволяє тільки цифри, мінус і десятковий роздільник. type="tel" на мобільних пристроях показує цифрову клавіатуру. type="email" перевіряє наявність @ під час надсилання форми. type="url" вимагає протокол. Це не блокує введення повністю, але дає правильну екранну клавіатуру і базову валідацію під час submit.

pattern, регулярний вираз на полі. Атрибут приймає regex і валідує значення під час надсилання форми:

1<input type="text" pattern="[0-9]{6}" placeholder="Шесть цифр" title="Ровно 6 цифр">

Браузер блокує submit, якщо значення не збігається з шаблоном. Мінус: pattern не заважає вводити недозволені символи, він тільки перевіряє результат. Користувач може надрукувати «abc», і помилку побачить лише під час спроби надіслати форму.

inputmode, правильна клавіатура на мобільних. inputmode="numeric" відкриває цифрову клавіатуру, але не забороняє введення літер. inputmode="decimal" додає роздільник. Корисно у зв'язці з JavaScript-фільтром: клавіатура вже правильна, а JS добирає решту.

Що вибрати. Якщо потрібно саме заборонити введення недозволеного символу в реальному часі, HTML-атрибутів недостатньо. Йдемо в JavaScript.

JavaScript: блокування натискань через keydown

Підхід із keydown ловить кожне натискання клавіші до того, як символ з'явиться в полі. Якщо клавіша не в білому списку, event.preventDefault() гасить її.

Варіант 1: jQuery, тільки цифри

Код вішається на INPUT за id, дозволяє цифри і службові клавіші (backspace, стрілки, Tab), все інше ріжеться:

1$(document).ready(function() {
2 $("#phone_input").keydown(function(event) {
3 // Служебные клавиши — пропускаем
4 if (event.keyCode === 46 || event.keyCode === 8 ||
5 event.keyCode === 9 || event.keyCode === 27 ||
6 (event.keyCode === 65 && event.ctrlKey === true) ||
7 (event.keyCode >= 35 && event.keyCode <= 39)) {
8 return;
9 }
10 // Блокируем всё кроме цифр (основной блок и numpad)
11 if ((event.keyCode &lt; 48 || event.keyCode &gt; 57) &&
12 (event.keyCode &lt; 96 || event.keyCode &gt; 105)) {
13 event.preventDefault();
14 }
15 });
16});

Що тут відбувається порядково: keyCode 46 (Delete), 8 (Backspace), 9 (Tab), 27 (Escape), 65 + Ctrl (виділити все), 35..39 (Home, End, стрілки). Далі йдуть цифри основного блоку 48..57 (0..9) і numpad 96..105. Все, що не потрапило в ці діапазони,, preventDefault.

Повна таблиця кодів клавіш, на Cambia Research.

Варіант 2: чистий JavaScript, тільки цифри

Те саме, без jQuery, через onkeypress. Цей варіант компактніший і не тягне бібліотеку:

1document.getElementById("phone_input").onkeypress = function(event) {
2 event = event || window.event;
3 if (event.charCode && (event.charCode &lt; 48 || event.charCode &gt; 57)) {
4 return false;
5 }
6};

charCode перевіряє, що в події є друкований символ, службові клавіші (стрілки, backspace) проходять автоматично, charCode у них дорівнює 0. Цифри: 48..57, решта, return false.

Важливо: keyCode вважається застарілим (deprecated). У сучасному коді краще використовувати event.key, він повертає рядок із назвою клавіші і не залежить від розкладки:

1element.addEventListener("keydown", function(event) {
2 // Разрешаем цифры, Backspace, Delete, стрелки, Tab
3 const allowedKeys = [
4 "Backspace", "Delete", "Tab", "Escape",
5 "ArrowLeft", "ArrowRight", "ArrowUp", "ArrowDown",
6 "Home", "End"
7 ];
8 if (allowedKeys.includes(event.key)) return;
9 // Ctrl+A / Ctrl+C / Ctrl+V
10 if (event.ctrlKey) return;
11 // Только цифры
12 if (!/^[0-9]$/.test(event.key)) {
13 event.preventDefault();
14 }
15});

Підхід з event.key читається простіше і не вимагає запам'ятовувати числові коди. Але для підтримки старих браузерів keyCode-версія вище все ще працює.

Блокування вставлення: ловимо Ctrl+V і контекстне меню

keydown ловить натискання клавіш, але користувач може вставити текст через Ctrl+V або правий клік → «Вставити». Скопіював «abc123» у поле для цифр, і половина проскочила.

Рішення, подія input. Вона спрацьовує після БУДЬ-ЯКОЇ зміни значення поля: ручне введення, вставлення, автозаповнення, перетягування тексту. Фільтруємо підсумкове значення за регулярним виразом:

1document.getElementById("digits_only").addEventListener("input", function(event) {
2 this.value = this.value.replace(/[^0-9]/g, "");
3});

Все. Один рядок, і через поле не пройде жодна не-цифра, незалежно від того, як вона туди потрапила. Для літер: replace(/[^a-zA-Zа-яА-ЯёЁ]/g, ""). Для латиниці: replace(/[^a-zA-Z]/g, "").

Комбінований підхід, золота середина. keydown дає миттєвий зворотний зв'язок (клавіша «не натискається»), а input страхує від вставлення. Ставте обидва обробники:

1const field = document.getElementById("digits_only");
2
3field.addEventListener("keydown", function(event) {
4 const allowed = ["Backspace", "Delete", "Tab", "Escape",
5 "ArrowLeft", "ArrowRight", "Home", "End"];
6 if (allowed.includes(event.key)) return;
7 if (event.ctrlKey) return;
8 if (!/^[0-9]$/.test(event.key)) event.preventDefault();
9});
10
11field.addEventListener("input", function() {
12 this.value = this.value.replace(/[^0-9]/g, "");
13});

Перший обробник ріже недозволені натискання миттєво. Другий, чистить хвости після вставлення й автозаповнення.

Готовий шаблон під будь-які обмеження

Зберемо функцію, яка приймає INPUT і регулярний вираз дозволених символів. Підійде для телефону, поштового індексу, логіна, пошуку за артикулом:

1function restrictInput(element, allowedPattern) {
2 element.addEventListener("keydown", function(event) {
3 const serviceKeys = [
4 "Backspace", "Delete", "Tab", "Escape",
5 "ArrowLeft", "ArrowRight", "Home", "End"
6 ];
7 if (serviceKeys.includes(event.key)) return;
8 if (event.ctrlKey && ["a", "c", "v", "x", "z"].includes(event.key.toLowerCase())) return;
9 if (!allowedPattern.test(event.key)) event.preventDefault();
10 });
11
12 element.addEventListener("input", function() {
13 // Собираем глобальный паттерн из переданного и чистим
14 const globalPattern = new RegExp(
15 allowedPattern.source.replace("^", "").replace("$", ""),
16 "g"
17 );
18 // Удаляем всё, что НЕ подходит под паттерн
19 const inverted = new RegExp(
20 "[^" + allowedPattern.source.slice(1, -1) + "]", "g"
21 );
22 this.value = this.value.replace(inverted, "");
23 });
24}

Використання:

1// Только цифры
2restrictInput(document.getElementById("phone"), /^[0-9]$/);
3// Только латиница без пробелов
4restrictInput(document.getElementById("login"), /^[a-zA-Z]$/);
5// Буквы и цифры
6restrictInput(document.getElementById("postal"), /^[a-zA-Z0-9]$/);

Функція не залежить від jQuery, працює в усіх сучасних браузерах і покриває три сценарії: ручне введення (keydown), вставлення (input), автозаповнення (input).

Зверніть увагу: keydown не спрацьовує на віртуальних клавіатурах деяких мобільних пристроїв, там input залишається єдиною страховкою. Тому два обробники у зв'язці — це не надмірність, а необхідність.

Відео вище, розбір валідації форм на чистому JavaScript від Web Dev Simplified. Охоплює вбудовані Constraint Validation API, кастомні повідомлення про помилки і стилізацію невалідних полів, гарне доповнення до описаних тут підходів.

⁉️🤔 Часті запитання

Чому не використовувати просто type="number"?

type="number" дозволяє введення e і E (експонента), плюса, мінуса і крапки. Все це валідні символи для чисел із рухомою комою та експоненційного запису. Для поля телефону або поштового індексу вони зайві. Плюс браузери по-різному обробляють нечислове введення: одні мовчки пропускають, інші показують помилку тільки під час submit.

Чи можна повністю заблокувати вставлення через Ctrl+V?

Блокувати вставлення повністю, погана практика. Це ламає користувацький досвід і не захищає від інших способів вставлення (контекстне меню, перетягування). Правильний підхід: дозволити вставлення, але негайно очистити результат через input-обробник, як показано в розділі вище.

Що робити з автозаповненням браузера?

Автозаповнення спрацьовує до keydown і input, браузер вставляє значення напряму. Обробник input перехоплює і цей випадок: значення з'являється в полі, а потім одразу фільтрується. Якщо автозаповнення заважає (підставляє літери в поле телефону), додайте до INPUT атрибут autocomplete="off".

Чи працює це на мобільних пристроях?

Так, але із застереженням: віртуальні клавіатури не завжди генерують keydown з очікуваними keyCode і key. Обробник input працює стабільно скрізь. На мобільних ставте inputmode="numeric" або inputmode="decimal" на INPUT, користувач отримає правильну клавіатуру, навіть якщо keydown-фільтр не спрацює.

Як заборонити пробіли?

Додайте пробіл у клас недозволених символів: replace(/[^0-9a-zA-Z]/g, "") прибирає все, крім цифр і латиниці, включно з пробілами. Або явно: this.value = this.value.replace(/\s/g, "") видалить усі пробіли, табуляції та перенесення рядків.

Який підхід вибрати під вашу задачу

Розробник за робочим столом з кодом на екрані

Якщо форма проста і критичної шкоди від пари невірних символів немає, беріть HTML5: type, pattern і inputmode закриють базові сценарії без жодного рядка JS. Швидко, нативно, жодних залежностей.

Якщо важливий контроль у реальному часі та миттєва реакція на кожне натискання, ставте зв'язку keydown + input. Перший блокує натискання, другий чистить наслідки вставлення. Універсальна функція-шаблон із розділу вище адаптується під будь-яке поле за хвилину.

Головне правило, не блокуйте вставлення повністю. Це дратує користувачів і не дає реального захисту. Чистьте результат після вставлення, а не забороняйте її.