Skip to content

Tutto per WordPress, lo sviluppo web — e non solo

⚙️ Come limitare l'inserimento di caratteri indesiderati in INPUT con JavaScript

⚙️ Come limitare l'inserimento di caratteri indesiderati in INPUT con JavaScript

Modulo di registrazione, campo telefono, ricerca nel catalogo: l’utente clicca su un INPUT e digita qualsiasi cosa. Lettere dove ti aspetti cifre. Caratteri speciali in un numero d’ordine. Emoji in un campo email. Il risultato: spazzatura nel database, query che si rompono, validazione backend che fallisce con un errore.

Il problema si risolve sul frontend in 15 righe di codice. Niente plugin, niente librerie, solo JavaScript puro o un paio di attributi HTML. Qui sotto trovi tre approcci funzionanti: dal rapido HTML5 al filtraggio granulare su keydown, con esempi pronti per gli scenari più comuni.

💡 Panoramica rapida:

  • Esaminiamo quando bastano gli attributi HTML pattern, inputmode e type, e quando serve JavaScript
  • Scriviamo un filtro «solo cifre» in jQuery e in JS puro, entrambe le versioni con spiegazione riga per riga
  • Aggiungiamo la protezione contro l’incolla tramite Ctrl+V e menu contestuale
  • Costruiamo una funzione template universale per qualsiasi restrizione: lettere, caratteri latini, maschere personalizzate

HTML5: cosa puoi fare senza una sola riga di JavaScript

Il modo più semplice e affidabile per limitare l’input è dire al browser esattamente cosa ti aspetti in un campo. I browser moderni comprendono tre attributi chiave che coprono la maggior parte delle esigenze comuni.

type, il filtro principale. type="number" consente solo cifre, meno e separatore decimale. type="tel" sui dispositivi mobili mostra una tastiera numerica. type="email" verifica la presenza di @ all’invio del form. type="url" richiede un protocollo. Questo non blocca del tutto l’input, ma fornisce la tastiera a schermo corretta e una validazione di base all’invio.

pattern, una espressione regolare sul campo. L’attributo accetta una regex e convalida il valore all’invio del form:

1<input type="text" pattern="[0-9]{6}" placeholder="Six digits" title="Exactly 6 digits">

Il browser blocca l’invio se il valore non corrisponde al pattern. Il lato negativo: pattern non impedisce di inserire caratteri non consentiti; convalida solo il risultato. L’utente può digitare «abc» e vedrà l’errore solo quando proverà a inviare il form.

inputmode, la tastiera corretta su mobile. inputmode="numeric" apre una tastiera numerica ma non vieta l’inserimento di lettere. inputmode="decimal" aggiunge un separatore. Utile in combinazione con un filtro JavaScript: la tastiera è già corretta e JS gestisce il resto.

Cosa scegliere. Se devi impedire effettivamente l’inserimento di caratteri non consentiti in tempo reale, gli attributi HTML non bastano. Passiamo a JavaScript.

JavaScript: bloccare i tasti premuti con keydown

L’approccio keydown intercetta ogni tasto prima che il carattere appaia nel campo. Se il tasto non è nella whitelist, event.preventDefault() lo sopprime.

Opzione 1: jQuery, solo cifre

Il codice è agganciato a un INPUT tramite id, consente cifre e tasti di servizio (backspace, frecce, Tab) e blocca tutto il resto:

