SELFHTML/Aides à la navigation HTML dynamique Les différents modèles DHTML |
Le modèle DOM est une norme adoptée par le consortium W3 qui décrit tout d'abord l'accès des langages script à des éléments au choix d'un document dans un langage de marquage. Le modèle DOM n'est donc lui même ni un langage script distinct, ni limité à HTML. Il définit somme toute des objets, propriétés et méthodes qu'un langage script doit transcrire s'il veut se désigner comme interprétant le DOM. Ces objets, propriétés et méthodes doivent pouvoir être appliqués à tous les documents qui sont écrits dans un langage de marquage conforme à XML. Le consortium W3 insiste bien sur le fait que le modèle DOM ne doit pas simplement être une norme pour "HTML dynamique". Le modèle DOM n'est pas non plus limité au côté client donc par exemple au navigateur Web. Il peut tout aussi bien être mis en œuvre dans des scripts côté serveur, par exemple dans des scripts CGI pour créer des documents de façon dynamique.
Quoiqu'il en soit - le modèle DOM est la solution salvatrice également pour ce qu'on entend ici par HTML dynamique, à savoir la modification dynamique a posteriori des contenus d'une page affichée dans la fenêtre du navigateur. Sorti en 1998 tout d'abord comme recommandation officielle du W3, il a été implémenté dans l'Explorer Internet MS 5.0 et dans le navigateur Netscape, entièrement reprogrammé par la communauté des développeurs de Mozilla que Netscape lui même propose en tant que version 6.0 (JavaScript Version 1.5). L'implémentation dans les navigateurs actuels n'est pas encore complète. Il arrive sans cesse que l'on soit confronté en tant que programmeur à la conduite mystérieuse de l'un ou l'autre navigateur. La voie est cependant tracée qui indique comment HTML dynamique sera programmé à l'avenir.
Un langage de marquage comme HTML ou tout autre langage basé sur XML peut être schématisé comme une arborescence hiérarchisée. Les différentes composantes d'une telle arborescence sont désignés comme étant des nœuds. L'objet central du modèle DOM est pour cette raison l'objet node (node = nœud). Il existe différents types de nœuds. Dans un document HTML ordinaire existent dans tous les cas trois types de nœud importants qu'il vous faut distinguer: les nœuds-élément, les nœuds-attribut, et les nœuds-texte.
Pour comprendre, examinez la construction HTML simple suivante:
<h1 align="center">Hello monde</h1>
Dans cette construction, il y a un nœud-élément, à savoir le nœud-élément de l'élément h1
. De plus, il y a un nœud-attribut, à savoir celui de l'attribut align
, et enfin il y a ce qu'on appelle des "données en caractères", que l'on trouve à deux endroits: à savoir une fois comme contenu de l'élément h1
, et une fois pour l'affectation de valeur à l'attribut align
. Ces données en caractères représentent elles-mêmes des nœuds, à savoir des nœuds texte.
Un autre exemple de construction doit aider à mieux comprendre:
<h1 align="center">Hello <i>monde</i></h1>
Dans cet exemple est ajouté le marquage en italique du mot monde
. Il est important de comprendre maintenant, à quoi ressemble la hiérarchie des nœuds:
L'élément h1
est, dans ce petit extrait de structure arborescente le nœud de sortie. Ce nœud a d'après les règles du modèle DOM, deux nœuds-enfant et un nœud associé: les nœuds enfant sont d'une part le nœud texte avec le mot Hello
suivi d'un espace ainsi que le nœud élément de l'élément i
. L'attribut align
dans le repère d'ouverture <h1>
n'est pas par contre un nœud-enfant mais un nœud associé. Le nœud-attribut a toutefois lui-même un nœud enfant à savoir la valeur affectée (center
). Même la nœud-élément de l'élément i
a, à son tour, un nœud-enfant, à savoir le nœud-texte de son contenu de caractères, donc le mot monde
.
L'arborescence d'une page Web complexe peut avoir, comme on peut le déduire de ces exemples simples, des imbrications larges et profondes. Dans un langage script, il doit cependant être possible d'accéder à des nœuds distincts, le plus vite et le plus efficacement possible. Dans le modèle DOM il existe pour cette raison trois méthodes importantes de l'objet document pour pouvoir au moins accéder directement à chaque nœud-élément de son choix:
getElementById() peut accéder à des éléments qui contiennent un attribut id
clair et sans ambiguïté pour tout le document par exemple
<p id="le_paragraphe">ici se trouve le texte</p>
getElementsByName() peut accéder à des éléments qui possèdent un nom (qui n'est pas forcément unique et clair), par exemple
<input name="champ_saisie" type="text" size="40">
getElementsByTagName() peut accéder à tous les éléments sous la forme: "donne le 27 ème élément td
du document".
Partant d'un nœud-élément recherché, il est rapide ensuite d'accéder à ses attributs et à son contenu. Pour cela aussi le modèle DOM dispose de propriétés et de méthodes. Ici il y a cependant deux variantes pour les pages basées sur HTML. D'un côté vous pouvez utiliser les propriétés et méthodes de l'objet node pour accéder aux nœuds-enfants et nœuds associés. De l'autre, vous pouvez également employer les objets éléments HTML. Les objets éléments HTML sont bien appropriés avant tout pour accéder aux attributs distincts d'un élément.
HTML dynamique peut aussi consister à créer des nouveaux éléments avec des contenus et formatages sur le temps d'affichage d'une page Web. Le modèle Dom dispose également de méthodes à cette fin.
Dans la version 1.0 du modèle Dom n'était réglé que l'accès aux nœuds. L'accès aux propriétés de style affectées et la gestion d'événements n'y sont pas encore abordés. Dans la version 2.0 du modèle DOM de novembre 2000 ces domaines importants pour les pages Web dynamiques sont toutefois également traités. C'est pourquoi il est recommandé en tous cas, pour de nouvelles page Web à créer, de se baser sur les techniques réglées dans le modèle DOM. Les modèles plus anciens de Microsoft et de Netscape doivent encore actuellement être mis en œuvre pour des raisons de compatibilité vers l'amont, mais disparaître cependant peu à peu définitivement à terme, pour qu'enfin un standard de langage homogène facilite la programmation de pages Web dynamiques.
Il y a beaucoup de cas d'application indiqués de modification dynamique d'éléments HTML affichés dans un premier temps. L'exemple qui suit en présente un. Dans l'exemple est sortie une liste numérotée triée d'abord par ordre alphabétique. Sous la liste, l'utilisateur peut néanmoins à l'aide de deux boutons de formulaire alterner l'ordre géographique et l'ordre alphabétique.
<html><head><title>Test</title> <script type="text/javascript"> <!-- var tableau_geo = new Array(5,4,6,3,12,11,7,8,2,10,0,1,9); function ABC() { var villes = new Array(); for(var i = 0; i < document.getElementsByTagName("li").length; i++) villes.push(document.getElementsByTagName("li")[i].firstChild.nodeValue); villes.sort(); for(i = 0; i < document.getElementsByTagName("li").length; i++) document.getElementsByTagName("li")[i].firstChild.nodeValue = villes[i]; document.getElementById("ordre").firstChild.nodeValue = "alphabétique de A à Z"; } function GEO() { var villes = new Array(); for(var i = 0; i < document.getElementsByTagName("li").length; i++) villes.push(document.getElementsByTagName("li")[i].firstChild.nodeValue); for(i = 0; i < document.getElementsByTagName("li").length; i++) document.getElementsByTagName("li")[i].firstChild.nodeValue = villes[tableau_geo[i]]; document.getElementById("ordre").firstChild.nodeValue = "géographique du nord au sud"; } //--> </script> </head><body> <h1>Grandes villes dans l'ordre <span id="ordre">alphabétique de A à Z</span></h1> <ol> <li>Aix en Provence</li> <li>Biarritz</li> <li>Bordeaux</li> <li>Brest</li> <li>Calais</li> <li>Dunkerque</li> <li>Lille</li> <li>Limoges</li> <li>Lyon</li> <li>Marseille</li> <li>Montélimar</li> <li>Nantes</li> <li>Paris</li> </ol> <form name="formulaire" action=""> <input type="button" name="abc" value="alphabétiquement" onClick="ABC()"> <input type="button" name="geo" value="géographiquement" onClick="GEO()"> </form> </body></html> |
Dans l'exemple la liste numérotée est tout d'abord notée dans l'ordre alphabétique des noms de villes. Dans le formulaire sous la liste sont notés deux boutons pouvant être cliqués. L'un appelle la fonction ABC()
, l'autre la fonction GEO()
. Un clic sur ABC()
n'apporte bien sûr rien, étant donné que la liste est triée dans l'ordre alphabétique dès le départ. Donc il va de soi de cliquer d'abord sur le bouton portant l'inscription géographiquement
. La fonction GEO()
, qu'il appelle, définit d'entrée avec var villes = new Array();
un nouvel Array vide. Le but est de remplir ce tableau avec les noms de villes de la liste. Pour ce faire, la fonction accède dans l'ordre dans une boucle for
à tous les éléments du type li
qui sont placés dans le document.
L'accès a lieu avec document.getElementsByTagName("li")
.
Par document.getElementsByTagName("li").length
le nombre des éléments li
du document peuvent être recherchés. La fonction a besoin de cette information comme condition d'interruption de la boucle for
. Dans la boucle et grâce à la méthode push le contenu de l'élément li
actuel est ajouté au tableau.
Avec document.getElementsByTagName("li")[i].firstChild.nodeValue
il est accédé ici au contenu de chacun des éléments li
. Pour le modèle DOM document.getElementsByTagName("li")[i]
est un nœud, à savoir l'élément li
placé en i
ème position dans le document. firstChild
est une propriété de l'objet node. Par cette propriété, vous pouvez accéder au premier nœud-enfant d'un nœud. Le premier nœud-enfant de tous les éléments li
du document est son contenu en texte, donc le nom de la ville. La propriété firstChild
ne renvoie pas encore le contenu de l'élément, mais seulement l'objet du contenu. Pour accéder effectivement au contenu, donc au nom concret de la ville, il faut faire appel à une autre propriété de l'objet node
, à savoir la propriété nodeValue
. Notez vous bien la combinaison firstChild.nodeValue
. Vous utiliserez souvent cette combinaison pour accéder au contenu d'un élément.
Après que le tableau est rempli avec les noms de villes, la fonction GEO()
fait simplement l'inverse et écrit le tableau à nouveau dans la liste - là aussi dans une boucle for
.
L'expression document.getElementsByTagName("li")[i].firstChild.nodeValue
figure cette fois à gauche de l'affectation. C'est ainsi qu'une nouvelle valeur sera affectée au contenu de l'élément de la liste. Dans l'exemple, il s'agit de la valeur villes[tableau_geo[i]]
à l'aspect quelque peu compliqué. Les villes doivent bien être sorties dans l'ordre géographique. Il n'y a pas ici d'algorithme qui connaît la géographie. Tout en haut dans le passage script est noté à cet effet un tableau nommé tableau_geo
. Les nombres avec lesquels ils est initialisé sont tout simplement les numéros d'index des villes dans l'ordre alphabétique. Ainsi par exemple tableau_geo[0]
a pour valeur 6
. Grâce à cette information, la fonction GEO()
, sait que la ville située le plus au nord est celle qui dans l'ordre alphabétique a le numéro 5 (Dunkerque). La fonction utilise
, donc l'accès à villes[tableau_geo[i]]
tableau_geo
, comme numéro d'index de la ville qui doit être écrite dans la liste.
La fonction ABC()
marche exactement de la même façon que la fonction GEO()
. Elle ne se distingue de cette dernière qu'en ce que, après la lecture du tableau villes
, la méthode objet sort() lui soit appliquée pour trier les enregistrements. Ensuite, elle écrit simplement le tableau trié à nouveau dans la liste.
Un autre élément est également encore modifié par les deux fonctions: à savoir l'élément span
placé dans le titre. Étant donné que pour cet élément est notée dans le code HTML une valeur Id avec id="ordre"
, il est commode d'y accéder avec document.getElementById("ordre")
. Avec la syntaxe habituelle firstChild.nodeValue
le texte de l'élément est adressé et modifié de façon dynamique.
Par l'ajour, la modification ou l'effacement dynamiques d'attributs HTML, il est possible d'atteindre des effets intéressants mais aussi des objectifs utiles. L'exemple suivant montre comment vous pouvez changer des liens de façon dynamique.
<html><head><title>Test</title> <script type="text/javascript"> <!-- var liens_favoris = new Array( "http://www.tf1.fr/news/monde/", "http://www.presence-pc.com/", "http://fr.news.yahoo.com/", "http://www.france.diplomatie.fr/actual/", "http://forum.fr.selfhtml.org/" ) var lien_actuel = 0; function lien_favori() { document.getElementsByName("cible")[0].href = liens_favoris[lien_actuel]; document.getElementsByName("cible")[0].firstChild.firstChild.nodeValue = liens_favoris[lien_actuel]; lien_actuel += 1; if(lien_actuel >= liens_favoris.length) lien_actuel = 0; } function fenetre_liens(fenetre) { document.getElementsByName("cible")[0].target = fenetre; } //--> </script> </head><body> <p><a name="cible" href="#cible"><b>Lien pr&:eacute;féré&</b></a><br> <a href="javascript:lien_favori()">Lien favori suivant!</a><br> liens_favoris: <a href="javascript:fenetre_liens('_blank')">ouvrir dans une nouvelle fenêtre!</a> oder <a href="javascript:fenetre_liens('_self')">ouvrir dans la fenêtre active!</a></p> </body></html> |
L'exemple contient dans le passage visible un "lien préféré", qui mène d'abord à lui même (name="cible" href="#cible"
). Au dessous sont notés trois autres liens. Le premier annonce le lien favori suivant et les deux autres permettent à l'utilisateur de fixer comment il veut ouvrir ce lien - s'il veut l'ouvrir dans une nouvelle fenêtre ou dans la même fenêtre. Tous les trois appellent des fonctions JavaScript, notées dans l'entête de fichier. Le premier lien qui annonce le lien favori suivant, appelle la fonction lien_favori()
.
Cette fonction accède au premier élément du document pour lequel est noté comme attribut name="cible"
. Elle le fait avec document.getElementsByName("cible")[0]
. C'est le cas dans l'exemple pour le lien qui doit afficher les liens favoris et qui pointe jusque là sur lui-même. Doivent être modifiés pour ce lien aussi bien son attribut href
que son lien de texte visible. L'accès à l'attribut href
est tout simple, parce que, d'après la syntaxe du modèle DOM des objets éléments HTML tout attribut imaginable d'un élément HTML représente simplement une propriété de l'objet HTML correspondant. Pour accéder à des attributs HTML, vous n'avez donc besoin que d'accéder à l'élément désiré et derrière, séparé par un point, de noter le nom d'attribut comme propriété. Observez ici la distinction particulière entre minuscules et majuscules pour certains attributs comme bgColor
, vSpace
ou bien cellPadding
.
Avec document.getElementsByName("cible")[0].href
il est donc, dans l'exemple, accédé directement à la valeur de l'attribut href
du lien désiré. En lui affectant une valeur, l'attribut est modifié de façon dynamique. Dans l'exemple, une nouvelle valeur de l' Array noté plus haut dans le script, et nommé liens_favoris
est affectée. Comme compteur d'index, c'est la variable lien_actuel
également déjà définie auparavant qui est employée. Celle-ci est enfin incrémentée de 1 pour qu'au prochain appel de la fonction, ce soit le lien favori suivant dans le tableau qui soit posé. Quand la valeur de lien_actuel
est trop élevée pour trouver encore un enregistrement dans le tableau, la variable est fixée à nouveau à 0 et au prochain clic, c'est à nouveau le premier enregistrement dans le tableau qui est servi..
L'accès au texte du lien a encore lieu par firstChild.value
. Pourtant dans l'exemple est noté firstChild.firstChild.nodeValue
. La raison en est que le texte du lien ne figure pas directement entre <a>
et </a>
, mais qu'il est encore inclus dans un élément b
pour le marquage en caractères gras. Du point de vue de l'élément a
, l'élément b
est donc le firstChild
, et le texte du lien visible n'est donc que le firstChild
de ce dernier.
Les liens qui règlent dans quelle fenêtre les liens favoris doivent être ouverts appellent chacun la fonction fenetre_liens()
et lui transmettent comme paramètre le nom de fenêtre cible désirée _self
(ouvrir dans la même fenêtre) ou _blank
(ouvrir dans un nouvelle fenêtre). La fonction fenetre_liens()
utilise à nouveau le chemin commode par les objets éléments HTML, pour accéder directement à la propriété target
de l'élément a
et pour fixer l'attribut correspondant. Il n'y a donc aucun problème pour fixer des attributs qui ne sont pas notés dans le texte source HTML d'un élément.
Au cas où vous voulez effacer un élément, vous avez deux possibilités: soit vous fixez sa valeur à ""
(chaîne de caractères vide), ou bien, - et c'est plus propre - vous travaillez avec la méthode removeAttribute() de l'objet node
.
Depuis la version 2.0 du modèle DOM, il est également réglé comment accéder aux mentions de feuilles de style. Ici on s'est largement inspiré de l'objet style introduit en son temps par Microsoft.
L'exemple suivant montre comment, à l'aide de la technique du modèle DOM, vous écrivez du HTML dynamique typique et classique avec déplacement d'éléments positionnés. À cet effet sert la possibilité de positionner des éléments de façon absolue à l'aide de propriétés de feuilles de style.
<html><head><title>Test</title> <script type="text/javascript"> <!-- var pr, pb, moi; var vitesse_pr = 10, vitesse_pb = 20; var grade_pr = 0, grade_pb = 0; var X_pr = 170, Y_pr = 170, X_pb = 170, Y_pb = 170; var rayon_pr = 150, rayon_pb = 150; function Init() { pr = eval(document.getElementById("point_rouge")); pb = eval(document.getElementById("point_bleu")); moi = eval(document.getElementById("moi")); pr.style.position = "absolute"; pr.style.top = 20; pr.style.left = 320; pb.style.position = "absolute"; pb.style.top = 320; pb.style.left = 320; moi.style.position = "absolute"; moi.style.top = 110; moi.style.left = 90; moi.style.fontFamily = "Courier New,Courier"; moi.style.fontSize = "72pt"; moi.style.fontWeight = "bold"; moi.style.color = "#009900"; cercle_pr(); cercle_pb(); } function cercle_pr() { grade_pr += vitesse_pr/1000; if(grade_pr > 360) grade_pr = 0; pr.style.top = Math.round(Y_pr + (rayon_pr * Math.cos(grade_pr))); pr.style.left = Math.round(X_pr + (rayon_pr * Math.sin(grade_pr))); window.setTimeout("cercle_pr()",100/vitesse_pr); } function cercle_pb() { grade_pb += vitesse_pb/1000; if(grade_pb > 360) grade_pb = 0; bp.style.top = Math.round(Y_pb + (rayon_pb * Math.cos(grade_pb))); pb.style.left = Math.round(X_pb + (rayon_pb * Math.sin(grade_pb))); window.setTimeout("cercle_pb()",100/vitesse_pb); } //--> </script> </head><body onLoad="Init()"> <div id="point_rouge"><img src="tourneautour1.gif" width="20" height="20" border="0" alt="point rouge"></div> <div id="point_bleu"><img src="tourneautour2.gif" width="20" height="20" border="0" alt="point bleu"></div> <div id="moi">MOI</div> </body></html> |
Dans le passage body
de l'exemple, sont simplement notés trois passages div
sans autre formatage. Les deux premiers contiennent chacun un petit graphique - tourneautour1.gif
est un point rouge, tourneautour2.gif
un point bleu. Les deux graphiques ont un arrière plan transparent, ce qui est important étant donné que les points dans le déroulement ultérieur se chevauchent souvent.
Dans le repère d'ouverture <body>
est noté le gestionnaire d'événement onLoad()
. Celui-ci se déclenche, dès que le fichier est chargé complètement dans le navigateur. Alors est appelée la fonction Init()
, notée dans l'entête de fichier. Cette fonction met tout d'abord en œuvre la fonction JavaScript eval(), pour raccourcir l'accès aux passages div
. Étant donné que les trois passages div
ont un attribut id
, l'accès aux nœuds-élément correspondants avec getElementById("point_rouge")
etc... est possible. Par l'application de eval
sur une telle expression est sauvegardée dans une variable telle que pr
la "signification" pour ainsi dire de getElementById("point_rouge")
, et après cela il est possible de travailler exactement de la même façon avec pr
que si l'on notait à chaque fois getElementById("point_rouge")
.
Par les variables pr
, pb
et moi
il est ensuite également possible d'adresser l'objet style
. La fonction Init()
équipe d'abord les trois passages div
avec les propriétés de feuilles de style CSS de départ. Les trois passages sont positionnés de façon absolue avec style.position = "absolute"
. Le coin supérieur gauche de chaque passage est déterminé avec style.left
et style.top
. Le contenu du passage moi
, donc le mot MOI
, est formaté en grand et bien visible.
À la fin, la fonction Init()
appelle les deux autres fonctions cercle_pr()
et cercle_pb()
. Chacune de ces deux fonctions contrôle le mouvement circulaire de l'un des deux points, en recalculant somme toute, le coin supérieur gauche du passage div
qui contient chacun des deux graphiques. Pour cela entrent en jeu les fonctions de cercle pour sinus ( Math.sin()) et cosinus Cosinus ( Math.cos()). À la fin, chacune des deux fonctions se rappelle elle-même de façon récursive avec window.setTimeout(), pour fixer la prochaine position du passage div
avec le graphique. Les variables comme grade_pb
, vitesse_pb
etc... avec lesquelles ces fonctions travaillent, ont été initialisées auparavant dans le passage global du script.
HTML dynamique d'après le modèle DOM ne signifie pas seulement l'accès à des éléments HTML déjà existants mais aussi la création de nouveaux éléments et leur ajout dans l'arborescence. Comment cela fonctionne, c'est ce que montre l'exemple suivant. Il représente un éditeur HTML rudimentaire.
<html><head><title>Test</title> <style type="text/css"> <!-- h1 { font-family:Arial,sans-serif; font-size:24pt; font-weight:normal; border-bottom:2px solid red; } h2 { font-family:Arial,sans-serif; font-size:20pt; font-weight:normal; border-bottom:1px solid red; } h3 { font-family:Arial,sans-serif; font-size:12pt; font-weight:bold; } p { font-family:Arial,sans-serif; font-size:11pt; } --> </style> <script type="text/javascript"> <!-- function ajouter() { var type = document.formulaire.type_element.options[document.formulaire.type_element.selectedIndex].value; var noeud_element = document.createElement(type); if(type == "hr") document.getElementById("utilisateur").appendChild(noeud_element); else { var noeud_texte = document.createTextNode(document.formulaire.contenu_element.value); noeud_element.appendChild(noeud_texte); document.getElementById("utilisateur").appendChild(noeud_element); } } //--> </script> </head><body> <form name="formulaire" style="background-color:#EEEEEE; padding:10px" action=""> <select name="type_element" size="1"> <option value="h1">Titre 1</option> <option value="h2">Titre 2</option> <option value="h3">Titre 3</option> <option value="p">Paragraphe de texte</option> <option value="hr">Ligne de séparation</option> </select> <input type="text" name="contenu_element" size="50"> <input type="button" value="Ajouter" onClick="ajouter()"> </form> <div id="utilisateur" style="background-color:#FFFFC0; padding:10px"> </div> </body></html> |
L'exemple contient dans le passage HTML visible, un formulaire avec une liste de choix, un champ de saisie et un bouton pouvant être cliqué. Au dessous est encore noté un passage div
, qui n'a cependant aucun contenu concret. Dans la liste de choix du formulaire, l'utilisateur peut choisir un type d'élément HTML - Dans les attributs value
des éléments option
sont sauvegardés les noms effectifs d'éléments HTML des différents choix. Dans le champ de saisie du formulaire, l'utilisateur peut entrer un contenu en texte pour l'élément qu'il a choisi. Quand il clique ensuite sur le bouton, la fonction ajouter()
qui est notée dans un passage JavaScript de l'entête de fichier, est appelée.
Là est d'abord sauvegardée la longue et peu commode expression document.formulaire.type_element.options[document.formulaire.type_element.selectedIndex].value
dans la variable type
. la longue expression ou plutôt la variable sauvegarde le type d'élément HTML choisi dans le formulaire par l'utilisateur, à savoir par exemple h1
ou bien p
.
Avec document.createElement(type)
est ensuite créé un nouvel élément vide du type type
, donc selon la valeur de la variable type
par exemple un élément h1
ou un élément p
. Ceci n'affiche pourtant pas encore l'élément. document.createElement()
crée en fin de compte le nœud-élément sans l'ajouter cependant dans l'arborescence du document. C'est exactement la même chose qu'avec document.createTextNode()
. Cette méthode crée un nœud texte, mais ne fixe en aucune façon l'endroit où ce nœud-texte doit être ajouté. Dans l'exemple, un tel nœud-texte est créé avec document.createTextNode(document.formulaire.contenu_element.value)
à partir de ce que l'utilisateur a entré dans le champ de saisie. L'"accrochage" dans l'arborescence est la prochaine tâche du script.
Pour cela, le script doit pourtant distinguer entre les éléments qui ont un contenu en texte et ceux qui n'en ont pas. L'élément hr
que l'utilisateur peut également choisir, donc l'élément HTML pour une ligne de séparation, ne peut pas avoir de contenu en texte. C'est la raison pour laquelle le script distingue avec if
et else
entre type == "hr"
et toutes les autres valeurs possibles de type
. Si l'utilisateur a choisi l'élément hr
, le nouvel élément créé hr
sauvegardé dans la variable noeud_element
est ajouté dans l'arborescence. Le nœud texte quant à lui est rejeté. Dans tous les autres cas (embranchement else
) le nœud-texte doit d'abord être ajouté au nœud-élément pour que l'élément puisse recevoir le texte comme contenu. Enfin, l'élément doit être ajouté dans l'arborescence.
Pour tous les processus d'ajout, la méthode appendChild()
de l'objet node est employée. La méthode est applicable à un objet nœud qui peut avoir des nœuds-enfants. Donc par exemple, un nœud-élément. La méthode attend comme paramètre le nœud qui doit être ajouté comme nœud-enfant.
Si dans l'exemple figure donc: noeud_element.appendChild(noeud_texte);
Alors noeud_element
est une variable dans laquelle a été créé auparavant un élément objet par createElement()
, et noeud_texte
est une variable qui a auparavant sauvegardé un nœud-texte par l'appel de createTextNode()
.
Avec l'instruction document.getElementById("utilisateur").appendChild(noeud_element)
il est accédé au passage div
tout d'abord vide du document. À cet élément, est ajouté le nouveau nœud-élément.
La normalisation de la gestion d'événements dans le modèle DOM n'était toujours pas achevé au moment de la rédaction de ce document - ainsi il manquait par exemple toujours l'implémentation d'événements clavier. L'Explorer Internet 5.x n'interprète encore toujours pas les événements d'après la syntaxe DOM, Netscape 6.x par contre le fait déjà. L'exemple suivant montre le principe selon lequel fonctionne la gestion d'événements d'après la syntaxe du modèle DOM.
<html><head><title>Test</title> <script type="text/javascript"> <!-- function sortir(texte) { element_protocole = document.createElement("li"); nouveau_texte = document.createTextNode(texte); element_protocole.appendChild(nouveau_texte); document.getElementById("protocole").appendChild(element_protocole); } function gestion_clic_champ_saisie(ev) { Event = ev; texte = "Vous avez cliqué dans le champ de saisie. "; texte = texte + "Event-Typ = " + Event.type + ", "; texte = texte + "Event-Target-Elementname = " + Event.target.nodeName + "."; sortir(texte); } function gestion_mouvement_passage(ev) { Event = ev; texte = "Vous avez bougé la souris dans le passage. "; texte = texte + "position_X = " + Event.clientX + ", "; texte = texte + "position_Y = " + Event.clientY + "."; sortir(texte); } function gestion_clic_passage(ev) { Event = ev; texte = "Vous avez cliqué dans le passage. "; texte = texte + "position_X = " + Event.clientX + ", "; texte = texte + "position_Y = " + Event.clientY + "."; sortir(texte); } function Init() { document.getElementsByName("saisie")[0].addEventListener("click", gestion_clic_champ_saisie, true); document.getElementById("passage").addEventListener("mousemove", gestion_mouvement_passage, true); document.getElementById("passage").addEventListener("click", gestion_clic_passage, true); } //--> </script> </head><body onLoad="Init()"> <form name="formulaire" style="background-color:#EEEEEE; padding:10px" action=""> <input type="text" name="saisie" size="50"> </form> <div id="passage" style="background-color:#FF0000; color:#FFFFFF; font-weight:bold; width:100px">Ein passage</div> <ol id="protocole" style="font-family:Arial,sans-serif; font-size:10pt"><li>Ereignisliste</li></ol> </body></html> |
Dans le passage visible du fichier HTML est noté un formulaire avec un champ de saisie, plus un passage div
, et enfin une liste numérotée vide. Dans le repère d'introduction <body>
est noté le gestionnaire d'événement onLoad
, qui n'a néanmoins toujours rien à voir avec la gestion d'événements d'après la syntaxe du modèle DOM. Là est tout simplement appelée la fonction Init()
, qui est notée dans l'entête de fichier.
Dans la fonction Init()
on aborde cependant le cœur du sujet en ce qui concerne la gestion d'événements dans le modèle DOM. La gestion d'événements consiste d'abord dans le modèle DOM à enregistrer une surveillance d'événement pour un nœud de votre choix dans le document. Pour ce faire existe la méthode addEventListener()
. Avec la partie qui précède, dans l'exemple par exemple document.getElementsByName("saisie")[0]
, est adressé le nœud du document pour lequel une surveillance d'événements doit être enregistrée. Dans l'exemple de la fonction Init()
trois surveillances d'événements en tout sont sollicitées: une pour le champ de saisie du formulaire et deux pour le passage div
.
La méthode addEventListener()
attend trois paramètres. Le premier paramètre mentionne quel type d'événement doit être surveillé. Pour les événements souris, il s'agit pour une large part des types d'événements connus de l'objet JavaScript event comme click
, mouseover
, mousedown
, mouseup
, mousemove
. À cela s'ajoutent les types d'événements du modèle DOM tels que DOMFocusIn
(le nœud devient zone de saisie active), DOMFocusOut
(le nœud cesse d'être la zone de saisie active), DOMActivate
(le nœud est activé par un clic de souris ou une touche clavier), ainsi que des événements indépendants de l'utilisateur tels que DOMSubtreeModified
(arborescence modifiée), DOMNodeInserted
(nœud inséré dans l'arborescence) ou bien DOMNodeRemoved
(nœud effacé de l'arborescence). Le nom du type d'événement doit figurer entre guillemets dans la mention du paramètre.
Le deuxième paramètre, que le addEventListener()
attend, est le nom d'une fonction, qui doit être appelée si l'événement survient. Le nom de la fonction est mentionné sans guillemets. La fonction mentionnée reçoit automatiquement un objet événement et peut ainsi commencer ce qu'elle doit faire. À ce sujet, voir plus bas.
Comme troisième paramètre, il faut transmettre à l' addEventListener()
soit true
soit false
. Avec true
vous activez la surveillance d'événement, avec false
pas encore.
Pour chaque événement que vous désirez surveiller, vous avez besoin d'une fonction qui réagit à l'événement. C'est la fonction dont le nom est transmis comme deuxième paramètre pour addEventListener()
. Dans l'exemple ci-dessus, trois événements doivent être surveillés. C'est pourquoi il y a trois fonctions similaires des noms de gestion_clic_champ_saisie()
, gestion_mouvement_passage()
et gestion_clic_passage()
. Toutes les trois reçoivent l'événement en tant qu'objet lors de leur appel automatique qui a lieu lorsque l'événement survient. Les fonctions de l'exemple attendent pour cette raison un paramètre ev
, qu'elles affectent dans leur première instruction à la variable Event
. Après les fonctions peuvent accéder par la variable Event
aux propriétés et méthodes de l'objet événement. Pour les événements souris existent par exemple des propriétés telle que clientX
(nombre de pixels à compter du bord gauche du passage visible du nœud), clientY
(nombre de pixels à compter du bord supérieur du passage visible du nœud), screenX
(nombre de pixels à compter du bord gauche de l'écran) ou screenY
(nombre de pixels à compter du bord supérieur de l'écran).
Dans l'exemple, les fonctions qui surveillent un événement, composent simplement un texte et appellent ensuite la fonction sortir()
avec le texte formé. La fonction sortir()
crée d'abord un nouvel élément HTML du type li
avec document.createElement("li")
. Ensuite elle crée un nouveau nœud texte avec le texte transmis avec document.createTextNode(texte)
. Enfin, elle ajoute le nœud-texte avec appendChild()
en tant que nœud enfant du nœud-élément créé li
, et ajoute celui-ci dans la liste numérotée notée dans le document. De cette manière, la liste numérotée se remplit de façon dynamique avec chaque événement ayant été reconnu.
L'ancien modèle DHTML de Microsoft | |
généralités sur HTML dynamique | |
SELFHTML/Aides à la navigation HTML dynamique Les différents modèles DHTML |
© 2001 Stefan Münz / © 2002 Traduction Serge François, 13405@free.fr
selfhtml@fr.selfhtml.org