Академический Документы
Профессиональный Документы
Культура Документы
www.openclassrooms.com
Licence Creative Commons 6 2.0
Dernire mise jour le 9/12/2012
2/378
Sommaire
Sommaire ...........................................................................................................................................
Lire aussi ............................................................................................................................................
Dynamisez vos sites web avec Javascript ! .......................................................................................
Partie 1 : Les bases du Javascript ......................................................................................................
2
6
8
9
10
10
11
12
12
13
13
13
Sommaire
3/378
78
78
78
78
80
80
80
81
88
Sommaire
4/378
164
165
165
171
199
199
200
201
202
202
203
Sommaire
5/378
225
225
225
227
227
228
229
230
249
249
249
249
250
250
250
255
255
255
255
256
Sommaire
6/378
278
278
278
278
279
279
281
281
281
282
283
285
285
286
286
286
287
289
289
289
289
291
292
292
295
302
304
304
304
304
305
305
305
307
Lire aussi
7/378
329
329
330
330
331
331
334
335
335
335
336
338
341
344
344
345
348
365
366
366
367
367
370
373
373
373
374
374
376
Lire aussi
8/378
Par
Bienvenue tous,
Vous voici sur la page d'accueil du cours traitant du langage Web Javascript ! Au cours de la lecture de ce cours vous
apprendrez comment dynamiser vos pages Web et les rendre beaucoup plus attrayantes pour vos visiteurs. Ce cours traitera de
nombreux sujets, en partant des bases. Vous apprendrez raliser des animations, des applications complexes et utiliser ce
langage conjointement avec le HTML5, la nouvelle version du fameux langage de balisage du W3C !
Ce cours va principalement aborder l'usage du Javascript dans l'environnement d'un navigateur Web, il est donc de rigueur que
vous sachiez coder la fois en HTML et en CSS. Le PHP peut tre un plus, mais vous n'en aurez rellement besoin que lorsque
nous aborderons la partie AJAX, qui traite des communications entre le Javascript et un serveur.
Voici quelques exemples de ce qui est ralisable grce au Javascript :
9/378
10/378
Introduction au Javascript
Avant d'entrer directement dans le vif du sujet, ce chapitre va vous apprendre ce qu'est le Javascript, ce qu'il permet de faire,
quand il peut ou doit tre utilis et comment il a volu depuis sa cration en 1995.
Nous aborderons aussi plusieurs notions de bases telles que les dfinitions exactes de certains termes.
Dans cette description un peu barbare se trouvent plusieurs lments que nous allons dcortiquer.
Un langage de programmation
Tout d'abord, un langage de programmation est un langage qui permet aux dveloppeurs d'crire du code source qui sera
analys par l'ordinateur.
Un dveloppeur, ou un programmeur, est une personne qui dveloppe des programmes. a peut tre un professionnel (un
ingnieur, un informaticien ou un analyste programmeur) ou bien un amateur.
Le code source est crit par le dveloppeur. C'est un ensemble d'actions, appeles instructions, qui vont permettre de donner
des ordres l'ordinateur afin de faire fonctionner le programme. Le code source est quelque chose de cach, un peu comme un
moteur dans une voiture : le moteur est cach, mais il est bien l, et c'est lui qui fait en sorte que la voiture puisse tre propulse.
Dans le cas d'un programme, c'est pareil, c'est le code source qui rgit le fonctionnement du programme.
En fonction du code source, l'ordinateur excute diffrentes actions, comme ouvrir un menu, dmarrer une application, effectuer
une recherche, enfin bref, tout ce que l'ordinateur est capable de faire. Il existe normment de langages de programmation, la
plupart tant lists sur cette page.
11/378
Les scripts sont majoritairement interprts. Et quand on dit que le Javascript est un langage de scripts, cela signifie qu'il s'agit
d'un langage interprt ! Il est donc ncessaire de possder un interprteur pour faire fonctionner du code Javascript, et un
interprteur, vous en utilisez un frquemment : il est inclus dans votre navigateur Web !
Chaque navigateur possde un interprteur Javascript, qui diffre selon le navigateur. Si vous utilisez Internet Explorer, son
interprteur Javascript s'appelle JScript (l'interprteur de la version 9 s'appelle Chakra), celui de Mozilla Firefox se nomme
SpiderMonkey et celui de Google Chrome est V8.
Le Javascript est un langage dit client-side, c'est--dire que les scripts sont excuts par le navigateur chez l'internaute (le
client). Cela diffre des langages de scripts dits server-side qui sont excuts par le serveur Web. C'est le cas des langages
comme le PHP.
C'est important, car la finalit des scripts client-side et server-side n'est pas la mme. Un script server-side va s'occuper de
crer la page Web qui sera envoye au navigateur. Ce dernier va alors afficher la page puis excuter les scripts client-side tel
que le Javascript. Voici un schma reprenant ce fonctionnement :
12/378
Le navigateur Firefox 4
13/378
Brendan Eich
La graphie de base est JavaScript, avec un S majuscule. Il est cependant courant de lire Javascript, comme ce sera le
cas dans ce tutoriel.
Le Javascript sort en dcembre 1995 et est embarqu dans le navigateur Netscape 2. Le langage est alors un succs, si bien que
Microsoft dveloppe une version semblable, appele JScript, qu'il embarque dans Internet Explorer 3, en 1996.
Netscape dcide d'envoyer sa version de Javascript l'ECMA International (European Computer Manufacturers Association
l'poque, aujourd'hui European association for standardizing information and communication systems ) pour que le langage
soit standardis, c'est--dire pour qu'une rfrence du langage soit cre et que le langage puisse ainsi tre utilis par d'autres
personnes et embarqu dans d'autres logiciels. L'ECMA International standardise le langage sous le nom d'ECMAScript.
Depuis, les versions de l'ECMAScript ont volu. La version la plus connue et mondialement utilise est la version ECMAScript
3, parue en dcembre 1999.
Un logo inconnu
Il n'y a pas de logo officiel pour reprsenter le Javascript. Cependant, le logo suivant est de plus en plus utilis par la
communaut, surtout depuis sa prsentation la JSConf EU de 2011. Vous pourrez le trouver cette adresse sous diffrents
formats, n'hsitez pas en abuser en cas de besoin.
14/378
En rsum
Le Javascript est un langage de programmation interprt, c'est--dire qu'il a besoin d'un interprteur pour pouvoir tre
excut.
Le Javascript est utilis majoritairement au sein des pages Web.
Tout comme le HTML, le Javascript est excut par le navigateur de l'internaute : on parle d'un comportement client-side,
par opposition au server-side lorsque le code est excut par le serveur.
Le Javascript est standardis par l'ECMA International sous le nom d'ECMAScript qui constitue la rfrence du langage.
D'autres langages dcoulent de l'ECMAScript, comme ActionScript, EX4 ou encore JScript.NET.
La dernire version standardise du Javascript est base sur l'ECMAScript 5, sorti en 2009.
15/378
Essayer !
crivez ce code dans un fichier HTML, et ouvrez ce dernier avec votre navigateur habituel. Une bote de dialogue s'ouvre, vous
prsentant le texte Hello World! :
Vous remarquerez que nous vous avons fourni un lien nomm Essayer ! afin que vous puissiez tester le code. Vous
constaterez rapidement que ce ne sera pas toujours le cas car mettre en ligne tous les codes n'est pas forcment
ncessaire surtout quand il s'agit d'afficher une simple phrase.
Bref, nous, les auteurs, avons dcid de vous fournir des liens d'exemples quand le code ncessitera une interaction de
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
16/378
la part de l'utilisateur. Ainsi, les codes avec, par exemple, un simple calcul ne demandant aucune action de la part de
l'utilisateur ne seront pas mis en ligne. En revanche, dfaut de mettre certains codes en ligne, le rsultat de chaque
code sera toujours affich dans les commentaires du code.
Les nouveauts
Dans le code HTML donn prcdemment, on remarque quelques nouveauts.
Tout d'abord, un lment <script> est prsent : c'est lui qui contient le code Javascript que voici :
Code : JavaScript
alert('Hello world!');
Il s'agit d'une instruction, c'est--dire une commande, un ordre, ou plutt une action que l'ordinateur va devoir raliser. Les
langages de programmation sont constitus d'une suite d'instructions qui, mises bout bout, permettent d'obtenir un programme
ou un script complet.
Dans cet exemple, il n'y a qu'une instruction : l'appel de la fonction alert().
La syntaxe du Javascript
Les instructions
La syntaxe du Javascript n'est pas complique. De manire gnrale, les instructions doivent tre spares par un point-virgule
que l'on place la fin de chaque instruction :
Code : JavaScript
instruction_1;
instruction_2;
instruction_3;
En ralit le point-virgule n'est pas obligatoire si l'instruction qui suit se trouve sur la ligne suivante, comme dans notre exemple.
En revanche, si vous crivez plusieurs instructions sur une mme ligne, comme dans l'exemple suivant, le point-virgule est
obligatoire. Si le point-virgule n'est pas mis, l'interprteur ne va pas comprendre qu'il s'agit d'une autre instruction et risque de
retourner une erreur.
Code : JavaScript
Instruction_1;Instruction_2
Instruction_3
Mais attention ! Ne pas mettre les points-virgules est considr comme une mauvaise pratique, c'est quelque chose
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
17/378
que les dveloppeurs Javascript vitent de faire, mme si le langage le permet. Ainsi, dans ce tutoriel, toutes les
instructions seront termines par un point-virgule.
Les espaces
Le Javascript n'est pas sensible aux espaces. Cela veut dire que vous pouvez aligner des instructions comme vous le voulez,
sans que cela ne gne en rien l'excution du script. Par exemple, ceci est correct :
Code : JavaScript
instruction_1;
instruction_1_1;
instruction_1_2;
instruction_2;
instruction_3;
Indentation et prsentation
L'indentation, en informatique, est une faon de structurer du code pour le rendre plus lisible. Les instructions sont hirarchises
en plusieurs niveaux et on utilise des espaces ou des tabulations pour les dcaler vers la droite et ainsi crer une hirarchie. Voici
un exemple de code indent :
Code : JavaScript
function toggle(elemID) {
var elem = document.getElementById(elemID);
if (elem.style.display == 'block') {
elem.style.display = 'none';
} else {
elem.style.display = 'block';
}
Ce code est indent de quatre espaces, c'est--dire que le dcalage est chaque fois un multiple de quatre. Un dcalage de quatre
espaces est courant, tout comme un dcalage de deux. Il est possible d'utiliser des tabulations pour indenter du code. Les
tabulations prsentent l'avantage d'tre affiches diffremment suivant l'diteur utilis, et de cette faon, si vous donnez votre
code quelqu'un, l'indentation qu'il verra dpendra de son diteur et il ne sera pas perturb par une indentation qu'il n'apprcie
pas (par exemple, nous n'aimons pas les indentations de deux, nous prfrons celles de quatre).
Voici le mme code, mais non indent, pour vous montrer que l'indentation est une aide la lecture :
Code : JavaScript
function toggle(elemID) {
var elem = document.getElementById(elemID);
if (elem.style.display == 'block') {
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
18/378
elem.style.display = 'none';
} else {
elem.style.display = 'block';
}
}
La prsentation des codes est importante aussi, un peu comme si vous rdigiez une lettre : a ne se fait pas n'importe comment. Il
n'y a pas de rgles prdfinies comme pour l'criture des lettres, donc il faudra vous arranger pour organiser votre code de faon
claire. Dans le code indent donn prcdemment, vous pouvez voir qu'il y a des espaces un peu partout pour arer le code et
qu'il y a une seule instruction par ligne ( l'exception des if else, mais nous verrons cela plus tard). Certains dveloppeurs
crivent leur code comme a :
Code : JavaScript
function toggle(elemID){
var elem=document.getElementById(elemID);
if(elem.style.display=='block'){
elem.style.display='none';
}else{elem.style.display='block';}
}
Vous conviendrez comme nous que c'est tout de suite moins lisible non ? Gardez l'esprit que votre code doit tre propre, mme
si vous tes le seul y toucher : vous pouvez laisser le code de ct quelques temps et le reprendre par la suite, et l, bonne
chance pour vous y retrouver.
Les commentaires
Les commentaires sont des annotations faites par le dveloppeur pour expliquer le fonctionnement d'un script, d'une instruction
ou mme d'un groupe d'instructions. Les commentaires ne gnent pas l'excution d'un script.
Il existe deux types de commentaires : les commentaires de fin de ligne, et les commentaires multilignes.
Le texte plac dans un commentaire est ignor lors de l'excution du script, ce qui veut dire que vous pouvez mettre ce que bon
vous semble en commentaire, mme une instruction (qui ne sera videmment pas excute) :
Code : JavaScript
instruction_1; // Ceci est ma premire instruction
instruction_2;
// La troisime instruction ci-dessous pose problme, je l'annule
temporairement
// instruction_3;
19/378
Commentaires multilignes
Ce type de commentaires permet les retours la ligne. Un commentaire multiligne commence par /* et se termine par */ :
Code : JavaScript
/* Ce script comporte 3 instructions :
- Instruction 1 qui fait telle chose
- Instruction 2 qui fait autre chose
- Instruction 3 qui termine le script
*/
instruction_1;
instruction_2;
instruction_3; // Fin du script
Remarquez qu'un commentaire multiligne peut aussi tre affich sur une seule ligne :
Code : JavaScript
instruction_1; /* Ceci est ma premire instruction */
instruction_2;
Les fonctions
Dans l'exemple du Hello world!, nous avons utilis la fonction alert(). Nous reviendrons en dtail sur le
fonctionnement des fonctions, mais pour les chapitres suivants, il sera ncessaire de connatre sommairement leur syntaxe.
Une fonction se compose de deux choses : son nom, suivi d'un couple de parenthses (une ouvrante et une fermante) :
Code : JavaScript
myFunction(); // function veut dire fonction en anglais
Entre les parenthses se trouvent les arguments, que l'on appelle aussi paramtres. Ceux-ci contiennent des valeurs qui sont
transmises la fonction. Dans le cas du Hello world!, ce sont les mots Hello world! qui sont passs en paramtre :
Code : JavaScript
alert('Hello world!');
Si vous n'utilisez pas le HTML5, sachez que l'attribut type prend comme valeur text/javascript, qui est en fait le type
MIME d'un code Javascript.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
20/378
Le type MIME est un identifiant qui dcrit un format de donnes. Ici, avec text/javascript, il s'agit de donnes
textuelles et c'est du Javascript.
Le Javascript externe
Il est possible, et mme conseill, d'crire le code Javascript dans un fichier externe, portant l'extension .js. Ce fichier est
ensuite appel depuis la page Web au moyen de l'lment <script> et de son attribut src qui contient l'URL du fichier .js.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
21/378
On suppose ici que le fichier hello.js se trouve dans le mme rpertoire que la page Web.
Il vaut mieux privilgier un fichier externe plutt que d'inclure le code Javascript directement dans la page, pour la
simple et bonne raison que le fichier externe est mis en cache par le navigateur, et n'est donc pas recharg chaque
chargement de page, ce qui acclre laffichage de la page.
22/378
</p>
<script>
// Un peu de code Javascript...
</script>
<script src="hello.js"></script>
</body>
</html>
Il est noter que certains navigateurs modernes chargent automatiquement les fichiers Javascript en dernier, mais ce
n'est pas toujours le cas. C'est pour cela qu'il vaut mieux s'en tenir cette mthode.
Quelques aides
Les documentations
Pendant la lecture de ce cours, il se peut que vous ayez besoin de plus de renseignements sur diverses choses abordes ;
normalement toutes les informations ncessaires sont fournies mais si vous le souhaitez vous pouvez consulter une
documentation, voici celle que nous vous conseillons :
jsFiddle
Ce site est trs utile car il vous permet de tester des codes en passant directement par votre navigateur web, ainsi vous n'avez
pas besoin de crer de fichier sur votre PC pour tester un malheureux code de quelques lignes.
Pour l'utiliser, rien de plus simple : vous copiez le code que vous souhaitez tester puis vous le collez dans la section
Javascript en bas gauche de la page. Une fois que vous avez copi le texte, il ne vous reste plus qu' cliquer sur le bouton
Run en haut gauche et votre code sera excut immdiatement dans la section Result en bas droite. Essayez donc avec ce
code pour voir :
Code : JavaScript
alert('Bien, vous savez maintenant utiliser le site jsFiddle !');
Voil tout pour les liens, n'oubliez pas de vous en servir lorsque vous en avez besoin, ils peuvent vous tre trs utiles !
En rsum
23/378
Questionnaire rcapitulatif
24/378
Les variables
Nous abordons enfin le premier chapitre technique de ce cours ! Tout au long de sa lecture vous allez dcouvrir l'utilisation des
variables, les diffrents types principaux qu'elles peuvent contenir et surtout comment faire vos premiers calculs. Vous serez
aussi initis la concatnation et la conversion des types. Et enfin, un lment important de ce chapitre : vous allez apprendre
l'utilisation d'une nouvelle fonction vous permettant d'interagir avec l'utilisateur !
Le Javascript tant un langage sensible la casse, faites bien attention ne pas vous tromper sur les majuscules et minuscules
utilises car, dans l'exemple suivant, nous avons bel et bien trois variables diffrentes dclares :
Code : JavaScript
var myVariable;
var myvariable;
var MYVARIABLE;
Le mot-cl var est prsent pour indiquer que vous dclarez une variable. Une fois celle-ci dclare, il ne vous est plus
ncessaire d'utiliser ce mot-cl pour cette variable et vous pouvez y stocker ce que vous souhaitez :
Code : JavaScript
var myVariable;
myVariable = 2;
Le signe = sert attribuer une valeur la variable ; ici nous lui avons attribu le nombre 2. Quand on donne une valeur une
variable, on dit que l'on fait une affectation, car on affecte une valeur la variable.
Il est possible de simplifier ce code en une seule ligne :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
25/378
Code : JavaScript
var myVariable = 5.5; // Comme vous pouvez le constater, les nombres
virgule s'crivent avec un point
De mme, vous pouvez dclarer et assigner des variables sur une seule et mme ligne :
Code : JavaScript
var myVariable1, myVariable2 = 4, myVariable3;
Ici, nous avons dclar trois variables en une ligne mais seulement la deuxime s'est vu attribuer une valeur.
Une petite prcision ici s'impose : quand vous utilisez une seule fois l'instruction var pour dclarer plusieurs variables,
vous devez placer une virgule aprs chaque variable (et son ventuelle attribution de valeur) et vous ne devez utiliser
le point-virgule (qui termine une instruction) qu' la fin de la dclaration de toutes les variables.
Et enfin une dernire chose qui pourra vous tre utile de temps en temps :
Code : JavaScript
var myVariable1, myVariable2;
myVariable1 = myVariable2 = 2;
Les deux variables contiennent maintenant le mme nombre : 2 ! Vous pouvez faire la mme chose avec autant de variables que
vous le souhaitez.
26/378
Il est important de prciser que si vous crivez var myVariable = '2'; alors le type de cette variable est une
chane de caractres et non pas un type numrique.
Une autre prcision importante, si vous utilisez les apostrophes pour encadrer votre texte et que vous souhaitez
utiliser des apostrophes dans ce mme texte, il vous faudra alors chapper vos apostrophes de cette faon :
Code : JavaScript
var text = 'a c\'est quelque chose !';
Pourquoi ? Car si vous n'chappez pas votre apostrophe, le Javascript croira que votre texte s'arrte l'apostrophe
contenue dans le mot c'est . noter que ce problme est identique pour les guillemets.
En ce qui nous concerne, nous utilisons gnralement les apostrophes mais quand le texte en contient trop alors les
guillemets peuvent tre bien utiles. C'est vous de voir comment vous souhaitez prsenter vos codes, libre vous de
faire comme vous le souhaitez !
Les boolens (alias boolean) : les boolens sont un type bien particulier que vous n'tudierez rellement qu'au chapitre
suivant. Dans l'immdiat, pour faire simple, un boolen est un type deux tats qui sont les suivants : vrai ou faux. Ces
deux tats s'crivent de la faon suivante :
Code : JavaScript
var isTrue = true;
var isFalse = false;
Voil pour les trois principaux types. Il en existe d'autres, mais nous les tudierons lorsque ce sera ncessaire.
Voil un type de variable trs important ! Si l'instruction typeof vous renvoie undefined, c'est soit que votre variable est
inexistante, soit qu'elle est dclare mais ne contient rien.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
27/378
Signe
addition
soustraction
multiplication
division
modulo
Concernant le dernier oprateur, le modulo est tout simplement le reste d'une division. Par exemple, si vous divisez 5 par 2 alors il
vous reste 1 ; c'est le modulo !
Alors vous savez faire des calculs avec deux nombres c'est bien, mais avec deux variables contenant elles-mmes des nombres
c'est mieux :
Code : JavaScript
var number1 = 3, number2 = 2, result;
result = number1 * number2;
alert(result); // Affiche : 6
On peut aller encore plus loin comme a en crivant des calculs impliquant plusieurs oprateurs ainsi que des variables :
Code : JavaScript
var divisor = 3, result1, result2, result3;
result1 = (16 + 8) / 2 - 2 ; // 10
result2 = result1 / divisor;
result3 = result1 % divisor;
alert(result2); // Rsultat de la division : 3,33
alert(result3); // Reste de la division : 1
Vous remarquerez que nous avons utilis des parenthses pour le calcul de la variable result1. Elles s'utilisent comme en
maths : grce elles le navigateur calcule d'abord 16 + 8 puis divise le rsultat par 2.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
28/378
Ce n'est pas spcialement long ou compliqu faire, mais cela peut devenir trs vite rbarbatif, il existe donc une solution plus
simple pour ajouter un nombre une variable :
Code : JavaScript
var number = 3;
number += 5;
alert(number); // Affiche : 8
Ce code a exactement le mme effet que le prcdent mais est plus rapide crire.
noter que ceci ne s'applique pas uniquement aux additions mais fonctionne avec tous les autres oprateurs arithmtiques :
+=
-=
*=
/=
%=
La concatnation
Une concatnation consiste ajouter une chane de caractres la fin d'une autre, comme dans cet exemple :
Code : JavaScript
var hi = 'Bonjour', name = 'toi', result;
result = hi + name;
alert(result); // Affiche : Bonjourtoi
Cet exemple va afficher la phrase Bonjourtoi . Vous remarquerez qu'il n'y a pas d'espace entre les deux mots, en effet, la
concatnation respecte ce que vous avez crit dans les variables la lettre prs. Si vous voulez un espace, il vous faut en ajouter
un l'une des variables, comme ceci : var hi = 'Bonjour ';
Autre chose, vous souvenez-vous toujours de l'addition suivante ?
Code : JavaScript
var number = 3;
number += 5;
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
29/378
Eh bien vous pouvez faire la mme chose avec les chanes de caractres :
Code : JavaScript
var text = 'Bonjour ';
text += 'toi';
alert(text); // Affiche Bonjour toi .
Essayer !
La fonction prompt() s'utilise comme alert() mais a une petite particularit. Elle renvoie ce que l'utilisateur a crit sous
forme d'une chane de caractres, voil pourquoi on crit de cette manire :
Code : JavaScript
var text = prompt('Tapez quelque chose :');
Ainsi, le texte tap par l'utilisateur se retrouvera directement stock dans la variable text.
Maintenant nous pouvons essayer de dire bonjour nos visiteurs :
Code : JavaScript
var start = 'Bonjour ', name, end = ' !', result;
name
= prompt('Quel est votre prnom ?');
result = start + name + end;
alert(result);
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
30/378
Essayer !
noter que dans notre cas de figure actuel, nous concatnons des chanes de caractres entre elles, mais sachez que vous
pouvez trs bien concatner une chane de caractres et un nombre de la mme manire :
Code : JavaScript
var text = 'Voici un nombre : ', number = 42, result;
result = text + number;
alert(result); // Affiche : Voici un nombre : 42
Essayer !
Si vous avez essay ce code, vous avez srement remarqu qu'il y a un problme. Admettons que vous ayez tap deux fois le
chiffre 1, le rsultat sera 11 Pourquoi ? Eh bien la raison a dj t crite quelques lignes plus haut :
Citation
Elle renvoie ce que l'utilisateur a crit sous forme d'une chane de caractres []
Voil le problme, tout ce qui est crit dans le champ de texte de prompt() est rcupr sous forme d'une chane de caractres,
que ce soit un chiffre ou non. Du coup, si vous utilisez l'oprateur +, vous ne ferez pas une addition mais une concatnation !
C'est l que la conversion des types intervient. Le concept est simple : il suffit de convertir la chane de caractres en nombre.
Pour cela, vous allez avoir besoin de la fonction parseInt() qui s'utilise de cette manire :
Code : JavaScript
var text = '1337', number;
number = parseInt(text);
alert(typeof number); // Affiche : number
alert(number); // Affiche : 1337
Maintenant que vous savez comment vous en servir, on va pouvoir l'adapter notre code :
Code : JavaScript
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
31/378
Essayer !
Maintenant, si vous crivez deux fois le chiffre 1, vous obtiendrez bien 2 comme rsultat.
Qu'avons-nous fait ? Nous avons juste ajout une chane de caractres vide entre les deux nombres, ce qui aura eu pour effet de
les convertir en chanes de caractres.
Il existe une solution un peu moins archaque que de rajouter une chane vide mais vous la dcouvrirez plus tard.
En rsum
Une variable est un moyen pour stocker une valeur.
On utilise le mot cl var pour dclarer une variable, et on utilise = pour affecter une valeur la variable.
Les variables sont types dynamiquement, ce qui veut dire que l'on n'a pas besoin de spcifier le type de contenu que la
variable va contenir.
Grce diffrents oprateurs, on peut faire des oprations entre les variables.
L'oprateur + permet de concatner des chanes de caractres, c'est--dire de les mettre bout bout.
La fonction prompt() permet d'interagir avec l'utilisateur.
Questionnaire rcapitulatif
Dclarer et initialiser une variable
Dclarer deux variables en une fois
32/378
Les conditions
Dans le chapitre prcdent vous avez appris comment crer et modifier des variables. C'est dj bien mais malgr tout on se sent
encore un peu limit dans nos codes. Dans ce chapitre, vous allez donc dcouvrir les conditions de tout type et surtout vous
rendre compte que les possibilits pour votre code seront dj bien plus ouvertes car vos conditions vont influer directement
sur la faon dont va ragir votre code certains critres.
En plus des conditions, vous allez aussi pouvoir approfondir vos connaissances sur un fameux type de variable : le boolen !
Oprateur
Signification
==
gal
!=
diffrent de
===
!==
>
>=
<
<=
suprieur
suprieur ou gal
infrieur
infrieur ou gal
Nous n'allons pas vous faire un exemple pour chacun d'entre eux mais nous allons au moins vous montrer comment les utiliser
afin que vous puissiez essayer les autres :
Code : JavaScript
var number1 = 2, number2 = 2, number3 = 4, result;
result = number1 == number2; // Au lieu d'une seule valeur, on en
crit deux avec l'oprateur de comparaison entre elles
alert(result); // Affiche true , la condition est donc vrifie
car les deux variables contiennent bien la mme valeur
result = number1 == number3;
alert(result); // Affiche false , la condition n'est pas
vrifie car 2 est diffrent de 4
result = number1 < number3;
alert(result); // Affiche true , la condition est vrifie car 2
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
33/378
Comme vous le voyez, le concept n'est pas bien compliqu, il suffit d'crire deux valeurs avec l'oprateur de comparaison
souhait entre les deux et un boolen est retourn. Si celui-ci est true alors la condition est vrifie, si c'est false alors elle ne
l'est pas.
Sur ces huit oprateurs, deux d'entre eux peuvent tre difficiles comprendre pour un dbutant : il s'agit de === et !==. Afin que
vous ne soyez pas perdus, voyons leur fonctionnement avec quelques exemples :
Code : JavaScript
var number = 4, text = '4', result;
result = number == text;
alert(result); // Affiche true alors que number est un
nombre et text une chane de caractres
result = number === text;
alert(result); // Affiche false car cet oprateur compare aussi
les types des variables en plus de leurs valeurs
Vous comprenez leur principe maintenant ? Les conditions normales font des conversions de type pour vrifier les galits,
ce qui fait que si vous voulez diffrencier le nombre 4 d'une chane de caractres contenant le chiffre 4 il vous faudra alors
utiliser le triple gal ===.
Voil tout pour les oprateurs de comparaison, vous avez tous les outils dont vous avez besoin pour faire quelques
exprimentations. Passons maintenant la suite.
Utilisation
&&
ET
||
OU
valeur1 || valeur2
NON
!valeur
L'oprateur ET
Cet oprateur vrifie la condition lorsque toutes les valeurs qui lui sont passes valent true. Si une seule d'entre elles vaut
false alors la condition ne sera pas vrifie. Exemple :
Code : JavaScript
var result = true && true;
alert(result); // Affiche : true
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
34/378
L'oprateur OU
Cet oprateur est plus souple car il renvoie true si une des valeurs qui lui est soumise contient true, qu'importent les
autres valeurs. Exemple :
Code : JavaScript
var result = true || true;
alert(result); // Affiche : true
result = true || false;
alert(result); // Affiche : true
result = false || false;
alert(result); // Affiche : false
L'oprateur NON
Cet oprateur se diffrencie des deux autres car il ne prend qu'une seule valeur la fois. S'il se nomme NON c'est parce que sa
fonction est d'inverser la valeur qui lui est passe, ainsi true deviendra false et inversement. Exemple :
Code : JavaScript
var result = false;
result = !result; // On stocke dans result l'inverse de
result , c'est parfaitement possible
alert(result); // Affiche true car on voulait l'inverse de
false
result = !result;
alert(result); // Affiche false car on a invers de nouveau
result , on est donc pass de true false
35/378
Il est bien entendu possible de raccourcir le code en combinant tout a sur une seule ligne, dornavant toutes les conditions
seront sur une seule ligne dans ce tutoriel :
Code : JavaScript
var result = 2 > 8 && 8 > 2;
alert(result); // Affiche false
Voil tout pour les boolens et les oprateurs conditionnels, nous allons enfin pouvoir commencer utiliser les conditions
comme il se doit.
La condition if else
Enfin nous abordons les conditions ! Ou, plus exactement, les structures conditionnelles, mais nous crirons dornavant le mot
condition qui sera quand mme plus rapide crire et lire.
Avant toute chose, prcisons qu'il existe trois types de conditions, nous allons commencer par la condition if else qui est la
plus utilise.
36/378
Et vu que nos oprateurs conditionnels renvoient des boolens, nous allons donc pouvoir les utiliser directement dans nos
conditions :
Code : JavaScript
if (2 < 8 && 8 >= 4) { // Cette condition renvoie true , le code
est donc excut
alert('La condition est bien vrifie.');
}
if (2 > 8 || 8 <= 4) { // Cette condition renvoie false , le
code n'est donc pas excut
alert("La condition n'est pas vrifie mais vous ne le saurez
pas vu que ce code ne s'excute pas.");
}
Comme vous pouvez le constater, avant nous dcomposions toutes les tapes d'une condition dans plusieurs variables,
dornavant nous vous conseillons de tout mettre sur une seule et mme ligne car ce sera plus rapide crire pour vous et plus
facile lire pour tout le monde.
Essayer !
Comme vous pouvez le constater, le code s'excute lorsque vous cliquez sur le bouton OK et ne s'excute pas lorsque vous
cliquez sur Annuler. En clair : dans le premier cas la fonction renvoie true et dans le deuxime cas elle renvoie false. Ce qui
en fait une fonction trs pratique utiliser avec les conditions.
Aprs ce petit intermde nous pouvons revenir nos conditions.
37/378
structure else :
Code : JavaScript
if (confirm('Pour accder ce site vous devez avoir 18 ans ou plus,
cliquez sur "OK" si c\'est le cas.')) {
alert('Vous allez tre redirig vers le site.');
}
else {
alert("Dsol, vous n'avez pas accs ce site.");
}
Essayer !
Comme vous pouvez le constater, la structure else permet d'excuter un certain code si la condition n'a pas t vrifie, et vous
allez rapidement vous rendre compte qu'elle vous sera trs utile de nombreuses occasions.
Concernant la faon d'indenter vos structures if else, il est conseill de procder de la faon suivante :
Code : JavaScript
if ( /* condition */ ) {
// Du code
} else {
// Du code
}
Ainsi la structure else suit directement l'accolade de fermeture de la structure if, pas de risque de se tromper quant au fait de
savoir quelle structure else appartient quelle structure if . Et puis c'est, selon les gots, un peu plus propre lire. Enfin
vous n'tes pas obligs de faire de cette faon, il s'agit juste d'un conseil.
38/378
} else {
alert("L'tage spcifi n'existe pas.");
}
Essayer !
noter que la structure else if peut tre utilise plusieurs fois de suite, la seule chose qui lui est ncessaire pour pouvoir
fonctionner est d'avoir une condition avec la structure if juste avant elle.
La condition switch
Nous venons d'tudier le fonctionnement de la condition if else qui est trs utile dans de nombreux cas, toutefois elle n'est
pas trs pratique pour faire du cas par cas ; c'est l qu'intervient switch !
Prenons un exemple : nous avons un meuble avec quatre tiroirs contenant chacun des objets diffrents, et il faut que l'utilisateur
puisse connatre le contenu du tiroir dont il entre le chiffre. Si nous voulions le faire avec if else ce serait assez long et
fastidieux :
Code : JavaScript
var drawer = parseInt(prompt('Choisissez le tiroir ouvrir (1 4)
:'));
if (drawer == 1) {
alert('Contient divers outils pour dessiner : du papier, des
crayons, etc.');
} else if (drawer == 2) {
alert('Contient du matriel informatique : des cbles, des
composants, etc.');
} else if (drawer == 3) {
alert('Ah ? Ce tiroir est ferm cl ! Dommage !');
} else if (drawer == 4) {
alert('Contient des vtements : des chemises, des pantalons,
etc.');
} else {
alert("Info du jour : le meuble ne contient que 4 tiroirs et,
jusqu' preuve du contraire, les tiroirs ngatifs n'existent pas.");
}
C'est long, non ? Et en plus ce n'est pas trs adapt ce que l'on souhaite faire. Le plus gros problme est de devoir rcrire
chaque fois la condition ; mais avec switch c'est un peu plus facile :
Code : JavaScript
var drawer = parseInt(prompt('Choisissez le tiroir ouvrir (1 4)
:'));
switch (drawer) {
case 1:
alert('Contient divers outils pour dessiner : du papier, des
crayons, etc.');
break;
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
39/378
case 2:
alert('Contient du matriel informatique : des cbles, des
composants, etc.');
break;
case 3:
alert('Ah ? Ce tiroir est ferm cl ! Dommage !');
break;
case 4:
alert('Contient des vtements : des chemises, des pantalons,
etc.');
break;
default:
alert("Info du jour : le meuble ne contient que 4 tiroirs
et, jusqu' preuve du contraire, les tiroirs ngatifs n'existent
pas.");
}
Essayer !
Comme vous pouvez le constater, le code n'est pas spcialement plus court mais il est dj mieux organis et donc plus
comprhensible. Dtaillons maintenant son fonctionnement :
On crit le mot-cl switch suivi de la variable analyser entre parenthses et d'une paire d'accolades ;
Dans les accolades se trouvent tous les cas de figure pour notre variable, dfinis par le mot-cl case suivi de la valeur
qu'il doit prendre en compte (cela peut tre un nombre mais aussi du texte) et de deux points ;
Tout ce qui suit les deux points d'un case sera excut si la variable analyse par le switch contient la valeur du case
;
chaque fin d'un case on crit l'instruction break pour casser le switch et ainsi viter d'excuter le reste du
code qu'il contient ;
Et enfin on crit le mot-cl default suivi de deux points. Le code qui suit cette instruction sera excut si aucun des
cas prcdents n'a t excut. Attention, cette partie est optionnelle, vous n'tes pas obligs de l'intgrer votre code.
Dans l'ensemble, vous n'aurez pas de mal comprendre le fonctionnement du switch, en revanche l'instruction break vous
posera peut-tre problme, je vous invite donc essayer le code sans cette instruction.
Vous commencez comprendre le problme ? Sans l'instruction break vous excutez tout le code contenu dans le switch
partir du case que vous avez choisi. Ainsi, si vous choisissez le tiroir n2 c'est comme si vous excutiez ce code :
Code : JavaScript
alert('Contient du matriel informatique : des cbles, des
composants, etc.');
alert('Ah ? Ce tiroir est ferm cl ! Dommage !');
alert('Contient des vtements : des chemises, des pantalons, etc.');
alert("Info du jour : le meuble ne contient que 4 tiroirs et,
jusqu' preuve du contraire, les tiroirs ngatifs n'existent pas.");
Dans certains cas, ce systme peut tre pratique mais cela reste extrmement rare.
Avant de clore cette partie, il est ncessaire de vous faire comprendre un point essentiel : un switch permet de faire une action
en fonction d'une valeur mais aussi en fonction du type de la valeur (comme l'oprateur ===), ce qui veut dire que ce code
n'affichera jamais Bravo ! :
Code : JavaScript
var drawer = prompt('Entrez la valeur 1 :');
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
40/378
switch (drawer) {
case 1:
alert('Bravo !');
break;
default:
alert('Perdu !');
En effet, nous avons retir la fonction parseInt() de notre code, ce qui veut dire que nous passons une chane de caractres
notre switch. Puisque ce dernier vrifie aussi les types des valeurs, le message Bravo ! ne sera jamais affich.
En revanche, si nous modifions notre premier case pour vrifier une chane de caractres plutt qu'un nombre alors nous
n'avons aucun problme :
Code : JavaScript
var drawer = prompt('Entrez la valeur 1 :');
switch (drawer) {
case '1':
alert('Bravo !');
break;
default:
alert('Perdu !');
Les ternaires
Et voici enfin le dernier type de condition, les ternaires. Vous allez voir qu'elles sont trs particulires, tout d'abord parce qu'elles
sont trs rapides crire (mais peu lisibles) et surtout parce qu'elles renvoient une valeur.
Pour que vous puissiez bien comprendre dans quel cas de figure vous pouvez utiliser les ternaires, nous allons commencer par
un petit exemple avec la condition if else :
Code : JavaScript
var startMessage = 'Votre catgorie : ',
endMessage,
adult = confirm('tes-vous majeur ?');
if (adult) { // La variable adult contient un boolen, on peut
donc directement la soumettre la structure if sans oprateur
conditionnel
endMessage = '18+';
} else {
endMessage = '-18';
}
alert(startMessage + endMessage);
Essayer !
Comme vous pouvez le constater, le code est plutt long pour un rsultat assez moindre. Avec les ternaires vous pouvez vous
permettre de simplifier votre code de faon substantielle :
Code : JavaScript
var startMessage = 'Votre catgorie : ',
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
41/378
endMessage,
adult = confirm('tes-vous majeur ?');
endMessage = adult ? '18+' : '-18';
alert(startMessage + endMessage);
Alors comment fonctionnent les ternaires ? Pour le comprendre il faut regarder la ligne 5 du code prcdent : endMessage =
adult ? '18+' : '-18';
Si l'on dcompose cette ligne on peut voir :
La variable endMessage qui va accueillir le rsultat de la ternaire ;
La variable adult qui va tre analyse par la ternaire ;
Un point d'interrogation suivi d'une valeur (un nombre, du texte, etc.) ;
Deux points suivis d'une deuxime valeur et enfin le point-virgule marquant la fin de la ligne d'instructions.
Le fonctionnement est simple : si la variable adult vaut true alors la valeur retourne par la ternaire sera celle crite juste
aprs le point d'interrogation, si elle vaut false alors la valeur retourne sera celle aprs les deux points.
Pas trs compliqu n'est-ce pas ? Les ternaires sont des conditions trs simples et rapides crire, mais elles ont la mauvaise
rputation d'tre assez peu lisibles (on ne les remarque pas facilement dans un code de plusieurs lignes). Beaucoup de
personnes en dconseillent l'utilisation, pour notre part nous vous conseillons plutt de vous en servir car elles sont trs utiles.
Si vous purez bien votre code les ternaires seront facilement visibles, ce qu'il vous faut viter ce sont des codes de ce style :
Code : JavaScript
alert('Votre catgorie : ' + (confirm('tes-vous majeur ?') ? '18+'
: '-18'));
Impressionnant n'est-ce pas ? Notre code initial faisait onze lignes et maintenant tout est condens en une seule ligne. Toutefois,
il faut reconnatre que c'est trs peu lisible. Les ternaires sont trs utiles pour raccourcir des codes mais il ne faut pas pousser
leurs capacits leur paroxysme ou bien vous vous retrouverez avec un code que vous ne saurez plus lire vous-mme.
Bref, les ternaires c'est bon, mangez-en ! Mais pas jusqu' l'indigestion !
42/378
Essayer !
Le code nous affiche le texte Fonctionne ! . Pourquoi ? Tout simplement parce que la variable conditionTest a t
convertie en boolen et que son contenu est valu comme tant vrai (true).
Qu'est-ce qu'un contenu vrai ou faux ? Eh bien, il suffit simplement de lister les contenus faux pour le savoir : un nombre qui vaut
zro ou bien une chane de caractres vide. C'est tout, ces deux cas sont les seuls tre valus comme tant false. Bon,
aprs il est possible d'valuer des attributs, des mthodes, des objets, etc. Seulement, vous verrez cela plus tard.
Bien entendu, la valeur undefined est aussi value false.
Le cas de l'oprateur OU
Encore un cas part : l'oprateur OU ! Celui-ci, en plus de sa fonction principale, permet de renvoyer la premire variable
possdant une valeur value true ! Exemple :
Code : JavaScript
var conditionTest1 = '', conditionTest2 = 'Une chane de
caractres';
alert(conditionTest1 || conditionTest2);
Essayer !
Au final, ce code nous retourne la valeur Une chane de caractres . Pourquoi ? Eh bien parce que l'oprateur OU va se
charger de retourner la valeur de la premire variable dont le contenu est valu true. Ceci est extrmement pratique ! Tchez
de bien vous en rappeler car nous allons nous en resservir frquemment !
Prsentation de l'exercice
Qu'est-ce que l'on va essayer de faire ? Quelque chose de tout simple : fournir un commentaire selon l'ge de la personne. Vous
devez fournir un commentaire sur quatre tranches d'ge diffrentes qui sont les suivantes :
Tranche d'ge
Exemple de commentaire
1 17 ans
18 49 ans
50 59 ans
60 120 ans
43/378
Correction
Et voici la correction :
Secret (cliquez pour afficher)
Code : JavaScript
var age = parseInt(prompt('Quel est votre ge ?')); // Ne pas
oublier : il faut "parser" (cela consiste analyser) la valeur
renvoye par prompt() pour avoir un nombre !
if (age <= 0) { // Il faut bien penser au fait que l'utilisateur
peut rentrer un ge ngatif
alert("Oh vraiment ? Vous avez moins d'un an ? C'est pas trs
crdible =p");
} else if (1 <= age && age < 18) {
alert("Vous n'tes pas encore majeur.");
} else if (18 <= age && age < 50) {
alert('Vous tes majeur mais pas encore senior.');
} else if (50 <= age && age < 60) {
alert('Vous tes senior mais pas encore retrait.');
} else if (60 <= age && age <= 120) {
alert('Vous tes retrait, profitez de votre temps libre !');
} else if (age > 120) { // Ne pas oublier les plus de 120 ans,
ils n'existent probablement pas mais on le met dans le doute
alert("Plus de 120 ans ?!! C'est possible a ?!");
} else { // Si prompt() contient autre chose que les intervalles
de nombres ci-dessus alors l'utilisateur a crit n'importe quoi
alert("Vous n'avez pas entr d'ge !");
}
Essayer !
Alors, est-ce que vous aviez bien pens toutes les ventualits ? J'ai un doute pour la condition de la structure else !
En
effet, l'utilisateur peut choisir de ne pas rentrer un nombre mais un mot ou une phrase quelconque, dans ce cas la fonction
parseInt() ne va pas russir trouver de nombre et va donc renvoyer la valeur NaN (value false) qui signifie Not a
Number. Nos diffrentes conditions ne se vrifieront donc pas et la structure else sera finalement excute, avertissant ainsi
l'utilisateur qu'il n'a pas entr de nombre.
Pour ceux qui ont choisi d'utiliser les ternaires ou les switch, nous vous conseillons de relire un peu ce chapitre car ils ne sont
clairement pas adapts ce type d'utilisation.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
44/378
En rsum
Une condition retourne une valeur boolenne : true ou false.
De nombreux oprateurs existent afin de tester des conditions et ils peuvent tre combins entre eux.
La condition if else est la plus utilise et permet de combiner les conditions.
Quand il s'agit de tester une galit entre une multitude de valeurs, la condition switch est prfrable.
Les ternaires sont un moyen concis d'crire des conditions if else et ont l'avantage de retourner une valeur.
Questionnaire rcapitulatif
Ecrire une condition
Ecrire une condition sous forme de ternaire
45/378
Les boucles
Les programmeurs sont rputs pour tre des gens fainants, ce qui n'est pas totalement faux puisque le but de la programmation
est de faire excuter des choses un ordinateur, pour ne pas les faire nous-mmes. Ce chapitre va mettre en lumire ce
comportement intressant : nous allons en effet voir comment rpter des actions, pour ne pas crire plusieurs fois les mmes
instructions. Mais avant a, nous allons aborder le sujet de l'incrmentation.
L'incrmentation
Considrons le calcul suivant :
Code : JavaScript
var number = 0;
number = number + 1;
La variable number contient donc la valeur 1. Seulement l'instruction pour ajouter 1 est assez lourde crire et souvenez-vous,
nous sommes des fainants. Le Javascript, comme d'autres langages de programmation, permet ce que l'on appelle
l'incrmentation, ainsi que son contraire, la dcrmentation.
Le fonctionnement
L'incrmentation permet d'ajouter une unit un nombre au moyen d'une syntaxe courte. l'inverse, la dcrmentation permet de
soustraire une unit.
Code : JavaScript
var number = 0;
number++;
alert(number); // Affiche : 1
number--;
alert(number); // Affiche : 0
Il s'agit donc d'une mthode assez rapide pour ajouter ou soustraire une unit une variable (on dit incrmenter et
dcrmenter), et cela nous sera particulirement utile tout au long de ce chapitre.
46/378
number_1 et number_2 ont tous deux t incrments. Quelle est donc la diffrence entre les deux procds ?
La diffrence rside en fait dans la priorit de l'opration, et a a de l'importance si vous voulez rcuprer le rsultat de
l'incrmentation. Dans l'exemple suivant, ++number retourne la valeur de number incrmente, c'est--dire 1.
Code : JavaScript
var number = 0;
var output = ++number;
alert(number); // Affiche : 1
alert(output); // Affiche : 1
Maintenant, si on place l'oprateur aprs la variable incrmenter, l'opration retourne la valeur de number avant qu'elle ne soit
incrmente :
Code : JavaScript
var number = 0;
var output = number++;
alert(number); // Affiche : 1
alert(output); // Affiche : 0
La boucle while
Une boucle est une structure analogue aux structures conditionnelles vues dans le chapitre prcdent sauf qu'ici il s'agit de
rpter une srie d'instructions. La rptition se fait jusqu' ce qu'on dise la boucle de s'arrter. chaque fois que la boucle se
rpte on parle d'itration (qui est en fait un synonyme de rptition).
Pour faire fonctionner une boucle, il est ncessaire de dfinir une condition. Tant que celle-ci est vraie (true), la boucle se
rpte. Ds que la condition est fausse (false), la boucle s'arrte.
Voici un exemple de la syntaxe d'une boucle while :
Code : JavaScript
while (condition) {
instruction_1;
instruction_2;
instruction_3;
}
47/378
Au dpart, number vaut 1. Arrive ensuite la boucle qui va demander si number est strictement plus petit que 10. Comme c'est
vrai, la boucle est excute, et number est incrment. chaque fois que les instructions prsentes dans la boucle sont
excutes, la condition de la boucle est rvalue pour savoir s'il faut rexcuter la boucle ou non. Dans cet exemple, la boucle se
rpte jusqu' ce que number soit gal 10. Si number vaut 10, la condition number < 10 est fausse, et la boucle s'arrte.
Quand la boucle s'arrte, les instructions qui suivent la boucle (la fonction alert() dans notre exemple) sont excutes
normalement.
Exemple pratique
Imaginons un petit script qui va demander l'internaute son prnom, ainsi que les prnoms de ses frres et surs. Ce n'est pas
compliqu faire direz-vous, puisqu'il s'agit d'afficher une bote de dialogue l'aide de prompt() pour chaque prnom.
Seulement, comment savoir l'avance le nombre de frres et surs ?
Nous allons utiliser une boucle while, qui va demander, chaque passage dans la boucle, un prnom supplmentaire. La
boucle ne s'arrtera que lorsque l'utilisateur choisira de ne plus entrer de prnom.
Code : JavaScript
var nicks = '', nick,
proceed = true;
while (proceed) {
nick = prompt('Entrez un prnom :');
if (nick) {
nicks += nick + ' '; // Ajoute le nouveau prnom ainsi
qu'une espace juste aprs
} else {
proceed = false; // Aucun prnom n'a t entr, donc on
fait en sorte d'invalider la condition
}
}
alert(nicks); // Affiche les prnoms la suite
Essayer !
La variable proceed est ce qu'on appelle une variable tmoin, ou bien une variable de boucle. C'est une variable qui
n'intervient pas directement dans les instructions de la boucle mais qui sert juste pour tester la condition. Nous avons choisi de
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
48/378
Quelques amliorations
Utilisation de break
Dans l'exemple des prnoms, nous utilisons une variable de boucle pour pouvoir arrter la boucle. Cependant, il existe un mot-cl
pour arrter la boucle d'un seul coup. Ce mot-cl est break, et il s'utilise exactement comme dans la structure conditionnelle
switch, vue au chapitre prcdent. Si l'on reprend l'exemple, voici ce que a donne avec un break :
Code : JavaScript
var nicks = '', nick;
while (true) {
nick = prompt('Entrez un prnom :');
if (nick) {
nicks += nick + ' '; // Ajoute le nouveau prnom ainsi
qu'une espace juste aprs
} else {
break; // On quitte la boucle
}
}
alert(nicks); // Affiche les prnoms la suite
Essayer !
Utilisation de continue
Cette instruction est plus rare, car les opportunits de l'utiliser ne sont pas toujours frquentes. continue, un peu comme
break, permet de mettre fin une itration, mais attention, elle ne provoque pas la fin de la boucle : l'itration en cours est
stoppe, et la boucle passe l'itration suivante.
La boucle do while
La boucle do while ressemble trs fortement la boucle while, sauf que dans ce cas la boucle est toujours excute au
moins une fois. Dans le cas d'une boucle while, si la condition n'est pas valide, la boucle n'est pas excute. Avec do while,
la boucle est excute une premire fois, puis la condition est teste pour savoir si la boucle doit continuer.
Voici la syntaxe d'une boucle do while :
Code : JavaScript
do {
instruction_1;
instruction_2;
instruction_3;
} while (condition);
On note donc une diffrence fondamentale dans l'criture par rapport la boucle while, ce qui permet de bien faire la diffrence
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
49/378
entre les deux. Cela dit, l'utilisation des boucles do while n'est pas trs frquente, et il est fort possible que vous n'en ayez
jamais l'utilit car gnralement les programmeurs utilisent une boucle while normale, avec une condition qui fait que celle-ci
est toujours excute une fois.
Attention la syntaxe de la boucle do while : il y a un point-virgule aprs la parenthse fermante du while !
La boucle for
La boucle for ressemble dans son fonctionnement la boucle while, mais son architecture parat complique au premier
abord. La boucle for est en ralit une boucle qui fonctionne assez simplement, mais qui semble trs complexe pour les
dbutants en raison de sa syntaxe. Une fois que cette boucle est matrise, il y a fort parier que c'est celle-ci que vous utiliserez
le plus souvent.
Le schma d'une boucle for est le suivant :
Code : JavaScript
for (initialisation; condition; incrmentation) {
instruction_1;
instruction_2;
instruction_3;
}
Dans les parenthses de la boucle ne se trouve plus juste la condition, mais trois blocs : initialisation, condition, et
incrmentation. Ces trois blocs sont spars par un point-virgule ; c'est un peu comme si les parenthses contenaient trois
instructions distinctes.
Dans le premier bloc, l'initialisation, on initialise une variable appele iter qui vaut 0 ; le mot-cl var est requis, comme pour
toute initialisation. On dfinit dans la condition que la boucle continue tant qu'iter est strictement infrieure 5. Enfin, dans le
bloc d'incrmentation, on indique qu'iter sera incrmente chaque itration termine.
Mais il ne m'affiche que Itration n4 la fin, il n'y a pas d'itration n5 ?
C'est tout fait normal, ce pour deux raisons : le premier tour de boucle porte l'indice 0, donc si on compte de 0 4, il y a bien 5
tours : 0, 1, 2, 3 et 4. Ensuite, l'incrmentation n'a pas lieu avant chaque itration, mais la fin de chaque itration. Donc, le tout
premier tour de boucle est fait avec iter qui vaut 0, avant d'tre incrment.
50/378
Avec les quelques points de thorie que nous venons de voir, nous pouvons rcrire notre exemple des prnoms, tout en
montrant qu'une boucle for peut tre utilise sans le comptage :
Code : JavaScript
for (var nicks = '', nick; true;) {
nick = prompt('Entrez un prnom :');
if (nick) {
nicks += nick + ' ';
} else {
break;
}
alert(nicks);
Essayer !
Dans le bloc d'initialisation (le premier), on commence par initialiser nos deux variables. Vient alors le bloc avec la condition (le
deuxime), qui vaut simplement true. On termine par le bloc d'incrmentation et il n'y en a pas besoin ici, puisqu'il n'y a pas
besoin d'incrmenter. On le fera pour un autre exemple juste aprs. Ce troisime bloc est vide, mais existe. C'est pour cela que l'on
doit quand mme mettre le point-virgule aprs le deuxime bloc (la condition).
Maintenant, modifions la boucle de manire compter combien de prnoms ont t enregistrs. Pour ce faire, nous allons crer
une variable de boucle, nomme i, qui sera incrmente chaque passage de boucle.
Les variables de boucles for sont gnralement nommes i. Si une boucle se trouve dans une autre boucle, la
variable de cette boucle sera nomme j, puis k et ainsi de suite. C'est une sorte de convention implicite, que l'on
retrouve dans la majorit des langages de programmation.
Code : JavaScript
for (var i = 0, nicks = '', nick; true; i++) {
nick = prompt('Entrez un prnom :');
if (nick) {
nicks += nick + ' ';
} else {
break;
}
Essayer !
La variable de boucle a t ajoute dans le bloc d'initialisation. Le bloc d'incrmentation a lui aussi t modifi : on indique qu'il
faut incrmenter la variable de boucle i. Ainsi, chaque passage dans la boucle, i est incrmente, ce qui va nous permettre de
compter assez facilement le nombre de prnoms ajouts.
Les deux caractres \n sont l pour faire des sauts de ligne. Un \n permet de faire un saut de ligne, donc dans le
code prcdent nous faisons deux sauts de ligne.
51/378
performance (vitesse d'excution) et de logique : il n'y a en effet pas besoin de dclarer une mme variable chaque passage
dans la boucle ! Il est conseill de dclarer les variables directement dans le bloc d'initialisation, comme montr dans les
exemples de ce cours. Mais attention : une fois que la boucle est excute, la variable existe toujours, ce qui explique que dans
l'exemple prcdent on puisse rcuprer la valeur de i une fois la boucle termine. Ce comportement est diffrent de celui de
nombreux autres langages, dans lesquels une variable dclare dans une boucle est dtruite une fois la boucle excute.
Priorit d'excution
Les trois blocs qui constituent la boucle for ne sont pas excuts en mme temps :
Initialisation : juste avant que la boucle ne dmarre. C'est comme si les instructions d'initialisation avaient t crites
juste avant la boucle, un peu comme pour une boucle while ;
Condition : avant chaque passage de boucle, exactement comme la condition d'une boucle while ;
Incrmentation : aprs chaque passage de boucle. Cela veut dire que, si vous faites un break dans une boucle for, le
passage dans la boucle lors du break ne sera pas comptabilis.
La boucle for est trs utilise en Javascript, bien plus que la boucle while, contrairement d'autres langages de
programmation. Comme nous le verrons par la suite, le fonctionnement mme du Javascript fait que la boucle for est ncessaire
dans la majorit des cas comme la manipulation des tableaux ainsi que des objets. Ce sera vu plus tard. Nous verrons aussi une
variante de la boucle for, appele for in, mais que nous ne pouvons aborder maintenant car elle ne s'utilise que dans
certains cas spcifiques.
En rsum
L'incrmentation est importante au sein des boucles. Incrmenter ou dcrmenter signifie ajouter ou soustraire une unit
une variable. Le comportement d'un oprateur d'incrmentation est diffrent s'il se place avant ou aprs la variable.
La boucle while permet de rpter une liste d'instructions tant que la condition est vrifie.
La boucle do while est une variante de while qui sera excute au moins une fois, peu importe la condition.
La boucle for est une boucle utilise pour rpter une liste d'instructions un certain nombre de fois. C'est donc une
variante trs cible de la boucle while.
Questionnaire rcapitulatif
Ecrire une boucle while
Reconstituer une boucle for
Ecrire une boucle while qui excute un prompt()
52/378
Les fonctions
Voici un chapitre trs important, tant par sa longueur que par les connaissances qu'il permet d'acqurir ! Vous allez y dcouvrir ce
que sont exactement les fonctions et comment en crer vous-mmes. Tout y passera, vous saurez grer vos variables dans les
fonctions, utiliser des arguments, retourner des valeurs, crer des fonctions dites anonymes , bref, tout ce qu'il vous faut
pour faire des fonctions utiles !
Sur ce, nous allons tout de suite commencer, parce qu'il y a du boulot !
Dcortiquons un peu tout a et analysons un peu ce que nous pouvons lire dans ce code :
Le mot-cl function est prsent chaque dclaration de fonction. C'est lui qui permet de dire Voil, j'cris ici une
fonction ! ;
Vient ensuite le nom de votre fonction, ici myFunction ;
S'ensuit un couple de parenthses contenant ce que l'on appelle des arguments. Ces arguments servent fournir des
informations la fonction lors de son excution. Par exemple, avec la fonction alert() quand vous lui passez en
paramtre ce que vous voulez afficher l'cran ;
Et vient enfin un couple d'accolades contenant le code que votre fonction devra excuter.
Il est important de prciser que tout code crit dans une fonction ne s'excutera que si vous appelez cette dernire ( appeler
une fonction signifie excuter ). Sans a, le code qu'elle contient ne s'excutera jamais.
Bien entendu, tout comme les variables, les noms de fonctions sont limits aux caractres alphanumriques (dont les
chiffres) et aux deux caractres suivants : _ et $.
Bien, maintenant que vous connaissez un peu le principe d'une fonction, voici un petit exemple :
Code : JavaScript
function showMsg() {
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
53/378
Essayer !
Dans ce code nous pouvons voir la dclaration d'une fonction showMsg() qui excute elle-mme une autre fonction qui n'est
autre que alert() avec un message prdfini.
Bien sr, tout code crit dans une fonction ne s'excute pas immdiatement, sinon l'intrt serait nul. C'est pourquoi la fin du
code on appelle la fonction afin de l'excuter, ce qui nous affiche le message souhait.
Un exemple concret
Comme nous le disions plus haut, l'intrt d'une fonction rside notamment dans le fait de ne pas avoir rcrire plusieurs fois le
mme code. Nous allons ici tudier un cas intressant o l'utilisation d'une fonction va se rvler utile :
Code : JavaScript
var result;
result = parseInt(prompt('Donnez le nombre multiplier par 2 :'));
alert(result * 2);
result = parseInt(prompt('Donnez le nombre multiplier par 2 :'));
alert(result * 2);
Comme vous pouvez le constater, nous avons crit ici exactement deux fois le mme code, ce qui nous donne un rsultat peu
efficace. Nous pouvons envisager d'utiliser une boucle mais si nous voulons afficher un texte entre les deux oprations comme
ceci alors la boucle devient inutilisable :
Code : JavaScript
var result;
result = parseInt(prompt('Donnez le nombre multiplier par 2 :'));
alert(result * 2);
alert('Vous en tes la moiti !');
result = parseInt(prompt('Donnez le nombre multiplier par 2 :'));
alert(result * 2);
Notre solution, ici, est donc de faire appel au systme des fonctions de cette faon :
Code : JavaScript
function byTwo() {
var result = parseInt(prompt('Donnez le nombre multiplier par
2 :'));
alert(result * 2);
}
byTwo();
alert('Vous en tes la moiti !');
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
54/378
byTwo();
Essayer !
Concrtement, qu'est-ce qui a chang ? Eh bien, tout d'abord, nous avons cr une fonction qui contient le code excuter deux
fois (ou autant de fois qu'on le souhaite). Ensuite, nous faisons la dclaration de notre variable result directement dans notre
fonction (oui, c'est possible, vous allez obtenir de plus amples explications d'ici peu) et surtout nous appelons deux fois notre
fonction plutt que de rcrire le code qu'elle contient.
Voil l'utilit basique des fonctions : viter la rptition d'un code. Mais leur utilisation peut tre largement plus pousse,
continuons donc sur notre lance !
Essayer !
Ici, pas de problme, on dclare une variable dans laquelle on stocke du texte puis on cre une fonction qui se charge de
l'afficher l'cran et enfin on excute cette dernire. Maintenant, nous allons lgrement modifier l'ordre des instructions mais
l'effet devrait normalement rester le mme :
Code : JavaScript
function sayHello() {
var ohai = 'Hello world !';
}
sayHello();
alert(ohai);
Essayer !
Alors ? Aucun rsultat ? Ce n'est pas surprenant ! Il s'est produit ce que l'on appelle une erreur : en clair, le code s'est arrt car il
n'est pas capable d'excuter ce que vous lui avez demand. L'erreur en question (nous allons revenir sur l'affichage de cette
erreur dans un instant) nous indique que la variable ohai n'existe pas au moment de son affichage avec la fonction alert()
alors que nous avons pourtant bien dclar cette variable dans la fonction sayHello().
Et si je dclare la variable ohai en-dehors de la fonction ?
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
55/378
L, a fonctionnera ! Voil tout le concept de la porte des variables : toute variable dclare dans une fonction n'est utilisable
que dans cette mme fonction ! Ces variables spcifiques une seule fonction ont un nom : les variables locales.
Comme je vous le disais, une erreur s'est dclenche, mais comment avons-nous pu le savoir ? Nous avons en fait
utilis ce qui s'appelle un dbogueur ! Un chapitre est consacr cela dans la partie annexe du cours. Il est vivement
conseill de le lire.
Essayer !
Comme vous pouvez le constater, quand on excute la fonction, la variable locale prend le dessus sur la variable globale de mme
nom pendant tout le temps de l'excution de la fonction. Mais une fois la fonction termine (et donc, la variable locale dtruite)
c'est la variable globale qui reprend ses droits.
Il existe une solution pour utiliser la variable globale dans une fonction malgr la cration d'une variable locale de mme nom,
mais nous tudierons cela bien plus tard car ce n'est actuellement pas de votre niveau.
noter que, dans l'ensemble, il est plutt dconseill de crer des variables globales et locales de mme nom, cela est souvent
source de confusion.
56/378
Dans ce code, vous pouvez voir que les variables var1 et var2 ne sont utilises que pour la fonction calculate() et pour
rien d'autre, or ce sont ici des variables globales. Par principe, cette faon de faire est stupide : vu que ces variables ne servent
qu' la fonction calculate(), autant les dclarer dans la fonction de la manire suivante :
Code : JavaScript
function calculate() {
var var1 = 2, var2 = 3;
alert(var1 * var2);
}
calculate();
Ainsi, ces variables n'iront pas interfrer avec d'autres fonctions qui peuvent utiliser des variables de mme nom. Et surtout, cela
reste quand mme plus logique !
Juste un petit avertissement : beaucoup de personnes rlent sous prtexte que certains codes contiennent des
variables globales. Les variables globales ne sont pas un mal, elles peuvent tre utiles dans certains cas, il suffit juste
de savoir s'en servir bon escient. Et pour que vous arriviez vous en servir correctement, il vous faut pratiquer.
Bien, vous avez termin la partie concernant la porte des variables. Faites bien attention ! Cela peut vous paratre simple au
premier abord mais il est facile de se faire piger, je vous conseille de faire tous les tests qui vous passent par la tte afin de bien
explorer toutes les possibilits et les ventuels piges.
Les arguments
Crer et utiliser un argument
Comme nous venons de le dire, les arguments sont des informations envoyes une fonction. Ces informations peuvent servir
beaucoup de choses, libre vous de les utiliser comme vous le souhaitez. D'ailleurs, il vous est dj arriv d'envoyer des
arguments certaines fonctions, par exemple avec la fonction alert() :
Code : JavaScript
// Voici la fonction alert sans argument, elle n'affiche rien :
alert();
// Et avec un argument, elle affiche ce que vous lui envoyez :
alert('Mon message afficher');
Selon les fonctions, vous n'aurez parfois pas besoin de spcifier d'arguments, parfois il vous faudra en spcifier un, voire
plusieurs. Il existe aussi des arguments facultatifs que vous n'tes pas obligs de spcifier.
Pour crer une fonction avec un argument, il vous suffit d'crire de la faon suivante :
Code : JavaScript
function myFunction (arg) { // Vous pouvez mettre une espace entre
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
57/378
Ainsi, si vous passez un argument cette mme fonction, vous retrouverez dans la variable arg ce qui a t pass en paramtre.
Exemple :
Code : JavaScript
function myFunction(arg) { // Notre argument est la variable arg
Essayer !
Encore mieux ! Puisqu'un argument n'est qu'une simple variable, vous pouvez trs bien lui passer ce que vous souhaitez, tel que
le texte crit par un utilisateur :
Code : JavaScript
function myFunction(arg) {
alert('Votre argument : ' + arg);
}
myFunction(prompt('Que souhaitez-vous passer en argument la
fonction ?'));
Essayer !
Certains d'entre vous seront peut-tre tonns de voir la fonction prompt() s'excuter avant la fonction myFunction().
Ceci est parfaitement normal, faisons un rcapitulatif de l'ordre d'excution de ce code :
La fonction myFunction() est dclare, son code est donc enregistr en mmoire mais ne s'excute pas tant qu'on ne
l'appelle pas ;
la dernire ligne, nous faisons appel myFunction() mais en lui passant un argument, la fonction va donc attendre
de recevoir tous les arguments avant de s'excuter ;
La fonction prompt() s'excute puis renvoie la valeur entre par l'utilisateur, ce n'est qu'une fois cette valeur renvoye
que la fonction myFunction() va pouvoir s'excuter car tous les arguments auront enfin t reus ;
Enfin, myFunction() s'excute !
Vous l'aurez peut-tre constat mais il nous arrive de dire que nous passons des valeurs en paramtres d'une fonction.
Cela veut dire que ces valeurs deviennent les arguments d'une fonction, tout simplement. Ces deux manires de
dsigner les choses sont couramment utilises, mieux vaut donc savoir ce qu'elles signifient.
58/378
de la dclaration de la fonction. Voici, en gros, ce qui se passe quand un argument est reu dans la fonction :
Code : JavaScript
function scope(arg) {
// Au dbut de la fonction, la variable arg est cre avec
le contenu de l'argument qui a t pass la fonction
alert(arg); // Nous pouvons maintenant utiliser l'argument comme
souhait : l'afficher, le modifier, etc.
// Une fois l'excution de la fonction termine, toutes les
variables contenant les arguments sont dtruites
}
Ce fonctionnement est exactement le mme que lorsque vous crez vous-mmes une variable dans la fonction : elle ne sera
accessible que dans cette fonction et nulle part ailleurs. Les arguments sont propres leur fonction, ils ne serviront aucune
autre fonction.
Comme vous pouvez le constater, les diffrents arguments sont spars par une virgule, comme lorsque vous voulez dclarer
plusieurs variables avec un seul mot-cl var ! Maintenant, pour excuter notre fonction, il ne nous reste plus qu' passer les
arguments souhaits notre fonction, de cette manire :
Code : JavaScript
moar('Un !', 'Deux !');
Bien sr, nous pouvons toujours faire interagir l'utilisateur sans problme :
Code : JavaScript
moar(prompt('Entrez votre premier argument :'), prompt('Entrez votre
deuxime argument :'));
59/378
moar(
prompt('Entrez votre premier argument :'),
prompt('Entrez votre deuxime argument :')
);
Essayer !
undefined, voil ce que l'on obtient, et c'est parfaitement normal ! La variable arg a t dclare par la fonction mais pas
initialise car vous ne lui avez pas pass d'argument. Le contenu de cette variable est donc indfini.
Mais, dans le fond, quoi peut bien servir un argument facultatif ?
Prenons un exemple concret : imaginez que l'on dcide de crer une fonction qui affiche l'cran une fentre demandant d'inscrire
quelque chose (comme la fonction prompt()). La fonction possde deux arguments : le premier doit contenir le texte afficher
dans la fentre, et le deuxime (qui est un boolen) autorise ou non l'utilisateur quitter la fentre sans entrer de texte. Voici la
base de la fonction :
Code : JavaScript
function prompt2(text, allowCancel) {
// Le code que l'on ne crera pas :p
}
L'argument text est videmment obligatoire vu qu'il existe une multitude de possibilits. En revanche, l'argument
allowCancel est un boolen, il n'y a donc que deux possibilits :
true, l'utilisateur peut fermer la fentre sans entrer de texte ;
false, l'utilisateur est oblig d'crire quelque chose avant de pouvoir fermer la fentre.
Comme la plupart des dveloppeurs souhaitent gnralement que l'utilisateur entre une valeur, on peut considrer que la valeur
la plus utilise sera false.
Et c'est l que l'argument facultatif entre en scne ! Un argument facultatif est videmment facultatif (eh oui !
) mais doit
gnralement possder une valeur par dfaut dans le cas o l'argument n'a pas t rempli, dans notre cas ce sera false. Ainsi,
on peut donc amliorer notre fonction de la faon suivante :
Code : JavaScript
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
60/378
De cette faon, si l'argument n'a pas t spcifi pour la variable allowCancel (comme dans cet exemple) on attribue alors la
valeur false cette dernire. Bien sr, les arguments facultatifs ne possdent pas obligatoirement une valeur par dfaut, mais
au moins vous saurez comment faire si vous en avez besoin.
Petit pige viter : inversons le positionnement des arguments de notre fonction. Le second argument passe en premier et viceversa. On se retrouve ainsi avec l'argument facultatif en premier et celui obligatoire en second, la premire ligne de notre code est
donc modifie de cette faon :
Code : JavaScript
function prompt2(allowCancel, text) {
Imaginons maintenant que l'utilisateur de votre fonction ne souhaite remplir que l'argument obligatoire, il va donc crire ceci :
Code : JavaScript
prompt2('Le texte');
Oui, mais le problme c'est qu'au final son texte va se retrouver dans la variable allowCancel au lieu de la variable text !
Alors quelle solution existe-t-il donc pour rsoudre ce problme ? Aucune ! Vous devez imprativement mettre les arguments
facultatifs de votre fonction en dernire position, vous n'avez pas le choix.
Pour faire retourner une valeur notre fonction, rien de plus simple, il suffit d'utiliser l'instruction return suivie de la valeur
retourner. Exemple :
Code : JavaScript
61/378
function sayHello() {
return 'Bonjour !'; // L'instruction return suivie d'une
valeur, cette dernire est donc renvoye par la fonction
}
alert(sayHello()); // Ici on affiche la valeur retourne par la
fonction sayHello()
Maintenant essayons d'ajouter une ligne de code aprs la ligne contenant notre return :
Code : JavaScript
function sayHello() {
return 'Bonjour !';
alert('Attention ! Le texte arrive !');
}
alert(sayHello());
Essayer !
Comme vous pouvez le constater, notre premier alert() ne s'est pas affich ! Cela s'explique par la prsence du return :
cette instruction met fin la fonction, puis retourne la valeur. Pour ceux qui n'ont pas compris, la fin d'une fonction est tout
simplement l'arrt de la fonction un point donn (dans notre cas, la ligne du return) avec, ventuellement, le renvoi d'une
valeur.
Ce fonctionnement explique d'ailleurs pourquoi on ne peut pas faire plusieurs renvois de valeurs pour une mme fonction : si on
crit deux return la suite, seul le premier sera excut puisque le premier return aura dj mis un terme l'excution de la
fonction.
Voil tout pour les valeurs de retour. Leur utilisation est bien plus simple que pour les arguments mais reste vaste quand mme, je
vous conseille de vous entraner vous en servir car elles sont trs utiles !
C'est bien joli, mais du coup comment fait-on pour excuter cette fonction si elle ne possde pas de nom ?
62/378
Eh bien il existe de trs nombreuses faons de faire ! Cependant, dans l'tat actuel de vos connaissances, nous devons nous
limiter une seule solution : assigner notre fonction une variable. Nous verrons les autres solutions au fil des chapitres
suivants (nous vous avions bien dit que vous ne sauriez pas encore exploiter tout le potentiel de ces fonctions).
Pour assigner une fonction anonyme une variable, rien de plus simple :
Code : JavaScript
var sayHello = function() {
alert('Bonjour !');
};
Ainsi, il ne nous reste plus qu' appeler notre fonction par le biais du nom de la variable laquelle nous l'avons affecte :
Code : JavaScript
sayHello(); // Affiche : Bonjour !
il s'agit d'une structure seule, pas besoin de point-virgule. Tandis que si j'cris :
Code : JavaScript
var instruction = 1234;
il s'agit d'une instruction permettant d'assigner une valeur une variable, le point-virgule est ncessaire. Maintenant, si j'cris de
cette manire :
Code : JavaScript
var instruction = function() {
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
63/378
// Du code
il s'agit alors d'une instruction assignant une structure une variable, le point virgule est donc toujours ncessaire car, malgr la
prsence d'une structure, l'action globale reste bien une instruction.
Hou l, une syntaxe bizarre ! Il est vrai que ce code peut drouter un petit peu au premier abord, nous allons donc vous expliquer
a pas pas.
Tout d'abord, nous distinguons une fonction anonyme :
Code : JavaScript
function() {
// Code isol
}
Viennent ensuite deux paires de parenthses, une premire paire encadrant la fonction et une deuxime paire suivant la premire :
Code : JavaScript
(function() {
// Code isol
})()
Pourquoi ces parenthses ? Eh bien pour une raison simple : une fonction, lorsqu'elle est dclare, n'excute pas immdiatement
le code qu'elle contient, elle attend d'tre appele. Or, nous, nous souhaitons excuter ce code immdiatement ! La solution est
donc d'utiliser ce couple de parenthses.
Pour expliquer simplement, prenons l'exemple d'une fonction nomme :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
64/378
Code : JavaScript
function test() {
// Du code
}
test();
Comme vous pouvez le constater, pour excuter la fonction test() immdiatement aprs sa dclaration, nous avons d
l'appeler par la suite, mais il est possible de supprimer cette tape en utilisant le mme couple de parenthses que pour les
fonctions anonymes :
Code : JavaScript
(function test() {
// Code.
})();
Le premier couple de parenthses permet de dire je dsigne cette fonction pour que l'on puisse ensuite indiquer, avec le
deuxime couple de parenthses, que l'on souhaite l'excuter. Le code volue donc de cette manire :
Code : JavaScript
// Ce code :
(function test() {
})();
// Devient :
(test)();
// Qui devient :
test();
Alors, pour une fonction nomme, la solution sans ces deux couples de parenthses est plus propre, mais pour une fonction
anonyme il n'y a pas le choix : on ne peut plus appeler une fonction anonyme une fois dclare (sauf si elle a t assigne une
variable), c'est pourquoi on doit utiliser ces parenthses.
titre d'information, sachez que ces fonctions immdiatement excutes se nomment des Immediately Executed
Functions, abrges IEF. Nous utiliserons cette abrviation dornavant.
Une fois les parenthses ajoutes, la fonction (qui est une structure) est excute, ce qui fait que l'on obtient une instruction, il
faut donc ajouter un point-virgule :
Code : JavaScript
(function() {
// Code isol
})();
65/378
Notre fonction anonyme fonctionne exactement comme une fonction classique, sauf qu'elle ne possde pas de nom et qu'elle est
excute immdiatement, ce sont les deux seules diffrences. Ainsi donc, la rgle de la porte des variables s'applique aussi
cette fonction anonyme.
Bref, l'intrt de cet isolement de code concerne la porte des variables : vous pouvez crer autant de variables que vous le
souhaitez dans cette fonction avec les noms que vous souhaitez, tout sera dtruit une fois que votre fonction aura fini de
s'excuter. Exemple (lisez bien les commentaires) :
Code : JavaScript
var test = 'noir'; // On cre une variable test contenant le
mot noir
(function() { // Dbut de la zone isole
var test = 'blanc'; // On cre une variable du mme nom avec le
contenu blanc dans la zone isole
alert('Dans la zone isole, la couleur est : ' + test);
})(); // Fin de la zone isole. Les variables cres dans cette
zone sont dtruites.
alert('Dans la zone non-isole, la couleur est : ' + test); // Le
texte final contient bien le mot noir vu que la zone isole
n'a aucune influence sur le reste du code
Essayer !
Allez, une dernire chose avant de finir ce chapitre !
Les zones isoles sont pratiques (vous dcouvrirez bien vite pourquoi) mais parfois on aimerait bien enregistrer dans le code
global une des valeurs gnres dans une zone isole. Pour cela il vous suffit de procder de la mme faon qu'avec une
fonction classique, c'est--dire comme ceci :
Code : JavaScript
var sayHello = (function() {
return 'Yop !';
})();
alert(sayHello); // Affiche : Yop !
Et voil tout ! Le chapitre des fonctions est enfin termin ! Il est trs important, je vous conseille de le relire un autre jour si vous
n'avez pas encore tout compris. Et pensez bien vous exercer entre temps !
En rsum
Il existe des fonctions natives, mais il est aussi possible d'en crer, avec le mot-cl function.
Les variables dclares avec var au sein d'une fonction ne sont accessibles que dans cette fonction.
Il faut viter le plus possible d'avoir recours aux variables globales.
Une fonction peut recevoir un nombre dfini ou indfini de paramtres. Elle peut aussi retourner une valeur ou ne rien
retourner du tout.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
66/378
Des fonctions qui ne portent pas de nom sont des fonctions anonymes et servent isoler une partie du code.
Questionnaire rcapitulatif
Dfinir une fonction
crire une fonction pour comparer deux nombres
Ecrire une fonction qui demande un nombre
67/378
Si, mais en ralit, une variable contient surtout un objet. Par exemple, si nous crons une chane de caractres, comme ceci :
Code : JavaScript
var myString = 'Ceci est une chane de caractres';
la variable myString contient un objet, et cet objet reprsente une chane de caractres. C'est la raison pour laquelle on dit que
le Javascript n'est pas un langage typ, car les variables contiennent toujours la mme chose : un objet. Mais cet objet peut tre
de nature diffrente (un nombre, un boolen).
Outre les objets natifs, le Javascript nous permet de fabriquer nos propres objets. Ceci fera toutefois partie d'un chapitre part,
car la cration d'objets est plus complique que l'utilisation des objets natifs.
Toutefois, attention, le Javascript n'est pas un langage orient objet du mme style que le C++, le C# ou le Java. Le
Javascript est un langage orient objet par prototype. Si vous avez dj des notions de programmation oriente objet,
vous verrez quelques diffrences, mais les principales viendront par la suite, lors de la cration d'objets.
Le constructeur
Le constructeur est un code qui est excut quand on utilise un nouvel objet. Il permet deffectuer des actions comme dfinir
diverses variables au sein mme de l'objet (comme le nombre de caractres d'une chane de caractres). Tout cela est fait
automatiquement pour les objets natifs, nous en reparlerons quand nous aborderons l'orient objet.
Les proprits
Toute valeur va tre place dans une variable au sein de l'objet : c'est ce que l'on appelle une proprit. Une proprit est une
variable contenue dans l'objet, elle contient des informations ncessaires au fonctionnement de l'objet.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
68/378
Les mthodes
Enfin, il est possible de modifier l'objet. Cela se fait par l'intermdiaire des mthodes. Les mthodes sont des fonctions contenues
dans l'objet, et qui permettent de raliser des oprations sur le contenu de l'objet. Par exemple, dans le cas d'une chane de
caractres, il existe une mthode qui permet de mettre la chane de caractres en majuscules.
Exemple d'utilisation
Nous allons crer une chane de caractres, pour ensuite afficher son nombre de caractres et la transformer en majuscules. Soit
la mise en pratique de la partie thorique que nous venons de voir.
Code : JavaScript
var myString = 'Ceci est une chane de caractres'; // On cre un
objet String
alert(myString.length); // On affiche le nombre de caractres, au
moyen de la proprit length
alert(myString.toUpperCase()); // On rcupre la chane en
majuscules, avec la mthode toUpperCase()
Essayer !
On remarque quelque chose de nouveau dans ce code : la prsence d'un point. Ce dernier permet d'accder aux proprits et aux
mthodes d'un objet. Ainsi, quand nous crivons myString.length, nous demandons au Javascript de fournir le nombre de
caractres contenus dans myString. La proprit length contient ce nombre, qui a t dfini quand nous avons cr l'objet.
Ce nombre est galement mis jour quand on modifie la chane de caractres :
Code : JavaScript
var myString = 'Test';
alert(myString.length); // Affiche : 4
myString = 'Test 2';
alert(myString.length); // Affiche : 6 (l'espace est aussi un
caractre)
Essayer !
C'est pareil pour les mthodes : avec myString.toUpperCase(), je demande au Javascript de changer la casse de la
chane, ici, tout mettre en majuscules. l'inverse, la mthode toLowerCase() permet de tout mettre en minuscules.
69/378
Les tableaux
Souvenez-vous : dans le chapitre sur les boucles, il tait question de demander l'utilisateur les prnoms de ses frres et surs.
Les prnoms taient concatns dans une chane de caractres, puis affichs. cause de cette mthode de stockage, part
rafficher les prnoms tels quels, on ne sait pas faire grand-chose.
C'est dans un tel cas que les tableaux entrent en jeu. Un tableau, ou plutt un array en anglais, est une variable qui contient
plusieurs valeurs, appeles items. Chaque item est accessible au moyen d'un indice (index en anglais) et dont la numrotation
commence partir de 0. Voici un schma reprsentant un tableau, qui stocke cinq items :
Indice
Les indices
Comme vous le voyez dans le tableau, la numrotation des items commence 0 ! C'est trs important, car il y aura toujours un
dcalage d'une unit : l'item numro 1 porte l'indice 0, et donc le cinquime item porte l'indice 4. Vous devrez donc faire trs
attention ne pas vous emmler les pinceaux, et toujours garder cela en tte, sinon a vous posera problme.
Dclarer un tableau
On utilise bien videmment var pour dclarer un tableau, mais la syntaxe pour dfinir les valeurs est spcifique :
Code : JavaScript
var myArray = ['Sbastien', 'Laurence', 'Ludovic', 'Pauline',
'Guillaume'];
Le contenu du tableau se dfinit entre crochets, et chaque valeur est spare par une virgule. Les valeurs sont introduites
comme pour des variables simples, c'est--dire qu'il faut des guillemets ou des apostrophes pour dfinir les chanes de caractres
:
Code : JavaScript
var myArray_a = [42, 12, 6, 3];
var myArray_b = [42, 'Sbastien', 12, 'Laurence'];
70/378
Le mot-cl new de cette syntaxe demande au Javascript de dfinir un nouvel array dont le contenu se trouve en paramtre (un
peu comme une fonction). Vous verrez l'utilisation de ce mot-cl plus tard. En attendant il faut que vous sachiez que cette syntaxe
est dprcie et qu'il est conseill d'utiliser celle avec les crochets.
Essayer !
Comme dit dans la partie thorique sur les objets, les mthodes sont des fonctions, et peuvent donc recevoir des paramtres. Ici,
push() peut recevoir un nombre illimit de paramtres, et chaque paramtre reprsente un item ajouter la fin du tableau.
La mthode unshift() fonctionne comme push(), except que les items sont ajouts au dbut du tableau. Cette mthode
n'est pas trs frquente mais peut tre utile.
Les mthodes shift() et pop() retirent respectivement le premier et le dernier lment du tableau.
Code : JavaScript
71/378
Essayer !
La mthode split() va couper la chane de caractres chaque fois qu'elle va rencontrer une espace. Les portions ainsi
dcoupes sont places dans un tableau, ici cousinsArray.
Remarquez que quand vous affichez un array via alert() les lments sont spars par des virgules et il n'y a pas
d'apostrophes ou de guillemets. C'est d alert() qui, pour afficher un objet (un tableau, un boolen, un
nombre), le transforme en une chane de caractres grce une mthode nomme toString().
L'inverse de split(), c'est--dire crer une chane de caractres depuis un tableau, se nomme join() :
Code : JavaScript
var cousinsString_2 = cousinsArray.join('-');
alert(cousinsString_2);
Parcourir un tableau
Soyez attentifs, il s'agit ici d'un gros morceau ! Parcourir un tableau est quelque chose que vous allez faire trs frquemment en
Javascript, surtout plus tard, quand nous verrons comment interagir avec les lments HTML.
Parcourir un tableau signifie passer en revue chaque item du tableau pour, par exemple, afficher les items un un,
leur faire subir des modifications ou excuter des actions en fonction de leur contenu.
72/378
Dans le chapitre sur les boucles nous avons tudi la boucle for. Celle-ci va nous servir parcourir les tableaux. La boucle
while peut aussi tre utilise, mais for est la plus adapte pour cela. Nous allons voir aussi une variante de for : la boucle
for in.
Le principe pour parcourir un tableau est simple : il faut faire autant d'itrations qu'il y a d'items. Le nombre d'items d'un tableau
se rcupre avec la proprit length, exactement comme pour le nombre de caractres d'une chane de caractres. chaque
itration, on va avancer d'un item dans le tableau, en utilisant la variable de boucle i : chaque itration, elle s'incrmente, ce qui
permet d'avancer dans le tableau item par item. Voici un exemple :
Code : JavaScript
for (var i = 0; i < myArray.length; i++) {
alert(myArray[i]);
}
Attention la condition
Nous avons volontairement mal rdig le code prcdent. En effet, dans le chapitre sur les boucles, nous avons dit que le
deuxime bloc d'une boucle for, le bloc de condition, tait excut chaque itration. Ici a veut donc dire que
myArray.length est utilis chaque itration, ce qui, part ralentir la boucle, n'a que peu d'intrt puisque le nombre d'items
du tableau ne change normalement pas (dans le cas contraire, n'utilisez pas la solution qui suit).
L'astuce est de dfinir une seconde variable, dans le bloc d'initialisation, qui contiendra la valeur de length. On utilisera cette
variable pour la condition :
Code : JavaScript
for (var i = 0, c = myArray.length; i < c; i++) {
alert(myArray[i]);
}
73/378
Nous utilisons c comme nom de variable, qui signifie count (compter), mais vous pouvez utiliser ce que vous voulez.
Cette dclaration va crer un objet analogue un tableau, except le fait que chaque item sera accessible au moyen d'un
identifiant, ce qui donne schmatiquement ceci :
Identifiant self
Donne
sister
brother
cousin_1 cousin_2
Guillaume
Pour les objets c'est peu prs similaire sauf que l'on met des accolades la place des crochets :
Code : JavaScript
var myObject = {};
74/378
Comme l'indique ce code, il suffit de taper l'identifiant souhait suivi de deux points et de la valeur lui attribuer. La sparation
des items se fait comme pour un tableau, avec une virgule.
Il existe une autre manire, semblable celle qui permet d'accder aux items d'un tableau en connaissant l'indice, sauf qu'ici on va
simplement spcifier le nom de la proprit :
Code : JavaScript
family['sister'];
Cela va nous tre particulirement utile si l'identifiant est contenu dans une variable, comme ce sera le cas avec la boucle que
nous allons voir aprs. Exemple :
Code : JavaScript
var id = 'sister';
alert(family[id]); // Affiche : Laurence
Cette faon de faire convient galement aux proprits de tout objet. Ainsi, si mon tableau se nomme myArray, je peux
faire myArray['length'] pour rcuprer le nombre d'items.
75/378
Parce que les tableaux se voient souvent attribuer des mthodes supplmentaires par certains navigateurs ou certains scripts
tiers utiliss dans la page, ce qui fait que la boucle for in va vous les numrer en mme temps que les items du tableau.
Il y a aussi un autre facteur important prendre en compte : la boucle for in est plus gourmande qu'une boucle for
classique. Vous trouverez plus d'informations ce propos sur cet article provenant du site de dveloppement d'Opera. Gardez cet
article de ct, il ne pourra que vous resservir durant votre apprentissage.
return { x: 12, y: 21 };
La valeur de retour de la fonction getCoords() est mise dans la variable coords, et l'accs x et y en est simplifi.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
76/378
Exercice rcapitulatif
Le chapitre suivant contient un TP, c'est--dire un travail pratique. Cela dit, avant de le commencer, nous vous proposons un
petit exercice qui reprend de manire simple ce que nous avons vu dans ce chapitre.
nonc
Dans le chapitre sur les boucles, nous avions utilis un script pour demander l'utilisateur les prnoms de ses frres et surs.
Les prnoms taient alors stocks dans une chane de caractres. Pour rappel, voici ce code :
Code : JavaScript - Rappel
var nicks = '', nick;
while (true) {
nick = prompt('Entrez un prnom :');
if (nick) {
nicks += nick + ' '; // Ajoute le nouveau prnom ainsi qu'une espace juste apr
} else {
break; // On quitte la boucle
}
Ce que nous vous demandons ici, c'est de stocker les prnoms dans un tableau. Pensez la mthode push(). la fin, il faudra
afficher le contenu du tableau, avec alert(), seulement si le tableau contient des prnoms ; en effet, a ne sert rien de
l'afficher s'il ne contient rien. Pour l'affichage, sparez chaque prnom par une espace. Si le tableau ne contient rien, faites-le
savoir lutilisateur, toujours avec alert().
Correction
Secret (cliquez pour afficher)
Code : JavaScript
var nicks = [], // Cration du tableau vide
nick;
while (nick = prompt('Entrez un prnom :')) { // Si la valeur assigne la variable
nick est valide (diffrente de null ) alors la boucle s'excute
nicks.push(nick); // Ajoute le nouveau prnom au tableau
}
if (nicks.length > 0) { // On regarde le nombre d'items
alert(nicks.join(' ')); // Affiche les prnoms la suite
} else {
alert('Il n\'y a aucun prnom en mmoire !');
}
Essayer !
Nous avons donc repris le code donn dans l'nonc, et l'avons modifi pour y faire intervenir un tableau : nicks. la fin,
nous vrifions si le tableau contient des items, avec la condition nicks.length > 0. Le contenu du tableau est alors affich
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
77/378
avec la mthode join(), qui permet de spcifier le sparateur. Car en effet, si nous avions fait alert(nicks), les prnoms
auraient t spars par une virgule.
En rsum
Un objet contient un constructeur, des proprits et des mthodes.
Les tableaux sont des variables qui contiennent plusieurs valeurs, chacune tant accessible au moyen d'un indice.
Les indices d'un tableau sont toujours numrots partir de 0. Ainsi, la premire valeur porte l'indice 0.
Des oprations peuvent tre ralises sur les tableaux, comme ajouter des items ou en supprimer.
Pour parcourir un tableau, on utilise gnralement une boucle for, puisqu'on connat, grce la proprit length, le
nombre d'items du tableau.
Les objets littraux sont une variante des tableaux o chaque item est accessible via un identifiant et non un indice.
Questionnaire rcapitulatif
crire une boucle for pour parcourir un tableau
crire un objet littral et le parcourir avec for in
78/378
Prsentation de l'exercice
Ce TP sera consacr un exercice bien particulier : la conversion d'un nombre en toutes lettres. Ainsi, si l'utilisateur entre le
nombre 41 , le script devra retourner ce nombre en toutes lettres : quarante-et-un . Ne vous inquitez pas : vous en tes
parfaitement capables, et nous allons mme vous aider un peu avant de vous donner le corrig !
La marche suivre
Pour mener bien votre exercice, voici quelles sont les tapes que votre script devra suivre (vous n'tes pas obligs de faire
comme a, mais c'est conseill) :
L'utilisateur est invit entrer un nombre entre 0 et 999.
Ce nombre doit tre envoy une fonction qui se charge de le convertir en toutes lettres.
Cette mme fonction doit contenir un systme permettant de sparer les centaines, les dizaines et les units. Ainsi, la
fonction doit tre capable de voir que dans le nombre 365 il y a trois centaines, six dizaines et cinq units. Pour obtenir ce
rsultat, pensez bien utiliser le modulo. Exemple : 365 % 10 = 5.
Une fois le nombre dcoup en trois chiffres, il ne reste plus qu' convertir ces derniers en toutes lettres.
Lorsque la fonction a fini de s'excuter, elle renvoie le nombre en toutes lettres.
Une fois le rsultat de la fonction obtenu, il est affich l'utilisateur.
Lorsque l'affichage du nombre en toutes lettres est termin, on redemande un nouveau nombre l'utilisateur.
noter que vous n'tes pas obligs de respecter toutes ces rgles orthographiques, ce qui compte c'est que votre code puisse
afficher les nombres en toutes lettres, les fautes orthographiques sont secondaires.
79/378
Concernant parseInt(), il s'agit juste d'un approfondissement de son utilisation tant donn que vous savez dj vous en
servir. Cette fonction possde en ralit non pas un mais deux arguments. Le deuxime est trs utile dans certains cas, comme
celui-ci par exemple :
Code : JavaScript
alert(parseInt('010')); // Affiche : 8
Et l vous constatez que le chiffre affich n'est pas 10 comme souhait mais 8 ! Pourquoi ? Tout simplement parce que la fonction
parseInt() supporte plusieurs bases arithmtiques, ainsi on peut lui dire que le premier argument est en binaire. La fonction
nous retournera alors le nombre en base 10 (notre propre base de calcul, le systme dcimal) aprs avoir fait la conversion base 2
(systme binaire) base 10 (systme dcimal). Donc, si nous crivons :
Code : JavaScript
alert(parseInt('100', 2)); // Affiche : 4
Tout simplement parce que si le deuxime argument n'est pas spcifi, la fonction parseInt() va tenter de trouver elle-mme
la base arithmtique du nombre que vous avez pass en premier argument. Ce comportement est stupide vu que la fonction se
trompe trs facilement, la preuve : notre premier exemple sans le deuxime argument a interprt notre nombre comme tant en
base 8 (systme octal) simplement parce que la chane de caractres commence par un 0.
Bref, pour convertir correctement notre premier nombre, il nous faut indiquer parseInt() que ce dernier est en base 10,
comme ceci :
Code : JavaScript
alert(parseInt('010', 10)); // Affiche 10
Maintenant nous obtenons bien le nombre 10 ! Rappelez-vous bien ce deuxime argument, il vous servira pour le TP et, n'en
pas douter, dans une multitude de problmes futurs !
La fonction isNaN()
Jusqu' prsent, pour tester si une variable tait un nombre, vous utilisiez l'instruction typeof, sauf qu'elle pose problme :
Code : JavaScript
var test = parseInt('test'); // Contient au final la valeur NaN
alert(typeof test); // Affiche number
Voil le problme : notre variable contient la valeur NaN qui signifie Not a Number et pourtant l'instruction typeof nous
renvoie number en guise de type, c'est assez contradictoire non ? En fait, typeof est limit pour tester les nombres, la
place mieux vaut utiliser la fonction isNaN() (is Not a Number) :
80/378
Code : JavaScript
var test = parseInt('test'); // Contient au final la valeur NaN
alert(isNaN(test)); // Affiche true
Pourquoi true ? Tout simplement parce que isNaN() renvoie true quand la variable n'est pas un nombre, et false dans le
cas contraire.
Correction
Allez hop ! C'est fini ! Nous esprons que vous avez russi faire quelque chose d'intressant, normalement vous en tes
parfaitement capables ! Le sujet est certes un peu tordu, mais vous avez largement assez de connaissances pour pouvoir le
raliser.
Toutefois, si vous avez bloqu alors que vous connaissiez trs bien ce que l'on a appris dans les chapitres prcdents, ne vous
inquitez pas : la programmation est un domaine o la logique rgne en matresse (bon, d'accord, pas tout le temps !), il faut donc
de l'exprience pour en arriver dvelopper de faon logique. Ce que nous voulons dire, c'est que si vous n'avez pas russi
coder l'exercice aujourd'hui, ce n'est pas un drame ! Faites une pause, essayez de faire des exercices plus simples et revenez
ensuite sur celui-ci.
De toute manire, c'est bien simple, si vous arrivez lire et comprendre le corrig que nous fournissons, alors vous tes capables
de raliser cet exercice tout aussi bien que nous, voire mme mieux !
Le corrig complet
Voici donc la correction. Prcisons que ce code n'est pas universel ! Il existe de nombreuses autres faons de coder cet exercice,
et cette version n'est pas forcment la meilleure. Donc, si vous cherchez recoder cet exercice aprs avoir lu le corrig, ne refaites
pas exactement la mme chose ! Inventez votre propre solution, innovez selon vos propres ides ! Aprs tout, on dit qu'il existe
autant d'algorithmes que de personnes dans le monde, car chacun possde sa propre faon de penser ; vous devriez donc tre
capables de raliser une version de ce code en rflchissant par vous-mmes !
Code : JavaScript
function num2Letters(number) {
if (isNaN(number) || number < 0 || 999 < number) {
return 'Veuillez entrer un nombre entier compris entre 0 et
999.';
}
var units2Letters = ['', 'un', 'deux', 'trois', 'quatre',
'cinq', 'six', 'sept', 'huit', 'neuf', 'dix', 'onze', 'douze',
'treize', 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit',
'dix-neuf'],
tens2Letters = ['', 'dix', 'vingt', 'trente', 'quarante',
'cinquante', 'soixante', 'soixante', 'quatre-vingt', 'quatrevingt'];
var units
= number % 10,
tens
= (number % 100 - units) / 10,
hundreds = (number % 1000 - number % 100) / 100;
var unitsOut, tensOut, hundredsOut;
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
81/378
if (number === 0) {
return 'zro';
} else {
// Traitement des units
unitsOut = (units === 1 && tens > 0 && tens !== 8 ? 'et-' :
'') + units2Letters[units];
// Traitement des dizaines
if (tens === 1 && units > 0) {
tensOut = units2Letters[10 + units];
unitsOut = '';
} else if (tens === 7 || tens === 9) {
tensOut = tens2Letters[tens] +'-'+ (tens === 7 && units
=== 1 ? 'et-' : '') + units2Letters[10 + units];
unitsOut = '';
} else {
tensOut = tens2Letters[tens];
}
tensOut += (units === 0 && tens === 8 ? 's' : '');
// Traitement des centaines
hundredsOut = (hundreds > 1 ? units2Letters[hundreds] + '-'
: '') + (hundreds > 0 ? 'cent' : '') + (hundreds > 1 && tens == 0 &&
units == 0 ? 's' : '');
// Retour du total
return hundredsOut + (hundredsOut && tensOut ? '-': '') +
tensOut + (hundredsOut && unitsOut || tensOut && unitsOut ? '-': '')
+ unitsOut;
}
}
var userEntry;
while (userEntry = prompt('Indiquez le nombre crire en toutes
lettres (entre 0 et 999) :')) {
alert(num2Letters(parseInt(userEntry, 10)));
}
Essayer !
Les explications
Vous avez le code, bien ! Mais maintenant il vous faut le comprendre, et on commence tout de suite !
82/378
Le squelette du code
Un code doit toujours possder ce qui peut tre appel un squelette autour duquel il peut s'articuler, c'est--dire un code de
base contenant les principales structures de votre script (comme un objet, une boucle, une fonction, etc.) que l'on va pouvoir
toffer au fur et mesure de l'avance du code. Dans notre cas, nous avons besoin d'une fonction qui fera la conversion des
nombres, ainsi que d'une boucle pour demander l'utilisateur d'entrer un nouveau nombre sans jamais s'arrter (sauf si
l'utilisateur le demande). Voici ce que a donne :
Code : JavaScript
function num2Letters(number) { // num2Letters se lit number to
letters , le 2 est une abrviation souvent utilise en
programmation
// Notre fonction qui s'occupera de la conversion du nombre.
Elle possde un argument lui permettant de recevoir les nombres en
question.
}
var userEntry; // Contient le texte entr par l'utilisateur
while (userEntry = prompt('Indiquez le nombre crire en toutes
lettres (entre 0 et 999) :')) {
/*
Dans la condition de la boucle, on stocke le texte de l'utilisateur
dans la variable userEntry .
Ce qui fait que si l'utilisateur n'a rien entr (valeur nulle, donc
quivalente false) la condition ne sera pas valide.
Donc la boucle while ne s'excutera pas et dans le cas contraire la
boucle s'excutera.
*/
}
alert(num2Letters(parseInt(userEntry, 10)));
Puis nous dclarons les variables ncessaires la bonne excution de notre fonction :
Code : JavaScript
function num2Letters(number) {
// Code de vrification de l'argument []
/*
Ci-dessous on dclare deux tableaux contenant les nombres en toutes
lettres, un tableau pour les units et un autre pour les dizaines.
Le tableau des
units va du chiffre 1 19 afin de simplifier quelques oprations
lors de la conversion du nombre en lettres. Vous comprendrez ce
systme par la suite.
*/
var units2Letters = ['', 'un', 'deux', 'trois', 'quatre',
'cinq', 'six', 'sept', 'huit', 'neuf', 'dix', 'onze', 'douze',
'treize', 'quatorze', 'quinze', 'seize', 'dix-sept', 'dix-huit',
'dix-neuf'],
tens2Letters = ['', 'dix', 'vingt', 'trente', 'quarante',
'cinquante', 'soixante', 'soixante', 'quatre-vingt', 'quatrevingt'];
/*
Ci-dessous on calcule le nombre d'units, de dizaines et de
centaines l'aide du modulo.
Le principe est simple : si on prend 365 % 10 on obtient le reste
de la division par 10 qui est : 5. Voil les units.
Ensuite, sur 365 % 100 on obtient 65, on soustrait les units ce
nombre 65 - 5 = 60, et on divise par 10 pour obtenir 6, voil les
dizaines !
Le principe est le mme pour les centaines sauf que l'on ne
soustrait pas seulement les units mais aussi les dizaines.
*/
var units
= number % 10,
tens
= (number % 100 - units) / 10,
hundreds = (number % 1000 - number % 100) / 100;
// Et enfin on cre les trois variables qui contiendront les
units, les dizaines et les centaines en toutes lettres.
var unitsOut, tensOut, hundredsOut;
}
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
83/378
84/378
Vous remarquerez que nous avons rduit le code de vrification de l'argument crit prcdemment un simple
commentaire. Nous prfrons faire a afin que vous puissiez vous focaliser directement sur le code actuellement tudi,
donc ne vous tonnez pas de voir des commentaires de ce genre.
Si a parat aussi simple c'est parce que notre code a t bien pens ds le dbut et organis de faon pouvoir travailler le plus
facilement possible. Il y a srement moyen de faire mieux, mais ce code simplifie quand mme grandement les choses, non ?
Maintenant notre plus grande difficult va tre de se plier toutes les rgles orthographiques de la langue franaise.
Bref, continuons !
Vous remarquerez que dans nos tableaux il n'y a pas le nombre zro . Nous allons l'ajouter nous-mmes l'aide d'une condition
:
Code : JavaScript
function num2Letters(number) {
// Code de vrification de l'argument []
// Code d'initialisation []
if (number === 0) {
return 'zro'; // Tout simplement ! Si le nombre vaut 0
alors on retourne zro , normal !
}
85/378
Afin de vous simplifier la lecture du code, nous avons mis toutes les ternaires entre parenthses, mme si en temps
normal cela n'est pas vraiment ncessaire.
86/378
Un peu tordu tout a, n'est-ce pas ? Rassurez-vous, vous venez de terminer le passage le plus difficile. Nous nous attaquons
maintenant aux centaines, qui sont plus simples :
Code : JavaScript
function num2Letters(number) {
// Code de vrification de l'argument []
// Code d'initialisation []
if (number === 0) {
return 'zro'; // Tout simplement ! Si le nombre vaut 0
alors on retourne zro , normal !
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
87/378
88/378
Conclusion
La correction et les explications de l'exercice sont enfin termines ! Si vous avez trouv a dur, rassurez-vous : a l'tait.
Bon,
certes, il existe des codes beaucoup plus volus et compliqus que a, mais pour quelqu'un qui dbute c'est dj beaucoup que
de faire a ! Si vous n'avez toujours pas tout compris, je ne peux que vous encourager relire les explications ou bien refaire
l'exercice par vous-mmes. Si, malgr tout, vous n'y arrivez pas, n'oubliez pas que le Site du Zro possde une rubrique
consacre au Javascript dans le forum, vous y trouverez facilement de l'aide pour peu que vous expliquiez correctement votre
problme.
89/378
Le DOM est donc une API qui s'utilise avec les documents XML et HTML, et qui va nous permettre, via le Javascript, d'accder
au code XML et/ou HTML d'un document. C'est grce au DOM que nous allons pouvoir modifier des lments HTML (afficher
ou masquer un <div> par exemple), en ajouter, en dplacer ou mme en supprimer.
Petite note de vocabulaire : dans un cours sur le HTML, on parlera de balises HTML (une paire de balises en ralit :
une balise ouvrante et une balise fermante). Ici, en Javascript, on parlera d'lment HTML, pour la simple raison que
chaque paire de balises (ouvrante et fermante) est vue comme un objet. Par commodit, et pour ne pas confondre, on
parle donc d'lment HTML.
Petit historique
l'origine, quand le Javascript a t intgr dans les premiers navigateurs (Internet Explorer et Netscape Navigator), le DOM
n'tait pas unifi, c'est--dire que les deux navigateurs possdaient un DOM diffrent. Et donc, pour accder un lment
HTML, la manire de faire diffrait d'un navigateur l'autre, ce qui obligeait les dveloppeurs Web coder diffremment en
fonction du navigateur. En bref, c'tait un peu la jungle.
Le W3C a mis de l'ordre dans tout a, et a publi une nouvelle spcification que nous appellerons DOM-1 (pour DOM Level
1). Cette nouvelle spcification dfinit clairement ce qu'est le DOM, et surtout comment un document HTML ou XML est
schmatis. Depuis lors, un document HTML ou XML est reprsent sous la forme d'un arbre, ou plutt hirarchiquement. Ainsi,
l'lment <html> contient deux lments enfants : <head> et <body>, qui leur tour contiennent d'autres lments enfants.
Ensuite, la spcification DOM-2 a t publie. La grande nouveaut de cette version 2 est l'introduction de la mthode
getElementById() qui permet de rcuprer un lment HTML ou XML en connaissant son ID.
L'objet window
Avant de vritablement parler du document, c'est--dire de la page Web, nous allons parler de l'objet window. L'objet window
est ce qu'on appelle un objet global qui reprsente la fentre du navigateur. C'est partir de cet objet que le Javascript est
excut.
Si nous reprenons notre Hello World! du dbut, nous avons :
Code : HTML
<!DOCTYPE html>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
90/378
<html>
<head>
<title>Hello World!</title>
</head>
<body>
<script>
alert('Hello world!');
</script>
</body>
</html>
Contrairement ce qui a t dit dans ce cours, alert() n'est pas vraiment une fonction. Il s'agit en ralit d'une mthode
appartenant l'objet window. Mais l'objet window est dit implicite, c'est--dire qu'il n'y a gnralement pas besoin de le
spcifier. Ainsi, ces deux instructions produisent le mme effet, savoir ouvrir une bote de dialogue :
Code : JavaScript
window.alert('Hello world!');
alert('Hello world!');
Puisqu'il n'est pas ncessaire de spcifier l'objet window, on ne le fait gnralement pas sauf si cela est ncessaire, par exemple
si on manipule des frames.
Ne faites pas de gnralisation htive : si alert() est une mthode de l'objet window, toutes les fonctions ne font
pas ncessairement partie de l'objet window. Ainsi, les fonctions comme isNaN(), parseInt() ou encore
parseFloat() ne dpendent pas d'un objet. Ce sont des fonctions globales. Ces dernires sont, cependant,
extrmement rares. Les quelques fonctions cites dans ce paragraphe reprsentent prs de la moiti des fonctions dites
globales , ce qui prouve clairement qu'elles ne sont pas bien nombreuses.
De mme, lorsque vous dclarez une variable dans le contexte global de votre script, cette variable deviendra en vrit une
proprit de l'objet window. Afin de vous dmontrer facilement la chose, regardez donc ceci :
Code : JavaScript
var text = 'Variable globale !';
(function() { // On utilise une IEF pour isoler du code
var text = 'Variable locale !';
alert(text); // Forcment, la variable locale prend le dessus
alert(window.text); // Mais il est toujours possible d'accder
la variable globale grce l'objet window
})();
Si vous tentez d'excuter cet exemple via le site jsfiddle.net vous risquez alors d'obtenir un rsultat erron. Il peut
arriver que ce genre de site ne permette pas l'excution de tous les types de codes, en particulier lorsque vous touchez
window.
91/378
Une dernire chose importante qu'il vous faut mmoriser : toute variable non dclare (donc utilise sans jamais crire le mot-cl
var) deviendra immdiatement une proprit de l'objet window, et ce, quel que soit l'endroit o vous utilisez cette variable !
Prenons un exemple simple :
Code : JavaScript
(function() { // On utilise une IEF pour isoler du code
text = 'Variable accessible !'; // Cette variable n'a jamais
t dclare et pourtant on lui attribue une valeur
})();
alert(text); // Affiche : Variable accessible !
Notre variable a t utilise pour la premire fois dans une IEF et pourtant nous y avons accs depuis l'espace global ! Alors
pourquoi cela fonctionne-t-il de cette manire ? Tout simplement parce que le Javascript va chercher rsoudre le problme que
nous lui avons donn : on lui demande d'attribuer une valeur la variable text, il va donc chercher cette variable mais ne la
trouve pas, la seule solution pour rsoudre le problme qui lui est donn est alors d'utiliser l'objet window. Ce qui veut dire
qu'en crivant :
Code : JavaScript
text = 'Variable accessible !';
le code sera alors interprt de cette manire si aucune variable accessible n'existe avec ce nom :
Code : JavaScript
window.text = 'Variable accessible !';
Si nous vous montrons cette particularit du Javascript c'est pour vous conseiller de ne pas vous en servir ! Si vous n'utilisez
jamais le mot-cl var alors vous allez trs vite arriver de grandes confusions dans votre code (et de nombreux bugs). Si vous
souhaitez dclarer une variable dans l'espace global alors que vous vous trouvez actuellement dans un autre espace (une IEF,
par exemple), spcifiez donc explicitement l'objet window. Le reste du temps, pensez bien crire le mot-cl var.
Le document
L'objet document est un sous-objet de window, l'un des plus utiliss. Et pour cause, il reprsente la page Web et plus
prcisment la balise <html>. C'est grce cet lment-l que nous allons pouvoir accder aux lments HTML et les modifier.
Voyons donc, dans la sous-partie suivante, comment naviguer dans le document.
92/378
Le schma est plutt simple : l'lment <html> contient deux lments, appels enfants : <head> et <body>. Pour ces deux
enfants, <html> est l'lment parent. Chaque lment est appel nud (node en anglais). L'lment <head> contient lui aussi
deux enfants : <meta> et <title>. <meta> ne contient pas d'enfant tandis que <title> en contient un, qui sappelle
#text. Comme son nom l'indique, #text est un lment qui contient du texte.
Il est important de bien saisir cette notion : le texte prsent dans une page Web est vu par le DOM comme un nud de type
#text. Dans le schma prcdent, l'exemple du paragraphe qui contient du texte et un lien illustre bien cela :
Code : HTML
<p>
</p>
Un peu de texte
<a>et un lien</a>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
93/378
Si on va la ligne aprs chaque nud, on remarque clairement que l'lment <p> contient deux enfants : #text qui contient
Un peu de texte et <a>, qui lui-mme contient un enfant #text reprsentant et un lien .
getElementById()
Cette mthode permet d'accder un lment en connaissant son ID qui est simplement l'attribut id de l'lment. Cela
fonctionne de cette manire :
Code : HTML
<div id="myDiv">
<p>Un peu de texte <a>et un lien</a></p>
</div>
<script>
var div = document.getElementById('myDiv');
alert(div);
</script>
Essayer !
En excutant ce code, le navigateur affiche ceci :
HTMLDivElement
Il nous dit que div est un objet de type HTMLDivElement. En clair, c'est un lment HTML qui se trouve tre un <div>, ce
qui nous montre que le script fonctionne correctement.
getElementsByTagName()
Faites trs attention dans le nom de cette mthode : il y a un s Elements. C'est une source frquente d'erreurs.
Cette mthode permet de rcuprer, sous la forme d'un tableau, tous les lments de la famille. Si, dans une page, on veut
rcuprer tous les <div>, il suffit de faire comme ceci :
Code : JavaScript
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
94/378
Essayer !
La mthode retourne une collection d'lments (utilisable de la mme manire qu'un tableau). Pour accder chaque lment, il
est ncessaire de parcourir le tableau avec une petite boucle.
Deux petites astuces :
1. Cette mthode est accessible sur n'importe quel lment HTML et pas seulement sur l'objet document.
2. En paramtre de cette mthode vous pouvez mettre une chane de caractres contenant un astrisque * qui rcuprera
tous les lments HTML contenus dans l'lment cibl.
getElementsByName()
Cette mthode est semblable getElementsByTagName() et permet de ne rcuprer que les lments qui possdent un
attribut name que vous spcifiez. L'attribut name n'est utilis qu'au sein des formulaires, et est dprci depuis la spcification
HTML5 dans tout autre lment que celui d'un formulaire. Par exemple, vous pouvez vous en servir pour un lment <input>
mais pas pour un lment <map>.
Sachez aussi que cette mthode est dprcie en XHTML mais est maintenant standardise pour l'HTML5.
Ce slecteur CSS stipule que l'on souhaite slectionner les balises de type <span> contenues dans les classes .item ellesmmes contenues dans un lment dont l'identifiant est #menu.
Le principe est plutt simple mais trs efficace. Sachez que ces deux mthodes supportent aussi les slecteurs CSS 3, bien plus
complets ! Vous pouvez consulter leur liste sur la spcification du W3C.
Voyons maintenant les particularits de ces deux mthodes. La premire, querySelector(), renvoie le premier lment
trouv correspondant au slecteur CSS, tandis que querySelectorAll() va renvoyer tous les lments (sous forme de
tableau) correspondant au slecteur CSS fourni. Prenons un exemple simple :
Code : HTML
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
95/378
<div id="menu">
<div class="item">
<span>lment 1</span>
<span>lment 2</span>
</div>
<div class="publicite">
<span>lment 3</span>
<span>lment 4</span>
</div>
</div>
<div id="contenu">
<span>Introduction au contenu de la page...</span>
</div>
Maintenant, essayons le slecteur CSS prsent plus haut : #menu .item span
Dans le code suivant, nous utilisons une nouvelle proprit nomme innerHTML, nous l'tudierons plus tard dans ce
chapitre. Dans l'immdiat, sachez seulement qu'elle permet d'accder au contenu d'un lment HTML.
Code : JavaScript
var query = document.querySelector('#menu .item span'),
queryAll = document.querySelectorAll('#menu .item span');
alert(query.innerHTML); // Affiche : "lment 1"
alert(queryAll.length); // Affiche : "2"
alert(queryAll[0].innerHTML + ' - ' + queryAll[1].innerHTML); //
Affiche : "lment 1 - lment 2"
Nous obtenons bien les rsultats escompts ! Nous vous conseillons de bien vous rappeler ces deux mthodes. Elles sont dj
utiles sur des projets vous tourner sur des navigateurs rcents, et d'ici quelques annes elles pourraient bien devenir
habituelles (le temps que les vieilles versions des navigateurs disparaissent pour de bon).
Notion d'hritage
Nous avons vu qu'un lment <div> est un objet HTMLDivElement, mais un objet, en Javascript, peut appartenir
diffrents groupes. Ainsi, notre <div> est un HTMLDivElement, qui est un sous-objet d'HTMLElement qui est lui-mme
un sous-objet d'Element. Element est enfin un sous-objet de Node. Ce schma est plus parlant :
96/378
L'objet Node apporte un certain nombre de proprits et de mthodes qui pourront tre utilises depuis un de ses sous-objets.
En clair, les sous-objets hritent des proprits et mthodes de leurs objets parents. Voil donc ce que l'on appelle l'hritage.
Les attributs
Via l'objet Element
Pour interagir avec les attributs, l'objet Element nous fournit deux mthodes, getAttribute() et setAttribute()
permettant respectivement de rcuprer et d'diter un attribut. Le premier paramtre est le nom de l'attribut, et le deuxime, dans le
cas de setAttribute() uniquement, est la nouvelle valeur donner l'attribut. Petit exemple :
Code : HTML
<body>
<a id="myLink" href="http://www.un_lien_quelconque.com">Un lien
modifi dynamiquement</a>
<script>
var link = document.getElementById('myLink');
var href = link.getAttribute('href'); // On rcupre l'attribut
href
alert(href);
link.setAttribute('href', 'http://www.siteduzero.com'); // On
dite l'attribut href
</script>
</body>
On commence par rcuprer l'lment myLink, et on lit son attribut href via getAttribute(). Ensuite on modifie la valeur
de l'attribut href avec setAttribute(). Le lien pointe maintenant vers http://www.siteduzero.com.
97/378
En fait, pour la plupart des lments courants comme <a>, il est possible d'accder un attribut via une proprit. Ainsi, si on
veut modifier la destination d'un lien, on peut utiliser la proprit href, comme ceci :
Code : HTML
<body>
<a id="myLink" href="http://www.un_lien_quelconque.com">Un lien
modifi dynamiquement</a>
<script>
var link = document.getElementById('myLink');
var href = link.href;
alert(href);
link.href = 'http://www.siteduzero.com';
</script>
</body>
Essayer !
C'est cette faon de faire que l'on utilisera majoritairement pour les formulaires : pour rcuprer ou modifier la valeur
d'un champ, on utilisera la proprit value.
La classe
On peut penser que pour modifier l'attribut class d'un lment HTML, il suffit d'utiliser element.class. Ce n'est pas
possible, car le mot-cl class est rserv en Javascript, bien qu'il n'ait aucune utilit. la place de class, il faudra utiliser
className.
Code : HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Le titre de la page</title>
<style type="text/css">
.blue {
background: blue;
color: white;
}
</style>
</head>
<body>
<div id="myColoredDiv">
<p>Un peu de texte <a>et un lien</a></p>
</div>
<script>
document.getElementById('myColoredDiv').className = 'blue';
</script>
</body>
</html>
Dans cet exemple, on dfinit la classe CSS .blue l'lment myColoredDiv, ce qui fait que cet lment sera affich avec un
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
98/378
Faites attention : si votre lment comporte plusieurs classes (exemple : <a class="external red u">) et que vous
rcuprez la classe avec className, cette proprit ne retournera pas un tableau avec les diffrentes classes, mais bien la
chane external red u , ce qui n'est pas vraiment le comportement souhait. Il vous faudra alors couper cette chane avec la
mthode split() pour obtenir un tableau, comme ceci :
Code : JavaScript
var classes
= document.getElementById('myLink').className;
var classesNew = [];
classes = classes.split(' ');
for (var i = 0, c = classes.length; i < c; i++) {
if (classes[i]) {
classesNew.push(classes[i]);
}
}
alert(classesNew);
Essayer !
L, on rcupre les classes, on dcoupe la chane, mais comme il se peut que plusieurs espaces soient prsentes entre chaque
nom de classe, on vrifie chaque lment pour voir s'il contient quelque chose (s'il n'est pas vide). On en profite pour crer un
nouveau tableau, classesNew, qui contiendra les noms des classes, sans parasites .
Le contenu : innerHTML
La proprit innerHTML est spciale et demande une petite introduction. Elle a t cre par Microsoft pour les besoins
d'Internet Explorer et vient tout juste d'tre normalise au sein du HTML5. Bien que non normalise pendant des annes, elle est
devenue un standard parce que tous les navigateurs la supportaient dj, et non l'inverse comme c'est gnralement le cas.
Rcuprer du HTML
innerHTML permet de rcuprer le code HTML enfant d'un lment sous forme de texte. Ainsi, si des balises sont prsentes,
innerHTML les retournera sous forme de texte :
Code : HTML
<body>
<div id="myDiv">
<p>Un peu de texte <a>et un lien</a></p>
</div>
<script>
var div = document.getElementById('myDiv');
alert(div.innerHTML);
</script>
</body>
Nous avons donc bien une bote de dialogue qui affiche le contenu de myDiv, sous forme de texte :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
99/378
Si vous voulez ajouter du contenu, et ne pas modifier le contenu dj en place, il suffit dutiliser += la place de l'oprateur
d'affectation :
Code : JavaScript
document.getElementById('myDiv').innerHTML += ' et <strong>une
portion mise en emphase</strong>.';
Toutefois, une petite mise en garde : il ne faut pas utiliser le += dans une boucle ! En effet, innerHTML ralentit
considrablement l'excution du code si l'on opre de cette manire, il vaut donc mieux concatner son texte dans une variable
pour ensuite ajouter le tout via innerHTML. Exemple :
Code : JavaScript
var text = '';
while( /* condition */ ) {
text += 'votre_texte'; // On concatne dans la variable text
}
element.innerHTML = text; // Une fois la concatnation termine, on
ajoute le tout element via innerHTML
Attention ! Si un jour il vous prend l'envie d'ajouter une balise <script> votre page par le biais de la proprit
innerHTML, sachez que ceci ne fonctionne pas ! Il est toutefois possible de crer cette balise par le biais de la
mthode createElement() que nous tudierons au prochain chapitre.
innerText et textContent
Penchons-nous maintenant sur deux proprits analogues innerHTML : innerText pour Internet Explorer et
textContent pour les autres navigateurs.
innerText
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
100/378
La proprit innerText a aussi t introduite dans Internet Explorer, mais la diffrence de sa proprit sur innerHTML,
elle n'a jamais t standardise et n'est pas supporte par tous les navigateurs. Internet Explorer (pour toute version antrieure
la neuvime) ne supporte que cette proprit et non pas la version standardise que nous verrons par la suite.
Le fonctionnement d'innerText est le mme qu'innerHTML except le fait que seul le texte est rcupr, et non les balises.
C'est pratique pour rcuprer du contenu sans le balisage, petit exemple :
Code : HTML
<body>
<div id="myDiv">
<p>Un peu de texte <a>et un lien</a></p>
</div>
<script>
var div = document.getElementById('myDiv');
alert(div.innerText);
</script>
</body>
Ce qui nous donne bien Un peu de texte et un lien , sans les balises :
textContent
La proprit textContent est la version standardise d'innerText ; elle est reconnue par tous les navigateurs l'exception
d'Internet Explorer, bien que la version 9 la prenne aussi en charge. Le fonctionnement est videmment le mme. Maintenant une
question se pose : comment faire un script qui fonctionne la fois pour Internet Explorer et les autres navigateurs ? C'est ce que
nous allons voir !
Tester le navigateur
Il est possible via une simple condition de tester si le navigateur prend en charge telle ou telle mthode ou proprit.
Code : HTML
<body>
<div id="myDiv">
<p>Un peu de texte <a>et un lien</a></p>
</div>
<script>
var div = document.getElementById('myDiv');
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
101/378
Il suffit donc de tester par le biais d'une condition si l'instruction fonctionne. Si textContent ne fonctionne pas, pas de
soucis, on prend innerText :
Cela dit, ce code est quand mme trs long et redondant. Il est possible de le raccourcir de manire considrable :
Code : JavaScript
txt = div.textContent || div.innerText || '';
En rsum
Le DOM va servir accder aux lments HTML prsents dans un document afin de les modifier et d'interagir avec eux.
L'objet window est un objet global qui reprsente la fentre du navigateur. document, quant lui, est un sous-objet de
window et reprsente la page Web. C'est grce lui que l'on va pouvoir accder aux lments HTML de la page Web.
Les lments de la page sont structurs comme un arbre gnalogique, avec l'lment <html> comme lment fondateur.
Diffrentes mthodes, comme getElementById(), getElementsByTagName(), querySelector() ou
querySelectorAll(), sont disponibles pour accder aux lments.
Les attributs peuvent tous tre modifis grce setAttribute(). Certains lments possdent des proprits qui
permettent de modifier ces attributs.
La proprit innerHTML permet de rcuprer ou de dfinir le code HTML prsent l'intrieur d'un lment.
De leur ct, textContent et innerText ne sont capables que de dfinir ou rcuprer du texte brut, sans aucunes
balises HTML.
102/378
Questionnaire rcapitulatif
Modifier un lment
Modifier un attribut de manire gnrique
Utilisation d'innerHTML
103/378
La proprit parentNode
La proprit parentNode permet d'accder l'lment parent d'un lment. Regardez ce code :
Code : HTML
<blockquote>
<p id="myP">Ceci est un paragraphe !</p>
</blockquote>
Admettons qu'on doive accder myP, et que pour une autre raison on doive accder l'lment <blockquote>, qui est le
parent de myP. Il suffit d'accder myP puis son parent, avec parentNode :
Code : JavaScript
var paragraph = document.getElementById('myP');
var blockquote = paragraph.parentNode;
nodeType et nodeName
nodeType et nodeName servent respectivement vrifier le type d'un nud et le nom d'un nud. nodeType retourne un
nombre, qui correspond un type de nud. Voici un tableau qui liste les types possibles, ainsi que leurs numros (les types
courants sont mis en gras) :
Numro
Type de nud
Nud lment
Nud attribut
Nud texte
104/378
Nud document
10
11
12
nodeName, quant lui, retourne simplement le nom de l'lment, en majuscule. Il est toutefois conseill d'utiliser
toLowerCase() (ou toUpperCase()) pour forcer un format de casse et ainsi viter les mauvaises surprises.
Code : JavaScript
var paragraph = document.getElementById('myP');
alert(paragraph.nodeType + '\n\n' +
paragraph.nodeName.toLowerCase());
Essayer !
Essayer !
En schmatisant l'lment myP prcdent, on obtient ceci :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
105/378
Schma de l'lment
myP
Le premier enfant de <p> est un nud textuel, alors que le dernier enfant est un lment <strong>.
Dans le cas o vous ne souhaiteriez rcuprer que les enfants qui sont considrs comme des lments HTML (et donc
viter les nuds #text par exemple), sachez qu'il existe les proprits firstElementChild et
lastElementChild. Ainsi, dans l'exemple prcdent, la proprit firstElementChild renverrait l'lment
<a>.
Malheureusement, il s'agit l de deux proprits rcentes, leur utilisation est donc limite aux versions rcentes des
navigateurs ( partir de la version 9 concernant Internet Explorer).
nodeValue et data
Changeons de problme : il faut rcuprer le texte du premier enfant, et le texte contenu dans l'lment <strong>, mais
comment faire ?
Il faut soit utiliser la proprit nodeValue soit la proprit data. Si on recode le script prcdent, nous obtenons ceci :
Code : JavaScript
var paragraph = document.getElementById('myP');
var first = paragraph.firstChild;
var last = paragraph.lastChild;
alert(first.nodeValue);
alert(last.firstChild.data);
Essayer !
first contient le premier nud, un nud textuel. Il suffit de lui appliquer la proprit nodeValue (ou data) pour rcuprer
son contenu ; pas de difficult ici. En revanche, il y a une petite diffrence avec notre lment <strong> : vu que les proprits
nodeValue et data ne s'appliquent que sur des nuds textuels, il nous faut d'abord accder au nud textuel que contient
notre lment, c'est--dire son nud enfant. Pour cela, on utilise firstChild (et non pas firstElementChild), et
ensuite on rcupre le contenu avec nodeValue ou data.
childNodes
La proprit childNodes retourne un tableau contenant la liste des enfants d'un lment. L'exemple suivant illustre le
fonctionnement de cette proprit, de manire rcuprer le contenu des lments enfants :
Code : HTML
<body>
<div>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
106/378
Essayer !
nextSibling et previousSibling
nextSibling et previousSibling sont deux proprits qui permettent d'accder respectivement au nud suivant et au
nud prcdent.
Code : HTML
<body>
<div>
<p id="myP">Un peu de texte, <a>un lien</a> et <strong>une
portion en emphase</strong></p>
</div>
<script>
var paragraph = document.getElementById('myP');
var first = paragraph.firstChild;
var next = first.nextSibling;
alert(next.firstChild.data); // Affiche un lien
</script>
</body>
Essayer !
Dans cet exemple, on rcupre le premier enfant de myP, et sur ce premier enfant on utilise nextSibling, qui permet de
rcuprer llment <a>. Avec a, il est mme possible de parcourir les enfants d'un lment, en utilisant une boucle while :
Code : HTML
<body>
<div>
<p id="myP">Un peu de texte <a>et un lien</a></p>
</div>
<script>
var paragraph = document.getElementById('myP');
var child = paragraph.lastChild; // On prend le dernier enfant
while (child) {
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
107/378
Essayer !
Pour changer un peu, la boucle tourne l'envers , car on commence par rcuprer le dernier enfant et on chemine reculons.
Tout comme pour firstChild et lastChild, sachez qu'il existe les proprits nextElementSibling et
previousElementSibling qui permettent, elles aussi, de ne rcuprer que les lments HTML. Ces deux
proprits ont les mmes problmes de compatibilit que firstElementChild et lastElementChild.
En fait, les espaces entre les lments tout comme les retours la ligne sont considrs comme des nuds textuels (enfin, cela
dpend des navigateurs) ! Ainsi donc, si l'on schmatise le premier code, on obtient ceci :
108/378
Cration de l'lment
La cration d'un lment se fait avec la mthode createElement(), un sous-objet de l'objet racine, c'est--dire document
dans la majorit des cas :
Code : JavaScript
var newLink = document.createElement('a');
On cre ici un nouvel lment <a>. Cet lment est cr, mais n'est pas insr dans le document, il n'est donc pas visible. Cela
dit, on peut dj travailler dessus, en lui ajoutant des attributs ou mme des vnements (que nous verrons dans le chapitre
suivant).
Si vous travaillez dans une page Web, l'lment racine sera toujours document, sauf dans le cas des frames. La
cration d'lments au sein de fichiers XML sera aborde plus tard.
109/378
Insertion de l'lment
On utilise la mthode appendChild() pour insrer l'lment. Append child signifie ajouter un enfant , ce qui signifie qu'il
nous faut connatre l'lment auquel on va ajouter l'lment cr. Considrons donc le code suivant :
Code : HTML
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<title>Le titre de la page</title>
</head>
<body>
<div>
<p id="myP">Un peu de texte <a>et un lien</a></p>
</div>
</body>
</html>
On va ajouter notre lment <a> dans l'lment <p> portant l'ID myP. Pour ce faire, il suffit de rcuprer cet lment, et d'ajouter
notre lment <a> via appendChild() :
Code : JavaScript
document.getElementById('myP').appendChild(newLink);
Une petite explication s'impose ! Avant d'insrer notre lment <a>, la structure DOM du document ressemble ceci :
110/378
Cela veut dire qu'appendChild() insrera toujours l'lment en tant que dernier enfant, ce qui n'est pas toujours trs
pratique. Nous verrons plus tard comment insrer un lment avant ou aprs un enfant donn.
L'insertion se fait ici aussi avec appendChild(), sur l'lment newLink. Afin d'y voir plus clair, rsumons le code :
Code : HTML
<body>
<div>
<p id="myP">Un peu de texte <a>et un lien</a></p>
</div>
<script>
var newLink = document.createElement('a');
newLink.id
= 'sdz_link';
newLink.href = 'http://www.siteduzero.com';
newLink.title = 'Dcouvrez le Site du Zro !';
newLink.setAttribute('tabindex', '10');
document.getElementById('myP').appendChild(newLink);
var newLinkText = document.createTextNode("Le Site du Zro");
newLink.appendChild(newLinkText);
</script>
</body>
Essayer !
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
111/378
Le rsultat obtenu
Il y a quelque chose savoir : le fait d'insrer via appendChild() n'a aucune incidence sur l'ordre dexcution des
instructions. Cela veut donc dire que l'on peut travailler sur les lments HTML et les nuds textuels sans qu'ils soient au
pralable insrs dans le document. Par exemple, on pourrait ordonner le code comme ceci :
Code : JavaScript
var newLink = document.createElement('a');
var newLinkText = document.createTextNode("Le Site du Zro");
newLink.id
= 'sdz_link';
newLink.href = 'http://www.siteduzero.com';
newLink.title = 'Dcouvrez le Site du Zro !';
newLink.setAttribute('tabindex', '10');
newLink.appendChild(newLinkText);
document.getElementById('myP').appendChild(newLink);
Ici, on commence par crer les deux lments (le lien et le nud de texte), puis on affecte les variables au lien et on lui ajoute le
nud textuel. ce stade-ci, l'lment HTML contient le nud textuel, mais cet lment n'est pas encore insr dans le document
:
112/378
appendChild() retourne une rfrence (voir plus loin pour plus de dtails) pointant sur l'objet qui vient d'tre insr. Cela
peut servir dans le cas o vous n'avez pas dclar de variable intermdiaire lors du processus de cration de votre lment. Par
exemple, le code suivant ne pose pas de problme :
Code : JavaScript
var span = document.createElement('span');
document.body.appendChild(span);
span.innerHTML = 'Du texte en plus !';
En revanche, si vous retirez l'tape intermdiaire (la premire ligne) pour gagner une ligne de code alors vous allez tre embt
pour modifier le contenu :
Code : JavaScript
document.body.appendChild(document.createElement('span'));
span.innerHTML = 'Du texte en plus !'; // La variable span
n'existe plus Le code plante.
La solution ce problme est d'utiliser la rfrence retourne par appendChild() de la faon suivante :
Code : JavaScript
var span =
document.body.appendChild(document.createElement('span'));
span.innerHTML = 'Du texte en plus !'; // L, tout fonctionne !
Si on modifie la valeur de nick2, la valeur de nick1 reste inchange : normal, les deux variables sont bien distinctes.
Les rfrences
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
113/378
Outre le passage par valeur , le Javascript possde un passage par rfrence . En fait, quand une variable est cre, sa
valeur est mise en mmoire par l'ordinateur. Pour pouvoir retrouver cette valeur, elle est associe une adresse que seul
l'ordinateur connat et manipule (on ne s'en occupe pas).
Quand on passe une valeur par rfrence, on transmet l'adresse de la valeur, ce qui va permettre d'avoir deux variables qui
pointent sur une mme valeur ! Malheureusement, un exemple thorique d'un passage par rfrence n'est pas vraiment
envisageable ce stade du tutoriel, il faudra attendre d'aborder le chapitre sur la cration d'objets. Cela dit, quand on manipule
une page Web avec le DOM, on est confront des rfrences, tout comme dans le chapitre suivant sur les vnements.
La variable newLink contient en ralit une rfrence vers l'lment <a> qui a t cr. newLink ne contient pas l'lment, il
contient une adresse qui pointe vers ce fameux <a>. Une fois que l'lment HTML est insr dans la page, on peut y accder de
nombreuses autres faons, comme avec getElementById(). Quand on accde un lment via getElementById(), on
le fait aussi au moyen d'une rfrence.
Ce qu'il faut retenir de tout a, c'est que les objets du DOM sont toujours accessibles par rfrence, et c'est la raison pour
laquelle ce code ne fonctionne pas :
Code : JavaScript
var newDiv1 = document.createElement('div');
var newDiv2 = newDiv1; // On tente de copier le <div>
Eh oui, si vous avez tout suivi, newDiv2 contient une rfrence qui pointe vers le mme <div> que newDiv1. Mais comment
dupliquer un lment alors ? Eh bien il faut le cloner, et c'est ce que nous allons voir maintenant !
114/378
// On va cloner un lment cr :
var hr1 = document.createElement('hr');
var hr2 = hr1.cloneNode(false); // Il n'a pas d'enfants
// Ici, on clone un lment existant :
var paragraph1 = document.getElementById('myP');
var paragraph2 = paragraph1.cloneNode(true);
// Et attention, l'lment est clon, mais pas insr tant que
l'on n'a pas appel appendChild() :
paragraph1.parentNode.appendChild(paragraph2);
Essayer !
Une chose trs importante retenir, bien qu'elle ne vous concernera qu'au chapitre suivant, est que la mthode
cloneNode() ne copie malheureusement pas les vnements associs et crs avec le DOM (avec
addEventListener()), mme avec un paramtre true. Pensez bien cela !
Essayer !
Supprimer un lment
Pour insrer un lment, on utilise appendChild(), et pour en supprimer un, on utilise removeChild(). Cette mthode
prend en paramtre le nud enfant retirer. Si on se calque sur le code HTML de l'exemple prcdent, le script ressemble ceci :
Code : JavaScript
var link = document.getElementsByTagName('a')[0];
link.parentNode.removeChild(link);
115/378
Il n'y a pas besoin de rcuprer myP (l'lment parent) avec getElementById(), autant le faire directement avec
parentNode.
noter que la mthode removeChild() retourne l'lment supprim, ce qui veut dire qu'il est parfaitement possible de
supprimer un lment HTML pour ensuite le rintgrer o on le souhaite dans le DOM :
Code : JavaScript
var link = document.getElementsByTagName('a')[0];
var oldLink = link.parentNode.removeChild(link); // On supprime
l'lment et on le garde en stock
document.body.appendChild(oldLink); // On rintgre ensuite
l'lment supprim o on veut et quand on veut
Autres actions
Vrifier la prsence d'lments enfants
Rien de plus facile pour vrifier la prsence d'lments enfants : hasChildNodes(). Il suffit d'utiliser cette mthode sur
l'lment de votre choix ; si cet lment possde au moins un enfant, la mthode renverra true :
Code : HTML
<div>
<p id="myP">Un peu de texte <a>et un lien</a></p>
</div>
<script>
var paragraph = document.getElementsByTagName('p')[0];
alert(paragraph.hasChildNodes()); // Affiche true
</script>
Essayer !
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
116/378
Algorithme
Pour insrer aprs un lment, on va d'abord rcuprer l'lment parent. C'est logique, puisque l'insertion de l'lment va se faire
soit via appendChild(), soit via insertBefore() : si on veut ajouter notre lment aprs le dernier enfant, c'est simple, il
suffit d'appliquer appendChild(). Par contre, si l'lment aprs lequel on veut insrer notre lment n'est pas le dernier, on va
utiliser insertBefore() en ciblant l'enfant suivant, avec nextSibling :
Code : JavaScript
function insertAfter(newElement, afterElement) {
var parent = afterElement.parentNode;
if (parent.lastChild === afterElement) { // Si le dernier
lment est le mme que l'lment aprs lequel on veut insrer, il
suffit de faire appendChild()
parent.appendChild(newElement);
} else { // Dans le cas contraire, on fait un insertBefore() sur
l'lment suivant
parent.insertBefore(newElement, afterElement.nextSibling);
}
}
Premier exercice
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
nonc
Pour ce premier exercice, nous vous proposons de recrer du texte mlang divers lments tels des <a> et des
<strong>. C'est assez simple, mais pensez bien ne pas vous emmler les pinceaux avec tous les nuds textuels !
Code : HTML
<div id="divTP1">
Le <strong>World Wide Web Consortium</strong>, abrg par le sigle
<strong>W3C</strong>, est un
<a href="http://fr.wikipedia.org/wiki/Organisme_de_normalisation"
title="Organisme de normalisation">organisme de standardisation</a>
but non-lucratif charg de promouvoir la compatibilit des
technologies du <a
href="http://fr.wikipedia.org/wiki/World_Wide_Web" title="World Wide
Web">World Wide Web</a>.
</div>
Corrig
Secret (cliquez pour afficher)
Code : JavaScript
// On cre l'lment conteneur
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
117/378
118/378
Essayer !
Par mesure de facilit, tous les nuds textuels sont contenus dans le tableau textNodes, a vite de faire 250 variables
diffrentes. Une fois les nuds textuels crs, on cre les lments <a> et <strong>. Une fois que tout cela est fait, on
insre le tout, un lment aprs l'autre, dans le div conteneur.
Deuxime exercice
nonc
Code : HTML
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
119/378
<div id="divTP2">
<p>Langages bass sur ECMAScript :</p>
<ul>
<li>JavaScript</li>
<li>JScript</li>
<li>ActionScript</li>
<li>EX4</li>
</ul>
</div>
On ne va tout de mme pas crer quatre lments <li> la main Utilisez une boucle for ! Et souvenez-vous, utilisez un
tableau pour dfinir les lments textuels.
Corrig
Secret (cliquez pour afficher)
Code : JavaScript
// On cre l'lment conteneur
var mainDiv = document.createElement('div');
mainDiv.id = 'divTP2';
// On cre tous les nuds textuels, pour plus de facilit
var languages = [
document.createTextNode('JavaScript'),
document.createTextNode('JScript'),
document.createTextNode('ActionScript'),
document.createTextNode('EX4')
];
// On cre le paragraphe
var paragraph
= document.createElement('p');
var paragraphText = document.createTextNode('Langages bass sur
ECMAScript :');
paragraph.appendChild(paragraphText);
// On cre la liste, et on boucle pour ajouter chaque item
var uList = document.createElement('ul'),
uItem;
for (var i = 0, c=languages.length; i < c; i++) {
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
120/378
uItem = document.createElement('li');
uItem.appendChild(languages[i]);
uList.appendChild(uItem);
Essayer !
Les nuds textuels de la liste puces sont crs par le biais du tableau languages, et pour crer chaque lment <li>, il
suffit de boucler sur le nombre d'items du tableau.
Troisime exercice
nonc
Voici une version lgrement plus complexe de l'exercice prcdent. Le schma de fonctionnement est le mme, mais ici le tableau
languages contiendra des objets littraux, et chacun de ces objets contiendra deux proprits : le nud du <dt> et le noeud
du <dd>.
Code : HTML
<div id="divTP3">
<p>Langages bass sur ECMAScript :</p>
<dl>
<dt>JavaScript</dt>
<dd>JavaScript est un langage de programmation de scripts
principalement utilis dans les pages web interactives mais aussi
cot serveur.</dd>
<dt>JScript</dt>
<dd>JScript est le nom gnrique de plusieurs implmentations
d'ECMAScript 3 cres par Microsoft.</dd>
<dt>ActionScript</dt>
<dd>ActionScript est le langage de programmation utilis au sein
d'applications clientes (Adobe Flash, Adobe Flex) et serveur (Flash
media server, JRun, Macromedia Generator).</dd>
<dt>EX4</dt>
<dd>ECMAScript for XML (E4X) est une extension XML au langage
ECMAScript.</dd>
</dl>
</div>
Corrig
Secret (cliquez pour afficher)
Code : JavaScript
// On cre l'lment conteneur
var mainDiv = document.createElement('div');
mainDiv.id = 'divTP3';
// On place le texte dans des objets, eux-mmes placs dans un
tableau
// Par facilit, la cration des nuds textuels se fera dans la
boucle
var languages = [
{ t: 'JavaScript',
d: 'JavaScript est un langage de programmation de scripts
principalement utilis dans les pages web interactives mais aussi
cot serveur.' },
{ t: 'JScript',
d: 'JScript est le nom gnrique de plusieurs
implmentations d\'ECMAScript 3 cres par Microsoft.' },
{ t: 'ActionScript',
d: 'ActionScript est le langage de programmation utilis au
sein d\'applications clientes (Adobe Flash, Adobe Flex) et serveur
(Flash media server, JRun, Macromedia Generator).' },
{ t: 'EX4',
d: 'ECMAScript for XML (E4X) est une extension XML au
langage ECMAScript.' }
];
// On cre le paragraphe
var paragraph
= document.createElement('p');
var paragraphText = document.createTextNode('Langages bass sur
ECMAScript :');
paragraph.appendChild(paragraphText);
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
121/378
122/378
defList.appendChild(defTerm);
defList.appendChild(defDefn);
t: 'Terme',
d: 'Dfinition'}
Essayer !
Crer une liste de dfinitions (<dl>) n'est pas plus compliqu qu'une liste puces normale, la seule chose qui diffre est que
<dt> et <dd> sont ajouts conjointement au sein de la boucle.
Quatrime exercice
nonc
Un rien plus cors quoique. Ici, la difficult rside dans le nombre important d'lments imbriquer les uns dans les autres. Si
vous procdez mthodiquement, vous avez peu de chance de vous planter.
Code : HTML
<div id="divTP4">
<form enctype="multipart/form-data" method="post"
action="upload.php">
<fieldset>
<legend>Uploader une image</legend>
<div style="text-align: center">
<label for="inputUpload">Image uploader :</label>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
Corrig
Secret (cliquez pour afficher)
Code : JavaScript
// On cre l'lment conteneur
var mainDiv = document.createElement('div');
mainDiv.id = 'divTP4';
// Cration de
var form
var fieldset
var legend
legendText
var center
la structure du formulaire
= document.createElement('form');
= document.createElement('fieldset');
= document.createElement('legend'),
= document.createTextNode('Uploader une image');
= document.createElement('div');
form.action = 'upload.php';
form.enctype = 'multipart/form-data';
form.method = 'post';
center.setAttribute('style', 'text-align: center');
legend.appendChild(legendText);
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
123/378
124/378
fieldset.appendChild(legend);
fieldset.appendChild(center);
form.appendChild(fieldset);
// Cration des
var label =
labelText =
var input =
var br =
var submit =
champs
document.createElement('label'),
document.createTextNode('Image uploader :');
document.createElement('input');
document.createElement('br');
document.createElement('input');
input.type = 'file';
input.id
= 'inputUpload';
input.name = input.id;
submit.type = 'submit';
submit.value = 'Envoyer';
label.htmlFor = 'inputUpload';
label.appendChild(labelText);
center.appendChild(label);
center.appendChild(input);
center.appendChild(br);
center.appendChild(br.cloneNode(false)); // On clone, pour mettre
un deuxime <br />
center.appendChild(submit);
// On insre le formulaire dans mainDiv
mainDiv.appendChild(form);
// On insre mainDiv dans le <body>
document.body.appendChild(mainDiv);
Essayer !
Comme il y a beaucoup d'lments crer, pourquoi ne pas diviser le script en deux : la structure du formulaire, et les champs.
C'est plus propre, et on s'y retrouve mieux.
Conclusion des TP
Il est trs probable que vous n'ayez pas organis votre code comme dans les corrections, ou que vous n'ayez pas utilis les
mmes ides, comme utiliser un tableau, ou mme un tableau d'objets. Votre code est certainement bon, mais retenez une chose :
essayez d'avoir un code clair et propre, tout en tant facile comprendre, cela vous simplifiera la tche !
En rsum
Une fois qu'on a accd un lment, on peut naviguer vers d'autres lments avec parentNode,
previousSibling et nextSibling, ainsi que rcuprer des informations sur le nom des lments et leur contenu.
Pour ajouter un lment, il faut d'abord le crer, puis lui adjoindre des attributs et enfin l'insrer l'endroit voulu au sein
du document.
Outre le passage par valeur , le Javascript possde un passage par rfrence qui est frquent lorsqu'on manipule le
DOM. C'est cette histoire de rfrence qui nous oblige utiliser une mthode telle que cloneNode() pour dupliquer
un lment. En effet, copier la variable qui pointe vers cet lment ne sert rien.
Si appendChild() est particulirement pratique, insertBefore() l'est tout autant pour insrer un lment avant
un autre. Crer une fonction insertAfter() est assez simple et peut faire gagner du temps.
125/378
Questionnaire rcapitulatif
Insrer des lments
Modifier un tableau
Remplacer un lment par un autre
Supprimer les balises <br />
Supprimer tous les enfants
126/378
Les vnements
Aprs l'introduction au DOM, il est temps d'approfondir ce domaine en abordant les vnements en Javascript. Au cours de ce
chapitre, nous tudierons l'utilisation des vnements sans le DOM, avec le DOM-0 (invent par Netscape) puis avec le DOM-2.
Nous verrons comment mettre en place ces vnements, les utiliser, modifier leur comportement, etc.
Aprs ce chapitre, vous pourrez d'ores-et-dj commencer interagir avec l'utilisateur, vous permettant ainsi de crer des pages
web interactives capables de ragir diverses actions effectues soit par le visiteur, soit par le navigateur.
La thorie
Liste des vnements
Il existe de nombreux vnements, tous plus ou moins utiles. Voici la liste des vnements principaux, ainsi que les actions
effectuer pour qu'ils se dclenchent :
Nom de l'vnement
click
dblclick
mouseover
mouseout
mousedown
mouseup
mousemove
keydown
keyup
keypress
focus
blur
change
Changer la valeur d'un lment spcifique aux formulaires (input, checkbox, etc.)
select
Il a t dit prcdemment que les vnements mousedown et mouseup se dclenchaient avec le bouton gauche de la
souris. Ceci n'est pas tout fait exact, ces deux vnements peuvent se dclencher avec d'autres boutons de la souris
comme le clic de la molette ou le bouton droit. Cependant, cela ne fonctionne pas avec tous les navigateurs comme
Firefox qui a choisi de bloquer cette possibilit. L'utilisation de ces deux vnements se limite donc gnralement au
bouton gauche de la souris.
Toutefois, ce n'est pas tout, il existe aussi deux vnements spcifiques l'lment <form>, que voici :
127/378
Nom de l'vnement Action pour le dclencher
submit
reset
Envoyer le formulaire
Rinitialiser le formulaire
Tout cela est pour le moment trs thorique, nous ne faisons que vous lister quelques vnements existants, mais nous allons
rapidement apprendre les utiliser aprs un dernier petit passage concernant ce qu'on appelle le focus.
La pratique
Utiliser les vnements
Bien, maintenant que vous avez vu le ct thorique (et barbant) des vnements, nous allons pouvoir passer un peu la
pratique. Toutefois, dans un premier temps, il n'est que question de vous faire dcouvrir quoi sert tel ou tel vnement et
comment il ragit, nous allons donc voir comment les utiliser sans le DOM, ce qui est considrablement plus limit.
Bien, commenons par l'vnement click sur un simple <span> :
Code : HTML
<span onclick="alert('Hello !');">Cliquez-moi !</span>
Essayer !
Comme vous pouvez le constater, il suffit de cliquer sur le texte pour que la bote de dialogue s'affiche. Afin d'obtenir ce rsultat
nous avons ajout notre <span> un attribut contenant les deux lettres on et le nom de notre vnement click ; nous
obtenons donc onclick .
Cet attribut possde une valeur qui est un code Javascript, vous pouvez y crire quasiment tout ce que vous souhaitez, mais
tout doit tenir entre les guillemets de l'attribut.
Le mot-cl this
Ce mot-cl n'est, normalement, pas cens vous servir ds maintenant, cependant il est toujours bon de le connatre pour les
vnements. Il s'agit d'une proprit pointant sur l'objet actuellement en cours d'utilisation. Donc, si vous faites appel ce motcl lorsqu'un vnement est dclench, l'objet point sera l'lment qui a dclench l'vnement. Exemple :
Code : HTML
<span onclick="alert('Voici le contenu de l\'lment que vous avez
cliqu :\n\n' + this.innerHTML);">Cliquez-moi !</span>
128/378
Essayer !
Ce mot-cl ne vous servira, dans l'immdiat, que pour l'utilisation des vnements sans le DOM ou avec le DOM-1. Si
vous tentez de vous en servir avec le DOM-2 vous risquez alors d'avoir quelques problmes avec Internet Explorer !
Nous tudierons une solution plus loin.
Essayer !
Comme vous pouvez le constater, lorsque vous cliquez sur l'input, celui-ci possde le focus : il excute donc l'vnement et
affiche alors un texte diffrent vous demandant d'appuyer sur votre touche de tabulation. L'appui sur la touche de tabulation
permet de faire passer le focus l'lment suivant. En clair, en appuyant sur cette touche vous faites perdre le focus l'input,
ce qui dclenche l'vnement blur (qui dsigne la perte du focus) et fait passer le focus sur le lien qui affiche alors son
message grce son vnement focus.
Essayer !
Si vous avez essay le code, vous avez srement remarqu que la fonction alert() a bien fonctionn, mais qu'aprs vous
avez t redirig vers le Site du Zro, or on souhaite bloquer cette redirection. Pour cela, il suffit juste d'ajouter le code return
false; dans notre vnement click :
Code : HTML
<a href="http://www.siteduzero.com" onclick="alert('Vous avez cliqu
!'); return false;">Cliquez-moi !</a>
Essayer !
129/378
Ici, le return false; sert juste bloquer l'action par dfaut de l'vnement qui le dclenche.
noter que l'utilisation de return true; permet de faire fonctionner l'vnement comme si de rien n'tait. En clair,
comme si on n'utilisait pas de return false;
Cela peut avoir son utilit si vous utilisez, par exemple, la fonction confirm() dans votre vnement.
Nous vous dconseillons fortement de faire cela ! Si vous le faites quand mme, ne venez pas dire que vous avez appris
le Javascript grce ce cours, ce serait la honte pour nous !
Plus srieusement, il s'agit d'une vieille mthode qui permet d'insrer du Javascript directement dans l'attribut href de votre lien
juste en ajoutant javascript: au dbut de l'attribut. Cette technique est maintenant obsolte et nous serions dus de vous
voir l'utiliser, nous vous en dconseillons donc trs fortement l'utilisation et vous proposons mme une mthode alternative :
Code : HTML
<a href="#" onclick="alert('Vous avez cliqu !'); return
false;">Cliquez-moi !</a>
Essayer !
Concrtement, qu'est-ce qui change ? On a tout d'abord remplac l'immonde javascript: par un dise (#) puis on a mis notre
code Javascript dans l'vnement appropri (click). Par ailleurs, on libre l'attribut href, ce qui nous permet, si besoin, de
laisser un lien pour ceux qui n'activent pas le Javascript ou bien encore pour ceux qui aiment bien ouvrir leurs liens dans de
nouveaux onglets.
OK, j'ai compris, mais pourquoi un return false; ?
Tout simplement parce que le dise redirige tout en haut de la page Web, ce qui n'est pas ce que l'on souhaite. On bloque donc
cette redirection avec notre petit bout de code.
Vous savez maintenant que l'utilisation de javascript: dans les liens est prohibe et c'est dj une bonne chose.
Cependant, gardez bien l'esprit que l'utilisation d'un lien uniquement pour le dclenchement d'un vnement click
n'est pas une bonne chose, prfrez plutt l'utilisation d'une balise <button> laquelle vous aurez retir le style CSS.
La balise <a>, elle, est conue pour rediriger vers une page Web et non pas pour servir exclusivement de dclencheur !
Le DOM-0
Cette interface est vieille mais n'est pas forcment dnue d'intrt. Elle reste trs pratique pour crer des vnements et peut
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
130/378
Essayer !
Alors, voyons par tapes ce que nous avons fait dans ce code :
On rcupre tout d'abord l'lment HTML dont l'ID est clickme ;
On accde ensuite la proprit onclick laquelle on assigne une fonction anonyme ;
Dans cette mme fonction, on fait un appel la fonction alert() avec un texte en paramtre.
Comme vous le voyez, on dfinit maintenant les vnements non plus dans le code HTML mais directement en Javascript.
Chaque vnement standard possde donc une proprit dont le nom est, nouveau, prcd par les deux lettres on . Cette
proprit ne prend plus pour valeur un code Javascript brut, mais soit le nom d'une fonction, soit une fonction anonyme. Bref,
dans tous les cas, il faut lui fournir une fonction qui contiendra le code excuter en cas de dclenchement de l'vnement.
Concernant la suppression d'un vnement avec le DOM-0, il suffit tout simplement de lui attribuer une fonction anonyme vide :
Code : JavaScript
element.onclick = function() {};
Voil tout pour les vnements DOM-0, nous pouvons maintenant passer au cur des vnements : le DOM-2 et l'objet Event.
Le DOM-2
Nous y voici enfin ! Alors, tout d'abord, pourquoi le DOM-2 et non pas le DOM-0 voire pas de DOM du tout ? Concernant la
mthode sans le DOM, c'est simple : on ne peut pas y utiliser l'objet Event qui est pourtant une mine d'informations sur
l'vnement dclench. Il est donc conseill de mettre cette mthode de ct ds maintenant (nous l'avons enseigne juste pour
que vous sachiez la reconnatre).
En ce qui concerne le DOM-0, il a deux problmes majeurs : il est vieux, et il ne permet pas de crer plusieurs fois le mme
vnement.
Le DOM-2, lui, permet la cration multiple d'un mme vnement et gre aussi l'objet Event. Autrement dit, le DOM-2 c'est bien,
mangez-en !
En clair, il faut constamment utiliser le DOM-2 ?
Non, pas vraiment. Autant la technique sans le DOM est bannir, autant l'utilisation du DOM-0 est largement possible, tout
dpend de votre code.
D'ailleurs, dans la majorit des cas, vous choisirez le DOM-0 pour sa simplicit d'utilisation et sa rapidit de mise en place. Ce
n'est, gnralement, que lorsque vous aurez besoin de crer plusieurs vnements d'un mme type (click, par exemple) que
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
131/378
Essayer !
Concrtement, qu'est-ce qui change par rapport au DOM-0 ? Alors tout d'abord nous n'utilisons plus une proprit mais une
mthode nomme addEventListener() (qui ne fonctionne pas sous IE8 et antrieur, mais nous en reparlerons par la suite),
et qui prend trois paramtres :
Le nom de l'vnement (sans les lettres on ) ;
La fonction excuter ;
Un boolen pour spcifier si l'on souhaite utiliser la phase de capture ou bien celle de bouillonnement. Nous expliquerons
ce concept un peu plus tard dans ce chapitre. Sachez simplement que l'on utilise gnralement la valeur false pour ce
paramtre.
Une petite explication s'impose pour ceux qui n'arriveraient ventuellement pas comprendre le code prcdent : nous avons bel
et bien utilis la mthode addEventListener(), elle est simplement crite sur trois lignes :
La premire ligne contient l'appel la mthode addEventListener(), le premier paramtre, et l'initialisation de la
fonction anonyme pour le deuxime paramtre ;
La deuxime ligne contient le code de la fonction anonyme ;
La troisime ligne contient l'accolade fermante de la fonction anonyme, puis le troisime paramtre.
132/378
Comme indiqu plus haut, le DOM-2 permet la cration multiple d'vnements identiques pour un mme lment, ainsi, vous
pouvez trs bien faire ceci :
Code : HTML
<span id="clickme">Cliquez-moi !</span>
<script>
var element = document.getElementById('clickme');
// Premier vnement click
element.addEventListener('click', function() {
alert("Et de un !");
}, false);
// Deuxime vnement click
element.addEventListener('click', function() {
alert("Et de deux !");
}, false);
</script>
Essayer !
Si vous avez excut ce code, vous avez peut-tre eu les vnements dclenchs dans l'ordre de cration, cependant ce ne sera
pas forcment le cas chaque essai. En effet, l'ordre de dclenchement est un peu alatoire
Venons-en maintenant la suppression des vnements ! Celle-ci s'opre avec la mthode removeEventListener() et se
fait de manire trs simple :
Code : JavaScript
element.addEventListener('click', myFunction, false); // On cre
l'vnement
element.removeEventListener('click', myFunction, false); // On
supprime l'vnement en lui repassant les mmes paramtres
Toute suppression d'vnement avec le DOM-2 se fait avec les mmes paramtres utiliss lors de sa cration ! Cependant, cela
ne fonctionne pas aussi facilement avec les fonctions anonymes ! Tout vnement DOM-2 cr avec une fonction anonyme est
particulirement complexe supprimer, car il faut possder une rfrence vers la fonction concerne, ce qui n'est gnralement
pas le cas avec une fonction anonyme.
133/378
// On cre l'vnement
element.attachEvent('onclick', function() {
alert('Tadaaaam !');
});
// On supprime l'vnement en lui repassant les mmes paramtres
element.detachEvent('onclick', function() {
alert('Tadaaaam !');
});
Internet Explorer, partir de sa neuvime version, supporte les mthodes standards. En revanche, pour les versions antrieures il
vous faudra jongler entre les mthodes standards et les mthodes de IE. Gnralement, on utilise un code de ce genre pour grer
la compatibilit entre navigateurs :
Code : JavaScript
function addEvent(element, event, func) {
if (element.addEventListener) { // Si notre lment possde la
mthode addEventListener()
element.addEventListener(event, func, false);
} else { // Si notre lment ne possde pas la mthode
addEventListener()
element.attachEvent('on' + event, func);
}
}
addEvent(element, 'click', function() {
// Votre code
});
Ces deux phases sont deux tapes distinctes de l'excution d'un vnement. La premire, la capture (capture en anglais),
s'excute avant le dclenchement de l'vnement, tandis que la deuxime, le bouillonnement (bubbling en anglais), s'excute
aprs que l'vnement a t dclench. Toutes deux permettent de dfinir le sens de propagation des vnements.
Mais qu'est-ce que la propagation d'un vnement ? Pour expliquer cela, prenons un exemple avec ces deux lments HTML :
Code : HTML
<div>
<span>Du texte !</span>
</div>
134/378
Si nous attribuons une fonction l'vnement click de chacun de ces deux lments et que l'on clique sur le texte, quel
vnement va se dclencher en premier votre avis ? Bonne question n'est-ce pas ?
Notre rponse se trouve dans les phases de capture et de bouillonnement. Si vous dcidez d'utiliser la capture, alors l'vnement
du <div> se dclenchera en premier puis viendra ensuite l'vnement du <span>. En revanche, si vous utilisez le
bouillonnement, ce sera d'abord l'vnement du <span> qui se dclenchera, puis viendra par la suite celui du <div>.
Voici un petit code qui met en pratique l'utilisation de ces deux phases :
Code : HTML
<div id="capt1">
<span id="capt2">Cliquez-moi pour la phase de capture.</span>
</div>
<div id="boul1">
<span id="boul2">Cliquez-moi pour la phase de
bouillonnement.</span>
</div>
<script>
var capt1
capt2
boul1
boul2
=
=
=
=
document.getElementById('capt1'),
document.getElementById('capt2'),
document.getElementById('boul1'),
document.getElementById('boul2');
capt1.addEventListener('click', function() {
alert("L'vnement du div vient de se dclencher.");
}, true);
capt2.addEventListener('click', function() {
alert("L'vnement du span vient de se dclencher.");
}, true);
boul1.addEventListener('click', function() {
alert("L'vnement du div vient de se dclencher.");
}, false);
boul2.addEventListener('click', function() {
alert("L'vnement du span vient de se dclencher.");
}, false);
</script>
Essayer !
Et pour finir, un lien vers la spcification du W3C concernant ces phases si vous avez envie d'aller plus loin. Il est conseill de
regarder ce lien ne serait-ce que pour voir le schma fourni qui explique bien le concept de ces phases.
Du ct de la pratique
Bien, vous savez maintenant quoi servent ces deux phases et pourtant, mme si en thorie ce systme se rvle utile, en
pratique vous ne vous en servirez quasiment jamais pour la simple et bonne raison que la mthode attachEvent() d'Internet
Explorer ne gre que la phase de bouillonnement, ce qui explique que l'on mette gnralement le dernier paramtre de
addEventListener() false.
Autre chose, les vnements sans le DOM ou avec le DOM-0 ne grent, eux aussi, que la phase de bouillonnement.
Cela dit, ne vous en faites pas, vous n'avez pas appris a en vain. Il est toujours bon de savoir cela, la fois pour la
connaissance globale du Javascript, mais aussi pour comprendre ce que vous faites quand vous codez.
L'objet Event
Maintenant que nous avons vu comment crer et supprimer des vnements, nous pouvons passer l'objet Event !
135/378
Il est important de prciser que l'objet Event peut se rcuprer dans un argument autre que e ! Vous pouvez trs bien le
rcuprer dans un argument nomm test, hello, ou autre Aprs tout, l'objet Event est tout simplement pass en rfrence
l'argument de votre fonction, ce qui vous permet de choisir le nom que vous souhaitez.
Concernant Internet Explorer (dans toutes ses versions antrieures la neuvime), si vous souhaitez utiliser le DOM-0
vous constaterez que l'objet Event n'est accessible qu'en utilisant window.event, ce qui signifie qu'il n'est pas
ncessaire (pour IE bien entendu) d'utiliser un argument dans la fonction excute par l'vnement. A contrario , si
vous utilisez le DOM-2, vous n'tes pas obligs d'utiliser window.event.
Afin de garder la compatibilit avec les autres navigateurs, on utilisera gnralement ce code dans la fonction excute
par l'vnement : e = e || window.event;.
136/378
Comme il y a toujours un problme quelque part, voil qu'Internet Explorer (versions antrieures la version 9) ne supporte pas
cette proprit. Ou plutt, il la supporte sa manire avec la proprit srcElement. Voici le mme code que prcdemment
mais compatible avec tous les navigateurs (dont IE) :
Code : HTML
<span id="clickme">Cliquez-moi !</span>
<script>
function addEvent(element, event, func) { // On rutilise notre
fonction de compatibilit pour les vnements DOM-2
if (element.addEventListener) {
element.addEventListener(event, func, false);
} else {
element.attachEvent('on' + event, func);
}
}
var clickme = document.getElementById('clickme');
addEvent(clickme, 'click', function(e) {
var target = e.target || e.srcElement; // Si vous avez
oubli cette spcificit de l'oprateur OU, allez voir le chapitre
des conditions
target.innerHTML = 'Vous avez cliqu !';
});
</script>
Essayer !
noter qu'ici nous avons fait un code compatible pour Internet Explorer parce que le but tait de grer la compatibilit,
mais pour le reste des autres codes nous ne le ferons que si cela s'avre ncessaire. Il vaut donc mieux avoir un
navigateur jour pour pouvoir tester tous les codes de ce cours.
Eh bien non ! Pour expliquer cela de faon simple, certains vnements appliqus un lment parent peuvent se propager d'euxmmes aux lments enfants ; c'est le cas des vnements mouseover, mouseout, mousemove, click ainsi que d'autres
vnements moins utiliss. Regardez donc cet exemple pour mieux comprendre :
Code : HTML
<p id="result"></p>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
137/378
<div id="parent1">
Parent
<div id="child1">Enfant N1</div>
<div id="child2">Enfant N2</div>
</div>
<script>
var parent1 = document.getElementById('parent1'),
result = document.getElementById('result');
parent1.addEventListener('mouseover', function(e) {
result.innerHTML = "L'lment dclencheur de l'vnement
\"mouseover\" possde l'ID : " + e.target.id;
}, false);
</script>
Essayer !
En testant cet exemple, vous avez srement remarqu que la proprit target renvoyait toujours l'lment dclencheur de
l'vnement, or nous souhaitons obtenir l'lment sur lequel a t appliqu l'vnement. Autrement dit, on veut connatre
l'lment l'origine de cet vnement, et non pas ses enfants.
La solution est simple : utiliser la proprit currentTarget au lieu de target. Essayez donc par vous-mmes aprs
modification de cette seule ligne, l'ID affich ne changera jamais :
Code : JavaScript
result.innerHTML = "L'lment dclencheur de l'vnement
\"mouseover\" possde l'ID : " + e.currentTarget.id;
Bien que cette proprit semble intressante pour certains cas d'application, il est assez difficile de la mettre en pratique
car Internet Explorer (versions antrieures la version 9) ne la supporte pas et il n'y a pas d'autre possibilit correcte
(mis part avec l'utilisation du mot-cl this avec le DOM-0 ou sans le DOM).
Comme d'habitude, voici un petit exemple pour que vous compreniez bien :
Code : HTML
<div id="position"></div>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
138/378
<script>
var position = document.getElementById('position');
document.addEventListener('mousemove', function(e) {
position.innerHTML = 'Position X : ' + e.clientX + 'px<br
/>Position Y : ' + e.clientY + 'px';
}, false);
</script>
Essayer !
Pas trs compliqu, n'est-ce pas ? Bon, il est possible que vous trouviez l'intrt de ce code assez limit, mais quand vous saurez
manipuler les proprits CSS des lments vous pourrez, par exemple, faire en sorte que des lments HTML suivent votre
curseur. Ce sera dj bien plus sympathique !
Essayer !
Concernant Internet Explorer (toutes versions antrieures la neuvime), il vous faut utiliser les proprits fromElement et
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
139/378
Si nous devions numrer toutes les proprits capables de vous fournir une valeur, il y en aurait trois : keyCode, charCode
et which. Ces proprits renvoient chacune un code ASCII correspondant la touche presse.
Cependant, la proprit keyCode est amplement suffisante dans tous les cas, comme vous pouvez le constater dans l'exemple
qui suit :
Code : HTML
<p>
</p>
<table>
<tr>
<td>keydown</td>
<td id="down"></td>
</tr>
<tr>
<td>keypress</td>
<td id="press"></td>
</tr>
<tr>
<td>keyup</td>
<td id="up"></td>
</tr>
</table>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
140/378
<script>
var field = document.getElementById('field'),
down = document.getElementById('down'),
press = document.getElementById('press'),
up = document.getElementById('up');
document.addEventListener('keydown', function(e) {
down.innerHTML = e.keyCode;
}, false);
document.addEventListener('keypress', function(e) {
press.innerHTML = e.keyCode;
}, false);
document.addEventListener('keyup', function(e) {
up.innerHTML = e.keyCode;
}, false);
</script>
Essayer !
Dans ce cas, il n'existe qu'une seule solution : la mthode fromCharCode(). Elle prend en paramtre une infinit d'arguments.
Cependant, pour des raisons un peu particulires qui ne seront abordes que plus tard dans ce cours, sachez que cette mthode
s'utilise avec le prfixe String., comme suit :
Code : JavaScript
String.fromCharCode(/* valeur */);
Cette mthode est donc conue pour convertir les valeurs ASCII vers des caractres lisibles. Faites donc bien attention
n'utiliser cette mthode qu'avec un vnement keypress afin d'viter d'afficher, par exemple, le caractre d'un code
correspondant la touche Ctrl, cela ne fonctionnera pas !
Pour terminer, voici un court exemple :
Code : JavaScript
String.fromCharCode(84, 101, 115, 116); // Affiche : Test
141/378
Essayer !
C'est simple comme bonjour et a fonctionne sans problme avec tous les navigateurs, que demander de plus ? Enfin, tous les
navigateurs sauf les versions d'Internet Explorer antrieures la neuvime (c'est pnible, hein ?). Pour IE, il va vous falloir utiliser
la proprit returnValue et lui attribuer la valeur false pour bloquer l'action par dfaut :
Code : JavaScript
e.returnValue = false;
Pour avoir un code compatible avec tous les navigateurs, utilisez donc ceci :
Code : JavaScript
e.returnValue = false;
if (e.preventDefault) {
e.preventDefault();
}
Le problme
Plutt que de vous expliquer le problme, nous allons vous le faire constater. Prenez donc ce code HTML ainsi que ce code CSS :
Code : HTML
<div id="myDiv">
<div>Texte 1</div>
<div>Texte 2</div>
<div>Texte 3</div>
<div>Texte 4</div>
</div>
<div id="results"></div>
Code : CSS
#myDiv, #results {
margin: 50px;
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
142/378
}
#myDiv {
padding: 10px;
width: 200px;
text-align: center;
background-color: #000;
}
#myDiv div {
margin: 10px;
background-color: #555;
}
Maintenant, voyons ce que nous souhaitons obtenir. Notre but ici est de faire en sorte de dtecter quand le curseur entre sur
notre lment #myDiv et quand il en ressort. Vous allez donc penser qu'il n'y a rien de plus facile et vous lancer dans un code de
ce genre :
Code : JavaScript
var myDiv = document.getElementById('myDiv'),
results = document.getElementById('results');
myDiv.onmouseover = function() {
results.innerHTML += "Le curseur vient d'entrer.";
};
myDiv.onmouseout = function() {
results.innerHTML += "Le curseur vient de sortir.";
};
Si cela peut vous rassurer, personne ne voit bien d'o cela peut venir au premier coup d'il. En fait, le souci est tout bte et a dj
t fortement voqu au travers de ce chapitre, relisez donc ceci :
Citation
Certains vnements appliqus un lment parent peuvent se propager d'eux-mmes aux lments enfants, c'est le cas des
vnements mouseover, mouseout, mousemove, click ainsi que d'autres vnements moins utiliss.
Voici notre problme : les enfants hritent des proprits des vnements susnomms appliqus aux lments parents. Ainsi,
lorsque vous dplacez votre curseur depuis le <div> #myDiv jusqu' un <div> enfant, vous allez dclencher l'vnement
mouseout sur #myDiv et l'vnement mouseover sur le <div> enfant.
La solution
Afin de pallier ce problme, il existe une solution assez tordue. Vous souvenez-vous de la proprit relatedTarget aborde
dans ce chapitre ? Son but va tre de dtecter quel est l'lment vers lequel le curseur se dirige ou de quel lment il provient.
Ainsi, nous avons deux cas de figure :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
143/378
Dans le cas de l'vnement mouseover, nous devons dtecter la provenance du curseur. Si le curseur vient d'un enfant
de #myDiv alors le code de l'vnement ne devra pas tre excut. S'il provient d'un lment extrieur #myDiv alors
l'excution du code peut s'effectuer.
Dans le cas de mouseout, le principe est similaire, si ce n'est que l nous devons dtecter la destination du curseur.
Dans le cas o la destination du curseur est un enfant de #myDiv alors le code de l'vnement n'est pas excut, sinon il
s'excutera sans problme.
Mettons cela en pratique avec l'vnement mouseover pour commencer. Voici le code d'origine :
Code : JavaScript
myDiv.onmouseover = function() {
results.innerHTML += "Le curseur vient d'entrer.";
};
Il nous faut maintenant obtenir l'lment de provenance. Puisque relatedTarget n'est pas support par les vieilles versions
d'Internet Explorer, nous allons devoir ruser un peu :
Code : JavaScript
myDiv.onmouseover = function(e) {
e = e || window.event; // Compatibilit IE
var relatedTarget = e.relatedTarget || e.fromElement; // Idem
results.innerHTML += "Le curseur vient d'entrer.";
};
Maintenant, il nous faut savoir si l'lment en question est un enfant direct de myDiv ou non. La solution consiste remonter
tout le long de ses lments parents jusqu' tomber soit sur myDiv, soit sur l'lment <body> qui dsigne l'lment HTML le
plus haut dans notre document. Il va donc nous falloir une boucle while :
Code : JavaScript
myDiv.onmouseover = function(e) {
e = e || window.event; // Compatibilit IE
var relatedTarget = e.relatedTarget || e.fromElement; // Idem
while (relatedTarget != myDiv && relatedTarget.nodeName !=
'BODY') {
relatedTarget = relatedTarget.parentNode;
}
results.innerHTML += "Le curseur vient d'entrer.";
};
Ainsi, nous retrouverons dans notre variable relatedTarget le premier lment trouv qui correspond nos critres, donc
soit myDiv, soit <body>. Il nous suffit alors d'insrer une condition qui excutera le code de notre vnement uniquement
dans le cas o la variable relatedTarget ne pointe pas sur l'lment myDiv :
Code : JavaScript
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
144/378
myDiv.onmouseover = function(e) {
e = e || window.event; // Compatibilit IE
var relatedTarget = e.relatedTarget || e.fromElement; // Idem
while (relatedTarget != myDiv && relatedTarget.nodeName !=
'BODY') {
relatedTarget = relatedTarget.parentNode;
}
if (relatedTarget != myDiv) {
results.innerHTML += "Le curseur vient d'entrer.";
}
};
Cependant, il reste encore un petit cas de figure qui n'a pas t gr et qui peut tre source de problmes ! Comme vous le savez,
la balise <body> ne couvre pas forcment la page Web complte de votre navigateur, ce qui fait que votre curseur peut provenir
d'un lment situ encore plus haut que la balise <body>. Cet lment correspond la balise <html> soit l'lment
document en Javascript , il nous faut donc faire une petite modification afin de bien prciser que si le curseur provient de
document il ne peut forcment pas provenir de myDiv :
Code : JavaScript
myDiv.onmouseover = function(e) {
e = e || window.event; // Compatibilit IE
var relatedTarget = e.relatedTarget || e.fromElement; // Idem
while (relatedTarget != myDiv && relatedTarget.nodeName != 'BODY' &&
relatedTarget != document) {
relatedTarget = relatedTarget.parentNode;
}
if (relatedTarget != myDiv) {
results.innerHTML += "Le curseur vient d'entrer.";
}
};
Voil ! Maintenant, notre vnement mouseover fonctionne comme nous le souhaitions ! Rassurez-vous, vous avez fait le plus
gros, il ne nous reste plus qu' adapter un peu le code pour l'vnement mouseout. Cet vnement va utiliser le mme code que
celui de mouseover deux choses prs :
Le texte afficher n'est pas le mme ;
Nous n'utilisons plus fromElement mais toElement, car nous souhaitons l'lment de destination.
145/378
}
if (relatedTarget != myDiv) {
results.innerHTML += "Le curseur vient de sortir.<br />";
}
};
Enfin, nous avons termin ! Il est grand temps d'essayer le code complet !
L'tude de ce problme tait quelque peu avance par rapport vos connaissances actuelles, sachez que vous n'tes pas obligs
de retenir la solution. Retenez cependant qu'elle existe et que vous pouvez la trouver ici, dans ce chapitre, car ce genre de soucis
peut tre trs embtant dans certains cas, notamment quand il s'agit de faire des animations.
En rsum
Les vnements sont utiliss pour appeler une fonction partir d'une action produite ou non par l'utilisateur.
Diffrents vnements existent pour dtecter certaines actions comme le clic, le survol, la frappe au clavier et le contrle
des champs de formulaires.
Le DOM-0 est l'ancienne manire de capturer des vnements. Le DOM-2 introduit l'objet Event et la fameuse mthode
addEventListener(). Il faudra faire attention, car Internet Explorer ne reconnat que la mthode
attachEvent().
L'objet Event permet de rcolter toutes sortes d'informations se rapportant l'vnement dclench : son type, depuis
quel lment il a t dclench, la position du curseur, les touches frappes Il est aussi possible de bloquer l'action
d'un vnement avec preventDefault().
Parfois, un vnement appliqu sur un parent se propage ses enfants. Cet hritage des vnements peut provoquer des
comportements inattendus.
146/378
Les formulaires
Aprs l'tude des vnements, il est temps de passer aux formulaires ! Ici commence l'interaction avec l'utilisateur grce aux
nombreuses proprits et mthodes dont sont dots les lments HTML utiliss dans les formulaires.
Il s'agit cette fois d'un trs court chapitre, cela vous changera un peu du bourrage de crne habituel !
Les proprits
Les formulaires sont simples utiliser, cependant il faut d'abord mmoriser quelques proprits de base.
Comme vous le savez dj, il est possible d'accder n'importe quelle proprit d'un lment HTML juste en tapant son nom, il
en va donc de mme pour des proprits spcifiques aux lments d'un formulaire comme value, disabled, checked, etc.
Nous allons voir ici comment utiliser ces proprits spcifiques aux formulaires.
Essayer !
Alors par contre, une petite prcision ! Cette proprit s'utilise aussi avec un lment <textarea> ! En effet, en HTML, on
prend souvent l'habitude de mettre du texte dans un <textarea> en crivant :
Code : HTML
<textarea>Et voil du texte !</textarea>
Du coup, en Javascript, on est souvent tent d'utiliser innerHTML pour rcuprer le contenu de notre <textarea>,
cependant cela ne fonctionne pas : il faut bien utiliser value la place !
147/378
Il n'est probablement pas ncessaire de vous expliquer comment fonctionne la proprit checked avec une checkbox, il suffit
d'oprer de la mme manire qu'avec la proprit disabled. En revanche, mieux vaut dtailler son utilisation avec les boutons
de type radio. Chaque bouton radio coch se verra attribuer la valeur true sa proprit checked, il va donc nous falloir
utiliser une boucle for pour vrifier quel bouton radio a t slectionn :
Code : HTML
<label><input type="radio" name="check"
1</label><br />
<label><input type="radio" name="check"
2</label><br />
<label><input type="radio" name="check"
3</label><br />
<label><input type="radio" name="check"
4</label>
<br /><br />
<input type="button" value="Afficher la
onclick="check();" />
<script>
function check() {
var inputs = document.getElementsByTagName('input'),
inputsLength = inputs.length;
for (var i = 0 ; i < inputsLength ; i++) {
if (inputs[i].type == 'radio' && inputs[i].checked) {
alert('La case coche est la n'+ inputs[i].value);
}
}
}
</script>
Essayer !
Voil donc pour les boutons radio, le principe est simple, il suffit juste d'y penser !
148/378
list.addEventListener('change', function() {
// On affiche le contenu de l'lment <option> cibl par la
proprit selectedIndex
alert(list.options[list.selectedIndex].innerHTML);
}, true);
</script>
Essayer !
Dans le cadre d'un <select> multiple, la proprit selectedIndex retourne l'index du premier lment slectionn
.
Maintenant revenons sur deux vnements : submit et reset, encore les mmes noms ! Il n'y a srement pas besoin de vous
expliquer quand l'un et l'autre se dclenchent, cela parat vident. Cependant, il est important de prciser une chose : envoyer un
formulaire avec la mthode submit() du Javascript ne dclenchera jamais l'vnement submit ! Mais dans le doute, voici un
exemple complet dans le cas o vous n'auriez pas tout compris :
Code : HTML
<form id="myForm">
<input type="text" value="Entrez un texte" />
<br /><br />
<input type="submit" value="Submit !" />
<input type="reset" value="Reset !" />
</form>
<script>
var myForm = document.getElementById('myForm');
myForm.addEventListener('submit', function(e) {
alert('Vous avez envoy le formulaire !\n\nMais celui-ci a t
bloqu pour que vous ne changiez pas de page.');
e.preventDefault();
}, true);
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
149/378
myForm.addEventListener('reset', function(e) {
alert('Vous avez rinitialis le formulaire !');
}, true);
</script>
Essayer !
Essayer !
Dans le mme genre, il existe la mthode select() qui, en plus de donner le focus l'lment, slectionne le texte de celui-ci si
cela est possible :
Code : HTML
<input id="text" type="text" value="Entrez un texte" />
<br /><br />
<input type="button" value="Slectionner le texte"
onclick="document.getElementById('text').select();" />
Essayer !
Bien sr, cette mthode ne fonctionne que sur des champs de texte comme un <input> de type text ou bien un
<textarea>.
En rsum
La proprit value s'emploie sur la plupart des lments de formulaire pour en rcuprer la valeur.
Les listes droulantes fonctionnent diffremment, puisqu'il faut d'abord rcuprer l'index de l'lment slectionn avec
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
150/378
selectedIndex.
Les mthodes focus() et blur() permettent de donner ou de retirer le focus un lment de formulaire.
Attention l'vnement onchange, car il ne fonctionne pas toujours comme son nom le suggre, en particulier pour les
champs de texte.
151/378
Manipuler le CSS
Le Javascript est un langage permettant de rendre une page Web dynamique du ct du client. Seulement, quand on pense
dynamique , on pense aussi animations . Or, pour faire des animations, il faut savoir accder au CSS et le modifier. C'est ce
que nous allons tudier dans ce chapitre.
Au programme, l'dition du CSS et son analyse. Pour terminer le chapitre, nous tudierons comment raliser un petit systme de
drag & drop : un sujet intressant !
Mais on peut tout aussi bien diter les feuilles de style qui se prsentent de la manire suivante :
Code : CSS
div {
color: red; /* Ici on modifie la couleur du texte de tous les
lments <div> */
}
Il est de bon ton de vous le rappeler : les proprits CSS de l'attribut style sont prioritaires sur les proprits d'une feuille de
style ! Ainsi, dans le code d'exemple suivant, le texte n'est pas rouge mais bleu :
Code : HTML
<style type="text/css">
div {
color: red;
}
</style>
<div style="color:blue;">I'm blue ! DABADIDABADA !</div>
Voil tout pour les rappels sur le CSS. Oui, c'tait trs rapide, mais il suffisait simplement d'insister sur cette histoire de priorit
des styles CSS, parce que a va vous servir !
152/378
Alors comment accder la proprit style de notre lment ? Eh bien de la mme manire que pour accder n'importe quelle
proprit de notre lment :
Code : JavaScript
element.style; // On accde la proprit style de l'lment
element
Une fois que l'on a accd notre proprit, comment modifier les styles CSS ? Eh bien tout simplement en crivant leur nom et
en leur attribuant une valeur, width (pour la largeur) par exemple :
Code : JavaScript
element.style.width = '150px'; // On modifie la largeur de notre
lment 150px
Pensez bien crire l'unit de votre valeur, il est frquent de l'oublier et gnralement cela pose de nombreux problmes
dans un code !
Maintenant, une petite question pour vous : comment accde-t-on une proprit CSS qui possde un nom compos ? En
Javascript, les tirets sont interdits dans les noms des proprits, ce qui fait que ce code ne fonctionne pas :
Code : JavaScript
element.style.background-color = 'blue'; // Ce code ne fonctionne
pas, les tirets sont interdits
La solution est simple : supprimer les tirets et chaque mot suivant normalement un tiret voit sa premire lettre devenir une
majuscule. Ainsi, notre code prcdent doit s'crire de la manire suivante pour fonctionner correctement :
Code : JavaScript
element.style.backgroundColor = 'blue'; // Aprs avoir supprim le
tiret et ajout une majuscule au deuxime mot, le code fonctionne !
Comme vous pouvez le constater, l'dition du CSS d'un lment n'est pas bien complique. Cependant, il y a une limitation de
taille : la lecture des proprits CSS !
Prenons un exemple :
Code : HTML
<style type="text/css">
#myDiv {
background-color: orange;
}
</style>
<div id="myDiv">Je possde un fond orange.</div>
<script>
var myDiv = document.getElementById('myDiv');
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
153/378
Essayer !
Et on n'obtient rien ! Pourquoi ? Parce que notre code va lire uniquement les valeurs contenues dans la proprit style. C'est-
-dire, rien du tout dans notre exemple, car nous avons modifi les styles CSS depuis une feuille de style, et non pas depuis
l'attribut style.
En revanche, en modifiant le CSS avec l'attribut style, on retrouve sans problme la couleur de notre fond :
Code : HTML
<div id="myDiv" style="background-color: orange">Je possde un fond
orange.</div>
<script>
var myDiv = document.getElementById('myDiv');
alert('Selon le Javascript, la couleur de fond de ce DIV est : ' +
myDiv.style.backgroundColor); // On affiche la couleur de fond
</script>
Essayer !
C'est gnant n'est-ce pas ? Malheureusement, on ne peut pas y faire grand-chose partir de la proprit style, pour cela nous
allons devoir utiliser la mthode getComputedStyle() !
Comme vous avez pu le constater, il n'est pas possible de rcuprer les valeurs des proprits CSS d'un lment par le biais de la
proprit style vu que celle-ci n'intgre pas les proprits CSS des feuilles de style, ce qui nous limite normment dans nos
possibilits d'analyse Heureusement, il existe une fonction permettant de remdier ce problme : getComputedStyle() !
Cette fonction va se charger de rcuprer, notre place, la valeur de n'importe quel style CSS ! Qu'il soit dclar dans la proprit
style, une feuille de style ou bien mme encore calcul automatiquement, cela importe peu : getComputedStyle() la
rcuprera sans problme.
Son fonctionnement est trs simple et se fait de cette manire :
Code : HTML
<style type="text/css">
#text {
color: red;
}
</style>
<span id="text"></span>
<script>
var text = document.getElementById('text'),
color = getComputedStyle(text, null).color;
alert(color);
</script>
154/378
Essayer !
Il s'agit en fait d'un argument facultatif qui permet de spcifier une pseudo-classe notre lment, nous n'allons cependant pas
nous y attarder plus longtemps car nous ne nous en servirons pas. En effet, Internet Explorer (versions antrieures la version
9) ne supporte pas l'utilisation de la fonction getComputedStyle() et utilise la place la proprit currentStyle qui,
elle, ne supporte pas l'utilisation des pseudo-classes.
N'y a-t-il rien qui vous choque dans le prcdent paragraphe ? Il a t dit qu'il s'agissait d'un argument facultatif alors que
pourtant on l'a spcifi ! Il ne s'agit pas d'une erreur de notre part, mais c'est tout simplement parce que cette fois c'est Firefox qui
nous embte : il considre cet argument comme tant obligatoire. Ce comportement perdure jusqu' la version 4 de Firefox.
Contient
Contient la largeur complte (width + padding + border) de l'lment.
offsetParent
155/378
Leur utilisation ne se fait pas de la mme manire que n'importe quel style CSS, tout d'abord parce que ce ne sont pas des styles
CSS ! Ce sont juste des proprits (en lecture seule) mises jour dynamiquement qui concernent certains tats physiques d'un
lment.
Pour les utiliser, on oublie la proprit style vu qu'il ne s'agit pas de styles CSS et on les lit directement sur l'objet de notre
lment HTML :
Code : JavaScript
alert(el.offsetHeight); // On affiche la hauteur complte de notre
lment HTML
Faites bien attention : les valeurs contenues dans ces proprits ( part offsetParent) sont exprimes en pixels et
sont donc de type Number, pas comme les styles CSS qui sont de type String et pour lesquelles les units sont
explicitement spcifies (px, cm, em, etc.).
La proprit offsetParent
Concernant la proprit offsetParent, elle contient l'objet de l'lment parent par rapport auquel est positionn votre
lment actuel. C'est bien, mais qu'est-ce que a veut dire ?
Ce que nous allons vous expliquer concerne des connaissances en HTML et en CSS et non pas en Javascript ! Seulement, il est
fort possible que certains d'entre vous ne connaissent pas ce fonctionnement particulier du positionnement absolu, nous
prfrons donc vous le rappeler.
Lorsque vous dcidez de mettre un de vos lments HTML en positionnement absolu, celui-ci est sorti du positionnement par
dfaut des lments HTML et va aller se placer tout en haut gauche de votre page Web, par-dessus tous les autres lments.
Seulement, ce principe n'est applicable que lorsque votre lment n'est pas dj lui-mme plac dans un lment en
positionnement absolu. Si cela arrive, alors votre lment se positionnera non plus par rapport au coin suprieur gauche de la
page Web, mais par rapport au coin suprieur gauche du prcdent lment plac en positionnement absolu, relatif ou fixe .
Ce systme de positionnement est clair ? Bon, nous pouvons alors revenir notre proprit offsetParent ! Si elle existe,
c'est parce que les proprits offsetTop et offsetLeft contiennent le positionnement de votre lment par rapport son
prcdent lment parent et non pas par rapport la page ! Si nous voulons obtenir son positionnement par rapport la page, il
faudra alors aussi ajouter les valeurs de positionnement de son (ses) lment(s) parent(s).
Voici le problme mis en pratique ainsi que sa solution :
Code : HTML
<style type="text/css">
#parent, #child {
position: absolute;
top: 50px; left: 100px;
}
#parent {
width: 200px; height: 200px;
background-color: blue;
}
#child {
width: 50px; height: 50px;
background-color: red;
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
156/378
}
</style>
<div id="parent">
<div id="child"></div>
</div>
<script>
var parent = document.getElementById('parent');
var child = document.getElementById('child');
alert("Sans la fonction de calcul, la position de l'lment enfant
est : \n\n" +
'offsetTop : ' + child.offsetTop + 'px\n' +
'offsetLeft : ' + child.offsetLeft + 'px');
top += element.offsetTop;
left += element.offsetLeft;
} while (element = element.offsetParent); // Tant que
element reoit un offsetParent valide alors on additionne les
valeurs des offsets
return { // On retourne un objet, cela nous permet de
retourner les deux valeurs calcules
top: top,
left: left
};
}
Essayer !
Comme vous pouvez le constater, les valeurs seules de positionnement de notre lment enfant ne sont pas correctes si nous
souhaitons connatre son positionnement par rapport la page et non pas par rapport l'lment parent. Nous sommes
finalement obligs de crer une fonction pour calculer le positionnement par rapport la page.
Concernant cette fonction, nous allons insister sur la boucle qu'elle contient car il est probable que le principe ne soit pas clair
pour vous :
Code : JavaScript
do {
top += element.offsetTop;
left += element.offsetLeft;
} while (element = element.offsetParent);
157/378
<body>
<div id="parent" style="position:absolute; top:200px;
left:200px;">
<div id="child" style="position:absolute; top:100px;
left:100px;"></div>
</div>
</body>
son schma de fonctionnement sera le suivant pour le calcul des valeurs de positionnement de l'lment #child :
La boucle s'excute une premire fois en ajoutant les valeurs de positionnement de l'lment #child nos deux
variables top et left. Le calcul effectu est donc :
Code : JavaScript
top = 0 + 100; // 100
left = 0 + 100; // 100
Ligne 4, on attribue element l'objet de l'lment parent de #child. En gros, on monte d'un cran dans l'arbre DOM.
L'opration est donc la suivante :
Code : JavaScript
element = child.offsetParent; // Le nouvel lment est parent
Toujours ligne 4, element possde une rfrence vers un objet valide (qui est l'lment #parent), la condition est
donc vrifie (l'objet est valu true) et la boucle s'excute de nouveau.
La boucle se rpte en ajoutant cette fois les valeurs de positionnement de l'lment #parent nos variables top et
left. Le calcul effectu est donc :
Code : JavaScript
top = 100 + 200; // 300
left = 100 + 200; // 300
Ligne 4, cette fois l'objet parent de #parent est l'lment <body>. La boucle va donc se rpter avec <body> qui est
un objet valide. Comme nous n'avons pas touch ses styles CSS il ne possde pas de valeurs de positionnement, le
calcul effectu est donc :
Code : JavaScript
top = 300 + 0; // 300
left = 300 + 0; // 300
Ligne 4, <body> a une proprit offsetParent qui est undefined, la boucle s'arrte donc.
Voil tout pour cette boucle ! Son fonctionnement n'est pas bien compliqu mais peut en drouter certains, c'est pourquoi il valait
mieux vous l'expliquer en dtail.
Avant de terminer : pourquoi avoir crit hauteur complte (width + padding + border) dans le tableau ?
Qu'est-ce que a veut dire ?
Il faut savoir qu'en HTML, la largeur (ou hauteur) complte d'un lment correspond la valeur de width + celle du padding +
celle des bordures.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
158/378
la largeur complte de notre lment <div> vaut : 100 (width) + 10 (padding-left) + 10 (padding-right) + 2
(border-left) + 2 (border-right) = 124px.
Et il s'agit bien de la valeur retourne par offsetWidth :
Code : JavaScript
var offsetTest = document.getElementById('offsetTest');
alert(offsetTest.offsetWidth);
Prsentation de l'exercice
Tout d'abord, qu'est-ce que le drag & drop ? Il s'agit d'un systme permettant le dplacement d'lments par un simple
dplacement de souris. Pour faire simple, c'est comme lorsque vous avez un fichier dans un dossier et que vous le dplacez dans
un autre dossier en le faisant glisser avec votre souris.
Et je suis vraiment capable de faire a ?
Bien videmment ! Bon, il faut avoir suivi attentivement le cours et se dmener un peu, mais c'est parfaitement possible, vous en
tes capables !
Avant de se lancer dans le code, listons les tapes de fonctionnement d'un systme de drag & drop :
L'utilisateur enfonce (et ne relche pas) le bouton gauche de sa souris sur un lment. Le drag & drop s'initialise alors en
sachant qu'il va devoir grer le dplacement de cet lment. Pour information, l'vnement utiliser ici est mousedown.
L'utilisateur, tout en laissant le bouton de sa souris enfonc, commence dplacer son curseur, l'lment cibl suit alors
ses mouvements la trace. L'vnement utiliser est mousemove et nous vous conseillons de l'appliquer l'lment
document, nous vous expliquerons pourquoi dans la correction.
L'utilisateur relche le bouton de sa souris. Le drag & drop prend alors fin et l'lment ne suit plus le curseur de la souris.
L'vnement utilis est mouseup.
159/378
Code : CSS
.draggableBox {
position: absolute;
width: 80px; height: 60px;
padding-top: 10px;
text-align: center;
font-size: 40px;
background-color: #222;
color: #CCC;
cursor: move;
}
Correction
Vous avez termin l'exercice ? Nous esprons que vous l'avez russi, mais si ce n'est pas le cas ce n'est pas grave ! Regardez
attentivement la correction, et tout devrait tre plus clair.
Code : JavaScript
(function() { // On utilise une IEF pour ne pas polluer l'espace
global
var storage = {}; // Contient l'objet du div en cours de
dplacement
function addEvent(element, event, func) { // Une fonction pour
grer les vnements sous tous les navigateurs
if (element.attachEvent) {
element.attachEvent('on' + event, func);
} else {
element.addEventListener(event, func, true);
}
}
function init() { // La fonction d'initialisation
var elements = document.getElementsByTagName('div'),
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
160/378
elementsLength = elements.length;
for (var i = 0 ; i < elementsLength ; i++) {
if (elements[i].className === 'draggableBox') {
addEvent(elements[i], 'mousedown', function(e) { //
Initialise le drag & drop
var s = storage;
s.target = e.target || event.srcElement;
s.offsetX = e.clientX - s.target.offsetLeft;
s.offsetY = e.clientY - s.target.offsetTop;
});
addEvent(elements[i], 'mouseup', function() { //
Termine le drag & drop
storage = {};
});
}
}
addEvent(document, 'mousemove', function(e) { // Permet le
suivi du drag & drop
var target = storage.target;
if (target) {
target.style.top = e.clientY - storage.offsetY +
'px';
'px';
}
});
161/378
Dans ce code, nous avons volontairement cach les codes d'ajout d'vnements, car ce qui nous intresse c'est cette boucle et la
condition. Cette boucle couple la mthode getElementsByTagName(), vous l'avez dj vue dans le chapitre sur la
manipulation du code HTML, elle permet de parcourir tous les lments HTML d'un type donn. Dans notre cas, nous
parcourons tous les lments <div>.
chaque lment <div> trouv, on vrifie que sa classe correspond bien .draggableBox. Pourquoi faire cela ? Parce que
si vous ajoutez d'autres lments <div> ils ne seront pas pris en compte sauf si vous leur attribuez la bonne classe, ainsi vous
pouvez utiliser des <div> sans qu'ils soient forcment dplaables.
Comme vous pouvez le voir, ces deux vnements ne font qu'accder la variable storage. quoi nous sert donc cette
variable ? Il s'agit tout simplement d'un objet qui nous sert d'espace de stockage, il permet de mmoriser l'lment actuellement en
cours de dplacement ainsi que la position du curseur par rapport notre lment (nous reviendrons sur ce dernier point plus
tard).
Bref, dans notre vnement mousedown (qui initialise le drag & drop), nous ajoutons l'vnement cibl dans la proprit
storage['target'] puis les positions du curseur par rapport notre lment dans storage['offsetX'] et
storage['offsetY'].
En ce qui concerne notre vnement mouseup (qui termine le drag & drop), on attribue juste un objet vide notre variable
storage, comme a tout est vid !
162/378
Rflchissons ! Si nous appliquons cet vnement l'lment cibl, que va-t-il se passer ? Ds que l'on bougera la souris,
l'vnement se dclenchera et tout se passera comme on le souhaite, mais si je me mets bouger la souris trop rapidement, le
curseur va alors sortir de notre lment avant que celui-ci n'ait eu le temps de se dplacer, ce qui fait que l'vnement ne se
dclenchera plus tant que l'on ne replacera pas notre curseur sur l'lment. La probabilit pour que cela se produise est plus
leve que l'on ne le pense, autant prendre toutes les prcautions ncessaires.
Un autre problme peut aussi surgir : dans notre code actuel, nous ne grons pas le style CSS z-index, ce qui fait que
lorsqu'on dplace le premier lment et que l'on place notre curseur sur un des deux autres lments, le premier lment se
retrouve alors en dessous d'eux. En quoi est-ce un problme ? Eh bien si on a appliqu le mousemove sur notre lment au lieu
du document alors cet vnement ne se dclenchera pas vu que l'on bouge notre curseur sur un des deux autres lments et
non pas sur notre lment en cours de dplacement.
La solution est donc de mettre l'vnement mousemove sur notre document. Vu que cet vnement se propage aux enfants,
nous sommes srs qu'il se dclenchera n'importe quel dplacement du curseur sur la page.
Le reste du code n'est pas bien sorcier :
On utilise une condition qui vrifie qu'il existe bien un indice target dans notre espace de stockage. Si il n'y en a pas
c'est qu'il n'y a aucun drag & drop en cours d'excution.
On assigne notre lment cible (target) ses nouvelles coordonnes par rapport au curseur.
Alors revenons sur un point important du prcdent code : il nous a fallu enregistrer la position du curseur par rapport au coin
suprieur gauche de notre lment ds l'initialisation du drag & drop :
La valeur X
dsigne le dcalage (en pixels) entre les bordures gauche de l'lment et du curseur, la valeur Y fait de mme entre les bordures
suprieures
Pourquoi ? Car si vous ne le faites pas, chaque fois que vous dplacerez votre lment, celui-ci placera son bord suprieur
gauche sous votre curseur et ce n'est clairement pas ce que l'on souhaite.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
163/378
En rsum
Pour modifier les styles CSS d'un lment, il suffit d'utiliser la proprit style. Il ne reste plus qu' accder la bonne
proprit CSS, par exemple : element.style.height = '300px'.
Le nom des proprits composes doit s'crire sans tiret et avec une majuscule pour dbuter chaque mot, l'exception du
premier. Ainsi, border-radius devient borderRadius.
La fonction getComputedStyle() rcupre la valeur de n'importe quelle proprit CSS. C'est utile, car la proprit
style n'accde pas aux proprits dfinies dans la feuille de style.
Les proprits de type offset, au nombre de cinq, permettent de rcuprer des valeurs lies la taille et au
positionnement.
Le positionnement absolu peut poser des problmes. Voil pourquoi il faut savoir utiliser la proprit offsetParent,
combine aux autres proprits offset.
164/378
TP : un formulaire interactif
Nous sommes presque au bout de cette deuxime partie du cours ! Cette dernire aura t trs volumineuse et il se peut que
vous ayez oubli pas mal de choses depuis votre lecture, ce TP va donc se charger de vous rappeler l'essentiel de ce que nous
avons appris ensemble.
Le sujet va porter sur la cration d'un formulaire dynamique. Qu'est-ce nous entendons par formulaire dynamique ? Eh bien, un
formulaire dont une partie des vrifications est effectue par le Javascript, ct client. On peut par exemple vrifier que
l'utilisateur a bien complt tous les champs, ou bien qu'ils contiennent des valeurs valides (si le champ ge ne contient pas
des lettres au lieu de chiffres par exemple).
ce propos, nous allons tout de suite faire une petite prcision trs importante pour ce TP et tous vos codes en Javascript :
Une vrification des informations ct client ne dispensera jamais de faire cette mme vrification ct serveur. Le
Javascript est un langage qui s'excute ct client, or le client peut trs bien modifier son comportement ou bien
carrment le dsactiver, ce qui annulera les vrifications. Bref, continuez faire comme vous l'avez toujours fait sans le
Javascript : faites des vrifications ct serveur !
Prsentation de l'exercice
Faire un formulaire c'est bien, mais encore faut-il savoir quoi demander l'utilisateur. Dans notre cas, nous allons faire simple et
classique : un formulaire d'inscription. Notre formulaire d'inscription aura besoin de quelques informations concernant
l'utilisateur, cela nous permettra d'utiliser un peu tous les lments HTML spcifiques aux formulaires que nous avons vus
jusqu' prsent. Voici les informations rcuprer ainsi que les types d'lments HTML :
Information relever
Sexe
Nom
Prnom
ge
Pseudo
Mot de passe
<select>
Si l'utilisateur souhaite
recevoir des mails
Bien sr, chacune de ces informations devra tre traite afin que l'on sache si le contenu est bon. Par exemple, si l'utilisateur a
bien spcifi son sexe ou bien s'il n'a pas entr de chiffres dans son prnom, etc. Dans notre cas, nos vrifications de contenu ne
seront pas trs pousses pour la simple et bonne raison que nous n'avons pas encore tudi les regex ce stade du cours,
nous nous limiterons donc la vrification de la longueur de la chane ou bien la prsence de certains caractres. Bref, rien
d'incroyable, mais cela suffira amplement car le but de ce TP n'est pas vraiment de vous faire analyser le contenu mais plutt de
grer les vnements et le CSS de votre formulaire.
Voici donc les conditions respecter pour chaque information :
Information relever
Condition respecter
Sexe
Nom
Prnom
ge
165/378
Pseudo
Mot de passe
Si l'utilisateur souhaite
recevoir des mails
Pas de condition
Nous avons choisi de limiter les noms et prnoms deux caractres minimum, mme s'il en existe avec un seul caractre.
Il s'agit ici d'un exemple, libre vous de dfinir vos propres conditions.
Concrtement, l'utilisateur n'est pas cens connatre toutes ces conditions quand il arrive sur votre formulaire, il faudra donc les
lui indiquer avant mme qu'il ne commence entrer ses informations, comme a il ne perdra pas de temps corriger ses fautes.
Pour cela, il va vous falloir afficher chaque condition d'un champ de texte quand l'utilisateur fera une erreur. Pourquoi parlonsnous ici uniquement des champs de texte ? Tout simplement parce que nous n'allons pas dire l'utilisateur Slectionnez votre
sexe alors qu'il n'a qu'une case cocher, cela parat vident.
Autre chose, il faudra aussi faire une vrification complte du formulaire lorsque l'utilisateur aura cliqu sur le bouton de
soumission. ce moment-l, si l'utilisateur n'a pas coch de case pour son sexe on pourra lui dire qu'il manque une information,
pareil s'il n'a pas slectionn de pays.
Vous voil avec toutes les informations ncessaires pour vous lancer dans ce TP. Nous vous laissons concevoir votre propre
code HTML, mais vous pouvez trs bien utiliser celui de la correction si vous le souhaitez.
Correction
Bien, vous avez probablement termin si vous lisez cette phrase. Ou bien vous n'avez pas russi aller jusqu'au bout, ce qui peut
arriver !
166/378
Vous remarquerez que de nombreuses balises <span> possdent une classe nomme .tooltip. Elles contiennent le texte
afficher lorsque le contenu du champ les concernant ne correspond pas ce qui est souhait.
Nous allons maintenant passer au CSS. D'habitude nous ne vous le fournissons pas directement, mais cette fois il fait partie
intgrante de ce TP, donc le voici :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
167/378
168/378
Notez bien les deux classes .correct et .incorrect : elles seront appliques aux <input> de type text et password
afin de bien montrer si un champ est correctement rempli ou non.
Nous pouvons maintenant passer au plus compliqu, le code Javascript :
Code : JavaScript
(function() { // On utilise une IEF pour ne pas polluer l'espace
global
// Fonction de dsactivation de l'affichage des tooltips
function deactivateTooltips() {
var spans = document.getElementsByTagName('span'),
spansLength = spans.length;
for (var i = 0 ; i < spansLength ; i++) {
if (spans[i].className == 'tooltip') {
spans[i].style.display = 'none';
}
}
}
// La fonction ci-dessous permet de rcuprer la tooltip
qui correspond notre input
function getTooltip(element) {
while (element = element.nextSibling) {
if (element.className === 'tooltip') {
return element;
}
}
return false;
}
// Fonctions de vrification du formulaire, elles renvoient
true si tout est OK
var check = {}; // On met toutes nos fonctions dans un objet
littral
check['sex'] = function() {
var sex = document.getElementsByName('sex'),
tooltipStyle = getTooltip(sex[1].parentNode).style;
if (sex[0].checked || sex[1].checked) {
tooltipStyle.display = 'none';
return true;
} else {
tooltipStyle.display = 'inline-block';
return false;
}
};
check['lastName'] = function(id) {
var name = document.getElementById(id),
tooltipStyle = getTooltip(name).style;
if (name.value.length >= 2) {
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
169/378
tooltipStyle.display = 'none';
return true;
} else {
tooltipStyle.display = 'inline-block';
return false;
}
};
// Mise en place des vnements
myForm.onsubmit = function() {
var result = true;
for (var i in check) {
result = check[i](i) && result;
}
if (result) {
alert('Le formulaire est bien rempli.');
}
return false;
};
myForm.onreset = function() {
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
170/378
171/378
Les explications
Les explications vont essentiellement porter sur le code Javascript qui est, mine de rien, plutt long (plus de deux cents lignes de
code, a commence faire pas mal).
Si vous faites cela, vous prenez le risque qu'un utilisateur ayant dsactiv le Javascript ne puisse pas voir les bulles d'aide, ce
qui serait plutt fcheux, non ? Aprs tout, afficher les bulles d'aide par dfaut et les cacher avec le Javascript ne cote pas
grand-chose, autant le faire De plus, nous allons avoir besoin de cette fonction plus tard quand l'utilisateur voudra rinitialiser
son formulaire.
Venons-en donc au code :
Code : JavaScript
function deactivateTooltips() {
var spans = document.getElementsByTagName('span'),
spansLength = spans.length;
for (var i = 0 ; i < spansLength ; i++) {
if (spans[i].className == 'tooltip') {
spans[i].style.display = 'none';
}
}
}
172/378
Est-il vraiment ncessaire de vous expliquer ce code en dtail ? Il ne s'agit que d'un simple parcours de balises comme vous en
avez dj vu. Il est juste important de prciser qu'il y a une condition la ligne 7 qui permet de ne slectionner que les balises
<span> qui ont une classe .tooltip.
Notre fonction prend en argument l'<input> actuellement en cours de traitement. Notre boucle while se charge alors de
vrifier tous les lments suivants notre <input> (d'o l'utilisation du nextSibling). Une fois qu'un lment avec la classe
.tooltip a t trouv, il ne reste plus qu' le retourner.
Alors oui, au premier abord, cette ligne de code ne sert vraiment pas grand-chose, mais en vrit elle a une trs grande utilit :
l'objet cr va nous permettre d'y stocker toutes les fonctions permettant de checker (d'o le nom de l'objet) chaque valeur
entre par l'utilisateur. L'intrt de cet objet est triple :
Nous allons pouvoir excuter la fonction correspondant un champ de cette manire :
check['id_du_champ']();. Cela va grandement simplifier notre code lors de la mise en place des vnements.
Il sera possible d'excuter toutes les fonctions de check juste en parcourant l'objet, ce sera trs pratique lorsque
l'utilisateur cliquera sur le bouton d'inscription et qu'il faudra alors revrifier tout le formulaire.
L'ajout d'un champ de texte et de sa fonction d'analyse devient trs simple si on concentre tout dans cet objet, vous
comprendrez trs rapidement pourquoi !
Nous n'allons pas tudier toutes les fonctions d'analyse, elles se ressemblent beaucoup, nous allons donc uniquement tudier
deux fonctions afin de mettre les choses au clair :
Code : JavaScript
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
173/378
check['login'] = function() {
var login = document.getElementById('login'),
tooltipStyle = getTooltip(login).style;
if (login.value.length >= 4) {
login.className = 'correct';
tooltipStyle.display = 'none';
return true;
} else {
login.className = 'incorrect';
tooltipStyle.display = 'inline-block';
return false;
}
}
Il est trs important que vous constatiez que notre fonction est contenue dans l'index login de l'objet check, l'index n'est rien
d'autre que l'identifiant du champ de texte auquel la fonction appartient. Le code n'est pas bien compliqu : on rcupre
l'<input> et la proprit style de la bulle d'aide qui correspondent notre fonction et on passe l'analyse du contenu.
Si le contenu remplit bien la condition, alors on attribue notre <input> la classe .correct, on dsactive l'affichage de la
bulle d'aide et on retourne true.
Si le contenu ne remplit pas la condition, notre <input> se voit alors attribuer la classe .incorrect et la bulle d'aide est
affiche. En plus de cela, on renvoie la valeur false.
Passons maintenant une deuxime fonction que nous tenions aborder :
Code : JavaScript
check['lastName'] = function(id) {
var name = document.getElementById(id),
tooltipStyle = getTooltip(name).style;
if (name.value.length >= 2) {
name.className = 'correct';
tooltipStyle.display = 'none';
return true;
} else {
name.className = 'incorrect';
tooltipStyle.display = 'inline-block';
return false;
}
};
Cette fonction diffre de la prcdente sur un seul point : elle possde un argument id ! Cet argument sert rcuprer
l'identifiant de l'<input> analyser. Pourquoi ? Tout simplement parce qu'elle va nous servir analyser deux champs de texte
diffrents : celui du nom et celui du prnom. Puisqu'ils ont tous les deux la mme condition, il aurait t stupide de crer deux fois
la mme fonction.
Donc, au lieu de faire appel cette fonction sans aucun argument, il faut lui passer l'identifiant du champ de texte analyser, ce
qui donne deux possibilits :
Code : JavaScript
check['lastName']('lastName');
check['lastName']('firstName');
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
174/378
Cependant, ce fonctionnement pose un problme, car nous tions partis du principe que nous allions faire appel nos fonctions
d'analyse selon le principe suivant :
Code : JavaScript
check['id_du_champ']();
Or, si nous faisons a, cela veut dire que nous ferons aussi appel la fonction check['firstName']() qui n'existe pas
Nous n'allons pas crer cette fonction sinon nous perdrons l'intrt de notre systme d'argument sur la fonction
check['lastName'](). La solution est donc de faire une rfrence de la manire suivante :
Code : JavaScript
check['firstName'] = check['lastName'];
Comme nous l'avons dj fait plus haut, nous n'allons pas prendre la peine de vous expliquer le fonctionnement de cette boucle
et de la condition qu'elle contient, il ne s'agit que de parcourir les <input> et d'agir seulement sur ceux qui sont de type text
ou password.
En revanche, il va falloir des explications sur les lignes 7 9. Les lignes 7 et 9 permettent d'assigner une fonction anonyme
l'vnement keyup de l'<input> actuellement trait. Quant la ligne 8, elle fait appel la fonction d'analyse qui correspond
l'<input> qui a excut l'vnement. Ainsi, si l'<input> #login dclenche son vnement, il appellera alors la fonction
check['login']().
Cependant, un argument est pass chaque fonction d'analyse que l'on excute. Pourquoi ? Eh bien il s'agit de l'argument
ncessaire la fonction check['lastName'](), ainsi lorsque les <input> #lastName et #firstName dclencheront
leur vnement, ils excuteront alors respectivement les lignes de codes suivantes :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
175/378
Code : JavaScript
check['lastName']('lastName');
et
Code : JavaScript
check['firstName']('firstName');
Mais l on passe l'argument toutes les fonctions d'analyse, cela ne pose pas de problme normalement ?
Pourquoi cela en poserait-il un ? Imaginons que l'<input> #login dclenche son vnement, il excutera alors la ligne de
code suivante :
Code : JavaScript
check['login']('login');
Cela fera passer un argument inutile dont la fonction ne tiendra pas compte, c'est tout.
myForm.onsubmit = function() {
var result = true;
for (var i in check) {
result = check[i](i) && result;
}
if (result) {
alert('Le formulaire est bien rempli.');
}
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
176/378
return false;
};
myForm.onreset = function() {
for (var i = 0 ; i < inputsLength ; i++) {
if (inputs[i].type == 'text' || inputs[i].type ==
'password') {
inputs[i].className = '';
}
}
deactivateTooltips();
};
})();
Comme vous pouvez le constater, nous n'avons pas appliqu d'vnements click sur les boutons mais avons directement
appliqu submit et reset sur le formulaire, ce qui est bien plus pratique dans notre cas.
Alors concernant notre vnement submit, celui-ci va parcourir notre tableau check et excuter toutes les fonctions qu'il
contient (y compris celles qui ne sont pas associes un champ de texte comme check['sex']() et
check['country']()). Chaque valeur retourne par ces fonctions est ajoute la variable result, ce qui fait que si
une des fonctions a renvoy false alors result sera aussi false et l'excution de la fonction alert() ne se fera pas.
Concernant notre vnement reset, c'est trs simple : on parcourt les champs de texte, on retire leur classe et ensuite on
dsactive toutes les bulles d'aide grce notre fonction deactivateTooltips().
Voil, ce TP est maintenant termin.
177/378
Les objets
Nous avons vu dans la premire partie du cours un chapitre sur les objets et les tableaux. Ce chapitre en est la suite et permet de
mettre les pieds dans l'univers de la cration et de la modification d'objets en Javascript.
Au programme, vous dcouvrirez comment crer un objet de A Z en lui dfinissant un constructeur, des proprits et des
mthodes ; vous saurez aussi comment modifier un objet natif. S'en suivra alors une manire d'exploiter les objets pour les utiliser
en tant que namespaces et, pour terminer, nous tudierons la modification du contexte d'excution d'une mthode.
Petite problmatique
Le Javascript possde des objets natifs, comme String, Boolean et Array, mais nous permet aussi de crer nos propres
objets, avec leurs propres mthodes et proprits.
Mais quel est l'intrt ?
L'intrt est gnralement une propret de code ainsi qu'une facilit de dveloppement. Les objets sont l pour nous faciliter la
vie, mais leur cration peut prendre du temps.
Rappelez-vous l'exemple des tableaux avec les prnoms :
Code : JavaScript
var myArray = ['Sbastien', 'Laurence', 'Ludovic', 'Pauline',
'Guillaume'];
Ce tableau sert juste stocker les prnoms, rien de plus. Imaginons qu'il faille faire un tableau contenant normment de
donnes, et ce pour chaque personne. Par exemple, pour chaque personne, on aurait les donnes suivantes : prnom, ge, sexe,
parent, travail Comment structurer tout cela ?
Avec une trs grosse dose de motivation, il est possible de raliser quelque chose comme ceci :
Code : JavaScript
var myArray = [
{
nick: 'Sbastien',
age: 23,
sex: 'm',
parent: 'an',
work: 'Javascripteur'
},
{
nick: 'Laurence',
age: 19,
sex: 'f',
parent: 'soeur',
work: 'Sous-officier'
},
// et ainsi de suite
];
178/378
Ce n'est pas encore trop compliqu car les donnes restent relativement simples. Maintenant, pour chaque personne, nous
allons ajouter un tableau qui contiendra ses amis, et pour chaque ami, les mmes donnes. L, c'est dj plus compliqu
Profitons de cette problmatique pour tudier les objets !
Objet constructeur
Nous avons vu que le Javascript nous permettait de crer des objets littraux et nous allons voir maintenant comment crer de
vritables objets qui possdent des proprits et des mthodes tout comme les objets natifs.
Un objet reprsente quelque chose, une ide ou un concept. Ici, suite l'exemple de la famille, nous allons crer un objet appel
Person qui contiendra des donnes, savoir le prnom, l'ge, le sexe, le lien de parent, le travail et la liste des amis (qui sera
un tableau).
L'utilisation de tels objets se fait en deux temps :
1. On dfinit l'objet via un constructeur, cette tape permet de dfinir un objet qui pourra tre rutilis par la suite. Cet objet
ne sera pas directement utilis car nous en utiliserons une copie : on parle alors d'instance.
2. chaque fois que l'on a besoin d'utiliser notre objet, on cre une instance de celui-ci, c'est--dire qu'on le copie .
De manire gnrale on met une majuscule la premire lettre d'un constructeur. Cela permet de mieux le diffrencier
d'une fonction normale et le fait ressembler aux noms des objets natifs qui portent tous une majuscule (Array,
Date, String).
Le code du constructeur va contenir une petite particularit : le mot-cl this. Ce mot-cl fait rfrence l'objet dans lequel il est
excut, c'est--dire ici le constructeur Person. Si on utilise this au sein du constructeur Person, this pointe vers
Person. Grce this, nous allons pouvoir dfinir les proprits de l'objet Person :
Code : JavaScript
function Person(nick, age, sex, parent, work, friends) {
this.nick = nick;
this.age = age;
this.sex = sex;
this.parent = parent;
this.work = work;
this.friends = friends;
}
Les paramtres de notre constructeur (les paramtres de la fonction si vous prfrez) vont tre dtruits la fin de l'excution de
ce dernier, alors que les proprits dfinies par le biais de this vont rester prsentes. Autrement dit, this.nick affecte une
proprit nick notre objet, tandis que le paramtre nick n'est qu'une simple variable qui sera dtruite la fin de l'excution
du constructeur.
179/378
Utilisation de l'objet
L'objet Person a t dfini grce au constructeur qu'il ne nous reste plus qu' utiliser :
Code : JavaScript
// Dfinition de l'objet Person via un constructeur
function Person(nick, age, sex, parent, work, friends) {
this.nick = nick;
this.age = age;
this.sex = sex;
this.parent = parent;
this.work = work;
this.friends = friends;
}
// On cre des variables qui vont contenir une instance de l'objet
Person :
var seb = new Person('Sbastien', 23, 'm', 'an', 'Javascripteur',
[]);
var lau = new Person('Laurence', 19, 'f', 'soeur', 'Sous-officier',
[]);
alert(seb.nick); // Affiche : Sbastien
alert(lau.nick); // Affiche : Laurence
Que s'est-il pass ici ? L'objet Person a t dfini comme nous l'avons vu plus haut. Pour pouvoir utiliser cet objet, on dfinit
une variable qui va contenir une instance de l'objet Person, c'est--dire une copie. Pour indiquer au Javascript qu'il faut utiliser
une instance, on utilise le mot-cl new.
Retenez bien que ce mot-cl new ne signifie pas crer un nouvel objet , mais signifie crer une nouvelle instance de l'objet
, ce qui est trs diffrent puisque dans le deuxime cas on ne fait que crer une instance, une copie, de l'objet initial, ce qui nous
permet de conserver l'objet en question.
Il est possible de faire un test pour savoir si la variable seb est une instance de Person. Pour ce faire, il convient
d'utiliser le mot-cl instanceof, comme ceci :
Code : JavaScript
alert(seb instanceof Person); // Affiche true
Dans les paramtres de l'objet, on transmet les diffrentes informations pour la personne. Ainsi donc, en transmettant
'Sbastien' comme premier paramtre, celui-ci ira s'enregistrer dans la proprit this.nick, et il sera possible de le
rcuprer en faisant seb.nick.
180/378
Au final, si on reprend la problmatique du dbut de ce chapitre, on peut rcrire myArray comme contenant des lments de
type Person :
Code : JavaScript
var myArray = [
new Person('Sbastien', 23, 'm', 'an', 'Javascripteur', []),
new Person('Laurence', 19, 'f', 'soeur', 'Sous-officier', []),
new Person('Ludovic', 9, 'm', 'frre', 'Etudiant', []),
new Person('Pauline', 16, 'f', 'cousine', 'Etudiante', []),
new Person('Guillaume', 16, 'm', 'cousin', 'Dessinateur', []),
];
Il sera ainsi possible d'accder aux diffrents membres de la famille de cette manire pour rcuprer le travail :
myArray[i].work.
L'objet vu prcdemment est simple. Il y a moyen de l'amliorer en lui ajoutant des mthodes. Les mthodes, vous savez ce que
c'est car vous en avez dj crois dans les chapitres sur les tableaux. Si nous reprenons l'exemple prcdent et que l'on souhaite
ajouter un ami, il faut faire comme ceci :
Code : JavaScript
var seb = new Person('Sbastien', 23, 'm', 'an', 'Javascripteur',
[]);
// On ajoute un ami dans le tableau friends
seb.friends.push(new Person('Johann', 19, 'm', 'an',
'Javascripteur aussi', []));
alert(seb.friends[0].nick); // Affiche : Johann
181/378
Il y a deux manires de dfinir une mthode pour un objet : dans le constructeur ou via prototype. Dfinir les mthodes
directement dans le constructeur est facile puisque c'est nous qui crons le constructeur. La dfinition de mthodes via
prototype est utile surtout si on n'a pas cr le constructeur : ce sera alors utile pour ajouter des mthodes des objets natifs,
comme String ou Array.
Le code de cette mthode est simple : il ajoute un objet Person dans le tableau des amis.
N'aurions-nous pas pu utiliser new this(/* ... */) la place de new Person(/* ... */) ?
Non, car, comme nous l'avons vu plus haut, this fait rfrence l'objet dans lequel il est appel, c'est--dire le constructeur
Person. Si nous avions fait new this(/* ... */) cela aurait quivalu insrer le constructeur dans lui-mme. Mais de
toute faon, en tentant de faire a, vous obtenez une erreur du type this n'est pas un constructeur , donc l'interprteur
Javascript ne plante heureusement pas.
Cet objet prototype va nous permettre d'ajouter des mthodes un objet. Voici comment ajouter une mthode
addFriend() notre objet Person :
Code : JavaScript
Person.prototype.addFriend = function(nick, age, sex, parent, work,
friends) {
this.friends.push(new Person(nick, age, sex, parent, work,
friends));
}
182/378
Le this fait ici aussi rfrence l'objet dans lequel il s'excute, c'est--dire l'objet Person.
L'ajout de mthodes par prototype a l'avantage d'tre indpendant de l'objet, c'est--dire que vous pouvez dfinir votre objet
dans un fichier, et ajouter des mthodes dans un autre fichier (pour autant que les deux fichiers soient inclus dans la mme page
Web).
En ralit, l'ajout de mthodes par prototype est particulier, car les mthodes ajoutes ne seront pas copies dans
les instances de votre objet. Autrement dit, en ajoutant la mthode addFriend() par prototype, une instance
comme seb ne possdera pas la mthode directement dans son propre objet, elle sera oblige d'aller la chercher au sein
de son objet constructeur, ici Person. Cela veut dire que si vous faites une modification sur une mthode contenue
dans un prototype alors vous affecterez toutes les instances de votre objet (y compris celles qui sont dj cres),
cette solution est donc privilgier.
Ajout de mthodes
Ce n'est parfois pas facile de visualiser le contenu d'un tableau avec alert(). Pourquoi ne pas crer une mthode qui
afficherait le contenu d'un objet littral via alert(), mais de faon plus lgante (un peu comme la fonction var_dump() du
PHP si vous connaissez) ?
Voici le type d'objet afficher proprement :
Code : JavaScript
var family = {
self:
'Sbastien',
sister:
'Laurence',
brother: 'Ludovic',
cousin_1: 'Pauline',
cousin_2: 'Guillaume'
};
family.debug(); // Nous allons crer cette mthode debug()
183/378
Comme il s'agit d'un objet, le type natif est Object. Comme vu prcdemment, nous allons utiliser son sous-objet prototype
pour lui ajouter la mthode voulue :
Code : JavaScript
// Testons si cette mthode n'existe pas dj !
if (!Object.prototype.debug) {
// Crons la mthode
Object.prototype.debug = function() {
var text = 'Object {\n';
for (var i in this) {
if (i !== 'debug') {
text += ' [' + i + '] => ' + this[i] + '\n';
}
}
}
alert(text + '}');
Parce qu'en ajoutant la mthode debug() aux objets, elle s'ajoute mme aux objets littraux : autrement dit, debug() va se
lister elle-mme ce qui n'a pas beaucoup d'intrt. Regardez donc le rsultat en enlevant cette condition :
184/378
Nous avons ajout une mthode Object. Nous l'avons fait pour l'exemple, mais ceci ne doit jamais tre reproduit dans vos
scripts pour une raison trs simple : aprs ajout d'une mthode ou d'une proprit Object, celle-ci sera liste chaque fois
que vous utiliserez un for in. Par exemple, le code suivant ne devrait mme pas afficher une seule alerte :
Code : JavaScript
var myObject = {};
for (var i in myObject) {
alert(i);
}
Et pourtant, aprs l'ajout d'une mthode comme debug(), votre boucle affichera cette mthode pour tout objet parcouru, ce qui
n'est clairement pas conseill. Cependant, notez bien que cette restriction s'applique uniquement l'objet natif Object, les
autres objets comme Array, String, etc. ne sont pas concerns.
Limitations
Dans Internet Explorer
En thorie, chaque objet peut se voir attribuer des mthodes via prototype. Mais en pratique, si cela fonctionne avec les objets
natifs gnriques comme String, Date, Array, Object, Number, Boolean et de nombreux autres, cela fonctionne moins
bien avec les objets natifs lis au DOM comme Node, Element ou encore HTMLElement, en particulier dans Internet
Explorer.
Les namespaces
En informatique, un namespace, ou espace de nom en franais, est un ensemble fictif qui contient des informations,
gnralement des proprits et des mthodes, ainsi que des sous-namespaces. Le but d'un namespace est de s'assurer de
l'unicit des informations qu'il contient.
Par exemple, Sbastien et Johann habitent tous deux au numro 42. Sbastien dans la rue de Belgique et Johann dans la rue de
France. Les numros de leurs maisons peuvent tre confondus, puisqu'il s'agit du mme. Ainsi, si Johann dit J'habite au
numro 42 , c'est ambigu, car Sbastien aussi. Alors, pour diffrencier les deux numros, nous allons toujours donner le nom de
la rue. Ce nom de rue peut tre vu comme un namespace : il permet de diffrencier deux donnes identiques.
En programmation, quelque chose d'analogue peut se produire : imaginez que vous dveloppiez une fonction
myBestFunction(), et vous trouvez un script tout fait pour raliser un effet quelconque. Vous ajoutez alors ce script au
vtre. Problme : dans ce script tout fait, une fonction myBestFunction() est aussi prsente Votre fonction se retrouve
crase par l'autre, et votre script ne fonctionnera plus correctement.
Pour viter ce genre de dsagrment, nous allons utiliser un namespace !
Le Javascript, au contraire de langages comme le C# ou le Java, ne propose pas de vrai systme de namespace. Ce que
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
185/378
l'on tudie ici est un systme pour reproduire plus ou moins correctement un tel systme.
Dfinir un namespace
Un namespace est une sorte de catgorie : vous allez vous crer un namespace, et, au sein de celui-ci, vous allez placer vos
fonctions. De cette manire, vos fonctions seront en quelque sorte prserves d'ventuels crasements. Comme le Javascript ne
gre pas nativement les namespaces (comprenez : il n'y a pas de structure consacre cela), nous allons devoir nous dbrouiller
seuls, et utiliser un simple objet littral. Premier exemple :
Code : JavaScript
var myNamespace = {
myBestFunction: function() {
alert('Ma meilleure fonction !');
}
};
// On excute la fonction :
myNamespace.myBestFunction();
On commence par crer un objet littral appel myNamespace. Ensuite on dfinit une mthode : myBestFunction().
Souvenez-vous, dans le chapitre sur les objets littraux, nous avions vu que nous pouvions dfinir des proprits, et il est aussi
possible de dfinir des mthodes, en utilisant la mme syntaxe.
Pour appeler myBestFunction(), il faut obligatoirement passer par l'objet myNamespace, ce qui limite trs fortement la
probabilit de voir votre fonction crase par une autre. Bien videmment, votre namespace doit tre original pour tre certain
qu'un autre dveloppeur n'utilise pas le mme Cette technique n'est donc pas infaillible, mais rduit considrablement les
problmes.
Un style de code
Utiliser un namespace est aussi lgant, car cela permet d'avoir un code visuellement propre et structur. Une grande majorit
des gros scripts sont organiss via un namespace, notamment car il est possible de dcomposer le script en catgories. Par
exemple, vous faites un script qui gre un webmail (comme Hotmail ou GMail) :
Code : JavaScript
var thundersebWebMail = {
// Proprits
version: 1.42,
lang: 'english',
// Initialisation
init : function() { /* initialisation */ },
// Gestion des mails
mails: {
list: function() { /* affiche la liste des mails */ },
show: function() { /* affiche un mail */ },
trash: function() { /* supprime un mail */ },
// et ctera
},
};
186/378
Ce code fictif comprend une mthode d'initialisation et deux sous-namespaces : mails et contacts, servant respectivement
grer les e-mails et les contacts. Chacun de ces sous-namespaces contient les mthodes qui lui sont propres.
Structurer son code de cette manire est propre et lisible, ce qui n'est pas toujours le cas d'une succession de fonctions. Voici
l'exemple que nous venons de voir mais cette fois-ci sans namespaces :
Code : JavaScript
var webmailVersion = 1.42,
webmailLang
= 'english';
function webmailInit() { /* initialisation */ }
function webmailMailsList() { /* affiche la liste des mails */ }
function webmailMailsShow() { /* affiche un mail */ }
function webmailMailsTrash() { /* supprime un mail */ }
function webmailContactsList() { /* affiche la liste des contacts */
}
function webmailContactsEdit() { /* dite un contact */ }
C'est tout de suite plus confus, il n'y a pas de hirarchie, c'est brouillon. Bien videmment, cela dpend du codeur : un code en
namespace peut tre brouillon, alors qu'un code normal peut tre trs propre ; mais de manire gnrale, un code en
namespace est accessible, plus lisible et plus comprhensible. C'est videmment une question d'habitude.
L'emploi de this
Le mot-cl this s'utilise ici exactement comme dans les objets vus prcdemment. Mais attention, si vous utilisez this dans
un sous-namespace, celui-ci pointera vers ce sous-namespace, et non vers le namespace parent. Ainsi, l'exemple suivant ne
fonctionnera pas correctement, car en appelant la mthode init() on lui demande d'excuter this.test(). Or, this
pointe vers subNamespace, et il n'existe aucune mthode test() au sein de subNamespace.
Code : JavaScript
var myNamespace = {
test: function() { alert('Test'); },
subNamespace: {
init: function() {
this.test();
}
}
};
myNamespace.subNamespace.init();
Pour accder l'objet parent, il n'y a malheureusement pas de solution si ce n'est crire son nom entirement :
Code : JavaScript
var myNamespace = {
test: function() { alert('Test'); },
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
187/378
subNamespace: {
init: function() {
myNamespace.test();
}
}
};
myNamespace.subNamespace.init();
Une mthode, en revanche, est dpendante d'un objet. C'est le cas par exemple de la mthode push() qui est dpendante de
l'objet Array. Le fait qu'elle soit dpendante est la fois un avantage et un inconvnient :
Un avantage car vous n'avez pas spcifier quel objet la mthode doit modifier ;
Un inconvnient car cette mthode ne pourra fonctionner que sur l'objet dont elle est dpendante !
Cet inconvnient peut tre rsolu grce deux mthodes nommes apply() et call().
Comme vous le savez, une mthode utilise gnralement le mot-cl this pour savoir quel objet elle appartient, c'est ce qui fait
qu'elle est dpendante. Les deux mthodes apply() et call() existent pour permettre de rediriger la rfrence du mot-cl
this vers un autre objet !
Nous n'allons pas faire de cas pratique avec la mthode push(), car son fonctionnement est spcifique aux tableaux (il serait
difficile de lui demander d'ajouter une donne sur un objet dont la structure est totalement diffrente). En revanche, il existe une
mthode que tout objet possde : toString() ! Cette mthode a pour but de fournir une reprsentation d'un objet sous forme
de chane de caractres, c'est elle qui est appele par la fonction alert() lorsque vous lui passez un objet en paramtre. Elle
possde cependant un fonctionnement diffrent selon l'objet sur lequel elle est utilise :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
188/378
Code : JavaScript
alert(['test']); // Affiche : test
alert({0:'test'}); // Affiche : [object Object]
Nous n'avons pas fait appel la mthode toString(), mais, comme nous l'avons dit prcdemment, alert() le
fait implicitement.
Comme vous avez pu le constater, la mthode toString() renvoie un rsultat radicalement diffrent selon l'objet. Dans le cas
d'un tableau, elle retourne son contenu, mais quand il s'agit d'un objet, elle retourne son type converti en chane de caractres.
Notre objectif maintenant va tre de faire en sorte d'appliquer la mthode toString() de l'objet Object sur un objet Array,
et ce afin d'obtenir sous forme de chane de caractres le type de notre tableau au lieu d'obtenir son contenu.
C'est l qu'entrent en jeu nos deux mthodes apply() et call(). Elles vont nous permettre de redfinir le mot-cl this de la
mthode toString(). Ces deux mthodes fonctionnent quasiment de la mme manire, elles prennent toutes les deux en
paramtre un premier argument obligatoire qui est l'objet vers lequel va pointer le mot-cl this. Nos deux mthodes se
diffrencient sur les arguments facultatifs, mais nous en reparlerons plus tard. En attendant, nous allons nous servir de la
mthode call().
Comment utiliser notre mthode call() ? Tout simplement de la manire suivante :
Code : JavaScript
methode_a_modifier.call(objet_a_definir);
Dans notre exemple actuel, la mthode modifier est toString() de l'objet Object. En sachant cela il ne nous reste plus
qu' faire ceci :
Code : JavaScript
var result = Object.prototype.toString.call(['test']);
alert(result); // Affiche : [object Array]
Nous y voil ! La mthode toString() de Object a bien t applique notre tableau, nous obtenons donc son type et
non pas son contenu.
Revenons maintenant sur les arguments facultatifs de nos deux mthodes apply() et call(). La premire prend en
paramtre facultatif un tableau de valeurs, tandis que la deuxime prend une infinit de valeurs en paramtres. Ces arguments
facultatifs servent la mme chose : ils seront passs en paramtres la mthode souhaite.
Ainsi, si nous crivons :
Code : JavaScript
var myArray = [];
myArray.push.apply(myArray, [1, 2, 3]);
189/378
Voil pour ces deux mthodes ! Leurs cas d'application sont assez rares, mais sachez au moins qu'elles existent, nous y aurons
srement recours plus tard dans ce tutoriel.
En rsum
Outre les objets natifs, le Javascript nous offre la possibilit de crer des objets personnaliss.
Le constructeur contient la structure de base de l'objet. On dfinit un constructeur de la mme manire qu'une fonction.
Le mot-cl this fait rfrence l'objet dans lequel il est utilis, ce qui nous permet de crer les proprits et les
mthodes de l'objet.
Une fois le constructeur dfini, il est conseill d'ajouter les mthodes via l'objet prototype.
Un namespace est un objet qui permet de s'assurer que toutes nos fonctions seront uniques, et que l'emploi d'un script
tiers ne risque pas de les remplacer.
Il est possible de modifier le contexte d'excution d'une mthode. C'est peu frquent, mais il est bon de le savoir.
190/378
Nous avons vu, tout au long du cours, que les chanes de caractres taient des objets String, les tableaux des Array, etc.
C'est toujours vrai mais il convient de nuancer ces propos en introduisant le concept de type primitif .
Pour crer une chane de caractres, on utilise gnralement cette syntaxe :
Code : JavaScript
var myString = "Chane de caractres primitive";
Cet exemple cre ce que l'on appelle une chane de caractres primitive, qui n'est pas un objet String. Pour instancier un objet
String, il faut faire comme ceci :
Code : JavaScript
var myRealString = new String("Chane");
Ce que nous avons utilis jusqu' prsent tait en fait des types primitifs, et non des instances d'objets.
Quelle est la diffrence entre un type primitif et une instance ?
La diffrence est minime pour nous, dveloppeurs. Prenons l'exemple de la chane de caractres : chaque fois que nous allons
faire une opration sur une chane primitive, le Javascript va automatiquement convertir cette chane en une instance temporaire
de String, de manire pouvoir utiliser les proprits et mthodes fournies par l'objet String. Une fois les oprations
termines, l'instance temporaire est dtruite.
Au final, utiliser un type primitif ou une instance revient au mme du point de vue de l'utilisation. Mais il subsiste de lgres
diffrences avec l'oprateur instanceof qui peut retourner de drles de rsultats
Pour une raison ou une autre, imaginons que l'on veuille savoir de quelle instance est issu un objet :
Code : JavaScript
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
191/378
La condition sera fausse ! Et c'est bien normal puisque myString est une chane primitive et non une instance de String.
Pour tester le type primitif, il convient d'utiliser l'oprateur typeof :
Code : JavaScript
if (typeof myString === 'string') {
// Faire quelque chose
}
typeof permet de vrifier le type primitif (en anglais on parle de datatype). Mais ici aussi faites attention au pige, car la forme
primitive d'une instance de String est object :
Code : JavaScript
alert(typeof myRealString); // Affiche : object
Il faudra donc faire bien attention en testant le type ou l'instance d'un objet ! Il est mme d'ailleurs dconseill de faire ce genre
de tests vu le nombre de problmes que cela peut causer. La seule valeur retourne par typeof dont on peut tre sr, c'est
"undefined". Nous allons tudier, plus tard dans ce chapitre, une solution pour tester si une variable contient une chane de
caractres.
Retenez bien une chose dans l'ensemble : il est plus simple en tous points d'utiliser directement les types primitifs !
L'objet String
L'objet String est l'objet que vous manipulez depuis le dbut du tutoriel : c'est lui qui gre les chanes de caractres.
Proprits
String ne possde qu'une seule proprit, length, qui retourne le nombre de caractres contenus dans une chane. Les
espaces, les signes de ponctuation, les chiffres sont considrs comme des caractres. Ainsi, cette chane de caractres
contient 21 caractres :
Code : JavaScript
alert('Ceci est une chane !'.length);
Essayer !
En fait, il n'est pas toujours obligatoire de dclarer une variable pour utiliser les proprits et les mthodes d'un objet. En effet,
vous pouvez crire directement le contenu de votre variable et utiliser une de ses proprits ou de ses mthodes, comme c'est le
cas ici. Notez cependant que cela ne fonctionne pas avec les nombres sous forme primitive car le point est le caractre
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
192/378
permettant d'ajouter une ou plusieurs dcimales. Ainsi, ce code gnrera une erreur :
Code : JavaScript
0.toString(); // Une erreur se produira si vous excutez ce code
Mthodes
String possde quelques mthodes qui sont pour la plupart assez intressantes mais basiques. Le Javascript est un langage
assez simple, qui ne contient pas normment de mthodes de base. C'est un peu l'inverse du PHP qui contient une multitude de
fonctions pour raliser un peu tout et n'importe quoi. Par exemple, le PHP possde une fonction pour mettre la premire lettre
d'une chane en majuscule, alors qu'en Javascript il faudra nous-mmes rcuprer le premier caractre et le mettre en majuscule.
Le Javascript fournit juste quelques mthodes de base, et ce sera vous de coder vous-mmes d'autres mthodes ou fonctions
selon vos besoins.
String embarque aussi toute une srie de mthodes obsoltes destines ajouter des balises HTML une chane de
caractres. Ne soyez donc pas tonns si un jour vous rencontrez de telles mthodes dans de vieux scripts au dtour de vos
recherches sur Internet. Ces mthodes, anchor(), big(), blink(), bold(), fixed(), fontcolor(), fontsize(),
link(), small(), strike(), sub(), sup() s'utilisent de cette manire :
Code : JavaScript
var myString = 'Chane insrer';
document.body.innerHTML += myString.bold();
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
193/378
En fait, les chanes de caractres peuvent tre imagines comme des tableaux, la diffrence qu'il n'est pas possible d'accder aux
caractres en utilisant les crochets : la place, il faut utiliser charAt().
Certains navigateurs permettent toutefois d'accder aux caractres d'une chane comme s'il s'agissait d'un tableau, c'est-dire comme ceci : myString[0]. Ce n'est pas standard, donc il est fortement conseill d'utiliser
myString.charAt(0).
194/378
Ce n'est pas trs frquent, mais cela peut tre utile dans un cas bien particulier : dtecter les touches du clavier. Admettons qu'il
faille savoir quelle touche du clavier t presse par l'utilisateur. Pour cela, on utilise la proprit keyCode de l'objet Event :
Code : HTML
<textarea onkeyup="listenKey(event)"></textarea>
indexOf() retourne la position du premier caractre trouv, et s'il n'y en a pas la valeur -1 est retourne.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
195/378
Code : JavaScript
var myString = 'Le JavaScript est plutt cool';
var result = myString.indexOf('JavaScript');
if (result > -1) {
alert('La chane contient le mot "Javascript" qui dbute la
position ' + result);
}
Essayer !
Ce code a pour but de savoir si la chane myString contient la chane JavaScript . La position de la premire occurrence de
la chane recherche est stocke dans la variable result. Si result vaut -1, alors la chane n'a pas t trouve. Si, en
revanche, result vaut 0 (le premier caractre) ou une autre valeur, la chane est trouve.
Si indexOf() retourne la position de la premire occurrence trouve, lastIndexOf() retourne la position de la dernire.
Notons que ces deux fonctions possdent chacune un deuxime argument qui permet de spcifier partir de quel index la
recherche doit commencer.
Eh bien pas tant que a ! Le tilde est effectivement trs peu utile en temps normal, mais dans le cadre d'une utilisation avec les
deux mthodes tudies, il est redoutablement efficace pour dtecter si une chane de caractres contient un caractre ou un
morceau de chane. En temps normal nous ferions comme ceci :
Code : JavaScript
var myString = 'Le JavaScript est plutt cool';
if (myString.indexOf('JavaScript') != -1) {
alert('La chane contient bien le mot "Javascript".');
}
196/378
if (~myString.indexOf('JavaScript')) {
alert('La chane contient bien le mot "Javascript".');
}
En faisant cela, dans le cas o le rsultat serait -1, celui-ci va alors se retrouver incrment et arriver 0, ce qui donnera donc une
valuation false pour notre chane de caractres. La valeur -1 tant la seule pouvoir atteindre la valeur 0 avec le tilde ~, il
n'y a pas d'hsitation avoir vu que tous les autres nombres seront valus true !
Oui, cette technique a t conue pour les parfaits fainants, mais il y a fort parier que vous vous en souviendrez.
Le but du jeu va tre de rcuprer, dans deux variables diffrentes, les deux pseudonymes contenus dans myString. Pour ce
faire, nous allons utiliser substring(). substring(a, b) permet d'extraire une chane partir de la position a (incluse)
jusqu' la position b (exclue).
Pour extraire Thunderseb , il suffit de connatre la position du premier espace, puisque la position de dpart vaut 0 :
Code : JavaScript
var nick_1 = myString.substring(0, myString.indexOf(' '));
Pour Nesquik69 , il suffit de connatre la position du dernier espace : c'est ce moment que commencera la chane. Comme
Nesquik69 termine la chane, il n'y a pas besoin de spcifier de deuxime paramtre pour substring(), la mthode va
automatiquement aller jusqu'au bout :
Code : JavaScript
var nick_2 = myString.substring(myString.lastIndexOf(' ') + 1); //
Ne pas oublier d'ajouter 1, pour commencer au N et non l'espace
Une autre manire de procder serait d'utiliser substr(), la mthode sur de substring(). substr(a, n) accepte deux
paramtres : le premier est la position de dbut, et le deuxime le nombre de caractres extraire. Cela suppose donc de connatre
le nombre de caractres extraire. a limite son utilisation et c'est une mthode que vous ne rencontrerez pas frquemment, au
contraire de substring().
Une dernire mthode d'extraction existe : slice(). slice() ressemble trs fortement substring(), mais avec une
option en plus. Une valeur ngative est transmise pour la position de fin, slice() va extraire la chane jusqu' la fin, en
dcomptant le nombre de caractres indiqu. Par exemple, si on ne veut rcuprer que Thunder , on peut faire comme ceci :
Code : JavaScript
var nick_1 = 'Thunderseb'.slice(0, -3);
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
197/378
Essayer !
Dans cet exemple, splitted contient un tableau contenant trois lments : Pauline , Guillaume et Clarisse .
split() peut aussi couper une chane chaque fois qu'un retour la ligne est rencontr :
myString.split('\n'). C'est trs pratique pour crer un tableau o chaque item contient une ligne.
alors l'instruction typeof montre bien que string_1 est une instance de String et que string_2 est une valeur
primitive :
Code : JavaScript
alert(typeof string_1); // Affiche : object
alert(typeof string_2); // Affiche : string
198/378
Grce cette mthode, il devient bien plus simple de vrifier si une variable contient une chane de caractres. Voici notre code
final :
Code : JavaScript
function isString(variable) {
return typeof variable.valueOf() === 'string'; // Si le type de
la valeur primitive est string alors on retourne true
}
D'accord, cette fonction va s'excuter correctement si on envoie une instance de String. Mais que va renvoyer
valueOf() si on passe une valeur primitive notre fonction ?
Eh bien, tout simplement la mme valeur. Expliquons-nous : valueOf() retourne la valeur primitive d'un objet, mais si cette
mthode est utilise sur une valeur qui est dj de type primitif, alors elle va retourner la mme valeur primitive, ce qui convient
trs bien vu que dans tous les cas il s'agit de la valeur primitive que nous souhaitons analyser !
Pour vous convaincre, testez donc par vous-mmes :
Code : JavaScript
alert(isString('Test')); // Affiche : true
alert(isString(new String('Test'))); // Affiche : true
Pour rappel, Object est l'objet dont tous les autres objets (tel que String) hritent. Ainsi, en crant une instance de Object
avec un type primitif en paramtre, l'objet instanci sera de mme type que la valeur primitive. En clair, si vous passez en
paramtre un type primitif string alors vous obtiendrez une instance de l'objet String avec la mme valeur passe en
paramtre.
En rsum
Il existe des objets et des types primitifs. Si leur utilisation semble identique, il faut faire attention lors des tests avec les
oprateurs instanceof et typeof. Mais heureusement valueOf() sera d'une aide prcieuse.
Il est prfrable d'utiliser les types primitifs, comme nous le faisons depuis le dbut de ce cours.
String fournit des mthodes pour manipuler les caractres : mettre en majuscule ou en minuscule, rcuprer un
caractre grce sa position et supprimer les espaces de part et d'autre de la chane.
String fournit aussi des mthodes pour rechercher, couper et extraire.
L'utilisation du caractre tilde est mconnue, mais peut se rvler trs utile en couple avec indexOf() ou
lastIndexOf().
199/378
Utilisation
Les regex ne s'utilisent pas seules, et il y a deux manires de s'en servir : soit par le biais de RegExp qui est l'objet qui gre les
expressions rgulires, soit par le biais de certaines mthodes de l'objet String :
match() : retourne un tableau contenant toutes les occurrences recherches ;
search() : retourne la position d'une portion de texte (semblable indexOf() mais avec une regex);
split() : la fameuse mthode split(), mais avec une regex en paramtre ;
replace() : effectue un rechercher/remplacer.
Nous n'allons pas commencer par ces quatre mthodes car nous allons d'abord nous entraner crire et tester des regex. Pour ce
faire, nous utiliserons la mthode test() fournie par l'objet RegExp. L'instanciation d'un objet RegExp se fait comme ceci :
Code : JavaScript
var myRegex = /contenu__rechercher/;
Cela ressemble une chane de caractres l'exception prs qu'elle est encadre par deux slashs / au lieu des apostrophes ou
guillemets traditionnels.
Si votre regex contient elle-mme des slashs, n'oubliez pas de les chapper en utilisant un anti-slash comme suit :
Code : JavaScript
var regex_1 = /contenu_/_contenu/; // La syntaxe est fausse car le
slash n'est pas chapp
var regex_2 = /contenu_\/_contenu/; // La syntaxe est bonne car le
slash est chapp avec un anti-slash
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
200/378
L'utilisation de la mthode test() est trs simple. En cas de russite du test, elle renvoie true ; dans le cas contraire, elle
renvoie false.
Code : JavaScript
if (myRegex.test('Chane de caractres dans laquelle effectuer la
recherche')) {
// Retourne true si le test est russi
} else {
// Retourne false dans le cas contraire
}
Pour vos tests, n'hsitez pas utiliser une syntaxe plus concise, comme ceci :
Code : JavaScript
if (/contenu__rechercher/.test('Chane de caractres bla bla bla'))
Recherches de mots
Le sujet tant complexe, nous allons commencer par des choses simples, c'est--dire des recherches de mots. Ce n'est pas si
anodin que a, car il y a dj moyen de faire beaucoup de choses. Comme nous venons de le voir, une regex s'crit comme suit :
Code : JavaScript
/contenu_de_la_regex/
O contenu_de_la_regex sera remplacer par ce que nous allons rechercher. Comme nous faisons du Javascript, nous avons
de bons gots et donc nous allons parler de raclette savoyarde. crivons donc une regex qui va regarder si dans une phrase le
mot raclette apparat :
Code : JavaScript
/raclette/
Essayer !
Rsumons tout a. Le mot raclette a t trouv dans la phrase Je mangerais bien une raclette savoyarde ! . Si on change le
mot recherch, tartiflette par exemple, le test retourne false, puisque ce mot n'est pas contenu dans la phrase.
Si on change notre regex et que l'on met une majuscule au mot raclette , comme ceci : /Raclette/, le test renverra false,
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
201/378
car le mot raclette prsent dans la phrase ne comporte pas de majuscule. C'est relativement logique en fait. Il est possible,
grce aux options, de dire la regex d'ignorer la casse, c'est--dire de rechercher indiffremment les majuscules et les minuscules.
Cette option s'appelle i, et comme chaque option (nous en verrons d'autres), elle se place juste aprs le slash de fermeture de la
regex :
/Raclette/i
Avec cette option, la regex reste utilisable comme nous l'avons vu prcdemment, savoir :
Code : JavaScript
if (/Raclette/i.test('Je mangerais bien une raclette savoyarde !'))
{
alert('a semble parler de raclette');
} else {
alert('Pas de raclette l\'horizon');
}
Essayer !
Ici, majuscule ou pas, la regex n'en tient pas compte, et donc le mot Raclette est trouv, mme si le mot prsent dans la phrase
ne comporte pas de majuscule.
la place de Raclette , la phrase pourrait contenir le mot Tartiflette . Pouvoir crire une regex qui rechercherait soit
Raclette soit Tartiflette serait donc intressant. Pour ce faire, nous disposons de l'oprateur OU, reprsent par la barre
verticale pipe |. Son utilisation est trs simple puisqu'il suffit de la placer entre chaque mot recherch, comme ceci :
Code : JavaScript
if (/Raclette|Tartiflette/i.test('Je mangerais bien une tartiflette
savoyarde !')) {
alert('a semble parler de trucs savoyards');
} else {
alert('Pas de plats lgers l\'horizon');
}
Essayer !
La recherche peut videmment inclure plus de deux possibilits :
Code : JavaScript
/Raclette|Tartiflette|Fondue|Croziflette/i
Avec cette regex, on saura si la phrase contient une de ces quatre spcialits savoyardes !
202/378
/^raclette savoyarde$/
Voici un tableau avec divers tests qui sont effectus pour montrer l'utilisation de ces deux symboles :
Chane
Regex
Raclette savoyarde
/^Raclette/
false
/savoyarde$/
true
Rsultat
false
Une classe de caractres est crite entre crochets et sa signification est simple : une des lettres qui se trouve entre les crochets
peut convenir. Cela veut donc dire que l'exemple prcdent va trouver les mots gras et gros , car la classe, la place de la
voyelle, contient aux choix les lettres a et o. Beaucoup de caractres peuvent tre utiliss au sein d'une classe :
Code : JavaScript
/gr[aio]s/
Ici, la regex trouvera les mots gras , grs , gris et gros . Ainsi donc, en parlant d'une tartiflette, qu'elle soit grosse ou
grasse, cette regex le saura :
Chane
Regex
Rsultat
203/378
L'exclusion d'un intervalle est possible aussi : [^b-y] qui exclura les lettres allant de b y.
Il faut prendre en compte que la recherche n'ignore pas les caractres accentus. Ainsi, [a-z] trouvera a, b, i, o
mais ne trouvera pas , ou encore . S'il s'agit de trouver un caractre accentu, il faut l'indiquer explicitement : [az]. Il n'y a toutefois pas besoin d'crire les variantes en majuscules si l'option i est utilise :
/[a-z]/i.
Les quantificateurs
Les quantificateurs permettent de dire combien de fois un caractre doit tre recherch. Il est possible de dire qu'un caractre
peut apparatre 0 ou 1 fois, 1 fois ou une infinit de fois, ou mme, avec des accolades, de dire qu'un caractre peut tre rpt 3,
4, 5 ou 10 fois.
partir d'ici, la syntaxe des regex va devenir plus complexe !
Reprenons notre raclette. Il y a deux t, mais il se pourrait que l'utilisateur ait fait une faute de frappe et n'en ait mis qu'un seul. On
va donc crire une regex capable de grer ce cas de figure :
Code : JavaScript
/raclett?e/
Ici, le premier t sera trouv, et derrire le deuxime se trouve le point d'interrogation, ce qui signifie que le deuxime t peut
apparatre 0 ou 1 fois. Cette regex gre donc notre cas de figure.
Un cas saugrenu serait qu'il y ait beaucoup de t : raclettttttttttte . Pas de panique, il suffit d'utiliser le quantificateur + :
Code : JavaScript
/raclet+e/
Le + indique que le t sera prsent une fois ou un nombre infini de fois. Avec le symbole *, la lettre est facultative mais peut tre
rpte un nombre infini de fois. En utilisant *, la regex prcdente peut s'crire :
Code : JavaScript
204/378
/raclett*e/
Les accolades
la place des trois symboles vus prcdemment, on peut utiliser des accolades pour dfinir explicitement combien de fois un
caractre peut tre rpt. Trois syntaxes sont disponibles :
{n} : le caractre est rpt n fois ;
{n,m} : le caractre est rpt de n m fois. Par exemple, si on a {0, 5}, le caractre peut tre prsent de 0 5 fois ;
{n,} : le caractre est rpt de n fois l'infini.
Les quantificateurs, accolades ou symboles, peuvent aussi tre utiliss avec les classes de caractres. Si on mange une racleffe
au lieu d'une raclette , on peut imaginer la regex suivante :
Code : JavaScript
/racle[tf]+e/
Voici, pour clore cette section, quelques exemples de regex qui utilisent tout ce qui a t vu :
Chane
Regex
Rsultat
Hellowwwwwwwww /Hellow+/
true
Goooooogle
/Go{2,}gle/
true
Le 1er septembre
Le 1er septembre
/Le [1-9][a-z]{2,3}[a-z]+/
false
La dernire regex est fausse cause de l'espace. En effet, la classe [a-z] ne trouvera pas l'espace. Nous verrons cela dans un
prochain chapitre sur les regex.
Les mtacaractres
Nous avons vu prcdemment que la syntaxe des regex est dfinie par un certain nombre de caractres spciaux, comme ^, $, [ et
], ou encore + et *. Ces caractres sont ce que l'on appelle des mtacaractres, et en voici la liste complte :
Code : Autre
! ^ $ ( ) [ ] { } ? + * . / \ |
Un problme se pose si on veut chercher la prsence d'une accolade dans une chane de caractres. En effet, si on a ceci, la regex
ne fonctionnera pas :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
Chane
205/378
Regex
Rsultat
C'est normal, car les accolades sont des mtacaractres qui dfinissent un nombre de rptition : en clair, cette regex n'a aucun
sens pour l'interprteur Javascript ! Pour pallier ce problme, il suffit d'chapper les accolades au moyen d'un anti-slash :
Code : JavaScript
/accolade \{comme ceci\}/
De cette manire, les accolades seront vues par l'interprteur comme tant des accolades dans le texte , et non comme des
mtacaractres. Il en va de mme pour tous les mtacaractres cits prcdemment. Il faut mme penser chapper l'anti-slash
avec un anti-slash :
Chane
Regex
Rsultat
erreur de syntaxe
Et s'il faut trouver un slash ou un anti-slash, il ne faut pas oublier de les chapper :
Code : JavaScript
/[a-z!?\/\\]/
206/378
Nous avons vu que les classes taient pratiques pour chercher un caractre au sein d'un groupe, ce qui permet de trouver un
caractre sans savoir au pralable quel sera ce caractre. Seulement, utiliser des classes alourdit fortement la syntaxe des regex et
les rend difficilement lisibles. Pour pallier ce petit souci, nous allons utiliser ce que l'on appelle des types gnriques. Certains
parlent aussi de classes raccourcies , mais ce terme n'est pas tout fait exact.
Les types gnriques s'crivent tous de la manire suivante : \x, o x reprsente une lettre. Voici la liste de tous les types
gnriques :
Type
Description
\d
\D
\s
\S
\w
Trouve un caractre de mot : une lettre, accentue ou non, ainsi que l'underscore
\W
Description
\n
\t
Ces deux caractres sont reconnus par le type gnrique \s (qui trouve, pour rappel, n'importe quel espace blanc).
Les assertions
Les assertions s'crivent comme les types gnriques mais ne fonctionnent pas tout fait de la mme faon. Un type gnrique
recherche un caractre, tandis qu'une assertion recherche entre deux caractres. C'est tout de suite plus simple avec un tableau :
Type
Description
\b
\B
Il faut juste faire attention avec l'utilisation de \b, car cette assertion reconnat les caractres accentus comme des
limites de mots . a peut donc provoquer des comportements inattendus.
Ce n'est pas fini ! Les regex reviennent ds le chapitre suivant, o nous tudierons leur utilisation avec diverses mthodes
Javascript.
En rsum
Les regex constituent une technologie part, utilise au sein du Javascript et qui permet de manipuler les chanes de
caractres. La syntaxe de ces regex se base sur celle du langage Perl.
Plusieurs mthodes de l'objet String peuvent tre utilises avec des regex, savoir match(), search(), split()
et replace().
L'option i indique la regex que la casse doit tre ignore.
Les caractres ^ et $ indiquent respectivement le dbut et la fin de la chane de caractres.
Les classes et les intervalles de caractres, ainsi que les types gnriques, servent rechercher un caractre possible
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
207/378
208/378
Pour construire une regex, il suffit de procder par tapes : faisons comme si nous lisions la chane de caractres et crivons la
regex au fur et mesure. On crit tout d'abord la partie locale, qui n'est compose que de lettres, de chiffres et ventuellement
d'un tiret, un trait de soulignement et un point. Tous ces caractres peuvent tre rpts plus d'une fois (il faut donc utiliser le
quantificateur +) :
Code : JavaScript
/^[a-z0-9._-]+$/
Aprs vient le label du nom de domaine, lui aussi compos de lettres, de chiffres, de tirets et de traits de soulignement. Ne pas
oublier le point, car il peut s'agir d'un sous-domaine (par exemple @tutoriels.siteduzero.com) :
Code : JavaScript
/^[a-z0-9._-]+@[a-z0-9._-]+$/
Puis vient le point de l'extension du domaine : attention ne pas oublier de l'chapper, car il s'agit d'un mtacaractre :
Code : JavaScript
/^[a-z0-9._-]+@[a-z0-9._-]+\.$/
Et pour finir, l'extension ! Une extension de nom de domaine ne contient que des lettres, au minimum 2, au maximum 6. Ce qui
nous fait :
Code : JavaScript
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
209/378
/^[a-z0-9._-]+@[a-z0-9._-]+\.[a-z]{2,6}$/
Testons donc :
Code : JavaScript
var email = prompt("Entrez votre adresse e-mail :",
"javascript@siteduzero.com");
if (/^[a-z0-9._-]+@[a-z0-9._-]+\.[a-z]{2,6}$/.test(email)) {
alert("Adresse e-mail valide !");
} else {
alert("Adresse e-mail invalide !");
}
L'objet RegExp
L'objet RegExp est l'objet qui gre les expressions rgulires. Il y a donc deux faons de dclarer une regex : via RegExp ou via
son type primitif que nous avons utilis jusqu' prsent :
Code : JavaScript
var myRegex1 = /^Raclette$/i;
var myRegex2 = new RegExp("^Raclette$", "i");
Le constructeur RegExp reoit deux paramtres : le premier est l'expression rgulire sous la forme d'une chane de caractres, et
le deuxime est l'option de recherche, ici i. L'intrt d'utiliser RegExp est qu'il est possible d'inclure des variables dans la regex,
chose impossible en passant par le type primitif :
Code : JavaScript
var nickname = "Sbastien";
var myRegex = new RegExp("Mon prnom est " + nickname, "i");
Ce n'est pas spcialement frquent, mais cela peut se rvler particulirement utile. Il est cependant conseill d'utiliser la notation
littrale (le type primitif) quand l'utilisation du constructeur RegExp n'est pas ncessaire.
Mthodes
RegExp ne possde que deux mthodes : test() et exec(). La mthode test() a dj t utilise et permet de tester une
expression rgulire ; elle renvoie true si le test est russi ou false si le test choue. De son ct, exec() applique
galement une expression rgulire, mais renvoie un tableau dont le premier lment contient la portion de texte trouve dans la
chane de caractres. Si rien n'est trouv, null est renvoy.
Code : JavaScript
var sentence = "Si ton tonton";
var result = /\bton\b/.exec(sentence); // On cherche rcuprer le
mot ton
if (result) { // On vrifie que ce n'est pas null
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
210/378
Proprits
L'objet RegExp contient neuf proprits, appeles $1, $2, $3 jusqu' $9. Comme nous allons le voir dans la sous-partie
suivante, il est possible d'utiliser une regex pour extraire des portions de texte, et ces portions sont accessibles via les proprits
$1 $9.
Tout cela va tre mis en lumire un peu plus loin en parlant des parenthses !
Les parenthses
Les parenthses capturantes
Nous avons vu pour le moment que les regex servaient voir si une chane de caractres correspondait un modle. Mais il y a
moyen de faire mieux, comme extraire des informations. Pour dfinir les informations extraire, on utilise des parenthses, que
l'on appelle parenthses capturantes, car leur utilit est de capturer une portion de texte, que la regex va extraire.
Considrons cette chane de caractres : Je suis n en mars . Au moyen de parenthses capturantes, nous allons extraire le
mois de la naissance, pour pouvoir le rutiliser :
Code : JavaScript
var birth = 'Je suis n en mars';
/^Je suis n en (\S+)$/.exec(birth);
alert(RegExp.$1); // Affiche : mars
Cet exemple est un peu droutant, mais est en ralit assez simple comprendre. Dans un premier temps, on cre la regex avec les
fameuses parenthses. Comme les mois sont faits de caractres qui peuvent tre accentus, on peut directement utiliser le type
gnrique \S. \S+ indique qu'on recherche une srie de caractres, jusqu' la fin de la chane (dlimite, pour rappel, par $) : ce
sera le mois. On englobe ce mois dans des parenthses pour faire comprendre l'interprteur Javascript que leur contenu
devra tre extrait.
La regex est excute via exec(). Et ici une autre explication s'impose. Quand on excute test() ou exec(), le contenu des
parenthses capturantes est enregistr temporairement au sein de l'objet RegExp. Le premier couple de parenthses sera
enregistr dans la proprit $1, le deuxime dans $2 et ainsi de suite, jusqu'au neuvime, dans $9. Cela veut donc dire qu'il ne
peut y avoir qu'un maximum de neuf couples de parenthses. Les couples sont numrots suivant le sens de lecture, de gauche
droite.
Et pour accder aux proprits, il suffit de faire RegExp.$1, RegExp.$2, etc.
Voici un autre exemple, reprenant la regex de validation de l'adresse e-mail. Ici, le but est de dcomposer l'adresse pour rcuprer
les diffrentes parties :
Code : JavaScript
var email = prompt("Entrez votre adresse e-mail :",
"javascript@siteduzero.com");
if (/^([a-z0-9._-]+)@([a-z0-9._-]+)\.([a-z]{2,6})$/.test(email)) {
alert('Partie locale : ' + RegExp.$1 + '\nDomaine : ' +
RegExp.$2 + '\nExtension : ' + RegExp.$3);
} else {
alert('Adresse e-mail invalide !');
}
211/378
Essayer !
Remarquez que mme si test() et exec() sont excuts au sein d'un if() le contenu des parenthses est quand
mme enregistr. Pas de changement de ce ct-l puisque ces deux mthodes sont quand mme excutes au sein de
la condition.
Le mot anglais greedy signifie gourmand . En Javascript, les regex sont gnralement gourmandes, ce qui veut dire que
lorsqu'on utilise un quantificateur comme le +, le maximum de caractres est recherch, alors que ce n'est pas toujours le
comportement espr. Petite mise en lumire : nous allons construire une regex qui va extraire l'adresse Web partir de cette
portion de HTML sous forme de chane de caractres :
Code : JavaScript
var html = '<a href="www.mon-adresse.be">Mon site</a>';
212/378
Et a marche :
Code : JavaScript
/<a href="(.+)">/.exec(html);
alert(RegExp.$1); // www.mon-adresse.be
Et l, c'est le drame :
En spcifiant .+ comme quantificateur, on demande de rechercher le plus possible de caractres jusqu' rencontrer les caractres
"> , et c'est ce que le Javascript fait :
Javascript s'arrte la
dernire occurrence souhaite
Le Javascript va trouver la partie surligne : il cherche jusqu' ce qu'il tombe sur la dernire apparition des caractres "> .
Mais ce n'est pas dramatique, fort heureusement !
Pour pallier ce problme, nous allons crire le quantificateur directement suivi du point d'interrogation, comme ceci :
Code : JavaScript
var html = '<a href="www.mon-adresse.be"><strong class="web">Mon
site</strong></a>';
/<a href="(.+?)">/.exec(html);
alert(RegExp.$1);
Le point d'interrogation va faire en sorte que la recherche soit moins gourmande et s'arrte une fois que le minimum requis est
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
213/378
Rechercher et remplacer
Une fonctionnalit intressante des regex est de pouvoir effectuer des rechercher-remplacer . Rechercher-remplacer signifie
qu'on recherche des portions de texte dans une chane de caractres et qu'on remplace ces portions par d'autres. C'est
relativement pratique pour modifier une chane rapidement, ou pour convertir des donnes. Une utilisation frquente est la
conversion de balises BBCode en HTML pour prvisualiser le contenu d'une zone de texte.
Un rechercher-remplacer se fait au moyen de la mthode replace() de l'objet String. Elle reoit deux arguments : la regex et
une chane de caractres qui sera le texte de remplacement. Petit exemple :
Code : JavaScript
var sentence = 'Je m\'appelle Sbastien';
var result = sentence.replace(/Sbastien/, 'Johann');
alert(result); // Affiche : Je m'appelle Johann
L'option g
Nous avions vu l'option i qui permet aux regex d'tre insensibles la casse des caractres. Il existe une autre option, g, qui
signifie rechercher plusieurs fois . Par dfaut, la regex donne prcdemment ne sera excute qu'une fois : ds que
Sbastien sera trouv, il sera remplac et puis c'est tout. Donc si le prnom Sbastien est prsent deux fois, seul le
premier sera remplac. Pour viter a, on utilisera l'option g qui va dire de continuer la recherche jusqu' ce que plus rien ne soit
trouv :
Code : JavaScript
var sentence = 'Il s\'appelle Sbastien. Sbastien crit un
tutoriel.';
var result = sentence.replace(/Sbastien/g, 'Johann');
alert(result); // Il s'appelle Johann. Johann crit un tutoriel.
Ainsi, toutes les occurrences de Sbastien sont correctement remplaces par Johann . Le mot occurrence est nouveau ici,
et il est maintenant temps de l'employer. chaque fois que la regex trouve la portion de texte qu'elle recherche, on parle
d'occurrence. Dans le code prcdent, deux occurrences de Sbastien sont trouves : une juste aprs appelle et l'autre
aprs le premier point.
214/378
Rechercher et capturer
Il est possible d'utiliser les parenthses capturantes pour extraire des informations et les rutiliser au sein de la chane de
remplacement. Par exemple, nous avons une date au format amricain : 05/26/2011, et nous souhaitons la convertir au format
jour/mois/anne. Rien de plus simple :
Code : JavaScript
var date = '05/26/2011';
date = date.replace(/^(\d{2})\/(\d{2})\/(\d{4})$/, 'Le $2/$1/$3');
alert(date); // Le 26/05/2011
Chaque nombre est captur avec une parenthse, et pour rcuprer chaque parenthse, il suffit d'utiliser $1, $2 et $3
(directement dans la chane de caractres), exactement comme nous l'aurions fait avec RegExp.$1.
Et si on veut juste remplacer un caractre par le signe dollar, il faut l'chapper ?
Pour placer un simple caractre $ dans la chane de remplacement, il suffit de le doubler, comme ceci :
Code : JavaScript
var total = 'J\'ai 25 dollars en liquide.';
alert(total.replace(/dollars?/, '$$'); // J'ai 25 $ en liquide
Le mot dollars est effectivement remplac par son symbole. Un point d'interrogation a t plac aprs le s pour pouvoir
trouver soit dollars soit dollar .
Voici un autre exemple illustrant ce principe. L'ide ici est de convertir une balise BBCode de mise en gras
([b]un peu de texte[/b]) en un formatage HTML de ce type : <strong>un peu de texte</strong>.
N'oubliez pas d'chapper les crochets qui sont, pour rappel, des mtacaractres !
Code : JavaScript
var text = 'bla bla [b]un peu de texte[/b] bla [b]bla bla en
gras[/b] bla bla';
text = text.replace(/\[b\]([\s\S]*?)\[\/b\]/g,
'<strong>$1</strong>');
alert(text);
Il s'agit ici de trouver tous les caractres qui se trouvent entre les balises. Or, le point ne trouve que des caractres et des
espaces blanc hormis le retour la ligne. C'est la raison pour laquelle on utilisera souvent la classe comprenant \s et \S quand il
s'agira de trouver du texte comportant des retours la ligne.
Cette petite regex de remplacement est la base d'un systme de prvisualisation du BBCode. Il suffit d'crire une regex de ce type
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
215/378
document.getElementById("output").innerHTML = value;
</script>
<form>
<textarea id="text"></textarea><br />
<button type="button" onclick="preview()">Prvisualiser</button>
<div id="output"></div>
</form>
Essayer !
Si on n'a besoin que de p1 et de p2 et pas des deux derniers paramtres, ces deux derniers peuvent tre omis.
Pour illustrer cela, nous allons raliser un petit script tout simple, qui recherchera des nombres dans une chane et les
transformera en toutes lettres. La transformation se fera au moyen de de la fonction num2Letters() qui a t code lors du
tout premier TP : Convertir un nombre en toutes lettres.
Code : JavaScript
var sentence = 'Dans 22 jours, j\'aurai 24 ans';
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
216/378
});
if (!isNaN(p1)) {
return num2Letters(p1);
}
L'exemple utilise une fonction anonyme, mais il est bien videmment possible de dclarer une fonction :
Code : JavaScript
function convertNumbers(str) {
str = parseInt(str);
if (!isNaN(str)) {
return num2Letters(str);
}
Autres recherches
Il reste deux mthodes de String voir, search() et match(), plus un petit retour sur la mthode split().
217/378
L'alert() affiche donc un tableau contenant tous les prnoms, car il a t demand split() de couper la chane ds
qu'une virgule, un deux-points ou un point-virgule est rencontr.
En rsum
Construire une regex se fait rarement du premier coup. Il faut y aller par tapes, morceau par morceau, car la syntaxe
devient vite complique.
En combinant les parenthses capturantes et la mthode exec(), il est possible d'extraire des informations.
Les recherches doivent se faire en mode non-greedy. C'est plus rapide et correspond plus au comportement que l'on
attend.
L'option g indique qu'il faut effectuer plusieurs remplacements, et non pas un seul.
Il est possible d'utiliser une fonction pour la ralisation d'un remplacement. Ce n'est utile que quand il est ncessaire de
faire des oprations en mme temps que le remplacement.
La mthode search() s'utilise comme la mthode indexOf(), sauf que le paramtre est une regex.
218/378
L'objet Number
L'objet Number est la base de tout nombre et pourtant on ne s'en sert quasiment jamais de manire explicite, car on lui prfre
(comme pour la plupart des objets) l'utilisation de son type primitif. Cet objet possde pourtant des fonctions intressantes
comme, par exemple, celle permettant de faire des conversions depuis une chane de caractres jusqu' un nombre en instanciant
un nouvel objet Number :
Code : JavaScript
var myNumber = new Number('3'); // La chane de caractres 3
est convertie en un nombre de valeur 3
Cependant, cette conversion est imprcise dans le sens o on ne sait pas si on obtiendra un nombre entier ou flottant en retour.
On lui prfre donc les fonctions parseInt() et parseFloat() qui permettent d'tre sr de ce que l'on obtiendra. De plus,
parseInt() utilise un second argument permettant de spcifier la base (2 pour le systme binaire, 10 pour le systme dcimal,
etc.) du nombre crit dans la chane de caractres, ce qui permet de lever tout soupon sur le rsultat obtenu.
Cet objet possde des proprits accessibles directement sans aucune instanciation (on appelle cela des proprits propres
l'objet constructeur). Elles sont au nombre de cinq, et sont donnes ici titre informatif, car leur usage est peu courant :
NaN : vous connaissez dj cette proprit qui signifie Not A Number et qui permet, gnralement, d'identifier l'chec
d'une conversion de chane de caractres en un nombre. noter que cette proprit est aussi disponible dans l'espace
global. Passer par l'objet Number pour y accder n'a donc que peu d'intrt, surtout qu'il est bien rare d'utiliser cette
proprit, car on lui prfre la fonction isNaN(), plus fiable.
MAX_VALUE : cette proprit reprsente le nombre maximum pouvant tre stock dans une variable en Javascript. Cette
constante peut changer selon la version du Javascript utilise.
MIN_VALUE : identique la constante MAX_VALUE sauf que l il s'agit de la valeur minimale.
POSITIVE_INFINITY : il s'agit ici d'une constante reprsentant l'infini positif. Vous pouvez l'obtenir en rsultat d'un
calcul si vous divisez une valeur positive par 0. Cependant, son utilisation est rare, car on lui prfre la fonction
isFinite(), plus fiable.
NEGATIVE_INFINITY : identique POSITIVE_INFINITY sauf que l il s'agit de l'infini ngatif. Vous pouvez
obtenir cette constante en rsultat d'un calcul si vous divisez une valeur ngative par 0.
Passons donc aux essais :
Code : JavaScript
var max = Number.MAX_VALUE, // Comme vous pouvez le constater, nous
n'instancions pas d'objet, comme pour un accs au prototype
inf = Number.POSITIVE_INFINITY;
if (max < inf) {
alert("La valeur maximum en Javascript est infrieure l'infini
! Surprenant, n'est-ce pas ?");
}
Essayer !
Du ct des mthodes, l'objet Number n'est pas bien plus intressant, car toutes les mthodes qu'il possde sont dj
supportes par l'objet Math. Nous allons donc faire l'impasse dessus.
L'objet Math
Aprs une premire sous-partie assez peu intressante, nous passons enfin l'objet Math qui va rellement nous servir ! Tout
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
219/378
Les proprits
Les proprits de l'objet Math sont des constantes qui dfinissent certaines valeurs mathmatiques comme le nombre pi () ou
le nombre d'Euler (e). Nous ne parlons que de ces deux constantes car les autres ne sont pas souvent utilises en Javascript.
Pour les utiliser, rien de bien compliqu :
Code : JavaScript
alert(Math.PI); // Affiche la valeur du nombre pi
alert(Math.E); // Affiche la valeur du nombre d'Euler
Voil tout, les proprits de l'objet Math ne sont pas bien dures utiliser donc il n'y a pas grand-chose vous apprendre
dessus. En revanche, les mthodes sont nettement plus intressantes !
Les mthodes
L'objet Math comporte de nombreuses mthodes permettant de faire divers calculs un peu plus volus qu'une simple division.
Il existe des mthodes pour le calcul des cosinus et sinus, des mthodes d'arrondi et de troncature, etc. Elles sont assez
nombreuses pour faire bon nombre d'applications pratiques.
Arrondir et tronquer
Vous aurez souvent besoin d'arrondir vos nombres en Javascript, notamment si vous faites des animations. Il est par exemple
impossible de dire un lment HTML qu'il fait 23,33 pixels de largeur, il faut un nombre entier. C'est pourquoi nous allons
aborder les mthodes floor(), ceil() et round().
La mthode floor() retourne le plus grand entier infrieur ou gal la valeur que vous avez passe en paramtre :
Code : JavaScript
Math.floor(33.15); // Retourne : 33
Math.floor(33.95); // Retourne : 33
Math.floor(34);
// Retourne : 34
Concernant la mthode ceil(), celle-ci retourne le plus petit entier suprieur ou gal la valeur que vous avez passe en
paramtre :
Code : JavaScript
Math.ceil(33.15); // Retourne : 34
Math.ceil(33.95); // Retourne : 34
Math.ceil(34);
// Retourne : 34
220/378
Code : JavaScript
Math.round(33.15); // Retourne : 33
Math.round(33.95); // Retourne : 34
Math.round(34);
// Retourne : 34
Concernant le calcul de la racine carre d'un nombre, il existe aussi une mthode prvue pour cela, elle se nomme sqrt()
(abrviation de square root) :
Code : JavaScript
Math.sqrt(9); // Retourne : 3
221/378
Essayer !
L, notre script est un peu limit du coup, la solution est donc de crer notre propre fonction qui va grer les nombres minimum
(inclus) et maximum (exclu) :
Code : JavaScript
function rand(min, max, integer) {
if (!integer) {
return Math.random() * (max - min) + min;
} else {
return Math.floor(Math.random() * (max - min + 1) + min);
}
}
Et voil une fonction prte tre utilise ! Le troisime paramtre sert dfinir si l'on souhaite obtenir un nombre entier ou non.
Essayer une adaptation de ce code !
Cette fonction est assez simple en terme de rflexion : on prend le nombre minimum que l'on soustrait au maximum, on obtient
alors l'intervalle de valeur qui n'a plus qu' tre multipli au nombre alatoire (qui est compris entre 0 et 1), le rsultat obtenu sera
alors compris entre 0 et la valeur de l'intervalle, il ne reste alors plus qu' lui ajouter le nombre minimum pour obtenir une valeur
comprise entre notre minimum et notre maximum !
Nous pensons qu'il est bon de vous informer d'une certaine chose : la mthode random() de l'objet Math ne renvoie
pas vraiment un nombre alatoire, ce n'est d'ailleurs pas rellement possible sur un ordinateur. Cette mthode est base
sur plusieurs algorithmes qui permettent de renvoyer un nombre pseudo-alatoire, mais le nombre n'est jamais vraiment
alatoire. vrai dire, cela ne devrait pas vous affecter dans vos projets, mais il est toujours bon de le savoir.
Les inclassables
Bien que les objets Number et Math implmentent l'essentiel des mthodes de gestion des donnes numriques qui existent en
Javascript, certaines fonctions globales permettent de faire quelques conversions et contrles de donnes un peu plus pousss.
222/378
Alors pourquoi cette diffrence de rsultat ? La solution est simple : en l'absence d'un second argument, les fonctions
parseInt() et parseFloat() vont tenter de deviner la base utilise et donc le systme de numration associ par le
nombre crit dans la chane de caractres. Ici, la chane de caractres commence par un 0, ce qui est caractristique du systme
octal, on obtient donc 0 en retour. Afin d'viter d'ventuelles conversions hasardeuses, il est toujours bon de spcifier le
systme de numration de travail.
Attention une chose ! Les fonctions parseInt() et parseFloat() peuvent russir retrouver un nombre dans
une chane de caractres, ainsi, la chane de caractres 303 pixels renverra bien 303 aprs conversion.
Cependant, cela ne fonctionne que si la chane de caractres commence par le nombre retourner. Ainsi, la chane de
caractres Il y a 303 pixels ne renverra que la valeur NaN. Pensez-y !
Quant isFinite(), cette fonction renvoie true si le nombre ne tend pas vers l'infini :
Code : JavaScript
var myNumber = 1/0; // 1 divis par 0 tend vers l'infini
alert(isFinite(myNumber)); // Affiche false , ce nombre tend
vers l'infini
223/378
Mais pourquoi utiliser ces deux fonctions ? Je n'ai qu' vrifier si ma variable contient la valeur NaN ou Infinity
Essayer !
Voyez-vous le problme ? Cette variable ne contient pas de nombre, mais ce code croit pourtant que c'est le cas. Cela est d au
fait que l'on ne fait que tester la prsence de la valeur NaN. Or elle est prsente uniquement si la tentative d'criture d'un nombre
a chou (une conversion loupe par exemple), elle ne sera jamais prsente si la variable tait destine contenir autre chose
qu'un nombre.
Un autre facteur important aussi, c'est que la valeur NaN n'est pas gale elle-mme !
Code : JavaScript
alert(NaN == NaN); // Affiche : false
Bref, la fonction isNaN() est utile car elle vrifie si votre variable tait destine contenir un nombre et vrifie ensuite que ce
nombre ne possde pas la valeur NaN.
Concernant isFinite(), un nombre peut tendre soit vers l'infini positif, soit vers l'infini ngatif. Une condition de ce genre ne
peut donc pas fonctionner :
Code : JavaScript
var myNumber = -1/0;
if (myNumber == Number.POSITIVE_INFINITY) {
alert("Ce nombre tend vers l'infini.");
} else {
alert("Ce nombre ne tend pas vers l'infini.");
}
Essayer !
Ce code est faux, on ne fait que tester si notre nombre tend vers l'infini positif, alors que la fonction isFinite() se charge de
tester aussi si le nombre tend vers l'infini ngatif.
En rsum
Un objet possde parfois des proprits issues du constructeur. C'est le cas de l'objet Number, avec des proprits
comme Number.MAX_VALUE ou Number.NaN.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
224/378
De mme que Number, l'objet Math possde ce genre de proprits. Utiliser est alors simple : Math.PI.
Il faut privilgier parseInt() et parseFloat() pour convertir une chane de caractres en un nombre.
L'usage des proprits de l'objet Number lors de tests est dconseill : il vaut mieux utiliser les fonctions globales
prvues cet effet, comme par exemple isNaN() au lieu de NaN.
225/378
La gestion du temps
La gestion du temps est importante en Javascript ! Elle vous permet de temporiser vos codes et donc de crer, par exemple, des
animations, des compteurs rebours et bien d'autres choses qui ncessitent une temporisation dans un code.
En plus de cela, nous allons aussi apprendre manipuler la date et l'heure.
Le systme de datation
L'heure et la date sont gres par un seul et mme objet qui se nomme Date. Avant de l'tudier de fond en comble, nous allons
d'abord comprendre comment fonctionne le systme de datation en Javascript.
Il s'agit en fait, en Javascript, du nombre de millisecondes coules depuis le 1er janvier 1970 minuit. Cette manire d'enregistrer
la date est trs fortement inspire du systme d'horodatage utilis par les systmes Unix. La seule diffrence entre le systme
Unix et le systme du Javascript, c'est que ce dernier stocke le nombre de millisecondes, tandis que le premier stocke le nombre
de secondes. Dans les deux cas, ce nombre s'appelle un timestamp.
Au final, ce nombre ne nous sert vraiment qu' peu de choses nous, dveloppeurs, car nous allons utiliser l'objet Date qui va
s'occuper de faire tous les calculs ncessaires pour obtenir la date ou l'heure partir de n'importe quel timestamp.
L'objet Date
L'objet Date nous fournit un grand nombre de mthodes pour lire ou crire une date. Il y en a d'ailleurs tellement que nous
n'allons en voir qu'une infime partie.
Le constructeur
Commenons par le constructeur ! Ce dernier prend en paramtre de nombreux arguments et s'utilise de diffrentes manires.
Voici les quatre manires de l'utiliser :
Code : JavaScript
new Date();
new Date(timestamp);
new Date(dateString);
new Date(anne, mois, jour [, heure, minutes, secondes,
millisecondes ]);
chaque instanciation de l'objet Date, ce dernier enregistre soit la date actuelle si aucun paramtre n'est spcifi, soit une date
que vous avez choisie. Les calculs effectus par les mthodes de notre objet instanci se feront partir de la date enregistre.
Dtaillons l'utilisation de notre constructeur :
La premire ligne instancie un objet Date dont la date est fixe celle de l'instant mme de l'instanciation.
La deuxime ligne vous permet de spcifier le timestamp utiliser pour notre instanciation.
La troisime ligne prend en paramtre une chane de caractres qui doit tre interprtable par la mthode parse(), nous
y reviendrons.
Enfin, la dernire ligne permet de spcifier manuellement chaque composant qui constitue une date, nous retrouvons
donc en paramtres obligatoires : l'anne, le mois et le jour. Les quatre derniers paramtres sont facultatifs (c'est pour cela
que vous voyez des crochets, ils signifient que les paramtres sont facultatifs). Ils seront initialiss 0 s'ils ne sont pas
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
226/378
spcifis, nous y retrouvons : les heures, les minutes, les secondes et les millisecondes.
Cette date reprsente donc le samedi 4 mai 1991 20h pile avec un dcalage de deux heures supplmentaires par rapport
l'horloge de Greenwich.
Il existe plusieurs manires d'crire la date, cependant nous ne fournissons que celle-l, car les drives sont nombreuses. Si vous
voulez connatre toutes les syntaxes existantes, allez donc jeter un coup dil au document qui traite de la standardisation de
cette syntaxe (la syntaxe est dcrite partir de la page 11).
Enfin, pour utiliser cette syntaxe avec notre mthode, rien de plus simple :
Code : JavaScript
var timestamp = Date.parse('Sat, 04 May 1991 20:00:00 GMT+02:00');
alert(timestamp); // Affiche : 673380000000
Ces huit mthodes possdent chacune une fonction homologue de type set . Par exemple, avec la mthode
getDay() il existe aussi, pour le mme objet Date, la mthode setDay() qui permet de dfinir le jour en le passant
en paramtre.
Chacune de ces mthodes s'utilise d'une manire enfantine : vous instanciez un objet Date et il ne vous reste plus qu' appeler
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
227/378
Comment allons-nous oprer maintenant ? Nous allons rcuprer le timestamp avant l'excution de la fonction puis aprs son
excution, il n'y aura ensuite plus qu' soustraire le premier timestamp au deuxime et nous aurons notre temps d'excution !
Allons-y :
Code : JavaScript
var firstTimestamp = new Date().getTime(); // On obtient le
timestamp avant l'excution
slow(); // La fonction travaille
var secondTimestamp = new Date().getTime(), // On rcupre le
timestamp aprs l'excution
result = secondTimestamp - firstTimestamp; // On fait la
soustraction
alert("Le temps d'excution est de : " + result + "
millisecondes.");
228/378
En utilisant une sale mthode que vous devez bannir de tous vos codes :
Code : JavaScript
setTimeout('myFunction()', 2000);
Pourquoi ne pas procder de cette manire ? Tout simplement parce que cela appelle implicitement la fonction eval()
qui va se charger d'analyser et excuter votre chane de caractres. Pour de plus amples informations, redirigez-vous vers
l'excellent Bonnes pratiques Javascript par nod_ sur le Site du Zro.
En ce qui concerne le deuxime paramtre, il n'y a pas grand-chose dire mis part qu'il s'agit du temps spcifier (en
millisecondes) votre fonction. Une bonne chose savoir c'est que ce temps n'a que peu d'intrt tre en dessous de 10 ms
(environ, cela dpend des navigateurs !) pour la simple et bonne raison que la plupart des navigateurs n'arriveront pas excuter
votre code avec un temps aussi petit. En clair, si vous spcifiez un temps de 5 ms, votre code sera probablement excut au bout
de 10 ms.
Faites attention avec la fonction setTimeout(), il n'y a pas de o majuscule. C'est une erreur trs frquente !
229/378
Code : JavaScript
setTimeout(myFunction, 2000, param1, param2);
Ainsi, au terme du temps pass en deuxime paramtre, notre fonction myFunction() sera appele de la manire suivante :
Code : JavaScript
myFunction(param1, param2);
Cependant, cette technique ne fonctionne pas sur les vieilles versions d'Internet Explorer, il nous faut donc ruser :
Code : JavaScript
setTimeout(function() {
myFunction(param1, param2);
}, 2000);
Nous avons cr une fonction anonyme qui va se charger d'appeler la fonction finale avec les bons paramtres, et cela
fonctionne sur tous les navigateurs !
230/378
})();
</script>
Essayer !
On peut mme aller un peu plus loin en grant plusieurs actions temporelles la fois :
Code : HTML
<button id="myButton">Annuler le compte rebours (5s)</button>
<script>
(function() {
var button = document.getElementById('myButton'),
timeLeft = 5;
var timerID = setTimeout(function() { // On cre notre compte
rebours
clearInterval(intervalID);
button.innerHTML = "Annuler le compte rebours (0s)";
alert("Vous n'tes pas trs ractif vous !");
}, 5000);
var intervalID = setInterval(function() { // On met en place
l'intervalle pour afficher la progression du temps
button.innerHTML = "Annuler le compte rebours (" + -timeLeft + "s)";
}, 1000);
button.onclick = function() {
clearTimeout(timerID); // On annule le compte rebours
clearInterval(intervalID); // Et l'intervalle
alert("Le compte rebours a bien t annul.");
};
})();
</script>
Essayer !
231/378
Le problme ici, c'est que notre opacit a t modifie immdiatement de 1 0,2. Nous, nous voulons que ce soit progressif, il
faudrait donc faire comme ceci :
Code : JavaScript
var myImg = document.getElementById('myImg');
for (var i = 0.9 ; i >= 0.2 ; i -= 0.1) {
myImg.style.opacity = i;
}
Mais encore une fois, tout s'est pass en une fraction de seconde ! C'est l que les actions temporelles vont entrer en action et
ceci afin de temporiser notre code et de lui laisser le temps d'afficher la progression l'utilisateur ! Dans notre cas, nous allons
utiliser la fonction setTimeout() :
Code : JavaScript
var myImg = document.getElementById('myImg');
function anim() {
var s = myImg.style,
result = s.opacity = parseFloat(s.opacity) - 0.1;
if ( result > 0.2 ) {
setTimeout(anim, 50); // La fonction anim() fait appel
elle-mme si elle n'a pas termin son travail
}
}
anim(); // Et on lance la premire phase de l'animation
Essayer !
Et voil, cela fonctionne sans problme et ce n'est pas aussi compliqu qu'on ne le pense au premier abord ! Alors aprs il est
possible d'aller bien plus loin en combinant les animations, mais, maintenant que vous avez les bases, vous devriez tre capables
de faire toutes les animations dont vous rvez !
Vous remarquerez que nous avons utilis la fonction setTimeout() au lieu de setInterval() pour raliser
notre animation. Pourquoi donc ? Eh bien il faut savoir que setTimeout() est en fait bien plus stable que
setInterval(), ce qui fait que vous obtenez des animations bien plus fluides. Dans l'ensemble, mieux vaut se
passer de setInterval() et utiliser setTimeout() en boucle, quel que soit le cas d'application.
En rsum
Le Javascript se base sur un timestamp exprim en millisecondes pour calculer les dates. Il faut faire attention, car un
timestamp est parfois exprim en secondes, comme au sein du systme Unix ou dans des langages comme le PHP.
En instanciant, sans paramtres, un objet Date, ce dernier contient la date de son instanciation. Il est ensuite possible
de dfinir une autre date par le biais de mthodes ad hoc.
Date est couramment utilis pour dterminer le temps d'excution d'un script. Il suffit de soustraire le timestamp du
dbut au timestamp de fin.
Plusieurs fonctions existent pour crer des dlais d'excution et de rptition, ce qui peut tre utilis pour raliser des
animations.
232/378
Les tableaux
Dans la premire partie de ce cours vous avez dj pu vous initier de manire basique aux tableaux. Ce que vous y avez appris
vous a srement suffi jusqu' prsent, mais il faut savoir que les tableaux possdent de nombreuses mthodes qui vous sont
encore inconnues et qui pourtant pourraient vous aider facilement traiter leur contenu. Dans ce chapitre nous allons donc
tudier de manire avance l'utilisation des tableaux.
L'objet Array
L'objet Array est la base de tout tableau. Il possde toutes les mthodes et les proprits ncessaires l'utilisation et la
modification des tableaux. Prcisons que cet objet ne concerne que les tableaux itratifs, les objets littraux ne sont pas des
tableaux, ce sont des objets, tout simplement !
Le constructeur
Cet objet peut tre instanci de trois manires diffrentes. Cependant, gardez bien l'esprit que l'utilisation de son type primitif
est bien prfrable l'instanciation de son objet. Nous n'abordons ce sujet qu' titre indicatif.
Voici un cas particulier du constructeur de l'objet Array : il est possible de spcifier la longueur du tableau. Cela parat assez
intressant sur le principe, mais en ralit cela ne sert quasiment rien vu que le Javascript redfinit la taille des tableaux quand
on ajoute ou supprime un item du tableau.
Les proprits
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
233/378
Ici, les tableaux ont le mrite de rendre les choses simples, ils ne possdent qu'une seule proprit (accessible uniquement aprs
instanciation) que vous connaissez dj tous : length ! Pour rappel, cette proprit est en lecture seule et vous indique
combien d'lments existent dans votre tableau.
Ainsi, avec ce tableau :
Code : JavaScript
var myArray = [
'lement1',
'lement2',
'lement3',
'lement4'
];
Les mthodes
Plusieurs mthodes ont dj t abordes au cours du chapitre de la premire partie consacr aux tableaux. Elles sont de
nouveau listes dans ce chapitre, mais de manire plus approfondie afin que celui-ci vous serve, en quelque sorte, de rfrence.
Pas terrible, n'est-ce pas ? Heureusement, les tableaux possdent une mthode nomme concat() qui nous permet d'obtenir le
rsultat souhait :
Code : JavaScript
var myArray = ['test1', 'test2'].concat(['test3', 'test4']);
alert(myArray);
234/378
Notez bien que la mthode concat() ne modifie aucun tableau ! Elle ne fait que retourner un tableau qui correspond
la concatnation souhaite.
Parcourir un tableau
Le fait de parcourir un tableau est une faon de faire trs courante en programmation, que ce soit en Javascript ou dans un autre
langage. Vous savez dj faire a de cette manire :
Code : JavaScript
var myArray = ["C'est", "un", "test"],
length = myArray.length;
for (var i = 0 ; i < length ; i++) {
alert(
'Index : ' + i
+ '\n' +
'Valeur : ' + myArray[i]
);
}
Essayer !
Cependant, ce code est quand mme contraignant, nous sommes obligs de crer deux variables, une pour l'incrmentation, et
une pour stocker la longueur de notre tableau (cela vite notre boucle d'aller chercher la longueur dans le tableau, on
conomise des ressources), tout a n'est pas trs pratique.
C'est l qu'intervient une nouvelle mthode nomme forEach(). Elle est supporte par tous les navigateurs sauf Internet
Explorer 8 et ses versions antrieures. Cette mthode prend pour paramtre deux arguments, le premier reoit la fonction
excuter pour chaque index existant et le deuxime (qui est facultatif) reoit un objet qui sera point par le mot-cl this dans la
fonction que vous avez spcifie pour le premier argument.
Concentrons-nous sur la fonction passe en paramtre. Celle-ci sera excute pour chaque index existant (dans l'ordre croissant
bien entendu) et recevra en paramtres trois arguments :
Le premier contient la valeur contenue l'index actuel ;
Le deuxime contient l'index actuel ;
Le troisime est une rfrence au tableau actuellement parcouru.
Essayons donc :
Code : JavaScript
var myArray = ["C'est", "un", "test"];
myArray.forEach(function(value, index, array) {
alert(
'Index : ' + index
+ '\n' +
'Valeur : ' + value
);
});
Essayer !
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
235/378
Vous avez srement constat que nous n'utilisons pas l'argument array dans notre fonction anonyme, vous pouvez trs bien
ne pas le spcifier, votre code fonctionnera sans problme !
Faites attention avec cette mthode ! Celle-ci ne fonctionne qu'avec des tableaux, elle n'existe pas pour les collections
d'lments retournes par les mthodes du style document.getElementsByTagName() !
Dans ce code, c'est bien le tableau ['test'] qui a t trouv, et non pas la chane de caractres 'test' !
Les deux tableaux sont de mme valeur mais sont pourtant reconnus comme tant deux tableaux diffrents, tout simplement parce
que ce ne sont pas les mmes instanciations de tableaux ! Lorsque vous crivez une premire fois ['test'], vous faites une
premire instanciation de tableau, donc la deuxime fois que vous crirez cela vous ferez une deuxime instanciation.
La solution pour tre sr de comparer deux mmes instanciations est de passer la rfrence de votre instanciation une variable.
Ainsi, vous n'avez plus aucun problme :
Code : JavaScript
var myArray = ['test'];
alert(myArray == myArray); // Affiche : true
Pour terminer sur nos deux fonctions, sachez qu'elles possdent, elles aussi, un second paramtre permettant de spcifier partir
de quel index vous souhaitez faire dbuter la recherche. Une autre bonne chose savoir aussi : elles ne sont pas supportes par
les versions antrieures Internet Explorer 9 !
Trier un tableau
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
236/378
Deux mthodes peuvent vous servir trier un tableau. Nous allons commencer par la plus simple d'entre elles : reverse().
La mthode reverse()
Cette mthode ne prend aucun argument en paramtre et ne retourne aucune valeur, son seul rle est d'inverser l'ordre des
valeurs de votre tableau :
Code : JavaScript
var myArray = [1, 2, 3, 4, 5];
myArray.reverse();
alert(myArray); // Affiche : 5,4,3,2,1
La mthode sort()
En ce qui concerne la deuxime mthode, les choses se corsent un peu. Celle-ci se nomme sort(), par dfaut cette mthode trie
votre tableau par ordre alphabtique uniquement. Mais cette mthode possde aussi un argument facultatif permettant de
spcifier l'ordre dfinir, et c'est l que les choses se compliquent. Tout d'abord, prenons un exemple simple :
Code : JavaScript
var myArray = [3, 1, 5, 10, 4, 2];
myArray.sort();
alert(myArray); // Affiche : 1,10,2,3,4,5
Quand nous disions que cette mthode ne triait, par dfaut, que par ordre alphabtique, c'tait vrai et ce dans tous les cas ! Cette
mthode possde en fait un mode de fonctionnement bien particulier : elle commence par convertir toutes les donnes du tableau
en chanes de caractres et ce n'est qu'aprs a qu'elle applique son tri alphabtique. Dans notre exemple, la logique peut vous
paratre obscure, mais si nous essayons de remplacer nos chiffres par des caractres cela devrait vous paratre plus logique :
Code : Autre
0 = a ; 1 = b ; 2 = c
Notre suite 1, 10, 2 devient donc b, ba, c ! Ce tri vous parat dj plus logique avec des caractres, non ? Eh bien, pour la
mthode sort(), cette logique s'applique mme aux chiffres !
Venons-en maintenant l'argument facultatif de sort() : il a pour but de raliser un tri personnalis. Il doit contenir une
rfrence vers une fonction que vous avez cre, cette dernire devant possder deux arguments qui seront spcifis par la
mthode sort(). La fonction devra alors dire si les valeurs transmises en paramtres sont de mme valeur, ou bien si l'une des
deux est suprieure l'autre.
Notre but ici est de faire en sorte que notre tri soit, non pas alphabtique, mais par ordre croissant (et donc que la valeur 10 se
retrouve la fin du tableau). Nous allons donc commencer par crer notre fonction anonyme que nous fournirons au moment du
tri :
Code : JavaScript
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
237/378
function(a, b) {
// Comparaison des valeurs
}
Nous avons notre fonction, mais que faire maintenant ? Eh bien, nous allons devoir comparer les deux valeurs fournies. Avant
tout, sachez que la mthode sort() ne convertit pas les donnes du tableau en chanes de caractres lorsque vous avez dfini
l'argument facultatif, ce qui fait que les valeurs que nous allons recevoir en paramtres seront bien de type Number et non pas
de type String, cela nous facilite dj la tche !
Commenons par crire le code pour comparer les valeurs :
Code : JavaScript
function(a, b) {
if (a < b) {
// La valeur de a est infrieure celle de b
} else if (a > b) {
// La valeur de a est suprieure celle de b
} else {
// Les deux valeurs sont gales
}
}
Bien, nous avons fait nos comparaisons, mais que faut-il renvoyer la mthode sort() pour lui indiquer qu'une valeur est
infrieure, suprieure ou gale l'autre ?
Le principe est simple :
On retourne -1 lorsque a est infrieur b ;
On retourne 1 lorsque a est suprieur b ;
Et on retourne 0 quand les valeurs sont gales.
Notre fonction devient donc la suivante :
Code : JavaScript
function(a, b) {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
}
238/378
myArray.sort(function (a, b) {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
});
alert(myArray); // Affiche : 1,2,3,4,5,10
Et voil ! La mthode sort() trie maintenant notre tableau dans l'ordre croissant !
Notons aussi que le deuxime argument possde une petite particularit intressante qui rappellera un peu le PHP aux
connaisseurs :
Code : JavaScript
var myArray = [1, 2, 3, 4, 5];
alert(myArray.slice(1, -1)); // Affiche : 2,3,4
Lorsque vous spcifiez un nombre ngatif au deuxime argument, alors l'extraction se terminera l'index de fin moins la valeur
que vous avez spcifie. Dans notre exemple, l'extraction se termine donc l'index qui prcde celui de la fin du tableau, donc
l'index 3.
239/378
Notez bien aussi une chose : si vous ajoutez des lments dans le tableau, vous pouvez mettre le deuxime argument 0, ce qui
aura pour effet d'ajouter des lments sans tre oblig d'en supprimer d'autres. Cette mthode splice() peut donc tre utilise
comme une mthode d'insertion de donnes.
Cependant, sachez que cette fonction est trs rcente et peut donc ne pas tre disponible sur de nombreux navigateurs (vous
pouvez dj oublier les versions d'Internet Explorer antrieures la neuvime). Vous trouverez ici un tableau de compatibilit
pour cette fonction.
240/378
push() : ajoute un ou plusieurs lments la fin du tableau (un argument par lment ajout) et retourne la nouvelle
taille de ce dernier.
pop() : retire et retourne le dernier lment d'un tableau.
unshift() : ajoute un ou plusieurs lments au dbut du tableau (un argument par lment ajout) et retourne la
nouvelle taille de ce dernier.
shift() : retire et retourne le premier lment d'un tableau.
Les piles
Les piles partent du principe que le premier lment ajout sera le dernier retir, comme une pile de livres ! Elles sont utilisables
de deux manires diffrentes : soit avec les deux mthodes push() et pop(), soit avec les deux restantes unshift() et
shift(). Dans le premier cas, la pile sera empile et dpile la fin du tableau, dans le deuxime cas, les oprations se feront
au dbut du tableau.
Code : JavaScript
var myArray = ['Livre 1'];
var result = myArray.push('Livre 2', 'Livre 3');
alert(myArray); // Affiche : Livre 1,Livre 2,Livre 3
alert(result); // Affiche : 3
result = myArray.pop();
alert(myArray); // Affiche : Livre 1,Livre 2
alert(result); // Affiche : Livre 3
Aucun problme pour les mthodes push() et pop() ? Essayons maintenant le couple unshift()/shift() :
Code : JavaScript
var myArray = ['Livre 3'];
var result = myArray.unshift('Livre 1', 'Livre 2');
alert(myArray); // Affiche : Livre 1,Livre 2,Livre 3
alert(result); // Affiche : 3
result = myArray.shift();
alert(myArray); // Affiche : Livre 2,Livre 3
alert(result); // Affiche : Livre 1
Les files
Les files partent d'un autre principe tout aussi simple : le premier lment ajout est le premier sorti, comme une file d'attente.
Elles sont, elles aussi, utilisables de deux manires diffrentes : soit avec le couple push()/shift(), soit avec le couple
unshift()/pop().
En Javascript, les files sont bien moins utilises que les piles, car elles sont dpendantes des mthodes unshift() et
shift(). Ces dernires souffrent d'un manque de performance, nous y reviendrons.
241/378
Code : JavaScript
var myArray = ['Fanboy 1', 'Fanboy 2'];
var result = myArray.push('Fanboy 3', 'Fanboy 4');
alert(myArray); // Affiche : Fanboy 1,Fanboy 2,Fanboy 3,Fanboy 4
alert(result); // Affiche : 4
result = myArray.shift();
alert(myArray); // Affiche : Fanboy 2,Fanboy 3,Fanboy 4
alert(result); // Affiche : Fanboy 1
alert(result); // Affiche : 4
result = myArray.pop();
alert(myArray); // Affiche : Fanboy 1,Fanboy 2,Fanboy 3
alert(result); // Affiche : Fanboy 4
=>
=>
=>
=>
'test
'test
'test
'test
supplmentaire'
1'
2'
3'
242/378
Ce qui fait que nous devons rcrire tous les index suivants :
Code : Console
0
1
2
3
=>
=>
=>
=>
'test
'test
'test
'test
supplmentaire'
1'
2'
3'
Si le tableau possde de nombreux lments, cela peut parfois prendre un peu de temps. C'est ce qui fait que les piles sont
gnralement prfres aux files en Javascript, car elles peuvent se passer de ces deux mthodes. Cela dit, il faut relativiser : la
perte de performance n'est pas dramatique, vous pouvez trs bien vous en servir pour des tableaux de petite taille (en dessous
de 10 000 entres, en gros), mais au-dessus il faudra peut-tre songer utiliser les piles ou bien utiliser des scripts qui
rsolvent ce genre de problmes.
En rsum
Pour concatner deux tableaux, il faut utiliser la mthode concat(), car l'oprateur + ne fonctionne pas selon le
comportement voulu.
La mthode forEach() permet de parcourir un tableau en s'affranchissant d'une boucle for. Mais cette mthode n'est
pas supporte par les versions d'Internet Explorer antrieures la version 9.
indexOf() et lastIndexOf() permettent de rechercher un lment qui peut tre une chane de caractres, un
nombre, ou mme un tableau. Il faudra toutefois faire attention lors de la comparaison de deux tableaux.
L'utilisation d'une fonction pour trier un tableau est possible et se rvle particulirement utile pour effectuer un tri
personnalis.
Les piles et les files sont un moyen efficace pour stocker et accder de grandes quantits de donnes.
243/378
Les images
Les objets natifs en Javascript couvrent de nombreux domaines comme le temps ou les mathmatiques, mais il existe des objets
encore plus particuliers comme Image ! Cet objet permet de faire des manipulations assez sommaires sur une image et permet
surtout de savoir si elle a t entirement tlcharge, c'est gnralement pour cela que l'on va se servir de cet objet.
Nous tenons faire une petite remarque avant que vous n'alliez plus loin dans ce chapitre : il existe bon nombre de
documentations Javascript sur le Web mais aucune d'entre elles n'a jamais t capable de dfinir correctement quels
sont les proprits ou les vnements standards de l'objet Image. Il se peut donc que vous trouviez de nouvelles
proprits ou vnements dans diverses documentations. Notre but dans ce cours est de vous fournir des informations
fiables, nous n'aborderons donc que les proprits ou vnements qui fonctionnent parfaitement bien et ne causent
aucun problme majeur, quel que soit le navigateur utilis.
L'objet Image
Comme dit dans l'introduction, la manipulation des images se fait par le biais de l'objet Image, qui possde plusieurs proprits
permettant d'obtenir divers renseignements sur l'image actuellement instancie.
Le constructeur
Le constructeur de l'objet Image ne prend aucun argument en paramtre, cela a au moins le mrite d'tre simple :
Code : JavaScript
var myImg = new Image();
Proprits
Voici une liste non exhaustive des proprits de l'objet Image. Consultez la documentation pour une liste complte (mais pas
forcment fiable).
Nom de la
proprit
Contient
width
Contient la largeur originale de l'image. Vous pouvez redfinir cette proprit pour modifier la taille de l'image.
height
Contient la hauteur originale de l'image. Vous pouvez redfinir cette proprit pour modifier la taille de l'image.
src
Cette proprit vous sert spcifier l'adresse (absolue ou relative) de l'image. Une fois que cette proprit est
spcifie, l'image commence immdiatement tre charge.
Il existe une proprit nomme complete qui permet de savoir si l'image a t entirement charge. Cependant, cette
proprit n'est pas standard (sauf en HTML5) et son implmentation est assez hasardeuse, parfois cette proprit
fonctionne, mais la plupart du temps on obtient une valeur errone. Nous en dconseillons donc l'utilisation.
vnements
L'objet Image ne possde qu'un seul vnement nomm load, il est trs utile, notamment lorsque l'on souhaite crer un script
de type Lightbox, car il vous permet de savoir quand une image est charge.
Son utilisation se fait comme tout vnement :
Code : JavaScript
var myImg = new Image();
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
244/378
myImg.src = 'adresse_de_mon_image';
myImg.onload = function() { // Il est bien entendu possible
d'utiliser le DOM-2
// Etc.
};
Cependant, ce code risque de causer un problme majeur : notre vnement pourrait ne jamais se dclencher ! Pourquoi donc ?
Eh bien, parce que nous avons spcifi l'adresse de notre image avant mme d'avoir spcifi notre vnement, ce qui fait que si
l'image a t trop rapidement charge, l'vnement load se sera dclench avant mme que nous n'ayons eu le temps de le
modifier.
Il existe une solution toute simple pour pallier ce problme, il suffit de spcifier l'adresse de notre image aprs avoir modifi notre
vnement :
Code : JavaScript
var myImg = new Image();
myImg.onload = function() { // tape 1 : on modifie notre vnement
// Etc.
};
myImg.src = 'adresse_de_mon_image'; // tape 2 : on spcifie
l'adresse de notre image
Ainsi, vous n'aurez aucun problme : votre vnement sera toujours dclench !
Particularits
L'objet Image est un peu spcial, dans le sens o vous pouvez l'ajouter votre arbre DOM comme vous le feriez avec la valeur
retourne par la mthode document.createElement(). Ce comportement est spcial et ne peut se rvler utile que dans
de trs rares cas d'application, mais il est quand mme prfrable de vous en parler afin que vous connaissiez l'astuce :
Code : JavaScript
var myImg = new Image();
myImg.src = 'adresse_de_mon_image';
document.body.appendChild(myImg); // L'image est ajoute au DOM
Mise en pratique
Nous allons rapidement voir une petite mise en pratique de l'objet Image en ralisant une Lightbox trs simple. Le principe d'une
Lightbox est de permettre l'affichage d'une image en taille relle directement dans la page Web o se trouvent les miniatures de
toutes nos images.
La mise en pratique qui va suivre ncessite de possder quelques images pour tester les codes que nous allons fournir.
Plutt que de vous embter chercher des images, les redimensionner puis les renommer, vous pouvez utiliser notre
pack d'images toutes prtes que vous pouvez tlcharger ici.
Commenons tout d'abord par un code HTML simple pour lister nos miniatures et les liens vers les images originales :
Code : HTML
<p>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
245/378
originale"><img
originale"><img
originale"><img
originale"><img
Notre but ici est de bloquer la redirection des liens et d'afficher les images d'origine directement dans la page Web, plutt que
dans une nouvelle page. Pour cela, nous allons devoir parcourir tous les liens de la page, bloquer leurs redirections et afficher
l'image d'origine une fois que celle-ci aura fini d'tre charge (car une Lightbox est aussi conue pour embellir la navigation).
Normalement, de nombreux autres paramtres entrent en compte pour la ralisation d'une Lightbox, comme la
vrification de l'existence d'une miniature dans un lien. Ici, nous faisons abstraction de ces vrifications ennuyeuses et
allons l'essentiel. Gardez bien l'esprit que le script que nous ralisons ici n'est applicable qu' l'exemple que nous
sommes en train de voir et qu'il serait difficile de l'utiliser sur un quelconque site Web.
Vous pouvez constater que nous faisons appel une fonction displayImg() qui n'existe pas, nous allons donc la crer !
Que doit donc contenir notre fonction ? Il faut tout d'abord qu'elle commence par charger l'image originale avant de l'afficher,
commenons par cela :
Code : JavaScript
function displayImg(link) {
var img = new Image();
img.onload = function() {
// Affichage de l'image
};
img.src = link.href;
}
Avant de commencer implmenter l'affichage de l'image, il nous faut tout d'abord mettre en place un overlay. Mais qu'est-ce
que c'est ? En dveloppement Web, il s'agit gnralement d'une surcouche sur la page Web, permettant de diffrencier deux
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
246/378
couches de contenu. Vous allez vite comprendre le principe quand vous le verrez en action. Pour l'overlay, nous allons avoir
besoin d'une balise supplmentaire dans notre code HTML :
Code : HTML
<div id="overlay"></div>
Et nous lui donnons un style CSS afin qu'il puisse couvrir toute la page Web :
Code : CSS
#overlay {
display : none; /* Par dfaut, on cache l'overlay */
position: absolute;
top: 0; left: 0;
width: 100%; height: 100%;
text-align: center; /* Pour centrer l'image que l'overlay
contiendra */
/* Ci-dessous, nous appliquons un background de couleur noire et
d'opacit 0.6. Il s'agit d'une proprit CSS3. */
background-color: rgba(0,0,0,0.6);
}
Maintenant, le principe va tre d'afficher l'overlay quand on cliquera sur une miniature. Il faudra aussi mettre un petit message
pour faire patienter le visiteur pendant le chargement de l'image. Une fois l'image charge, il ne restera plus qu' supprimer le texte
et ajouter l'image originale la place. Allons-y !
Code : JavaScript
function displayImg(link) {
var img = new Image(),
overlay = document.getElementById('overlay');
img.onload = function() {
overlay.innerHTML = '';
overlay.appendChild(img);
};
img.src = link.href;
overlay.style.display = 'block';
overlay.innerHTML = '<span>Chargement en cours...</span>';
}
Voil, notre image se charge et s'affiche, mais il nous manque une chose : pouvoir fermer l'overlay pour choisir une autre image !
La solution est simple, il suffit de quitter l'overlay lorsque l'on clique quelque part dessus :
Code : JavaScript
document.getElementById('overlay').onclick = function() {
this.style.display = 'none';
};
247/378
Il ne nous reste plus qu' ajouter un petit bout de CSS pour embellir le tout, et c'est fini :
Code : CSS
#overlay img {
margin-top: 100px;
}
p {
margin-top: 300px;
text-align: center;
}
originale"><img
originale"><img
originale"><img
originale"><img
<div id="overlay"></div>
248/378
Comme nous vous l'avons prcis plus tt, ce script est actuellement inutilisable sur un site en production. Cependant, si vous
souhaitez amliorer ce code afin de le publier, nous vous conseillons d'tudier ces quelques points :
vitez d'appliquer l'vnement click tous les liens de la page. Ajoutez un lment diffrenciateur aux liens de la
Lightbox, tel qu'une classe ou un attribut name.
Redimensionnez dynamiquement les images originales afin d'viter qu'elles ne dbordent de la page. Utilisez soit un
redimensionnement fixe (trs simple faire), soit un redimensionnement variant selon la taille de l'cran (des recherches
sur le Web seront ncessaires).
Implmentez l'utilisation des touches flches : flche droite pour l'image suivante, flche gauche pour la prcdente.
Faites donc quelque chose de plus beau, notre exemple est vraiment moche !
En rsum
L'objet Image est gnralement utilis pour s'assurer qu'une image a t charge, en utilisant l'vnement load().
Il est possible d'ajouter une Image directement dans l'arbre DOM, mais ce n'est pas chose courante.
249/378
La solution
Il existe un moyen de se faciliter plus ou moins la tche, cela s'appelle les polyfills ! Concrtement, un polyfill est un script qui a
pour but de fournir une technologie tous les navigateurs existants. Une fois implment dans votre code, un polyfill a deux
manires de ragir :
Le navigateur est rcent et supporte la technologie souhaite, le polyfill ne va alors strictement rien faire et va vous
laisser utiliser cette technologie comme elle devrait l'tre nativement.
Le navigateur est trop vieux et ne supporte pas la technologie souhaite, le polyfill va alors imiter cette technologie
grce diverses astuces et vous permettra de l'utiliser comme si elle tait disponible nativement.
Rien ne vaut un bon exemple pour comprendre le principe ! Essayez donc le script suivant avec votre navigateur habituel (qui se
doit d'tre rcent) puis sur un vieux navigateur ne supportant pas la mthode isArray(), Internet Explorer 8 fera trs bien
l'affaire :
Code : JavaScript
if (!Array.isArray) { // Si isArray() n'existe pas, alors on cre
notre mthode alternative :
Array.isArray = function(element) {
return Object.prototype.toString.call(element) == '[object
Array]';
};
}
alert(Array.isArray([])); // Affiche : true
alert(Array.isArray({})); // Affiche : false
Essayer !
La mthode isArray() fonctionne maintenant sur tous les navigateurs ! Pas besoin de s'embter vrifier chaque fois si elle
existe, il suffit juste de s'en servir comme notre habitude et notre polyfill s'occupe de tout !
250/378
Le principe des polyfills ayant t abord, sachez maintenant que la plupart d'entre vous n'auront pratiquement jamais raliser
vos propres polyfills, car ils sont dj nombreux avoir t crs par d'autres dveloppeurs Javascript. Le MDN est un bon
concentr de polyfills et les recherches sur Google peuvent aussi vous aider. Essayez donc de taper le nom d'une mthode suivi
du mot-cl polyfill , vous trouverez rapidement ce que vous cherchez.
Depuis le dbut de ce cours, nous vous avons parl de nombreuses mthodes et proprits qui ne sont pas supportes par de
vieux navigateurs (Internet Explorer tant souvent en cause). chaque fois, nous avons tch de vous fournir une solution
fonctionnelle, cependant il existe trois mthodes pour lesquelles nous ne vous avions pas fourni de solutions car les polyfills
sont bien plus adapts. Vous trouverez donc ici un lien vers un polyfill pour chacune des mthodes dsignes :
Mthode trim() de l'objet String : lien vers le polyfill du MDN
Mthode isArray() de l'objet Array : lien vers le polyfill du MDN
Mthode forEach() de l'objet Array : lien vers le polyfill du MDN
Mais est-ce que vous vous souvenez de ce qui a t dit dans le premier chapitre de cette partie du cours ? Voici un petit rappel :
Citation
En thorie, chaque objet peut se voir attribuer des mthodes via prototype. Mais en pratique, si cela fonctionne avec les
objets natifs gnriques comme String, Date, Array, Object, Number, Boolean et de nombreux autres, cela
fonctionne moins bien avec les objets natifs lis au DOM comme Node, Element ou encore HTMLElement, en particulier
dans Internet Explorer.
De plus, la modification d'un objet natif est plutt dconseille au final, car vous risquez de modifier une mthode dj existante.
Bref, nous avons besoin de mthodes et de proprits supplmentaires mais nous ne pouvons pas les ajouter sans risques, alors
comment faire ?
La solution
Il existe une solution nomme wrapper . Un wrapper est un code qui a pour but d'encadrer l'utilisation de certains lments du
Javascript. Il peut ainsi contrler la manire dont ils sont employs et peut ragir en consquence pour fournir des
fonctionnalits supplmentaires aux dveloppeurs.
Vous vous souvenez lorsque nous avions abord l'objet Image ? La proprit complete avait t voque mais non tudie
en raison de son comportement hasardeux. Nous allons ici essayer de permettre son support.
Tout d'abord, par quoi commence-t-on le dveloppement d'un wrapper ? Comme dit plus haut, il s'agit d'un code qui a pour but
d'encadrer l'utilisation de certains lments, il s'agit en fait d'une surcouche par laquelle nous allons passer pour pouvoir
contrler nos lments. Dans l'idal, un wrapper doit permettre au dveloppeur de se passer de l'lment original, ainsi le travail
ne s'effectuera que par le biais de la surcouche que constitue le wrapper.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
251/378
Puisque notre wrapper doit servir de surcouche de A Z, celui-ci va se prsenter sous forme d'objet qui sera instanci la place
de l'objet Image :
Code : JavaScript
function Img() {
var obj = this; // Nous faisons une petite rfrence vers notre
objet Img. Cela nous facilitera la tche.
this.originalImg = new Image(); // On instancie l'objet
original, le wrapper servira alors d'intermdiaire
}
Notre but tant de permettre le support de la proprit complete, nous allons devoir crer par dfaut un vnement load qui
se chargera de modifier la proprit complete lors de son excution. Il nous faut aussi assurer le support de l'vnement load
pour les dveloppeurs :
Code : JavaScript
function Img() {
var obj = this; // Nous faisons une petite rfrence vers notre
objet Img. Cela nous facilitera la tche.
this.originalImg = new Image(); // On instancie l'objet
original, le wrapper servira alors d'intermdiaire
this.complete = false;
this.onload = function() {}; // Voici l'vnement que les
dveloppeurs pourront modifier
this.originalImg.onload = function() {
obj.complete = true; // L'image est charge !
obj.onload(); // On excute l'vnement ventuellement
spcifi par le dveloppeur
};
}
Actuellement, notre wrapper fait ce qu'on voulait qu'il fasse : assurer un support de la proprit complete. Cependant, il nous
est actuellement impossible de spcifier les proprits standards de l'objet original sans passer par notre proprit
originalImg, or ce n'est pas ce que l'on souhaite car le dveloppeur pourrait compromettre le fonctionnement de notre
wrapper, par exemple en modifiant la proprit onload de l'objet original. Il va donc nous falloir crer une mthode permettant
l'accs ces proprits sans passer par l'objet original.
Ajoutons donc deux mthodes set() et get() assurant le support des proprits d'origine :
Code : JavaScript
Img.prototype.set = function(name, value) {
var allowed = ['width', 'height', 'src']; // On spcifie les
proprits dont on autorise la modification
if (allowed.indexOf(name) != -1) {
this.originalImg[name] = value; // Si la proprit est
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
252/378
Vous remarquerez au passage qu'un wrapper peut vous donner un avantage certain sur le contrle de vos objets, ici en
autorisant la lecture de certaines proprits mais en interdisant leur criture.
Nous voici maintenant avec un wrapper relativement complet qui possde cependant une certaine absurdit : l'accs aux
proprits de l'objet d'origine se fait par le biais des mthodes set() et get(), tandis que l'accs aux proprits relatives au
wrapper se fait sans ces mthodes. Le principe est plutt stupide vu qu'un wrapper a pour but d'tre une surcouche
transparente. La solution pourrait donc tre la suivante : faire passer les modifications/lectures des proprits par les mthodes
set() et get() dans tous les cas, y compris lorsqu'il s'agit de proprits appartenant au wrapper.
Mettons cela en place :
Code : JavaScript
Img.prototype.set = function(name, value) {
var allowed = ['width', 'height', 'src'], // On spcifie les
proprits dont on autorise la modification
wrapperProperties = ['complete', 'onload'];
if (allowed.indexOf(name) != -1) {
this.originalImg[name] = value; // Si la proprit est
autorise alors on la modifie
}
else if(wrapperProperties.indexOf(name) != -1) {
this[name] = value; // Ici, la proprit appartient au
wrapper et non pas l'objet original
}
};
Img.prototype.get = function(name) {
// Si la proprit n'existe pas sur le wrapper, on essaye alors
sur l'objet original :
return typeof this[name] != 'undefined' ? this[name] :
this.originalImg[name];
};
Nous approchons grandement du code final. Il nous reste maintenant une dernire chose mettre en place qui peut se rvler
pratique : pouvoir spcifier l'adresse de l'image ds l'instanciation de l'objet. La modification est simple :
Code : JavaScript
function Img(src) { // On ajoute un paramtre src
var obj = this; // Nous faisons une petite rfrence vers notre
objet Img. Cela nous facilitera la tche.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
253/378
Et voil ! Notre wrapper est termin et entirement oprationnel ! Voici le code complet dans le cas o vous auriez eu du mal
suivre :
Code : JavaScript
function Img(src) {
var obj = this; // Nous faisons une petite rfrence vers notre
objet Img. Cela nous facilitera la tche.
this.originalImg = new Image(); // On instancie l'objet
original, le wrapper servira alors d'intermdiaire
this.complete = false;
this.onload = function() {}; // Voici l'vnement que les
dveloppeurs pourront modifier
this.originalImg.onload = function() {
obj.complete = true; // L'image est charge !
obj.onload(); // On excute l'vnement ventuellement
spcifi par le dveloppeur
};
if (src) {
this.originalImg.src = src; // Si elle est spcifie, on
dfini alors la proprit src
}
}
Img.prototype.set = function(name, value) {
var allowed = ['width', 'height', 'src'], // On spcifie les
proprits dont on autorise la modification
wrapperProperties = ['complete', 'onload'];
if (allowed.indexOf(name) != -1) {
this.originalImg[name] = value; // Si la proprit est
autorise alors on la modifie
}
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
254/378
Essayer !
Alors, c'est plutt convaincant, non ?
Pour information, sachez que les wrappers sont la base de nombreuses bibliothques Javascript. Ils ont l'avantage de permettre
une gestion simple du langage sans pour autant l'altrer.
En rsum
Les polyfills sont un moyen de s'assurer de la prise en charge d'une mthode si celle-ci n'est pas supporte par le
navigateur, et ce sans intervenir dans le code principal. C'est donc totalement transparent.
Les wrappers permettent d'ajouter des proprits ou des mthodes aux objets, en particulier les objets natifs, en crant un
objet driv de l'objet en question.
255/378
Introduction au concept
Prsentation
AJAX est l'acronyme d'Asynchronous Javascript and XML, ce qui, transcrit en franais, signifie Javascript et XML
asynchrones .
Derrire ce nom se cache un ensemble de technologies destines raliser de rapides mises jour du contenu d'une page Web,
sans qu'elles ncessitent le moindre rechargement visible par l'utilisateur de la page Web. Les technologies employes sont
diverses et dpendent du type de requtes que l'on souhaite utiliser, mais d'une manire gnrale le Javascript est constamment
prsent.
D'autres langages sont bien entendu pris en compte comme le HTML et le CSS, qui servent l'affichage, mais ceux-ci ne sont pas
inclus dans le processus de communication. Le transfert de donnes est gr exclusivement par le Javascript, et utilise certaines
technologies de formatage de donnes, comme le XML ou le JSON, mais cela s'arrte l.
L'AJAX est un vaste domaine, dans le sens o les manires de charger un contenu sont nombreuses. Nous verrons les
techniques les plus courantes dans les chapitres suivants, mais tout ne sera pas abord.
Fonctionnement
Concrtement, quoi peut servir l'AJAX ? Le rafrachissement complet de la page n'est-il pas plus simple ? Eh bien, cela dpend
des cas d'application !
Prenons l'exemple du Site du Zro ! Ce site a recours l'AJAX pour plusieurs de ses technologies, nous allons parler de deux
d'entre elles et expliquer pourquoi nous avons besoin de l'AJAX pour les faire fonctionner correctement :
Lauto-compltion ! Lorsque vous recherchez un membre et que vous tapez les premires lettres de son pseudo dans le
formulaire prvu cet effet, vous obtenez une liste des membres dont le pseudo commence par les caractres que vous
avez spcifis. Ce systme requiert de l'AJAX pour la simple et bonne raison qu'il faut demander au serveur de chercher
les membres correspondant la recherche, et ce sans recharger la page, car les caractres entrs seraient alors perdus et
l'ergonomie serait plus que douteuse.
La sauvegarde automatique des textes ! Le Site du Zro intgre un outil trs pratique : tout texte crit sur un cours, une
news, ou mme un simple message sur le forum, est sauvegard intervalles rguliers dans une sorte de bloc-notes.
Cette sauvegarde doit se faire de manire transparente afin de ne pas gner le rdacteur. Le rechargement complet d'une
page Web n'est donc pas envisageable. C'est donc l qu'intervient l'AJAX en permettant votre navigateur d'envoyer
tout votre texte au serveur sans vous gner.
Dans ces deux cas, les requtes ne sont pas superflues, elles contiennent juste les donnes faire transiter, rien de plus. Et c'est
l que rside l'intrt de l'AJAX : les requtes doivent tre rapides. Par exemple, pour obtenir la liste des membres, la requte
AJAX ne va pas recevoir une page complte du Site du Zro (bannire, menu, contenu, etc.) ; elle va juste obtenir une liste des
membres formate de manire pouvoir l'analyser facilement.
256/378
Prsentation
L'AJAX est donc un ensemble de technologies visant effectuer des transferts de donnes. Dans ce cas, il faut savoir
structurer nos donnes. Il existe de nombreux formats pour transfrer des donnes, nous allons voir ici les quatre principaux :
Le format texte est le plus simple, et pour cause : il ne possde aucune structure prdfinie. Il sert essentiellement
transmettre une phrase afficher l'utilisateur, comme un message d'erreur ou autre. Bref, il s'agit d'une chane de
caractres, rien de plus.
Le HTML est aussi une manire de transfrer facilement des donnes. Gnralement, il a pour but d'acheminer des
donnes qui sont dj formates par le serveur puis affiches directement dans la page sans aucun traitement pralable
de la part du Javascript.
Un autre format de donnes proche du HTML est le XML, acronyme de eXtensible Markup Language. Il permet de
stocker les donnes dans un langage de balisage semblable au HTML. Il est trs pratique pour stocker de nombreuses
donnes ayant besoin d'tre formates, tout en fournissant un moyen simple d'y accder.
Le plus courant est le JSON , acronyme de JavaScript Object Notation. Il a pour particularit de segmenter les donnes
dans un objet Javascript, il est trs avantageux pour de petits transferts de donnes segmentes et est de plus en plus
utilis dans de trs nombreux langages.
Utilisation
Les formats classiques
Lorsque nous parlons de format classique , nous voulons dsigner les deux premiers qui viennent d'tre prsents : le texte et
le HTML. Ces deux formats n'ont rien de bien particulier, vous rcuprez leur contenu et vous l'affichez l o il faut, ils ne
ncessitent aucun traitement. Par exemple, si vous recevez le texte suivant :
Code : Autre
Je suis une alerte afficher sur l'cran de l'utilisateur.
Que voulez-vous faire de plus, part afficher cela l'endroit appropri ? Cela va de mme pour le HTML :
Code : HTML
<p>Je suis un paragraphe <strong>inintressant</strong> qui doit
tre copi quelque part dans le DOM.</p>
Que peut-on faire, part copier ce code HTML l o il devrait tre ? Le texte tant dj format sous sa forme finale, il n'y a
aucun traitement effectuer, il est prt l'emploi en quelque sorte.
Le XML
Le format XML est dj autrement plus intressant pour nous, il permet de structurer des donnes de la mme manire qu'en
HTML, mais avec des balises personnalises. Si vous ne savez absolument pas ce qu'est le XML, il est conseill de jeter un coup
dil au cours du Site du Zro Le point sur XML par Tangui avant de continuer.
Le XML vous permet de structurer un document comme bon vous semble, tout comme en HTML, mais avec des noms de balise
personnaliss. Il est donc possible de rduire drastiquement le poids d'un transfert simplement grce l'utilisation de noms de
balise plutt courts. Par exemple, nous avons ici la reprsentation d'un tableau grce au XML :
Code : XML
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
257/378
L o l'utilisation du XML est intressante, c'est que, en utilisant la requte approprie, vous pouvez parcourir ce code XML
avec les mmes mthodes que vous utilisez pour le DOM HTML, comme getElementsByTagName() par exemple !
Comment a se fait ? Eh bien, suite votre requte, votre code Javascript va recevoir une chane de caractres contenant un
code comme celui de ce tableau. ce stade-l, il n'est pas encore possible de parcourir ce code, car il ne s'agit que d'une chane
de caractres. Cependant, une fois la requte termine et toutes les donnes reues, un parseur (ou analyseur syntaxique) va se
mettre en route pour analyser le code reu, le dcomposer, et enfin le reconstituer sous forme d'arbre DOM qu'il sera possible de
parcourir.
Ainsi, nous pouvons trs bien compter le nombre de cellules (les balises <cel>) qui existent et voir leur contenu grce aux
mthodes que nous sommes habitus utiliser avec le DOM HTML. Nous verrons cela dans le chapitre suivant.
Le JSON
Le JSON est le format le plus utilis et le plus pratique pour nous. Comme l'indique son nom (JavaScript Object Notation), il
s'agit d'une reprsentation des donnes sous forme d'objet Javascript. Essayons, par exemple, de reprsenter une liste de
membres ainsi que leurs informations :
Code : JavaScript
{
Membre1: {
posts: 6230,
inscription: '22/08/2003'
},
Membre2: {
posts: 200,
inscription: '04/06/2011'
}
}
Cela ne vous dit rien ? Il s'agit pourtant d'un objet classique, comme ceux auxquels vous tes habitus ! Tout comme avec le
XML, vous recevez ce code sous forme de chane de caractres ; cependant, le parseur ne se dclenche pas automatiquement
pour ce format. Il faut utiliser l'objet nomm JSON, qui possde deux mthodes bien pratiques :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
258/378
La premire, parse(), prend en paramtre la chane de caractres analyser et retourne le rsultat sous forme d'objet
JSON ;
La seconde, stringify(), permet de faire l'inverse : elle prend en paramtre un objet JSON et retourne son quivalent
sous forme de chane de caractres.
Voici un exemple d'utilisation de ces deux mthodes :
Code : JavaScript
var obj = { index: 'contenu' },
string;
string = JSON.stringify(obj);
alert(typeof string + ' : ' + string); // Affiche : string :
{"index":"contenu"}
obj = JSON.parse(string);
alert(typeof obj + ' : ' + obj); // Affiche : object : [object
Object]
Le JSON est trs pratique pour recevoir des donnes, mais aussi pour en envoyer, surtout depuis que le PHP 5.2 permet le
support des fonctions json_decode() et json_encode().
Le JSON n'est malheureusement pas support par Internet Explorer 7 et antrieurs, il vous faudra donc utiliser un
polyfill, comme celui propos par Douglas Crockford.
En rsum
L'AJAX est un moyen de charger des donnes sans recharger la page, en utilisant le Javascript.
Dans une requte AJAX, les deux formats de donnes plbiscits sont le XML et le JSON. Mais les donnes au format
texte sont permises.
Les donnes reues au format XML ont l'avantage de pouvoir tre traites avec des mthodes DOM, comme
getElementById(). Le dsavantage est que le XML peut se rvler assez verbeux, ce qui alourdit la taille du fichier.
Les donnes reues au format JSON ont l'avantage d'tre trs concises, mais ne sont pas toujours trs lisibles pour un
humain. Un autre avantage est que les donnes sont accessibles en tant qu'objets littraux.
259/378
XMLHttpRequest
Il est temps de mettre le principe de l'AJAX en pratique avec l'objet XMLHttpRequest. Cette technique AJAX est la plus
courante et est dfinitivement incontournable.
Au cours de ce chapitre nous allons tudier deux versions de cet objet. Les bases seront tout d'abord tudies avec la premire
version : nous verrons comment raliser de simples transferts de donnes, puis nous aborderons la rsolution des problmes
d'encodage. La deuxime version fera office d'tude avance des transferts de donnes, les problmes lis au principe de la same
origin policy seront levs et nous tudierons l'usage d'un nouvel objet nomm FormData.
partir de ce chapitre, il est ncessaire d'avoir quelques connaissances en PHP afin de ne rien louper du cours. Les
deux premires parties du cours PHP par M@teo21 suffisent amplement pour ce que nous allons voir.
L'objet XMLHttpRequest
Prsentation
L'objet XMLHttpRequest a t initialement conu par Microsoft et implment dans Internet Explorer et Outlook sous forme
d'un contrle ActiveX. Nomm l'origine XMLHTTP par Microsoft, il a t par la suite repris par de nombreux navigateurs sous
le nom que nous lui connaissons actuellement : XMLHttpRequest. Sa standardisation viendra par la suite par le biais du
W3C.
Le principe mme de cet objet est classique : une requte HTTP est envoye l'adresse spcifie, une rponse est alors attendue
en retour de la part du serveur ; une fois la rponse obtenue, la requte s'arrte et peut ventuellement tre relance.
XMLHttpRequest, versions 1 et 2
L'objet que nous allons tudier dans ce chapitre possde deux versions majeures. La premire version est celle issue de la
standardisation de l'objet d'origine. Son support est assur par tous les navigateurs (sauf IE6, mais nous ignorons ce navigateur
dans la totalit de ce cours). L'utilisation de cette premire version est extrmement courante, mais les fonctionnalits paraissent
maintenant bien limites, tant donn l'volution des technologies.
La deuxime version introduit de nouvelles fonctionnalits intressantes, comme la gestion du cross-domain (nous reviendrons
sur ce terme plus tard), ainsi que l'introduction de l'objet FormData. Cependant, peu de navigateurs supportent actuellement
son utilisation.
Alors, quelle version utiliser ?
Dans un cas gnral, la premire version est trs fortement conseille ! Un site Web utilisant la deuxime version de
XMLHttpRequest risque de priver une partie de ses visiteurs des fonctionnalits AJAX fournies en temps normal. D'autant
plus qu'il n'existe pas de polyfill pour ce genre de technologies (on ne parle pas ici d'imiter simplement le fonctionnement d'une
seule mthode, mais d'une technologie complte).
En revanche, la deuxime version est plus qu'intressante si vous dveloppez une extension pour un navigateur ou un
userscript, car ce genre de dveloppement se fait gnralement pour des navigateurs rcents.
260/378
Pour commencer prparer notre requte, il nous faut tout d'abord instancier un objet XHR :
Code : JavaScript
var xhr = new XMLHttpRequest();
La prparation de la requte se fait par le biais de la mthode open(), qui prend en paramtres cinq arguments diffrents, dont
trois facultatifs :
Le premier argument contient la mthode d'envoi des donnes, les trois mthodes principales sont GET, POST et HEAD.
Le deuxime argument est l'URL laquelle vous souhaitez soumettre votre requte, par exemple :
'http://mon_site_web.com'.
Le troisime argument est un boolen facultatif dont la valeur par dfaut est true. true, la requte sera de type
asynchrone, false elle sera synchrone (la diffrence est explique plus tard).
Les deux derniers arguments sont spcifier en cas d'identification ncessaire sur le site Web ( cause d'un .htaccess par
exemple). Le premier contient le nom de l'utilisateur, tandis que le deuxime contient le mot de passe.
Cette ligne de code prpare une requte afin que cette dernire contacte la page ajax.php sur le nom de domaine
mon_site_web.com par le biais du protocole http (vous pouvez trs bien utiliser d'autres protocoles, comme HTTPS ou
FTP par exemple). Tout paramtre spcifi la requte sera transmis par le biais de la mthode GET.
Aprs prparation de la requte, il ne reste plus qu' l'envoyer avec la mthode send(). Cette dernire prend en paramtre un
argument obligatoire que nous tudierons plus tard. Dans l'immdiat, nous lui spcifions la valeur null :
Code : JavaScript
xhr.send(null);
Aprs excution de cette mthode, l'envoi de la requte commence. Cependant, nous n'avons spcifi aucun paramtre ni aucune
solution pour vrifier le retour des donnes, l'intrt est donc quasi nul.
Si vous travaillez avec des requtes asynchrones (ce que vous ferez dans 99% des cas), sachez qu'il existe une
mthode abort() permettant de stopper toute activit. La connexion au serveur est alors interrompue et votre
instance de l'objet XHR est remise zro. Son utilisation est trs rare, mais elle peut servir si vous avez des requtes
qui prennent bien trop de temps.
Synchrone ou asynchrone ?
Vous savez trs probablement ce que signifient ces termes dans la vie courante, mais que peuvent-ils donc dsigner une fois
transposs au sujet actuel ? Une requte synchrone va bloquer votre script tant que la rponse n'aura pas t obtenue, tandis
qu'une requte asynchrone laissera continuer l'excution de votre script et vous prviendra de l'obtention de la rponse par le
biais d'un vnement.
Quelle est la solution la plus intressante ?
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
261/378
Il s'agit sans conteste de la requte asynchrone. Il est bien rare que vous ayez besoin que votre script reste inactif simplement
parce qu'il attend une rponse une requte. La requte asynchrone vous permet de grer votre interface pendant que vous
attendez la rponse du serveur, vous pouvez donc indiquer au client de patienter ou vous occuper d'autres tches en attendant.
Il est cependant conseill, quelle que soit la mthode utilise (GET ou POST), d'encoder toutes les valeurs que vous passez en
paramtre grce la fonction encodeURIComponent(), afin d'viter d'crire d'ventuels caractres interdits dans une URL :
Code : JavaScript
var value1 = encodeURIComponent(value1),
value2 = encodeURIComponent(value2);
xhr.open('GET', 'http://mon_site_web.com/ajax.php?param1=' + value1
+ '¶m2=' + value2);
Votre requte est maintenant prte envoyer des paramtres par le biais de la mthode GET !
En ce qui concerne la mthode POST, les paramtres ne sont pas spcifier avec la mthode open() mais avec la mthode
send() :
Code : JavaScript
xhr.open('POST', 'http://mon_site_web.com/ajax.php');
xhr.send('param1=' + value1 + '¶m2=' + value2);
Cependant, la mthode POST consiste gnralement envoyer des valeurs contenues dans un formulaire, il faut donc modifier
les en-ttes d'envoi des donnes afin de prciser qu'il s'agit de donnes provenant d'un formulaire (mme si, la base, ce n'est
pas le cas) :
Code : JavaScript
xhr.open('POST', 'http://mon_site_web.com/ajax.php');
xhr.setRequestHeader("Content-Type", "application/x-www-formurlencoded");
xhr.send('param1=' + value1 + '¶m2=' + value2);
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
262/378
La mthode setRequestHeader() permet l'ajout ou la modification d'un en-tte, elle prend en paramtres deux arguments :
le premier est l'en-tte concern et le deuxime est la valeur lui attribuer.
Cependant, cet vnement ne se dclenche pas seulement lorsque la requte est termine, mais plutt, comme son nom l'indique,
chaque changement d'tat. Il existe cinq tats diffrents reprsents par des constantes spcifiques l'objet
XMLHttpRequest :
Constante
Valeur
Description
UNSENT
L'objet XHR a t cr, mais pas initialis (la mthode open() n'a pas encore t appele).
OPENED
La mthode open() a t appele, mais la requte n'a pas encore t envoye par la
mthode send().
HEADERS_RECEIVED
LOADING
Le serveur traite les informations et a commenc renvoyer les donnes. Tous les en-ttes
des fichiers ont t reus.
DONE
L'utilisation de la proprit readyState est ncessaire pour connatre l'tat de la requte. L'tat qui nous intresse est le
cinquime (la constante DONE), car nous voulons simplement savoir quand notre requte est termine. Il existe deux manires
pour vrifier que la proprit readyState contient bien une valeur indiquant que la requte est termine. La premire consiste
utiliser la constante elle-mme :
Code : JavaScript
xhr.onreadystatechange = function() {
if (xhr.readyState == xhr.DONE) { // La constante DONE
appartient l'objet XMLHttpRequest, elle n'est pas globale
// Votre code
}
};
Tandis que la deuxime manire de faire, qui est la plus courante (et que nous utiliserons), consiste utiliser directement la valeur
de la constante, soit 4 pour la constante DONE:
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
263/378
Code : JavaScript
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
// Votre code
}
};
De cette manire, notre code ne s'excutera que lorsque la requte aura termin son travail. Toutefois, mme si la requte a
termin son travail, cela ne veut pas forcment dire qu'elle l'a men bien, pour cela nous allons devoir consulter le statut de la
requte grce la proprit status. Cette dernire renvoie le code correspondant son statut, comme le fameux 404 pour les
fichiers non trouvs. Le statut qui nous intresse est le 200, qui signifie que tout s'est bien pass :
Code : JavaScript
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
// Votre code
}
};
noter qu'il existe aussi une proprit nomme statusText contenant une version au format texte du statut de la requte, en
anglais seulement. Par exemple, un statut 404 vous donnera le texte suivant : Not Found .
Si vous souhaitez tester votre requte XHR sur votre ordinateur sans mme utiliser de serveur de test (WampServer par
exemple), alors vous n'obtiendrez jamais de statut quivalent 200 puisque c'est normalement le rle du serveur HTTP
(Apache par exemple, fourni avec WampServer) de fournir cette valeur. Vrifiez alors si le statut quivaut 0, cela
suffira.
Nous avons ici trait le cas d'une requte asynchrone, mais sachez que pour une requte synchrone il n'y a qu' vrifier le statut
de votre requte, tout simplement.
Les deux proprits ncessaires l'obtention des donnes sont responseText et responseXML. Cette dernire est
particulire, dans le sens o elle contient un arbre DOM que vous pouvez facilement parcourir. Par exemple, si vous recevez
l'arbre DOM suivant :
Code : XML
<?xml version="1.0" encoding="utf-8"?>
<table>
<line>
<cel>Ligne 1 - Colonne 1</cel>
<cel>Ligne 1 - Colonne 2</cel>
<cel>Ligne 1 - Colonne 3</cel>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
264/378
</line>
<line>
<cel>Ligne 2 - Colonne 1</cel>
<cel>Ligne 2 - Colonne 2</cel>
<cel>Ligne 2 - Colonne 3</cel>
</line>
<line>
<cel>Ligne 3 - Colonne 1</cel>
<cel>Ligne 3 - Colonne 2</cel>
<cel>Ligne 3 - Colonne 3</cel>
</line>
</table>
Une petite prcision est ncessaire concernant l'utilisation de la proprit responseXML. Sur de vieux navigateurs
(notamment avec de vieilles versions de Firefox), celle-ci peut ne pas tre utilisable si le serveur n'a pas renvoy une
rponse avec un en-tte spcifiant qu'il s'agit bel et bien d'un fichier XML. La proprit pourrait alors tre inutilisable,
bien que le contenu soit pourtant un fichier XML. Pensez donc bien spcifier l'en-tte Content-type avec la
valeur text/xml pour viter les mauvaises surprises. Le Javascript reconnatra alors le type MIME XML. En PHP,
cela se fait de la manire suivante :
Code : PHP
<?php header('Content-type: text/xml'); ?>
La deuxime mthode, getResponseHeader(), permet la rcupration d'un seul en-tte. Il suffit d'en spcifier le nom en
paramtre et la mthode retournera sa valeur :
Code : JavaScript
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
265/378
Mise en pratique
L'tude de cet objet tant assez segmente, nous n'avons pas encore eu l'occasion d'aborder un quelconque exemple. Pallions ce
problme en crant une page qui va s'occuper de charger le contenu de deux autres fichiers selon le choix de l'utilisateur.
Commenons par le plus simple et crons notre page HTML qui va s'occuper de charger le contenu des deux fichiers :
Code : HTML
<p>
Veuillez choisir quel est le fichier dont vous souhaitez voir le
contenu :
</p>
<p>
<input type="button" value="file1.txt" />
<input type="button" value="file2.txt" />
</p>
<p id="fileContent">
<span>Aucun fichier charg</span>
</p>
Comme vous pouvez le constater, le principe est trs simple, nous allons pouvoir commencer notre code Javascript. Crons tout
d'abord une fonction qui sera appele lors d'un clic sur un des deux boutons, elle sera charge de s'occuper du tlchargement et
de l'affichage du fichier pass en paramtre :
Code : JavaScript
function loadFile(file) {
var xhr = new XMLHttpRequest();
// On souhaite juste rcuprer le contenu du fichier, la
mthode GET suffit amplement :
xhr.open('GET', file);
xhr.onreadystatechange = function() { // On gre ici une
requte asynchrone
if (xhr.readyState == 4 && xhr.status == 200) { // Si le
fichier est charg sans erreur
document.getElementById('fileContent').innerHTML =
'<span>' + xhr.responseText + '</span>'; // Et on affiche !
}
};
xhr.send(null); // La requte est prte, on envoie tout !
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
266/378
Il ne nous reste maintenant plus qu' mettre en place les vnements qui dclencheront tout le processus. a commence tre
du classique pour vous, non ?
Code : JavaScript
(function() { // Comme d'habitude, une fonction anonyme pour viter
les variables globales
var inputs = document.getElementsByTagName('input'),
inputsLen = inputs.length;
for (var i = 0 ; i < inputsLen ; i++) {
inputs[i].onclick = function() {
loadFile(this.value); // chaque clic, un fichier sera
charg dans la page
};
}
})();
Et c'est tout bon ! Il ne vous reste plus qu' essayer le rsultat de ce travail !
Essayer le code complet !
Cela fonctionne plutt bien, n'est-ce pas ? Peut-tre mme trop bien, on ne se rend pas compte que l'on utilise ici de l'AJAX
tellement le rsultat est rapide. Enfin, on ne va pas s'en plaindre !
Cet exercice vous a srement clarifi un peu l'esprit quant l'utilisation de cet objet, mais il reste un point qui n'a pas t abord.
Bien qu'il ne soit pas complexe, mieux vaut vous le montrer, notamment afin de ne jamais l'oublier : la gestion des erreurs !
Le code de l'exercice que nous venons de raliser ne sait pas prvenir en cas d'erreur, ce qui est assez gnant au final, car
l'utilisateur pourrait ne pas savoir si ce qui se passe est normal. Nous allons donc mettre en place un petit bout de code pour
prvenir en cas de problme, et nous allons aussi faire en sorte de provoquer une erreur afin que vous n'ayez pas faire 30 000
chargements de fichiers avant d'obtenir une erreur.
Commenons par fournir un moyen de gnrer une erreur en chargeant un fichier inexistant (nous aurons donc une erreur 404) :
Code : HTML
<p>
<input type="button" value="file1.txt" />
<input type="button" value="file2.txt" />
<br /><br />
<input type="button" value="unknown.txt" />
</p>
267/378
268/378
langues radicalement diffrentes (le franais et le japonais, par exemple) dans un mme document ? Une solution serait de crer
une nouvelle norme utilisant plus de bits afin d'y stocker tous les caractres existants dans le monde, mais il y a un dfaut majeur
: en passant plus de 8 bits, le stockage d'un seul caractre ne se fait plus sur 1 octet mais sur 2, ce qui multiplie le poids des
fichiers textes par deux, et c'est absolument inconcevable !
La solution se nomme UTF-8. Cette norme est trs particulire, dans le sens o elle stocke les caractres sur un nombre variable
de bits. Autrement dit, un caractre classique, comme la lettre A, sera stock sur 8 bits (1 octet donc), mais un caractre plus
exotique comme le A en japonais ( ) est stock sur 24 bits (3 octets), le maximum de bits utilisables par l'UTF-8 tant 32, soit 4
octets. En clair, l'UTF-8 est une norme qui sait s'adapter aux diffrentes langues et est probablement la norme d'encodage la plus
aboutie de notre poque.
Pour information, si vous avez t capables de lire le caractre japonais , c'est parce que le Site du Zro utilise l'UTF-8
comme norme d'encodage. Et cela se voit bien, car vous lisez ici du franais et pourtant il y a aussi un caractre
japonais affich, le tout sur la mme page.
Bref, beaucoup de manires de faire pour pas grand-chose, un bon paramtrage du serveur HTTP (Apache dans notre cas) est
gnralement suffisant, condition d'avoir des fichiers encods avec la norme spcifie par le serveur, bien sr. Alors, pourquoi
vous avoir montr a ? Parce que vous risquez d'avoir des problmes d'encodage avec l'AJAX et que ce petit rcapitulatif des
manires de faire pour la spcification d'un encodage pourra srement vous aider les rsoudre.
Attention une chose ! Dans votre diteur de texte, lorsque vous voudrez spcifier l'encodage, il se peut que vous
ayez deux types d'encodage UTF-8 proposs : un nomm UTF-8 avec BOM , et l'autre nomm UTF-8 sans BOM .
Utilisez en permanence l'encodage sans BOM !
Le BOM est une indication de l'ordre des octets qui est ajoute au tout dbut du fichier, ce qui fait que, si vous
souhaitez appeler la fonction header() en PHP, vous ne pourrez pas, car des caractres auront dj t envoys, en
loccurrence les caractres concernant le BOM.
Le problme
269/378
Eh oui, il n'y a qu'un seul problme, mais il est de taille, bien que facile rgler une fois que l'on a bien compris le concept. Le
voici : lorsque vous faites une requte AJAX, toutes les donnes sont envoyes avec un encodage UTF-8, quel que soit
l'encodage du fichier HTML qui contient le script pour la requte AJAX !
Eh bien, cela pose problme si vous travaillez autrement qu'en UTF-8 ct serveur. Car si le fichier PHP appel par la requte
AJAX est encod, par exemple, en ISO 8859-1, alors il se doit de travailler avec des donnes ayant le mme encodage, ce que ne
fournira pas une requte AJAX.
Non, loin de l ! Mais vous allez vous retrouver avec des caractres tranges en lieu et place de certains caractres situs dans le
texte d'origine, tout particulirement pour les caractres accentus.
Comme vous le savez, l'ISO 8859-1 n'utilise que 8 bits pour l'encodage des caractres, tandis que l'UTF-8 peut aller jusqu' 32.
premire vue, ces deux normes n'ont aucune ressemblance, et pourtant si ! Leurs 7 premiers bits respectifs assignent les mmes
valeurs aux caractres concerns, ainsi la lettre A est reprsente par ces 7 bits quelle que soit la norme utilise, celle de l'ISO ou
l'UTF-8 : 100 0001.
La diffrence se situe en fait pour les caractres que l'on va qualifier d'exotiques , comme les caractres accentus. Ainsi, un e
avec accent circonflexe () a la valeur binaire suivante en ISO 8859-1 : 1110 1010, ce qui en UTF-8 quivaut un caractre
impossible afficher. Bref, pas trs pratique.
Mais les choses se corsent encore plus lorsque la conversion est faite depuis l'UTF-8 vers une autre norme, comme l'ISO 8859-1,
car l'UTF-8 utilisera parfois 2 octets (voire plus) pour stocker un seul caractre, ce que les autres normes interprteront comme
tant deux caractres. Par exemple, la mme lettre encode en UTF-8 donne le code binaire suivant : 1100 0011 1010 1010. L'ISO
8859-1 va y voir 2 octets puisqu'il y a 16 bits, la premire squence de 8 bits (1100 0011) va donc tre traduite avec le caractre ,
et la deuxime squence (1010 1010) avec .
Bref, tout cela signifie que si votre fichier HTML client est en ISO 8859-1 et qu'il envoie par l'AJAX le caractre une page PHP
encode elle aussi en ISO 8859-1, alors les donnes qui seront lues par le serveur seront les suivantes : .
Ces trois points doivent vous faire comprendre qu'une requte AJAX n'opre en UTF-8 que lors de l'envoi des donnes, le
problme d'encodage ne survient donc que lorsque les donnes sont rceptionnes par le serveur, et non pas quand le client
reoit les donnes renvoyes par le serveur.
Deux solutions
Il existe deux solutions pour viter ce problme d'encodage sur vos requtes AJAX.
La premire, qui est de loin la plus simple et la plus prenne, consiste ce que votre site soit entirement encod en UTF-8,
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
270/378
comme a les requtes AJAX envoient des donnes en UTF-8 qui seront reues par un serveur demandant traiter de l'UTF-8,
donc sans aucun problme. Un site en UTF-8 implique que tous vos fichiers textes soient encods en UTF-8, que le serveur
indique au client le bon encodage, et que vos ressources externes, comme les bases de donnes, soient aussi en UTF-8.
Cette solution est vraiment la meilleure dans tous les sens du terme, mais est difficile mettre en place sur un projet Web dj
bien entam. Si vous souhaitez vous y mettre (et c'est mme fortement conseill), nous vous conseillons de lire le cours Passer
du latin1 l'unicode crit par vyk12 sur le Site du Zro.
La deuxime solution, encore bien souvent rencontre, est plus adapte si votre projet est dj bien entam et que vous ne
pouvez vous permettre de faire une conversion complte de son encodage. Il s'agit de dcoder les caractres reus par le biais
d'une requte AJAX avec la fonction PHP utf8_decode().
Admettons que vous envoyiez une requte AJAX la page suivante :
Code : PHP
<?php
header('Content-Type: text/plain; charset=iso-8859-1'); // On
prcise bien qu'il s'agit d'une page en ISO 8859-1
echo $_GET['parameter'];
?>
Si la requte AJAX envoie en paramtre la chane de caractres Drle de tte , le serveur va alors vous renvoyer ceci :
Code : Console
Drle de tte
La solution consiste donc dcoder l'UTF-8 reu pour le convertir en ISO 8859-1, la fonction utf8_decode() intervient donc
ici :
Code : PHP
<?php
header('Content-Type: text/plain; charset=iso-8859-1'); // On
prcise bien qu'il s'agit d'une page en ISO 8859-1
echo utf8_decode($_GET['parameter']);
?>
Et l, aucun problme :
Code : Console
Drle de tte
Et quand je renvoie les donnes du serveur au client, je dois encoder les donnes en UTF-8 ?
Absolument pas, car l'AJAX applique une conversion UTF-8 uniquement l'envoi des donnes, comme tudi un peu plus haut.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
271/378
Donc si vous affichez des donnes en ISO 8859-1, elles arriveront chez le client avec le mme encodage.
Si vous travaillez dans un encodage autre que l'ISO 8859-1, utilisez alors la fonction mb_convert_encoding().
Maintenant que tout est clair, entrons dans le vif du sujet : l'tude des nouvelles fonctionnalits.
Cependant, encore une petite chose : faites bien attention en utilisant cette deuxime mouture du XHR, peu de
navigateurs sont encore capables de l'exploiter au maximum. Attendez-vous donc des erreurs dues de nombreuses
incompatibilits. Toutefois, il est dj possible de dire avec certitude que Firefox 6, Chrome 13 et Safari 5 sont
suffisamment compatibles avec le XHR2 (bien que tout ne soit pas encore support).
URL appele
Rsultat
Raison
http://www.example.com/dir/page.html
Succs
http://www.example.com/dir2/other.html
Succs
http://www.example.com:81/dir/other.html chec
https://www.example.com/dir/other.html
chec
http://en.example.com/dir/other.html
chec
Sous-domaine diffrent
Si l'appel est fait depuis un nom de domaine dont les
272/378
chec
Alors, certes, cette scurit est imprative, mais il se peut que parfois nous possdions deux sites Web dont les noms de
domaine soient diffrents, mais dont la connexion doit se faire par le biais des requtes XHR. La deuxime version du XHR
introduit donc un systme simple et efficace permettant l'autorisation des requtes cross-domain.
Ainsi, le domaine http://example.com aura accs la page qui retourne cet en-tte. Si vous souhaitez spcifier plusieurs noms de
domaine, il vous faut alors utiliser le caractre | entre chaque nom de domaine :
Code : Autre
Access-Control-AllowOrigin: http://example1.com | http://example2.com
Pour spcifier que tous les noms de domaine ont accs votre page, utilisez l'astrisque * :
Code : Autre
Access-Control-Allow-Origin: *
Il ne vous reste ensuite plus qu' ajouter cet en-tte aux autres en-ttes de votre page Web, comme ici en PHP :
Code : PHP
<?php
header('Access-Control-Allow-Origin: *');
?>
Cependant, prenez garde l'utilisation de cet astrisque, ne l'utilisez que si vous n'avez pas le choix, car, lorsque vous autorisez
un nom de domaine faire des requtes cross-domain sur votre page, c'est comme si vous dsactiviez une scurit contre le
piratage vis--vis de ce domaine.
273/378
l'heure o nous crivons ces lignes, aucun navigateur ne supporte cette proprit. Essayez de bien vous renseigner
sur son support avant de vous acharner l'utiliser en vain.
Attention ! Cette mthode ne peut tre utilise que lorsque la proprit readyState possde les valeurs 1 ou 2.
Autrement dit, lorsque la mthode open() vient d'tre appele ou bien lorsque les en-ttes viennent d'tre reus, ni
avant, ni aprs.
274/378
Cependant, cette facilit d'utilisation est loin d'tre prsente lorsque vous souhaitez accder ces ressources avec une requte
cross-domain, car aucune valeur ne sera retourne par les tableaux $_COOKIE et $_SESSION.
Pourquoi ? Les cookies et les sessions ne sont pas envoys ?
Eh bien non ! Rassurez-vous, il ne s'agit pas d'une fonctionnalit conue pour vous embter, mais bien d'une scurit, car vous
allez devoir autoriser le navigateur et le serveur grer ces donnes.
Quand nous parlons du serveur, nous voulons surtout parler de la page appele par la requte. Vous allez devoir y spcifier l'entte suivant pour autoriser l'envoi des cookies et des sessions :
Code : Autre
Access-Control-Allow-Credentials: true
Mais, ct serveur, cela ne suffira pas si vous avez spcifi l'astrisque * pour l'en-tte Access-Control-Allow-Origin.
Il vous faut absolument spcifier un seul nom de domaine, ce qui est malheureusement trs contraignant dans certains cas
d'applications (bien qu'ils soient rares).
Vous devriez maintenant avoir une page PHP commenant par un code de ce genre :
Code : PHP
<?php
header('Access-Control-Allow-Origin: http://example.com');
header('Access-Control-Allow-Credentials: true');
?>
Cependant, vous pourrez toujours tenter d'accder aux cookies ou aux sessions, vous obtiendrez en permanence des valeurs
nulles. La raison est simple : le serveur est configur pour permettre l'accs ces donnes, mais le navigateur ne les envoie pas.
Pour pallier ce problme, il suffit d'indiquer notre requte que l'envoi de ces donnes est ncessaire. Cela se fait aprs
initialisation de la requte et avant son envoi (autrement dit, entre l'utilisation des mthodes open() et send()) avec la
proprit withCredentials :
Code : JavaScript
xhr.open( );
xhr.withCredentials = true; // Avec true , l'envoi des cookies et
des sessions est bien effectu
xhr.send( );
Maintenant, une petite question technique pour vous : nous avons une page Web nomme client.php situe sur un nom de
domaine A. Depuis cette page, nous appelons la page server.php situe sur le domaine B grce une requte cross-domain.
Les cookies et les sessions reus par la page server.php sont-ils ceux du domaine A ou bien ceux du domaine B ?
Bonne question, n'est-ce pas ? La rponse est simple et logique : il s'agit de ceux du domaine B. Si vous faites une requte crossdomain, les cookies et les sessions envoys seront constamment ceux qui concernent le domaine de la page appele. Cela
s'applique aussi si vous utilisez la fonction PHP setcookie() dans la page appele : les cookies modifis seront ceux du
domaine de cette page, et non pas ceux du domaine d'o provient la requte.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
275/378
Une dernire prcision, rappelez-vous bien que tout ce qui a t tudi ne vous concerne que lorsque vous faites une
requte cross-domain ! Dans le cas d'une requte dite classique , vous n'avez pas faire ces manipulations, tout
fonctionne sans cela, mme pour une requte XHR1.
Au final, l'utilit de cet vnement est assez quelconque, ce dernier a bien plus d'intrt dans le cas d'un upload (mais cela sera
abord dans la partie consacre au HTML5). Cela dit, il peut avoir son utilit dans le cas de prchargements de fichiers assez
lourds. Ainsi, le prchargement de plusieurs images avec une barre de progression peut tre une utilisation qui peut commencer
avoir son intrt (mais, nous vous l'accordons, cela n'a rien de transcendant).
Cet vnement n'tant pas trs important, nous ne ferons pas un exercice expliqu pas pas, toutefois, vous trouverez un lien
vers un exemple en ligne dont le code est comment, n'hsitez pas y jeter un coup dil !
Essayer une adaptation de cet vnement !
L'objet FormData
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
276/378
Cet objet consiste faciliter l'envoi des donnes par le biais de la mthode POST des requtes XHR. Comme nous l'avons dit
plus tt dans ce chapitre, l'envoi des donnes par le biais de POST est une chose assez fastidieuse, car il faut spcifier un en-tte
dont on ne se souvient que trs rarement de tte, on perd alors du temps le chercher sur le Web.
Au-del de son ct pratique en terme de rapidit d'utilisation, l'objet FormData est aussi un formidable outil permettant de
faire un envoi de donnes binaires au serveur. Ce qui, concrtement, veut dire qu'il est possible de faire de l'upload de fichiers
par le biais des requtes XHR. Cependant, l'upload de fichiers ncessite des connaissances approfondies sur le HTML5, cela
sera donc trait plus tard. Nous allons tout d'abord nous contenter d'une utilisation relativement simple.
Tout d'abord, l'objet FormData doit tre instanci :
Code : JavaScript
var form = new FormData();
Une fois instanci, vous pouvez vous servir de son unique mthode : append(). Celle-ci ne retourne aucune valeur et prend
en paramtres deux arguments obligatoires : le nom d'un champ (qui correspond l'attribut name des lments d'un formulaire)
et sa valeur. Son utilisation est donc trs simple :
Code : JavaScript
form.append('champ1', 'valeur1');
form.append('champ2', 'valeur2');
C'est l que cet objet est intressant : pas besoin de spcifier un en-tte particulier pour dire que l'on envoie des donnes sous
forme de formulaire. Il suffit juste de passer notre objet de type FormData la mthode send(), ce qui donne ceci sur un
code complet :
Code : JavaScript
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://example.com');
var form = new FormData();
form.append('champ1', 'valeur1');
form.append('champ2', 'valeur2');
xhr.send(form);
Et ct serveur, vous pouvez rcuprer les donnes tout aussi simplement que d'habitude :
Code : PHP
<?php
echo $_POST['champ1'] . ' - ' . $_POST['champ2']; // Affiche :
valeur1 - valeur2
?>
Revenons rapidement sur le constructeur de cet objet, car celui-ci possde un argument bien pratique : passez donc en paramtre
un lment de formulaire et votre objet FormData sera alors prrempli avec toutes les valeurs de votre formulaire. Voici un
exemple simple :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
277/378
Code : HTML
<form id="myForm">
<input id="myText" name="myText" type="text" value="Test ! Un,
deux, un, deux !" />
</form>
<script>
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://example.com');
var myForm = document.getElementById('myForm'),
form = new FormData(myForm);
xhr.send(form);
</script>
?>
Voil tout, cet objet est, mine de rien, bien pratique, mme si vous ne savez pas encore faire d'upload de fichiers. Il facilite quand
mme dj bien les choses !
En rsum
L'objet XMLHttpRequest est l'objet le plus utilis pour l'AJAX. Deux versions de cet objet existent, la deuxime tant
plus complte mais pas toujours disponible au sein de tous les navigateurs.
Deux modes sont disponibles : synchrone et asynchrone. Une requte de mode asynchrone sera excute en parallle et
ne bloquera pas l'excution du script, tandis que la requte synchrone attendra la fin de la requte pour poursuivre
l'excution du script.
Deux mthodes d'envoi sont utilisables : GET et POST. Dans le cas d'une mthode GET, les paramtres de l'URL doivent
tre encods avec encodeURIComponent().
Il faut faire attention l'encodage, car toutes les requtes sont envoyes en UTF-8 !
La version 2 du XHR introduit les requtes cross-domain ainsi que les objets FormData et de nouveaux vnements.
278/378
Accder au contenu
Pour accder au contenu de l'iframe, il faut d'abord accder l'iframe elle-mme et ensuite passer par la proprit
contentDocument :
Code : JavaScript
var frame = document.getElementById('myFrame').contentDocument
Cela dit, pour les anciennes version d'Internet Explorer qui ne prennent pas en charge contentDocument, il suffit de passer
par une proprit document. Voici donc le script que nous allons utiliser, qui fonctionne pour tous les navigateurs :
Code : JavaScript
var frame = document.getElementById('myFrame');
frame = frame.contentDocument || frame.document;
Une fois que l'on a accd au contenu de l'iframe, c'est--dire son document, on peut naviguer dans le DOM comme s'il
s'agissait d'un document normal :
Code : JavaScript
var frame_links = frame.getElementsByTagName('a').length;
Vous souvenez-vous de la rgle de scurit same origin policy ? Eh bien figurez-vous que cette rgle s'applique aussi
aux iframes ! Cela veut dire que si vous tes sur une page d'un domaine A et que vous appelez une page d'un domaine
B par le biais d'une iframe, alors vous ne pourrez pas accder au contenu de la page B depuis la page A.
Chargement de contenu
Il y a deux techniques pour charger une page dans une iframe. La premire est de tout simplement changer lattribut src de
l'iframe via le Javascript, la deuxime est d'ouvrir un lien dans l'iframe. Cette action est rendue possible via l'attribut target
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
279/378
(standardis en HTML5) que l'on peut utiliser sur un lien ou sur un formulaire. C'est cette dernire technique que nous
utiliserons pour la ralisation du systme d'upload.
L'attribut target indique au formulaire que son contenu doit tre envoy au sein de l'iframe dont l'attribut name est myFrame
(l'attribut name est donc obligatoire ici !). De cette manire le contenu du formulaire y sera envoy, et la page courante ne sera
pas recharge.
Le Javascript pourra tre utilis comme mthode alternative pour envoyer le formulaire. Pour rappel, pour envoyer un formulaire,
il faut utiliser la mthode submit() :
Code : JavaScript
document.getElementById('myForm').submit();
Dtecter le chargement
Avec l'vnement load
280/378
Les iframes possdent un vnement load, dclench une fois que le contenu de l'iframe est charg. chaque contenu charg,
load est dclench. C'est un moyen efficace pour savoir si le document est charg, et ainsi pouvoir le rcuprer. Voici un petit
exemple :
Code : HTML
<iframe src="file.html" name="myFrame" id="myFrame"
onload="trigger()"></iframe>
<script>
function trigger() {
var frame = document.getElementById('myFrame');
frame = frame.contentDocument || frame.document;
}
alert(frame.body.textContent);
</script>
L'objet window.top pointe vers la fentre mre , ce qui nous permet ici d'atteindre la page qui contient l'iframe.
Voici un exemple qui illustre ce mcanisme :
Code : HTML - Page 'mre'
<iframe src="file.html" name="myFrame" id="myFrame"></iframe>
<script>
function trigger() {
var frame = document.getElementById('myFrame');
frame = frame.contentDocument || frame.document;
}
</script>
281/378
callback
</script>
<p>Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Suspendisse molestie suscipit arcu.</p>
Essayer !
Rcuprer du contenu
Le chargement de donnes via une iframe a un gros avantage : il est possible de charger n'importe quoi comme donnes. a peut
tre une page Web complte, du texte brut ou mme du Javascript, comme le format JSON.
Ici, un tableau Javascript est construit via le PHP et envoy la fonction trigger() en tant que paramtre.
Exemple complet
Code : HTML
<form id="myForm" method="post" action="request.php"
target="myFrame">
<div>
<label for="nick">Votre pseudo :</label>
<input type="text" id="nick" name="nick" />
<input type="button" value="Envoyer" onclick="sendForm();"
/>
</div>
</form>
<iframe src="#" name="myFrame" id="myFrame"></iframe>
<script>
function sendForm() {
var nick = document.getElementById("nick").value;
if (nick) { // Si c'est OK
document.getElementById("myForm").submit(); // On envoie le
formulaire
}
}
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
282/378
function receiveData(data) {
alert('Votre pseudo est "' + data + '"');
}
</script>
Essayer !
Ce script ne fait que rcuprer la variable $_POST['nick'], pour ensuite appeler la fonction receiveData() en lui
passant le pseudo en paramtre. La fonction PHP htmlentities() permet d'viter que l'utilisateur insre d'ventuelles
balises HTML potentiellement dangereuses telles que la balise <script>. Alors, certes, ici l'insertion de balise ne pose pas de
problme puisque l'on affiche le pseudo dans une fentre alert(), mais mieux vaut prvenir que gurir, non ?
Le systme d'upload
Par le biais d'un formulaire et d'une iframe, crer un systme d'upload n'est absolument pas compliqu. C'est mme relativement
simple ! Les lments <form> possdent un attribut enctype qui doit absolument contenir la valeur multipart/formdata. Pour faire simple, cette valeur indique que le formulaire est prvu pour envoyer de grandes quantits de donnes (les
fichiers sont des donnes volumineuses).
Notre formulaire d'upload peut donc tre crit comme ceci :
Code : HTML
<form id="uploadForm" enctype="multipart/form-data"
action="upload.php" target="uploadFrame" method="post">
<label for="uploadFile">Image :</label>
<input id="uploadFile" name="uploadFile" type="file" />
<br /><br />
<input id="uploadSubmit" type="submit" value="Upload !" />
</form>
Ensuite, on place l'iframe, ainsi qu'un autre petit <div> que nous utiliserons pour afficher le rsultat de l'upload :
Code : HTML
<div id="uploadInfos">
<div id="uploadStatus">Aucun upload en cours</div>
<iframe id="uploadFrame" name="uploadFrame"></iframe>
</div>
283/378
Quelques explications s'imposent. Ds que le formulaire est envoy, la fonction anonyme de l'vnement submit est excute.
Celle-ci va remplacer le texte du <div> #uploadStatus pour indiquer que le chargement est en cours. Car, en fonction de la
taille du fichier envoyer, l'attente peut tre longue. L'argument error contiendra soit OK , soit une explication sur une
erreur ventuelle. L'argument path contiendra l'URL du fichier venant d'tre upload. L'appel vers la fonction uploadEnd()
sera fait via l'iframe, comme nous le verrons plus loin.
284/378
Avec ce code, le fichier upload est analys puis enregistr sur le serveur. Si vous souhaitez obtenir plus d'informations
sur le fonctionnement de ce code PHP, n'hsitez pas vous reporter au tutoriel Upload de fichiers par formulaire
crit par DHKold sur le Site du Zro.
Avec ce script tout simple, il est donc possible de mettre en place un upload de fichiers sans rechargement . Il ne reste plus
qu' amliorer le systme, notamment en scurisant le script PHP (dtecter le type MIME du fichier, pour n'autoriser que les
images par exemple), ou en arrangeant le code Javascript pour afficher la suite les fichiers uploads s'il y en a plusieurs
Si vous souhaitez essayer ce script en ligne, sachez que nous avons mis une version en ligne, mais que celle-ci n'enregistre pas
les fichiers sur le serveur et que cela implique donc que l'affichage de l'image n'est pas effectu. Vous tes en revanche prvenus
lorsqu'un fichier a fini d'tre upload, ce qui est, somme toute, le but principal de notre script.
Essayer la version light !
En rsum
L'utilisation d'une iframe est une technique AJAX assez rpandue et facile mettre en uvre pour raliser un upload de
fichiers compatible avec tous les navigateurs.
Il suffit d'utiliser l'vnement load sur une iframe pour savoir si la page qu'elle contient vient d'tre charge. Il ne reste
plus qu' accder cette page et rcuprer ce qui nous intresse.
Depuis une iframe, il faut utiliser window.top pour accder la page qui contient l'iframe. C'est utile dans le cas d'un
callback.
285/378
Un concept simple
Avec le DOM, il est possible d'insrer n'importe quel lment HTML au sein d'une page Web, et cela vaut galement pour un
lment <script>. Il est donc possible de lier et d'excuter un fichier Javascript aprs que la page a t charge :
Code : JavaScript
window.addEventListener('load', function() {
var scriptElement = document.createElement('script');
scriptElement.src = 'url/du/fichier.js';
document.body.appendChild(scriptElement);
}, false);
Avec ce code, un nouvel lment <script> sera insr dans la page une fois que cette dernire aura t charge. Mais s'il est
possible de charger un fichier Javascript la demande, pourquoi ne pas s'en servir pour charger des donnes, et faire de
l'AJAX ?
Un premier exemple
Nous allons commencer par quelque chose de trs simple : dans une page HTML, on va charger un fichier Javascript qui
excutera une fonction. Cette fonction se trouve dans la page HTML.
Code : HTML
<script>
function sendDSL() {
var scriptElement = document.createElement('script');
scriptElement.src = 'dsl_script.js';
}
document.body.appendChild(scriptElement);
function receiveMessage(message) {
alert(message);
}
</script>
<p><button type="button" onclick="sendDSL()">Excuter le
script</button></p>
Essayer !
Voici maintenant le contenu du fichier dsl_script.js :
Code : JavaScript
receiveMessage('Ce message est envoy par le serveur !');
286/378
Dcortiquons tout cela. Ds qu'on clique sur le bouton, la fonction sendDSL() va charger le fichier Javascript qui contient un
appel vers la fonction receiveMessage(), tout en prenant soin de lui passer un message en paramtre. Ainsi, via la fonction
receiveMessage(), on est en mesure de rcuprer du contenu. videmment, cet exemple n'est pas trs intressant puisque
l'on sait l'avance ce que le fichier Javascript va renvoyer. Ce que nous allons faire, c'est crer le fichier Javascript via du PHP !
En ce qui concerne le fichier PHP, il va falloir utiliser la fonction header() pour indiquer au navigateur que le contenu du
fichier PHP est en ralit du Javascript.
Puis, il ne reste plus qu' introduire la variable $_GET['nick'] au sein du script Javascript :
Code : PHP
<?php header("Content-type: text/javascript"); ?>
var string = 'Bonjour <?php echo $_GET['nick'] ?> !';
receiveMessage(string);
Charger du JSON
Comme dans l'exemple prcdent, nous allons utiliser une page PHP pour gnrer le contenu du fichier Javascript, et donc notre
JSON. Les donnes JSON contiennent une liste d'diteurs et pour chacun une liste de programmes qu'ils ditent :
Code : PHP
<?php
header("Content-type: text/javascript");
echo 'var softwares = {
"Adobe": [
"Acrobat",
"Dreamweaver",
"Photoshop",
"Flash"
],
"Mozilla": [
"Firefox",
"Thunderbird",
"Lightning"
],
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
287/378
"Microsoft": [
"Office",
"Visual C# Express",
"Azure"
]
};';
?>
receiveMessage(softwares);
Au niveau de la page HTML, pas de gros changements Nous allons juste coder une meilleure fonction
receiveMessage() de manire afficher, dans une alerte, les donnes issues du JSON. On utilise une boucle for in pour
parcourir le tableau associatif, et une deuxime boucle for imbrique pour chaque tableau :
Code : HTML
<script>
function sendDSL() {
var scriptElement = document.createElement('script');
scriptElement.src = 'dsl_script_json.php';
}
document.body.appendChild(scriptElement);
function receiveMessage(json) {
var tree = '', nbItems, i;
for (node in json) {
tree
+= node + "\n";
nbItems = json[node].length;
for (i=0; i<nbItems; i++) {
tree += '\t' + json[node][i] + '\n';
}
}
}
alert(tree);
</script>
<p><button type="button" onclick="sendDSL()">Charger le
JSON</button></p>
En rsum
Il est possible de charger un fichier .js en ajoutant un lment <script> via le Javascript. On appelle cela le Dynamic
Script Loading.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
288/378
Cette technique est particulirement efficace pour charger des donnes au format JSON.
Comme pour les iframes vues prcdemment, il faut utiliser un systme de callback pour transmettre les donnes une
fois le fichier Javascript charg.
289/378
TP : un systme d'auto-compltion
Aprs avoir absorb autant d'informations sur le concept de l'AJAX, il est grand temps de mettre en pratique une bonne partie
de vos connaissances. Le TP de cette partie sera consacr la cration d'un systme d'auto-compltion qui sera capable d'aller
chercher, dans un fichier, les villes de France commenant par les lettres que vous aurez commenc crire dans le champ de
recherche. Le but est d'acclrer et de valider la saisie de vos mot-cls.
Malheureusement, ce TP n'utilisera l'AJAX que par le biais de l'objet XMLHttpRequest afin de rester dans des dimensions
raisonnables. Cependant, il s'agit, et de loin, de la mthode la plus en vogue de nos jours, l'utilisation d'iframes et de DSL tant
rserve des cas bien plus particuliers.
Prsentation de l'exercice
Les technologies employer
Avant de commencer, il nous faut dterminer le type de technologie dont nous avons besoin, car ici nous ne faisons pas
uniquement appel au Javascript, nous allons devoir employer d'autres langages.
Dans un cadre gnral, un systme d'auto-compltion fait appel trois technologies diffrentes :
Un langage client ayant la capacit de dialoguer avec un serveur ;
Un langage serveur capable de fournir les donnes au client ;
Une base de donnes qui stocke toutes les donnes.
Dans notre cas, nous allons utiliser le Javascript ainsi que le PHP (bien que n'importe quel autre langage serveur soit capable de
faire son travail). Nous allons, en revanche, faire une petite entorse au troisime point en utilisant un fichier de stockage plutt
qu'une base de donnes, cela pour une raison bien simple : simplifier notre code, surtout que nous n'avons pas besoin d'une
base de donnes pour le peu de donnes enregistrer.
Principe de l'auto-compltion
Un systme d'auto-compltion se prsente de la manire suivante :
Conception
290/378
Nous connaissons le principe de l'auto-compltion et les technologies ncessaires. Cependant, cela n'explique pas comment tout
cela doit tre utilis. Nous allons donc vous guider pour vous permettre de vous lancer sans trop d'apprhension dans ce vaste
projet.
L'interface
Commenons par l'interface ! De quoi allons-nous avoir besoin ? L'auto-compltion tant affilie, gnralement, tout ce qui est
du domaine de la recherche, il va nous falloir un champ de texte pour crire les mots-cls. Cependant, ce dernier va nous poser
problme, car le navigateur enregistre gnralement ce qui a t crit dans les champs de texte afin de vous le reproposer plus
tard sous forme d'auto-compltion, ce qui va donc faire doublon avec notre systme Heureusement, il est possible de
dsactiver cette auto-compltion en utilisant l'attribut autocomplete de cette manire :
Code : HTML
<input type="text" autocomplete="off" />
cela nous allons devoir ajouter un lment capable d'englober les suggestions de recherches. Celui-ci sera compos d'une
balise <div> contenant autant de <div> que de rsultats, comme ceci :
Code : HTML
<div id="results">
<div>Rsultat 1</div>
<div>Rsultat 2</div>
</div>
Chaque rsultat dans les suggestions devra changer d'aspect lorsque celui-ci sera survol ou slectionn par le biais des
touches flches.
En ce qui concerne un ventuel bouton de type submit, nous allons nous en passer, car notre but n'est pas de lancer la
recherche, mais seulement d'afficher une auto-compltion.
titre d'information, puisque vous allez devoir grer les touches flches, voici les valeurs respectives de la proprit
keyCode pour les touches Haut, Bas et Entre : 38, 40 et 13.
La communication client/serveur
Contrairement ce que l'on pourrait penser, il ne s'agit pas ici d'une partie bien complique car, dans le fond, qu'allons-nous
devoir faire ? Simplement effectuer une requte chaque caractre crit afin de proposer une liste de suggestions. Il nous faudra
donc une fonction lie l'vnement keyup de notre champ de recherche, qui sera charge d'effectuer une nouvelle requte
chaque caractre tap.
Cependant, admettons que nous tapions deux caractres dans le champ de recherche, que la premire requte rponde en 100 ms
et la seconde en 65 ms : nous allons alors obtenir les rsultats de la premire requte aprs ceux de la seconde et donc afficher
des suggestions qui ne seront plus du tout en accord avec les caractres taps dans le champ de recherche. La solution cela
est simple : utiliser la mthode abort() sur la prcdente requte effectue si celle-ci n'est pas termine. Ainsi, elle ne risque
pas de renvoyer des informations dpasses par la suite.
291/378
Tlcharger l'archive !
La linarisation d'une variable en PHP permet de sauvegarder des donnes sous forme de chane de caractres. Cela est
pratique lorsque l'on souhaite sauvegarder un tableau dans un fichier, c'est ce que nous avons fait pour les villes. Les
fonctions permettant de faire cela se nomment serialize() et unserialize().
Le PHP n'tant pas forcment votre point fort (aprs tout, vous tes l pour apprendre le Javascript), nous allons tcher de bien
dtailler ce que vous devez faire pour russir faire votre recherche.
Tout d'abord, il vous faut rcuprer les donnes contenues dans le fichier towns.txt (disponible dans l'archive fournie plus
haut). Pour cela, il va vous falloir lire ce fichier avec la fonction file_get_contents(), puis convertir son contenu en tant
que tableau PHP grce la fonction unserialize().
Une fois cela fait, le tableau obtenu doit tre parcouru la recherche de rsultats en cohrence avec les caractres taps par
l'utilisateur dans le champ de recherche. Pour cela, vous aurez besoin d'une boucle ainsi que de la fonction count() pour
obtenir le nombre d'lments contenus dans le tableau.
Pour vrifier si un index du tableau correspond votre recherche, il va vous falloir utiliser la fonction stripos(), qui permet
de vrifier si une chane de caractres contient certains caractres, et ce sans tenir compte de la casse. Si vous trouvez un
rsultat en cohrence avec la recherche, alors ajoutez-le un tableau (que vous aurez pralablement cr) grce la fonction
array_push().
Une fois le tableau parcouru, il ne vous reste plus qu' trier les rsultats avec la fonction sort(), puis renvoyer les donnes
au client
Oui, mais sous quelle forme ? XML ? JSON ?
Tout comme join() en Javascript, il existe une fonction PHP qui vous permet de concatner toutes les valeurs d'un tableau
dans une chane de caractres avec un ou plusieurs caractres de sparation : il s'agit de la fonction implode(). Une fois la
fonction utilise, il ne vous reste plus qu' retourner le tout au client avec un bon vieil echo et analyser cela ct Javascript.
C'est vous !
Maintenant que vous avez toutes les cartes en main, vous de jouer ! N'hsitez pas regarder la correction du fichier PHP si
besoin, nous pouvons comprendre que vous puissiez ne pas le coder vous-mmes sachant que ce n'est pas le sujet de ce cours.
Mais je commence par o ? Le serveur ou le client ?
292/378
Il est prfrable que vous commenciez par le code PHP afin de vous assurer que celui-ci fonctionne bien, cela vous vitera bien
des ennuis de dbogage.
En cas de dysfonctionnements dans votre code, pensez bien regarder la console d'erreurs et aussi vrifier ce que vous a
renvoy le serveur, car l'erreur peut provenir de ce dernier et non pas forcment du client.
Correction
Votre systme d'auto-compltion est termin ? Bien ! Fonctionnel ou pas, l'important est d'essayer et de comprendre d'o
proviennent vos erreurs, donc ne vous en faites pas si vous n'avez pas russi aller jusqu'au bout.
Le corrig complet
Vous trouverez ici la correction des diffrentes parties ncessaires l'auto-compltion. Commenons tout d'abord par le code
PHP du serveur, car nous vous avions conseill de commencer par celui-ci :
Code : PHP
<?php
$data = unserialize(file_get_contents('towns.txt')); //
Rcupration de la liste complte des villes
$dataLen = count($data);
sort($data); // On trie les villes dans l'ordre alphabtique
$results = array(); // Le tableau o seront stocks les
rsultats de la recherche
// La boucle ci-dessous parcourt tout le tableau $data, jusqu'
un maximum de 10 rsultats
for ($i = 0 ; $i < $dataLen && count($results) < 10 ; $i++)
xhr.send(null);
return xhr;
}
function displayResults(response) { // Affiche les rsultats
d'une requte
results.style.display = response.length ? 'block' : 'none';
// On cache le conteneur si on n'a pas de rsultats
if (response.length) { // On ne modifie les rsultats que
si on en a obtenu
response = response.split('|');
var responseLen = response.length;
results.innerHTML = ''; // On vide les rsultats
for (var i = 0, div ; i < responseLen ; i++) {
div =
results.appendChild(document.createElement('div'));
div.innerHTML = response[i];
div.onclick = function() {
chooseResult(this);
};
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
293/378
searchElement.onkeyup = function(e) {
pour IE
294/378
295/378
Les explications
Ce TP n'est pas compliqu en soi mais aborde de nouveaux concepts, il se peut donc que vous soyez quelque peu perdus la
lecture des codes fournis. Laissez-nous vous expliquer comment tout cela fonctionne.
Avant de commencer notre analyse de donnes, il nous faut prcharger le fichier, convertir son contenu en tableau PHP et enfin
trier ce dernier. cela s'ajoutent le calcul de la taille du tableau gnr ainsi que la cration d'un tableau pour sauvegarder les
rsultats en cohrence avec la recherche :
Code : PHP
<?php
$data = unserialize(file_get_contents('towns.txt')); //
Rcupration de la liste complte des villes
$dataLen = count($data);
sort($data); // On trie les villes dans l'ordre alphabtique
$results = array(); // Le tableau o seront stocks les
rsultats de la recherche
?>
Maintenant que toutes les donnes sont accessibles, il va nous falloir les analyser. Basiquement, il s'agit de la mme opration
qu'en Javascript : une boucle pour parcourir le tableau et une condition pour dterminer si le contenu est valide. Voici ce que cela
donne en PHP :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
296/378
Code : PHP
<?php
// La boucle ci-dessous parcourt tout le tableau $data, jusqu' un
maximum de 10 rsultats
for ($i = 0 ; $i < $dataLen && count($results) < 10 ; $i++) {
if (stripos($data[$i], $_GET['s']) === 0) { // Si la valeur
commence par les mmes caractres que la recherche
// Du code
}
}
?>
La boucle for possde une condition un peu particulire qui stipule qu'elle doit continuer tourner tant qu'elle n'a pas lu tout le
tableau $data et qu'elle n'a pas atteint le nombre maximum de rsultats retourner. Cette limite de rsultats est ncessaire, car
une auto-compltion ne doit pas afficher tous les rsultats sous peine de provoquer des ralentissements dus au nombre lev de
donnes, sans compter qu'un trop grand nombre de rsultats serait difficile parcourir (et analyser) pour l'utilisateur.
La fonction stripos() retourne la premire occurrence de la recherche dtecte dans la valeur actuellement analyse. Il est
ncessaire de vrifier que la valeur retourne est bien gale 0, car nous ne souhaitons obtenir que les rsultats qui commencent
par notre recherche. La triple quivalence (===) s'explique par le fait que la fonction stripos() retourne false en cas
d'chec de la recherche, ce que la double quivalence (==) aurait confondu avec un 0.
Une fois qu'un rsultat cohrent a t trouv, il ne reste plus qu' l'ajouter notre tableau $results :
Code : PHP
<?php
for ($i = 0 ; $i < $dataLen && count($results) < 10 ; $i++) {
if (stripos($data[$i], $_GET['s']) === 0) { // Si la valeur
commence par les mmes caractres que la recherche
array_push($results, $data[$i]); // On ajoute alors le
rsultat la liste retourner
}
}
?>
Une fois que la boucle a termin son excution, il ne reste plus qu' retourner le contenu de notre tableau de rsultats sous forme
de chane de caractres. Lors de la prsentation de ce TP, nous avons voqu le fait de retourner les rsultats spars par une
barre verticale, c'est donc ce que nous appliquons dans le code suivant :
Code : PHP
<?php
echo implode('|', $results); // On affiche les rsultats spars
par une barre verticale |
?>
Ainsi, notre script ct client n'aura plus qu' faire un bon vieux split('|') sur la chane de caractres obtenue grce au
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
297/378
Voil tout pour la partie HTML ! En ce qui concerne le Javascript, il nous faut tout d'abord, avant de crer les vnements et
autres choses fastidieuses, dclarer les variables dont nous allons avoir besoin. Plutt que de les laisser traner dans la nature,
nous allons les dclarer dans une IEF (pour les trous de mmoire sur ce terme, c'est par ici) :
Code : JavaScript
(function() {
var searchElement = document.getElementById('search'),
results = document.getElementById('results'),
selectedResult = -1, // Permet de savoir quel rsultat est
slectionn : -1 signifie aucune slection
previousRequest, // On stocke notre prcdente requte dans
cette variable
previousValue = searchElement.value; // On fait de mme avec
la prcdente valeur
})();
Si l'utilit de la variable previousValue vous semble douteuse, ne vous en faites pas, vous allez vite comprendre quoi elle
sert !
298/378
Commenons tout d'abord par grer les touches flches Haut et Bas. C'est l que notre variable selectedResult entre en
action, car elle stocke la position actuelle de la slection des rsultats. Avec -1, il n'y a aucune slection et le curseur se trouve
donc sur le champ de recherche ; avec 0, le curseur est positionn sur le premier rsultat, 1 dsigne le deuxime rsultat, etc.
Pour chaque dplacement de la slection, il vous faut appliquer un style sur le rsultat slectionn afin que l'on puisse le
distinguer des autres. Il existe plusieurs solutions pour cela, cependant nous avons retenu celle qui utilise les classes CSS.
Autrement dit, lorsqu'un rsultat est slectionn, vous n'avez qu' lui attribuer une classe CSS qui va modifier son style. Cette
classe doit bien sr tre retire ds qu'un autre rsultat est slectionn. Concrtement, cette solution donne ceci pour la gestion
de la flche Haut :
Code : JavaScript
if (e.keyCode == 38 && selectedResult > -1) { // Si la touche
presse est la flche haut
divs[selectedResult--].className = ''; // On retire la classe
de l'lment infrieur et on dcrmente la variable
selectedResult
if (selectedResult > -1) { // Cette condition vite une
modification de childNodes[-1], qui n'existe pas, bien entendu
divs[selectedResult].className = 'result_focus'; // On
applique une classe l'lment actuellement slectionn
}
}
Vous constaterez que la premire condition doit vrifier deux rgles. La premire est la touche frappe, jusque l tout va bien.
Quant la seconde rgle, elle consiste vrifier que notre slection n'est pas dj positionne sur le champ de texte, afin d'viter
de sortir de notre champ d'action , qui s'tend du champ de texte jusqu'au dernier rsultat suggr par notre auto-compltion.
Curieusement, nous retrouvons une seconde condition (ligne 5) effectuant la mme vrification que la premire :
selectedResult > -1. Cela est en fait logique, car si l'on regarde bien la troisime ligne, la valeur de selectedResult
est dcrmente, il faut alors effectuer une nouvelle vrification.
Concernant la flche Bas, les changements sont assez peu flagrants, ajoutons donc la gestion de cette touche notre code :
Code : JavaScript
else if (e.keyCode == 40 && selectedResult < divs.length - 1) { //
Si la touche presse est la flche bas
results.style.display = 'block'; // On affiche les rsultats
au cas o
if (selectedResult > -1) { // Cette condition vite une
modification de childNodes[-1], qui n'existe pas, bien entendu
divs[selectedResult].className = '';
}
divs[++selectedResult].className = 'result_focus';
}
Ici, les changements portent surtout sur les valeurs analyser ou modifier. On ne dcrmente plus selectedResult mais
on l'incrmente. La premire condition est modifie afin de vrifier que l'on ne se trouve pas la fin des rsultats au lieu du
dbut, etc.
Et, surtout, l'ajout d'une nouvelle ligne (la troisime) qui permet d'afficher les rsultats dans tous les cas. Pourquoi cet ajout ? Eh
bien, pour simplifier l'utilisation de notre script. Vous le constaterez plus tard, mais lorsque vous choisirez un rsultat (donc un
clic ou un appui sur Entre) cela entranera la disparition de la liste des rsultats. Grce l'ajout de notre ligne de code, vous
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
299/378
Alors oui, vous tes en droit de vous demander quelle est cette fonction chooseResult(). Il s'agit en fait d'une des trois
fonctions que nous allons crer, mais plus tard ! Pour le moment, retenez seulement qu'elle permet de choisir un rsultat (et donc
de grer tout ce qui s'ensuit) et qu'elle prend en paramtre l'lment choisir. Nous nous intresserons son code un peu plus
tard.
Maintenant, il ne nous reste plus qu' dtecter quand le champ de texte a t modifi.
Cest simple, chaque fois que l'vnement keyup se dclenche, cela veut dire que le champ a t modifi, non ?
Pas tout fait, non ! Cet vnement se dclenche quelle que soit la touche relche, cela inclut donc les touches flches, les
touches de fonction, etc. Tout cela nous pose problme au final, car nous souhaitons savoir quand la valeur du champ de
recherche est modifie et non pas quand une touche quelconque est relche. Il y aurait une solution cela : vrifier que la
touche enfonce fournit bien un caractre, cependant il s'agit d'une vrification assez fastidieuse et pas forcment simple
mettre en place si l'on souhaite tre compatible avec Internet Explorer.
Cest donc l que notre variable previousValue entre en piste ! Le principe est d'y enregistrer la dernire valeur du champ de
recherche. Ainsi, ds que notre vnement se dclenche, il suffit de comparer la variable previousValue la valeur actuelle
du champ de recherche ; si c'est diffrent, alors on enregistre la nouvelle valeur du champ dans la variable, on effectue ce qu'on a
faire et c'est reparti pour un tour. Simple, mais efficace !
Une fois que l'on sait que la valeur de notre champ de texte a t modifie, il ne nous reste plus qu' lancer une nouvelle requte
effectuant la recherche auprs du serveur :
Code : JavaScript
else if (searchElement.value != previousValue) { // Si le contenu du
champ de recherche a chang
previousValue = searchElement.value; // On change la valeur
prcdente par la valeur actuelle
getResults(previousValue); // On effectue une nouvelle requte
selectedResult = -1; // On remet la slection zro chaque
caractre crit
}
La fonction getResults() sera tudie plus tard, elle est charge d'effectuer une requte auprs du serveur, puis d'en
afficher ses rsultats. Elle prend en paramtre le contenu du champ de recherche.
Il est ncessaire de remettre la slection des rsultats -1 (ligne 7) car la liste des rsultats va tre actualise. Sans cette
modification, nous pourrions tre positionns sur un rsultat inexistant. La valeur -1 tant celle dsignant le champ de recherche,
nous sommes srs que cette valeur ne posera jamais de problme.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
300/378
Alors, en thorie, notre code fonctionne plutt bien, mais il manque cependant une chose : nous ne nous sommes pas encore
servis de la variable previousRequest. Rappelez-vous, elle est suppose contenir une rfrence vers le dernier objet XHR
cr, cela afin que sa requte puisse tre annule dans le cas o nous aurions besoin de lancer une nouvelle requte alors que la
prcdente n'est pas encore termine. Mettons donc son utilisation en pratique :
Code : JavaScript
else if (searchElement.value != previousValue) { // Si le contenu du
champ de recherche a chang
previousValue = searchElement.value;
if (previousRequest && previousRequest.readyState < 4) {
previousRequest.abort(); // Si on a toujours une requte en
cours, on l'arrte
}
previousRequest = getResults(previousValue); // On stocke la
nouvelle requte
selectedResult = -1; // On remet la slection zro chaque
caractre crit
}
Alors, qu'avons-nous de nouveau ? Tout d'abord, il faut savoir que la fonction getResults() est cense retourner l'objet
XHR initialis, nous profitons donc de cela pour stocker ce dernier dans la variable previousRequest (ligne 9).
Ligne 5, vous pouvez voir une condition qui vrifie si la variable previousRequest est bien initalise et surtout si l'objet
XHR qu'elle rfrence a bien termin son travail. Si l'objet existe mais que son travail n'est pas termin, alors on utilise la mthode
abort() sur cet objet avant de faire une nouvelle requte.
301/378
xhr.send(null);
return xhr;
}
Nous avons donc une requte XHR banale qui envoie les termes de la recherche la page search.php, le tout dans une
variable GET nomme s . Comme vous pouvez le constater, pensez bien utiliser la fonction encodeURIComponent()
afin d'viter tout caractre indsirable dans l'URL de la requte.
Le mot-cl return en fin de fonction retourne l'objet XHR initialis afin qu'il puisse tre stock dans la variable
previousRequest pour effectuer une ventuelle annulation de la requte grce la mthode abort().
Une fois la requte termine et russie, il ne reste plus qu' afficher les rsultats, nous allons donc passer ces derniers en
paramtres la fonction displayResults() :
Code : JavaScript
xhr.onreadystatechange = function() {
if (xhr.readyState == 4 && xhr.status == 200) {
displayResults(xhr.responseText);
};
Passons maintenant la fonction displayResults(). Cette dernire a pour but d'afficher l'utilisateur les rsultats de la
recherche. Son but est donc de parser la rponse de la requte, puis de crer les lments HTML ncessaires l'affichage, et
enfin de leur attribuer chacun un des rsultats de la recherche. Ce qui nous donne donc ceci :
Code : JavaScript
function displayResults(response) { // Affiche les rsultats d'une
requte
results.style.display = response.length ? 'block' : 'none'; //
On cache le conteneur si on n'a pas de rsultats
if(response.length) { // On ne modifie les rsultats que si on
en a obtenu
response = response.split('|'); // On parse la rponse de
la requte afin d'obtenir les rsultats dans un tableau
var responseLen = response.length;
results.innerHTML = ''; // On vide les anciens rsultats
for (var i = 0, div ; i < responseLen ; i++) { // On
parcourt les nouveaux rsultats
div =
results.appendChild(document.createElement('div')); // Ajout d'un
nouvel lment <div>
div.innerHTML = response[i];
est cliqu
div.onclick = function() {
chooseResult(this); // Le rsultat sera choisi s'il
};
}
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
302/378
}
}
Rien de bien terrible, n'est-ce pas ? Il suffit juste de comprendre que cette fonction cre un nouvel lment pour chaque rsultat
trouv et lui attribue un contenu et un vnement, rien de plus.
Maintenant, il ne nous reste plus qu' tudier la fonction chooseResult(). Basiquement, son but est vident : choisir un
rsultat, ce qui veut dire qu'un rsultat a t slectionn et doit venir remplacer le contenu de notre champ de recherche. D'un
point de vue utilisateur, l'opration semble simple, mais d'un point de vue dveloppeur il faut penser grer pas mal de choses,
comme la rinitialisation des styles des rsultats par exemple. Voici la fonction :
Code : JavaScript
function chooseResult(result) { // Choisit un des rsultats d'une
requte et gre tout ce qui y est attach
searchElement.value = previousValue = result.innerHTML; // On
change le contenu du champ de recherche et on enregistre en tant
que prcdente valeur
results.style.display = 'none'; // On cache les rsultats
result.className = ''; // On supprime l'effet de focus
selectedResult = -1; // On remet la slection zro
searchElement.focus(); // Si le rsultat a t choisi par le
biais d'un clic, alors le focus est perdu, donc on le rattribue
}
Vous voyez, il n'y a rien de bien compliqu pour cette fonction, mais il fallait penser tous ces petits dtails pour viter
d'ventuels bugs minimes.
La correction de ce TP est maintenant termine, n'hsitez pas l'amliorer selon vos envies, les possibilits sont multiples.
Ides d'amliorations
Afin de ne pas vous laisser vous reposer sur vos lauriers jusqu'au prochain chapitre, nous vous proposons deux ides
d'amliorations.
La premire consiste faciliter la saisie de caractres dans le champ de texte. Le principe consiste crire, dans le champ, le
premier rsultat et surligner la partie qui n'a pas t mentionne par l'utilisateur. Exemple :
Le premier rsultat est crit dans le champ et une partie est grise
Comme vous pouvez le constater, nous avons commenc crire les lettres to , les rsultats se sont affichs et surtout le
script nous a rajout les derniers caractres du premier rsultat tout en les surlignant afin que l'on puisse rcrire par-dessus
sans tre gn dans notre saisie. Ce n'est pas trs compliqu mettre en place, mais cela vous demandera un petit
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
303/378
approfondissement du Javascript, notamment grce au cours Insertion de balises dans une zone de texte crit par
Thunderseb sur le Site du Zro, cela afin de savoir comment surligner seulement une partie d'un texte contenu dans un champ.
La deuxime amlioration consiste vous faire utiliser un format de structuration afin d'afficher bien plus de donnes. Par
exemple, vous pouvez trs bien ajouter des donnes pour quelques villes (pas toutes quand mme), tout transfrer de manire
structure grce au JSON et afficher le tout dans la liste des rsultats, comme ceci par exemple :
Il est possible d'afficher des donnes sur les villes grce au JSON
Cela fait un bon petit dfi, n'est-ce pas ? Sur ce, c'est vous de choisir si vous souhaitez vous lancer dans cette aventure, nous
nous retrouvons la prochaine partie, qui traitera du HTML5.
304/378
Accessibilit et smantique
Le HTML5 apporte ds lors de nouveaux lments comme <nav>,
<header>, <article>, <figure> qui amliorent l'accessibilit, ainsi
que des lments comme <mark> ou <data> qui amliorent la smantique
(c'est--dire le sens qu'on donne aux textes).
Le logo de HTML 5
305/378
contraignant. L'lment <canvas> permettra de dessiner et donc de raliser des animations, comme on le ferait avec Flash et
Silverlight !
Nouvelles API
ContentEditable
ContentEditable est une technique, invente par Microsoft pour Internet Explorer, qui permet de rendre ditable un
lment HTML. Cela permet l'utilisateur d'entrer du texte dans un <div>, ou bien de crer une interface WYSIWYG (What You
See Is What You Get, c'est--dire ce que vous voyez est ce que vous obtenez ), comme Word.
Dmonstration
Aperu de lattribut ContentEditable en HTML5
Web Storage
Le Web Storage est, d'une certaine manire, le successeur des fameux cookies. Cette API permet de conserver des informations
dans la mmoire du navigateur, pendant le temps que vous naviguez, ou pour une dure beaucoup plus longue. Les cookies
fournissent plus ou moins 4 KB de stockage, alors que le Web Storage en propose 5 MB pour la plupart des navigateurs et 10
MB pour Internet Explorer. Cependant, le Web Storage n'est pas accessible par les serveurs Web, les cookies sont donc toujours
de rigueur.
Pour enregistrer une valeur, c'est tout simple, il suffit de faire :
Code : JavaScript
localStorage.setItem('nom-de-ma-cle', 'valeur de la cl');
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
306/378
Il faut donc donner un nom la cl pour pouvoir rcuprer la valeur plus tard :
Code : JavaScript
alert(localStorage.getItem('nom-de-ma-cle'));
Si les donnes ne doivent tre gardes en mmoire que pendant le temps de la navigation (elles seront perdues si l'utilisateur
ferme son navigateur), il convient d'utiliser sessionStorage au lieu de localStorage.
HTML5 Les API JavaScript
Web storage sur Wikipedia (en)
Documentation MDN
WebSocket
Le WebSocket permet une page Web de communiquer avec le serveur Web de faon bidirectionnelle : a veut dire que le
serveur peut envoyer des informations la page, tout comme cette dernire peut envoyer des informations au serveur. C'est en
quelque sorte une API approfondie du XMLHttpRequest. C'est plus complexe, car cela ncessite un serveur adapt.
HTML5 et les WebSockets
HTML5 Les API JavaScript
Documentation MDN
Geolocation
L'API de golocalisation permet, comme son nom le laisse entendre, de dtecter la position gographique du visiteur. Mais
attention, cela ne fonctionne que si l'utilisateur donne son accord, en rglant les paramtres de navigation de son navigateur. a
fonctionne pour tous les navigateurs modernes, except Internet Explorer.
Tutoriel de golocalisation en HTML5
L'API golocalisation en HTML 5
HTML5 Les API JavaScript
Documentation MDN
Workers et Messaging
L'API Workers permettent d'excuter du code en tche de fond. Ce code est alors excut en parallle de celui de la page. Si le
code de la page rencontre une erreur, a n'affecte pas le code du Worker et inversement.
Le Worker est capable d'envoyer des messages au script principal via l'API Messaging. Le script principal peut aussi envoyer
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
307/378
des messages au Worker. L'API Messaging peut aussi tre utilise pour envoyer et recevoir des messages entre une <iframe>
et sa page mre, mme si elles ne sont pas hberges sur le mme domaine.
L'API Messaging est notamment utilise pour les extensions de certains navigateurs tels qu'Opera ou Google Chrome.
Ainsi, pour ce dernier, les scripts peuvent communiquer avec une page spciale appele page d'arrire-plan , qui
permet d'enregistrer des prfrences ou d'excuter des actions spciales, comme ouvrir un nouvel onglet.
En rsum
Le HTML5 est la nouvelle mouture du langage de balisage HTML. Il a t conu afin d'amliorer l'accessibilit et la
smantique et augmenter l'interactivit avec l'utilisateur.
Cette nouvelle version n'est pas qu'un amas de nouvelles balises. Elle apporte aussi de nouvelles technologies utilisables
au sein du Javascript.
Parmi les nouvelles API apportes par le HTML5, nous en tudierons quatre : Canvas, Drag & Drop , File et
Audio/Video.
308/378
L'audio et la vido
Une des grandes nouveauts du HTML5 est l'apparition des lments <audio> et <video>, qui permettent de jouer des sons
et d'excuter des vidos, le tout nativement, c'est--dire sans plugins tels que Flash, QuickTime ou mme Windows Media Player.
Nous allons donc voir ici comment interagir, via le Javascript, avec ces deux lments !
Pour bien comprendre ce chapitre, il serait bon que vous ayez quelques notions sur ces deux lments HTML. Nous vous
invitons lire le chapitre La vido et l'audio du tutoriel de M@teo21 sur le HTML5. C'est important, car nous ne reviendrons
que trs sommairement sur l'utilisation HTML de ces deux lments : ici on s'occupe du Javascript !
L'audio
Les lments <audio> et <video> se ressemblent fortement. D'ailleurs, ils sont reprsents par le mme objet, savoir
HTMLMediaElement. Comme ils drivent du mme objet, ils en possdent les proprits et mthodes.
L'insertion d'un lment <audio> est trs simple.
Code : HTML
<audio id="audioPlayer" src="hype_home.mp3"></audio>
Ce bout de code suffit insrer un lecteur audio qui lira le son hype_home.mp3. Mais, nous, nous n'allons pas utiliser
l'attribut src, mais plutt deux lments <source>, comme ceci :
Code : HTML
<audio id="audioPlayer">
<source src="hype_home.ogg"></source>
<source src="hype_home.mp3"></source>
</audio>
De cette manire, si le navigateur est capable de lire le format .ogg, il le fera. Sans quoi, il lira le format .mp3. a permet une plus
grande interoprabilit (compatibilit entre les navigateurs et les plates-formes).
Pour afficher un contrleur de lecteur, il faut utiliser l'attribut boolen controls, comme ceci : <audio
controls="controls"></audio>. Mais ici, c'est un cours de Javascript, donc nous allons crer notre propre contrleur
de lecture !
Contrles simples
Voyons pour commencer comment recrer les boutons Play , Pause et Stop . On commence par accder l'lment :
Code : JavaScript
var player = document.querySelector('#audioPlayer');
Tant qu' tre dans la partie HTML5 du cours, vous remarquerez que nous utilisons dsormais la mthode
querySelector(), qui est, tout de mme, bien plus pratique.
309/378
Par contre, il n'y a pas de mthode stop(). Si on appuie sur un bouton Stop , la lecture s'arrte et se remet au dbut. Pour ce
faire, il suffit de faire Pause et d'indiquer que la lecture doit se remettre au dbut, avec la proprit currentTime, exprime
en secondes :
Code : JavaScript
player.pause();
player.currentTime = 0;
Deux boutons ont t placs : le premier est un bouton Play et Pause en mme temps (comme sur la plupart des lecteurs
modernes), et le second permet de stopper et de rembobiner la lecture. Voici les fonctions play et resume :
Code : JavaScript
function play(idPlayer, control) {
var player = document.querySelector('#' + idPlayer);
if (player.paused) {
player.play();
control.textContent = 'Pause';
} else {
player.pause();
control.textContent = 'Play';
}
function resume(idPlayer) {
var player = document.querySelector('#' + idPlayer);
player.currentTime = 0;
player.pause();
310/378
Le fonctionnement du bouton Play est simple : avec la mthode paused, on vrifie si la lecture est en pause. En fonction de
a, on fait play() ou pause(), et on change le libell du bouton.
Essayer !
Contrle du volume
L'intensit sonore se rgle avec la proprit volume sur une chelle allant de 0 1. Si le volume est 0, il est muet, et s'il est 1,
il est fond. Pour le diminuer de moiti, on mettra 0,5. On va faire un systme trs simple : cinq barres verticales cliquables qui
permettent de choisir un niveau sonore prdfini :
Code : HTML
<span class="volume">
<a class="stick1" onclick="volume('audioPlayer',
<a class="stick2" onclick="volume('audioPlayer',
<a class="stick3" onclick="volume('audioPlayer',
<a class="stick4" onclick="volume('audioPlayer',
<a class="stick5" onclick="volume('audioPlayer',
</span>
0)"></a>
0.3)"></a>
0.5)"></a>
0.7)"></a>
1)"></a>
Et la fonction associe :
Code : JavaScript
function volume(idPlayer, vol) {
var player = document.querySelector('#' + idPlayer);
}
player.volume = vol;
Essayer !
Analyser la lecture
311/378
Un lment HTMLMediaElement possde toute une srie d'vnements pour analyser et agir sur le lecteur. L'vnement
ontimeupdate va nous tre utile pour dtecter quand le mdia est en train d'tre jou par le lecteur. Cet vnement est
dclench continuellement pendant la lecture.
Ajoutons donc cet vnement sur notre lment <audio> :
Code : HTML
<audio id="audioPlayer" ontimeupdate="update(this)">
L'ide est de rcuprer le temps coul et de calculer un pourcentage de manire afficher la barre de progression (qui fait 100 %
de large). Donc, si la chanson dure dix minutes et qu'on en est une minute de lecture, on a lu 10 %.
La proprit duration sert rcuprer la dure totale du mdia. Le calcul est simple : on divise le temps coul par la dure
totale et on multiplie par 100. Comme a ne tombera certainement pas juste, on arrondit avec Math.ceil(). Une fois le
pourcentage rcupr, on dfinit la largeur de la barre de progression, et on affiche le pourcentage l'intrieur.
Le petit lecteur est dsormais termin !
Essayer !
Amliorations
L'interface ralise prcdemment est fonctionnelle, mais rudimentaire. Deux amliorations principales sont possibles :
Afficher le temps coul ;
Rendre la barre de progression cliquable.
312/378
}
if (hours) {
if (mins < 10) {
mins = "0" + mins;
}
On opre quelques divisions et arrondissements afin d'extraire le nombre d'heures, de minutes et de secondes. Puis on complte
avec des 0 pour un affichage plus joli.
On peut donc ajouter ceci notre fonction update() :
Code : JavaScript
document.querySelector('#progressTime').textContent =
formatTime(time);
Et modifier la barre de progression pour y ajouter un <span> dans lequel s'affichera le temps coul :
Code : HTML
<div id="progressBarControl">
<div id="progressBar">Pas de lecture</div>
</div>
<span id="progressTime">00:00</span>
313/378
L'exemple ici ne permet que de reculer dans la lecture, puisque seule la barre de progression est cliquable. Il est bien
videmment possible de coder un systme pour avancer dans la lecture, en rendant cliquable le conteneur de la barre
de progression.
Les proprits pageX et pageY de l'objet event permettent respectivement de rcuprer les positions sur l'axe des X et sur
l'axe des Y. a fonctionne pour tous les navigateurs l'exception d'Internet Explorer qui demande d'utiliser clientX et
clientY. Mais en plus de cela, il faut additionner les valeurs du dfilement horizontal et vertical. En effet, sans cela, Internet
Explorer ne tient pas compte du dfilement de la page
Ce script est un script gnrique qui retournera un objet { x: "valeur", y: "valeur" }. Dans l'exemple ici,
connatre Y n'est pas important, mais au moins vous pouvez rutiliser cette fonction.
Essayer !
314/378
Trois nouvelles proprits : offsetLeft, offsetTop et offsetParent. Ces trois proprits ne sont pas standardises,
elles ont t introduites avec Internet Explorer, mais sont universellement reconnues. offsetLeft permet de connatre le
nombre de pixels, sur l'axe horizontal, dont est dcal un lment enfant par rapport son parent. offsetTop, c'est pareil, mais
pour le dcalage vertical.
offsetParent ressemble parentNode, mais n'est pas identique. offsetParent retourne le premier lment parent
positionn, c'est--dire qui est affich par le navigateur. De manire gnrale, on utilise parentNode pour naviguer dans le
DOM, et offsetParent pour tout ce qui concerne les mesures, comme c'est le cas ici.
On clique !
Maintenant que nous avons nos deux fonctions getMousePosition() et getPosition(), nous pouvons crire la
fonction clickProgress(), qui sera excute ds que l'internaute cliquera sur la barre de progression :
Code : JavaScript
function clickProgress(idPlayer, control, event) {
var parent = getPosition(control);
// La position absolue de
la progressBar
var target = getMousePosition(event); // L'endroit de la
progressBar o on a cliqu
var player = document.querySelector('#' + idPlayer);
var x = target.x - parent.x;
var wrapperWidth =
document.querySelector('#progressBarControl').offsetWidth;
var percent = Math.ceil((x / wrapperWidth) * 100);
var duration = player.duration;
}
On rcupre la distance x, qui est la distance entre le bord gauche de la barre et l'endroit o on a cliqu. On divise x par la
largeur totale du conteneur de la barre de progression (avec offsetWidth) et on multiplie par 100 pour obtenir un
pourcentage. Ensuite, on calcule le currentTime en multipliant le temps total de la chanson par le pourcentage, le tout divis
par 100.
Et n'oublions pas de modifier le code HTML en consquence :
Code : HTML
<div id="progressBar" onclick="clickProgress('audioPlayer', this,
event)">Pas de lecture</div>
Et a marche !
Essayer !
La vido
Il n'y a pas grand-chose ajouter en ce qui concerne les vidos. Le principe de fonctionnement est exactement le mme que pour
les lectures audio. L'lment <video> possde toutefois quelques proprits en plus :
Proprit
Description
height
width
315/378
poster
La largeur de la vido
En dehors de a, la cration et la personnalisation de la lecture d'une vido est rigoureusement identique celle d'une piste
audio.
l'heure o ce cours est rdig, l'implmentation des lments <audio> et <video> n'est pas encore parfaite au sein des
diffrents navigateurs, surtout en ce qui concerne leurs anciennes versions ou certains systmes d'exploitation qui ne
bnficient pas toujours des bons codecs. Pour se faciliter la vie, il peut tre utile d'utiliser un framework Javascript destin la
lecture d'lments <audio> et <video>. Ce genre de framework propose gnralement une solution en Flash si le navigateur
n'est pas la hauteur du HTML5.
Voici quelques frameworks qu'il peut tre intressant de considrer :
Popcorn.js
Video.js
HD Webplayer
Projekktor
En rsum
Les lments <audio> et <video> possdent tous les deux de nombreux attributs et mthodes afin que chacun
puisse crer un lecteur entirement personnalis.
La diffrence entre les deux lments est minime. Ils sont tous les deux bass sur le mme objet, l'lment <video>
n'apporte que quelques attributs supplmentaires permettant de grer l'affichage.
Contrairement au Flash, la protection du contenu n'existe pas avec ces deux lments. De plus, ils ne sont pas encore
entirement supports par tous les navigateurs Web. Rflchissez donc bien avant d'carter dfinitivement toute solution
avec Flash !
316/378
L'lment Canvas
L'lment <canvas> est une zone dans laquelle il va tre possible de dessiner au moyen du Javascript. Cet lment fait son
apparition dans la spcification HTML5, mais existe depuis plusieurs annes dj. Il a t dvelopp par Apple pour son
navigateur Safari. Firefox a t un des premiers navigateurs l'implmenter, suivi par Opera et Chrome, qui, pour rappel, utilise le
mme moteur de rendu que Safari. La dernire version d'Internet Explorer supporte galement <canvas>.
Canvas est un gros sujet qui mriterait un cours lui tout seul. Tout au long de ce chapitre d'initiation, nous allons dcouvrir les
bases de ce nouvel lment !
Premires manipulations
La premire chose faire est d'insrer le canvas :
Code : HTML
<canvas id="canvas" width="150" height="150">
<p>Dsol, votre navigateur ne supporte pas Canvas. Mettez-vous
jour</p>
</canvas>
Une fois qu'on a le canvas, il faut accder ce qu'on appelle son contexte, avec getContext(). Il n'y a pour l'instant qu'un
seul contexte disponible : la deux dimensions (2D). Il est prvu que les navigateurs grent un jour la 3D, mais a reste
exprimental l'heure actuelle.
Principe de fonctionnement
Dessiner avec Canvas se fait par le biais de coordonnes. Le coin suprieur gauche du canvas est de coordonnes (0,0). Si on
descend ou qu'on va vers la droite, on augmente les valeurs. a ne change finalement pas trop de ce qu'on connat, par exemple
pour le positionnement absolu en CSS.
On va utiliser les mthodes pour tracer des lignes et des formes gomtriques.
Traons un rectangle de 50 sur 80 pixels :
Code : JavaScript
context.fillStyle = "gold";
context.fillRect(0, 0, 50, 80);
317/378
Dans un premier temps, on choisit une couleur avec fillStyle, comme un peintre qui trempe son pinceau avant de
commencer son tableau. Puis, avec fillRect(), on trace un rectangle. Les deux premiers paramtres sont les coordonnes du
sommet suprieur gauche du rectangle que nous voulons tracer. Le troisime paramtre est la largeur du rectangle, et le
quatrime est la hauteur. Autrement dit : fillrect(x, y, largeur, hauteur).
Essayer !
Si on veut centrer ce rectangle, il faut sappliquer quelques calculs pour spcifier les coordonnes :
Code : JavaScript
context.fillRect(50, 35, 50, 80);
On recommence tout, et on centre le rectangle. Ds que c'est fait, on ajoute un carr de 40 pixels d'une couleur semi-transparente
:
Code : JavaScript
context.fillStyle = "gold";
context.fillRect(50, 35, 50, 80);
context.fillStyle = "rgba(23, 145, 167, 0.5)";
context.fillRect(40, 25, 40, 40);
La proprit fillStyle peut recevoir diverses valeurs : le nom de la couleur, un code hexadcimal (sans oublier le # devant),
une valeur RGB, HSL ou HSLA ou, comme ici, une valeur RGBA. Dans le cas d'une valeur RGBA, le quatrime paramtre est
l'opacit, dfinie sur une chelle de 0 1, le 0 tant transparent et le 1 opaque. Comme on peut le voir, le carr a t dessin pardessus le rectangle :
Essayer !
318/378
Nous avons cr des formes pleines, mais il est galement possible de crer des formes creuses, avec juste un contour. Canvas
considre deux types de formes : fill et stroke. Une forme fill est une forme remplie, comme nous avons fait
prcdemment, et une forme stroke est une forme vide pourvue d'un contour. Si pour crer un rectangle fill on utilise
fillRect(), pour crer un rectangle stroke on va utiliser strokeRect() !
Code : JavaScript
context.strokeStyle = "gold";
context.strokeRect(50, 35, 50, 80);
context.fillStyle = "rgba(23, 145, 167, 0.5)";
context.fillRect(40, 25, 40, 40);
Comme il s'agit d'un contour, il est possible de choisir l'paisseur utiliser. Cela se fait avec la proprit lineWidth :
Code : JavaScript
context.lineWidth = "5";
context.strokeStyle = "gold";
context.strokeRect(50, 35, 50, 80);
context.fillStyle = "rgba(23, 145, 167, 0.5)";
context.fillRect(40, 25, 40, 40);
Essayer !
Effacer
Une dernire mthode existe en ce qui concerne les rectangles : clearRect(x, y, largeur, hauteur). Cette
mthode agit comme une gomme, c'est--dire qu'elle va effacer du canvas les pixels dlimits par le rectangle. Tout comme
fillRect(), on lui fournit les coordonnes des quatre sommets. clearRect() est utile pour faire des dcoupes au sein
des formes, ou tout simplement pour effacer le contenu du canvas.
Code : JavaScript
context.strokeStyle = "gold";
context.strokeRect(50, 35, 50, 80);
context.fillStyle = "rgba(23, 145, 167, 0.5)";
context.fillRect(40, 25, 40, 40);
context.clearRect(45, 40, 30, 10);
Formes gomtriques
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
319/378
Canvas fournit peu de formes gomtriques. Il y a le rectangle, les arcs et c'est tout. Mais pour complter ce manque, Canvas
dispose de chemins ainsi que de courbes de Bzier cubiques et quadratiques.
closePath() n'est pas ncessaire ; il termine le chemin pour nous, en reliant le dernier point au tout premier. Si on veut une
forme ferme, via stroke(), c'est assez pratique. Par contre, si on veut remplir la forme avec fill(), la forme sera ferme
automatiquement, donc closePath() est inutile.
Essayer !
Les arcs
En plus des lignes droites, il est possible de tracer des arcs de cercle, avec la mthode arc(x, y, rayon,
angleDepart, angleFin, sensInverse). Les angles sont exprims en radians (oui, rappelez-vous vos cours de
trigonomtrie !). Avec les arcs, x et y sont les coordonnes du centre de l'arc. Les paramtres angleDepart et angleFin
dfinissent les angles de dbut et de fin de l'arc. Comme dit plus haut, c'est exprim en radians, et non en degrs.
Pour rappel, pour obtenir des radians il suffit de multiplier les degrs par divis par 180 : (Math.PI / 180) *
degrees.
Code : JavaScript
context.beginPath(); // Le cercle extrieur
context.arc(75, 75, 50, 0, Math.PI * 2); // Ici le calcul est
simplifi
context.stroke();
context.beginPath(); // La bouche, un arc de cercle
context.arc(75, 75, 40, 0, Math.PI); // Ici aussi
context.fill();
context.beginPath(); // L'il gauche
context.arc(55, 70, 20, (Math.PI / 180) * 220, (Math.PI / 180) *
320);
context.stroke();
context.beginPath(); // L'il droit
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
320/378
Essayer !
Pour chaque arc, il est plus propre et plus facile de commencer un nouveau chemin avec beginPath().
Utilisation de moveTo()
Comme on l'a vu plus haut, moveTo() permet de dplacer le crayon l'endroit o l'on souhaite commencer un chemin. Mais
cette mthode peut aussi tre utilise pour effectuer des leves de crayon au sein d'un mme chemin :
Code : JavaScript
context.beginPath(); // La bouche, un arc de cercle
context.arc(75, 75, 40, 0, Math.PI);
context.fill();
context.beginPath(); // Le cercle extrieur
context.arc(75, 75, 50, 0, Math.PI * 2);
context.moveTo(41, 58); // L'il gauche
context.arc(55, 70, 20, (Math.PI / 180) * 220, (Math.PI / 180) *
320);
context.moveTo(81, 58); // L'il droit
context.arc(95, 70, 20, (Math.PI / 180) * 220, (Math.PI / 180) *
320);
context.stroke();
Essayer !
Et si on retire les deux moveTo(), on obtient quelque chose comme a :
321/378
Les tangentes
Les courbes sont dfinies par leurs points d'arrive (x et y) et par les points de contrle. Dans le cas d'une courbe de Bzier
cubique, deux points sont ncessaires. La difficult des courbes de Bzier est de connatre les valeurs utiles pour les points de
contrle. C'est d'autant plus complexe qu'on ne voit pas en temps rel ce qu'on fait Ce genre de courbes est donc puissant,
mais complexe mettre en uvre.
Il existe toutefois des plugins qui permettent de convertir des dessins vectoriels en instructions Canvas. C'est le cas de
Ai2Canvas, un plugin pour Adobe Illustrator.
322/378
Essayer !
Ce n'est pas compliqu utiliser, c'est le mme principe qu'arc(). Ce qu'il y a de difficile ici est de s'y retrouver dans les
coordonnes.
Images et textes
Les images
Il est possible d'insrer des images au sein d'un canvas. Pour ce faire, on utilisera la mthode drawImage(image, x, y),
mais attention : pour qu'une image puisse tre utilise, elle doit au pralable tre accessible via un objet Image ou un lment
<img />. Il est galement possible d'insrer un canvas dans un canvas ! En effet, le canvas que l'on va insrer est considr
comme une image.
Insrons l'ne Zozor du Site du Zro au sein du canvas :
Code : JavaScript
var zozor = new Image();
zozor.src = 'zozor.png'; // Image de 80x80 pixels
context.drawImage(zozor, 35, 35);
On aurait pu rcuprer une image dj prsente dans la page : <img id="myZozor" src="zozor.png" alt="Zozor
assis" />
Code : JavaScript
var zozor = document.querySelector('#myZozor');
context.drawImage(zozor, 35, 35);
Attention aux grandes images : si l'image est trop longue charger, elle sera affiche de faon saccade au sein du canvas. Une
solution est d'utiliser onload pour dclencher le dessin de l'image une fois qu'elle est charge :
Code : JavaScript
var zozor = new Image();
zozor.src = 'zozor.png';
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
323/378
zozor.onload = function() {
context.drawImage(zozor, 35, 35);
}
Essayer !
Mise l'chelle
drawImage(image, x, y, largeur, hauteur) possde deux paramtres supplmentaires facultatifs : largeur et
hauteur, qui permettent de dfinir la largeur et la hauteur que l'image occupera une fois incruste dans le canvas. Si la
diminution de la taille des images ne pose pas trop de problmes, vitez toutefois de les agrandir, au risque de voir vos images
devenir floues.
Code : JavaScript
context.drawImage(zozor, 35, 35, 40, 40);
Ici, l'image est rduite de moiti, puisque de base elle fait 80 pixels sur 80 pixels.
Recadrage
Quatre paramtres supplmentaires et optionnels s'ajoutent drawImage(). Ils permettent de recadrer l'image, c'est--dire de
prlever une zone rectangulaire au sein de l'image afin de la placer dans le canvas :
Code : JavaScript
drawImage(image, sx, sy, sLargeur, sHauteur, dx, dy, dLargeur,
dHauteur)
Les paramtres commenant par s indiquent la source, c'est--dire l'image, ceux commenant par d indiquent la destination,
autrement dit le canvas :
324/378
image
Toute la difficult est donc de ne pas semmler les pinceaux dans les paramtres :
Code : JavaScript
var zozor = document.querySelector('#plush');
context.drawImage(zozor, 99, 27, 100, 100, 25, 25, 100, 100);
Essayer !
Les patterns
Comment faire se rpter une image pour, par exemple, crer un fond ? C'est possible de faire une double boucle for et d'insrer
plusieurs fois la mme image. Mais il y a plus simple : les patterns. On parle aussi de motifs en franais. Un pattern est une image
qui se rpte comme un papier peint. Pour en crer un, on utilise la mthode createPattern(image, type). Le premier
argument est l'image utiliser, et le deuxime est le type de pattern. Diffrents types existent, mais seul repeat semble reconnu
par la plupart des navigateurs :
Code : JavaScript
var zozor = new Image();
zozor.src = 'zozor.png';
zozor.onload = function() {
var pattern = context.createPattern(zozor, 'repeat');
context.fillStyle = pattern;
context.fillRect(0, 0, 150, 150);
}
325/378
Essayer !
La faon de procder est un peu trange, puisqu'il faut passer le pattern fillStyle, et ensuite crer un rectangle plein qui
recouvre l'entiret du canvas. En clair, il s'agit de crer un rectangle avec une image qui se rpte comme fond.
Vous devez absolument passer par lvnement load, sinon le pattern ne s'affichera pas correctement si l'image n'est
pas charge.
Le texte
Pour crire du texte au sein d'un canvas, il y a les mthodes fillText() et strokeText(), secondes par la proprit
font, qui permet de dfinir le style du texte :
Code : JavaScript
context.fillStyle = "rgba(23, 145, 167, 1)";
context.fillRect(50, 50, 50, 50);
context.font = "bold 22pt Calibri,Geneva,Arial";
context.fillStyle = "#fff";
context.fillText("js", 78, 92);
Essayer !
Les mthodes fillStyle et strokeStyle sont toujours utilisables, puisque les textes sont considrs comme des formes
au mme titre que les rectangles ou les arcs.
La proprit font reoit des informations sur la police utiliser, l'exception de la couleur, qui est gre par strokeStyle et
fillStyle. Dans l'exemple qui va suivre, nous allons utiliser un texte en Calibri, de 22 points et mis en gras. a ressemble du
CSS en fait.
fillText() reoit trois paramtres : le texte et les positions x et y de la ligne d'criture du texte :
Un quatrime paramtre peut tre ajout : la largeur maximale que le texte doit utiliser.
Lignes et dgrads
Les styles de lignes
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
326/378
Les extrmits
La proprit lineCap permet de dfinir la faon dont les extrmits des chemins sont affiches. Trois valeurs sont admises :
butt, celle par dfaut, round et square. Une image vaut mieux qu'un long discours, alors voici trois lignes, chacune avec un
lineCap diffrent :
>
lineCap s'utilise de la mme faon que lineWidth, exemple :
Code : JavaScript
context.beginPath();
context.lineCap = 'round';
context.moveTo(75, 20);
context.lineTo(75, 130);
context.stroke();
Les intersections
Comment grer la faon dont les angles des chemins sont affichs ? Simple, avec lineJoin. Cette proprit reoit elle aussi
trois valeurs diffrentes : round, bevel et miter, ce dernier tant la valeur par dfaut. Comme prcdemment, une image sera
plus explicite :
Les dgrads
l'heure actuelle, que ferions-nous sans dgrads ? Canvas propose deux types de dgrads : linaire et radial. Pour crer un
dgrad, on commence par crer un objet canvasGradient que l'on va assigner fillStyle. Pour crer un tel objet, on
utilise au choix createLinearGradient() ou createRadialGradient().
Dgrads linaires
On a besoin de quatre paramtres pour crer un dgrad linaire :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
327/378
Code : JavaScript
createLinearGradient(debutX, debutY, finX, finY)
debutX et debutY sont les coordonnes du point de dpart du dgrad, et finX et finY sont les coordonnes de fin.
Faisons un dgrad :
Code : JavaScript
var linear = new context.createLinearGradient(0, 0, 150, 150);
context.fillStyle = linear;
Ce n'est pas suffisant, puisqu'il manque les informations sur les couleurs. On va ajouter a avec
addColorStop(position, couleur). Le premier paramtre, position, est une valeur comprise entre 0 et 1. C'est la
position relative de la couleur par rapport au dgrad. Si on met 0.5, la couleur commencera au milieu :
Code : JavaScript
var linear = context.createLinearGradient(0, 0, 0, 150);
linear.addColorStop(0, 'white');
linear.addColorStop(1, '#1791a7');
context.fillStyle = linear;
context.fillRect(20, 20, 110, 110);
Pour modifier l'inclinaison du dgrad, il faut modifier les paramtres de createLinearGradient(). Par exemple, si on met
createLinearGradient(0, 0, 150, 150), la fin du dgrad sera dans le coin infrieur droit, et donc inclin 45
degrs.
Il est possible de mettre plus de deux addColorStop(). Voici un exemple avec quatre :
Code : JavaScript
var linear = context.createLinearGradient(0, 0, 0, 150);
linear.addColorStop(0, 'white');
linear.addColorStop(0.5, '#1791a7');
linear.addColorStop(0.5, 'orange');
linear.addColorStop(1, 'white');
context.fillStyle = linear;
context.fillRect(10, 10, 130, 130);
328/378
Essayer !
Dgrads radiaux
Du ct des dgrads radiaux, il faut six paramtres :
Code : JavaScript
createRadialGradient(centreX, centreY, centreRayon, finX, finY,
finRayon)
Un dgrad radial est dfini par deux choses : un premier cercle (le centre) qui fait office de point de dpart et un second qui fait
office de fin. Ce qui est pratique, c'est que les deux cercles n'ont pas besoin d'avoir la mme origine, ce qui permet d'orienter le
dgrad :
Code : JavaScript
var radial = context.createRadialGradient(75, 75, 0, 130, 130, 150);
radial.addColorStop(0, '#1791a7');
radial.addColorStop(1, 'white');
context.fillStyle = radial;
context.fillRect(10, 10, 130, 130);
Essayer !
Ici, le cercle du centre est au centre du canvas, et celui de fin en bas droite. Grce aux dgrads radiaux, il est possible de
crer des bulles assez facilement. La seule condition est que la couleur de fin du dgrad soit transparente, ce qui ncessite
l'utilisation d'une couleur RGBA ou HSLA :
Code : JavaScript
var radial1 = context.createRadialGradient(0, 0, 10, 100, 20, 150);
// fond
radial1.addColorStop(0, '#ddf5f9');
radial1.addColorStop(1, '#ffffff');
var radial2 = context.createRadialGradient(75, 75, 10, 82, 70, 30);
// bulle orange
radial2.addColorStop(0, '#ffc55c');
radial2.addColorStop(0.9, '#ffa500');
radial2.addColorStop(1, 'rgba(245,160,6,0)');
var radial3 = context.createRadialGradient(105, 105, 20, 112, 120,
50); // bulle turquoise
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
329/378
radial3.addColorStop(0, '#86cad2');
radial3.addColorStop(0.9, '#61aeb6');
radial3.addColorStop(1, 'rgba(159,209,216,0)');
context.fillStyle = radial1;
context.fillRect(10, 10, 130, 130);
context.fillStyle = radial2;
context.fillRect(10, 10, 130, 130);
context.fillStyle = radial3;
context.fillRect(10, 10, 130, 130);
Essayer !
Oprations
L'tat graphique
La mthode save() a pour fonction de sauvegarder l'tat graphique du canvas, c'est--dire les informations concernant les
styles appliqus au canvas. Ces informations sont fillStyle, strokeStyle, lineWidth, lineCap, lineJoin ainsi
que translate() et rotate(), que nous allons dcouvrir plus bas.
chaque appel de la mthode save(), l'tat graphique courant est sauvegard dans une pile. Pour restaurer l'tat prcdent, il
faut utiliser restore().
Les translations
La translation permet de dplacer le repaire d'axes du canvas. L'ide est de placer le point (0,0) l'endroit o l'on souhaite
dessiner une forme. De cette manire, on dessine la forme sans se soucier des calculs de son emplacement, ce qui peut se rvler
utile quand on insre des formes complexes. Une fois que les formes sont dessines, on replace les axes leur point d'origine. Et,
bonne nouvelle, save() et restore() prennent en compte les translations !
Les translations se font avec la mthode translate(x, y). x est l'importance du dplacement sur l'axe des abscisses et y
sur l'axe des ordonnes : les valeurs peuvent donc tre ngatives.
Code : JavaScript
context.save();
context.translate(40, 40);
context.fillStyle = "teal";
context.fillRect(0, 0, 50, 50);
context.restore();
context.fillStyle = "orange";
context.fillRect(0, 0, 50, 50);
330/378
Essayer !
On commence par sauvegarder l'tat du canvas. Ensuite, on dplace l'origine des axes au point (40,40) et on y dessine un carr
bleu-gris. Ds que c'est fait, on restaure l'tat, ce qui a pour consquence de replacer l'origine des axes au point (0,0) du canvas.
L, on dessine le carr orange. Grce la translation, on a pu laisser (0,0) comme coordonnes de fillRect() !
Les rotations
Les rotations permettent d'appliquer une rotation aux axes du canvas. Le canvas tourne autour de son point d'origine (0,0). La
mthode rotate() reoit un seul paramtre : l'angle de rotation spcifi en radians. Il est possible de combiner une rotation et
une translation, comme le montre l'exemple suivant :
Code : JavaScript
context.translate(75,75);
context.fillStyle = "teal";
context.rotate((Math.PI / 180) * 45);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "orange";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "teal";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "orange";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
Essayer
On place l'origine des axes au centre du canvas avec translate(). On opre une premire rotation de 45 degrs et on dessine
un carr bleu-gris. Ensuite, on fait une deuxime rotation de 90 degrs et on dessine un carr orange. On continue de tourner les
axes de 90 degrs et on dessine un nouveau carr bleu-gris. On fait une dernire rotation et on dessine un carr orange.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
331/378
Animations
La gestion des animations avec Canvas est quasi inexistante ! En effet, Canvas ne propose rien pour animer les formes, les
dplacer, les modifier Pour arriver crer une animation avec Canvas, il faut :
1.
2.
3.
4.
5.
6.
En clair, il suffit d'appeler une fonction qui, toutes les x secondes, va redessiner le canvas. Il est galement possible d'excuter
des fonctions la demande de l'utilisateur, mais a, c'est assez simple.
Un exemple concret
Reprenons le canvas que nous venons de raliser :
332/378
En nous basant sur son code, nous allons faire tourner le dessin dans le sens des aiguilles d'une montre. Pour commencer, il faut
crer une fonction qui sera appele par window.requestAnimationFrame(). Il s'agira de la fonction draw(angle).
Cette fonction efface le canvas et le redessine avec un angle de rotation incrment de quelques degrs.
Code : JavaScript
window.onload = function() {
var canvas = document.querySelector('#canvas');
var context = canvas.getContext('2d');
function draw(angle) {
context.save();
context.clearRect(0, 0, 150, 150);
context.translate(75,75);
context.fillStyle = "teal";
context.rotate((Math.PI / 180) * (45 + angle)); // ne pas
oublier le dcalage
context.fillRect(0, 0, 50, 50);
context.fillStyle = "orange";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "teal";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.fillStyle = "orange";
context.rotate(Math.PI / 2);
context.fillRect(0, 0, 50, 50);
context.restore();
angle = angle + 2; // on augmente le dcalage
if (angle >= 360) angle = 0; // on remet le dcalage 0,
puisqu'on a fait le tour du cercle
}
};
La variable angle reprsente le dcalage. Lors du premier appel de draw(), le dcalage vaut 0. Aprs le premier appel, on
incrmente angle de 2 degrs, et donc, lors du prochain appel, tout le canvas sera dessin avec un dcalage de 2 degrs. On
rincrmente de 2, et on redessine. Ainsi de suite, pour donner l'illusion que toute la forme bouge, alors qu'on ne fait que
spcifier un angle de rotation de dpart qui va croissant.
Essayer !
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
333/378
Les possibilits d'animation de Canvas sont toutes bases sur le mme principe : window.requestAnimationFrame().
Ici, il s'agissait de crer un effet de rotation, mais il est possible de crer une courbe qui s'tire (une courbe de Bzier pour
laquelle on incrmente les valeurs), d'animer une balle qui rebondit Bref, les possibilits sont nombreuses, mais une fois que le
principe est acquis, il est facile de se dbrouiller.
Ce chapitre d'introduction Canvas est dsormais termin. Toutes les ficelles de ce nouvel lment n'ont pas t vues, mais le
principal est l. Il ne tient qu' vous de vous exercer et d'approfondir votre connaissance de <canvas> !
En rsum
L'lment <canvas> est une zone de la page dans laquelle il est possible de dessiner des formes via le Javascript.
Canvas supporte galement un systme basique pour crer des animations.
Le dessin se fait par l'intermdiaire de coordonnes dont l'origine des axes (le point (0,0)) est le coin suprieur gauche
du canvas.
Une fois dessine, une forme n'est plus manipulable. Il est ncessaire d'effacer le contenu du canvas, puis de redessiner.
Canvas ne supporte que quelques formes : le rectangle, l'arc de cercle, et les courbes de Bzier quadratiques et cubiques.
Il est galement possible d'insrer des images au sein du canvas, tout comme de crer des dgrads ou d'ajouter du texte.
L'utilisation des rotations et des translations facilite les calculs des coordonnes et donc la cration du dessin.
Si canvas vous intresse, sachez qu'il existe des frameworks qui permettent de simplifier le dessin, et mme d'ajouter
des vnements aux "formes". C'est le cas de KineticJS, expliqu dans ce tutoriel de bestmomo.
334/378
L'API File
Auparavant, la gestion des fichiers tait extrmement limite avec le Javascript, les actions possibles taient peu intressantes,
la fois pour le dveloppeur et l'utilisateur. En revanche, le HTML5 fournit maintenant une API nomme File . Celle-ci est
nettement plus intressante que ce quoi nous tions limits avant son implmentation. Il est maintenant possible de manipuler
un ou plusieurs fichiers afin de les uploader ou d'obtenir des informations, comme leur poids par exemple.
L'objectif de ce chapitre est de vous fournir un tour d'horizon de l'API File.
Premire utilisation
L'API que nous allons dcouvrir n'est pas utilisable seule. Autrement dit, elle ncessite d'tre appele par diverses technologies
permettant son accs et lui fournissant les fichiers qu'elle peut manipuler. Cette API a t conue de cette manire afin d'viter
que ce ne soit vous, dveloppeurs, qui choisissiez quel fichier lire sur l'ordinateur du client. Si cette scurit nexistait pas, les
consquences pourraient tre dsastreuses.
Sachez que l'API File ne vous permet pas, actuellement, d'crire un fichier stock sur l'ordinateur d'un client ! Vous ne
pourrez que le lire ou bien l'uploader pour le modifier sur un serveur, l'criture d'un fichier sur l'ordinateur du client est
encore en cours d'tude l'heure o nous crivons ces lignes.
Afin de pouvoir utiliser notre API, il va nous falloir dfinir comment les fichiers vont pouvoir tre choisis par l'utilisateur. La
solution la plus simple pour commencer est l'utilisation d'une balise <input type="file" />, qui va nous permettre
d'accder aux proprits des fichiers slectionns par l'utilisateur. Ces proprits constituent une partie de l'API File.
Prenons donc une balise toute simple :
Code : HTML
<input id="file" type="file" />
Et ajoutons-lui un vnement :
Code : JavaScript
document.querySelector('#file').onchange = function() {
// Du code
};
Pour accder au fichier il va nous falloir passer par la proprit files de notre balise <input>. Celle-ci va nous permettre
d'accder une collection d'objets utilisables de la mme manire qu'un tableau, chaque objet reprsentant un fichier.
Pourquoi une collection d'objets, alors que notre input ne nous permet de slectionner qu'un seul fichier ?
Eh bien, parce que le HTML5 a ajout la possibilit de choisir plusieurs fichiers pour un seul et mme input ! Il vous suffit d'y
ajouter l'attribut multiple pour que cela soit autoris au client :
Code : HTML
<input id="file" type="file" multiple />
La proprit files est la mme pour tous, que la slection de fichiers soit multiple ou non. Si vous voulez lire le fichier d'un
<input> ne grant qu'un seul fichier, alors vous utiliserez files[0] et non pas file.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
335/378
Maintenant que ce point est clairci, essayons d'obtenir le nom du fichier slectionn grce la proprit name contenue dans
chaque objet de type File :
Code : JavaScript
document.querySelector('#file').onchange = function() {
alert(this.files[0].name);
};
Essayer !
Alors, certes, l'utilit est vraiment moindre, mais vous allez vite dcouvrir de nombreuses possibilits d'utilisation au cours des
paragraphes suivants. Ici, nous allons tcher de vous faire dcouvrir l'API File, nous aurons donc beaucoup de thorie, mais la
mise en pratique viendra aprs.
L'objet Blob
Un objet de type Blob est une structure reprsentant des donnes binaires disponibles uniquement en lecture seule. La plupart
du temps, vous rencontrerez ces objets uniquement lorsque vous manipulerez des fichiers, car ces objets reprsentent les
donnes binaires du fichier cibl.
Concrtement, que pouvons-nous faire avec un Blob ? Eh bien, pas grand-chose au final Enfin, pas en l'utilisant seul tout du
moins. Car, bien qu'il soit possible de crer un Blob par nous-mmes (avec l'objet BlobBuilder), nous ne le ferons
quasiment jamais puisque nous utiliserons ceux crs lors de la manipulation de fichiers, ce que nous verrons par la suite.
Les objets Blob possdent deux proprits nommes size et type qui permettent respectivement de rcuprer la taille en
octets des donnes manipules par le Blob ainsi que leur type MIME.
Il existe galement une mthode nomme slice(), mais c'est un sujet bien trop avanc et peu utile. Si vous souhaitez en savoir
plus sur cette fonction, nous vous invitons consulter la documentation du MDN.
L'objet File
Les objets File possdent un nom bien reprsentatif puisqu'ils permettent de manipuler les fichiers. Leur particularit est qu'ils
hritent des proprits et mthodes des objets Blob, voil pourquoi nous ne crerons quasiment jamais ces derniers par nousmmes.
Donc, en plus des proprits et mthodes des objets Blob, les objets File possdent deux proprits supplmentaires qui
sont name pour obtenir le nom du fichier et lastModifiedDate pour obtenir la date de la dernire modification du fichier
(sous forme d'objet Date bien videmment).
Et c'est tout ?
336/378
Heureusement que non ! Bien que les objets File ne soient pas intressants en terme d'informations, ils le deviennent
soudainement bien plus lorsque l'on commence aborder leur lecture, grce aux objets de type FileReader !
Comme prcis prcdemment, nous allons aborder la lecture des fichiers grce l'objet FileReader. Son instanciation
s'effectue sans aucun argument :
Code : JavaScript
var reader = new FileReader();
Cet objet permet la lecture asynchrone de fichiers, et ce grce trois mthodes diffrentes :
Nom
Description
Stocke les donnes dans un objet de type ArrayBuffer. Ces objets ont t conus pour
permettre l'criture et la lecture de donnes
readAsArrayBuffer() binaires directement dans leur forme native, ils sont surtout utiliss dans des domaines
exigeants tels que le WebGL. Il y a peu de
chances pour que vous utilisiez un jour cette mthode.
readAsDataURL()
Les donnes sont converties dans un format nomm DataURL. Ce format consiste convertir
toutes les donnes binaires d'un fichier
en base64 pour ensuite stocker le rsultat dans une chane de caractres. Cette dernire est
complte par la spcification du type
MIME du fichier concern. Les DataURL permettent donc de stocker un fichier sous forme
d'une URL lisible par les navigateurs rcents,
leur utilisation est de plus en plus frquente sur le Web.
readAsText()
Les donnes ne subissent aucune modification, elles sont tout simplement lues puis stockes
sous forme d'une chane de caractres.
Si vous allez consulter la documentation du MDN au sujet de l'objet FileReader, vous constaterez alors qu'il existe
une mthode supplmentaire nomme readAsBinaryString(). Nous n'en avons pas parl, car il se trouve qu'elle
est dj dprcie par le W3C.
Ces trois mthodes prennent chacune en paramtre un argument de type Blob ou File. La mthode readAsText()
possde un argument supplmentaire (et facultatif) permettant de spcifier l'encodage du fichier, qui s'utilise comme ceci :
Code : JavaScript
reader.readAsText(file, 'UTF-8');
reader.readAsText(file, 'ISO-8859-1');
Avant d'utiliser l'une de ces mthodes, rappelez-vous que nous avons bien prcis que la lecture d'un fichier est asynchrone ! Il
faut donc partir du principe que vous allez avoir plusieurs vnements votre disposition. Ces vnements diffrent peu de ceux
que l'on rencontre avec la seconde version de l'objet XMLHttpRequest :
Nom
Description
progress
Tout comme avec les objets XHR, l'vnement progress se dclenche intervalles rguliers durant la
progression
de la lecture. Il fournit, lui aussi, un objet en paramtre possdant deux proprits, loaded et total,
indiquant
respectivement le nombre d'octets lus et le nombre d'octets lire en tout.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
337/378
load
loadend
abort
Se dclenche quand la lecture est interrompue (avec la mthode abort() par exemple).
error
Se dclenche quand une erreur a t rencontre. La proprit error contiendra alors un objet de type
FileError
pouvant vous fournir plus d'informations.
Une fois les donnes lues, il ne vous reste plus qu' les rcuprer dans la proprit result. Ainsi, afin de lire un fichier texte,
vous n'avez qu' faire comme ceci :
Code : HTML
<input id="file" type="file" />
<script>
var fileInput = document.querySelector('#file');
fileInput.onchange = function() {
var reader = new FileReader();
reader.onload = function() {
alert('Contenu du fichier "' + fileInput.files[0].name + '"
:\n\n' + reader.result);
};
reader.readAsText(fileInput.files[0]);
};
</script>
Essayer !
Pour finir sur la lecture des fichiers, sachez que l'objet FileReader possde aussi une proprit readyState permettant de
connatre l'tat de la lecture. Il existe trois tats diffrents reprsents par des constantes spcifiques aux objets FileReader :
Constante Valeur
Description
EMPTY
LOADING
DONE
Tout comme avec un objet XHR, vous pouvez vrifier l'tat de la lecture, soit avec la constante :
Code : JavaScript
if(reader.readyState == reader.LOADING) {
// La lecture est en cours...
}
338/378
if(reader.readyState == 1) {
// La lecture est en cours...
}
Mise en pratique
L'tude de l'API File est maintenant termine. Il est probable que vous vous demandiez encore ce que nous lui trouvons
d'exceptionnel... Eh bien, il est vrai que, si nous l'utilisons uniquement avec des balises <input>, alors nous sommes assez
limits dans son utilisation. Ce chapitre couvre la base de l'API File, son utilisation seule, mais il faut savoir que le principal
intrt de cette API rside en fait dans son utilisation avec d'autres ressources. Ainsi, un petit plus loin dans ce chapitre, nous
allons tudier comment l'utiliser conjointement avec l'objet XMLHttpRequest afin d'effectuer des uploads ; nous verrons
aussi, dans un chapitre ultrieur, comment s'en servir efficacement avec le Drag & Drop. Bref, ne vous en faites pas, nous n'en
avons pas encore termin avec cette fameuse API.
Nous allons ici faire une mise en pratique plutt sympathique de cette API. Le scnario est le suivant : vous souhaitez crer un
site d'hbergement d'images interactif. Le principe est simple, l'utilisateur slectionne les images qu'il souhaite uploader, elles
sont alors affiches en prvisualisation sur la page et l'utilisateur n'a plus qu' cliquer sur le bouton d'upload une fois qu'il aura
vrifi qu'il a bien slectionn les bonnes images.
Notre objectif, ici, est de crer la partie concernant la slection et la prvisualisation des images, l'upload ne nous intresse pas.
Afin d'obtenir le rsultat escompt, nous allons devoir utiliser l'API File, qui va nous permettre de lire le contenu des fichiers
avant mme d'effectuer un quelconque upload.
Commenons par construire la page HTML qui va accueillir notre script :
Code : HTML
<input id="file" type="file" multiple />
<div id="prev"></div>
Il n'y a pas besoin de plus, nous avons notre balise <input> pour slectionner les fichiers (avec l'attribut multiple afin de
permettre la slection de plusieurs fichiers) ainsi qu'une balise <div> pour y afficher les images uploader.
Il nous faut maintenant passer au Javascript. Commenons par mettre en place la structure principale de notre script :
Code : JavaScript
(function() {
var allowedTypes = ['png', 'jpg', 'jpeg', 'gif'],
fileInput = document.querySelector('#file'),
prev = document.querySelector('#prev');
fileInput.onchange = function() {
// Analyse des fichiers et cration des prvisualisations
};
})();
Ce code dclare les variables et les vnements ncessaires. Vous constaterez qu'il existe une variable allowedTypes, celle-ci
contient un tableau listant les extensions d'images dont nous autorisons l'upload. L'analyse des fichiers peut maintenant
commencer. Sachant que nous avons autoris la slection multiple de fichiers, nous allons devoir utiliser une boucle afin de
parcourir les fichiers slectionns. Il nous faudra aussi vrifier quels sont les fichiers autoriser :
Code : JavaScript
339/378
fileInput.onchange = function() {
var files = this.files,
filesLen = files.length,
imgType;
for (var i = 0 ; i < filesLen ; i++) {
imgType = files[i].name.split('.');
imgType = imgType[imgType.length - 1].toLowerCase(); // On
utilise toLowerCase() pour viter les extensions en majuscules
if(allowedTypes.indexOf(imgType) != -1) {
// Le fichier est bien une image supporte, il ne reste
plus qu' l'afficher
}
}
};
Les fichiers sont parcourus puis analyss. Sur les lignes 9 et 10 nous faisons l'extraction de l'extension du fichier en faisant un
dcoupage de la chane de caractres grce un split('.') et nous rcuprons le dernier lment du tableau aprs l'avoir
pass en caractres minuscules. Une fois l'extension obtenue, nous vrifions sa prsence dans le tableau des extensions
autorises (ligne 12).
Il nous faut maintenant afficher l'image, comment allons-nous nous y prendre ? L'affichage d'une image, en HTML, se fait grce
la balise <img>, or celle-ci n'accepte qu'une URL en guise de valeur pour son attribut src. Nous pourrions lui fournir l'adresse
du fichier afficher, mais nous ne connaissons que son nom, pas son chemin. La rponse se trouve dans les DataURL !
Rappelez-vous, nous avions bien prcis que les DataURL permettaient de stocker des donnes dans une URL, cest
exactement ce qu'il nous faut ! Tout d'abord, avant de commencer cet affichage, plaons un appel vers une fonction
createThumbnail() la 14e ligne de notre prcdent code :
Code : JavaScript
if(allowedTypes.indexOf(imgType) != -1) {
createThumbnail(files[i]);
}
340/378
Comme vous pouvez le constater, il n'y a rien de compliqu l-dedans, nous instancions un objet FileReader, lui attribuons
un vnement load, puis lanons la lecture du fichier pour une DataURL. Une fois la lecture termine, l'vnement load se
dclenche si tout s'est termin correctement, il ne nous reste donc plus qu' afficher l'image :
Code : JavaScript
reader.onload = function() {
var imgElement = document.createElement('img');
imgElement.style.maxWidth = '150px';
imgElement.style.maxHeight = '150px';
imgElement.src = this.result;
prev.appendChild(imgElement);
};
Et voil, notre script est termin ! Vous pouvez l'essayer en ligne et voir les codes complets :
Code : HTML
<input id="file" type="file" multiple />
<div id="prev"></div>
Code : JavaScript
(function() {
function createThumbnail(file) {
var reader = new FileReader();
reader.onload = function() {
var imgElement = document.createElement('img');
imgElement.style.maxWidth = '150px';
imgElement.style.maxHeight = '150px';
imgElement.src = this.result;
prev.appendChild(imgElement);
};
reader.readAsDataURL(file);
}
var allowedTypes = ['png', 'jpg', 'jpeg', 'gif'],
fileInput = document.querySelector('#file'),
prev = document.querySelector('#prev');
fileInput.onchange = function() {
var files = this.files,
filesLen = files.length,
imgType;
for (var i = 0 ; i < filesLen ; i++) {
imgType = files[i].name.split('.');
imgType = imgType[imgType.length - 1];
if(allowedTypes.indexOf(imgType) != -1) {
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
341/378
createThumbnail(files[i]);
}
};
})();
cela, ajoutons un code Javascript qui rcupre le fichier spcifi et s'occupe de crer une requte XMLHttpRequest :
Code : JavaScript
var fileInput = document.querySelector('#file');
fileInput.onchange = function() {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://exemple.com'); // Rappelons qu'il est
obligatoire d'utiliser la mthode POST quand on souhaite utiliser
un FormData
xhr.onload = function() {
alert('Upload termin !');
};
// Upload du fichier
};
Maintenant, que fait-on ? C'est trs simple, il nous suffit de passer notre objet File un objet FormData et d'uploader ce
dernier :
Code : JavaScript
var form = new FormData();
form.append('file', fileInput.files[0]);
xhr.send(form);
342/378
Pensez bien uploader un petit fichier (<100 Ko) si vous voulez ne pas avoir un rsultat trop long l'affichage.
Et ? C'est tout ?
Plus ou moins. L'upload de fichiers par le biais d'un objet XHR ne va pas rvolutionner votre faon de coder. Il permet juste de
simplifier les choses puisque l'on n'a plus s'embter passer par le biais d'une <iframe>.
En revanche, il nous reste encore un petit quelque chose en plus tudier et cela va srement vous intresser : afficher la
progression de l'upload ! L'objet XHR est dj nettement plus intressant, non ?
Nous n'avions pas tudi cela plus tt, car vous n'auriez pas t capables de vous en servir de manire utile, mais sachez que
l'objet XHR possde une proprit upload donnant accs plusieurs vnements dont l'vnement progress. Ce dernier
fonctionne exactement de la mme manire que le prcdent vnement progress que nous avions tudi dans le chapitre
consacr l'objet XHR :
Code : JavaScript
xhr.upload.onprogress = function(e) {
e.loaded; // Nombre d'octets uploads
e.total; // Total d'octets uploader
};
Ainsi, il est facile de faire une barre de progression avec cet vnement et la balise HTML5 <progress> :
Code : HTML
<input id="file" type="file" />
<progress id="progress"></progress>
Code : JavaScript
var fileInput = document.querySelector('#file'),
progress = document.querySelector('#progress');
fileInput.onchange = function() {
var xhr = new XMLHttpRequest();
xhr.open('POST', 'http://exemple.com');
xhr.upload.onprogress = function(e) {
progress.value = e.loaded;
progress.max = e.total;
};
xhr.onload = function() {
alert('Upload termin !');
};
var form = new FormData();
form.append('file', fileInput.files[0]);
xhr.send(form);
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
343/378
};
Essayer !
Ici, utilisez plutt un fichier de taille moyenne (~1 Mo) si vous voulez voir un affichage de la progression.
En rsum
L'API File permet de manipuler les fichiers au travers d'un objet File qui hrite lui-mme de l'objet Blob, conu pour
manipuler les donnes binaires.
Il est maintenant possible de lire le contenu d'un fichier sans avoir passer par un quelconque serveur.
Les fichiers peuvent tre utiliss au travers de plusieurs autres technologies telles que l'AJAX ou la balise <canvas>.
344/378
Aperu de l'API
Comme notre habitude, cette prsentation de l'API Drag & Drop ne fait que survoler son fonctionnement, il s'agit
d'une simple initiation. Cependant, soyez srs que vous y dcouvrirez les fonctionnalits les plus importantes, nous
vous vitons ainsi d'tudier certains aspects qui ne vous seront que trs peu utiles.
Vous risquez probablement de rencontrer des problmes avec Firefox. En effet, ce navigateur ncessite une information
supplmentaire que nous vous prsenterons plus loin. Quant aux autres navigateurs, il se peut qu'ils soient nombreux
ne pas russir excuter correctement ce code, tout simplement parce qu'ils ne supportent pas encore le Drag & Drop.
Parmi les huit vnements que l'API Drag & Drop fournit, l'lment dplaable peut en utiliser deux : dragstart et dragend.
L'vnement dragstart se dclenche, comme son nom l'indique, lorsque l'lment cibl commence tre dplac. Cet
vnement est particulirement utile pour initialiser certains dtails utiliss tout au long du processus de dplacement. Pour cela,
il nous faudra utiliser l'objet dataTransfer que nous tudierons plus loin.
Quant l'vnement dragend, celui-ci permet de signaler l'objet dplac que son dplacement est termin, que le rsultat soit
un succs ou non.
345/378
La mthode setData() prend deux arguments en paramtres. Le premier est le type MIME des donnes (sous forme de chane
de caractres) que vous allez spcifier dans le deuxime argument. Prcisons que le deuxime argument est obligatoirement une
chane de caractres, ce qui signifie que le type MIME qui sera spcifi n'a que peu d'intrt, vous utiliserez gnralement le type
text/plain pour des raisons de simplicit :
Code : JavaScript
draggableElement.addEventListener('dragstart', function(e) {
e.dataTransfer.setData('text/plain', "Ce texte sera transmis
l'lment HTML de rception");
}, false);
En temps normal, vous nous diriez probablement que cette mthode est inutile puisqu'il suffirait de stocker les donnes dans une
variable plutt que par le biais de setData(). Eh bien, en travaillant sur la mme page oui, cependant le Drag & Drop en
HTML5 possde la facult de s'tendre bien au-del de votre page Web actuelle et donc de faire un glisser-dposer d'une page
une autre, que ce soit d'un onglet un autre ou bien mme d'un navigateur un autre ! Le transfert de donnes entre les pages
Web n'tant pas possible (tout du moins pas sans tricher ), il est utile d'utiliser la mthode setData().
Attention, l'utilisation de la mthode setData() est obligatoire avec Firefox ! Cela est stupide, car nous n'avons pas
forcment quelque chose y stocker, mais nous n'avons pas trop le choix. Utilisez donc le type MIME de votre choix et
passez-lui une chane de caractres vide, comme ceci : setData('text/plain', '');.
La mthode setDragImage() est extrmement utile pour qui souhaite personnaliser l'affichage de sa page Web ! Elle permet
de dfinir une image qui se placera sous le curseur pendant le dplacement de l'lment concern. La mthode prend trois
arguments en paramtres. Le premier est un lment <img> contenant l'image souhaite, le deuxime est la position horizontale
de l'image et le troisime est la position verticale :
Code : JavaScript
var dragImg = new Image(); // Il est conseill de prcharger l'image,
sinon elle risque de ne pas s'afficher pendant le dplacement
dragImg.src = 'drag_img.png';
document.querySelector('*[draggable="true"]').addEventListener('dragstart',
function(e) {
e.dataTransfer.setDragImage(dragImg, 40, 40); // Une position de 40x40
pixels centrera l'image (de 80x80 pixels) sous le curseur
}, false);
Essayer !
346/378
Par dfaut, le navigateur interdit de dposer un quelconque lment o que ce soit dans la page Web. Notre but est donc
d'annuler cette action par dfaut, et qui dit annulation d'une action par dfaut , dit preventDefault() ! Cette mthode va
devoir tre utilise au travers de l'vnement dragover.
Prenons un exemple simple :
Code : HTML
<div id="draggable" draggable="true">Je peux tre dplac !</div>
<div id="dropper">Je n'accepte pas les lments dplacs !</div>
Essayer !
Comme vous pouvez le constater, cet exemple ne fonctionne pas, le navigateur affiche un curseur montrant une interdiction
lorsque vous survolez le deuxime <div>. Afin d'autoriser cette action, il va vous falloir ajouter un code Javascript trs simple :
Code : JavaScript
document.querySelector('#dropper').addEventListener('dragover',
function(e) {
e.preventDefault(); // Annule l'interdiction de drop
}, false);
Essayer !
Avec ce code, le curseur n'affiche plus d'interdiction en survolant la zone de drop, cependant il ne se passe rien si nous
relchons notre lment sur la zone de drop. Cela est parfaitement normal, car c'est nous de dfinir la manire dont la zone de
drop doit grer les lments qu'elle reoit.
Avant toute chose, pour agir suite un drop d'lment, il nous faut dtecter ce fameux drop, nous allons donc devoir utiliser
l'vnement drop (logique, n'est-ce pas ?
), cela se fait de manire enfantine :
Code : JavaScript
document.querySelector('#dropper').addEventListener('drop',
function(e) {
e.preventDefault(); // Cette mthode est toujours ncessaire
pour viter une ventuelle redirection inattendue
alert('Vous avez bien dpos votre lment !');
}, false);
Essayer !
Tant que nous y sommes, essayons les vnements dragenter, dragleave et un petit oubli qui se nomme dragend :
Code : JavaScript
var dropper = document.querySelector('#dropper');
dropper.addEventListener('dragenter', function() {
dropper.style.borderStyle = 'dashed';
}, false);
dropper.addEventListener('dragleave', function() {
dropper.style.borderStyle = 'solid';
}, false);
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
347/378
// Cet vnement dtecte n'importe quel drag & drop qui se termine,
autant le mettre sur document :
document.addEventListener('dragend', function() {
alert("Un Drag & Drop vient de se terminer mais l'vnement
dragend ne sait pas si c'est un succs ou non.");
}, false);
Avant d'essayer ce code, il nous faut rflchir une chose : nous appliquons un style lorsque l'lment dplac entre dans la
zone de drop puis nous le retirons lorsqu'il en sort. Cependant, que se passe-t-il si nous relchons notre lment dans la zone de
drop ? Eh bien le style reste en place, car l'lment n'a pas dclench l'vnement dragleave. Il nous faut donc retirer le style
en modifiant notre vnement drop :
Code : JavaScript
dropper.addEventListener('drop', function(e) {
e.preventDefault(); // Cette mthode est toujours ncessaire
pour viter une ventuelle redirection inattendue
alert('Vous avez bien dpos votre lment !');
// Il est ncessaire d'ajouter cela car sinon le style appliqu
par l'vnement dragenter restera en place mme aprs un drop :
dropper.style.borderStyle = 'solid';
}, false);
Voil tout, essayez donc maintenant de dplacer l'lment appropri la fois dans la zone de drop et en-dehors de cette dernire :
Essayer !
Quant au deuxime rle, celui-ci consiste rcuprer les ventuels fichiers qui ont t dposs par l'utilisateur, car, oui, le drag &
drop de fichiers est maintenant possible en HTML5 ! Cela fonctionne plus ou moins de la mme manire qu'avec une balise
<input type="file" />, il nous faut toujours accder une proprit files, sauf que celle-ci est accessible dans
l'objet dataTransfer dans le cadre d'un drag & drop. Exemple :
Code : JavaScript
dropZone.addEventListener('drop', function(e) {
e.preventDefault();
var files = e.dataTransfer.files,
filesLen = files.length,
filenames = "";
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
348/378
Mise en pratique
Nous allons faire une petite mise en pratique avant de terminer ce chapitre. Notre but ici est de crer une page Web avec deux
zones de drop et quelques lments que l'on peut dplacer d'une zone l'autre.
Afin de vous viter de perdre du temps pour pas grand-chose, voici le code HTML utiliser et le CSS associ :
Code : HTML
<div class="dropper">
<div class="draggable">#1</div>
<div class="draggable">#2</div>
</div>
<div class="dropper">
<div class="draggable">#3</div>
<div class="draggable">#4</div>
</div>
Code : CSS
.dropper {
margin: 50px 10px 10px 50px;
width: 400px;
height: 250px;
background-color: #555;
border: 1px solid #111;
-moz-border-radius: 10px;
border-radius: 10px;
.drop_hover {
-moz-box-shadow: 0 0 30px rgba(0, 0, 0, 0.8) inset;
box-shadow: 0 0 30px rgba(0, 0, 0, 0.8) inset;
}
.draggable {
display: inline-block;
margin: 20px 10px 10px 20px;
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
349/378
padding-top: 20px;
width: 80px;
height: 60px;
color: #3D110F;
background-color: #822520;
border: 4px solid #3D110F;
text-align: center;
font-size: 2em;
cursor: move;
-moz-transition: all 200ms linear;
-webkit-transition: all 200ms linear;
-o-transition: all 200ms linear;
transition: all 200ms linear;
-moz-user-select: none;
-khtml-user-select: none;
-webkit-user-select: none;
user-select: none;
Rien de bien compliqu, le code HTML est extrmement simple et la seule chose comprendre au niveau du CSS est que la
classe .drop_hover sera applique une zone de drop lorsque celle-ci sera survole par un lment HTML dplaable.
Alors, par o commencer ? Il nous faut, avant toute chose, une structure pour notre code. Nous avons dcid de partir sur un
code bas sur cette forme :
Code : JavaScript
(function() {
var dndHandler = {
// Cet objet est conu pour tre un namespace et va
contenir les mthodes que nous allons crer pour notre systme de
drag & drop
};
// Ici se trouvera le code qui utilisera les mthodes de notre
namespace dndHandler
})();
Pour commencer exploiter notre structure, il nous faut une mthode capable de donner la possibilit aux lments concerns
d'tre dplacs. Les lments concerns sont ceux qui possdent une classe .draggable. Afin de les paramtrer, nous allons
crer une mthode applyDragEvents() dans notre objet dndHandler :
Code : JavaScript
var dndHandler = {
applyDragEvents: function(element) {
element.draggable = true;
}
};
350/378
Ici, notre mthode s'occupe de rendre dplaables tous les objets qui lui seront passs en paramtres. Cependant, cela ne suffit
pas pour deux raisons :
Nos zones de drop devront savoir quel est l'lment qui sera dpos, nous allons utiliser une proprit
draggedElement pour sauvegarder a.
Firefox ncessite l'envoi de donnes avec setData() pour autoriser le dplacement d'lments.
Ainsi, nos zones de drop n'auront qu' lire la proprit draggedElement pour savoir quel est l'lment qui a t dpos.
Passons maintenant la cration de la mthode applyDropEvents() qui, comme son nom l'indique, va se charger de grer
les vnements des deux zones de drop. Nous allons commencer par grer les deux vnements les plus simples : dragover et
dragleave.
Code : JavaScript
var dndHandler = {
// []
applyDropEvents: function(dropper) {
dropper.addEventListener('dragover', function(e) {
e.preventDefault(); // On autorise le drop d'lments
this.className = 'dropper drop_hover'; // Et on applique
le style adquat notre zone de drop quand un lment la survole
}, false);
dropper.addEventListener('dragleave', function() {
this.className = 'dropper'; // On revient au style de
base lorsque l'lment quitte la zone de drop
});
}
};
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
351/378
Notre but maintenant est de grer le drop d'lments. Notre systme doit fonctionner de la manire suivante :
Un lment est dropp ;
Notre vnement drop va alors rcuprer l'lment concern grce la proprit draggedElement ;
L'lment dplac est clon ;
Le clone est alors ajout la zone de drop concerne ;
L'lment d'origine est supprim ;
Et pour terminer, le clone se voit rattribuer les vnements qu'il aura perdus du fait que la mthode cloneNode() ne
conserve pas les vnements.
En soi, ce systme n'est pas bien compliqu raliser, voici ce que nous vous proposons comme solution :
Code : JavaScript
dropper.addEventListener('drop', function(e) {
var target = e.target,
draggedElement = dndHandler.draggedElement, // Rcupration
de l'lment concern
clonedElement = draggedElement.cloneNode(true); // On cr
immdiatement le clone de cet lment
target.className = 'dropper'; // Application du style par dfaut
clonedElement = target.appendChild(clonedElement); // Ajout de
l'lment clon la zone de drop actuelle
dndHandler.applyDragEvents(clonedElement); // Nouvelle
application des vnements qui ont t perdus lors du cloneNode()
draggedElement.parentNode.removeChild(draggedElement); //
Suppression de l'lment d'origine
});
Nos deux mthodes sont maintenant termines, il ne nous reste plus qu' les appliquer aux lments concerns :
Code : JavaScript
(function() {
var dndHandler = {
// []
};
var elements = document.querySelectorAll('.draggable'),
elementsLen = elements.length;
for(var i = 0 ; i < elementsLen ; i++) {
dndHandler.applyDragEvents(elements[i]); // Application des
paramtres ncessaires aux lments dplaables
}
var droppers = document.querySelectorAll('.dropper'),
droppersLen = droppers.length;
for(var i = 0 ; i < droppersLen ; i++) {
dndHandler.applyDropEvents(droppers[i]); // Application des
vnements ncessaires aux zones de drop
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
352/378
}
})();
Cela s'explique par le simple fait que l'vnement drop est hrit par les lments enfants, ce qui signifie que les lments
possdant la classe .draggable se comportent alors comme des zones de drop !
Une solution serait d'appliquer un vnement drop aux lments dplaables refusant tout lment HTML dpos, mais cela
obligerait alors l'utilisateur dposer son lment en faisant bien attention ne pas se retrouver au-dessus d'un lment
dplaable. Essayez donc pour voir, vous allez rapidement constater que cela peut tre vraiment pnible :
Code : JavaScript
applyDragEvents: function(element) {
// []
element.addEventListener('drop', function(e) {
e.stopPropagation(); // On stoppe la propagation de
l'vnement pour empcher la zone de drop d'agir
}, false);
},
Nous n'avions pas encore tudi la mthode stopPropagation(), car celle-ci ncessite un cas concret
d'utilisation, et nous en avons justement un ici !
Cette mthode sert stopper la propagation des vnements. Souvenez-vous des phases de capture et de
bouillonnement tudies dans le chapitre sur les vnements ! Dans une phase de bouillonnement, si un lment enfant
possde un vnement du mme type qu'un de ses lments parents, alors son vnement se dclenchera en premier,
puis viendra celui de l'lment parent. La mthode stopPropagation() sert brider ce fonctionnement.
Dans le cadre d'une phase de bouillonnement, en utilisant cette mthode dans l'vnement de l'lment enfant, vous
empcherez alors l'lment parent d'excuter son vnement. Dans le cadre d'une phase de capture, en utilisant cette
mthode sur l'lment parent, vous empcherez alors l'lment enfant de dclencher son vnement.
La solution la plus pratique pour l'utilisateur serait donc de faire en sorte de remonter les lments parents (avec
parentNode) jusqu' tomber sur une zone de drop. Cela est trs simple et se fait en trois lignes de code (lignes 7 9) :
Code : JavaScript
353/378
dropper.addEventListener('drop', function(e) {
var target = e.target,
draggedElement = dndHandler.draggedElement, // Rcupration
de l'lment concern
clonedElement = draggedElement.cloneNode(true); // On cre
immdiatement le clone de cet lment
while(target.className.indexOf('dropper') == -1) { // Cette boucle
permet de remonter jusqu' la zone de drop parente
target = target.parentNode;
}
target.className = 'dropper'; // Application du style par dfaut
clonedElement = target.appendChild(clonedElement); // Ajout de
l'lment clon la zone de drop actuelle
dndHandler.applyDragEvents(clonedElement); // Nouvelle
application des vnements qui ont t perdus lors du cloneNode()
draggedElement.parentNode.removeChild(draggedElement); //
Suppression de l'lment d'origine
});
d'lments
dropper.addEventListener('dragover', function(e) {
e.preventDefault(); // On autorise le drop
this.className = 'dropper drop_hover'; // Et on
354/378
clonedElement = target.appendChild(clonedElement);
// Ajout de l'lment clon la zone de drop actuelle
dndHandler.applyDragEvents(clonedElement); //
Nouvelle application des vnements qui ont t perdus lors du
cloneNode()
draggedElement.parentNode.removeChild(draggedElement); //
Suppression de l'lment d'origine
});
}
};
var elements = document.querySelectorAll('.draggable'),
elementsLen = elements.length;
for(var i = 0 ; i < elementsLen ; i++) {
dndHandler.applyDragEvents(elements[i]); // Application des
paramtres ncessaires aux lments dplaables
}
var droppers = document.querySelectorAll('.dropper'),
droppersLen = droppers.length;
for(var i = 0 ; i < droppersLen ; i++) {
dndHandler.applyDropEvents(droppers[i]); // Application des
vnements ncessaires aux zones de drop
}
})();
En rsum
Le Drag & Drop est une technologie conue pour permettre un dplacement natif d'lments en tous genres (texte,
fichiers, etc.).
Une action de drag & drop ncessite gnralement un transfert de donnes entre l'lment metteur et l'lment rcepteur,
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
355/378
Partie 6 : Annexe
356/378
Partie 6 : Annexe
Cette partie est ce que nous considrons comme tant une partie facultative, vous y trouverez divers chapitres qui pourront
vous tre utiles au cours de la lecture du cours, libre vous de les lire ou non. Sachez juste que cette partie peut tre une mine
d'or pour certains d'entre vous qui souhaitez pousser vos connaissances en Javascript au maximum.
Vous voyez la diffrence ? Du point de vue de l'interprteur Javascript, le premier code est faux, car il est incapable de l'excuter,
tandis que le deuxime code est excutable, mais on n'obtient pas la valeur escompte.
Il faut bien se mettre en tte que l'interprteur Javascript se fiche bien des valeurs retournes par votre code, il veut excuter le
code et c'est tout. Voici la diffrence entre le caractre syntaxique et algorithmique d'une erreur : la premire empche le code de
s'excuter, la seconde empche le bon droulement du script. Pourtant, les deux empchent votre code de s'excuter
correctement.
Le dbogage
Comme son nom l'indique, cette technique consiste supprimer les bugs qui existent dans votre code. Pour chaque type de bug
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
Partie 6 : Annexe
357/378
Mozilla Firefox
Allez dans le menu Outils puis cliquez sur Console d'erreurs et voici ce que vous obtenez :
On lit ici qu'une erreur superFunction is not defined est apparue la ligne 11, dans le fichier C:\Sebastien\fake.htm.
L'erreur dcrite signifie que l'on a voulu excuter la fonction superFunction() alors qu'elle n'existe pas.
Internet Explorer
Si une erreur survient, Internet Explorer (versions antrieures la verion 9) le signale gauche de la barre d'tat, via ce symbole :
Internet Explorer signale une Erreur Javascript . Il vous suffit de double-cliquer dessus pour afficher le dtail des
erreurs survenues :
Partie 6 : Annexe
358/378
La
Opera
Dans le menu, cliquez sur Page, sur Outils de dveloppeur et enfin sur Console d'erreur :
Partie 6 : Annexe
359/378
Ici le descriptif est assez prcis et la portion de code incrimine est affiche.
Google Chrome
Cliquez sur l'icne
L'icne Outils pour aller dans le menu Outils, puis cliquez sur Console JavaScript.
Cliquez aussi sur l'onglet Console pour n'afficher que la console Javascript.
Safari
Dans Safari, il faut dans un premier temps activer le menu Dveloppement. Pour ce faire, cliquez sur
Il faut dans un
premier temps activer le menu Dveloppement puis sur Prfrences. Dans l'onglet Avances, cochez la case
Afficher le menu Dveloppement dans la barre des menus. Quand c'est fait, pour ouvrir la console,
cliquez sur
Ce menu permet d'ouvrir la console des erreurs puis sur Dveloppement, et enfin sur
Afficher la console des erreurs :
Partie 6 : Annexe
360/378
Partie 6 : Annexe
361/378
Une boucle infinie ne prendra jamais fin et donc se rptera inlassablement. Ceci est un bug, et non pas une fonctionnalit
comme dans d'autres langages tels que le C. Prenez donc garde ne pas mettre une condition qui renvoie toujours une valeur
quivalente true, comme dans cet exemple :
Code : JavaScript
var nb1 = 4, nb2 = 5;
while (nb1 < nb2) {
// Etc.
}
Dans le cas o vous auriez cr une boucle infinie sans le vouloir, le navigateur n'excutera probablement pas votre code et
retournera une erreur.
Or, nombreuses sont les personnes qui crivent ceci lors du passage en rfrence :
Code : JavaScript
var function2 = function1();
Ce code est faux, car vous ne passez pas function2 la rfrence vers function1(), vous lui passez le retour de cette
dernire puisque vous l'excutez.
Partie 6 : Annexe
362/378
Concernant Internet Explorer, il existe un kit de dveloppement uniquement depuis la version 8, pas avant. Pour l'afficher
appuyez sur la touche F12 de votre clavier ; ce raccourci clavier est aussi valable pour Firefox et Chrome.
Concrtement, quoi peuvent rellement vous servir ces kits ? Il existe deux utilisations principales :
Afficher le code HTML dynamique, afin de voir comment votre code Javascript a modifi le DOM et surtout s'il a t
modifi correctement !
Mettre des points d'arrt dans votre code Javascript pour vrifier l'tat de votre code un moment donn.
Nous allons dcrire ces deux utilisations, mais uniquement sous Firebug tant donn que c'est le plus utilis et surtout
qu'il possde une version lite compatible sur un grand nombre de navigateurs. Si vous utilisez le kit d'un autre
navigateur, ne vous inquitez pas, le fonctionnement devrait tre sensiblement le mme, il suffira juste de chercher un
peu.
page (raccourci clavier : Ctrl + Maj + C) et dplacez votre curseur sur la page Web. Chaque lment survol sera encadr de bleu
; si vous cliquez sur l'un d'eux, vous verrez alors le code le concernant s'afficher comme ceci :
faire une pause sur une ligne d'un code Javascript et afficher l'tat complet des variables, mthodes, objets, etc. La quantit
d'informations disponible est tout simplement immense, vous pouvez les retrouver dans le cadre de droite de Firebug ds qu'un
point d'arrt est atteint :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
Partie 6 : Annexe
363/378
Voyons la structure de ce panneau de dbogage : gauche vous avez le code Javascript avec un bouton
Cette icne
permet de voir de quel fichier provient le Javascript qui spcifie le fichier contenant du Javascript qui est en cours de
visualisation, droite vous retrouvez toutes les informations obtenues ds qu'un point d'arrt est atteint.
Pour ajouter un nouveau point d'arrt, il vous suffit de cliquer gauche du numro de la ligne de code laquelle vous souhaitez
attribuer un point d'arrt, vous verrez alors un point rouge s'afficher comme ceci :
Un icne indique le point d'arrt
Notez bien que lorsque vous attribuez un point d'arrt une ligne de code, ce point d'arrt mettra le code en pause
avant l'excution de la ligne en question.
Aprs avoir mis vos points d'arrt, il ne vous reste plus qu' recharger la page avec F5 et votre code sera mis en pause chaque
point d'arrt rencontr. Firebug listera alors, dans le cadre de droite, l'tat de toutes les proprits de votre script. Pour passer au
point d'arrt suivant, vous n'aurez qu' cliquer sur continuer
Cette icne permet de reprendre l'excution du script aprs un
point d'arrt jusqu' ce que le code se termine.
Partie 6 : Annexe
364/378
En rsum
On distingue deux types de bugs : les bugs syntaxiques et les bugs algorithmiques. Le premier type peut tre facilement
rsolu grce la console d'erreurs de votre navigateur, le deuxime vous demandera en revanche bien plus de rflexion.
Quasiment tous les navigateurs (quelle que soit leur version) possdent une console d'erreurs capable de dtecter les
bugs syntaxiques de vos codes.
Les navigateurs les plus rcents vous offriront la possibilit d'utiliser un kit de dveloppement Web permettant une
analyse pousse de vos codes Javascript, mais aussi de tout ce qui est li votre page Web tel que le code HTML, le
CSS ou encore le trafic rseau.
Partie 6 : Annexe
365/378
Les closures
Au cours de la lecture de ce tutoriel, vous avez trs probablement d constater que les fonctions anonymes taient trs
frquemment utilises pour diverses choses, comme les vnements, les isolements de code, etc. Leurs utilisations sont
nombreuses et varies, car elles sont trs facilement adaptables toutes les situations. Et s'il y a bien un domaine o les
fonctions anonymes excellent, c'est bien les closures !
alert(myVar);
Mme sans l'excuter, vous vous doutez srement du rsultat que nous allons obtenir : une erreur. Ceci est normal, car myVar
est dclare dans une fonction tandis que nous essayons d'y accder depuis l'espace global (en cas d'oubli, nous vous invitons
relire cette sous-partie).
La seule fonction capable d'accder myVar est area(), car c'est elle qui l'a cre. Seulement, une fois l'excution de la
fonction termine, la variable est supprime et devient donc inaccessible.
Maintenant, si nous faisons ceci :
Code : JavaScript
function area() {
var myVar = 1;
function show() {
alert(myVar);
}
}
area();
alert(myVar);
Le rsultat est toujours le mme, il est nul. Cependant, en plus de la fonction area(), la fonction show() est maintenant
capable, elle aussi, d'accder myVar car elle a t cre dans le mme espace que celui de myVar. Mais pour cela il faudrait
l'excuter.
Plutt que de l'excuter immdiatement, nous allons l'excuter une seconde aprs l'excution de notre fonction area(), ce qui
devrait normalement retourner une erreur puisque myVar est cense tre dtruite une fois qu'area() a termin son excution.
Code : JavaScript
function area() {
Partie 6 : Annexe
366/378
var myVar = 1;
function show() {
alert(myVar);
}
setTimeout(show, 1000);
}
area();
Essayer !
Et, par miracle, cela fonctionne ! Vous n'tes probablement pas surpris, cela fait dj plusieurs fois que vous savez qu'il est
possible d'accder une variable mme aprs la disparition de l'espace dans lequel elle a t cre (ici, la fonction area()).
Cependant, savez-vous pourquoi ?
Tout ce qui suit est trs thorique et ne reflte pas forcment la vritable manire dont les variables sont gres.
Cependant, le principe expliqu vous clairera tout de mme sur ce concept avanc.
Vous souvenez-vous de la formulation passer une variable par rfrence ? Cela signifie que vous permettez que la variable
soit accessible par un autre nom que celui d'origine. Ainsi, si vous avez une variable var1 et que vous la passez en rfrence
var2, alors var1 et var2 pointeront sur la mme variable. Donc, en modifiant var1, cela affectera var2, et vice versa.
Tout cela nous amne la constatation suivante : une variable peut possder plusieurs rfrences. Dans notre fonction
area(), nous avons une premire rfrence vers notre variable, car elle y est dclare sous le nom myVar. Dans la fonction
show(), nous avons une deuxime rfrence du mme nom, myVar.
Quand une fonction termine son excution, la rfrence vers la variable est dtruite, rendant son accs impossible. Cest ce qui
se produit avec notre fonction area(). La variable en elle-mme continue exister tant qu'il reste encore une rfrence qui est
susceptible d'tre utilise. C'est aussi ce qui se produit avec la fonction show(). Puisque celle-ci possde une rfrence vers
notre variable, cette dernire n'est pas dtruite.
Ainsi, une variable peut trs bien perdre dix de ses rfrences, elle ne sera pas supprime tant qu'il lui en restera au moins une.
C'est ce qui explique que nous puissions accder la variable myVar dans la fonction show() malgr la fin de l'excution de
area().
Comprendre le problme
Les closures n'existent pas simplement pour dcorer, il existe des raisons bien particulires pour lesquelles elles ont t conues.
Les problmes qu'elles sont supposes rsoudre ne sont pas simples comprendre, nous allons tcher de vous expliquer cela au
mieux.
Premier exemple
Commenons par un exemple simple qui vous donnera un aperu de l'ampleur du problme :
Code : JavaScript
var number = 1;
setTimeout(function() {
alert(number);
}, 100);
number++;
Essayer !
Partie 6 : Annexe
367/378
Si vous avez essay le code, alors vous avez srement remarqu le problme : la fonction alert() ne nous affiche pas la
valeur 1 comme nous pourrions le penser, mais la valeur 2. Nous avons pourtant fait appel setTimeout() avant le
changement de valeur, alors comment se fait-il qu'il y ait ce problme ?
Eh bien, cela vient du fait que ce n'est que la fonction setTimeout() qui a t excute avant le changement de valeur. La
fonction anonyme, elle, n'est excute que 100 millisecondes aprs l'excution de setTimeout(), ce qui a largement laiss le
temps la valeur de number de changer.
Si cela vous semble trange, cest probablement parce que vous partez du principe que, lorsque nous dclarons notre fonction
anonyme, celle-ci va directement rcuprer les valeurs des variables utilises. Que nenni ! Lorsque vous dclarez votre fonction
en crivant le nom d'une variable, vous passez une rfrence vers cette variable votre fonction. Cette rfrence sera ensuite
utilise pour connatre la valeur de la variable, mais seulement une fois la fonction excute !
Maintenant que le problme est probablement plus clair dans votre tte, passons un exemple plus concret !
Un cas concret
Admettons que vous souhaitiez faire apparatre une dizaine de balises <div> de manire progressive, les unes la suite des
autres. Voici le code que vous tenteriez probablement de faire dans l'tat actuel de vos connaissances :
Code : JavaScript
var divs = document.getElementsByTagName('div'),
divsLen = divs.length;
for (var i = 0 ; i < divsLen ; i++) {
setTimeout(function() {
divs[i].style.display = 'block';
}, 200 * i); // Le temps augmentera de 200 ms chaque lment
}
Essayer !
Alors ? Le rsultat n'est pas trs concluant, n'est-ce pas ? Si vous jetez un coup dil la console d'erreurs, vous constaterez
qu'elle vous signale que la variable divs[i] est indfinie, et ce dix fois de suite, ce qui correspond nos dix itrations de
boucle. Si nous regardons d'un peu plus prs le problme, nous constatons alors que la variable i vaut toujours 10 chaque fois
qu'elle est utilise dans les fonctions anonymes, ce qui correspond sa valeur finale une fois que la boucle a termin son
excution.
Ceci nous ramne au mme problme : notre fonction anonyme ne prend en compte que la valeur finale de notre variable.
Heureusement, il existe les closures, qui peuvent contourner ce dsagrment !
Partie 6 : Annexe
368/378
Actuellement, le problme se situe dans le fait que la variable i change de valeur avant mme que nous n'ayons eu le temps
d'agir. Le seul moyen serait donc d'enregistrer cette valeur quelque part. Essayons :
Code : JavaScript
var divs = document.getElementsByTagName('div'),
divsLen = divs.length;
for (var i = 0 ; i < divsLen ; i++) {
var currentI = i; // Dclarer une variable DANS une boucle n'est
pas conseill, ici c'est juste pour l'exemple
setTimeout(function() {
divs[currentI].style.display = 'block';
}, 200 * i);
}
Ligne 10, nous utilisons la variable i, car la fonction setTimeout() s'excute immdiatement, la variable i n'a donc
pas le temps de changer de valeur.
Malheureusement, cela ne fonctionne pas, car nous en revenons toujours au mme : la variable currentI est rcrite chaque
tour de boucle, car le Javascript ne cre pas d'espace fonctionnel spcifique pour une boucle. Toute variable dclare au sein
d'une boucle est dclare dans l'espace fonctionnel parent la boucle. Cela nous empche donc de converser avec la valeur
crite dans notre variable, car la variable est rcrite chaque itration de la boucle.
Cependant, il est possible de contourner cette rcriture.
Actuellement, notre variable currentI est dclare dans l'espace global de notre code. Que se passerait-il si nous la
dclarions l'intrieur d'une IEF ? Eh bien, la variable serait dclare dans l'espace de la fonction, rendant impossible sa
rcriture depuis l'extrieur.
Oui, mais si l'accs cette variable est impossible depuis l'extrieur, comment peut-on alors l'utiliser pour notre
setTimeout() ?
La rponse est simple : en utilisant le setTimeout() dans la fonction contenant la variable ! Essayons :
Code : JavaScript
var divs = document.getElementsByTagName('div'),
divsLen = divs.length;
for (var i = 0 ; i < divsLen ; i++) {
(function() {
var currentI = i;
setTimeout(function() {
divs[currentI].style.display = 'block';
}, 200 * i);
})();
}
Partie 6 : Annexe
369/378
Essayer !
Pratique, non ? Le fonctionnement peut paratre un peu absurde la premire fois que l'on dcouvre ce concept, mais au final il est
parfaitement logique.
tudions le principe actuel de notre code : chaque tour de boucle, une IEF est cre. l'intrieur de cette dernire, une variable
currentI est dclare, puis nous lanons l'excution diffre d'une fonction anonyme faisant appel cette mme variable.
Cette dernire fonction va utiliser la premire (et la seule) variable currentI qu'elle connat, celle dclare dans notre IEF, car
elle n'a pas accs aux autres variables currentI dclares dans d'autres IEF.
Vous n'avez toujours pas oubli la premire sous-partie de ce chapitre, n'est-ce pas ? Car, si nous avons trait le sujet des
variables, c'est pour vous viter une mauvaise comprhension ce stade du chapitre. Ici nous avons un cas parfait de ce que
nous avons tudi : currentI est dclare dans une IEF, sa rfrence est donc dtruite la fin de l'excution de l'IEF.
Cependant, nous y avons toujours accs dans notre fonction anonyme excute en diffr, car nous possdons une rfrence
vers cette variable, ce qui vite sa suppression.
Dernire chose, vous risquerez de tomber assez frquemment sur des closures plutt crites de cette manire :
Code : JavaScript
var divs = document.getElementsByTagName('div'),
divsLen = divs.length;
for (var i = 0 ; i < divsLen ; i++) {
(function(currentI) {
setTimeout(function() {
divs[currentI].style.display = 'block';
}, 200 * i);
})(i);
}
Concrtement, qu'est-ce que l'on a fait ? Eh bien, nous avons tout simplement cr un argument currentI pour notre IEF et
nous lui passons en paramtre la valeur de i. Cette modification fait gagner un peu d'espace (suppression de la ligne 8) et permet
de mieux organiser le code, on distingue plus facilement ce qui constitue la closure ou non.
Tant que nous y sommes, nous pouvons nous permettre d'apporter une modification de plus la ligne 6 :
Code : JavaScript
var divs = document.getElementsByTagName('div'),
divsLen = divs.length;
for (var i = 0 ; i < divsLen ; i++) {
(function(i) {
setTimeout(function() {
divs[i].style.display = 'block';
}, 200 * i);
})(i);
}
Partie 6 : Annexe
370/378
Ainsi, mme dans la closure, nous utilisons une variable nomme i. Cela est bien plus pratique grer et prte moins
confusion pour peu que l'on ait compris que dans la closure nous utilisons une variable i diffrente de celle situe en-dehors de
la closure.
Voil, vous savez maintenant vous servir des closures dans leur cadre gnral. Bien qu'elles existent sous plusieurs formes et
pour plusieurs cas d'utilisation, nous avons ici tudi le cas principal.
Ces variables particulires sont dclares la premire excution de la fonction, mais ne sont pas supprimes la fin des
excutions. Elles sont conserves pour les prochaines utilisations de la fonction.
Ainsi, dans ce code en C, la variable myStatic est dclare et initialise 0 lors de la premire excution de myFunction().
La prochaine excution de la fonction ne dclarera pas de nouveau cette variable, mais la rutilisera avec la dernire valeur qui lui
a t affecte.
En gros, c'est comme si vous dclariez une variable globale en Javascript et que vous l'utilisiez dans votre fonction : la variable et
sa valeur ne seront jamais dtruites. En revanche, la variable globale est accessible par toutes les fonctions, tandis qu'une
variable statique n'est accessible que pour la fonction qui a fait sa dclaration.
En Javascript, nous pouvons faire ceci :
Code : JavaScript
var myVar = 0;
function display(value) {
if(typeof value != 'undefined') {
myVar = value;
}
alert(myVar);
}
display();
// Affiche : 0
display(42); // Affiche : 42
display();
// Affiche : 42
Alors que nous voudrions arriver ceci afin d'viter l'accs myVar par une fonction autre que display() :
Code : JavaScript
function display(value) {
static var myVar = 0;
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
Partie 6 : Annexe
371/378
Je viens de voir que le mot-cl static existe en Javascript, pourquoi ne pas l'utiliser ?
Ah oui ! Il s'agit d'une petite incohrence (de plus) en Javascript. Il faut savoir que ce langage a rserv de nombreux mots-cls
alors qu'ils lui sont inutiles. Le mot-cl static en fait partie. Autrement dit, il est rserv, mais ne sert rien et n'a donc aucune
influence sur votre code (mis part le fait de gnrer une erreur).
La solution se trouve donc avec les closures. En respectant le schma classique d'une closure, une IEF avec une fonction
anonyme l'intrieur, nous pouvons dclarer une variable dans l'IEF et ainsi elle ne sera utilisable que par la fonction anonyme et
ne sera jamais supprime :
Code : JavaScript
(function() {
var myVar = 0;
function() {
// Du code
}
})();
Cependant, comment accder notre fonction anonyme ? La solution est simple : en la retournant avec le mot-cl return et en
passant sa rfrence une variable :
Code : JavaScript
var myFunction = (function() {
var myVar = 0;
return function() {
// Du code
};
})();
Si nous reprenons notre exemple, mais adapt de manire ce qu'il possde une variable statique, alors nous obtenons ceci :
Code : JavaScript
var display = (function() {
var myVar = 0; // Dclaration de la variable pseudo-statique
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
Partie 6 : Annexe
372/378
return function(value) {
if(typeof value != 'undefined') {
myVar = value;
}
alert(myVar);
};
})();
display();
// Affiche : 0
display(42); // Affiche : 42
display();
// Affiche : 42
Essayer !
Et voil une fonction avec une variable statique nomme myVar ! Cela pourra vous tre utile par moments (bien que cela soit
assez rare).
En rsum
Une variable peut possder plusieurs rfrences. Elle ne sera jamais supprime tant qu'elle possdera encore une
rfrence active.
Les closures ont t inventes dans le but de rpondre plusieurs problmatiques concernant la gestion de donnes.
Une closure peut tre crite de plusieurs manires diffrentes, vous de choisir celle qui convient le mieux votre code.
Partie 6 : Annexe
373/378
Rcapitulatif express
Ce qu'il vous reste faire
Avant de nous plonger dans de nouvelles possibilits offertes par le Javascript, ce serait bien de situer votre propre niveau, car
vous n'tes pas encore des pros, il vous manque l'exprience ! Si nous avions voulu couvrir toutes les particularits du
Javascript, il aurait srement fallu un cours au moins deux fois plus long, ce qui n'est pas vraiment envisageable. Ces
particularits, vous les dcouvrirez donc en programmant !
Il est important pour vous de programmer, de trouver quelques ides pour des projets un peu fous, il vous faut coder et
rencontrer des problmes pour pouvoir progresser ! Vous serez ainsi capables de rsoudre par vous-mmes vos propres codes,
vous commencerez viter certaines erreurs autrefois habituelles, vous rflchirez de manire diffrente et plus optimise. Ce
sont toutes ces petites choses qui feront de vous un programmeur hors pair en Javascript. Dans ce cours, nous n'avons fait que
vous donner les outils pour que vous puissiez vous prendre en main, il ne tient qu' vous de les utiliser bon escient !
Puisque tout n'a pas t abord dans ce cours, sachez maintenant que vous aurez dornavant besoin de documentations afin de
trouver votre bonheur. Nous avons tch de vous fournir, quand l'occasion se prsentait, des liens vers la documentation du
MDN afin que vous commenciez ds le dbut apprendre bien vous en servir. partir de maintenant, les documentations
vous seront probablement indispensables, tchez de bien vous en servir, elles sont prcieusement utiles !
Le Javascript intrusif
N'oubliez jamais ce que nous avons essay de vous inculquer au travers de ce cours : ne faites pas de Javascript intrusif ! Partez
du principe qu'une page Web doit pouvoir fonctionner sans vos codes Javascript ! Il y a quelques annes, ce principe tait de
rigueur, car certains navigateurs ne savaient pas encore lire le Javascript, leurs utilisateurs taient donc bloqus sur certaines
pages. De nos jours, tous les navigateurs supportent le Javascript, mais il est quand mme important de garder ce principe de
base afin d'viter des problmes de ce genre :
Code : HTML
<a href="#" onclick="if(confirm('tes-vous sr ?')) { location =
'http://sitelambda.com'; }">Lien</a>
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
Partie 6 : Annexe
374/378
Dans cet exemple, nous prfrons demander confirmation avant que l'utilisateur ne soit redirig. Tout naturellement, nous crons
donc une condition faisant appel la fonction confirm(). Dans le cas o l'utilisateur est d'accord, nous faisons la redirection
avec l'objet location (vous ne savez pas quel est cet objet ? Allez hop ! documentation, commencez ds maintenant vous
en servir par vous-mmes !). Mais cette redirection est gnante et ne devrait pas exister !
Et pourquoi a ? Qu'est-ce qu'elle a de problmatique ?
Connaissez-vous le raccourci Ctrl + clic gauche ? Il permet d'ouvrir le lien cliqu dans un nouvel onglet, ce qui n'est pas possible
avec le code que nous venons de voir, car c'est le Javascript qui dfinit comment ouvrir la page. Voil le problme d'un code
Javascript intrusif ! Si vous tiez partis du principe que votre page Web devait fonctionner sans vos codes Javascript, alors
vous n'auriez pas eu ce problme, car vous auriez probablement cod quelque chose de ce genre :
Code : HTML
<a href="http://sitelambda.com" onclick="return confirm('tes-vous
sr ?');">Lien</a>
Ici, le Javascript peut tre dsactiv sans empcher le fonctionnement de la page Web. De plus, il ne perturbe pas les
fonctionnalits natives du navigateur comme le Ctrl + clic gauche.
Bien entendu, il existe certains codes qui ne peuvent pas se passer du Javascript pour fonctionner (un jeu par exemple), il y aura
donc certains cas o vous serez obligs de faire du Javascript intrusif. Essayez juste de faire le maximum pour viter cela.
tendre le Javascript
Ce cours n'a abord, jusqu' prsent, que le Javascript dit pur . Pur dans le sens o vous aviez besoin de tout dvelopper par
vous-mmes, ce qui peut rapidement se rvler fastidieux. Un bon exemple de ce qui est ncessaire de dvelopper rgulirement :
les animations ! Aussi incroyable que cela puisse paratre, le Javascript ne fournit aucune fonction capable de nous aider dans
nos animations, il nous faut donc les dvelopper par nous-mmes.
Heureusement, le Javascript est un langage extrmement utilis et sa communaut est immense, il est donc trs facile de trouver
des scripts adapts vos besoins. Parmi ces scripts, nous trouvons deux types : les frameworks et les bibliothques.
Les frameworks
Le terme framework est abusivement utilis en Javascript. Ce que nous allons vous prsenter ne sont pas des
frameworks au sens propre du terme, mais il est courant de les nommer de cette manire.
Un framework a pour but de fournir une surcouche au Javascript afin de simplifier l'utilisation des domaines les plus utiliss
de ce langage tout en facilitant la compatibilit de vos codes entre les navigateurs Web. Par exemple, quelques frameworks
disposent d'une fonction $() s'utilisant de la mme manire que la mthode querySelector(), et ce, sur tous les
navigateurs Web, facilitant ainsi la slection d'lments HTML. Pour faire simple, un framework est une grosse bote outils
contenant une multitude de fonctions permettant de subvenir aux besoins des dveloppeurs !
L'atout numro un d'un framework est sa capacit s'adapter toutes les utilisations du Javascript et fournir un systme
performant de plugins afin qu'il puisse tre tendu des utilisations non envisages par son systme de base. Grce ces deux
points, un framework permet de simplifier et d'acclrer considrablement le dveloppement d'applications Web.
Il existe de nombreux frameworks en Javascript en raison de la pauvret de ce langage en terme de fonctions natives, cependant
nous n'allons prsenter que les plus connus d'entre eux :
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
Partie 6 : Annexe
375/378
jQuery : il s'agit du framework Javascript le plus connu. Rput pour sa simplicit d'utilisation et sa communaut
gigantesque, il est clairement incontournable et a l'avantage de ne peser que 30 Ko environ ! Cependant, il n'est pas
toujours apprci en raison de sa volont de s'carter de la syntaxe de base du Javascript grce au chanage de
fonctions, que vous pouvez constater dans l'exemple qui suit :
$("p.neat").addClass("ohmy").show("slow");.
MooTools : un framework puissant et presque tout aussi connu que jQuery, bien que nettement moins utilis. Il est rput
pour sa modularit et son approche diffrente plus proche de la syntaxe de base du Javascript. En revanche, bien que ce
framework soit segmentable (vous ne tlchargez que ce dont vous avez besoin), il reste nettement plus lourd que
jQuery.
Dojo : connu pour sa capacit permettre la conception d'interfaces Web extrmement compltes, il possde des atouts
indniables face aux plus grands frameworks et tout particulirement jQuery UI, une extension de jQuery conue pour
faire des interfaces Web. Ce framework est l'un des plus modulaires que l'on puisse trouver sur Internet, ce qui fera la joie
des fans d'optimisation.
YUI : il est souvent oubli par les dveloppeurs Web, mais l'entreprise Yahoo! n'a pourtant pas dit son dernier mot avec
des projets ambitieux parmi lesquels compte YUI. Ce framework est pour le moins complet, ne vous fiez pas aux fausses
ides que vous pouvez avoir de Yahoo!, vous pourriez avoir bien des surprises en utilisant ce framework qui est
modulable et relativement performant, bien qu'il bnficie d'une communaut assez restreinte.
Prototype : l'un des pionniers des frameworks Javascript ! Nous le citons seulement en tant qu'exemple, car, malgr ses
qualits, il se fait vieux et la dernire mise jour officielle date du 16 novembre 2010, autant dire qu'il est mort. Son dclin
s'explique par le simple fait qu'il tendait les objets natifs lis au DOM, rendant le tout assez lent et peu compatible. Bref,
vous ne vous en servirez jamais, mais au moins vous saurez de quoi veulent parler certaines personnes en parlant de
Prototype avec un P majuscule.
Les bibliothques
Contrairement aux frameworks, les bibliothques (libraries en anglais) ont un but bien plus spcialis.
Quel est l'intrt si un framework me fournit dj tout ce dont j'ai besoin ?
L'intrt se situe la fois sur le poids du fichier Javascript utiliser (une bibliothque sera gnralement plus lgre qu'un
framework) et sur la spcialisation des bibliothques. Ces dernires ont souvent tendance aller plus loin que les frameworks, vu
qu'elles n'agissent que sur un domaine bien prcis, ce qui simplifie d'autant plus votre dveloppement dans le domaine concern
par la bibliothque.
Et puis il existe un principe important dans le dveloppement (Web ou logiciel) : l'optimisation. Utiliser un framework uniquement
pour faire une malheureuse animation n'est vraiment pas conseill, c'est un peu comme si vous cherchiez tuer une mouche avec
un tank Prfrez alors les bibliothques, en voici d'ailleurs quelques-unes qui pourraient vous servir :
Sizzle, Qwery : deux bibliothques conues pour fonctionner de la mme manire que la mthode querySelector(),
ce type de bibliothques est d'ailleurs l'origine de l'implmentation officielle de la mthode en question. La premire est
le moteur de slection du framework jQuery mais est relativement lourde, la seconde a l'avantage d'tre particulirement
lgre et un poil plus rapide en terme d'excution.
Popcorn.js : une bibliothque permettant une manipulation aise des balises <audio> et <video>, il devient ainsi trs
simple d'interagir avec ces balises afin de mettre en place des sous-titres, des commentaires placs un moment prcis de
la piste audio ou vido, etc.
Raphal, CAKE, Three.js : trois bibliothques spcialises dans le graphisme. La premire fonctionne exclusivement
avec les images SVG, la deuxime avec la balise <canvas> et la troisime s'est spcialise dans la 3D et gre la fois
SVG, <canvas> et surtout la bibliothque WebGL, qui sait tirer parti du moteur OpenGL !
Underscore.js : cette bibliothque est un must-have si vous souhaitez utiliser les fonctionnalits de l'ECMAScript 5 sur
tous les navigateurs ! Son principe de fonctionnement n'est pas bas sur des polyfills, qui pourraient perturber le bon
droulement d'autres scripts, mais plutt sur une collection de mthodes charges d'accomplir les mmes tches que les
mthodes prvues par l'ES 5.
Modernizr : comme vous le savez si bien, les langages Web sont plus ou moins bien supports selon les navigateurs,
surtout quand il s'agit de fonctionnalits rcentes ! Cette bibliothque a pour but de vous aider dtecter la prsence de
telle ou telle fonctionnalit, il ne vous restera alors plus qu' fournir un script rsolvant ce problme (un polyfill) ou
exploitant une solution alternative.
Ce PDF vous est offert par CAPGEMINI
Dcouv rez des mtiers plein d'env ies http://www.f r.capgemini.com/carrieres/technology _serv ices/
Partie 6 : Annexe
376/378
Il n'est malheureusement pas possible de vous faire une liste complte de tout ce qui existe en terme de bibliothques, elles sont
bien trop nombreuses. Toutefois, vous trouverez certains sites tels que microjs qui arrivent lister une bonne partie des
bibliothques Javascript les plus intressantes. Vous verrez, il y a de quoi faire !
Tant que nous y sommes, voici un site bien utile qui vous permettra de savoir quels navigateurs supportent telle ou
telle fonctionnalit du HTML ou du Javascript : http://caniuse.com/. utiliser sans modration !
En rsum
Il vous reste encore beaucoup faire pour tre rellement l'aise en Javascript. Pour cela, vous allez devoir coder afin
d'acqurir de l'exprience et gagner en assurance.
vitez au maximum toute obfsucation de code ou tout code intrusif. Cela ne vous amnera qu' de mauvaises pratiques et
n'aidera pas vos utilisateurs.
Afin de travailler plus vite, vous trouverez de nombreux frameworks ou bibliothques qui vous faciliteront la tche lors
de vos dveloppements. Connatre un ou deux frameworks sera un avantage pour vous lors d'un entretien d'embauche.
N'oubliez pas que le Javascript ne se rsume pas une simple utilisation au sein des navigateurs Web, il existe bien
d'autres plateformes qui s'en servent, tels que Adobe Air et Node.js prsents la fin de ce chapitre.
Ce tutoriel est maintenant termin ! Nous esprons qu'il aura convenu vos attentes. N'oubliez pas de consulter la partie annexe
du cours pour en apprendre un peu plus sur ce langage.
Nous tenons remercier les personnes qui ont contribu de prs ou de loin l'criture de ce cours. Ces personnes sans qui ce
cours aurait eu du mal avancer !
Commenons par trois accros du Javascript :
Partie 6 : Annexe
377/378