SVGround : cours SVG

Le DOM avec JavaScript

Introduction

Si vous êtes arrivés jusqu’ici, vous savez à peu près tout sur SVG. Ça tombe bien, c’est le but de ce cours !

Néanmoins, SVG ne peut pas tout faire à lui tout seul. C’est un langage de dessin vectoriel et il se débrouille plutôt bien pour ça, mais il lui manque l’interactivité.

Même si la partie animation permet un peu d’interactivité (démarrage au clic par exemple), certaines choses demeurent impossibles avec SVG seul. Par exemple, comment agrandir le rayon d’un cercle de 10 pixels à chaque clic ? C’est impossible avec SVG seul.

La solution se nomme ECMAScript, plus connu sous le nom de JavaScript. C’est un langage de script compatible avec SVG.

JavaScript est en fait plutôt vieux. Il a fait son apparition en 1995 et est très utilisé aujourd’hui avec HTML.

JavaScript permet de manipuler des document HTML ou XML, de répondre à des interactions avec l’utilisateur, de communiquer sur le réseau (le fameux AJAX), etc. Mais dans cette partie, nous allons exclusivement voir comment manipuler la structure d’un document SVG.

Et nous allons nous servir de DOM, l’acronyme de Document Object Model. DOM est un ensemble d’interfaces définies par le W3C, le consortium qui se charge de publier les normes du Web. Plus précisément nous allons étudier le DOM Level 2 (qui contrairement au DOM Level 1 peut gérer les espaces de noms).

Il faut savoir que JavaScript a une mauvaise réputation, et ce pour plusieurs raisons. La première est c’est un langage interprété qui a longtemps été lent (puisqu’interprété). Vu les progrès réalisés par les navigateurs, c’est un problème en passe d’être résolu. La seconde raison est que ce langage a été utilisé à tort et à travers et d’une manière très sale. Les navigateurs n’ont pas tous des implémentations compatibles et pour beaucoup JavaScript rime avec galère.

Point de cela ici : je vais vous apprendre à manipuler les documents XML (SVG, XHTML, XForms, XBL, MathML, etc.) via le DOM ce qui est la manière la plus propre (et d’ailleurs la seule) de faire. Le gros avantage, c’est que le DOM est utilisable dans quasiment tous les langages de programmation. Ainsi, ce que vous aller apprendre ici vous pourrez vous en servir en PHP, Perl, Java, … C’est un investissement que vous ne regretterez pas !

Cette partie n’est pas un tutoriel sur JavaScript. Si vous ne le connaissez pas, je vous conseille d’aller voir un ou deux tutorials sur le Web. Mais rassurez vous, c’est un langage très facile à apprendre. De plus, vous devez connaître les bases de la syntaxe XML. Si vous avez besoin de vous rafraîchir la mémoire, consulter ce tutorial sur XML.

Le modèle d’arbre

Le DOM représente le document XML en une structure arborescente. Cet arbre contient des nœuds, chaque nœud possède zéro, un ou plusieurs fils. Voilà, vous connaissez le DOM. Tout, absolument tout, est un nœud : éléments (on ne dit pas balise mais élément), attributs, commentaires, processing-instructions et texte pour les principaux. Une chose que vous devez intégrer est qu’un nœud élément n’est pas le texte qu’il contient. Ainsi dans le document XML suivant :

Du texte]]>

il y a deux nœuds et non un seul.

Prenons un document SVG basique et voyons comment il se décompose en arbre :

Document SVG de test Du texte en SVG ]]>

Ce document est simplifié à l’extrème. Voici comment il est représenté dans l’arborescence du DOM :

Voici l’arbre correspondant :
Arbre du document XML

Notez que l’ordre est important : le nœud texte "Du texte " précède le nœud tspan. C’est donc dans cet arbre que nous allons apprendre à naviguer, insérer et supprimer des éléments, modifier les attributs, etc.

Mais pour commencer, où met-on le script ? C’est très simple : on utilise l’élément script. On peut inclure le script directement entre les deux balises où utiliser un script d’un autre fichier. Nous avons pris l’habitude de tout séparer et nous allons donc continuer ainsi. Le fichier JavaScript en question est pointé par l’attribut xlink:href.

getElementById

La manière la plus simple et la plus utilisée pour se rendre à un élément précis du document est d’utiliser getElementById(identifiant). Cette méthode va tout simplement retourner l’élément qui à l’identifiant indiqué (via l’attribut id). Essayons avec ette ellipse :

<]]> < getElementById avec le DOM ]]>
getElementById avec le DOM

