5. Développement Web
Javascript





5.1. Qu'est ce que Javascript ?

D'après Wikipédia : Le langage a été créé en dix jours en mai 1995 pour le compte de la Netscape Communications Corporation par Brendan Eich, qui s'est inspiré de nombreux langages, notamment de Java mais en simplifiant la syntaxe pour les débutants.

Javascript est à la base un langage destiné à dynamiser les pages web du côté client, c'est à dire au niveau du navigateur de l'utilisateur. Le terme dynamiser est à prendre au sens de rendre plus attrayant.

Javascript peut être utilisé de manière procédurale, objet ou fonctionnelle ce qui en fait un langage parfois difficile à maîtriser, sachant que la couche objet est de type prototype ce qui se caractérise par le fait qu'un objet est mutable (modifiable) et non statique.

En effet, les pages web sont à la base des pages dites statiques, c'est à dire dont le contenu ne varie pas une fois chargé au sein du navigateur.

Javascript, généralement abrégé en JS, permet de manipuler des pages (X)HTML au travers de l'API (Application Programming Interface) DOM (Document Object Model), c'est à dire sous forme arborescente.

Le standard (X)HTML définit notamment la possibilité d'assigner à des balises, des actions, sous forme d'attributs (onclick, onsubmit, etc) et d'assigner à ces actions, une fonction Javascript.

Javascript a été standardisé (ECMAScript) au travers d'un consortium appelé ECMA (European Computer Manufacturers Association) qui est une organisation de standardisation de l'industrie informatique.

Attention il ne faut pas confondre le langage Javascript avec le langage Java qui, lui, est plus proche du C++.

5.1.1. AJAX

L'évolution de Javascript est AJAX (Asynchronous JAvascript and XML) qui est la possibilité de lancer des requêtes asynchrones, en d'autres termes : interroger un serveur, traiter sa réponse dès qu'on la reçoit et mettre à jour le DOM (Document Object Model).

AJAX permet de créer des RUI (Rich User Interface) comme par exemple les webmails des fournisseurs d'accès internet.

Exemple : on peut cliquer sur un mail pour en visualiser le contenu. Pendant que l'on interroge le serveur et que celui-ci fournit le contenu du mail au navigateur, on peut cliquer sur un bouton "check mail" qui vérifie si de nouveaux mails ont été reçus.

JS permet d'apporter un confort d'utilisation et une ergonomie aux pages web afin d'en faire des applications. De nombreux frameworks ont été créés afin de faciliter certaines tâches :

5.1.2. JSON

JSON (JavaScript Object Notation) est un format textuel pour l'échange d'information qui possède deux avantages :

{
	"nom" : "Richer", 
	"prenom" : "Sarah",
	"age" : 8,
	notes : [ 10, 8, 9 ]
}

JSON permet de transformer des objets Javascript en un texte qui peut alors être envoyé à un serveur. De son côté, le serveur récupère le texte et peut le transformer en objet.

5.1.3. Caractéristiques de Javascript

Javascript est, à la base, un langage exécuté côté client, celà signifie que le code s'exécute dans votre navigateur sur le poste client (votre machine).

Aujourd'hui, Javascript peut également être utilisé côté serveur grâce à Node.js.

Pour des raisons de sécurité, Javascript ne permet pas de lire ou écrire sur votre disque dur. Si c'était le cas, une personne mal intentionnée pourrait récupérer le contenu de votre disque ou endommager des fichiers.

network and web

Javascript est un langage :

  • de scripts : interprété (et non compilé comme Pascal ou C)
  • peu typé : le typage est dynamique, c'est à dire réalisé lors de l'affectation d'une valeur à une variable
  • dont la structure du langage (grammaire) repose sur celle du langage C, un langage de programmation impératif, généraliste, traditionnellement utilisé en programmation système (Unix / Linux) et inventé au début des années 1970 par Dennis Ritchie et Ken Thompson
  • orienté objet à prototype, c'est à dire que l'on appelle des méthodes associées aux variables et que l'héritage dépend des fonctions liées à l'objet.

En particulier, le fait que Javascript repose sur le langage C implique :

  • l'utilisation des mêmes structures de contrôle : if / while / for / switch
  • l'utilisation des mêmes structures d'évaluation des expressions arithmétiques et logiques
  • la disctinction entre majuscule et miniscule

5.2. Le langage

5.2.1. Variables

5.2.1.a  définition

Une variable est définie par un identifiant alphanumérique comme dans la plupart des langages :

Exemple d'identifiants:

Attention: on a indiqué que Javascript différencie lettres majuscules et minuscules, les identifiants suivants sont donc tous différents : A_b, A_B, a_B

