Quelques détails sur le javascript

LΕ javascript a été inventé pour rendre les pages HTML dynamiques et aurait été implémenté pour Netscape 2.0 en quelques jours seulement (de mauvaises langues disent que cela se ressent). Cela reste néanmoins pratique pour des applications côté client, pour ne pas solliciter le serveur comme le fait le PHP. Par ailleurs, les méthodes AJAX font justement collaborer PHP et javascript pour des pages très réactives, par exemple où l'introduction d'un début de mot produit une liste de noms filtrée par le serveur, sans devoir recharger ou changer de page.
2016.06.11 - Page incomplète, commencée selon mes nécessités, en phase de généralisation. Tests sur Firefox 45 à 68 (2016-20) et partiellement sur MacOSX et Android 4.

Cette page peut servir d'introduction, mais une documentation plus précise se trouve à la page developer.mozilla.org/fr/docs/Web/JavaScript (en français).

1. Généralités

1.1 Script
1.2 Syntaxe
1.3 Mise en œuvre

2. Variables

2.1 Nombres
2.2 Booléens
2.3 Chaînes
2.4 Expression régulières
2.5 Tableaux indexés
2.6 Tableaux associatifs
2.7 Tri d'une base de données

3. Structures

3.1 Comparateurs
3.2 Conditions
3.3 Boucles
3.4 Fonctions
3.5 Erreurs

4. Interactions

4.1 Boîtes
4.2 Contenu
4.3 Attributs
4.4 Formulaires
4.5 Événements

C. Autres classes

C.1 Date et heure
C.2 Mathématique

G. Graphisme

G.1 Texte
G.2 Lignes
G.3 Courbes
G.4 Rectangles
G.5 Effets

1. Généralités

Cette page nécessite au moins une connaissance des principes de l'HTML.

1.1 Script

Un script de javascript s'écrit traditionnellement entre les balises <script type="text/javascript"> et </script>, elles-mêmes placées entre les balises <head> et </head>. Il est possible de placer un script entre <body> et </body>, mais la page HTML étant un flux, il n'est pas dit qu'une fonction sera disponible si elle est écrite après le code qui l'appelle.

Le navigateur IExplorer ayant tardé à accepter la balise <script>, il convenait de cacher le code entre <!-- et -->, ce qui explique que vous verrez encore ces quelques signes dans certains exemples.

Il est encore possible d'éditer le code dans une page extérieure chargée par la balise suivante (à placer entre <head> et </head>

<script type="text/javascript" src="moncode.js"></script>

1.2 Syntaxe

La syntaxe est à peu de choses près celle du C/C++/PHP… ce qui signifie des scripts de type :

function cube(x)
  {
  return power(x,3);
  }
for(var i ; i< 10 ; i++)
  {
  alert(cube(i)) ;
  }

Les instructions sont séparées par un point-virgule ou une fin de ligne.

Les commentaires sont introduits comme en C :

// commentaire sur une ligne, souvent après une ligne de code

/* un commentaire qui peut
s'étendre sur plusieurs lignes */

1.3 Mise en œuvre

La façon la plus simple est d'insérer un bout de code dans une balise HTML, à l'aide d'un événement :

<p>
<span onMouseover="alert('Bonjour, Monde')">Survolez-moi avec la souris!<span>

Survolez-moi avec la souris!

Une instruction très simple permet d'afficher le traditionnel «Hello World!» :

alert("Hello World!");

Le script, le plus souvent inclus dans la page HTML ou dans une page chargée, est composé de de différentes fonctions appelées par des éléments HTML (boutons <input>, survol ou clic de souris…).

Pour lancer une ou plusieurs fonctions au chargement de la page, il suffit de les mentionner dans la balise <body onLoad="fct1(); fct2();">. Comme l'HTML traite un flux de données, il convient que les fonctions soient écrites avant leur appel. Dans le cas d'un appel dans la balise <body>, il faut qu'elles soient écrites entre <head> et </head>).

Ci-après un début de page HTML permettant de tester du code avec un navigateur acceptant le javascript. onLoad="essai()" dans la balise <body> permet de lancer, au chargement de page, la fonction essai() qui elle-même fait appel à la fonction hypothenuse()  :

<html><head><meta charset="utf-8">
<script>
function hypothenuse(x, y)
  {
  return (x *x + y *y) **0.5 ;
  }
function essai()
  {
  alert(hypothenuse(3, 4)) ;
  }
</script>
<body onLoad="essai()">
<!-- partie html -->
</body></html>

Note : l'UTF-8 (première ligne), prenant en compte les caractères le plus divers, est recommandé. Mais le fichier doit être sauvegardé sous le même format. Plus limités, les encodages iso8859-1(5) et cp1252 conviennent aux langues latines.

Il est possible de lire et de modifier le contenu de la page de façon précise, voire de composer des graphiques à la volée.

2. Variables

Une variable est un conteneur de valeur, modifiable. On définit, redéfinit une variable, dont on peut récupérer la valeur. Un nom de variable peut contenir des lettres, des tirets bas _ et des chiffres, mais ne peut commencer par un chiffre. Ces mots suivant sont réservés par javascript et ne peuvent donc pas servir de nom de variable :

abstract · boolean · break · byte · case · catch · char · class · const · continue · default · do · double · else · extends · false · final · finally · float · for · function · goto · if · implements · import · in · instanceof · int · interface · long · native · new · null · package · private · protected · public · return · short · static · super · switch · synchronized · this · throw · throws · transient · true · try · var · void · while · with

Déclaration

Une variable doit avoir été «initialisée» avant de pouvoir servir.

On peut déclarer explicitement (avec le mot réservé var) une variable avant de l'utiliser.

var nbr ; nbr =0.123 ; // .123 est incorrect!
var str ="ceci-cela" ;
var tableau =new Array() ;
tableau[0] =123 ;

Une variable peut se déclarer de façon implicite (sans le mot réservé var) :

nbr =10;
str ="ceci-cela";
tabl =new Array(123, 443);

Les variables ont généralement une portée globale : elles sont appelables ou modifiables à n'importe quel endroit du script. Néanmoins, les variables déclarées par var à l'intérieur d'une fonction ont une portée locale, limitée à la partie de script interne à cette fonction : elles ne seront appelables et modifiables que là. Il peut donc coexister deux variables différentes de même nom. Attention cependant, une variable déclarée de façon implicite dans une fonction garde une portée globale.

Types

Les données n'ont pas toutes la même nature : les nombres permettent des calculs, les chaînes représentent une suite de caractères, les booléens représentent le «vrai» et le «faux» logiques, le type «tableau» représentent une collection de données. De la même manière, les variables peuvent contenir des données de type nombre, chaîne, booléen ou tableau.