À présent, cliquez sur le dessin SVG : il doit apparaître [object SVGEllipseElement] ou quelque chose comme ça.

Regardons le script de plus près. Laissons tomber la première ligne pour le moment, nous y reviendrons plus tard. Elle est juste chargée de lancer la fonction myAlert lorsqu’on clique sur le dessin SVG. La première chose intéressante est que nous n’avons pas utilisé getElementById mais document.getElementById. document est un objet un peu spécial puisque vous y avez accès quand vous voulez ! Il représente le document par lequel le script a été appelé. C’est donc souvent par document que tout commence pour manipuler le DOM. Un détail important : document n’est pas la racine du document. C’est juste l’objet via lequel on va manipuler le document. La seconde chose intéressante c’est que la variable ellipse correspond maintenant à notre ellipse sur le dessin. Cette variable est en fait un objet : tout est objet avec DOM. Et comme tout objet, notre variable a des propriétés et des méthodes. Nous verrons lesquelles (enfin en partie).

getElementsByTagNameNS, espace de nom et liste de nœuds

Une des grandes différences entre le DOM niveau 1 et le DOM niveau 2 tient au fait que ce dernier sait gérer les espaces de noms (namespaces). Toutes les méthodes qui finissent par NS ont une sœur sans ce NS. Mais je vous en conjure, ne les utilisez pas : les espaces de noms sont vraiment une caractéristique fondamentale de XML alors ne les ignorons pas. Toutes ces méthodes qui finissent par NS prennent en paramètre la chaîne identifiant l’espace de nom (qui n’a rien à voir avec le préfixe qui lui peut être quelconque et variable). Pour ne pas s’embêter avec eux, le mieux et d’intégrer ceux qu’on utilise en début de document, dans des constantes.

Revenons à notre méthode. getElementsByTagNameNS(espace de nom, nom de l’élément) retourne la liste des éléments portant le nom indiqué dans l’espace de nom indiqué. Une liste ? Oui, il s’agit d’un objet (encore un) nommé NodeList et on ne peut accéder aux éléments qu’à travers cet objet.

Vous vous servirez souvent de cet objet. NodeList est simple à utiliser : il a une propriété, length, qui donne la taille de la liste et une méthode, item(i), qui renvoie le ième élément. Attention, ça commence à 0 et ça va jusqu’à length - 1.

Le bonus, c’est qu’on peut appeler cette méthode aussi bien sur document que sur n’importe quel élément du document. Dans ce dernier cas, seul les descendants correspondant à l’élément recherché seront sélectionnés.

<]]> < getElementsByTagNameNS avec le DOM ]]>
circleList = g.getElementsByTagNameNS(svgNS, 'circle'); // circleList est de type NodeList // parcourons le for(i=0;i<=circleList.length-1;i++) { alert(circleList.item(i)); } }]]>
getElementsByTagNameNS avec le DOM

Lors du clic, on a quatre fenêtres indiquant un [object SVGCircleElement], on n’a donc sélectionné que ceux qui sont dans le second g. Notez aussi qu’on aurait pu écrire directement document.getElementById('g2').getElementsByTagNameNS(svgNS, 'circle').

Descendre et remonter

Le DOM ayant un modèle d’arbre, on souhaite souvent descendre dans l’arborescence et, parfois, remonter.

Pour descendre, il y a trois possibilités :

Pour cet exemple, nous allons partir de la racine du document. On peut y accéder facilement via document.rootElement.

<]]> < Descendre et remonter dans le DOM ]]>
qui est le huitième fils de var g2 = root.childNodes.item(7); var firstCircle = g2.firstChild; alert('À présent sur le premier fils de g2 : ' + firstCircle); // on va sur le g imbriqué var g = g2.getElementsByTagNameNS(svgNS, 'g').item(0); alert('Le dernier nœud de ce est : ' + g.lastChild); }]]>
Descendre et remonter dans le DOM

Je vois déjà votre étonnement. Pourquoi g2 est il le huitième fils de svg ? Et pourquoi le premier fils de g2 n’est il pas de type SVGCircleElement ? Simplement parceque les espaces, tabulations et sauts à la ligne sont des nœuds textes ! Ce qui fait qu’il n’est finalement pas très facile de naviguer dans le document de cette manière…

Le premier nœud (firstChild) correspond donc au saut à la ligne plus la tabulation consécutive au tag <g id="g2">. Par contre, le dernier enfant du g imbriqué est bien le rectangle puisqu’il n’y a pas de texte entre les deux tags rect x="200" y="99" width="57" height="57" et </g>.