Pour déclarer une variable, il existe plusieurs possibilités :

var maVariable;
var maVariable1, maVariable2;
annee_de_naissance = 2013;
var x1 = 456, x2;

5.2.1.b  portée

La portée d'une variable caractérise son accessibilité. Dans le code suivant :

var factor = 4;
	
function product(x) {
    var n = x * factor;
    return n;
}

Attention : dans une fonction, une variable non déclarée explicitement par var devient globale mais uniquement si la fonction est appelée. Si la fonction n'est pas appelée, la variable est inconnue. Par exemple dans le cas suivant :


function sous_fonction() {
    for (i = 9; i <= 10; ++i) {
    	document.writeln( "sous fonction i = " + i + "<br />");
    }
}

function fonction() {
    for (i = 1; i <= 10; ++i) {
	document.writeln("fonction i = " + i + "<br />");
	sous_fonction(); 
    }
}

On affichera :

fonction i = 1
sous fonction i = 9
sous fonction i = 10

Si la variable est déclarée par var dans la fonction elle restera locale à la fonction.

5.2.2. Définition des types

On rappelle que le langage est peu typé. Le langage étant interprété cela signifie que le typage d'une variable est réalisé lors de l'affectation d'une valeur.

Il existe des types élémentaires :

  1. var entier = -1;
  2. var reel = 3.1415;
  3. var chaine1 = "toto"; // chaine avec double quote (guillemet double)
  4. var chaine2 = 'titi'; // chaine avec simple quote (guillemet simple)
  5. var booleen1 = true;
  6. var booleen2 = (entier > 3);
  7. var fonction = function f(x) { return x*x; }

Ainsi que des types élaborés (ou complexes) :

Pour déclarer des variables qui sont des instances de types élaborés (en fait des objets), il faut utiliser le nom du type précédé de l'opérateur new :

  1. tab = new Array();
  2. var une_date = new Date();
  3. var naissance = new Date(1970, 8, 30);

On détermine le type d'une variable en utilisant l'instruction typeof :

  1. // types élémentaires
  2. var entier = -1;
  3. var reel = 3.1415;
  4. var chaine1 = "toto";
  5. var chaine2 = 'titi';
  6. var booleen1 = true;
  7. var booleen2 = (entier > 3);
  8. var fonction = function(x) { return x; }
  9.  
  10. // types complexes
  11. var tableau = new Array();
  12. var une_date = new Date(1970, 8, 30);
  13.  
  14.  
  15. typeof entier;   // number
  16. typeof reel;     // number
  17. typeof chaine1;  // string
  18. typeof chaine2;  // string
  19. typeof booleen1; // boolean
  20. typeof booleen2; // boolean
  21. typeof fonction; // function
  22.  
  23. typeof tableau;  // object
  24. typeof une_date; // object
  25.  
  26. if (typeof entier == 'number') {
  27.     reel = reel / entier;
  28. }

Attention : on note que les types complexes apparaissent comme des "object". Il faut dans ce cas plutôt utiliser instanceof :

  1. if (typeof tableau == 'object') {
  2.     if (tableau instanceof Array) {
  3.        // traitement du tableau
  4.     }
  5. }

5.2.2.a  conversion de types élémentaires

a) Chaine vers entier ou réel :

On utilise les fonctions parseInt ou parseFloat.

  1. var chaine1 = "12";
  2. var chaine2 = "3.14";
  3.  
  4. var entier = parseInt(chaine1);
  5. var reel   = parseFloat(chaine2);

On notera que la fonction parseInt peut prendre un second argument qui est la base de conversion

  1. var n = parseInt("A0", 16); // A0 en hexadécimal = 160 en décimal
  2. var n = parseInt("77", 8); // 77 en octal = 63 en décimal

b) entier ou réel vers chaine :

On utilise les guillemets ou la méthode toString

  1. var entier = 12;
  2. var reel = 3.14;
  3.  
  4. var chaine1 = "" + entier;
  5. var chaine2 = "" + reel;
  6. // autre possibilité
  7. var chaine1 = entier.toString();
  8. var chaine2 = reel.toString();

On notera que la fonction toString peut prendre un argument qui est la base de conversion

  1. // s = "255 en décimal = ff en hexadécimal"
  2. var s = "255 en décimal = " + (255).toString(16) + " en hexadécimal";
  3. var entier = 255;
  4. var s = "255 en décimal = " + entier.toString(16) + " en hexadécimal";

c) cas problématique :

Si on écrit :

  1. var i = 12 + '4';
  2. var j = '12' + 4;

alors i et j seront égaux à la chaine "124" et non pas à la valeur 16, utilisez alors parseInt pour les chaines.

5.2.3. Expressions arithmétiques et logiques

