Skip to content

Tout pour WordPress, le développement web — et plus encore

⚙️ Comment restreindre la saisie de caractères indésirables dans un INPUT avec JavaScript

⚙️ Comment restreindre la saisie de caractères indésirables dans un INPUT avec JavaScript

Formulaire d’inscription, champ téléphone, recherche dans le catalogue: l’utilisateur clique sur un INPUT et tape n’importe quoi. Des lettres là où vous attendez des chiffres. Des caractères spéciaux dans un numéro de commande. Des emoji dans un champ email. Résultat: des données incohérentes en base, des requêtes cassées, une validation backend qui échoue avec une erreur.

Le problème se règle côté frontend en 15 lignes de code. Pas de plugin, pas de bibliothèque, juste du JavaScript ou quelques attributs HTML. Voici trois approches fonctionnelles: des solutions rapides en HTML5 jusqu’au filtrage fin sur keydown, avec des exemples prêts à l’emploi pour les cas les plus courants.

💡 En bref:

  • Nous examinons quand les attributs HTML pattern, inputmode et type suffisent, et quand le recours à JavaScript est nécessaire
  • Nous écrivons un filtre «chiffres uniquement» en jQuery et en JS natif, les deux versions commentées ligne par ligne
  • Nous ajoutons une protection contre le collage via Ctrl+V et le menu contextuel
  • Nous construisons une fonction générique adaptable à toute restriction: lettres, caractères latins, masques personnalisés

HTML5: ce que vous pouvez faire sans une seule ligne de JavaScript

La manière la plus simple et la plus fiable de restreindre la saisie consiste à indiquer au navigateur ce que vous attendez exactement dans un champ. Les navigateurs modernes comprennent trois attributs clés qui couvrent la majorité des besoins courants.

type, le filtre principal. type="number" n’autorise que les chiffres, le signe moins et le séparateur décimal. type="tel" affiche un clavier numérique sur mobile. type="email" vérifie la présence du @ à la soumission du formulaire. type="url" exige un protocole. Cela ne bloque pas entièrement la saisie, mais fournit le bon clavier à l’écran et une validation de base à la soumission.

pattern, une expression régulière sur le champ. L’attribut accepte une regex et valide la valeur au moment de la soumission du formulaire:

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

Le navigateur bloque la soumission si la valeur ne correspond pas au motif. L’inconvénient: pattern n’empêche pas la saisie de caractères interdits; il ne valide que le résultat. L’utilisateur peut taper «abc» et ne verra l’erreur qu’au moment de soumettre le formulaire.

inputmode, le bon clavier sur mobile. inputmode="numeric" ouvre un clavier numérique mais n’interdit pas la saisie de lettres. inputmode="decimal" ajoute un séparateur. Utile en complément d’un filtre JavaScript: le clavier est déjà le bon, et JS gère le reste.

Que choisir. Si vous devez réellement empêcher la saisie de caractères interdits en temps réel, les attributs HTML ne suffisent pas. Passons à JavaScript.

JavaScript: bloquer les frappes via keydown

L’approche keydown intercepte chaque frappe avant que le caractère n’apparaisse dans le champ. Si la touche n’est pas dans la liste blanche, event.preventDefault() la supprime.

Option 1: jQuery, chiffres uniquement

Le code est attaché à un INPUT par son id, autorise les chiffres et les touches de service (retour arrière, flèches, Tab) et bloque tout le reste:

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

Voici ce qui se passe ligne par ligne: keyCode 46 (Suppr), 8 (Retour arrière), 9 (Tab), 27 (Échap), 65 + Ctrl (tout sélectionner), 35..39 (Début, Fin, flèches). Viennent ensuite les chiffres du bloc principal 48..57 (0..9) et du pavé numérique 96..105. Tout ce qui ne tombe pas dans ces plages reçoit un preventDefault.

Table complète des key codes sur Cambia Research.

Option 2: JavaScript natif, chiffres uniquement

La même chose sans jQuery, en utilisant onkeypress. Cette version est plus compacte et ne nécessite aucune bibliothèque:

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 vérifie que l’événement comporte un caractère imprimable; les touches de service (flèches, retour arrière) passent automatiquement puisque leur charCode vaut 0. Chiffres: 48..57, tout le reste renvoie false.

Important: keyCode est considéré comme déprécié. Dans du code moderne, il vaut mieux utiliser event.key, qui renvoie une chaîne avec le nom de la touche et ne dépend pas de la disposition du clavier:

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’approche event.key se lit plus clairement et ne nécessite pas de mémoriser des codes numériques. Mais pour la prise en charge des navigateurs plus anciens, la version avec keyCode ci-dessus fonctionne toujours.

Bloquer le collage: intercepter Ctrl+V et le menu contextuel