Le javascript n'est cependant pas fortement typé, c'est-à-dire qu'il est capable d'interpréter le type d'une variable selon le contexte : "10"+5 a pour résultat la chaîne "105", et "10"/5 égale le nombre 2.

typeof expression renvoie boolean, number, string, symbol, function, object ou undefined (lorsqu'aucune valeur n'est attribuée à une variable).

Attention : typeof ["cha", "badaba", "da"] retourne objet. Utiliser Array.isArray(tabl) pour s'assurer que tabl est bien un tableau indexé (doit retourner true).

Il existe des fonctions de conversion de type : Number(""), var_nbr.toString(), String(nombre) et Boolean()

null est une donnée sans valeur.

2.1 Nombres

Attention : beaucoup de fonctions concernant les nombres doivent être préfixées avec Math : abs(), round(), floor(), ceil(), min(), max(), exp(x), pow(x,y), log(), sqrt(), voir module Math.

Javascript ne fait pas de différence entre nombres entiers et nombres réels (avec le point pour séparateur décimal). Un nombre inférieur à 1 doit afficher le 0 avant le point décimal : 0.43 et non .43.

Un nombre peut être écrit sous forme exponentielle : 23e4 ou 23E4 (23 multiplié par 104) ; 23e-4 ou 23E-4 (24 divisé par 104).

Number.MAX_VALUE est la plus grande quantité possible : 1.7976931348623157e+308 (pourrait dépendre du système)
Number.MIN_VALUE est la plus petite quantité possible entre deux valeurs : 5e-324 ; la moitié de ce nombre = 0

Font également partie de la classe Number :

Number.POSITIVE_INFINITY = Infinity, tout ce qui dépasse MAX_VALUE
Number.NEGATIVE_INFINITY = -Infinity
Number.NaN = (Not a Number), par exemple la division d'un infini par un autre infini, ou le résultat d'une opération où intervient une chaîne non numérique.

Tests

isInteger() renvoie true si une valeur est entière
isFinite() renvoie true si une valeur est finie
isNaN() renvoie true si l'élément est NaN
Number.isSafeInteger() renvoie true si un nombre est un entier compris entre -(253-1) et 253-1 (bornes incluses). Un nombre exprimé sous forme de chaîne, NaN, Infinity ou undefined retournent false.

Opérateurs

Les opérateurs sont habituels : +, -, * pour la multiplication, / pour la division, ** pour l'exposant.

% pour l'opération modulo (reste). Attention : (-15) %12 donne -3, et pas 9

- sert également à renverser le signe d'une variable : nbr =-nbr

= sert à l'affectation d'une valeur à une variable : nbr =3 ; mais jamais à tester l'égalité.

Notations raccourcies

Il est possible d'utiliser une notation raccourcie lorsqu'une variable réceptionne directement sa valeur modifiée par une opération :

nbr +=5 ajoute 5 à nbr ; peut remplacer nbr =nbr+5
nbr -=3 retire 3 à nbr ; peut remplacer nbr =nbr-3
nbr *=4 multiplie nbr par 4 ; peut remplacer nbr =nbr*4
nbr /=2 divise nbr par 2 ; peut remplacer nbr =nbr/2

Attention! nbr-=var retranche la valeur de var à la variable nbr ; nbr=-var affecte à nbr l'inverse de la valeur de var

nbr++ augmente la variable nbr de 1 (incrémentation)
nbr-- soustrait 1 de la variable nbr (décrémentation)

Priorité décroissante des opérateurs