5.2.3.a  opérateurs arithmétiques

Certains de ces opérateurs peuvent être combinés avec l'opérateur d'affectation = :

  1.  i = 1;
  2.  j = ++ i;  // j = 2, i = 2
  3.  
  4.  i = 1;
  5.  k = i ++;  // k = 1, i = 2
  6.  
  7.  i = 3;
  8.  k = i << 2;    // k = 12 = 3 * 2 * 2
  9.  
  10.  i = 5;
  11.  j = 2;
  12.  j *= 3;        // j = j * 3 = 6
  13.  i += j - 7; // i = i + (j - 7) = 5 + (6 - 7) = 4
  14.  

5.2.3.b  opérateurs de comparaison

Attention : il ne faut pas confondre l'opérateur d'affectation = et l'opérateur de comparaison pour l'égalité ==

5.2.3.c  opérateurs logiques

  1. // (x égal 1) ou (x égal 2)
  2. var booleen = (x == 1) || (x == 2);
  3.  
  4. // (x égal 1) et (x égal 2)
  5. var booleen = (x == 1) && (x == 2);
  6.  
  7. // (x égal 1) ou (non(y différent de 2))
  8. var booleen = (x == 1) || (~(y!=2));

5.2.4. Les structures de contrôle

5.2.4.a  la conditionnelle if / then / else (si alors sinon)

La conditionnelle, ou si alors sinon s'écrit de manière générique :

if (expression booléenne) { 
   instructions ;
} else { 
   instructions ;
}
  1. // if then
  2. if ( x != 0 ) {
  3.     y = y / x;
  4. }
  5.  
  6. // if then else
  7. if ( x != 0 ) {
  8.     y = y / x;
  9. } else {
  10.     y = 0;
  11. }
  12.  
  13. // if then else if
  14. if ( x != 0 ) {
  15.     y = y / x;
  16. } else if ( x > 0 ) {
  17.     y = 1 / x;
  18. } else {
  19.     y = 0;
  20. }

5.2.4.b  boucle while (tant que)

La boucle while, ou tant que s'écrit de manière générique :

while (expression booléenne) { 
   instructions ;
}
  1. // additionne les nombres entiers de 1 à 10
  2. var sum = 0;
  3. var i = 1;
  4. while ( i <= 10 ) {
  5.     sum = sum + i;
  6.     ++ i;
  7. }

5.2.4.c  boucle do while (répéter)

Il s'agit de l'équivalent du repeat until du Pascal avec une nuance. En Pascal on dit répéter ... jusqu'à, alors qu'en C (ou en Javascript), on dit répéter ... tant que.

do { 
   instructions ;
} while (expression booléenne);
  1. // additionne les nombres entiers de 1 à 10
  2. var sum = 0;
  3. var i = 1;
  4. do {
  5.     sum = sum + i;
  6.     ++ i;
  7. } while ( i <= 10 );

5.2.4.d  boucle for (pour)

Elle fonctionne sur le schéma :

for (initialisation ; condition-de-repetition ; increment ) { 
   instructions ;
}

En fait la boucle for est une autre manière d'écrire la boucle while.

initialisation; 
while (condition-de-repetition) { 
   instructions ;
   increment ;
}

Voici un exemple :

  1. // additionne les nombres entiers de 1 à 10
  2. var sum = 0;
  3. var i;
  4. for ( i = 1 ; i <= 10 ; ++ i) {
  5.     sum = sum + i;
  6. }

que l'on peut également écrire :

  1. // additionne les nombres entiers de 1 à 10
  2. for ( sum = 0 , i = 1 ; i <= 10 ; ++ i) {  
  3.     sum = sum + i;
  4. }

5.2.4.e  sortie de boucle (break)

L'instruction break permet de sortir d'une boucle :

  1. // additionne les nombres entiers de 1 à 5
  2. var sum = 0;
  3. var i;
  4. for ( i = 1; i <= 10; ++ i) {  
  5.     if ( i == 6 ) break;
  6.     sum = sum + i;
  7. }

5.2.4.f  conditionnelle switch (selon cas)

L'equivalent du case of du Pascal :

  1. switch(x) {
  2.     case 0: y = 0; break;
  3.     case 1: y = 1; break;
  4.     case -1: y = 75; break;
  5.     default: y = 999; break;  
  6. }
  7.  
  8. // reviendrait à écrire avec if then else
  9. if (x == 0) {
  10.     y = 0;
  11. } else if (x == 1) {
  12.     y = 1;
  13. } else if (x == -1) {
  14.     y = 75;
  15. } else  {
  16.     y = 999;
  17. }