Il n’y a pas ce genre de soucis avec la remontée. on peut accéder au père (qui est unique) de chaque nœud avec parentNode. Voici un exemple :

<]]> < parentNode avec le DOM ]]>
parentNode avec le DOM

Le père de g2 est bien la racine svg du document.

Passer par les frères

Toutes les méthodes et propriétés utilisées précédemment renvoient null lorsque l’élément n’existe pas. Par exemple, document.getElementBy('identifiant inexistant') ou document.getElementsByTagNameNS(svgNS, 'circle').item(500) renvoient null dans le document précédent.

On peut accéder au frère suivant et au frère précédent grâce aux propriétés nextSibling et previousSibling. Les frères sont les nœuds qui se situent strictement au même niveau. On ne descend pas ni ne remonte avec ces propriétés. Ces deux propriétés renvoient null si on est, selon le cas, sur le dernier nœud ou sur le premier. Parcourons le second g du document précédent frère par frère.

<]]> < Parcourir les frères avec le DOM ]]>
Parcourir les frères avec le DOM

Manipuler les attributs

Maintenant que nous savons comment naviguer dans le document, modifions le. Et pour commencer, les attributs.

Pour obtenir la valeur d’un attribut sur un élément, on appelle la méthode getAttributeNS(espace de nom, nom de l’attribut). Pour changer sa valeur, on utilise setAttributeNS(espace de nom, nom de l’attribut, nouvelle valeur).

Attention, il y a une étrangeté avec le DOM à ce sujet. Si l’attribut qu’on modifie est dans le même espace de nom (donc est du même langage) que son élément, alors on doit mettre la valeur null pour son espace de nom. C’est le cas dans l’exemple suivant puisque les attributs modifiés le sont dans l’espace de nom de SVG.

<]]> < Modifier la valeurs des attributs ]]>
Modifier la valeurs des attributs

Grâce à ces deux méthodes, on peut quasiment tout faire sur les attributs, à part les supprimer. Pour supprimer un attribut, on utilise la méthode removeAttributeNS(espace de nom, nom de l’attribut) de l’élément qui le porte.

<]]> < Supprimer un attribut ]]>
Supprimer un attribut

La valeur par défaut de cx est 0 et c’est la valeur que prend l’attribut lorsqu’il est supprimé. Remarquer qu’on a aussi mis null comme espace de nom.

Manipuler les éléments

Créer des éléments

Avant d’insérer des éléments dans un document, il faut les créer. Et pour créer un élément, il faut le demander à document via la méthode createElementNS(espace de nom, nom de l’élément) qui va donc renoyer le nouvel élément. On peut ensuite ajouter des attributs avec setAttributeNS avant d’insérer le nouvel élément dans le document.

Insérer des éléments dans le documents

Il existe deux manières d’ajouter : insérer à la fin d’un élément et insérer avant un élément.

Pour ajouter à la fin d’un élément elt, on utilise la méthode elt.appendChild(élément à ajouter)elt est l’élément dans lequel on insère le nœud. Le nœud ajouté sera donc le dernier fils de elt.

Dans l’exemple suivant, cliquez pour insérer 100 cercles !

<]]> < Créer et insérer des nœuds avec appendChild ]]>
document.rootElement.appendChild(nouveauCercle); } }]]>
Créer et insérer des nœuds avec appendChild

Pour insérer un nœud à un élément elt, on utilise elt.insertBefore(élément à insérer, élément de référence) et le nœud s’ajoute comme frère avant le nœud de référence.

<]]> < Insérer des nœuds avec insertBefore ]]>
document.rootElement.insertBefore(nouveauCercle, document.rootElement.firstChild); insert = confirm('Ajouter un autre élément ?'); }while(insert); }]]>
Insérer des nœuds avec insertBefore

Quelle est la différence avec appendChild ? Les formes SVG étant dessinée dans l’ordre du document, les éléments insérés seront dessinés derrière ceux qui sont déjà là. Insérez-en plusieurs et vous le verrez.

Supprimer un élément

Pour terminer, il est possible de supprimer des éléments avec removeChild qui s’utilise sur le père de l’élément à supprimer (ce qui est un peu contraignant) : père.removeChild(élément à supprimer).