( ) et virgule séparatrice de liste
! ++ -- - (inversion de la valeur d'une variable)
* /
+ -
< <= >= >
== !=
&&
||
? : (if then else en mode raccourci)
= += -= *= /= %=

Bases

Les entiers peuvent être écrits sous différentes bases :

Transformations

parseInt("",base) tente d'interpréter une chaîne de caractères, éventuellement selon la base précisée (nombre de 2 à 36), en s'arrêtant au premier caractère non utilisable, les caractères acceptés (de 0 à 9 et de a à z) dépendant de la base. La notation exponentielle n'est pas reconnue
parseFloat("") tente de convertir une chaîne en nombre réel. Les caractères acceptés sont les chiffres de 0 à 9, E, e, ., + et -.

D'autres fonctions transforment les nombres en chaînes :

var_num.toString(base) ou (43).toString(base)permet de convertir un nombre en chaîne à la base voulue, sans préfixe 0x ou 0 ; base 10 par défaut
nbr.toExponential() convertit un nombre en chaîne sous sa forme exponentielle (1.23e8 = 1,23 x 108)
nbr.toFixed(n) convertit une variable nombre en chaîne, avec n chiffres après la virgule
nbr.toPrecision(n) convertit un nombre en chaîne de longueur n. Si la longueur de la chaîne excède n, seule la partie avant l'exposant est concernée

2.2 Booléen

Les deux valeurs booléennes sont true et false. Une condition avec true est toujours vraie et toujours fausse avec false. Ils sont produits par les comparateurs et les tests.

&& «et» logique
|| «ou» logique
not inversion logique

Les valeurs reconnues comme fausses sont : null, NaN (not a number), 0 (zéro), "" (chaîne vide) mais normalement pas undefined. Attention : "0" ou " " ne sont pas des chaînes vides, comme new Array(0) et new Array("") ne sont pas des tableaux vides.

2.3 Chaînes 2016.06.19

N'importe quel suite de caractères entourées de guillemets. Possible sur plusieurs lignes si les guillemets sont `

var1 ="les guillemets double permettent l'insertion de l'apostrophe";
chaine ='les guillemets simples (apostrophe) permettent les "guillemets" doubles';
longuechaine =`Les accents graves (sans voyelle) permettent d'écrire une chaîne sur
plusieurs lignes, et d'inclure tous les guillemets 'simples' ou "doubles"
`

Entourer des caractères de / permet de définir une expression régulière.

La concaténation se fait avec +  : a ="un-"; b ='deux'; c =a +b
La notation courte += est acceptée : a ='un-'; b ="deux"; a +=b

chaine.concat() joint deux ou plusieurs chaines, convertissant les nombres en chaînes

Pour une variable chaine :

chaine.length contient le nombre de caractères d'une chaîne
chaine.charAt(n) contient le caractère d'une chaîne selon son index (n de 0 à length-1)
chaine.indexOf(ch, n) contient la première position d'une chaîne dans une autre, en commençant éventuellement la recherche à partir de n. -1 en cas d'échec
chaine.lastIndexOf("", n) retourne la position de la première occurrence en commençant par la fin
chaine.substring(deb, fin) retourne la sous-chaîne de la position deb à fin (non incluse)
chaine.slice(deb, fin) retourne une partie de chaîne à partir de l'index deb, jusqu'au bout si la fin n'est pas précisée
chaine.substr(deb, n) retourne la sous-chaîne de longueur n à partir de la position deb

chaine.toLowerCase() toutes les lettres minuscules
chaine.toUpperCase() toutes les lettres en MAJUSCULES
chaine.toLocaleLowerCase() toutes les lettres en minuscules, selon la locale spécifiée par l'hôte
chaine.toLocaleUpperCase() toutes les lettres en MAJUSCULES, selon la locale spécifiée par l'hôte

encodeURI() transforme en chaîne utilisable dans une adresse URI : certains caractères ASCII (0-127), comme l'espace en %20, < et > en %3C et %3E ; tout ce qui dépasse l'ASCII en %HH (H est un chiffre hexadécimal, de 0 à 9 et A à F) non :
L’arrêt (codé en UTF-8) devient L%E2%80%99arr%C3%AAt (3 octets pour , 2 pour ê), ce qui permet d'écrire une fonction qui mesure une chaîne UTF-8 en octets :

function octets(ch)
  {
  return encodeURI(ch).split(/%..|./).length -1 ;
  }

Cette fonction transforme la chaîne initiale en chaîne URI, la débite (split) selon une expression régulière signifiant «par une chaine composée de % suivi de deux caractères (%..), sinon (|) par un seul caractère (.)». Le tableau résultant est mesuré, soustrait de 1 (n délimitations donnent n+1 parties).

chaine.endsWith(ch) vérifie que la chaîne se termine par une autre ; retourne true ou false
chaine.includes(ch) vérifie que la chaîne en contient une autre ; retourne true ou false
chaine.startsWith(ch) vérifie que la chaîne commence par une sous-chaîne ; retourne true ou false

chaine.charCodeAt(n) retourne le code ascii/unicode du caractère à l'index
String.fromCharCode(n) convertit un code ascii/unicode en un caractère. Ne s'appliquant pas sur un objet «chaîne», il faut préciser le préfixe String.

ch =chaine.concat() joint deux ou plusieurs chaines. Les nombres sont convertis en chaînes
chaine.localeCompare(autre) compare deux chaîne. Retoune -1 si la première chaîne se classe alphabétiquement avant la seconde, 1 pour l'inverse, 0 pour la stricte égalité
nouv =chaine.repeat(n) retourne une nouvelle chaîne répétée n fois

Transformations des chaînes

a =123 ; ch =a.toString() et String(123) ; retournent la chaîne "123"

ch =chaine.trim() supprime les espaces en début et fin de chaîne

tab =chaine.split(dec) morcèle une chaîne (avec le découpeur dec) et retourne les morceaux dans un tableau (pour l'opération inverse: voir tableaux indexés)

"chaine".replace("hai","or") retourne une chaîne où la première occurrence hai est remplacée par or. Une façon en une ligne pour remplacer toutes les occurrences, :

nouv =texte.split("hai").join("or") ;

Pour mélanger les caractères d'une chaîne (début d'explication en cet endroit), j'ai rencontré au hasard du Net :

alert("abcdef".split("").sort(function() { return 0.5 -Math.random() ; }).join("")) ;

Mais le résultat n'est pas à la hauteur, voir cette page. Une autre méthode semble donner des résultats plus conformes à une distribution uniforme :

mel2 ="" ; dep ="abcdef" ;
for (k =0 ; k < 6 ; k++)
  {
  n =Math.floor(Math.random() * dep.length) ;
  mel2 +=dep.charAt(n) ;
  dep =dep.slice(0, n) +dep.slice(n +1) ;
  }

2.4 Expressions régulières ou rationnelles

Une expression rationnelle ou régulière est une façon d'exprimer un ensemble de chaînes possibles, il s'agit d'une extension des jokers ? et * respectivement utilisés pour décrire une lettre ou un ensemble de lettres dans la recherche de fichiers, voir par exemple cette page. En javascript, une expression régulière ou rationnelle est écrite entre barres obliques : /[0-9A-Za-z]{3}/ décrit toutes les chaînes formées de trois caractères qu'ils soient de majuscules, minuscules ou chiffres.

motif =RegExp("r[a-f]") ; crée un motif d'expression régulière ("r" suivi de "a" à "f"), qui vaut pour "ra", "rb", "rc", "rd", "re", "rf". motif =/r[a-f]/ est également valide avec FireFox. Attention : les expressions régulières sont sensibles à la casse (A n'est pas égal à a).

