![]() |
Bertrand Wattel |
|
|
|
| Adresse électronique: | |
| Présence Internet: |
Veuillez adresser vos questions relatives à cet article uniquement à son auteur.
Lorsque l'on traite les données d'un formulaire, il est souvent souhaitable de vérifier que l'utilisateur n'a pas entré de caractères interdits ou d'instructions malveillantes dans les champs de texte. C'est notamment le cas quand on utilise des bases de données avec les instructions SQL.
D'un autre côté, la vérification des saisies est souvent fastidieuse quand on l'opère côté client. De la même façon, l'utilisateur, tout heureux d'avoir fini la saisie d'un long formulaire, se voit brutalement renvoyé sur cette même page pour une petite erreur. Dans le pire des cas, les données du formulaire ont entièrement disparu et il doit tout recommencer.
La méthode (en fait 2 méthodes, une troisième est déjà donnée sur SELFHTML) présentée ici utilise JavaScript pour vérifier à la volée que les champs de saisie ne contiennent que des caractères admissibles. Concrètement, si le champ input du formulaire ne doit contenir que des chiffres, lorsque l'utilisateur tape sur une touche autre que celle d'un chiffre, il ne doit rien se passer.
Le script est compatible avec la plupart des navigateurs couramment utilisés, sauf si l'utilisateur a bien évidemment bridé la fonctionnalité JavaScript. Dans ce cas, soit on revient à la bonne vieille méthode de traitement côté serveur, soit on averti gentiment l'utilisateur que l'utilisation du formulaire est suspendu à l'activation de JavaScript.
JavaScript fournit un objet formidable pour gérer dynamiquement le comportement de l'utilisateur. L'objet event a été introduit dès JavaScript 1.2. En fait, il n'y a pas qu'un seul objet de ce type, mais autant que d'éléments sur la page web. Dès que le flux de données se modifie, l'objet est actualisé. La plupart du temps, la gestion en est laissé au navigateur, comme un clic sur un lien. Mais dans d'autres cas, le concepteur averti modifie le résultat de l'évènement, comme lors d'un survol avec la souris provoquant une modification d'aspect de l'élément survolé.
<html>
<body>
<a href="#" onMouseover="javascript:alert('Ouille!')">passez-moi dessus!</a>
<form>
tapez un texte ici, puis cliquez ailleurs sur la page
<input type="text" onblur="this.value='';alert('Inutile de continuer, je suis le croqueur de texte!')">
</form>
</body>
</html>
|
Lorsque le flux de données d'un élément se modifie, l'objet event est actualisé. Selon le type d'élément, il contient plus ou moins d'informations, mais nous le verrons plus tard.
En temps normal, le navigateur a des réactions prédéfinies aux évènements, par exemple change l'URL de la page quand on clique sur un lien, ou n'a aucune réaction définie par défaut. Ainsi dans notre exemple, si de passer la souris sur des liens faisait apparaître à chaque fois une alerte, ça se saurait.
Mais JavaScript permet à l'utilisateur de modifier le gestionnaire d'évènement, c'est à dire la réaction du navigateur. Ainsi, dans notre exemple, on indique au navigateur que l'évènement "onMouseover" (littéralement "quand la souris m'arrive dessus") est associé à une fenêtre d'alerte qui affichera ouille (hé oui, ça fait mal de se faire marcher dessus ;-)). Quant à notre champ texte, on se sert de l'évènement "onblur" pour en effacer le contenu.
Plusieurs types d'évènements sont disponibles selon l'élément et il est possible de définir ou de redéfinir le résultat d'un évènement. Pour ceux que titille l'envie d'en savoir plus, vous pouvez vous rapporter aux éléments existants de SELFHTML (lien ci-après)
Description de l'objet event et de ses viscicitudes
Les différents évènements en JavaScript
Abordons maintenant le coeur du problème. Nous voulons prévenir toute saisie de caractères ou d'expression illicites en même temps que l'utilisateur entre son texte. Lorsque l'utilisateur appuie sur une touche et la relache, l'objet event renvoie les valeurs suivantes:
Comme on le voit la gestion d'une frappe au clavier est assez fine. Seul l'évènement onKeyPress nous intéresse réellement par rapport au résultat que nous souhaitons obtenir et plus particulièrement le code de la touche qui a été enfoncée. Cette valeur est disponible grâce à la propriété keyCode ou which selon le navigateur employé. Notre première tâche est de récupérer le code décimal de la touche quelque soit le navigateur.
<html>
<head>
<script language="Javascript1.2" type="text/javascript">
<!--
function codeTouche(evenement)
{
for (prop in evenement)
{
if(prop == 'which') return('Vous utilisez Netscape');
}
return('Vous utilisez Internet Explorer');
}
function montreTouche(evenement)
{
alert(codeTouche(evenement));
}
-->
</script>
</head>
<body>
<form name="F">
Tapez des caractères ici: <input type="text" name="exemple" onKeyPress="montreTouche(event)">
</form>
</body>
</html>
|
Comme dans l'exemple précédent, nous imposons au navigateur de lancer la fonction montreTouche lorsque l'utilisateur appuie sur une touche. Pour pouvoir accéder au code de la touche, nous avons besoin de l'objet event associé à notre champ de texte, ce qui nous donne onKeyPress="montreTouche(event)".
Jusqu'ici tout va bien. Notre fonction montreTouche est chargée d'envoyer le code de la touche dans une fenêtre de message. Seul problème, quel est ce code? C'est là qu'intervient la fonction codeTouche et rien n'est simple dans ce bas monde, car:
Conclusion: pourquoi faire simple quand on peut faire compliqué? D'où l'astuce de tester l'existence d'une propriété which de l'objet event. Si on la trouve, c'est que nous sommes sur un navigateur compatible Netscape, sinon nous sommes sur un navigateur compatible IE. Bien évidemment, si l'on souhaite intercepter les touches spéciales, il faudra utiliser un moyen plus raffiné. Cette courte méthode permet de s'affranchir à moindre frais de la reconnaissance des navigateurs.
Cela dit, nous ne sommes pas sortis d'affaire pour autant, car la gestion de l'évènement OnKeyPress n'est pas strictement identique entre les deux navigateurs. Ainsi, la pression de la touche suppression en arrière génère un évènement OnKeyPress sous Netscape, mais pas sous Internet Explorer. De manière générale, Internet Explorer n'a pas la rigueur de Netscape et a tendance à "oublier" certaines touches dans l'émission d'un évènement (tabulation, touches de verrouillage, touches de fonction, ...).
Vous étiez impatients d'y arriver, hein? Pouvoir régner en maître sur les saisies de ces misérables internautes qui viennent polluer vos magnifiques formulaires! Et bien, voici la clé de vos désirs!
<html>
<head>
<script language="Javascript1.2" type="text/javascript">
<!--
function codeTouche(evenement)
{
for (prop in evenement)
{
if(prop == 'which') return(evenement.which);
}
return(evenement.keyCode);
}
function scanTouche(evenement)
{
var reCarValides = /\w/;
var codeDecimal = codeTouche(evenement);
var car = String.fromCharCode(codeDecimal);
var autorisation = reCarValides.test(car);
return autorisation;
}
-->
</script>
</head>
<body>
<form name="F">
Tapez des caractères ici (que des chiffres ou des lettres):
<input type="text" name="exemple" onKeyPress="return scanTouche(event)">
</form>
</body>
</html>
|
Nous sommes dans la continuité du script précédent. Notez un changement majeur pour assurer le succès de l'entreprise et bloquer ou laisser passer nos chers petits caractères: le handler onKeyPress du champ input est return montreTouche(event) et non plus juste montreTouche(event).
Ensuite la fonction scanTouche a été amendée pour comparer le caractère entré par l'utilisateur à l'ensemble des caractères permis. Pour cela, le plus efficace et le plus souple est encore d'utiliser les expressions régulières. Dans notre exemple, il s'agit d'une expression régulière toute simple, indiquant que toutes les lettres et tous les chiffres sont autorisées, ainsi que le trait de soulignement. Détaillons ensemble le déroulé de la fonction:
|
Jusqu'ici tout va bien. Et non! Souvenez-vous que IE et Netscape ne gère pas à l'identique les touches spéciales. Que se passe-t'il si l'utilisateur s'est trompé dans sa saisie et souhaite en effacer une partie? Sur IE, pas de problèmes avec ce script, car les touches de suppression ne génèrent pas d'évènement onKeyPress. Sur Netscape, il y a un hic. Le code de la touche retour arrière n'étant pas dans les caractères autorisés, point de suppression! La solution? Compléter notre script pour qu'il gère ces touches spéciales, à savoir:
En fait seul Netscape 6.+ génère un évènement onKeyPress et un code 0 pour certaines touches, qui sont néanmoins très utiles pour l'utilisateur. L'expression régulière correspondante s'écrit avec les codes hexadécimaux, /x0D par exemple. La fonction est ainsi modifiée:
function scanTouche(evenement)
{
var reCarSpeciaux = /[\x00\x08\x0D]/;
var reCarValides = /\w/;
var codeDecimal = codeTouche(evenement);
var car = String.fromCharCode(codeDecimal);
var autorisation = reCarValides.test(car) || reCarSpeciaux.test(car);
return autorisation;
}
|
C'est tout de même beaucoup plus confortable, non?
Les différents champ d'entrée d'un formulaire
Les expressions régulières en javaScript
Maintenant que nous savons intercepter et contrôler les saisies utilisateur se pose encore un problème. Pourquoi se priver du copier-coller (ctrl+V, ctrl+C, ctrl+X) et de la fonction d'annulation (ctrl+Z)? D'autant plus que notre script fonctionnera aussi bien dans un champ input que dans un champ textarea.
Et bien évidemment, la solution n'est pas simple si l'on souhaite apporter un minimum de portabilité:
<html>
<head>
<script language="Javascript1.2" type="text/javascript">
<!--
function codeTouche(evenement)
{
for (prop in evenement)
{
if(prop == 'which') return(evenement.which);
}
return(evenement.keyCode);
}
function pressePapierNS6(evenement,touche)
{
var rePressePapierNS = /[cvxz]/i;
for (prop in evenement) if (prop == 'ctrlKey') isModifiers = true;
if (isModifiers) return evenement.ctrlKey && rePressePapierNS.test(touche);
else return false;
}
function scanTouche(evenement)
{
var reCarSpeciaux = /[\x00\x08\x0D\x03\x16\x18\x1A]/;
var reCarValides = /\d/;
var codeDecimal = codeTouche(evenement);
var car = String.fromCharCode(codeDecimal);
var autorisation = reCarValides.test(car) || reCarSpeciaux.test(car) || pressePapierNS6(evenement,car);
return autorisation;
}
-->
</script>
</head>
<body>
<form name="F">
Tapez des caractères ici (que des chiffres): <textarea name="exemple" onKeyPress="return scanTouche(event);"></textarea>
</form>
</body>
</html>
|
Une nouvelle fonction a fait son apparition pressePapierNS6(evenement,touche). Elle utilise en paramètres l'objet event créé lors de la pression de touche et la valeur de la touche. Elle utilise également une expression régulière var rePressePapierNS = /[cvxz]/i; qui permet de savoir si la touche pressée correspond à c,v,x ou z. Nous testons ensuite l'existence de la propriété ctrlKey. Si celle-ci existe, la variable isModifiers est modifiée sur true. Si elle n'existe pas, la fonction renverra false dans tous les cas.
On exécute ensuite un test pour savoir si une des combinaisons du presse-papier a été utilisée. Il suffit ensuite de rajouter l'appel à cette fonction dans scanTouche au moment d'accorder l'autorisation.
Voilà, vous venez d'autoriser les copier-coller. De toute façon, entre nous, vous avez juste autorisé le raccourci clavier pour le copier-coller. N'importe quel utilisateur pouvait encore l'utiliser via le menu de la fenêtre ou le menu contextuel.
Alors du coup, il faut bien pouvoir vérifier a posteriori ce qu'a entré l'utilisateur. Mais il n'y a aucun problème pour utiliser une fonction testant le contenu du champ et l'effacant si une mauvaise valeur est entrée. On peut également se rapporter avec avantage à la section de SELFHTML en parlant. Je précise juste que je préfère réaliser un test avec onChange, plutôt que onSubmit (on peux aussi utiliser onBlur, mais cela génère des test plus fréquents et il n'est pas vraiment utile de tester un contenu qui n'a pas changé).
aperçu de l'exemple
Voir le code
Exemple de l'utilisation de l'évènement onSubmit pour vérifier le contenu d'un formulaire
La limite de ce script est bien évidemment de s'appuyer sur les évènements JavaScript. Certains navigateurs, surtout les plus anciens, ont tendance à se mélanger les pinceaux dans la chaîne d'évènements. On peut ainsi obtenir des résultats aléatoires. Essayez d'appuyer sur plusieurs touches simultanément, il est possible que le gestionnaire d'évènement soit débordé et que certaines lettres s'affichent malgré votre véto.
N'oubliez pas non plus que l'utilisateur non averti risque de ressentir une certaine angoisse en s'apercevant que son clavier ne fonctionne plus! Avant de le condamner à allez voir son SAV, n'oubliez pas d'inclure un petit message d'information quelque part. Une fenêtre d'alerte JavaScript peut ainsi contribuer à rassurer le pauvre internaute sur la santé de son clavier.
Enfin, un développement intéressant de ce script est de modifier en direct les saisies de l'utilisateur au lieu de se contenter de les bloquer. Par exemple, il est possible de changer à la volée une virgule en point pour que le résultat ressemble à un nombre décimal à l'anglo-saxonne. Cela peut-être utile en prémisses d'un script effectuant des calculs.
Un raffinement intéressant est également de paramétrer des expressions régulières type qui seront activées à l'aide d'une information placée dans la balise du champ de formulaire. Particulièrement utile lorsqu'un formulaire contient des données mixtes.
Je n'oublie pas non plus les débutants en expressions régulières (un outil puissant mais particulièrement coriace à assimiler) en leur donnant quelques expressions régulières type:
|
|