Version complète: sur le forum Webmaster Hub : Vérifiez une date en raisonnant par l'absurde !
Webmaster Hub > Création et exploitation de Sites Internet > Les langages du Net > AjaX et JavaScript
David Vincent
Si vous faites du développement web de manière régulière et que vous vous êtes essayé au Javascript, vous avez certainement déjà eu l'occasion de réaliser quelques scripts de contrôle de premier niveau sur la saisie des champs dans un formulaire html.

Parmi les différents contrôles que vous pouvez être amenés à faire sur des champs de saisie, il se peut que vous ayiez à réaliser un contrôle sur la validité d'une date. A partir de là, deux solutions s'offrent à vous :
  • soit vous récupérez un script sur le net et vous l'appliquez tel quel à votre cas.
  • soit vous vous plongez dans la programmation à partir de zéro et vous vous rendrez vite compte qu'il va falloir y passer plus de temps que vous ne le croyiez.
Lisez l'article intégral sur les publications du Hub

Faites-moi un petit coucou pour me dire si cette astuce vous a été utile wink.gif
Dan
Salut David,

Impressionnant ! Tu ne serais pas tenté par de la publication Spip ?
Je pense que ton article mérite d'y être déplacé wink.gif

Dan

<edit: c'est maintenant chose faite !>
MrFab
perso, j'évite les contrôles en js, il y a de trop nombreux utilisateurs qui le désactivent. Je m'en remets au php. Et sans contrôle, ça donne parfois des bases de données complètement trouées de partout : /
Au moins côté serveur, on est sûr de ne pas avoir de mauvaises surprises.

Ce qui n'enlève rien à la qualité de ton article, mon cher David biggrin.gif
David Vincent
Oui, je découvre SPIP depuis quelques heures et j'avoue que je cafouille un peu smile.gif
J'ai reposté cet article dans SPIP, j'espère ne pas provoquer trop de soucis.

Et pour répondre à MrFab, oui, tu as raison, il est indispensable de faire systématiquement les contrôles côté serveur. C'est effectivement la seule partie que tu maîtrises vraiment.

Ce n'est par contre pas le cas du navigateur client. Faire ses contrôles côté client uniquement n'est pas suffisant car le JavaScript peut-être désactivé.

L'utilité de faire des contrôles côté client existe pourtant bien, si JavaScript est activé, il permet d'éviter des aller / retour inutiles vers le serveur, ce qui permet d'alléger sa charge de travail (surtout s'il s'agit d'un site très fréquenté) et de faire gagner du temps à l'internaute.

Mais répétons-le, les contrôles côté serveur restent indispensables smile.gif
Ernestine
Bonjour David, et bravo pour cette adorable petite astuce smile.gif
Fallait y penser... Mac Gyver n'aurait pas fait mieux.
Dan
CITATION(David Vincent @ mardi 02 septembre 2003, 17:29)
Oui, je découvre SPIP depuis quelques heures et j'avoue que je cafouille un peu smile.gif
J'ai reposté cet article dans SPIP, j'espère ne pas provoquer trop de soucis.

Tu t'es débrouillé comme un chef!
Spip est un CMS très rapide à appréhender, tu viens d'en faire une éclatante démontration wink.gif

Dan

PS: J'ai édité ton post pour y mettre le lien vers l'article sous Spip. C'est mieux car Spip se référence infiniment mieux que n'importe quel forum.
Googlebot a digéré toute la partie publication cet après midi. wink.gif

Dan
Anonymus
petit coucou wink.gif
pour dire que l'info sera probablement bientot utile.
Je suis également du style à faire tout ca en php, mais c'est vrai que décharger une partie de la tache au javascript, ce peut etre une bonne alternative.

A+, Anonymus
Anonymus

Donc, en php, je propose :
<?
$date="03/9/2003";
$valide_date=explode("/",$date);
if (checkdate($valide_date[1],$valide_date[0],$valide_date[2])){
echo"date valide : <br>";
}
?>
Ca ne vérifie pas si la date est correcte, mais à mon avis, ca vérifie si elle est bonne. La différence ? La doc dit :
L'année est comprise entre entre 1 et 32767 inclus.


