§ getElementById

Introduction

J’ai connu le bon vieux temps où getElementById n’existait pas (j’aime bien, comme intro, ça fait vieux croûton nostalgique). Le temps où il fallait revoir sa tactique si l’on voulait accéder à un élément, selon que l’on soit sous IE ou sous Netscape. Depuis, les navigateurs ont fleuri, les usual suspects sus-mentionnés ont évolué et getElementById a fait son entrée sur le devant de la scène.

Pourtant, lorsque l’on furète un peu, on se rend bien vite compte que cette fonction magique n’est pas encore maîtrisée par la horde chaque jour plus nombreuse de sorciers en devenir qui se lancent dans JavaScript. Un tantinet ennuyeux, parce que, sous-jacente, pointe l’ignorance du DOM. Mais comme je ne me sens pas l’âme à parler du DOM, je vais juste expliquer ce qui va nous être utile pour comprendre getElementById – et ses petites sœurs getElementsByName, getElementsByTagName.

Exemple de représentation du DOM en arbre.

DOM

Pour faire simple, le Document Object Model (DOM) est une interface de programmation développée par le W3C permettant de créer et modifier des pages HTML – et des documents XML – en manipulant les objets qui les modélisent. Ces objets permettent de modifier à la fois l’apparence et le contenu des « balises » qu’ils représentent en appelant leurs méthodes et propriétés. Une page ainsi modélisée devient un arbre qu’il est possible de parcourir.

Parcourir. C’est donc ici qu’intervient notre getElementById. Pour retrouver un objet dans l’arbre, une des méthodes offertes par le DOM est getElementById, permettant de retrouver un objet par son identifiant :

var elt = document.getElementById("elementId");

Cacher, montrer un bloc de texte

Une fois cet objet récupéré, tout est fait : il n’y a plus qu’à « jouer » avec ses propriétés CSS. Une des première propriétés, une des plus utiles, est display : elle permet de cacher ou faire apparaître un objet.

Mon ancre

J’apparais, disparais à l'envi.

Le code pour ce petit exemple est extrêmement simple :

function cacheCache(id, vis)
{
	if (document.getElementById)
	{
		var elt = document.getElementById(id);
		elt.style.display = vis;
	}
}
cacheCache('elt', 'none');

La fonction cacheCache prend deux paramètres : id, qui sera l’identifiant de la balise à cacher/montrer, et vis la valeur de la propriété display à modifier. La première chose que fait cette fonction est de tester si la fonction getElementById existe : if (document.getElementById). Si cette fonction existe, on peut effectivement récupérer l’objet dont l’id est id. On manipule ensuite cet objet en modifiant la propriété display appartenant au style en affectant vis : elt.style.display = vis;.