"reniera".match(motif) renvoie la première occurrence d'une sous-chaîne correspondant au motif, re en l'occurrence
chaine.search(/exp_reg/) retourne la position de la première sous-chaîne dans une chaîne (0 pour la première position, -1 si pas d'occurrence).

Pour remplacer toutes les chaînes dont le motif est une expression régulière, il faut passer par .split().join() :
chaine ="apparaître".split(/r[aeiou]/).join("-") ; retourne appa-ît- ("ra" et "re" sont remplacés).

Principaux motifs

. vaut pour tout caractère, même les espaces, mais pas les fins de ligne
\d vaut pour tout chiffre de 0 à 9
\D vaut pour tout caractère autre que les chiffres de 0 à 9
\w vaut pour tout caractère alphanumérique, lettres et chiffres
\W vaut pour tout autre caractères que les alphanumériques
\s vaut pour tous les séparateurs, comme les espaces, tabulations, fins de paragraphe et sauts de page
\S vaut pour tout autre caractère que les séparateurs

\n vaut pour une fin de paragraphe
\t vaut pour une tabulation
\f vaut pour un saut de feuille
\r vaut pour un retour en début de ligne
\v vaut pour une tabulation verticale

D'autres séparateurs :

^ pointe un début de phrase
$ pointe une fin de phrase
\b indique une limite de mot
\B indique une non-limite de mot

Il est possible de filtrer les caractère de façon plus subtile, en utilisant [].

[a-em-p] permet les minuscules non accentuées a b c d e (de a à e) et m n o p (de m à p)
[a-z^jpq] permet toutes les minuscules non accentuées, sauf j p q
[?.*] sont pris pour leur valeur littérales et ne doivent pas être échappés ; \b code le retour en arrière


Il est possible de quantifier les caractères de plusieurs façon.

? rend l'expression précédente facultative :s? permet qu'il y ait un s ou non
+ suivant un caractère le rend obligatoire au moins une fois
* suit un caractère qui peut être absent ou présent une ou plusieurs fois
{n} multiplie n fois le caractère précédent
{m,n} permet un nombre de fois entre m et n
{m,} permet au moins m fois le caractère
{,n} permet jusqu'à n fois le caractère

? qui suit les expressions précédentes inddique que le nombre de répétitions doit être la moins gourmande possible :

\w*\d appliqué sur H2SO4 considère l'entièreté de l'expression (\w* prend H2SO et \d prend 4)
\w*?\d appliqué sur H2SO4 considère le minimum possible de l'expression (\w*? ne prend que H et \d prend 2)

Pour coder les caractères d'encodage . ? + ^ * / \ ( ) [ ] { } il faut les échapper, les faire précéder de l'antislash \ . Pour coder l'antislash, il faut le redoubler \\

2.5 Tableaux indexés

Un tableau est une suite indexée d'éléments divers : chaînes, nombres et même tableaux peuvent y cohabiter : cela ressemble plus à l'objet list du python qu'aux tableaux du langage C. On déclare un tableau de n (facultatifs) éléments avec

var tabl =new Array(n) ;
autre =[3, 5, 6, 7, 8] ;

Array.isArray(tabl) retourne true si tabl est un tableau indexé

On remplit un tableau indexé avec tabl[indice] =valeur et on récupère une de ses valeurs avec variable =tabl[indice]. Le premier élément est à l'indice 0 : un tableau de 14 éléments a des indices de 0 à 13.

tabl.length retourne le nombre d'éléments du tableau indexé tabl

Notes : l'appel à un index non défini retourne undefined.

Il est possible de parcourir un tableau indexé de deux façons :

tabl.includes(elem) est vrai si elem est trouvé dans tabl.

indexOf(val) pointe l'index de la première occurrence d'une valeur dans un tableau indexé :

couverts =["cuiller", "couteau", "fourchette"] ;
n =couverts.indexOf("couteau") ;

couverts.indexOf("couteau", 2) permet de ne commencer qu'à l'index 2

Transformations de types

tabl =chaine.split(ch) morcèle une chaîne (avec le découpeur ch) et retourne les morceaux dans un tableau indexé
chaine =tabl.join("-") joint les éléments d'un tableau en une chaîne, les éléments étant séparés ici par un trait d'union, une virgule par défaut, "" pour rien. Cela fonctionne avec un tableau de nombres, convertis en chaînes

Parties de tableaux indexés

tabl.push(elem1, elem2…) ajoute un ou plusieurs éléments à la fin d'un tableau. Un tableau ajouté est considéré comme un élément et non comme la suite de ses éléments.
tabl.append(tablautre) ajoute un à un les éléments d'un autre tableau à la fin du premier
tabl.unshift(elem1, elem2…) ajoute un ou plusieurs élément(s) au début du tableau.

elem =tabl.pop() exprime le dernier élément en le retirant du tableau
elem =tabl.shift() exprime le premier élément en le retirant du tableau

tabl[0] contient le premier élément d'un tableau
tabl[tabl.length -1] contient le dernier élément d'un tableau

nv =anc.slice(debut, fin) copie la partie de tableau entre les index debut et fin -1 dans un nouveau (l'entièreté si debut et fin ne sont pas précisés).

elems =tabl.splice(ind, n) exprime n éléments à partir de l'index ind en les retirant du tableau initial. Les index négatifs sont autorisés (-1 est le dernier rang, -2 l'avant-dernier).
elems =tabl.splice(ind, n, elem1, elem2…) exprime n éléments à partir de l'index ind en les retirant du tableau initial, en y ajoutant les éléments précisés

Tri d'un tableau indexé

tabl.sort() trie un tableau par ordre alphabétique, que les éléments soient des chaînes ou des nombres : 43 précède 5 ! Cette fonction s'applique directement sur le tableau, il n'est pas nécessaire de récupérer le résultat dans une variable.

Pour un tri numérique, il faut faire appel à une fonction utilisateur qui définit la hiérarchie entre les nombres. La fonction nmr() ci-dessous indique à la méthode sort() que pour tout a et b appartenant au tableau, si a -b est négatif, c'est que a est plus petit que b, et donc avant b :

function nmr(a, b)
  { return a -b ; }
tabl.sort(nmr)

Nv 2023.03.15 Cette fonction de tri «utilisateur» permet de mélanger un tableau indexé si l'on rend le critère de tri aléatoire (Math.random() renvoie une valeur entre 0 et 0.99999…, le résultat de la fonction anonyme sera au hasard positif ou négatif) :

alert(new Array("a", "b", "c", "d", "e").sort(function() { return 0.5 -Math.random() ; })) ;

tabl.reverse() inverse l'ordre des éléments d'un tableau. Cette fonction s'applique directement sur le tableau, il ne faut pas récupérer le résultat dans une variable.

Nv 2023.01.17 Notez que le tri de chaînes est dans alors basé sur le tri Unicode, liste dans laquelle les lettres accentuées viennent après autres. Pour un tri semblable à celui du dictionnaire, la fonction de tri devient :

function locale(x, y)
  {
  return x.localeCompare(y) ;
  }

Le résultat dépendra de la locale sélectionnée sur le système, qui peut varier selon l'internaute.

Tableaux à plusieurs dimensions

Il faut initialiser chaque élément comme un tableau. Les éléments sont accessibles par tableau[x][y]. Pour un tableau de cinq sous-tableaux :

tabl = new Array(5);
tabl[0] =new Array(3);
tabl[1] =new Array(3);
tabl[2] =new Array(3);
tabl[3] =new Array(3);
tabl[4] =new Array(3);
tabl[1][2] =valeur;

Remarques :

2.6 Tableaux associatifs

Un tableau associatif n'utilise pas d'index (nombre entier) mais des clés, sous forme de chaînes, pour désigner les valeurs qu'il contient :

assoc ={"zero" : "GA", "un" : "BU", "deux" : "ZO", "trois" : "MEU" };
val =assoc["zero"] // val vaut GA

Il est possible de déclarer et remplir le tableau de cette façon :

assoc ={}; assoc["cent"] ="hundred" ; assoc["mille"] ="thousand" ;

L'ordre n'y est plus garanti. D'autre part, l'association d'une valeur à une clé déjà existante remplace l'ancienne valeur. Il est possible d'utiliser un nombre comme clé, mais il sera considéré comme une chaîne : attention aux synonymes, pour les clés, 1 == "1" !

assoc = Object.assign({ 0 : "zéro" }, assoc1, assoc2) permet de fusionner deux tableaux associatif (et même d'ajouter des éléments)

Dans l'exemple suivant, la boucle boucle parcourt les clés, (i aura pour valeurs successives les chaînes utilisées comme clé), assoc[i] contenant à chaque fois la valeur associée.

assoc ={ "un" : "ek", "deux" : "do", "trois" : "tin" }
for(i in assoc) { cle =i ; valeur =assoc[i] ; }

Note : la boucle for(i of assoc) ne fonctionne pas avec les tableaux associatifs.

Pour des raisons propres à JavaScript (les «objets» n'y ont pas de dimension), un tableau associatif n'a pas de longueur. Pour compter le nombre de paires clé/valeur qu'il contient, il faut recourir à cette boucle :

var n =0 ; for (var i in assoc) { n++; }

cles =Object.keys(assoc)) crée le tableau indexé cles contenant les clés du tableau associatif assoc
vals =Object.keys(assoc)) crée le tableau indexé vals contenant les valeurs du tableau associatif assoc

2.7 Tri d'une base de données Nv 2023.01.17

Une base de données consiste en un ensemble de lignes, chacune représentant un enregistrement (ou «individu» au sens large) contenant plusieurs types de donnée (les colonnes). En javascript, ces lignes sont les éléments d'un tableau indexé dont chaque cellule est un tableau associatif contenant les mêmes clés (par exemple prenom, age, rue...).

data =[
  { pren:"Claire", age:45, rue:"Av. des Roses, 13", cp:"42440", munic:"Noirétable" },
  { pren:"Pierre", age:54, rue:"Rue du Champ, 42", cp:"38360", munic:"Engins" },
  { pren:"Anne", age:39, rue:"Chemin du Halage, 23", cp:"07140", munic:"Les Vans" },
  ] ;

Pour classer ce tableau par ordre alphabétique ou numérique, il faut prévoir un algorithme de tri, qui sera à préciser lors de l'appel de la méthode sort() de javascript :

function triPren(x, y) // algorithme de tri sur le prénom
  {
  return ((x.pren < y.pren) ? 1 : ((x.pren > y.pren) ? -1  : 0)) ;
  }

Et finalement, on trie la base de données :

data.sort(triPren) ;

Voici le code intégré dans une page prête à l'emploi :

<!doctype html>
<html><head>
<meta charset="utf-8">

<script>
function triPren(x, y) // algorithme de tri pour sort(), sur le prénom
  {
  return ((x.pren < y.pren) ? -1 : ((x.pren > y.pren) ? 1  : 0)) ;
  }

data =[
  { pren:"Claire", age:45, rue:"Av. des Roses, 13", cp:"42440", munic:"Noirétable" },
  { pren:"Pierre", age:42, rue:"Rue du Champ, 42", cp:"38360", munic:"Engins" },
  { pren:"Anne", age:39, rue:"Chemin du Halage, 23", cp:"07140", munic:"Les Vans" },
  ] ;

function tri()
  {
  data.sort(triPren) ;
  sortie ="" ;
  for (x of data)
    {
    sortie =sortie +"<tr><th>" +x.pren +"<td>" +x.age +"<td>" +x.rue +"<td>" +x.cp +"<td>" +x.munic ;
    }
  document.getElementById("tab").innerHTML =sortie ;
  }
</script>

</head><body onLoad="tri()">

<p>
Tableau trié par selon les prénoms
<table id="tab">
</table>

</body></html>

Il est possible de définir plusieurs fonctions de tri (triAge(), triCp(), triMunic()) où la clé de tri est changée (remplacer pren par age, cp, munic).

3. Structures

Les structures permettent l'exécution de partie de code sous condition. De façon générale, une structure a pour forme motcle(condition) { code }

3.1 Comparateurs

Les comparateurs servent à tester des (in)égalités afin de permettre au script de s'orienter. On les utilise dont surtout dans les conditions et boucles.

< strictement inférieur   <= inférieur ou égal   > strictement supérieur   >= supérieur ou égal

== même valeur, même si les types diffèrent : "1" ==1 renvoie true ; à ne pas confondre avec l'affection =
!= différent; teste les valeurs, pas les types : "1" !=1 renvoie false
=== strictement égal, même valeur et même type : "1" ===1 renvoie false
!== teste l'inégalité de valeur ou de type : "1" !==1 renvoie true

Les chaînes possèdent leurs méthodes semblables aux comparateurs.

3.2 Conditions

if(condition) { … } else if(…) { … } else { … } enchaînement de conditions. Au cas où la condition du if n'est pas rencontrée, la condition d'un ou plusieurs else if est évaluée, et en dernier ressort, le code après else est appliqué. Ni else if ni else n'est obligatoire.

Il est possible de composer des conditions avec le «et» ou le «ou» logique :

(cdt1 && cdt2) // est vrai si les deux conditions sont en même temps vraies
(cdt1 || cdt2) // est vrai si au moins l'une des deux conditions est vraie

(…) ? … : … ; est la condition rapide héritée du langage C :

(expr. logique) ? code_si_vrai : code_si_faux

3.3 Boucles

continue retourne en début de boucle, à l'itération suivante, normalement utilisée dans une condition
break sort directement de la boucle

while(condition) { … } permet l'exécution d'une partie de code à condition et tant que la condition définie est vraie.

do { … } while(cond) parcourt au moins une fois la boucle et la réitérera tant que la condition est vraie (correspond au REPEAT … UNTIL cond des BASIC)

for(init ; cond ; iter) { … } réitère une portion de code tant que la condition est vraie. init initialise une ou plusieurs variable(s) séparées par des virgules cond est la condition d'itération, et iter une opération sur la ou les variable(s) après chaque itération (souvent une incrémentation)

for(var in tableau) { … } parcourt un tableau

Dans les deux cas, tableau[var] accède à la valeur.

for(var of tableau) { … } parcourt dans l'ordre un tableau indexé (uniquement)

switch permet le choix d'un code selon les valeurs n1, n2… correspondent à la variable :

switch(variable)
  {
  case n1: code; break;
  case n2: code; break;
   …
  default: code
  }

3.4 Fonctions Rév 2023.01.17

Une fonction est une portion de code appelable de n'importe où et capable de retourner une valeur. La forme générique est la suivante :

function carre(x)
  {
  return x *x ;
  }

carre est un nom au choix, x est la variable de réception d'une valeur. Il peut y en avoir plusieurs. return stoppe l'exécution de la fonction et retourne une valeur, la valeur de réception multipliée par elle-même dans cet exemple. On appelle une fonction tout simplement par son nom (ici visualisable avec alert()) :

alert(carré(6)) ;

Pour résumer, quelle que soit la valeur particulière envoyée par carre() dans le script,function carre(x) { return x *x ; } renvoie le carré de cette valeur. L'intérêt Ce n'est peut-être pas bien grand pour une fonction si triviale, mais peu raccourcir un script ou le clarifier si la fonction est un peu plus complexe.

Attention : la variable de réception ( x entre parenthèss) est locale, c'est-à-dire qu'elle n'a de valeur qu'à l'intérieur de la fonction et qu'elle n'interfère pas avec la valeur d'une autre variable du script qui s'appellerait également x (elle reste invisible dans le reste du script).

Par contre, la déclaration w =99 ; dans une fonction a une portée globale : elle interférera avec une variable w du reste du script et pourra y être mobilisée. Pour déclarer une variable locale dans une fonction, il est nécessaire de la réserver de cette manière : var w =43

Une fonction peut en appeler une autre. Contrairement à certains langages de script, la fonction appelé peut être située après l'appel.

Une fonction peut même s'appeler elle-même, mais pour pour ne pas boucler indéfiniment, il est nécessaire de prévoir une condition de sortie. L'exemple le plus courant est la définition de la factorielle («factorielle de 7» est 7 *6 *5 *4 *3 *2 *1, soit 5040) :

function fact(x)
  {
  if (x > 1) // tant que x est supérieur à 1
    {
    return x *fact(x -1) ; // on le mutiplie à la factorielle de x -1
    }
  return 1 ; // jusqu'à ce qu'on arrive à 1, ou si l'entier de départ est 0
  }
function essai()
  {
  alert(fact(7)) ;
  }

3.5 Erreurs

À développer…

try { essai } catch { code alternatif } finally { toujours }
throw génère une erreur
debugger permet l'appel d'une fonction de débuggage

4. Interactions

4.1 Boîtes de dialogue

Le préfixe window. n'est pas obligatoire.

window.alert("") ouvre une boîte délivrant un message, éventuellement issu d'un code

<script>
function jdm() { a =new Date(); alert(a.getDate());}
</script>
<p>
<span onMouseover="jdm();">Jour du mois (à survoler)</span>

confirm() permet de récupérer false ou true selon le bouton choisi ([Annuler] ou [OK])

tf =window.confirm("Red?");
alert(tf);

prompt() permet à l'utilisateur d'éditer un champ, récupéré dans une variable

quest =window.prompt("What's your quest?");
quest =window.prompt("What's your quest?", "Graal"); // champ prérempli

cpt =setTimeout("votre_fonction()", ms) temporise (en millisecondes) un appel à une fonction
clearTimeout(cpt) permet d'arrêter le temporisateur et donc le déclenchement de la fonction (à lier à un événement)

4.2 Modification de contenu

texte =document.getElementById("id43").innerHTML; permet de lire ce que la balise désignée par son identifiant affiche actuellement.

document.getElementById("").innerHTML =""; remplace le contenu de la balise dont l'identifiant est précisé, par ce qui suit le signe =. Pour une balise HTML dont l'id est id43 :

document.getElementById("id43").innerHTML ="Vous avé gagnez $468.000 à la lotterie Micro-soft";

document.write(code); remplace la page courante par le contenu de la variable code.

4.3 Modification d'attribut

À développer…

getAttribute() permet de lire un attribut d'une balise particulière :

var =document.getElementById("tungstene").getAttribute("style") ;

setAttribute() permet de modifier un attribut d'un élément. Pour une seule cible :

document.getElementById("mon_canevas").setAttribute("height", "430") ;

clientHeight, clientWidth, clientTop, clientLeft retournent la hauteur, la largeur, le décalage à gauche, le décalage en haut d'une surface visible (pas ce qui est caché en cas d'ascenseur).