Voilà, A+, Anonymus.
Jan
Ex-cel-lent script! Comme quoi on n'a jamais fait complètement le tour de javascript rolleyes.gif

Si rien ne remplace effectivement la vérif coté serveur, j'essaye pour ma part de le soulager au maximum (le pôvre petit):
- pour les vérifications de formulaires, je place dans le formulaire à vérifier un champ caché (hidden), disons jsactif, dont la "value" par défaut est false.
- Lors de la soumission du formulaire, j'appelle un script javascript qui fait la vérif des champs du formulaire ET positionne jsactif à true
- après envoi au serveur, je teste coté serveur la valeur du champ jsactif
- s'il est false (le script javascript au onSubmit n'a pas été exécuté, donc javascript est désactivé), je fais la vérif coté serveur
- s'il est true (le script javascript au onSubmit a été exécuté, donc javascript est activé), je n'ai pas besoin de faire la vérif coté serveur: tout bénef...

C'est avec les petits ruisseaux qu'on fait les grandes rivières whistling.gif
phplive
Bjr

Oui ... mais

// Je regarde tout d'abord si la chaîne n'est pas vide, sinon pas la peine d'aller plus loin
if (chaineDate != "") return false

serait plus juste comme ca :

if (chaineDate == "") return false

biggrin.gif
silvain59
géniale l'idée !!!!

Mais juste une petite rectification de tordu !!! Ca vérifie bien si le jour,mois, année sont des entiers avec isNaN donc exclu les cas ou un caractère autre qu'un chiffre est entré.

Mais il y a une petite correction à rajouter: Si pour le jour,le mois ou l'année on rentre un "." à la fin comme 2./5./200. aucune erreur n'est renvoyée !! Car le parseInt renvoie pour le jour "2" qui est bien un nombre... Donc il faut faire un petit test pour etre sur qu'il n'y a pas un "." a la fin du jour, du mois et de l'année

voici le test complet que j'utilise:

if ((ladate.length != 3) || isNaN(ladate[0]) || isNaN(ladate[1]) || isNaN(ladate[2]) || eval(ladate[0])<0 || eval(ladate[1])<0 || eval(ladate[2])<0 || parseInt(ladate[0])!=parseFloat(ladate[0]) || parseInt(ladate[1])!=parseFloat(ladate[1]) || parseInt(ladate[2])!=parseFloat(ladate[2]) || ladate[0].substr(ladate[0].length-1,1)=="." || ladate[1].substr(ladate[1].length-1,1)=="." || ladate[2].substr(ladate[2].length-1,1)==".") return false


explications:

