Le Javascript est un langage de programmation puissant. On y retrouve tout les types de boucles (for, while, do while ... ) et les instructions (if, if else ...). On peut même faire de la programmation orientée objet, mais ça, c'est un autre chapitre.
Dans cet exemple, on va créer une nouvelle page html dans laquelle on demandera à l'utilisateur une adresse mail, son prénom et sa date de naissance puis calculera le nombre de jours vécus. On lui enverra aussi un mail automatiquement avec le résultat.
Dans un premier temps, on peut modifier le code html de notre site web précédent en rajoutant les menus "Accueil" et "Nombre de jours vécus". Le menu "Accueil" permettra de retourner sur la page principale "index.html"
<!DOCTYPE!>
<html>
<head>
<html lang="fr">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Titre de mon site</title>
<link href="css/styles.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="js/scripts.js"></script>
</head>
<body>
<div class='wrapper'>
<div id='header'>
<h1><a href='index.html'>Formation CSS</a></h1>
<div>Mon premier site internet et patati et patata. Ceci n'a aucun intéret dans cette entête, mais
en mathématiques, un groupe est un magma associatif et unifère dans lequel chaque élément est symétrisable.</div>
</div>
<div id='content'>
<div id='sidebar'>
<ul id='main-nav'>
<li><a href='http://lepoittevin.olivier.free.fr'>Site de Mr Le poittevin</a></li>
<li><a href='index.html'>Accueil</a></li>
<li><a href='joursVecus.html'>Nombre de jours vécus</a></li>
<li><a href='#' onclick="alert('En cours de construction')">Ecrire</a></li>
<li><a href='#' onclick="alert('En cours de construction')">Catégories</a></li>
<li><a href='#' onclick="alert('En cours de construction')">Contact</a></li>
</ul>
</div>
<div class='contents'>
<div class="entry">
<p>Amoureux de la prose, jeune vagabond lyrique, qui se découvre et se délie la langue après
deux shots de tequila paf, et se pose en spectacle pour délivrer ses besoins de reconnaissance et de luxure, prenez
place et sortez vos neurones, l’heure est à l’étude.</p>
</div>
<div class="entry">
<p>Tout ça avait pour but d'illustrer le péril du conformisme, et la difficulté de préserver
vos convictions, quoi qu'en pense les autres. [...] Nous avons tous besoin d'être accepté, mais soyez persuadé que vos
convictions sont uniques, les vôtres, même si on les trouve anormales ou impopulaires, même si le troupeau dit « C'est
maaaaaaaaal ».<br> Robert Frost a dit : « Deux routes s'offraient à moi, et là j'ai suivi celle où on n'allait pas, et
j'ai compris toute la différence. »</p>
<p><i>Robin Williams, Le Cercle des poètes disparus (1989), écrit par Tom Schulman</i></p>
</div>
</div>
</div>
<div id='footer'> Texte du pied de page
</div>
</div>
</body>
</html>
Le code css est le même que dans le tutoriel précédent.
/* Dans ce site, on va essayer de placer les éléments dans le flux, c'est à dire qu'il seront placés
les uns après les autres.*/
body{
/* L'image de fond sera dans le dossier img */
background: url(../img/fond_img.jpg) repeat center top transparent;
}
.wrapper{
/* Le wrapper n'aura pas de marge et occupera 100% de l'écran pour sa largeur */
margin: 0;
width: 100%;
}
#header{
margin-left:5%; /* Marge correspondant à 5% de la largeur de l'écran */
margin-top: 2%;
width: 90%; /* L'entête occupera 90% de la largeur de son parent, c'est à dire le block .wrapper */
background-color: rgba(0,0,0,0.7); /*La couleur sera noire (0,0,0) et aura une opacité de 0.7 */
color: #FFFFFF;
border-radius: 5px;/* Angle arrondis */
}
#content{
/* Définition des marges, largeur */
display: inline-block;
margin-left: 5%;
margin-top: 2%;
width: 90%;
}
#footer{
/* Définition des marges, largeur et hauteur */
margin-top:2%;
width: 100%;
height: 10%;
/* Couleur du fond */
background-color: #000000;
color: #FFFFFF;
border-radius: 5px;/* Angle arrondis */
}
#sidebar{
/* Sidebar sera positionné en ligne */
display:inline-block;
/* Définition dés marges, hauteur et largeur */
margin-top: 2%;
margin-left: 3%;
margin-bottom: 2%;
width: 25%;
}
.contents{
/* Sidebar sera positionné en ligne */
display:inline-block;
/* Définition dés marges, hauteur et largeur */
float: right;
margin-top: 2%;
margin-right: 3%;
margin-bottom: 2%;
width: 65%;
background-color: rgba(0,0,0,0.6); /*La couleur sera noire (0,0,0) et aura une opacité de 0.7 */
color: #FFFFFF; /* La couleur du texte sera blanche */
border-radius: 5px;/* Angle arrondis */
}
.entry{
margin-left: 5%;
margin-top:2%;
width: 90%;
border-bottom: 1px solid #CEC6B5; /* bordure en bas de .entry de 1 pixel d'épaisseur */
}
h1{
text-align: center; /* Centre tous les titre h1 comme le titre de l'entête */
}
a { /* on donne une couleur à tous les liens du document */
color: #FF0000;
text-decoration: none;
text-align: left;
text-transform: uppercase; /* transforme le texte en majuscule */
}
#main-nav li {
padding: 10px 4px 6px 6px;
margin: 5px 0px;
background-image: linear-gradient(#fff,#aaa);
border-radius: 20px;
list-style: none; /*on enleve les icones de liste */
}
On obtient la page web suivante :
En cliquant sur "Nombre de jours vécus" le navigateur lancera la page "joursVecus.html" dont on va maintenat s'occuper. Il faut donc créer ce dernier fichier que l'on placera au même niveau que le fichier "index.html". Ce qui donne le code suivant :
<!DOCTYPE!>
<html>
<head>
<html lang="fr">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>Titre de mon site</title>
<link href="css/styles.css" rel="stylesheet" type="text/css"/>
<script type="text/javascript" src="js/scripts.js"></script>
</head>
<body>
<div class='wrapper'>
<div id='header'>
<h1><a href='index.html'>Formation CSS</a></h1>
<div>Mon premier site internet et patati et patata. Ceci n'a aucun intéret dans cette entête, mais
en mathématiques, un groupe est un magma associatif et unifère dans lequel chaque élément est symétrisable.</div>
</div>
<div id='content'>
<div id='sidebar'>
<ul id='main-nav'>
<li><a href='http://lepoittevin.olivier.free.fr'>Site de Mr Le poittevin</a></li>
<li><a href='index.html'>Accueil</a></li>
<li><a href='joursVecus.html'>Nombre de jours vécus</a></li>
<li><a href='#' onclick="alert('En cours de construction')">Ecrire</a></li>
<li><a href='#' onclick="alert('En cours de construction')">Catégories</a></li>
<li><a href='#' onclick="alert('En cours de construction')">Contact</a></li>
</ul>
</div>
<div class='contents'>
<div class="entry">
<p></p>
</div>
<div class="entry">
<p></p>
</div>
</div>
</div>
<div id='footer'> Texte du pied de page
</div>
</div>
</body>
</html>
En cliquant sur "nombre de jours vécus, on obtient la page web suivante :
L'objectif est de modifier cette page afin de créer trois zones de saisies, un bouton et un affichage pour le résultat. Ces derniers devront être entre les balises <form> et </form> qui définissent un formulaire.
html propose deux types de balise pour saisir du texte, l'une pour des saisies d'une seule ligne <input> et l'autre pour des saisies sur plusieurs lignes <textarea>. Dans cet exemple, on utilisera les saisies sur une seule ligne. On doit donc créer trois champs :
- Saisie d'un texte pour le prénom
- Saisie d'une adresse mail
- Saisie d'une date pour la date de naissance
html5 offre une multitude d'attributs pour des saisies de texte, de nombre, de dates, d'adresse mail, ...
Pour le bouton, on utilisera l'attribut "type = button". En cliquant dessus, on executera la fonction Javascript "joursVecus()" qui aura préalablement été chargée avec le fichier "scripts.js" comme dans le tutoriel précédent.
On préparera aussi un block pour afficher le résultat "nbJours" pour l'affichage du résultat.
Pour toutes les zones de saisie ainsi que le bouton, on utilisera l'attibut "name= ..." qui nous permettra d'y faire référence pour récupérer les données saisies.
Vous trouverez la liste des attributs ainsi que des exemples d'utilisation des balises HTML5 sur le site : https://www.w3schools.com/
Remplacez le code html du block <div class='content'> du fichier "joursVecus.html" par le code suivant. Ce dernier va créer ces zones de saisies, le bouton et va préparer un élément html pour la réponse.
<div class="entry">
<form name="nbJoursVecu">
<p>
<label for="prenom">Prénom</label> :
<input type="text" name="prenom" id="prenom" size="10" value="Prénom"/>
<label for="mail">Adresse mail</label> :
<input type="email" name="mail" id="mail" size="20" value="olepoittevin@ac-nantes.fr"/>
</p>
<p>
<label for="dateNaissance">Date de naissance</label> :
<input type="date" name="dateNaissance" id="dateNaissance" required/>
</p>
<p>
<input type="button" name='calcul' id='calcul' value="Calculer le nombre de jours vécus"
onClick='joursVecus()'/>
</p>
</form>
<div id="nbJours">
<p>Nombre de jours vécus : </p>
</div>
</div>
Il faut aussi rajouter les attributs du nouveau block "nbJours' dans le fichier "styles.css" en y insérant le code suivant :
/* Attributs du block nbJours */
#nbJours{
margin-top:2%;
width: 90%;
border-top: 1px solid #CEC6B5; /* bordure en haut de id=nbJours de 1 pixel d'épaisseur */
}
On obtient la page web suivante :
Essayez de cliquer sur le texte « Prénom » ou Date de naissance : vous allez voir que le curseur se place automatiquement dans la zone de texte correspondante. c'est due à la balise "label" qui renvoie sur le champ du nom de "prenom" ou "dateNaissance" à l'aide de l'attribut : for="prenom" pour le prénom ou for='dateNaissance' pour la date de naissance.
Il ne reste plus qu'a créer la fonction javascript qui récupérera les données saisies et, après un traitement, affichera le résultat.
Le code javascript suivant définit deux fonctions :
- date() : pour afficher la date et l'heure dans le pied de page comme on l'a vu dans le tutoriel précédent.
- joursVecus() : pour calculer et afficher le nombre de jours vécu.
La dernière ligne "window.onload = date;" lancera la fonction date() au chargement de la fenêtre.
Recopiez le code suivant et sauvegardez le dans un fichier momé "scripts.js". Vous ferez attention à l'endroit ou vous sauvegarderez ce fichier. Il doit correspondre au chemin indiquez dans le fichier "joursVecus.html" lorsque l'on charge "scripts.js".
function date(){
// la variable date contient la date courante obtenu par la classe Date
var date = new Date();
// la variable mois contient le N° du mois à partir de 0
// pour un affichage cohérent on ajoute donc 1
var mois = date.getMonth() + 1;
var annee = date.getFullYear();
var jour = date.getDate();
var heure = date.getHours();
var min = date.getMinutes();
var sec = date.getSeconds();
// on stocke l'affichage de la date et heure dans des variables
var formatD = jour + "/" + mois + "/" + annee;
var formatH = heure + " : " + min + " : " + sec;
// on prépare une nouvel élément HTML <p> en le stockant dans une variable
var nouveauParagraphe = document.createElement('p');
// on lui assigne un attribut supplémentaire
nouveauParagraphe.setAttribute('title','voici le titre de mon paragraphe');
// on prépare du texte que l'on assigne au paragraphe
// on anti-slashe l'apostrophe puisque l'apostrophe sert de caractère d'entourage
// à la chaine de caractères
var duTexte = document.createTextNode('Nous sommes aujourd\'hui le '+formatD+' et il est '+formatH);
nouveauParagraphe.appendChild(duTexte);
// enfin on peut insérer notre nouveau noeud à l'intérieur d'un autre élément HTML
document.getElementById('footer').appendChild(nouveauParagraphe);
}
function joursVecus(){
//Cette fonction s'execute lors d'un clic sur le bouton
//Cette ligne sert à tester si le bouton lance bien la fonction joursVecus().
document.getElementById("nbJours").innerHTML = 'Super, le bouton marche correctement';
}
window.onload = date;
En cliquant sur le bouton, vous devriez voir le texte de la division "nbJours" changer. Cela signifie que la fonction est bien lancée via le bouton.
On va maintenant récupérer l'année, le mois et le jour de la date saisie ainsi que de la date du jour. Pour cela, on va utiliser la classe Date() qui contient des méthodes pour gérer les dates. Vous trouverez les spécifications de cette classe sont sur le site https://www.w3schools.com/jsref/jsref_obj_date.asp .
Modifiez le code de la fonction jourVecus() comme ci-dessous.
function joursVecus(){
//récupération des données saisies par l'utilisateur
var prenom = document.forms['nbJoursVecu'].prenom.value; // récupération du prénom du formulaire
var dtNaissance = document.forms['nbJoursVecu'].dateNaissance.value; // récupération de la date de naissance du formulaire
var date = new Date(dtNaissance) ; //transformation de la date de naissance saisie pour le mettre au format de la class Date()
var annee = date.getFullYear() ; // C'est l'année de naissance
var mois = date.getMonth() ; // c'est le mois de naissance, 0 étant le mois de janvier
var jour = date.getDate() ; // le jour de naissance
var dateJour = new Date() ; //Affecte à la variable dateJour la date du jour de l'ordinateur
var anneeToday = dateJour.getFullYear() ; //On récupère l'année de la date du hour
var moisToday = dateJour.getMonth() ; // 0 est le mois de janvier, 1 le mois de février etc.
var jourToday = dateJour.getDate() ; // On récupère le jour de la date du jour
//On efface les calculs et résultats précédents
document.getElementById("nbJours").innerHTML = '' ;
//On vérifie que la date est bien renseignée, cela évitera au programme de planter si cette dernière est manquante
if(dtNaissance != ''){
//Cette ligne sert à vérifier le fonctionnement du code précédent
document.getElementById("nbJours").innerHTML = 'la date saisie est le : ' + jour + '-' + mois + '-' + annee +
' et la date du jour est le '+ jourToday + '-' + moisToday + '-' + anneeToday ;
}else{
document.getElementById("nbJours").innerHTML = 'Il faut saisir une date de naissance.';
}
}
En testant ce nouveau code, ous remarquerez que le mois de la date ne correspond ni pour la date saisie, ni pour la date du jour. En effet, pour la classe Date, le premier mois de l'année est le mois 0 et le dernier est le mois 11, ce qui fait que l'on a :
- 0 pour Janvier.
- 1 pour Février.
- 2 pour Mars.
- 3 pour Avril.
- ...
- 10 pour Novembre.
- 11 pour Décembre.
On pourrait facilement corriger ce programme pour lui faire afficher les valeurs habituelles des mois, mais ces lignes n'étant là que pour vérifier le fonctionnement de cette fonction, on s'abstiendra.
Dans cette fonction, on vérifie bien qu'il y a une date saisie, mais il faut aussi vérifier que la cette dernière est inférieure à la date du jour.
Il nous reste maintenant à traiter les données pour calculer le nombre de jours entre les deux dates. Dans un premier temps et pour se simplifier la tâche, on considèrera que tous les mois ont 30 jours. Le code suivant reprend l'instruction conditionnelle de la fonction jourVecus(). Je vous laisse le décortiquez et le comprendre. Vous pourrez le tester en ne saissant aucune date, en saisissant votre date de naissance ou en saisissant une date supérieure à la date du jour. Trouvez ce que fait ce code dans ce dernier cas et pourquoi ?
if(dtNaissance != ''){
//Initialisation des varialbles
var nbJourMois = 30 ; //Par défaut, on considère que tous les mois ont 30 jours
var nbJoursVecus = 0 ; //Compteur du nombre de jour entre les deux dates
//On compte le nombre de jours à l'aide de cette boucle, | correspond à "ou"
while(annee < anneeToday | mois != moisToday | jour != jourToday){ //Tant que les deux dates sont différentes
nbJoursVecus = nbJoursVecus + 1 ; //on compte un jour de plus
if(jour != nbJourMois){ // Si l'on n'est pas au dernier jour du mois,
jour = jour + 1; //on incrémente jour de 1
}else{
jour = 1 ; //sinon on met jour à 1 (premier jour du mois)
if(mois < 11){ //si l'on n'est pas en décembre
mois = mois + 1 ; //on incrémente mois de 1 pour passer au mois suivant
}else{
mois = 0 ; //Sinon on reviens en janvier et on incrémente d'une année
annee = annee + 1 ;
}
}
}
//Affichage du résultat
document.getElementById("nbJours").innerHTML = 'Vous avez vécus ' + nbJoursVecus + ' jours depuis votre naissance' ;
}else{
document.getElementById("nbJours").innerHTML = 'Il faut saisir une date de naissance.';
}
Ce code a au moins deux problèmes :
- Le résultat est trop approximatif, il n'y a pas 30 jours par mois.
- Il affiche un nombre de jours vécus lorsque la date de naissance est supérieure à la date du jour
Pour corriger ces problèmes, ll serait intéressant d'afficher les calculs intermédiaires. On pourrait ainsi vérifier son fonctionnement.
On va donc rajouter dans la boucle "while" un nouvel élément html que l'on insèrera dans l'élément "nbJours" comme on l'a déja fait dans le tutoriel précédent pour insérer la date dans le pied de page. Le code suivant reprend complètement la fonction joursVecus().
function joursVecus(){
//récupération des données saisies par l'utilisateur
var prenom = document.forms['nbJoursVecu'].prenom.value; // récupération du prénom du formulaire
var dtNaissance = document.forms['nbJoursVecu'].dateNaissance.value; // récupération de la date de naissance du formulaire
var date = new Date(dtNaissance); //transformation de la date de naissance saisie pour le mettre au format de la class Date()
var annee = date.getFullYear(); // C'est l'année de naissance
var mois = date.getMonth() ; // c'est le mois de naissance, 0 étant le mois de janvier
var jour = date.getDate(); // le jour de naissance
var dateJour = new Date(); //Affecte à la variable dateJour la date du jour de l'ordinateur
var anneeToday = dateJour.getFullYear(); //On récupère l'année de la date du hour
var moisToday = dateJour.getMonth() ; // 0 est le mois de janvier, 1 le mois de février etc.
var jourToday = dateJour.getDate(); // On récupère le jour de la date du jour
//On efface les calculs et résultats précédents
document.getElementById("nbJours").innerHTML = '';
//On vérifie que la date est bien renseignée, cela évitera au programme de planter si cette dernière est manquante
if(dtNaissance != ''){
//Initialisation des varialbles
var nbJourMois = 30 ; //Par défaut, on considère que tous les mois ont 30 jours
var nbJoursVecus = 0 ; //Compteur du nombre de jour entre les deux dates
//On compte le nombre de jours à l'aide de cette boucle, | correspond à "ou"
while(annee < anneeToday | mois!=moisToday | jour!=jourToday){ //Tant que les deux dates sont différentes
nbJoursVecus = nbJoursVecus + 1 ; //on compte un jour de plus
if(jour != nbJourMois){ // Si l'on n'est pas au dernier jour du mois,
jour = jour + 1; //on incrémente jour de 1
}else{
jour = 1 ; //sinon on met jour à 1 (premier jour du mois)
if(mois < 11){ //si l'on n'est pas en décembre
mois = mois + 1 ; //on incrémente mois de 1 pour passer au mois suivant
}else{
mois = 0 ; //Sinon on reviens en janvier et on incrémente d'une année
annee = annee + 1 ;
}
}
// on prépare une nouvel élément HTML <p> en le stockant dans une variable
var nouveauParagraphe = document.createElement('p');
// on lui assigne un attribut supplémentaire
nouveauParagraphe.setAttribute('title','titre de la réponse');
// on prépare du texte que l'on assigne au paragraphe
var duTexte = document.createTextNode('le ' + jour + '-' + mois + '-' + annee + ' + 1 jour, d\'ou '
+ nbJoursVecus + ' jours et la date du jour est le '+ jourToday + '-' + moisToday + '-' + anneeToday );
nouveauParagraphe.appendChild(duTexte);
// enfin on peut insérer notre nouveau noeud à l'intérieur d'un autre élément HTML
document.getElementById('nbJours').appendChild(nouveauParagraphe);
}
}else{
document.getElementById("nbJours").innerHTML = 'Il faut saisir une date de naissance.';
}
}
En lançant le calcul du nombre de jours vécus, vous obtiendrez la page suivante :
On peut maintenant vérifier le fonctionnement du programme
Vous remarquerez que si la date est supérieure à la date du jour, ce programme calcul le nombre de jours entre la date saisie et la date du jours de l'année suivant l'année saisie comme dans l'image suivante. En effet, on sort de la boucle de "while" si l'année de la date est supérieure à la date du jour et si la date a le même mois et le même jours que ceux de la date du jour.
On va maintenant modifier le code pour calculer le nombre exacte de jours vécus. Pour ce faire, on va utiliser un tableau en variable qui contiendra les nombres de jours par mois une année donnée. Il sera définit comme suit :
- var nbJourMois = [31,28,31,30,31,30,31,31,30,31,30,31] ;
Pour connaitre le nombre maximal de jours le mois de janvier, on fera donc référence à nbJour[0] qui renverra le nombre entier 31, pour le mois de juin, on ferra référence à nbJour[5] qui donnera 30.
Essayez de modifier votre code pour arriver à prendre en compte les différent nombre de jours dans un mois. On laissera de coté les années bissextiles dans cet exercice.
Vous trouverez la correction en cliquant ici.
On va pour finir prendre en compte les année bissextiles. La règle est la suivante : les année bissextiles sont les année multiple de 4 avec une exception pour les années multiples de 100 et une contre exception pour les années multiples de 400. C'est à dire :
- 2016 est une année bissextile car multiple de 4 sans être multiple de 100
- 2100 ne sera pas une année bissextile bien qu'elle soit multiple de 4, car elle est aussi multiple de 100.
- Par contre, 2400 sera une année bissextile bien qu'elle soit multiple de 100, car elle est aussi multiple de 400.
Pour prendre en compte ces années bissextiles, on va créer une nouvelle fonction nbJourMoisMax(). On donnera en entrer de cette fonction une année, et elle nous donnera en sortie le tableau nbJourMois que l'on a utilisé précédemment. Essayez de compléter le code de la fonction suivant.
function nbJourMoisMax(annee){
var nbJoursMois = [31,28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31] ; // Par défaut, l'année n'est pas bissextile
if(annee % 4 == 0){ // si l'année est divisible par 4
if(...............){ // si l'année est divisible par 100
if(.......................){ // si l'année est divisible par 400 alors l'année est bissextile
nbJoursMois[1] = ............. ;
}
}else{ //si l'année est divisible par 4 sans être divisible par 100, alors elle est bissextile
..............[....] = ......... ;
}
}
return nbJoursMois ;
}
Vous trouverez la correction en cliquant ici.
Il ne reste plus qu'a appeler cette fonction au bon endroit pour avoir un tableau correct du nombre de jours par moi à l'aide du code ci dessous. Vous pourrez aussi vérifier que la date saisie est inférieure à la date du jour.
var nbJourMois = nbJourMoisMax(annee) ;
Une fois que vous aurez vérifier votre résultat, vous pourrez supprimer l'affichage des lignes de vérification et n'afficher que le résultat.
Vous trouverez la correction complète du fichier "scripts.js" en cliquant ici. La page web obtenu est la suivante.
Ce tutoriel est déja très long. On verra dans un autre tuto comment envoyer un mail automatiquement à l'adresse saisie.