4.4 Formulaires

Il est possible de tester ou modifier des formulaires ou du contenu ou des attributs de balise.

Récupérer une valeur

On récupère une donnée d'un formulaire par l'id du widget (textarea, menu déroulant, input…) :

ma_variable =document.getElementById("mon_id").value;

Dans le cas d'un menu déroulant, il peut être intéressant de préciser des valeurs différentes de ce qui y apparaît ("1" pour "un"…). Dans la partie HTML :

<select id="mon_menu">
<option value="1">Un</option>
<option value="10">Cent</option>
<option value="1000">Mille</option>
</select>

Dans la partie script, il sera possible de convertir la valeur (chaîne) en nombre :

nombre =document.getElementById("mon_menu").value ;
nbr =Number.parseInt(nombre) ;

Cases à cocher

Pour récupérer la valeur "coché" ou non d'un checkbox d'un formulaire dont le name est "pedigree" et dont le name du checkbox est "membre"  :

bool1 =document.forms.pedigree.membre.checked ;

Cette valeur est souvent testée dans une condition :

if(bool1 ==true)
  { … }

Pour récupérer la valeur "coché" ou non d'un radiobutton dont le name (multiple) est couleurs :

booleen =document.getElementsByName("couleurs")[1].checked

Attention! Elements prend ici toujours s puisque les radioboutons ne s'utilisent pas seuls. Cette méthode renvoie en fait un tableau de valeurs dont il faut préciser l'indice du bouton à tester. Pour n radioboutons, les indices vont de 0 à n-1, selon l'ordre de la page HTML.