keydown intercepte les frappes, mais l’utilisateur peut coller du texte via Ctrl+V ou clic droit → «Coller». Il a copié «abc123» dans un champ chiffres uniquement, et la moitié est passée.

La solution est l’événement input. Il se déclenche après TOUTE modification de la valeur du champ: saisie manuelle, collage, autocomplétion, glisser-déposer de texte. Nous filtrons la valeur finale avec une expression régulière:

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

C’est tout. Une ligne, et pas un seul caractère non numérique ne passera dans le champ, quelle que soit la manière dont il y est arrivé. Pour les lettres: replace(/[^a-zA-Zа-яА-ЯёЁ]/g, ""). Pour les caractères latins: replace(/[^a-zA-Z]/g, "").

Approche combinée (le juste milieu). keydown fournit un retour instantané (la touche «ne s’enfonce pas»), tandis que input protège contre le collage. Utilisez les deux gestionnaires:

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

Le premier gestionnaire coupe instantanément les frappes interdites. Le second nettoie les résidus après collage et autocomplétion.

Modèle prêt à l’emploi pour toute restriction

Construisons une fonction qui prend un INPUT et une expression régulière de caractères autorisés. Elle fonctionne pour les numéros de téléphone, les codes postaux, les identifiants, la recherche de références article:

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}

Utilisation:

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 fonction ne dépend pas de jQuery, fonctionne dans tous les navigateurs modernes et couvre trois scénarios: saisie manuelle (keydown), collage (input), autocomplétion (input).

Remarque: keydown ne se déclenche pas sur les claviers virtuels de certains appareils mobiles; là, input reste la seule sauvegarde. C’est pourquoi deux gestionnaires ensemble ne sont pas une redondance mais une nécessité.

La vidéo ci-dessus est une analyse de la validation de formulaire en JavaScript natif par Web Dev Simplified. Elle couvre l’API Constraint Validation intégrée, les messages d’erreur personnalisés et le stylage des champs invalides, un excellent complément aux approches décrites ici.

⁉️🤔 Foire aux questions

Pourquoi ne pas simplement utiliser type="number"?

type="number" autorise la saisie de e et E (exposant), plus, moins et point. Tous ces caractères sont valides pour les nombres à virgule flottante et la notation exponentielle. Pour un champ téléphone ou un code postal, ils sont inutiles. De plus, les navigateurs gèrent différemment les saisies non numériques: certains les laissent passer en silence, d’autres n’affichent une erreur qu’à la soumission.

Peut-on bloquer complètement le collage via Ctrl+V?

Bloquer entièrement le collage est une mauvaise pratique. Cela dégrade l’expérience utilisateur et ne protège pas contre les autres méthodes de collage (menu contextuel, glisser-déposer). La bonne approche: autoriser le collage, mais nettoyer immédiatement le résultat via un gestionnaire input, comme montré dans la section précédente.

Qu’en est-il de l’autocomplétion du navigateur?

L’autocomplétion se déclenche avant keydown et input; le navigateur insère la valeur directement. Le gestionnaire input couvre aussi ce cas: la valeur apparaît dans le champ, puis est filtrée immédiatement. Si l’autocomplétion est gênante (insertion de lettres dans un champ téléphone), ajoutez l’attribut autocomplete="off" sur l’INPUT.

Cela fonctionne-t-il sur les appareils mobiles?

Oui, mais avec une réserve: les claviers virtuels ne génèrent pas toujours un keydown avec les keyCode et key attendus. Le gestionnaire input fonctionne de manière fiable partout. Sur mobile, définissez inputmode="numeric" ou inputmode="decimal" sur l’INPUT; l’utilisateur obtiendra le bon clavier même si le filtre keydown ne se déclenche pas.

Comment interdire les espaces?

Ajoutez l’espace à la classe de caractères interdits: replace(/[^0-9a-zA-Z]/g, "") supprime tout sauf les chiffres et les lettres latines, y compris les espaces. Ou explicitement: this.value = this.value.replace(/\s/g, "") supprimera tous les espaces, tabulations et sauts de ligne.

Quelle approche choisir pour votre projet

Développeur à son bureau avec du code à l'écran

Si le formulaire est simple et que quelques caractères erronés ne causeront pas de dégâts critiques, utilisez HTML5: type, pattern et inputmode couvriront les scénarios de base sans une seule ligne de JS. Rapide, natif, sans dépendance.

Si le contrôle en temps réel et la réaction instantanée à chaque frappe sont importants, utilisez la combinaison keydown + input. Le premier bloque les frappes, le second nettoie les conséquences du collage. La fonction générique de la section précédente s’adapte à n’importe quel champ en une minute.

La règle principale: ne bloquez pas entièrement le collage. Cela agace les utilisateurs et n’apporte pas de réelle protection. Nettoyez le résultat après collage plutôt que de l’interdire.