Réalisation de sites web

Sommaire du site

Présentation
Comment apprendre
L'équipement
La page web
  Styles et CSS
  HTML, structure de la page
  HTML, éléments du corps
Le langage JavaScript
  JavaScript, objets "core"
  JavaScript, DOM, les bases
  JavaScript, DOM, node
  JavaScript, compléments
Le langage PHP, les bases
  PHP, fonctions utiles
  PHP pour le web
  PHP, compléments
SQL, introduction
  MySQL et PHP pour le web
  MySQL, plus loin...
Applications AJAX
Annexes utiles
  Fichier .htaccess
  Sécurité des sites web
  Conception d'un site web
  Référencement, syndication

Sommaire détaillé

Mentions légales.

Chapitres de cette page
Contenu  -> 

Page mise à jour le : 12-08-2015

Haut de la page

Remarques nécessaires
Détection du navigateur
Vérification de formulaires
Expressions rationnelles
Exemple commenté
A suivre...

JavaScript, compléments

Remarques nécessaires

Lors de la mise en place de passages JavaScript dans une page web, il est  indispensable d'avoir deux types de réflexions :

Voici quelques éléments pour aider ces réflexions.

Pas d'exécution du JavaScript

Certains navigateurs rustiques tels que Lynx ou Mosaic n'exécutent pas le JavaScript, certes ils sont rarement utilisés mais les robots des moteurs de recherche aussi exécutent rarement le JavaScript.

De plus certains utilisateurs désactivent volontairement le JavaScript sur leur ordinateur.

Par conséquent, il est indispensable de faire en sorte que le site web reste fonctionnel si le JavaScript est absent, en particulier si l'on envisage d'être connu des moteurs de recherche.

Un bon moyen de vérifier cela (outre la désactivation du JavaScript sur son navigateur) est de tester le site avec un navigateur rustique.
Téléchargement de Lynx : http://pachome1.pacific.net.sg/~kennethkwok/lynx/

Quelques suggestions

Comportement différents selon les navigateurs