Il est possible de modifier l'état d'un bouton de formulaire avec du code. Dans les deux exemples qui suivent, il faut survoler un texte pour changer l'état du bouton, ce qui est moins pratique que simplement cliquer dans le petit carré (checkbox) ou le petit rond (radiobutton), mais c'est pour montrer que le clic n'est pas nécessaire.

document.forms.id_formulaire.id_checkbox.checked =true force l'activation d'une boîte à cocher (false pour désactiver) :

<script>
function yeap()
  { document.forms.oiseau.choix.checked =true; }
</script>

<form id="oiseau">
<input type="checkbox" id="choix">Ibis
</form>
<p>
<span onMouseover="yeap();"><b>Survoler ici</b></span>

document.forms.id_formulaire.name_radio[n].checked =true force l'activation d'un radiobouton particulier, ce qui désactive les autres :

L'exemple suivant permet de ramener le checked sur le second item ([1]!) en survolant un mot. Le formulaire est identifié comme oiseau et les radioboutons ont choix pour nom. document.forms est ici facultatif.

<script>
function yeap()
  { document.forms.oiseau.choix[1].checked =true; }
<script>

<form id="oiseau">
<input type="radio" name="choix" checked="checked">Ibis
<input type="radio" name="choix">Pie
<input type="radio" name="choix">Hibou
</form>
<p>
<span onMouseover="yeap();"><b>Survoler ici</b></span>

4.5 Événements

Les événements envoient vers du code ou une fonction, sous la forme d'un attribut de balise. Pour l'événement imaginaire onEvent :

<p onEvent="code;">

ou

<p onEvent="faire();">

Voici les événements possibles (insensible à la casse) :

onClick clic sur un lien ou élément cliquable

onMouseOver survol d'un élément par la souris
onMouseOut abandon du survol de l'élément

onLoad lors du chargement de la page HTML contenant le script
onUnload lors de l'abandon de la page HTML contenant le script

onKeyPress lorsqu'une touche de clavier est appuyée lors de l'édition d'un formulaire
onKeyUp lorsqu'une touche du clavier est relâchée lors de l'édition d'un formulaire

onFocus lors de l'activation d'un élément de formulaire (survol?)
onSelect lors de la sélection d'un champ de formulaire
onBlur lors de l'abandon d'un champ de formulaire
onChange lors de la modification d'un formulaire
onSubmit lors du clic d'un bouton «Submit» (envoi de formulaire)

onCut [Ctrl-x] ou l'équivalent à la souris
onCopy [Ctrl-c] ou l'équivalent à la souris
onPaste [Ctrl-v] ou l'équivalent à la souris

onDragStart début de tiré de zone en inverse vidéo
onDrop fin de tiré de cette zone