<]]> < Supprimer un élément ]]>
0) { // on sélectionne le premier cercle toRemove = cercles.item(0); // on sélectionne le père parentCircle = toRemove.parentNode; // on supprime le cercle parentCircle.removeChild(toRemove); } }]]>
Supprimer un élément

Les nœuds de texte

Il ne manque plus qu’une chose pour pouvoir manipuler un document XML comme on veut : la gestion des nœuds de texte dans les éléments.

Un nœud texte a deux propriétés : data et length. Grâce à data on peut obtenir et modifier le texte du nœud. Avec length on obtient le nombre de lettres du nœud.

<]]> < Modification de texte SVGround ]]>
) // on veut le nœud texte donc le premier fils de texte = texte.firstChild; alert('Texte : ' + texte.data + '\nLongueur : '+texte.length); // modification du texte texte.data = 'Le SVG c’est kewl'; alert('Texte : ' + texte.data + '\nLongueur : '+texte.length); }]]>
Modification de texte

Parfois vous aurez besoin de créer des nœuds texte. En effet, dans l’exemple précédent, on a pu manipuler le nœud texte parcequ’il existait déjà. Mais si ce n’est pas le cas, il faut le créer et l’ajouter à l’élément.

Comme pour la création d’élément, la création d’un nouveau nœud texte se fait via document et la méthode createTextNode('Nouveau texte') qui renvoie le nœud texte.

Je vous propose de créer et d’ajouter a un document SVG le texte suivant : SVGround tout sur SVG]]>. Les différentes étapes pour obtenir ceci sont :

<]]> < Création de nœuds de texte ]]>
Création de nœuds de texte

Avec de la méthode, vous ne ferez normalement pas d’erreur. Pour débugger, je vous conseille d’utiliser la console d’erreur de Firefox.

Clonage

Dans l’exemple précédent, on a vu que le DOM était assez verbeux. C’est inévitable mais on peut parfois réutiliser des éléments qui sont déjà dans le document.

Pour cela, on appelle la méthode cloneNode(profondeur) sur l’élément que l’on veut cloner. Cette méthode renvoie le nouvel élément (la copie donc) et le paramêtre profondeur est un booléen qui indique si on doit copier les fils de cet élément. On peut donc copier tout un groupe g en mettant ce paramêtre à true.

Dans l’exemple suivant, on utilisera un rect déjà défini dans defs.

Une dernière méthode pourra vous être utile pour remplacer un élément par un autre. Il s’agit de père.replaceChild(nouvel élément, élément à remplacer) qui s’appelle sur le père de l’élément à remplacer.

Dans l’exemple suivant, nous allons remplacer tous les cercles par des carrés.

<]]> < Copie et remplacement d’éléments ]]>
0) { // on sélectionne le premier cercle cercleARemplacer = cercles.item(0); // on sauvegarde les coordonnées pour placer le carré à la même place cx = cercleARemplacer.getAttributeNS(null, 'cx'); cy = cercleARemplacer.getAttributeNS(null, 'cy'); // on sélectionne le père parentCircle = cercleARemplacer.parentNode; // on copie le carré prédéfini // ici pas besoin de copie en profondeur, n’a pas de fils nouveauCarré = document.getElementById('carré').cloneNode(false); // on le place au même endroit que le cercle nouveauCarré.setAttributeNS(null, 'x', cx - 30); nouveauCarré.setAttributeNS(null, 'y', cy - 30); // on rempalce le cercle parentCircle.replaceChild(nouveauCarré, cercleARemplacer); } }]]>
Copie et remplacement d’éléments

Voilà, vous connaissez le DOM Level 2 Core. Enfin les parties les plus importantes parcequ’il y a en fait beaucoup plus de méthodes et de propriétés mais celles dont vous vous servirez dans 99% des cas ont été présentées ici. Tout ce que vous avez appris jusqu’à cette phrase, vous pouvez le réutiliser quasiment à l’identique dans n’importe quel langage de programmation.

Style

Passons maintenant au DOM Level 2 Style (ça en jette). Il s’agit d’une API très volumineuse et complexe pour gérer les styles et les feuilles de style d’un document XML. Il est par exemple possible de créer sa feuille de style et d’écrire les règles une par une… Heureusement, nos besoins en la matière sont très simples : tout ce que nous voulons et de pouvoir récupérer un style précis d’un élément et de le modifier.

À part une subtilité que nous verrons plus tard, c’est très simple. Chaque élément à une propriété style qui renvoie un objet CSSStyleDeclaration. Cet objet à deux méthode qui nous intéressent :

Pour résumer, on obtient la valeur d’une propriété CSS sur un élément elt en écrivant elt.style.getPropertyValue('nom de la propriété') et on la change en écrivant elt.style.setProperty('nom de la propriété', 'nouvelle valeur', null).

<]]> < Accéder au style et le modifier avec le DOM ]]>

