<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE chapitre SYSTEM "../ressources/chapitre22.dtd">

<chapitre typecourssiteweb="dhtml">
	<cours nomfichier="introdom">Cours de manipulation du DOM et DHTML</cours>
	<entete>
		<titre>Premiers pas dans le DOM</titre>
		<auteur email="Gilles.Chagnon@upmc.fr">G. Chagnon</auteur>
		<resume>Ce chapitre présente un bref historique et les concepts de base du DOM.</resume>
		<motsclefs>dhtml, dom, javascript</motsclefs>
	</entete>
	<corpus>
		<partie titre="Introduction" ancre="domintro">
			<section titre="Qu'est-ce que le DOM?" ancre="koikce">
				<paragraphe>
					<texte>Le Modèle Objet de Document, ou <acronyme titre="Document Object Model">DOM</acronyme>, <autrelangue type="en">Document Object Model</autrelangue> est un outil permettant l'accès aux documents <code type='typefichier'>HTML</code> et <code type='typefichier'>XML</code>. Il permet deux choses au développeur&#160;:</texte>
					<liste>
						<item><texte>Il fournit une représentation structurée du document&#160;;</texte></item>
						<item><texte>Il codifie la manière dont un script peut accéder à cette structure.</texte></item>
					</liste>
					<texte>Il s'agit donc essentiellement d'un moyen de lier une page Web, par exemple, à un langage de programmation ou de script.</texte>
				</paragraphe>
				<paragraphe>
					<texte>Il est à remarquer que le DOM ne désigne pas une application particulière, ou bien un produit spécifique ou une présentation propriétaire d'une page Web ou, plus généralement, à un document écrit dans un langage de balisage (comme <reference href="../xml/"><code type="langage">XML</code></reference> par exemple). Il s'agit d'une interface qui permet de standardiser les moyens d'accès à un document balisé, notamment une page Web. Toutes les propriétés et méthodes ainsi que tous les événements disponibles pour le développeur pour manipuler et créer des pages dynamiques sont organisés sous forme de hiérarchies d'objets. Le présent cours va donner les bases permettant d'aborder ce riche domaine.</texte>
					<texte>Il existe maintenant des bibliothèques de scripts comme <reference href="http://jquery.com/">jQuery</reference>, <reference href="http://www.prototypejs.org/">Prototype</reference>, <reference href="http://mootools.net/">MooTools</reference>, <reference href="http://dojotoolkit.org/">dōjō</reference> ou la <reference href="http://developer.yahoo.com/yui/" lang="en">The Yahoo! User Interface Library</reference>, qui offrent des solutions «&#160;clé en main&#160;» pour lé développement d'interfaces évoluées. Néanmoins, pour les exploiter au mieux, il est souvent nécessaire d'analyser leur code.</texte>
				</paragraphe>
			</section>
			<section titre="Conception de l'arborescence" ancre="arborescence">
				<paragraphe titre="Qu'est-ce qu'un n&#339;ud?" ancre="quoinoeud">
					<texte>Un langage de marquage comme <code type="langage">HTML</code> ou tout autre langage basé sur <code type="langage">XML</code> 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&#339;uds. L'objet central du modèle DOM est pour cette raison l'objet <code>node</code> (<autrelangue type="en">node</autrelangue> = n&#339;ud). Il existe différents types de n&#339;uds. Dans un document <code type="typefichier">HTML</code> ordinaire existent dans tous les cas trois types de n&#339;ud importants qu'il nous faut distinguer&#160;: les n&#339;uds-élément, les n&#339;uds-attribut, et les n&#339;uds-texte.</texte>
				</paragraphe>
				<paragraphe titre="Un premier exemple" ancre="premierexemple">
					<texte>Pour comprendre, examinons la construction <code type="langage">HTML</code> simple suivante&#160;:</texte>
					<exemple type="HTML">
						<element nom="h1"><attribut nom="class">centre</attribut>Bonjour</element>
					</exemple>
					<texte>Dans cette construction, il y a un n&#339;ud-élément, à savoir le n&#339;ud-élément de l'élément <code>h1</code>. De plus, il y a un n&#339;ud-attribut, à savoir celui de l'attribut <code>align</code>, et enfin il y a ce qu'on appelle des «&#160;données en caractères&#160;», que l'on trouve à deux endroits&#160;: à savoir une fois comme contenu de l'élément <code>h1</code>, et une fois pour l'affectation de valeur à l'attribut <code>class</code>. Ces données en caractères représentent elles-mêmes des n&#339;uds, à savoir des n&#339;uds texte (pour plus de détails, il est nécessaire de se reporter à la définition des éléments et attributs dans un <reference href="../xml/">cours de <code type="langage">XML</code></reference>).</texte>
				</paragraphe>
				<paragraphe titre="Un deuxième exemple, plus complexe" ancre="casegate">
					<texte>Un autre exemple de construction peut aider à mieux comprendre&#160;:</texte>
					<exemple type="HTML">
						<element nom="h1"><attribut nom="class">centre</attribut>Bonjour <element nom="i" enligne="oui">tout le monde</element>&amp;nbsp;!</element>
					</exemple>
					<texte>Dans cet exemple est ajouté le marquage en italique du groupe de mots «&#160;tout le monde&#160;». Il est important de comprendre maintenant à quoi ressemble la hiérarchie des n&#339;uds.</texte>
					<texte>L'élément <code>h1</code> a d'après les règles du DOM, trois nœuds enfants et un nœud associé&#160;: les nœuds enfants sont le nœud texte avec le mot «&#160;Bonjour&#160;» suivi d'un espace,  le nœud élément de l'élément <code>i</code>, enfin le nœud texte constitué de la chaîne de caractères "&amp;nbsp;!". L'attribut <code>class</code> dans la balise ouvrante <code><![CDATA[<h1>]]></code> 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 (<code>centre</code>). Même le nœud de type élément <code>i</code> a, à son tour, un nœud enfant, à savoir le nœud de type texte de son contenu de caractères, donc les mots «&#160;tout le monde&#160;».</texte>
					<texte>Tous les nœuds de cette arborescence sont accessibles et manipulables -y compris les propriétés des feuilles de style.</texte>
				</paragraphe>
			</section>
			<section titre="DOM et JavaScript" ancre="dometjs">
				<paragraphe>
					<texte>Nous allons dans la suite de ce cours nous limiter à des exemples codés en <code type="langage">JavaScript</code>. Plus précisément, nous allons écrire des scripts en <code type="langage">JavaScript</code>, qui utiliseront le <acronyme titre="Document Object Model" lang="en">DOM</acronyme> pour manipuler dynamiquement les pages où ils se trouvent. Le DOM n'est pas un langage de programmation, mais sans lui, le <code type="langage">JavaScript</code> ne pourrait avoir aucun modèle pour appréhender la page Web. Par le passé, des méthodes et objets propriétaires ont été utilisés, tant par <logiciel>Netscape</logiciel> qu'<logiciel>Internet Explorer</logiciel>, amenant à des «&#160;bricolages&#160;» de code dès lors que l'on voulait s'assurer qu'un effet <code type="langage">DHTML</code> était accepté par les deux familles de navigateurs.</texte>
					<texte>À l'heure actuelle, il n'est heureusement plus nécessaire de passer par des scripts de détection de navigateur. Des solutions bien plus efficaces sont fournies par des détections fondées non plus sur l'identification du navigateur, mais sur la vérification du support ou non des méthodes nécessaires pour l'utilisation d'un script.</texte>
				</paragraphe>
			</section>
		</partie>
		<partie titre="Accès aux éléments et attributs" ancre="acces">
			<section titre="Accès direct" ancre="accesdirect">
				<paragraphe titre="Accès aux éléments à partir de l'ensemble du document" ancre="directdocument">
					<texte>L'objet <code>document</code> est un objet important, qui représente l'ensemble de l'arborescence du document analysé. Il possède de nombreuses propriétés et méthodes. Trois de ces dernières permettent de «&#160;pointer&#160;» directement un ou plusieurs éléments dans le document.</texte>
					<liste>
						<item><texte>La méthode <code>getElementById</code> permet de sélectionner un élément d'identifiant donné dans une page. Par exemple, si on a dans la page <code><![CDATA[<p id="intro">(...)</p>]]></code>, <code>document.getElementById("intro")</code> permettra de sélectionner précisément l'élément <code>p</code> en question.</texte></item>
						<item><texte>La méthode <code>getElementsByName</code> permet de sélectionner les éléments portant un nom donné dans une page&#160;; mais cette méthode, survivance de <logiciel>Netscape</logiciel>, n'est pas supportée par <logiciel>Internet Explorer</logiciel>&#160;;</texte></item>
						<item><texte>La méthode <code>getElementsByTagName</code> permet de sélectionner les éléments portant un nom de balise donné dans une page.</texte></item>
					</liste>
					<texte>Un exemple montre comment <reference href="exemples/exemple1.html">utiliser les méthodes <code>getElementById</code>, <code>getElementByName</code> et <code>getElementsByTagName</code></reference>.</texte>
					<texte>On peut également accéder aux divers éléments d'un document par leur numéro d'ordre dans ce dernier. Par exemple, les collections <code>document.forms</code> et <code>document.images</code> permettent d'accéder aux divers éléments de formulaires et images du document. Cette méthode présente cependant l'inconvénient de fortement dépendre d'une connaissance a priori du nombre d'éléments dans la page&#160;; pour peu que par exemple le nombre d'images change, la numérotation des éléments du tableau doit être revue si l'on veut pouvoir accéder à une image en particulier.</texte>
				</paragraphe>
				<exercice titre="Méthodes getElementById, getElementsByName et getElementsByTagName" ancre="exogetelement">
					<enonce href="exercices/exo6.html"/>
					<correction href="exercices/exo6cor.html"/>
				</exercice>
				<exercice titre="Petite récréation&#160;: réalisation d'une horloge" ancre="exohorloge">
					<enonce href="exercices/exo14.html"/>
					<correction href="exercices/exo14cor.html"/>
				</exercice>
				<paragraphe ancre="directelementqcq" titre="Accès aux nœuds à partir d'un élément quelconque d'un document">
					<texte>Il existe aussi des méthodes qui, à partir d'un élément donné, permettent d'accéder à certains de ses descendants&#160;:</texte>
					<liste>
						<item>
							<texte>La méthode <code>getElementsByTagName()</code>, comme précédemment, permet d'obtenir une collection d'éléments <valeur>descendants</valeur> de l'élément courant, et possédant un nom de balise donné. Par exemple,</texte>
							<exemplejavascript>
								<variable name="parag1"/><autres>=</autres><fonction name="document.getElementById"><variable name="'monpar'"/></fonction><finligne/>
								<variable name="liens"/><autres>=</autres><fonction name="parag1.getElementsByTagName"><variable name="'a'"/></fonction><finligne/>
							</exemplejavascript>
							<texte>renvoie la collection de liens dans le paragraphe identifié par <code>monpar</code>.</texte>
						</item>
						<item><texte>La méthode <code>getAttribute(nom_d_attribut)</code> permet de sélectionner un attribut particulier d'un élément déterminé.</texte></item>
					</liste>
				</paragraphe>
			</section>
			<section titre="Accès relatif" ancre="accesrelatif">
				<paragraphe titre="Introduction" ancre="relatifintro">
					<texte>Les méthodes précédentes demandent de connaître précisément soit l'identifiant, soit le nom exact du nœud cherché. Nous allons voir maintenant comment il est possible d'accéder à des collections de nœuds dont on ne connaît pas ces caractéristiques <autrelangue type="la">a priori</autrelangue>.</texte>
					<texte>Dans toute la suite, <code>elt</code> désignera un élément que l'on aura au préalable identifié (par exemple par une méthode <code>getElementById</code>).</texte>
				</paragraphe>
				<paragraphe titre="Accès aux attributs" ancre="accesattributs">
					<texte>Contrairement à la méthode <code>getAttribute()</code>, qui permet de retourner la valeur d'un attribut de nom donné, la propriété <code>attributes</code> renvoie à la collection complète des attributs d'un élément. Par exemple, si <code>elt</code> désigne l'élément <code>img</code> suivant, cette méthode renverra une liste constituée des <valeur>nœuds</valeur> <code>src</code>, <code>alt</code>, <code>width</code> et <code>height</code> (dans cet ordre)&#160;:.</texte>
					<exemple type="HTML">
						<element nom="img" vide="oui"><attribut nom="src">oiseau.gif</attribut><attribut nom="alt">Un oiseau sur un arbre</attribut><attribut nom="width">45</attribut><attribut nom="height">60</attribut></element>
					</exemple>
				</paragraphe>
				<paragraphe titre="Accès aux nœuds enfants" ancre="accesenfants">
					<texte>On peut accéder très facilement à la liste des nœuds-enfants d'un élément donné. Pour cela, trois propriétés existent.</texte>
					<liste>
						<item><texte><code>elt.childNodes</code> donne la liste de tous les nœuds-enfants de l'élément <code>elt</code> sous la forme d'un tableau.</texte></item>
						<item><texte><code>elt.firstChild</code> est équivalent à <code>elt.childNodes[0]</code>, et renvoie le premier nœud-enfant de l'élément <code>elt</code>.</texte></item>
						<item><texte><code>elt.lastChild</code> renvoie le dernier nœud-enfant de l'élément <code>elt</code>.</texte></item>
					</liste>
				</paragraphe>
				<exercice titre="Accès aux enfants" ancre="exoenfants">
					<enonce href="exercices/exo7.html"/>
					<correction href="exercices/exo7cor.html"/>
				</exercice>
				<exercice titre="Manipulation des styles des enfants" ancre="exoenfants2">
					<enonce href="exercices/exo15.html"/>
					<correction href="exercices/exo15cor.html"/>
				</exercice>
				<paragraphe ancre="accesfreres" titre="Accès aux nœuds-frères">
					<texte>Le nœud courant peut avoir des frères. On accède au frère précédent à l'aide de la propriété <code>previousSibling</code>, et au nœud suivant par la propriété <code>nextSibling</code>.</texte>
				</paragraphe>
				<paragraphe titre="Accès aux nœuds ancêtres" ancre="accesancetres">
					<texte>On peut enfin remonter d'un cran dans la hiérarchie des nœuds avec la propriété <code>parentNode</code>, et revenir à l'élément-racine d'un document (dans le cas d'un document <code type='typefichier'>HTML</code>, il s'agit bien sûr de <code>html</code>), avec la propriété <code>documentElement</code>.</texte>
				</paragraphe>
			</section>
			<section titre="Accès par les collections" ancre="accescollections">
				<paragraphe>
					<texte>Quatre collections donnent accès à différents éléments du document&#160;:</texte>
					<liste>
						<item><texte><code>window.frames</code> permet d'accéder à la liste des <autrelangue type="en">frames</autrelangue> du document courant&#160;; chaque élément de cette collection est alors du type <code>window</code>, et manipulable grâce aux propriétés et méthodes correspondantes (voir le chapitre dédié à la <reference href="window.html">manipulation des fenêtres du navigateur</reference>).</texte></item>
						<item><texte><code>document.forms</code>, <code>document.images</code> et <code>document.links</code> sont les collections des éléments de formulaire, d'images et de liens du document.</texte></item>
					</liste>
				</paragraphe>
			</section>
		</partie>
		<partie titre="Avoir des informations sur les nœuds" ancre="infonoeuds">
			<section titre="Obtenir des informations sur la nature d'un nœud" ancre="infonoeud">
				<paragraphe>
					<texte>Deux propriétés permettent d'obtenir des informations sur la nature d'un nœud déterminé&#160;: <code>nodeName</code> et <code>nodeType</code>.</texte>
					<liste>
						<item><texte><code>nodeName</code> renvoie le nom du nœud courant. Par exemple, si <code>elt</code> désigne un élément <code>img</code>, <code>elt.nodeName</code> renvoie la chaîne de caractères <code>"img"</code>.</texte></item>
						<item>
							<texte><code>nodeType</code> est d'un usage moins direct. Cette propriété renvoie au type de nœud du nœud courant, selon un code numérique.</texte>
							<tableau>
								<ligne type="header">
									<colonne id="noeud"><texte>Type de nœud</texte></colonne>
									<colonne id="valeur"><texte>Valeur renvoyée par la propriété</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>element_node</texte></colonne>
									<colonne headers="valeur"><texte>1</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>attribute_node</texte></colonne>
									<colonne headers="valeur"><texte>2</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>text_node</texte></colonne>
									<colonne headers="valeur"><texte>3</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>CDATA_section_node</texte></colonne>
									<colonne headers="valeur"><texte>4</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>entity_reference_node</texte></colonne>
									<colonne headers="valeur"><texte>5</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>entity_node</texte></colonne>
									<colonne headers="valeur"><texte>6</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>processing_instruction_node</texte></colonne>
									<colonne headers="valeur"><texte>7</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>comment_node</texte></colonne>
									<colonne headers="valeur"><texte>8</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>document_node</texte></colonne>
									<colonne headers="valeur"><texte>9</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>document_type_node</texte></colonne>
									<colonne headers="valeur"><texte>10</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>document_fragment_node</texte></colonne>
									<colonne headers="valeur"><texte>11</texte></colonne>
								</ligne>
								<ligne>
									<colonne headers="noeud"><texte>notation_node</texte></colonne>
									<colonne headers="valeur"><texte>12</texte></colonne>
								</ligne>
								<legende>Liste des codes numériques renvoyés par la méthode <code>nodeType</code>.</legende>
							</tableau>
						</item>
					</liste>
				</paragraphe>
			</section>
			<section titre="Obtenir des informations sur le contenu d'un nœud" ancre="infocontenus">
				<paragraphe>
					<texte>Deux méthodes renvoient des booléens permettant de déterminer si un nœud donné possède des enfants, et/ou des attributs. Ces méthodes, aux noms explicites, sont respectivement <code>hasChildNodes()</code> et <code>hasAttributes()</code>.</texte>
				</paragraphe>
			</section>
		</partie>
	</corpus>
</chapitre>