Événement automatique cadencé

Deux ou trois fonctions suffisent pour que la page exécute un code tous les n milli-secondes :

function faire()
  {
  // ce qui doit être fait toutes les demi-secondes ;
  }
function samsara()
  {
  iv =window.setInterval("faire()", 500) ;
  }
function nirvana()
  {
  window.clearInterval(iv);
  }

Remarque : l'intervalle temps entre deux appels de la fonction étant augmenté du temps de traitement de la fonction, un appel toutes les mille milli-secondes tend à retarder un compteur de secondes. Le seul moyen sûr d'avoir des secondes justes est de diminuer la période (100 millisecondes devraient suffire) avant l'appel et de vérifier que le système est passé à la seconde suivante, voir Temps.

C. Autres classes

C.1 Temps

nd =new Date(); renvoie une chaîne temporelle sous la forme "Fri Feb 29 08:43:43 1996". À partir de la variable créée, il est possible d'en extraire les informations suivante :

nd.getYear(); l'année, à partir de 1900 (116 pour 2016)
nd.getMonth(); l'heure, 0 à 11
nd.getDate(); le jour du mois, de 1 à 31
nd.getDay(); jour de la semaine

nd.getHours(); l'heure, de 0 à 23
nd.getMinutes(); la minute, de 0 et 59
nd.getSeconds(); la seconde, de 0 et 59

nd.getTime(); nombre de millisecondes depuis le 1 janvier 1970 à 00:00:00
nd.getTimezoneOffset(); nombre de minutes entre heure locale et UT

nd.toGMTString(); retourne une chaîne décrivant la date et l'heure en temps universel (UT, et non GMT!) :

Sun, 19 Jun 2016 13:06:57 GMT

nd.toLocaleString() retourne une chaîne décrivant la date (sans le jour de la semaine) et l'heure locale :

19/06/2016 à 15:07:42

Mettre le jour et l'heure

nd.setYear(x); ajuste l'année, à partir de 1900 (116 pour 2016)
nd.setMonth(x); ajuste le mois, de 0 et 11
nd.setDate(x); ajuste le jour, de 1 à 31

nd.setHours(x); ajuste l'heure, de 0 et 23
nd.setMinutes(x); ajuste les minutes, de 0 et 59
nd.setSeconds(x); ajuste les secondes, de 0 et 59

nd.setTime(x); ajuste l'heure selon le nombre de millisecondes écoulées depuis le 1 janvier 1970 à 00:00:00

C.2 Mathématiques

Constantes

Math.E retourne e, la constante d'Euler: 2.718…
Math.LN2 retourne le logarithme népérien de 2: 0.693
Math.LN10 retourne le logarithme népérien de 10: 2.302…
Math.LOG2E retourne le logarithme en base 2 de e: 1.442…
Math.LOG10E retourne le logarithme en base 10 de e: 0.434)
Math.SQRT1_2 retourne la racine carrée d'1/2: 0.707…
Math.SQRT2 retourne la racine carrée de 2 : 1.414…

Fonctions

Math.abs() retourne la valeur absolue
Math.round() arrondit un nombre à l'unité près
Math.floor() retourne l'entier inférieure ou égal
Math.ceil() retourne l'entier supérieur ou égal
Math.min() retourne la valeur la plus basse de la série
Math.max() retourne la valeur la plus haute de la série

Math.exp(x) retourne la valeur de ex
Math.pow(x,y) retourne la valeur de x à la puissance y
Math.log() retourne le logarithme naturel (en base e)
Math.sqrt() retourne la racine carrée

