
⚙️ Jak zabronić wprowadzania niepotrzebnych znaków w INPUT na JavaScript
Formularz rejestracyjny, pole telefonu, wyszukiwanie w katalogu, użytkownik klika w INPUT i wpisuje cokolwiek. Litery tam, gdzie oczekuje Pan cyfr. Znaki specjalne w numerze zamówienia. Emoji w polu email. Rezultat: śmieci w bazie, uszkodzone zapytania, walidacja na backendzie pada z błędem.
Problem rozwiązuje się na froncie w 15 linijkach kodu. Bez wtyczek, bez bibliotek, czystym JavaScript lub parą atrybutów HTML. Poniżej trzy działające podejścia: od szybkiego HTML5 do precyzyjnej filtracji na keydown, z gotowymi przykładami pod typowe scenariusze.
💡 Szybki przegląd:
- Rozbieramy, kiedy wystarczą atrybuty HTML
pattern,inputmodeitype, a kiedy potrzebny jest JavaScript - Piszemy filtr „tylko cyfry" na jQuery i czystym JS, oba warianty z analizą krok po kroku
- Dodajemy ochronę przed wklejaniem przez Ctrl+V i menu kontekstowe
- Składamy uniwersalną funkcję-szablon pod dowolne ograniczenia: litery, alfabet łaciński, niestandardowa maska
HTML5: co można zrobić bez ani jednej linijki JavaScript
Najprostszy i najbardziej niezawodny sposób na ograniczenie wprowadzania danych: powiedzieć przeglądarce, czego dokładnie oczekuje Pan w polu. Współczesne przeglądarki rozumieją trzy kluczowe atrybuty, które pokrywają większość typowych zadań.
type, filtr pierwotny. type="number" dopuszcza tylko cyfry, minus i separator dziesiętny. type="tel" na urządzeniach mobilnych pokazuje klawiaturę numeryczną. type="email" sprawdza obecność @ podczas wysyłania formularza. type="url" wymaga protokołu. Nie blokuje to całkowicie wprowadzania, ale daje właściwą klawiaturę ekranową i podstawową walidację podczas submit.
pattern, wyrażenie regularne na polu. Atrybut przyjmuje regex i waliduje wartość podczas wysyłania formularza:
1 <input type="text" pattern="[0-9]{6}" placeholder="Шесть цифр" title="Ровно 6 цифр">
Przeglądarka blokuje submit, jeśli wartość nie pasuje do wzorca. Minus: pattern nie zapobiega wprowadzaniu niedozwolonych znaków, jedynie sprawdza wynik. Użytkownik może wpisać „abc", a błąd zobaczy dopiero przy próbie wysłania formularza.
inputmode, właściwa klawiatura na urządzeniach mobilnych. inputmode="numeric" otwiera klawiaturę numeryczną, ale nie zabrania wprowadzania liter. inputmode="decimal" dodaje separator. Przydatne w połączeniu z filtrem JavaScript: klawiatura jest już właściwa, a JS dopełnia resztę.
Co wybrać. Jeśli potrzebuje Pan właśnie zakazać wprowadzania niedozwolonego znaku w czasie rzeczywistym, atrybuty HTML nie wystarczą. Przechodzimy do JavaScript.
JavaScript: blokowanie naciśnięć przez keydown
Podejście z keydown przechwytuje każde naciśnięcie klawisza, zanim znak pojawi się w polu. Jeśli klawisza nie ma na białej liście, event.preventDefault() go wygasza.
Wariant 1: jQuery, tylko cyfry
Kod wieszamy na INPUT po id, dopuszcza cyfry i klawisze serwisowe (backspace, strzałki, Tab), cała reszta jest wycinana:
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 < 48 || event.keyCode > 57) && 12 (event.keyCode < 96 || event.keyCode > 105)) { 13 event.preventDefault(); 14 } 15 }); 16 });
Co tu się dzieje krok po kroku: keyCode 46 (Delete), 8 (Backspace), 9 (Tab), 27 (Escape), 65 + Ctrl (zaznacz wszystko), 35..39 (Home, End, strzałki). Dalej idą cyfry bloku głównego 48..57 (0..9) i numpad 96..105. Wszystko, co nie trafiło w te zakresy, dostaje preventDefault.
Pełna tabela kodów klawiszy, na Cambia Research.
Wariant 2: czysty JavaScript, tylko cyfry
To samo, bez jQuery, przez onkeypress. Ten wariant jest bardziej kompaktowy i nie ciągnie biblioteki:
1 document.getElementById("phone_input").onkeypress = function(event) { 2 event = event || window.event; 3 if (event.charCode && (event.charCode < 48 || event.charCode > 57)) { 4 return false; 5 } 6 };
charCode sprawdza, czy w zdarzeniu jest drukowalny znak, klawisze serwisowe (strzałki, backspace) przechodzą automatycznie, ich charCode wynosi 0. Cyfry: 48..57, reszta dostaje return false.
Ważne: keyCode jest uznawany za przestarzały (deprecated). We współczesnym kodzie lepiej używać event.key, zwraca on ciąg znaków z nazwą klawisza i nie zależy od układu klawiatury:
1 element.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 });
Podejście z event.key czyta się prościej i nie wymaga zapamiętywania kodów numerycznych. Ale dla wsparcia starszych przeglądarek wersja z keyCode powyżej wciąż działa.
Blokowanie wklejania: łapiemy Ctrl+V i menu kontekstowe
keydown łapie naciśnięcia klawiszy, ale użytkownik może wkleić tekst przez Ctrl+V lub prawy przycisk myszy → „Wklej". Skopiował „abc123" do pola na cyfry i połowa przeszła.
Rozwiązanie: zdarzenie input. Uruchamia się ono po KAŻDEJ zmianie wartości pola: ręczne wprowadzanie, wklejanie, autouzupełnianie, przeciąganie tekstu. Filtrujemy końcową wartość za pomocą wyrażenia regularnego:
1 document.getElementById("digits_only").addEventListener("input", function(event) { 2 this.value = this.value.replace(/[^0-9]/g, ""); 3 });
To wszystko. Jedna linijka i przez pole nie przejdzie żadna nie-cyfra, niezależnie od tego, jak się tam dostała. Dla liter: replace(/[^a-zA-Zа-яА-ЯёЁ]/g, ""). Dla alfabetu łacińskiego: replace(/[^a-zA-Z]/g, "").
Podejście łączone, złoty środek. keydown daje natychmiastową informację zwrotną (klawisz „nie daje się wcisnąć"), a input zabezpiecza przed wklejaniem. Proszę stosować oba handlery:
1 const field = document.getElementById("digits_only"); 2 3 field.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 11 field.addEventListener("input", function() { 12 this.value = this.value.replace(/[^0-9]/g, ""); 13 });
Pierwszy handler wycina niedozwolone naciśnięcia natychmiast. Drugi czyści pozostałości po wklejaniu i autouzupełnianiu.
Gotowy szablon pod dowolne ograniczenia
Zbierzmy funkcję, która przyjmuje INPUT i wyrażenie regularne dozwolonych znaków. Sprawdzi się do telefonu, kodu pocztowego, loginu, wyszukiwania po numerze artykułu:
1 function 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 }
Użycie:
1 // Только цифры 2 restrictInput(document.getElementById("phone"), /^[0-9]$/); 3 // Только латиница без пробелов 4 restrictInput(document.getElementById("login"), /^[a-zA-Z]$/); 5 // Буквы и цифры 6 restrictInput(document.getElementById("postal"), /^[a-zA-Z0-9]$/);
Funkcja nie zależy od jQuery, działa we wszystkich współczesnych przeglądarkach i pokrywa trzy scenariusze: ręczne wprowadzanie (keydown), wklejanie (input), autouzupełnianie (input).
Proszę zwrócić uwagę: keydown nie działa na wirtualnych klawiaturach niektórych urządzeń mobilnych, tam input pozostaje jedynym zabezpieczeniem. Dlatego dwa handlery w połączeniu to nie nadmiarowość, a konieczność.
Powyższe wideo to analiza walidacji formularzy na czystym JavaScript od Web Dev Simplified. Obejmuje wbudowane Constraint Validation API, niestandardowe komunikaty o błędach i stylizację nieprawidłowych pól, dobre uzupełnienie opisanych tu podejść.
⁉️🤔 Często zadawane pytania
Dlaczego nie użyć po prostu type="number"?
type="number"dopuszcza wprowadzanieeiE(eksponenta), plusa, minusa i kropki. Wszystko to są prawidłowe znaki dla liczb zmiennoprzecinkowych i zapisu wykładniczego. W polu telefonu lub kodu pocztowego są one zbędne. Ponadto przeglądarki różnie obsługują nie numeryczne dane wejściowe: jedne przepuszczają je milcząco, inne pokazują błąd dopiero podczas submit.
Czy można całkowicie zablokować wklejanie przez Ctrl+V?
Całkowite blokowanie wklejania to zła praktyka. Psuje to doświadczenie użytkownika i nie chroni przed innymi sposobami wklejania (menu kontekstowe, przeciąganie). Właściwe podejście: pozwolić na wklejanie, ale natychmiast wyczyścić wynik przez handler
input, jak pokazano w rozdziale powyżej.
Co zrobić z autouzupełnianiem przeglądarki?
Autouzupełnianie uruchamia się przed
keydowniinput, przeglądarka wstawia wartość bezpośrednio. Handlerinputprzechwytuje również ten przypadek: wartość pojawia się w polu, a następnie jest natychmiast filtrowana. Jeśli autouzupełnianie przeszkadza (podstawia litery w polu telefonu), proszę dodać do INPUT atrybutautocomplete="off".
Czy działa to na urządzeniach mobilnych?
Tak, ale z zastrzeżeniem: wirtualne klawiatury nie zawsze generują
keydownz oczekiwanymikeyCodeikey. Handlerinputdziała stabilnie wszędzie. Na urządzeniach mobilnych proszę ustawićinputmode="numeric"lubinputmode="decimal"na INPUCIE, użytkownik otrzyma właściwą klawiaturę, nawet jeśli filtrkeydownnie zadziała.
Jak zabronić spacji?
Proszę dodać spację do klasy znaków niedozwolonych:
replace(/[^0-9a-zA-Z]/g, "")usuwa wszystko oprócz cyfr i liter alfabetu łacińskiego, włącznie ze spacjami. Lub jawnie:this.value = this.value.replace(/\s/g, "")usunie wszystkie spacje, tabulacje i znaki nowej linii.
Jakie podejście wybrać do swojego zadania

Jeśli formularz jest prosty i nie ma krytycznej szkody z powodu kilku błędnych znaków, proszę brać HTML5: type, pattern i inputmode pokryją podstawowe scenariusze bez ani jednej linijki JS. Szybko, natywnie, zero zależności.
Jeśli ważna jest kontrola w czasie rzeczywistym i natychmiastowa reakcja na każde naciśnięcie, proszę stosować połączenie keydown + input. Pierwszy blokuje naciśnięcia, drugi czyści skutki wklejania. Uniwersalna funkcja-szablon z rozdziału powyżej adaptuje się do dowolnego pola w minutę.
Główna zasada: nie blokować wklejania całkowicie. To irytuje użytkowników i nie daje realnej ochrony. Proszę czyścić wynik po wklejeniu, a nie zabraniać go.