Attention : dans la plupart des langages l'instruction case n'admet qu'une valeur scalaire (entier, caractère). En Javascript on peut également utiliser des chaines de caractères ou des réels.

5.2.5. Les fonctions

Les caractéristiques des fonctions sont les suivantes :

  1. // fonction sans paramètre
  2. function hello() {
  3.     document.write('coucou');
  4. }
  5.  
  6. // fonction avec deux paramètres
  7. function somme( a, b ) {
  8.     if ((typeof a == 'number') && (typeof b == 'number')) {
  9.         return a + b;
  10.     }
  11.     return 0;
  12. }

Pour appeler une fonction il suffit d'utiliser son nom et fournir des paramètres :

  1. // appel de hello
  2.  hello();
  3.  
  4. // appel de somme
  5. var y = 2;
  6. var sum = somme( 1, y );

5.2.5.a  passage par valeur ou par adresse ?

La situation est confuse :

Voir l'exemple suivant :

  1. function fBool(v) {
  2.     v = false;
  3. }
  4.  
  5. function fInt(v) {
  6.     v = 2;
  7. }
  8.  
  9. function fReal(v) {
  10.     v = Math.abs(v);
  11. }
  12.  
  13. function fStr(v) {
  14.     v = v + '2';
  15. }
  16.  
  17. function fArr(v) {
  18.     v.push(3);
  19. }
  20.  
  21. function fDate(v) {
  22.     v.setTime(v.getTime() + 1000000000);
  23. }
  24.  
  25. var myBool = true;
  26. var myInt = 1;
  27. var myReal = 1.1;
  28. var myStr = "1";
  29. var myArr = new Array(1, 2);
  30. var myDate = new Date("Sep 30, 1970");
  31.  
  32. fBool(myBool);
  33. fInt(myInt);
  34. fReal(myReal);
  35. fStr(myStr);
  36. fArr(myArr);
  37. fDate(myDate);
  38.  
  39. print('myBool = ' + myBool);
  40. print('myInt = ' + myInt);
  41. print('myReal = '+ myReal);
  42. print('myStr = '+myStr);
  43. print('myArr = '+myArr.join(","));
  44. print('myDate = '+myDate.toString());
  45.  

Dont le résultat est :

  1.  myBool = true
  2.  myInt = 1
  3.  myReal = 1.1
  4.  myStr = 1
  5.  myArr = 1,2,3  // !! on aurait du trouver 1,2
  6.  myDate = Sun Oct 11 1970 13:46:40 GMT+0100 (CET) // !! on aurait du trouver 30 Septembre 1970

Pour réaliser un passage par valeur d'un tableau, voici une possibilité qui consiste à dupliquer le tableau passé en paramètre puis à travailler sur la copie :

  1. function fArr(v) {
  2.   // début de la copie
  3.   vCopy = new Array();
  4.   for (i in v) {
  5.     vCopy.push(v[i]);
  6.   }
  7.   // fin de la copie
  8.   // on travaille sur la copie
  9.   vCopy.push(3);
  10.   vCopy[0] = vCopy[0] + 4;
  11.   print('vCopy[0] = ' + vCopy[0]);
  12.   print('vCopy = '+vCopy.join(","));
  13. }
  14.  
  15. var myArr = new Array(1, 2);
  16. fArr(myArr);
  17. print('myArr = '+myArr.join(","));
  18.  
  19.  

5.2.5.b  variable locale ou globale

5.2.6. Les chaînes de caractères (classe String)

5.2.6.a  déclaration

On déclare une chaine entre simple ou double quotes (guillemets).

Certains caractères spécifiques sont introduits par un caractère backslash \ :

  1.  s = 'I don\'t care';
  2.  s = "I don't care";
  3.  s = "message :\nyou are in C:\\windows";

5.2.6.b  length, charAt, charCodeAt

La donnée membre length permet d'obtenir la longueur de la chaine en nombre de caractères et la fonction charAt d'accèder au ième caractère. Le premier caractère de la chaine est en position 0 :

  1. var s = "coucou stéphanie";
  2.  document.writeln( "length = " + s.length ); // 16
  3.  document.writeln( "charAt(0) = " + s.charAt(0) ); // c
  4.  document.writeln( "charCodeAt(0) = " + s.charCodeAt(0) ); // 99
  5.  document.writeln( "charAt(9) = " + s.charAt(9) ); // é
  6.  document.writeln( "charCodeAt(9) = " + s.charCodeAt(9) ); // 233

5.2.6.c  concaténation

On utilise la fonction concat ou l'opérateur + :

  1. var s = "il était";
  2. var t = "une fois";
  3. var u = s + ' ' + t;        // u = "il était une fois"
  4. var v = t.concat( " ", s);  // v = "une fois il était"