Une fois cette fonction définie, on l’appelle pour « initialiser » notre bloc et le cacher : cacheCache('elt', 'none');. L’intérêt de cette méthode est double :

  • Si le JavaScript est désactivé, le bloc n’est pas caché et tout le monde peut tout de même lire son contenu ;
  • Si la méthode getElementById n’existe pas (en d’autres termes, si le DOM n’est pas supporté, le bloc n’est pas caché non plus.

Dans les cas extrêmes, elle permet donc de contourner les problèmes.

Il faut ensuite indiquer au navigateur que lorsque la souris passe sur le lien, le bloc apparaît, lorsque la souris quitte le lien, le bloc disparaît. Pour cela, on utilise les événements onmouseover et onmouseout :

<a href="#" 
   onmouseover="cacheCache('elt', 'block'); return false;" 
   onmouseout="cacheCache('elt', 'none'); return false;">Mon ancre</a>

Ces événements appellent notre fonction et désignent l’élément à cacher/montrer par son identifiant elt Là encore, en cas de coup dur, notre test if (document.getElementById) permet de s’en sortir à peu de frais : le bloc est visible et rien ne se passe lorsque l’on passe la souris sur le lien.

Ajoutons un peu de style...

Il suffit alors de manipuler CSS pour parvenir à des choses à la fois esthétiques et dynamiques. Par exemple, il est possible de créer le menu suivant :

Cette fois-ci, l’affaire est plus compliquée, et plusieurs styles à la fois sont modifiés : il est temps de trouver une autre méthode pour modifier notre style. Nous allons donc définir deux styles : un style pour le bloc caché, un style pour le bloc ouvert. La fonction cacher/montrer que nous avons vue tout à l’heure va désormais nous permettre d’affecter une nouvelle classe au bloc pour en modifier le style :

function activerMenu(source, menuNom)
{
	if (document.getElementById)
    {
		var menu = document.getElementById(menuNom);
		if (menu.className == 'ss-menu')
		{
			menu.className = 'ss-menu-open';
		}
		else 
		{
			menu.className = 'ss-menu';
		}
	}
}

Nous avons deux paramètres à cette fonction : la source du clic et le nom du sous-menu à cacher/montrer. Comme tout à l’heure, on vérifie au préalable que la fonction getElementById existe bien, puis on vérifie la classe du sous-menu. Si la classe est ss-menu, le sous-menu est fermé et caché ; si la classe ss-menu-open, le sous-menu est ouvert et visible. Il suffit alors d’inverser la tendance.

Si la classe est ss-menu, il faut ouvrir le sous-menu et pour ça, on appelle la propriété className et on lui affecte la classe pour un sous-menu ouvert :

		if (menu.className == 'ss-menu')
		{
			menu.className = 'ss-menu-open';
		}

Sinon, on lui affecte la classe pour un menu fermé, toujours en utilisant la propriété className :

		else 
		{
			menu.className = 'ss-menu';
		}

Maintenant, il faut initialiser les sous-menus et les cacher. Comme précédemment, il faut s’assurer que tout se passe bien 1) si le JavaScript est désactivé et 2) si le DOM n’est pas supporté.

On utilise donc un bout de script qui s’exécute automatiquement au chargement de la page et qui va écrire les styles CSS :

document.write ('<style>.ss-menu { display: none; } ¶
   .ss-menu-open { display: block; }</style>');
if (!document.getElementById)
	document.write ('<style>.ss-menu { display: block; }</style>');

La première ligne définit les deux classes (menu fermé, menu ouvert) ; les deux lignes suivantes interviennent si getElementbyId existe : la classe CSS est réécrite pour ne plus fermer le menu. Selon les règles de priorité des classes, c’est cette dernière qui sera prise en compte et les sous-menus seront ouverts.

Qu’advient-il si le JavaScript ne marche pas ? Les règles ne sont pas écrites et les menus restent ouverts. Tout va bien.

Pour finir, voici le code HTML qui correspond au menu :

<div id="main-menu">
<ul>
<li class="menu"><a href="#" ¶
       onClick="activerMenu(this, 'menu1'); ¶
       return false;" 
       class="niv1">Niveau 1.1</a>
       <div id="menu1" class="ss-menu">
       <ul>
       <li>Niveau 2.1</li>
       <li>Niveau 2.2</li>
       <li>Niveau 2.3</li>
       </ul>
       </div>
</li>
<li class="menu"><a href="#" 
       onClick="activerMenu(this, 'menu2'); 
       return false;" 
       class="niv1">Niveau 1.2</a>
       <div id="menu2" class="ss-menu">
       <ul>
       <li>Niveau 2.1</li>
       <li>Niveau 2.2</li>
       <li>Niveau 2.3</li>
       </ul>
       </div>
</li>
</ul>
</div>

Virtuellement...

Avec getElementById et className, il devient possible de faire n’importe quoi : il suffit de comprendre que le premier permet de récupérer n’importe quel objet et que le second permet de changer la classe (et donc l’apparence) de cet objet. Vous pouvez ainsi faire bouger un objet en modifiant sa classe, le faire clignoter, le cacher, le mettre en valeur, etc. C’est toute la force du DOM, base du DHTML. De bien nombreux exemples peuvent être trouvés, et soyez sûrs que je ne manquerai pas d’en présenter ici quelques-uns.

Pour aller plus loin...