Pour des raisons historiques (les premiers navigateurs ont été créés avant les normalisations du W3C et de l'ECMA) les comportements sont différents selon les plates-formes.

Cela affecte l'HTML, les CSS et surtout le JavaScript.

Il est donc important de vérifier que les pages que l'on crée aient un rendu analogue selon les navigateurs, au moins les principaux.

En 2010, voici (approximativement les parts de marché des navigateurs web.

Parts de marché des navigateurs

Par conséquent, il vaudrait mieux que les pages soient correctes sur les cinq principaux navigateurs. Et Internet Explorer (qui est majoritaire) est celui qui diffère le plus au niveau du JavaScript des autres.

Mais ce n'est pas tout... En effet, chaque navigateur existe en différentes versions et il est illusoire de croire que les utilisateurs ont toujours la dernière version.

Par exemple pour Internet Explorer, en février 2010, on peut estimer (approximativement) que :

L'idéal serait de tester le site, non seulement avec différents navigateurs mais aussi avec leurs différentes versions. Ce n'est pas facile d'autant que sur la même machine il est assez délicat de faire cohabiter différentes version d'Internet Explorer.

Une solution raisonnable est de posséder et de tester sur place avec quelques uns des principaux navigateurs et de demander à son entourage de tester avec d'autres.

Et la question qui se pose est "Mais comment rendre mon code fonctionnel sur ces différentes plates-formes ?". Les éléments de réponses sont au paragraphe suivant.

Détection du navigateur

Tout d'abord, il existe une interface ("classe") disposant de propriétés d'identification de la plate forme.

Propriétés de l'interface "navigator"

userAgent
Informations complètes ("signature") de la plate-forme. Donc des informations sur le navigateur, sa version mais aussi le système d'exploitation.

Une liste des "userAgent" est disponible sur Wikipédia à l'article "User-Agent" :
http://fr.wikipedia.org/wiki/User-Agent

On remarquera que pour certains systèmes Microsoft Windows récents, le nom du système d'exploitation n'est pas très révélateur, voici une traduction :
Trouvé dans "navigator.userAgent" Nom habituel du système
Windows NT 6.1 Windows 7
Windows NT 6.0 Windows Vista
Windows NT 5.1 Windows XP
Windows NT 5.0 'Windows 2000'

appCodeName
Toujours "Mozilla" donc sans grand intérêt.

appName
Nom "théorique" du navigateur. Mais Firefox, Chrome et Safari renvoient "Netscape" !

appVersion
Commence par le numéro de version (sauf sur IE et Safari), est suivi d'autres informations (selon les plates-formes).
Sur IE, commence par "4.0 (compatible MSIE " suivi du numéro de version.
Sur Safari, le numéro de version est vers la fin, à la suite de "Version/" 

Utiliser les commentaires conditionnels d'Internet Explorer

Les commentaires conditionnels ne fonctionnent que sous Internet Explorer. De plus ce n'est pas du JavaScript mais de l'HTML. Enfin on peut toujours intégrer du JavaScript dans l'HTML.

Exemple :

<script type="text/javascript">
<!--
    IE= false;
//-->
</script>

<!--[if IE]>
  <script type="text/javascript">
  <!--
    IE= true;
  //-->
  </script>

<![endif]-->

En savoir plus :
http://www.blog-and-blues.org/articles/Les_syntaxes_de_commentaires_conditionnels_pour_IE_Windows

Tester l'existence de propriétés ou de méthodes

Certaines propriétés et méthodes ne sont connues que de certains navigateurs, parfois on les trouve sous d'autres noms sur d'autres équipements. Une technique simple consiste, avant d'utiliser un tel composant, à tester son existence.

Voici un exemple avec une difficulté assez connue : trouver la hauteur de la fenêtre du navigateur.
La propriété "window.innerHeight" donne cette information sur tous les navigateurs excepté Internet Explorer. Sur celui-ci on obtient cette valeur avec "document.body.clientHeight", mais depuis la version 6 l'information est fausse il faut utiliser "document.documentElement.clientHeight". Evidement cette dernière propriété n'est pas connue des versions antérieures à la 6.

Alors, la solution est :

h= 'inconnu';
if (window.innerHeight)
  h= window.innerHeight;
else if (document.documentElement && document.documentElement.clientHeight)
  h= document.documentElement.clientHeight;
else if (document.body && document.body.clientHeight)
  h= document.body.clientHeight;

Le premier test vérifie si "window.innerHeight" existe, dans ce cas (non IE) on prend cette valeur et c'est tout.

Sinon on teste la présence de "document.documentElement.clientHeight" (notez le double test pour éviter une erreur si "document.documentElement" était inconnu), dans ce cas c'est IE 6 ou supérieur.

Sinon on vérifie "document.body.clientHeight" et on prend sa valeur.

Si aucun test n'a réussi, 'h' reste à 'inconnu'.

En savoir plus sur ces propriétés :
http://www.howtocreate.co.uk/tutorials/javascript/browserwindow (en anglais)

Vérification de formulaires

La vérification des informations de formulaire est une des applications du JavaScript des plus utiles. En effet avant de transmettre le formulaire à la page de traitement (attribut 'action'), il est souhaitable de vérifier si les champs sont correctement remplis. Cela permet à l'utilisateur du site de corriger ses éventuelles erreurs ou omissions et, par conséquent, soulage la page de traitement du formulaire.
Cependant, cette page de traitement doit, elle aussi, vérifier les informations car l'utilisateur a pu désactiver le JavaScript.
La vérification se fait en gérant l'événement "onsubmit" dans l'élément 'form'. Cet événement est un peu particulier car sa gestion doit renvoyer 'true' si les informations du formulaire sont correctes et, dans ce cas, l'action du formulaire est entreprise. Si le gestionnaire de l'événement renvoie 'false", l'action n'est pas réalisée et l'on reste sur le formulaire.
En général, la vérification du formulaire est faite par une fonction qui renverra 'true' ou 'false' il faut donc répercuter cette information dans le gestionnaire d'événement.
<script language="JavaScript" type="text/JavaScript">
<!--
function Controle() {
    ....
    return false; //Il y a une erreur
    ....
    return true; //Tout est correct
}
//-->
</script>
......
<form .... onsubmit="return Controle()">
....
</form>
.....

Accès aux éléments du formulaire

Bien qu'il serait souhaitable d'utiliser la méthode 'getElementById()' du DOM, on utilise souvent l'ancienne forme : "document.nom_formulaire.nom_element".

D'une façon ou d'une autre on peut connaitre la valeur d'un élément avec la propriété 'value' et, dans le cas de cases à cocher, utiliser la propriété "checked" qui renvoie un booléen indiquant si la case est cochée.

<script language="JavaScript" type="text/JavaScript">
<!--
function Controle() {
    ....
    ...document.ident.nom.value...
    if (document.ident.case.checked)....
    ....
}
//-->
</script>
......
<form name="ident".... onsubmit="return Controle()">
....
<input name="nom">
....
<input name="case" type="checkbox">
....
</form>
....

D'autres possibilités d'accès sont décrites dans l'exemple du bas de cette page.

Contrôle "instantané" sur un champ

Dans certains cas, il peut être utile de faire un contrôle dès la saisie d'un champ afin de prévenir l'utilisateur d'une erreur. Pour cela on gère un événement affectant ce champ. Le plus utilisé est "onchange" qui indique que la valeur d'un élément est modifiée.

Cela ne dispense pas de faire un contrôle final de validité car l'utilisateur peut ne pas corriger son erreur.

Là il est commode d'utiliser l'objet 'this' qui désigne l'élément courant.

<input name="mdp" type="password"
    onchange="if (this.value.length < 3) alert('Au moins 3 caractères')">

Expressions rationnelles (ou régulières)

Parfois (et notamment dans la vérification des formulaires) on doit vérifier si un texte saisi est conforme à une syntaxe particulière. Au lieu de faire une vérification fastidieuse et complexe en analysant le texte, il est souvent intéressant d'utiliser les fonctions sur les expressions rationnelles qui sont gérées par le JavaScript.

En fait, les expressions rationnelles ou régulières sont utilisées bien au delà du JavaScript car le PHP dispose aussi des fonctions associées et même les serveurs "Apache" les utilisent dans les fichiers d'accès.

Si l'on s'en tient au JavaScript, celui-ci utilise ces expressions dans les fonctions de chaîne de caractères :

test(); vérifie si une chaîne contient une expression.
exec(); sépare une chaîne en sous-chaînes.
match(); recherche des correspondances avec une expression rationnelle.
replace(); remplace dans une chaîne les occurrences d'une expression rationnelle.
search(); renvoie la position de la première occurrence d'une expression rationnelle dans une chaîne.

Il n'est pas de notre propos ici de décrire précisément ces fonctions car des sites spécialisés tels SelfHTML le font très correctement. Toutefois, nous allons voir les grands principes de la forme d'une expression rationnelle.

Type "expression rationnelle"

Le JavaScript utilise un type de données spécifique pour ces expressions (ce ne sont pas des chaînes de caractères) : 'RegExp' .

On peut utiliser une expression rationnelle constante en l'encadrant de barres obliques :
exp= /reg/;

Ou à partir d'une chaîne par instanciation du type :
exp= new RegExp("reg");

Syntaxe

Une expression rationnelle est une suite de caractères, certains ont un rôle particulier mais les lettres et les chiffres ont leur valeur propre.

Par exemple :

expression Avec 'test()' trouve dans (en gras)
e Albert est gentil
en Albert est gentil

Voici quelques caractères à rôle spécifique :

Car. Rôle Expression Trouve dans (en gras)
^ Début ^Je Je pense donc je suis
$ Fin s$ Je pense donc je suis
. Un caractère e.s Je pense donc je suis
* Zéro ou plusieurs fois ce qui précède s.*u Je pense donc je suis
[car] L'un des caractères entre crochets [dap] Je pense donc je suis

Il en existe beaucoup d'autres que l'on peut trouver sur des sites spécialisés comme :
https://developer.mozilla.org/fr/R%C3%A9f%C3%A9rence_de_JavaScript_1.5_Core/Objets_globaux/RegExp

Ces caractères spéciaux peuvent être neutralisés (si on les recherche) en les préfixant par l'anti-slash. Par exemple '\*' pour chercher l'astérique.


Application à la vérification d'une adresse électronique

Voici un fragment de script permettant de vérifier la validité d'une unique adresse électronique :
var reg = new RegExp(
'^[a-z0-9]+([_|\.|-]{1}[a-z0-9]+)*@[a-z0-9]+([_|\.|-]­{1}[a-z0-9]+)*[\.]{1}[a-z]{2,6}$'
, 'i');

if (reg.test(document.form_test.mail.value))
    //Adresse valide

Le dernier paramètre 'i' du constructeur 'RegExp' indique qu'il ne sera pas fait de différences entre majuscules et minuscules.

On a, dans l'ordre :

^[a-z0-9]+ Commence (^) par une des 26 lettres ou un chiffre, répété une ou plusieurs fois (+)
([_|\.|-]{1}[a-z0-9]+)* suivi du souligné, point, tiret (uniques), lettre ou chiffre (au moins un), répétés zéro, une ou plusieurs fois (*)
@ ensuite un arobase
[a-z0-9]+ lettres ou chiffre, répété une ou plusieurs fois (+)
([_|\.|-]­{1}[a-z0-9]+)* suivi du souligné, point, tiret (uniques), lettre ou chiffre (au moins un, répétés zéro, une ou plusieurs fois (*)
[\.]{1} un point et un seul
[a-z]{2,6}$ enfin se termine par 2 à 6 lettres.

Exemple commenté de gestion de formulaire

Utiliser l'exemple (autre fenêtre ou onglet)
(ne pas hésiter à consulter le source complet voire l'imprimer).

Commençons par voir quelques extraits de la partie HTML (dans l'élément 'body').

HTML

<body onload="document.form_test.texte.focus();" dir="ltr">
  <h1>Formulaire de test</h1>
  <form name="form_test" id="test" method="get"
        action="javascript:Valide()" onsubmit="return Verifie()">
    <table class="tab_form" align="center" border="1"
            cellpadding="2" cellspacing="0" width="80%">

On remarque que tous les champs ont un attribut 'name' afin de pouvoir être gérés par JavaScript.

Dans le cas de la liste de cases à cocher, le nom est donné sous la forme d'éléments de tableau afin d'avoir un traitement générique en JavaScript.

0<input name="lc[0]" value="0" type="checkbox">
1<input name="lc[1]" value="1" type="checkbox">
2<input name="lc[2]" value="2" type="checkbox">
3<input name="lc[3]" value="3" type="checkbox">

Dans le cas des boutons radio le nom est le même pour tous les boutons du groupe.

A<input name="br" value="a" type="radio">
B<input checked="checked" name="br" value="b" type="radio">
C<input name="br" value="c" type="radio">

A la fin de la page on trouve la division d'accueil des résultats qui est presque vide et est associée à l'ID 'result'.

    <div id="result" class="resultat">
      <h2>
        Résultats soumission
      </h2>
    </div>


Pour le JavaScript, on va commencer par examiner la fonction de contrôle avant soumission 'Vérifie()'.

Vérification du formulaire avant soumission

Au début, les déclarations de variables locales (utilisation du mot 'var').

function Verifie() {
var reg = new RegExp(
'^[a-z0-9]+([_|\.|-]{1}[a-z0-9]+)*@[a-z0-9]+([_|\.|-]­{1}[a-z0-9]+)*[\.]{1}[a-z]{2,6}$', 'i'
);
var msg= "";
var focus= null;
var coche= 0;

'reg' est utilisée pour la vérification de conformité de l'adresse électronique.
'msg" et 'focus' servent en cas d'erreur. La première pour contenir le message d'erreur, la seconde pour placer le curseur (méthode 'focus()') sur le premier champ en erreur.
'coche' contiendra le nombre de cases cochées de la liste.

Voici les premiers tests.

if (document.form_test.texte.value.length < 5) {
    msg= "Le champ 'Texte' est trop court\r\n";
    focus= document.form_test.texte;
}
if (document.form_test.mdp.value.length < 3) {
    msg += "Le champ 'Mot de passe' est trop court\r\n";
    if (focus == null) focus= document.form_test.mdp;
}
if (!reg.test(document.form_test.mail.value)) {
    msg += "Le champ 'Adresse électronique' est invalide\r\n";
    if (focus == null) focus= document.form_test.mail;
}

En cas d'erreur, au premier test, les variables 'msg' et 'focus' sont  affectées.
Pour les tests suivants et en cas d'erreur, 'msg' est complétée mais focus est affectée uniquement si elle ne l'était pas déjà.

Le test sur la liste de cases à cocher est un peu plus compliqué.

for (var i= 0; i < 4; i++) {
  var elt= "lc["+i+"]";
  if (document.form_test.elements[elt].checked) coche++;
}
if (coche < 2) {
  msg += "Il n'y a pas assez de cases cochées dans la liste\r\n";
  if (focus == null) focus= document.form_test.elements['lc[0]'];
}

Il faut "parcourir" les différentes cases pour savoir si elles sont cochées : boucle 'for'. A chaque tout la variable locale 'elt' indique le nom de la case : 'elt[0]', 'elt[1', etc.
Et on utilise la propriété de formulaire 'elements' indicée sur le nom de la case. Si la case est cochée la variable 'coche' est incrémentée.

Il suffit de tester la valeur de 'coche' pour savoir le nombre de cases cochées dans la liste.

La fonction de contrôle se termine par :

if (focus != null) {
  focus.focus();
  alert(msg);
  return false;
}

return true;

Dans le cas où la variable 'focus' est différente de 'null' il y a au moins une erreur.
Dans ce cas, 'focus' indique le premier élément en erreur, on place alors le curseur sur celui-ci avec la méthode 'focus()', on affiche l'ensemble des messages et on renvoie 'false' afin que le formulaire ne soit pas soumis.

Dans le cas où il n'y a pas d'erreur, il suffit de renvoyer 'true'. Le formulaire sera soumis.

Soumission du formulaire

En général, l'attribut 'action' de l'élément 'form' appelle une page exécutant un programme côté serveur (souvent écrit en PHP) qui traitera les informations du formulaire.

Pour cet exemple, comme on est dans la partie JavaScript, le traitement  est réalisé en JavaScript dans cette page. par la fonction 'Valide()'.

Voyons les premières déclarations.

var div_res=  document.getElementById("result");
function CreeLigne(texte) {
    var elt= document.createElement("P");
    var txt=document.createTextNode(texte);
    elt.appendChild(txt);
    div_res.appendChild(elt);
}

La variable locale 'div_res' contient l'élément qui accueillera les résultats.

Ensuite on a une fonction (interne) dont le but est d'afficher un résultat transmis par le paramètre 'texte'.
Pour cela on crée un élément paragraphe ('P'), un noeud texte qui contient le paramètre, on associe ce noeud à l'élément paragraphe créé et ce dernier est associé à la division des résultats.

Mais il s'agit là d'une fonction qui sera appelée pour chaque résultat. La soumission commence son exécution juste au dessous.

Une première partie est chargée de nettoyer la division des résultats d'éventuels résultats précédents.

var elt= div_res.firstChild;
while(elt != null){
 var sui= elt.nextSibling;
  if (elt.nodeName == 'P') div_res.removeChild(elt);
  elt= sui;
}

La variable 'elt' est placée sur le premier élément de cette division.
Si 'elt' n'est pas 'null' alors il y un élément, on commence par déterminer le suivant éventuel dans la variable 'sui'. Si l'élément 'elt' est un paragraphe on le supprime, ensuite l'élément courant devient le successeur et on boucle.
Ainsi tous les paragraphes de résultat on été effacé mais pas le titre qui est un élément 'h2'.

Le "ménage" fait, il faut afficher. Ce n'est pas compliqué pour les premiers champs.

CreeLigne("Texte : "+document.form_test.texte.value);
CreeLigne("Mot de passe : "+document.form_test.mdp.value);
CreeLigne("Adresse électronique : "+document.form_test.mail.value);
CreeLigne("Case à cocher unique : "+document.form_test.case_u.checked);

Notre fonction locale 'CreeLigne' s'en occupe.
Pour les champs de type texte et mot de passe, on utilise la propriété 'value'.
Pour la case à cocher unique, on prend la propriété 'checked' qui est un booléen.

A nouveau pour la liste de cases à cocher c'est un peu plus compliqué.

var cases= "";
for (var i= 0; i < 4; i++) {
    var elt= "lc["+i+"]";
    if (document.form_test.elements[elt].checked)
        cases += " "+document.form_test.elements[elt].value;
}
CreeLigne("Liste de cases à cocher :"+cases);

La variable 'cases' est initialisée à la chaîne vide, elle contiendra le texte à afficher.
Ensuite une boucle de parcours avec la création d'une variable 'elt' qui contiendra le nom de la case courante comme dans la fonction de contrôle du formulaire.
Mais là si la case est cochée (propriété 'checked') on ajoute sa valeur à la variable 'cases'.
Une fois la boucle terminée on fait l'affichage.

La récupération des informations des boutons radio est assez proche.

for (var i= 0; i < document.form_test.br.length; i++)
    if (document.form_test.br[i].checked) {
        CreeLigne("Bouton radio : "+document.form_test.br[i].value);
        break;
    }

Là aussi une boucle, mais on n'a pas à créer une variable de type case de tableau car les boutons radios se partageant le même nom sont considérés comme un tableau.
Il faut tout de même savoir lequel est actif, obtenir sa valeur et l'afficher.
Comme il ne peut y en avoir qu'un, une fois trouvé on quitte la boucle (instruction 'break'). Mais cela est facultatif c'est juste pour gagner un peu de temps.

Enfin il faut obtenir les informations de la liste à choix multiple.

var liste= "";
for (var i= 0; i < document.form_test.liste.length; i++)
    if (document.form_test.liste.options[i].selected)
        liste += " "+document.form_test.liste.options[i].value;
CreeLigne("Liste déroulante :"+liste);

On crée une variable de chaîne vide : 'liste' et on balaye la liste par une boucle. L'élément de liste est un tableau on peut utiliser la propriété 'length' pour connaître sa taille.
Les éléments de la liste (éléments 'option') sont dans la propriété tableau 'options' et disposent chacun de la propriété 'selected', booléen indiquant si cette option est sélectionnée. La propriété 'value' en donne la valeur.
Donc pour chaque option sélectionnée sa valeur est concaténée dans la variable locale 'liste' qui est  affichée une fois la boucle terminée.

A suivre...

Voilà c'est terminé pour le JavaScript. Bien sûr toutes les propriétés et méthodes de tous les objets possibles non pas été vues. En effet il n'est pas dans l'objectif de ce site d'être un manuel de référence.

Par contre, l'objectif est de donner un aperçu tout de même assez approfondi des possibilités du langage. Est-ce réussi ?

Avant de continuer il serait bon de prendre le temps de faire quelques réalisations en JavaScript.

Pour la suite, comme on en a fini avec ce qui se passe sur la machine de l'utilisateur, on va voir le côté serveur. La programmation n'est pas terminée car cette suite concerne le langage PHP qui va permettre au serveur de fabriquer les pages d'une façon plus personnalisée.

La suite sur PHP