5.2.6.d  indexOf, lastIndexOf

Ces fonctions donnent la position d'une sous-chaîne à l'intérieur d'une chaine, on pourra spécifier l'index dans la chaîne à partir duquel on commence la recherche :

  1. var chaine = "coucou dit le coucou tout à coup";
  2. var first = chaine.indexOf( "cou" ); // 0
  3. var last = chaine.lastIndexOf( "cou" ); // 28
  4. var first = chaine.indexOf( "cou", 8 ); // 14
  5. var first =  chaine.indexOf( "cout" ); // -1

5.2.6.e  search, match, replace

les fonctions suivantes utilisent des expressions régulières pour :

  1. var chaine = "Wed Sep 30 1970";
  2. var pos = chaine.search( /[0-9]{4}/ );  // pos = 11
  3. var a = chaine.match( /[0-9]+/g );      // a = [30 1970]
  4. var s = chaine.replace( / ([0-9]{2}) ([0-9]{4})/, " -\$2 \$1-" );
  5. // s = "Wed Sep -1970 30-"

5.2.6.f  substr, substring et slice

Ces fonctions permettent d'extraire des sous-chaînes

Par exemple les trois expressions suivantes vont extraire la chaine "coucou␣t" :

  1. var chaine = "coucou dit le coucou tout à coup";
  2. var sub_string = chaine.substring( 14, 22 );
  3. var sub_string = chaine.substr( 14, 8 );
  4. var sub_string = chaine.slice( 14, -10 );

5.2.6.g  toLowerCase, toUpperCase

Les fonctions toLowerCase et toUpperCase permettent de transformer respectivement en minuscules et majuscules une chaîne de caractères.

  1. var s = "tOTO";
  2. var t = s.toLowerCase();   // t = "toto"

5.2.7. Les tableaux

Les tableaux en javascript sont des tableaux associatifs qui fonctionnent avec une clé non forcément entière : à une clé (key) on associe une valeur (value).

5.2.7.a  déclaration

Il existe 3 façons de déclarer un tableau :

  1. // 1: utilisation des crochets []
  2.  a1 = [ 'a', 'b', 3, true ];
  3. // 2: création et initialisation
  4.  a2 = new Array( 'a', 'b', 3, true );
  5. // 3: création puis remplissage
  6.  a3 = new Array();
  7.  a3[ 0 ] = 'a';
  8.  a3[ 1 ] = 'b';
  9.  a3[ 2 ] = 3;
  10.  a3[ 3 ] = true;

On peut également déclarer des tableaux associatifs (clé non entière) :

  1.  colors = new Array();
  2.  colors[ "red" ]   = "#ff0000";
  3.  colors[ "green" ] = "#00ff00";
  4.  colors[ "blue" ]  = "#0000ff";

5.2.7.b  présence d'une valeur

Pour un tableau simple on utilisera indexOf(valeur), par contre pour un tableau associatif avec clé non entière on utilisera le mot clé in :

  1. var a = [ 1, 2, 8, 9, 25 ];
  2.  a.indexOf( 9 ); // 3, valeur 9 présente à l'indice 3 du tableau
  3.  a.indexOf( 12 ); // -1, élément non présent
  4.  
  5. var b = new Array();
  6.  b[ "a" ] = 65;
  7.  b[ "b" ] = 66;
  8.  b[ "0" ] = 48;
  9.  b[ "1" ] = 49;
  10.  if ( "0" in b ) {
  11.     ...
  12.  }

5.2.7.c  parcours des éléments

Soit on parcourt suivant l'indice (clé), soit suivant les valeurs :

  1. for ( i = 0; i < a3.length; ++i) {
  2.     document.writeln( a3[ i ] + " " );
  3. }
  4.  
  5. // red : #ff0000 green : #00ff00 blue : #0000ff
  6. for ( indice in colors ) {
  7.     document.writeln( indice + " : " + colors[ indice ] + " ");
  8. }

5.2.7.d  ajout, suppression

Les méthodes associées aux tableaux sont de type pile ou file

  1. var a = new Array();
  2.  a.push( "une" );
  3.  a.push( "fois" );
  4.  a.unshift( "était" );
  5.  a.unshift( "il" );
  6.  
  7. // affiche : il était une fois
  8.  document.writeln( a.join(" ") );

5.2.7.e  tri

