Skip to content

Wszystko o WordPressie, tworzeniu stron — i nie tylko

⚙️ Jak zabronić wprowadzania niepotrzebnych znaków w INPUT na JavaScript

⚙️ 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, inputmode i type, 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 &lt; 48 || event.keyCode &gt; 57) &&
12 (event.keyCode &lt; 96 || event.keyCode &gt; 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:

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

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});

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:

1document.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:

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});

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:

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}

Użycie:

1// Только цифры
2restrictInput(document.getElementById("phone"), /^[0-9]$/);
3// Только латиница без пробелов
4restrictInput(document.getElementById("login"), /^[a-zA-Z]$/);
5// Буквы и цифры
6restrictInput(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 wprowadzanie e i E (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 keydown i input, przeglądarka wstawia wartość bezpośrednio. Handler input przechwytuje 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 atrybut autocomplete="off".

Czy działa to na urządzeniach mobilnych?

Tak, ale z zastrzeżeniem: wirtualne klawiatury nie zawsze generują keydown z oczekiwanymi keyCode i key. Handler input działa stabilnie wszędzie. Na urządzeniach mobilnych proszę ustawić inputmode="numeric" lub inputmode="decimal" na INPUCIE, użytkownik otrzyma właściwą klawiaturę, nawet jeśli filtr keydown nie 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

Programista przy biurku z kodem na ekranie

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.