il faut naturellement tester que les entrées soit positives car isNaN(-1) renvoie true (c'est bel est bien un nombre un relatif !)

ensuite il faut tester que parseInt soit egal a parseFloat car exemple:
parseInt(.5) = 5
parseFloat(.5) = 0.5

on elimine donc par ce test le cas ou l'utilisateur rentre un floatant comme année par exemple

le test du "." a la fin est toujours necessaire car
parseInt(5.) = 5
parseFloat(5.) = 5

voila c'est un peu compliqué mais c'est histoire d'avoir une liste exhaustive des differentes eventualités et histoire d'etre sur que la date est CORRECTE a 100% !!

mais ca n'enleve rien a ton génie !

silvain
romsiw
En gros, ma question : cette fonction ne fait que vérifier ? (booléen ?)
romsiw
Bon excusez le post précédent, c'est du n'importe quoi sad.gif

Voici le test que j'ai fait :
j'ai cette date entrée dans le champs : 23/07/2004

onblur="if(doverif_valid_date(this.value)) alert('ok'); else alert('pas ok');"

et il me met pas ok onblur du champs... ??
silvain59
Oui cette fonction ne fait que vérifier.

Je te redis vite fait le principe pour que tu t'en rendes compte:

Javascript corrige automatiquement des dates incorrects et renvoie une valeur qui lui parait correcte.

Ainsi si tu tape 0 janvier 2001 comme date, soit si tu es sous IE il te retourne 31 decembre 2000, soit si tu es sous Netscape 2 janvier 2001. D'ou le 1er pb, si tes utilisateurs ont des navigateurs différents (ce qui est fort probable) la correction automatique ne sera pas la meme !

Et puis le 2e pb (nettement plus genant) si l'utilisateur tape une date au format completement merdique: sans le mois ou avec des lettres... comment veux-tu que la fonction puisse te corriger ca en une date cohérente proche de celle que l'utilisateur aura voulu rentrer ?!!! L'ère de l'IA approche mais tout de meme 1eye.gif

silvain
romsiw
peux tu répondre à mon deuxieme post stp ?
silvain59
j'ai essayé et je pense que tout simplement il te faut utiliser des { }:

onblur="if(doverif_valid_date(this.value)) {alert('ok');} else {alert('pas ok');}"

dis moi si ca marche wink.gif

silvain
romsiw
ah ok ! j'ai utilisé une autre méthode finalement, mais je pense que c'était ça wink.gif

http://www.toutjavascript.com/savoir/savoir06_4.php3
marche pas mal non plus smile.gif
Desesperance
Bonjour,

Ne serait-ce pas plus simple de passer par des regex ?
silvain59
connait pas... qu'est-ce donc ???
Desesperance
Ce sont les expressions régulières.

J'avoue ne pas être très fort là dedans, c'est un très grand tort d'ailleurs.
Ca permet un travail sur les chaines de caractères très précis et performant.

Pour le php le site qui fait référence (en français en tous cas) est http://www.expreg.com.

Pour le javascript une recherche sur google peut être pratique smile.gif
David Vincent
Absoluement, ma fonction peut être simplifiée au niveau de la vérification syntaxique grâce à une expression régulière. Je ne connaissais pas à l'époque et c'est pour ça que je n'en ai pas mis.

Celle-ci devrait faire l'affaire :

function isDateValid(chaineDate) {

// Je regarde tout d'abord si la chaîne n'est pas vide, sinon pas la peine d'aller plus loin
if (chaineDate == "") return false

// J'utilise une expression régulière pour normaliser ma date en "JJ/MM/AAAA"
// au cas où la date aurait été saisie au format "JJ-MM-AAAA" ou "JJ.MM.AAAA".
chaineDate = chaineDate.replace(/(-|\.)/g, "/")

// Je teste ensuite si la date contient des entiers.
// Le jour et le mois inférieurs à 10 peuvent être écrits sans le zéro.
// L'année doit être sur 4 chiffres.
if (chaineDate.search(/^[0-9]{1,2}\/[0-9]{1,2}\/[0-9]{4}$/) == -1) return false

// On crée un tableau dans lequel on récupère les jour mois année
var ladate = chaineDate.match(/\d{2,4}/g)

// Maintenant on crée la date correspondante. Attention, les mois sont étalonnés de 0 à 11
var unedate = new Date(eval(ladate[2]),eval(ladate[1])-1,eval(ladate[0]))

// Bug de l'an 2000 oblige, lorsque je récupère l'année, je n'ai pas toujours 4 chiffres selon les navigateurs, je rectifie donc ici le tir.
var annee = unedate.getYear()
if ((Math.abs(annee)+"").length < 4) annee = annee + 1900

// Il ne reste plus qu'à vérifier si le jour, le mois et l'année obtenus sont les mêmes que ceux saisis par l'utilisateur.
return ((unedate.getDate() == eval(ladate[0])) && (unedate.getMonth() == eval(ladate[1])-1) && (annee == eval(ladate[2])))
}


Ah, c'est quand-même dur de s'y mettre aux expressions, régulières, mais ça rend bien des services quand-même.
Ceci est une version "bas débit" de notre forum. Pour voir la version complète avec plus d'information, la mise en page et les images, veuillez cliquer ici.