On utilise la fonction sort, on peut également lui associer un paramètre qui est une fonction de comparaison :

  1.  a = new Array( "il" , "était", "une", "fois" );
  2.  a.sort();
  3.  
  4. // affiche : fois il une était
  5.  document.writeln( a.join(" ") );
  6.  
  7.  a = [ 1, 2, 7, 4, 25, -1, 8 ];
  8.  
  9. // <b>tri par défaut (alphabétique)</b> : -1 1 2 25 4 7 8
  10.  a.sort();
  11.  document.writeln( a.join(" ") );
  12.  
  13. // tri <b>numérique</b> ascendant : -1 1 2 4 7 8 25
  14. // nécessite une fonction de comparaison
  15.  a.sort( function( a, b ) { return a - b; } );
  16.  document.writeln( a.join(" ") );
  17.  
  18. // tri numérique descendant : 25 8 7 4 2 1 -1
  19.  a.sort( function( a, b ) { return b - a; } );
  20.  document.writeln( a.join(" ") );

5.2.7.f  décomposition (String.split), composition (Array.join)

La méthode split(chn) associée à une chaine de caractères permet de décomposer la chaine en un tableau en la découpant en fonction d'une sous-chaine chn.

La méthode join(chn) associée à Array permet de transformer un tableau en une chaine en regroupant les éléments et les séparant par chn.

  1. var s = "a..b.c....d";
  2. var a = s.split( ".." );
  3.  
  4. // affiche a-b.c--d
  5.  document.writeln(a.join("-") );

5.2.8. La classe Math

Cette classe définit un moyen d'utiliser les fonctions comme le logarithme, l'exponentielle, sinus, cosinus, ...

  1.  document.writeln( Math.sin( Math.PI ) ); // 1.2246063538223773e-16
  2.  document.writeln( Math.cos( Math.PI ) ); // -1
  3.  document.writeln( Math.sqrt( 2 ) );      // 1.4142135623730951

Voir également : w3schools.js.Math

5.2.9. La classe Date

5.2.9.a  création