Cliquez plusieurs fois :

Accéder au style et le modifier avec le DOM

Avez vous remarqué la subtilité ? Lors du premier clic, la valeur de la propriété CSS ne s’est pas affiché, ce qui signifie que getPropertyValue(prop) a renvoyé une chaîne vide, alors que la feuille de style donnait pourtant une valeur pour cette propriété.

En fait c’est le comportement normal. getPropertyValue(prop) ne renvoie une valeur que si le style a été indiqué via setProperty() ou via l’attribut style sur l’élément. Il n’est donc pas possible de récupérer la valeur pourtant bien réelle spécifiée dans la feuille de style avec getPropertyValue(prop).

Pour récupérer de telles valeurs, il faut utiliser, accrochez vous, la méthode document.defaultView.getComputedStyle(élément dont on veut récupérer le style, null) qui renvoie un objet CSSStyleDeclaration qui, si vous avez bien suivi, possède la méthode getPropertyValue(propriété CSS) que nous avons déjà vu. C’est de cette manière que l’on peut récupérer les véritables valeurs calculées (après avoir appliqué les styles) par le moteur de rendu SVG.

<]]> < Accéder aux véritables valeurs du style calculées ]]>
Accéder aux véritables valeurs du style calculées

En principe, nous n’aurons pas besoin des autres propriétés et méthodes. Nous pouvons donc passer à un autre module de DOM…

Gestion des évènements

… le DOM Level 2 Events. Décidemment, ça en jette !

Cette partie du DOM est celle qui permet de répondre directement aux actions de l’utilisateur. Ils existent une série d’évènements que l’on peut capturer afin d’agir en conséquence. Parmi ceux ci, nous allons traiter pour l’instant les suivants :

Tous ces évènements sont disponible dans des documents XHTML à la seule différence des évènements commençant par SVG. SVGLoad devient load et aisni de suite.

Il existe d’autres évènements spécifiques à SVG que nous verrons dans le prochain chapitre.

Pour enregistrer un évènement sur un élément elt, on utilise la méthode elt.addEventListener(nom de l’évènement, function à éxecuter, booléen phase). Le nom de l’évènement correspond à un des évènement ci-dessus. À chaque fois que l’évènement est déclenché (par exemple à chaque clic), la fonction à éxécuter est éxécutée. Nous laisserons le dernier paramêtre à false pour le moment.

Dans l’exemple suivant, on change la couleur de remplissage lorsque le pointeur survol ou finit de survoler le rectangle. C’est la propriété CSS pointer-events qui détermine sous quelle condition l’évènement est déclenché (voir le second chapitre sur les animations).

<]]> < Gestion des évènements avec le DOM Events ]]>
Gestion des évènements avec le DOM Events

Vous remarquez qu’on ajoute les observeurs d’évènement après que le fichier SVG soit prêt (SVGLoad) et c’est pour une bonne raison. En effet, si on le fait avant, il y a un risque que le script soit éxécuté avant que le moteur de rendu ait créé le rectangle. Ainsi, impossible de lui ajouter un observeur (rect.addEventListener()) puisqu’il n’existe pas encore ! En réalité, ça arrive dans quasiment tous les cas.

Qu’en est-il du troisième paramêtre ? Pour bien comprendre à quoi il sert, il faut comprendre comment les évènements cheminent à travers tout le document. En fait, l’évènement n’est pas déclenché que sur la cible (ici le rectangle). Il parcourt tout le document de la racine jusqu’à l’élément cible avant de remonter jusqu’à la racine par le même chemin. Il y a trois phases :

Ainsi dans l’exemple précédent, les évènements mouseover et mouseout sont aussi passés par les éléments svg et g, et même deux fois : une fois en descendant et une fois en remontant ! Le parcours a été le suivant : svg puis g puis rect puis g puis enfin svg.

Pour enfoncer le clou, car c’est très important, voici le schéma de ce qui s’est passé (sans les nœuds de texte) :

Le modèle DOM Level 2 Events

Et justement, le dernier paramêtre de addEventListener est un booléen qui détermine si l’évènement doit être déclenché pendant la phase de capture (true) ou pendant la phase de bouillonement (false). Dans l’exemple suivant, on place deux observeurs, un sur le g et un sur le rect. L’observeur placé sur le g a son troisième paramêtre à false et se déclenchera donc pendant la phase de bouillonnement, donc après le déclenchement sur le carré.