Math.random() retourne un nombre pseudo-aléatoire de 16 décimales, du segment [0,1[. Pour simuler le lancer d'une pièce de monnaie et d'un dé à six faces :

pf =Math.round(Math.random()); // retourne 0 ou 1
de =Math.floor(Math.random()*6) +1; // retourne 1, 2, 3, 4, 5 ou 6

Trigonométrie

Math.PI retoune PI : 3.14159…

L'argument doit être exprimé en radian. Pour transformer un angle exprimé en degrés en valeur en radian :

angle =Math.PI *degre /180

Math.sin() retourne le sinus d'un angle
Math.cos() retourne le cosinus d'un angle
Math.tan() retourne la tangente d'un angle

Rappelons que l'argument d'asin() et acos() est borné par -1 et 1 :

Math.asin() retourne l'arcsinus d'une valeur
Math.acos() retourne l'arccosinus d'une valeur

Math.atan() retourne l'arctangente ()
Math.atan2(dy, dx) retourne l'angle d'une pente ordonnée/abscisse).

G. Graphisme

Attention : pour le reste de la section Graphisme, ce qui suit est sous-entendu!

1. Pour afficher un graphisme il faut qu'une balise soit désignée pour le réceptionner

<canvas id="canevas" width="400" height="300" style="border:1px solid gray;">
La balise canvas n'est pas reconnu par le navigateur!
</canvas>

2. Dans le script même, avant de commencer l'affichage, au moins les deux premières lignes doivent figurer :

lieu =document.getElementById("canevas");
ici =lieu.getContext("2d");
ici.clearRect(0, 0, lieu.width, lieu.height);

ici.fillColor ="gray"; colore un affichage; plus finement avec "#RRVVBB"
ici.fillStyle ="red"; colore un remplissage; plus finement avec "#RRVVBB"

Pour localiser le pointeur graphique (souris) sur un objet canvas initialisé avec la variable canevas, utiliser

cnv =canevas.getBoundingClientRect() ;
x =Math.floor(event.clientX -cnv.left) ;
y =Math.floor(event.clientY -cnv.top) ;

G.1 Texte graphique

ici est expliqué ici.

ici.fillText("Votre texte", posx, posy) dessine un texte rempli
ici.strokeText("Votre texte", posx, posy) dessine un texte en trait contour

ici.font ="20px Arial bold"; retourne ou spécifie les paramètres de la fonte
ici.textAlign retourne ou spécifie la position du texte par rapport à ses coordonnées : "center", "justify", "start" (ou "left"), "end" (ou "right")
ici.textBaseline retourne ou spécifie la baseline utilisée, à savoir un décalage vertical par rapport à l'ordonnée d'un texte. Les valeurs du plus haut au plus bas sont : "top", "hanging", "middle", "alphabetic" (par défaut), "ideographic" et "bottom"
ici.measureText("Votre texte").width retourne la largeur d'un texte selon les paramètres actuels de font, ce qui est utile pour

G.2 Lignes

ici est expliqué ici.

ici.beginPath() commence un chemin
ici.lineTo() ajoute un point au chemin (il en faut au moins deux)
ici.moveTo() (facultatif) lève le crayon pour continuer le chemin plus loin
ici.closePath() (facultatif) sert à refermer le chemin en un circuit
ici.stroke() trace effectivement le chemin défini
ici.fill() remplit la figure définie par un chemin (en fait un circuit, même si closePath() n'est pas utilisé)

Styles de ligne

ici est expliqué ici.

ici.strokeStyle retourne ou définit la couleur, le gradient ou le style de la ligne
ici.lineWidth retourne ou définit la largeur de ligne
ici.lineCap retourne ou définit le style des fins de ligne : "butt" (la ligne s'arrête au point défini, par défaut), "square" (demi-largeur en plus) ou "round" (demi-rond ajouté)
ici.lineJoin retourne ou définit le type d'angle formé par une ligne brisée : "round" (arrondi), "miter" (pointu) ou "bevel" (coupé)
ici.miterLimit retourne ou définit la longueur maximale pour ici.lineJoin ="miter" : pour une ligne ayant une certaine grosseur, la pointe d'un angle très aigu risque de se retrouver très loin du point de jonction du milieu des deux segments. n semble être le rapport limite entre d(jonction,pointe) et la demi-largeur de la ligne : au delà, basculement en mode "bevel" (10 par défaut).

G.3 Courbes

ici est expliqué ici.

arc() crée un (arc de) cercle de centre (posX, posY) et de rayon r, le cercle étant défini avec un début 0 et une fin Math.PI*2

ici.beginPath();
posX =150; posY =150; r =70; deg1 =168; deg2 =340;
pi =Math.PI; deb =pi *deg1 /180 ; fin =pi *deg2 /180;
ici.beginPath();
ici.arc(posX, posY, r, deb, fin);
ici.fill();

Notes :

arcTo() trace un arc de cercle de rayon r tangeant aux deux droites se croisant au point (x1, y1) et contenant respectivement les points (x2, y2) et (x0, y0). Cet arc de cercle est prolongé par le segment entre le point (x0, y0) et l'arc de cercle :

ici.beginPath();
ici.moveTo(x0,y0);
ici.arcTo(x1, y1, x2, y2, r);
ici.stroke();

ellipse(cx, cy, ga, pa, or ,d , f) crée une ellipse orientatable, dont (cx, cy) est le centre, ga et pa les grand et petit demi-axes, or l'orientation en radian du grand axe, d et f le début et la fin de la courbe (0 / Math.PI*2 pour l'entièreté). On peut ajouter true en dernier paramètre pour le sens trigonométrique du tracé.

quadraticCurveTo() crée une courbe Bézier quadratique, où (dx, dy) et (fx, fy) sont les points de début et fin de courbe, (px, py) est le point de contrôle :

ici.beginPath();
ici.moveTo(dx,dy);
ici.quadraticCurveTo(px, py, fx, fy);
ici.stroke();

bezierCurveTo() crée une courbe Bézier cubique, où (dx, dy) et (fx, fy) sont les points de début et fin de courbe, (p1x, p1y) et (p2x, p2y) sont les points de contrôle :

ici.beginPath();
ici.moveTo(dx, dy);
ici.bezierCurveTo(p1x, p1y, p2x, p2y, fx, fy);
ici.stroke();

isPointInPath() retourne true si le point spécifié appartient au chemin, false sinon

G.4 Rectangles

ici est expliqué ici.

ici.strokeRect(x, y, w, h) trace un rectangle non rempli (coordonnées du point supérieur gauche, largeur, hauteur)
ici.fillRect(x, y, w, h) trace un rectangle rempli (coordonnées du point supérieur gauche, largeur, hauteur)
ici.clearRect(x, y, w, h) efface les pixels d'une surface rectangulaire (coordonnées du point supérieur gauche, largeur, hauteur)

ici.clip() clippe une région du canvas : la dernière figure tracée délimite l'espace des prochains affichages. Pour pouvoir revenir à la possiblilité d'afficher sur tout le canevas, il faut préalablement sauver l'état du contexte avec ici.save() et utiliser ici.restore() lorsque l'on veut supprimer les effets de clip(). Page html complète :

<html><head>
<script>
function texte() {
canevas =document.getElementById("ici") ;
ici =canevas.getContext("2d") ;
ici.rect(30, 70, 160, 60) ;
ici.stroke() ;
ici.font ="30px Arial" ;
ici.save() ; // sauvegarde le contexte
ici.clip() ;
ici.fillStyle ="red" ;
ici.fillText("V'là l'bon vent", 25, 85) ; // affichage tronqué
ici.restore() ; // restaure le contexte, sans la couleur rouge ni clip
ici.fillText("V'là l'joli vent", 25, 135) ; // affichage entier
}
</script>
</head><body onLoad="texte();">
<canvas id="ici" width="300" height="300" style="border:1px solid #b05">
</canvas>
</body></html>

G.5 Effets graphiques

ici est expliqué ici.

Ombre

Disponibles pour l'affichage de lignes, textes et figures géométriques :

ici.shadowColor retourne ou spécifie la couleur de l'ombre
ici.shadowBlur retourne ou spécifie en pixels le niveau de diffusion de l'ombre (0 pour une ombre nette)
ici.shadowOffsetX retourne ou spécifie le décalage horizontal à droite de l'ombre
ici.shadowOffsetY retourne ou spécifie le décalage vertical vers le bas de l'ombre

Gradient linéaire

grad =ici.createLinearGradient(x1, y1, x2, y1) crée un gradient linéaire du point (x1,y1) à (x2, y2)
grad.addColorStop(pc, "couleur") organise les plages (pourcentage de la longueur) et les couleurs

Entre les points (10, 20) et (300, 200), dégradé du vert le cyan du début à 30% de la surface, puis du blanc au violet de 30 à 100% de la surface :

grad =ici.createLinearGradient(10, 20, 300, 200);
grad.addColorStop(0, "green") ;
grad.addColorStop(0.3, "cyan") ;
grad.addColorStop(0.3, "white") ;
grad.addColorStop(1, "purple") ;
ici.fillStyle =grad ;
ici.fillRect(10, 20, 300, 200) ; // mêmes dimensions pour bien voir l'entièreté du dégradé

Gradient radial

ici.createRadialGradient(x1,y1,r1,x2,y2,r2) définit deux cercles pour un gradient radial
grad.addColorStop(pc,"couleur") organise les plages (pourcentage de l'éloignement) et les couleurs

Pour un gradient radial du cercle de centre (100,100) et de rayon 20 au cercle de centre (125,125) et de rayon 125, avec un dégradé du bleu vers le vert (10%) puis vers le blanc sur (50%) et du blanc vers le violet pour les 40% qui restent :

grad =ici.createRadialGradient(100, 100, 20, 125, 125, 125);
grad.addColorStop(0, "blue");
grad.addColorStop(0.1, "green");
grad.addColorStop(0.6, "white");
grad.addColorStop(1, "purple");
ici.fillStyle =grad ;
ici.fillRect(0, 0, 300, 300);

(à suivre)