La classe Date permet de stocker un timestamp (que l'on pourraît traduire par intervalle de temps), en l'occurrence il s'agit du nombre de millisecondes écoulées depuis le 1er Janvier 1970 à minuit.

  1. // Mon Jan 14 2013 18:04:28 GMT+0100 (CET)
  2. var d = new Date();
  3.  
  4. // Wed Sep 30 1970 00:00:00 GMT+0100 (CEST)
  5. var d = new Date("Sep 30, 1970");
  6.  
  7. // Mon Jan 12 1970 14:46:40 GMT+0100 (CET)
  8. var d = new Date(1000000000);
  9.  
  10. // Wed <span class="red">Sep</span> 30 1970 00:00:00 GMT+0100 (CEST)
  11. var d= new Date(1970, <span class="red">8</span>, 30);
  12.  
  13. var timestamp = Date.parse('Sep 30, 1970'); // 23497200000

Attention : lors de la définition de la date avec année, mois ,jour, le mois de Janvier a pour valeur 0, Février 1, ... On a donc indiqué 8 pour le mois de Septembre.

5.2.9.b  méthodes

On dispose d'un certain nombre de méthodes associées à la classe Date :

5.3. La couche objet en Javascript

5.3.1. Les objets sans classe

On peut créer des objets sans utiliser de classe car toute variable est un objet :

jean = {
	nom: "richer",
	prenom: "jean",
	ddn: "19700930"
};

mathieu = {
	nom: "richer",
	prenom: "mathieu",
	ddn: "19750312"
};

document.write( JSON.stringify(jean) +"<br />" );

On peut également ajouter un champ ou une méthode à un objet existant :

jean.salaire = 3000.0;

function augmente_salaire( pourcentage ) {
	this.salaire = Math.round( (1 + pourcentage/100.0) * this.salaire );
}

jean.augmente = augmente_salaire
mathieu.augmente = augmente_salaire

jean.augmente( 10 );
document.write( JSON.stringify(jean) +"<br />" );

Mais pour mathieu on n'a pas défini de champ salaire. Le code s'exécutera quand même mais sans erreur !

mathieu.augmente( 10 );
document.write( JSON.stringify( mathieu ) +"<br />" );

// l'appel à une fonction inconnue, comme :
// mathieu.fonction_inconnue();
// générera une erreur :
// TypeError: mathieu.fonction_inconnue is not a function

5.3.2. Les objets définis sous forme de classes

On peut définir des classes et les étendre en utilisant class et extends. On fait référence aux champs grâce au mot clé this et à une méthode définie dans la classe mère grâce au mot clé super :

class Personne {

	constructor( nom, prenom ) {
		this.nom = nom;
		this.prenom = prenom;
	}
	
	toString() {
		return this.nom + ", " + this.prenom;
	}
};

class Employe extends Personne {

	constructor( nom, prenom, salaire ) {
		super( nom, prenom );
		this.salaire = salaire;
	}
	
	toString() {
		return super.toString() + ", " + this.salaire + " €";
	}
		
};

elon_musk = new Employe( "Musk", "Elon", 3000000 );
jean_michel = new Employe( "Richer", "Jean-Michel", 3000 );
 
document.write( elon_musk.toString() + "<br />" + jean_michel.toString() );

5.3.3. Extension avec une fonction

On peut par la suite étendre une classe en ajoutant une fonction à son prototype :

Employe.prototype.augmente = function() {
	this.salaire = Math.round( this.salaire * 1.1);
}

elon_musk.augmente();
jean_michel.augmente();
document.write( elon_musk.toString() + "<br />" + jean_michel.toString() );

5.3.4. Extension avec un champ

Dans ce cas, on se trouve face à un problème lié au fait que JSON.stringify ne reportera le champ que si une instance est modifiée pour ce champ :

Employe.prototype.rang = "big boss";

// JSON.Stringify ne retourne pas le champ 'rang'
document.write( JSON.stringify( elon_musk ) + " " + elon_musk.rang + "<br />" );

// mais si on modifie le 'rang' pour une instance, alors celui-ci
// apparaît avec l'utilisation de JSON.stringify
jean_michel.rang = "chercheur";
document.write( JSON.stringify( jean_michel )  );

5.4. Interaction avec le navigateur

L'utilisation de Javascript au sein du navigateur impose de pouvoir interagir avec celui-ci. On dispose de deux moyens pour afficher de l'information :

5.5. La manipulation du DOM

Un des intérêts de Javascript est qu'il permet de manipuler le DOM. On dispose pour cela d'un ensemble de fonctions de base. Malheureusement, le résultat rendu par certaines fonctions est étrange et contient différents types d'information :

Malheureusement le traitement ultérieur du résultat de certaines de ces fonctions est parfois étrange (cf cette page.

Dans ce cas il est préférable d'utiliser querySelectorAll :

const matches = document.querySelectorAll("p");
const matches = document.querySelectorAll("div.note, div.alert");

Voir la documentation sur le site de Mozilla.

5.6. Les frameworks Javascript

5.6.1. Les CDN

Un réseau de diffusion de contenu (RDC) ou en anglais Content Delivery network (CDN) est constitué d’ordinateurs reliés en réseau à travers Internet et qui coopèrent afin de mettre à disposition du contenu ou des données à des utilisateurs.

On trouvera notamment cdnjs.com qui référence nombre de frameworks javascript ainsi que jsdelivr.com En particulier :

5.6.2. Quelques frameworks

Vous trouverez sur cette page, une liste comparative des frameworks Javascript liés au développement web généraliste.

Des frameworks plus spécifiques existent comme HighCharts qui permet de réaliser des graphiques.

5.7. AJAX

La technologie AJAX (Asynchronous JAvascript and XML) qui combine en fait trois technologies :

fait partie de l'aspect dynamique des pages web introduit grâce à Javascript.

Le fait que la requête soit asynchrone impose que l'interface du navigateur n'est pas bloquée entre le moment où on lance la requête et le moment où on récupère les données.

5.7.1. La classe XMLHttpRequest

Pour réaliser une requête asynchrone il faut créer une instance de la classe XMLHttpRequest. En fonction du navigateur, il faudra créer un objet d'un autre type (Microsoft). La création d'une requête ressemble donc plutôt au code suivant :

  1. /**
  2.  * Création d'une instance de la classe requête asynchrone
  3.  * en fonction du navigateur
  4.  */
  5. function getXMLHTTPRequest() {
  6.   try {
  7.  
  8.     req = new XMLHttpRequest();
  9.    
  10.   } catch(exc1) {
  11.    
  12.     try {
  13.    
  14.       req = new ActiveXObject( "Msxml2.XMLHTTP" );
  15.    
  16.     } catch(exc2) {
  17.    
  18.       try {
  19.    
  20.         req = new ActiveXObject( "Microsoft.XMLHTTP" );
  21.    
  22.       } catch(exc3) {
  23.    
  24.         req=false;
  25.        
  26.       }
  27.      
  28.     }
  29.    
  30.   }
  31.  
  32.   return req;
  33. }
  34.  

Avec les frameworks comme JQuery, la création de l'objet adéquat est transparente pour l'utilisateur (voir ci-après).

5.7.2. Récupération de données au format texte

  1. var request = getXMLHTTPRequest();
  2.  
  3. // Appel de l'URL avec la méthode GET
  4. // true indique que la requête est asynchrone
  5.  request.open( "GET", "http://....", true );
  6.  
  7. // indique quelle méthode sera appelée
  8. // quand on obtiendra une réponse
  9.  request.onreadystatechange = process_data;
  10.  
  11. // appel de la requête dans paramètre
  12.  request.send( null );
  13.  
  14. /**
  15.  * Fonction qui traite la réponse obtenue
  16.  *
  17.  */
  18. function process_data() {
  19.    
  20.     if ( request.readyState == 4) {
  21.         if ( request.status == 200) {
  22.             var my_text = request.responseText;
  23.             ...
  24.         }
  25.     }
  26.    
  27. }
  28.  

Le traitement de la réponse passe par une première étape qui vérifie que le traitement de la requête n'a pas rencontré d'erreur. On doit s'intéresser aux deux variables de la requête status et readyState qui maintiennent l'état d'avancement et de complétion (terminaison) de la requête :

 Valeur   Description 
 0   request not initialized 
 1   server connection established 
 2   request received 
 3   processing request 
 4   request finished and response is ready 
Variable readyState
 Valeur   Description 
 200   OK 
 204   No Content 
 205   Reset Content 
 400   Bad Request 
 404   Not Found 
 ...   autres codes d'erreurs 
Variable status

Il faut que :

pour qu'on puisse traiter les données car on a reçu les données et aucune erreur n'a été générée.

Il est généralement nécessaire de traiter les erreurs éventuelles en les signalant par un message d'alerte.

5.7.3. Récupération de données au format XML/XHTML

Dans le cas ou le serveur renvoie des données au format XML, il faudra les récupérer en utilisant la variable responseXML de la requête. Par exemple, si on récupère le fichier :

<doc>
	<today> 30/09/2022 </today>
	<message> Joyeux Anniversaire </message>
</doc>

On en extraira les champs de la manière suivante :

  1. var my_doc  = request.responseXML;
  2. var today   = my_doc.getElementsByTagName( "today" )[ 0 ].innerHTML
  3. var message = my_doc.getElementsByTagName( "message" )[ 0 ].innerHTML

5.7.4. Récupération de données au format JSON

Si les données sont au format JSON, soit, par exemple :

{
	"today" : "30/09/2022",
	"message" : "Joyeux Anniversaire"
}

On utilisera la variable responseText que l'on transformera en objet grâce à JSON.parse() :

  1. var my_obj = JSON.parse( request.responseText );
  2.  console.log( my_obj.today + ' '  + my_obj.message );

5.7.5. Utilisation de JQuery

Le framework JQuery permet de réaliser des requêtes AJAX. Il existe plusieurs manières de réaliser l'appel, j'ai choisi ici d'utiliser une requête généraliste :

  1. $.ajax({
  2.     type: 'GET',
  3.     dataType: "json",
  4.     url: 'ajax_get_data_as_json.php',
  5.     success: function( data ) {
  6.         $( "#id_text").val(
  7.             data.today + "\n" + data.message.replace( "<br />", "\n" )
  8.         );
  9.     },
  10.     error: function( xhr, status, error ) {
  11.         alert('An error occurred ! ' + status + ' ' + error);
  12.     }
  13. });
  14.  

5.7.6. Exemples AJAX

Voici quelques exemples qui reprennent ce que nous venons de voir :

5.8. Exercices

Exercice 5.1

Créer un programme Javascript qui permet de trier un tableau d'entiers. On initialisera le tableau avec des valeurs aléatoires (Math.random()) et on créera une fonction qui trie le tableau en utilisant un tri bulle et qui accepte un tableau en paramètre.

Exercice 5.2

Modifiez le programme précédent en implantant le tri sous forme d'un tri rapide.

Exercice 5.3

Récupérez les données d'un formulaire contenant un champ nom et un champ salaire puis modifier les nom en le passant en majuscules et en augmentant le salaire de 10%. Utilisez document.getElementById().

Exercice 5.4

Reprendre l'exercice précédent mais utilisez le framework JQuery.

Exercice 5.5

Reprendre l'exercice précédent mais utilisez le framework JQuery et une requête Ajax qui envoie les données du formulaire à un script PHP.

Exercice 5.6

Créer une hiérarchie d'objets en Javascript (Point, Rectangle, Circle) ainsi qu'un tableau d'objets et dessiner ces objets dans un canvas.

Exercice 5.7

Créer une classe Mask composée :

  • d'un tableau data de 16 entiers ayant des valeurs entre 0 et 1.
  • d'un entier total qui donne le nombre de valeurs à 1 dans data

Créer un constructeur qui prend en paramètre les valeurs du tableau data sous forme de chaîne de caractères et qui met à jour le champ total.

Créer une fonction contains(m) qui vérifie si le masque m passé en paramètre est contenu dans le masque, c'est à dire que les valeurs du tableau qui sont à 1 dans m le sont aussi dans le masque.

Tester sur quelques exemples.