<]]> < Bouillonement avec le DOM Events ]]>
g = document.getElementById('g'); g.addEventListener('click', gClick, false); // ajout de l’évènement sur le carré carré = document.getElementById('carré'); carré.addEventListener('click', carréClick, false); } function gClick() { alert('Clic sur le '); } function carréClick() { alert('Clic sur le carré'); }]]>
Bouillonement avec le DOM Events

Pour bien visualiser, voici dans le schéma suivant les deux observeurs schématisés en ronds bleus :

Bouillonnement avec le DOM Level 2 Events

Mais on peut décider de placer l’observeur lors de la phase de descente (la phase de capture). Dans ce cas le troisème paramêtre doit être true.

<]]> < Capture avec le DOM Events ]]>
g = document.getElementById('g'); // !!! en mode capure !!! g.addEventListener('click', gClick, true); carré = document.getElementById('carré'); carré.addEventListener('click', carréClick, false); } function gClick() { alert('Clic sur le '); } function carréClick() { alert('Clic sur le carré'); }]]>
Capture avec le DOM Events

Et dans ce cas, l’évènement du g se déclenche bien avant celui du rect.

Capture avec le DOM Level 2 Events

Vous avez remarqué qu’on ne peut pas passer des paramêtres aux fonctions qu’on appelle avec les observeurs. Une propriété géniale de ceux-ci est qu’ils envoient automatiquement à la fonction qu’on appelle un paramêtre de type Event qui contient plusieurs informations intéressantes, dont la cible de l’évènement via l’attribut target. Ainsi, on n’a pas besoin de savoir quel élément a intercepté l’évènement, il suffit de le demander de cette façon : event.target.

Pour que ça fonctionne, il faut néanmoins déclaré l’évènement comme premier paramêtre de la fonction appelée : function(evt){ /* code de la fonction */ }.

Dans l’exemple suivant, on place un observeur sur chaque cercle une fois le chargement fini. Ensuite, on agrandit le rayon du cercle de 10 pixels à chaque clic en récupérent le cercle en question grâce à evt.target.

<]]> < Récupération de la cible avec le DOM ]]>
Récupération de la cible avec le DOM

Petit détail : la cible event.target d’un évènement est toujours le dernier fils de l’arbre. Ainsi, si on place l’observeur sur l’élément g, la cible target sera le cercle et non le g. Alors qu’en réalité, on a cliqué sur le cercle circle mais aussi sur l’élément g et sur l’élément svg. Pour récupérer l’élément sur lequel on a placé l’observeur, on doit utiliser non pas target mais la propriété currentTarget.

Une dernière méthode qui peut être utile est evt.stopPropagation qui s’appelle sur un évènement. Elle met simplement fin à la propagation de l’évènement lors de sa descente ou de sa remontée. Pour être plus précis, l’évènement n’ira pas plus loin que l’élément sur lequel est placé l’observeur mais les observeurs restants (car on peut en mettre plusieurs sur un élément) seront exécutés.

Dans l’exemple suivant, on stoppe la propagation de l’évènement sur le carré de droite lors de la descente (phase de capture, le dernier paramêtre de addEventListener est true). De plus, on utilise currentTarget pour avoir l’élément sur lequel a été placé l’observeur.

<]]> < Arrêt de la propagation avec le DOM Events ]]>
Arrêt de la propagation avec le DOM Events

Voici le schéma de ce qui se passe pour le carré de droite. En rouge, l’endroit où la propagation de l’évènement est stoppé.

Capture avec le DOM Level 2 Events

Enfin, la dernière méthode dont vous aurez besoin permet de retirer un observeur et s’écrit : elt.removeEventListener(), s’effectue au même endroit que l’observeur qu’on veut retirer et prend exactement les mêmes paramêtres.

En effet, on peut mettre une multitude d’observeur sur un élément. Il suffit de changer un seul paramêtre. Par exemple, on peut changer la fonction a appeler pour éxécuter différentes fonctions lors du clic, ou encore changer le dernier paramêtre et avoir ainsi deux appels différents : un lors de la phase de capture (à la descente) et un lors de la phase de bouillonement (à la remontée).

Tout ce qui a été dit ici est valable pour XHTML, à quelques détails près. Notamment pour le nom de évènements (SVGLoad devient load, etc.).

La partie traitant du DOM classique est terminée mais SVG étend ce DOM avec des propriétés et des méthodes spécifiques à ce langage : il s’agit du DOM SVG.

XSLT pour SVG
Le DOM SVG