1$(document).ready(function() {
2 $("#phone_input").keydown(function(event) {
3 // Service keys — let them through
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 // Block everything except digits (main block and 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});

Ecco cosa succede riga per riga: keyCode 46 (Canc), 8 (Backspace), 9 (Tab), 27 (Esc), 65 + Ctrl (seleziona tutto), 35..39 (Home, Fine, frecce). Poi arriva il blocco principale delle cifre 48..57 (0..9) e del tastierino numerico 96..105. Tutto ciò che non rientra in questi intervalli riceve preventDefault.

Tabella completa dei codici tasto su Cambia Research.

Opzione 2: JavaScript puro, solo cifre

La stessa cosa senza jQuery, usando onkeypress. Questa versione è più compatta e non richiede una libreria:

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 verifica che l’evento abbia un carattere stampabile; i tasti di servizio (frecce, backspace) passano automaticamente perché il loro charCode è uguale a 0. Cifre: 48..57, tutto il resto restituisce false.

Importante: keyCode è considerato deprecato. Nel codice moderno è meglio usare event.key, che restituisce una stringa con il nome del tasto e non dipende dal layout della tastiera:

1element.addEventListener("keydown", function(event) {
2 // Allow digits, Backspace, Delete, arrows, 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 // Only digits
12 if (!/^[0-9]$/.test(event.key)) {
13 event.preventDefault();
14 }
15});

L’approccio con event.key si legge in modo più chiaro e non richiede di memorizzare codici numerici. Ma per supportare browser più vecchi, la versione con keyCode qui sopra funziona ancora.

Bloccare l’incolla: intercettare Ctrl+V e menu contestuale

keydown intercetta i tasti premuti, ma l’utente può incollare testo tramite Ctrl+V o tasto destro → «Incolla». Ha copiato «abc123» in un campo solo cifre e metà del testo è passato.

La soluzione è l’evento input. Si attiva dopo QUALSIASI modifica del valore del campo: input manuale, incolla, riempimento automatico, trascinamento di testo. Filtriamo il valore finale con una espressione regolare:

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

Tutto qui. Una riga, e nemmeno un carattere non numerico passerà attraverso il campo, indipendentemente da come ci è arrivato. Per le lettere: replace(/[^a-zA-Zа-яА-ЯёЁ]/g, ""). Per i caratteri latini: replace(/[^a-zA-Z]/g, "").

Approccio combinato (il giusto mezzo). keydown fornisce un feedback immediato (il tasto «non si preme»), mentre input protegge dall’incolla. Usa entrambi i gestori:

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

Il primo gestore taglia subito i tasti non consentiti. Il secondo ripulisce i residui dopo incolla e riempimento automatico.

Template pronto per qualsiasi restrizione

Costruiamo una funzione che prende un INPUT e un’espressione regolare di caratteri consentiti. Funziona per numeri di telefono, CAP, login, ricerca SKU:

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 // Build a global pattern from the provided one and clean
14 const globalPattern = new RegExp(
15 allowedPattern.source.replace("^", "").replace("$", ""),
16 "g"
17 );
18 // Remove everything that does NOT match the pattern
19 const inverted = new RegExp(
20 "[^" + allowedPattern.source.slice(1, -1) + "]", "g"
21 );
22 this.value = this.value.replace(inverted, "");
23 });
24}

Utilizzo:

1// Digits only
2restrictInput(document.getElementById("phone"), /^[0-9]$/);
3// Latin letters only without spaces
4restrictInput(document.getElementById("login"), /^[a-zA-Z]$/);
5// Letters and digits
6restrictInput(document.getElementById("postal"), /^[a-zA-Z0-9]$/);

La funzione non dipende da jQuery, funziona in tutti i browser moderni e copre tre scenari: input manuale (keydown), incolla (input), riempimento automatico (input).

Nota: keydown non si attiva sulle tastiere virtuali di alcuni dispositivi mobili; in quel caso input resta l’unica salvaguardia. Ecco perché due gestori insieme non sono una ridondanza ma una necessità.

Il video qui sopra è un’analisi della validazione dei form in JavaScript puro di Web Dev Simplified. Copre l’API Constraint Validation integrata, i messaggi di errore personalizzati e lo stile dei campi non validi, un ottimo complemento agli approcci descritti qui.

⁉️🤔 Domande frequenti

Perché non usare semplicemente type="number"?

type="number" consente di inserire e ed E (esponente), più, meno e punto. Tutti questi sono caratteri validi per numeri in virgola mobile e notazione esponenziale. Per un campo telefono o CAP non servono. Inoltre, i browser gestiscono l’input non numerico in modo diverso: alcuni lo lasciano passare in silenzio, altri mostrano un errore solo all’invio.

Si può bloccare completamente l’incolla tramite Ctrl+V?

Bloccare del tutto l’incolla è una cattiva pratica. Rovina l’esperienza utente e non protegge da altri metodi di incolla (menu contestuale, trascinamento). L’approccio corretto: consenti l’incolla, ma pulisci subito il risultato con un gestore input, come mostrato nella sezione precedente.

E il riempimento automatico del browser?

Il riempimento automatico si attiva prima di keydown e input; il browser inserisce il valore direttamente. Il gestore input intercetta anche questo caso: il valore appare nel campo e viene filtrato immediatamente. Se il riempimento automatico interferisce (inserendo lettere in un campo telefono), aggiungi l’attributo autocomplete="off" all’INPUT.

Funziona sui dispositivi mobili?

Sì, ma con una precisazione: le tastiere virtuali non sempre generano keydown con keyCode e key attesi. Il gestore input funziona in modo affidabile ovunque. Su mobile, imposta inputmode="numeric" o inputmode="decimal" sull’INPUT; l’utente riceverà la tastiera corretta anche se il filtro keydown non si attiva.

Come si impediscono gli spazi?

Aggiungi lo spazio alla classe di caratteri non consentiti: replace(/[^0-9a-zA-Z]/g, "") rimuove tutto tranne cifre e lettere latine, spazi inclusi. Oppure in modo esplicito: this.value = this.value.replace(/\s/g, "") rimuoverà tutti gli spazi, le tabulazioni e le interruzioni di riga.

Quale approccio scegliere per il tuo compito

Sviluppatore alla scrivania con codice sullo schermo

Se il form è semplice e un paio di caratteri sbagliati non causano danni critici, usa HTML5: type, pattern e inputmode copriranno gli scenari di base senza una sola riga di JS. Veloce, nativo, nessuna dipendenza.

Se contano il controllo in tempo reale e la reazione immediata a ogni tasto premuto, usa la combinazione keydown + input. Il primo blocca i tasti, il secondo ripulisce le conseguenze dell’incolla. La funzione template universale della sezione precedente si adatta a qualsiasi campo in un minuto.

La regola principale: non bloccare del tutto l’incolla. Infastidisce gli utenti e non fornisce una protezione reale. Pulisci il risultato dopo l’incolla invece di proibirlo.