Le DOM Scripting

Share:
Nous allons explorer au cours du présent article les avantages et parfois les complexités du DOM Scripting. Avant d’aller plus loin, voyons une définition succincte de ce qu’est le DOM Scripting. Ou de ce qu’il y a quelques années, on appelait le DHTML, qui suite à la guerre des navigateurs (the browser war) n’a pas eu un avenir brillant et a été supplanté par une nouvelle techno qui se nommait Flash.

Aujourd’hui, le DOM Scripting est une technique qui permet de manipuler le DOM d’une page web, ou de tout document structuré, à l’aide d’un langage de programmation. Javascript, ou jQuery, permet de gérer cela très facilement, et de ce fait, tout se passe côté client déchargeant ainsi le travail côté serveur.

Avantages et utilisations

L’interface utilisateur des applications peut donc être très souple à utiliser, pouvant ainsi adapter son ergonomie au contexte et faire évoluer le contenu, enrichissant ainsi largement l’expérience utilisateur.
Prévoir des fenêtres ou des espaces, déplaçables et modulables au sein d’une même page, anticiper la réorganisation du contenu en fonction des interactions, améliorer le ré-agencement de certaines données, proposer l’auto-complémentation des champs, lors de la saisie d’informations,… bref, les utilisations sont multiples et non exhaustives. De plus, si nous couplons ces interactions avec la gestion directe des CSS, de l’affichage et de la disposition des éléments, bien d’autres portes encore plus immergées s’ouvrent alors, et permettent des effets visuels de transitions ou de présentations : comme les classiques menus à onglets, les contenus accordéons, les sliders personnalisés, les fenêtres compilables, etc…
On serait tenté de penser que le DOM Scripting et AJAX cohabitent et vont de pair. En fait, cela est vrai en partie, mais pas systématique. L’un peut exister sans l’autre. Rappelons-nous qu’AJAX est avant tout, un ensemble de technologies dont DOM, Javascript et CSS font également partie.
L’apport d’AJAX permet d’ajouter au DOM le chargement de données complémentaires sans devoir recharger l’intégralité de la page. Rapprochez-vous des articles XMLHttpRequest et le formatage des données ou de jQuery et AJAX, lasynchrone en toute simplicité. Le DOM Scripting seul, permet de manipuler des données reçues ou déjà présentes dans le document, afin de les réorganiser de manière plus ergonomique ou contextuelle, suite à l’interaction de l’application ou de l’utilisateur.

Relation script / document

Affranchissons nous de la problématique du temps de chargement de la page, avant d’essayer d’interagir avec le contenu de nos pages.
En effet, le chargement de la page et de ses fichiers liés se fait de manière procédurale… c’est-à-dire au fur et à mesure de la lecture du document, en partant du haut vers le bas.
Si nous exécutons un code Javascript chargé dans l’entête du fichier HTML, il est certain que la page HTML elle-même, ne sera pas intégralement chargée à ce moment-là. Pour mettre en évidence cette problématique, créons un document HTML contenant simplement 3 paragraphes. Plaçons ensuite un premier <script> dans la balise <head> d’entête du document et un second <script> juste avant la fermeture de la balise </body>.
Chacun de ces script, hormis un élément textuel qui le distinguera, contiendra la même instruction Javascript supposée comptabiliser les balises <p> :
alert("Depuis le <head>/<body> : " + document.getElementsByTagName('p').length)
Alerte
Lancez la page d’illustration prévue à cet effet. L’évidence veut que le premier message affiche depuis le script : 0 et le second depuis le body : 3.
En fait, lorsque le script placé dans l’entête s’exécute, l’intégralité de la page n’est pas encore chargée, ce qui explique le 0 élément <p> qui ne sont toujours pas chargés. Alors que lorsque le script est lancé depuis la page, juste avant la fermeture de la balise </body>, le contenu précédent est forcément entièrement chargé, et les 3 éléments <p> sont bien interceptés, donc comptabilisés.

Gestion discrète du Javascript

JavaScript disableBien qu’il soit tentant d’apporter énormément de fonctionnalités à nos pages en s’appuyant sur javascript, il est important de prendre en considération que certains internautes désactivent l’utilisation du javascript sur leur navigateur.
Il est donc important de ne pas exclusivement baser l’interaction de nos contenus sur cette mécanique et de penser à proposer des solutions alternatives, certes moins riches en expérience utilisateur, mais toujours fonctionnelles.
En effet, si l’utilisateur a choisi de désactiver Javascript sur son navigateur, aucune interaction n’étant possible, la page peut devenir plus difficilement utilisable en dehors de la lecture de son propre contenu.
Pour cela, il est bon de penser aux interactions du Javascript comme un complément de fonctionnalités, un confort ergonomique supplémentaire et un enrichissement de l’expérience utilisateur.

Externalisation des scripts

De la même manière, il est intéressant et même recommandé, d’externaliser les feuilles de style CSS. Il en va de même pour les fichiers Javascript. Nous allons donc externaliser l’ensemble des fichiers Javascript utilisés dans une page. Il est donc préférable d’ajouter toutes instructions et évènements liés à Javascript, qu’il s’agisse d’interactions propres au document ou liées à l’utilisateur, plutôt que de placer ces évènements dans le document HTML sous forme d’attributs de balise. Par exemple le genre de code ci-dessous est à éviter afin de rendre chaque acteur (HTML, Javascript, CSS…) indépendants les uns des autres et également réutilisables.
<body onload="alert('coucou');">
<p onclick="alert('coucou');">
Les pages possèderont donc leur propre fonctionnement sans Javascript, et s’enrichiront au chargement de celui-ci, si celui-ci est activé pour le navigateur.
Pensez continuellement à tester le comportement de vos pages en désactivant Javascript. A ce sujet, Firefox offre parmi la pléïade d’outils de la web developer tool’s bar, un menu très fonctionnel à cet effet. En ce qui concerne les autres navigateurs, le site libellules.ch propose un article (qui date un peu certes, mais qui reste bien utile), Activer Javascript dans votre navigateur.

Prise en compte de l’évènementiel

Bien qu’il existe une multitude de fonctions évènementielles, nous allons nous concentrer sur les deux principales, qui sont le chargement d’un objet, quel qu’il soit, page, document, image, etc… et l’interaction utilisateur au travers de la souris, avec un clic sur un lien de type <a> ou sur tout autre élément que le DOM ciblera.
Depuis les dernières générations de navigateurs, le w3c ne cesse de recommander l’utilisation du DOM de niveau 2 sur les évènements qui procure des spécificités sur l’utilisation assez géniale d’écouteurs. Mais il existe encore des divergences entre les mastodontes de l’édition de navigateur.

Gestion du load

Différentes manières d’utiliser l’évènementiel :
  • soit on affecte un évènementiel à l’objet window, sous la forme d’un pointeur vers une fonction,
  • soit on place directement un écouteur sur l’objet window. Nous abroderons pas au court de cet article les diverses finesses d’une telle méthode en explorant les phases de capture ou de bubling.
window.onload=actionAgerer
window.addEventListener("load",actionAgerer,true)
Les deux manières fonctionnent et sont utilisables, comme nous pouvons le constater sur la page d’illustration. Cependant, comme d’habitude chacune de ces possibilités vient avec son lot d’avantages et bien sûr son lot d’inconvénients. Le principal inconvénient de l’ajout sous forme de pointeur vient que le dernier pointeur assigné écrasera le précédent… Plusieurs articles discutaillent le sujet, notamment :
  • Introduction to events – sur Quirksmode
  • Separating behavior and structure – sur Digital Web
Quoiqu’il en soit, comme la palisse dirait, il faut bien utiliser une méthode qui soit efficace dans notre situation et qui réponde à nos besoins. Pour la suite de ce tutoriel, nous allons utiliser la méthode proposée par Peter-Paul Koch, qui consiste à ajouter autant de fonctions à traiter lors du chargement au sein d’un gestionnaire master :
function addLoadEvent(func) {
var oldonload = window.onload;
if (typeof window.onload != 'function') {
window.onload = func;
} else {
window.onload = function() {
oldonload();
func();
}
}
}

Gestion du click

En ce qui concerne la gestion des interactions utilisateur basées sur des clics, ou autre type d’entrées, il existe également diverses manières de les apposer. La première, la plus simple, la plus directe et pas forcément la plus efficace, loin s’en faut, le pseudo protocole javascript. En effet dans l’attribut href d’un lien, il suffit de pointer sur un lien du style :
<a href="javascript:actionAgerer();">...</a>
Deux soucis, d’une part beaucoup de navigateurs anciens ne gèrent pas ce protocole et du coup ne suivent pas l’interaction, de plus, et si l’utilisateur à désactivé Javascript, toute action et interaction seront perdes. Alors, une manière un peu détournée est d’utiliser le gestionnaire d’évènement au sein de la balise <a> et de renseigner l’attribut href par un #, à la manière du script indiqué ci-après. Attention, en utilisant cette méthode cela nous oblige à placer une interaction javascript au sein même des balises HTML, et de ce fait nous ne respectons plus la pleine séparation des acteurs :
<a href="#" onclic="actionAgerer();return false;">...</a>
Le return false en fin de fonction est utile afin d’éviter que l’attribut href soit intercepté. Bien que sa valeur ne soit pas une url qui redirigerait la page vers un autre emplacement, l’ancre # est reconnue par beaucoup de navigateurs qui interpréteraient cela comme un rechargement de la page sur le sommet.
Enfin, une dernière variante consiste à utiliser le DOM Scripting pour créer à la volée des actions combinées, utilisant soit la propriété onclic d’un objet et en plçant ainsi un pointeur vers une fonction, soit en plaçant un écouteur sur l’élément affecté par l’interaction, comme nous l’avions vu précédemment lors de la gestion du load. Vous pouvez vérifier le résultat depuis la page d’illustration :
objet.onclick = actionAgerer
objet.addEventListener("click",actionAgerer,true)
Pour la suite de l’article, nous utiliserons alternativement objet.onclik = actionAgerer ou objet.addEventListener("click",actionAgerer,true). Libre à vous par la suite d’adapter le style et le code à vos besoins.

Illutration basique d’une manipulation du DOM

Bien sur le DOM Scripting, ne s’arrete pas simplement à l’ajout d’interaction, il est également possible de pouvoir intervenir directement sur la nature même du contenu, en supprimmant, modifiant, ajoutant du contenant structuré ou non. En complément de l’agissment sur la structure, il est aussi possible de pleinement s’appuyer sur des feuilles de style, ou sur l’ajout direct de style sur les éléments eux-mêmes.
Pour mettre en place une telle illustration (qui je l’admets sera ridiculement pauvre, à coté de ce que l’on peut voir sur le web) mais qui permettra de comprendre simplement le role de chaque acteur et les mécaniques sur lesquelles agir. En rappel, il nous suffit, donc, de mettre un peu de HTML, un peu de Javascript et un brin de CSS, de mélanger le tout et hop, et le tour sera joué. Commençonc par visualiser le document d’illustration qui va nous servir de base d’expérimentation. Il est composé de quelques balises d’entête, de paragraphes, de quelques balises d’emphase et d’une liste.
Découpons les opérations en deux phases. Dans un premier temps mettons en place un comptage de tout ces éléments et affichons le résultat directement dans la page. Ensuite, apportons un brin d’interactivité aux paragraphes en les colorant de rouge uniquement au moment de leur survol.

Première étape, comptage des éléments

Afin de simplifier l’analyse du code, bien qu’agissant de manière séparées, nous placerons l’ensemble des acteurs sur le même document qui nous servira de page d’illustration. Commencons par ajouter un écouteur de chargement du document afin de s’assurer de commencer à interagir avec le contenu une fois que celui-ci sera pleinement chargé. Définissons alors la liste des éléments que nous souhaitons comptabiliser et en s’appuyant sur l’article les bases du DOM, plus précisément dans la partie Description de l’API du DOM, créons le contenu HTML qui va afficher le résultat du comptage.
Ce contenu HTML est constitué, d’un bloc <div> contenant un titre de niveau <h2>, et d’une liste <ul> composée d’autant d’éléments <li> que d’éléments à comptabiliser. Une simple boucle nous permettra d’ajouter au fur et à mesure chacun de ces résultats. Il nous suffira enfin d’adjoindre une classe à ce nouveau bloc et enfin de placer le tout à la fin de la balise <body>.
var pioche = ['h1','h2','p','ul','strong']

// Mise en place du titre pour les résultats
var DOMTitre = document.createElement('h2')
var DOMTitreTexte = document.createTextNode("Comptage des éléments")
DOMTitre.appendChild(DOMTitreTexte)

// Comptage des balises et ajout du résultat dans une liste
var DOMListe = document.createElement('ul')
for (var i=0,nb=pioche.length; i<nb; i++){
var tmp = document.getElementsByTagName(pioche[i])
var DOMItem = document.createElement('li')
var texte = tmp.length + " éléments de type " + pioche[i]
var DOMItemTexte = document.createTextNode(texte)
DOMItem.appendChild(DOMItemTexte)
DOMListe.appendChild(DOMItem)
}

// Affichage du titre et de la liste des résultats
var DOMBloc = document.createElement('div')
DOMBloc.className = "fond"

DOMBloc.appendChild(DOMTitre)
DOMBloc.appendChild(DOMListe)
document.body.appendChild(DOMBloc)

Seconde étape, ajout de l’interaction sur les paragraphes

Dans la première étape nous avons joué sur l’ajout d’une classe afin de styler le bloc, nous allons cette fois-ci agir sur les style direct d’élément. Toujours dans la fonction de chargement du document, ajoutons une boucle pour affecter l’ensemble des paragraphes. Apposons leur un déclenchement lors des évènements mouseover et mouseout, afin d’être en accord avec l’ensemble des navigateurs. Ce déclenchement aura pour objectif d’intervenir sur le style direct de l’élément en initiant sa couleur à rouge lors du survol et à noir au moment où la souris quitte l’élément. Nous pouvons consulter la page d’illustration.
// Ajout d'interaction sur les paragraphes
var p = document.getElementsByTagName('p')
for (var i=0,nb = p.length; i<nb ; i++) {
p[i].onmouseover = function(){
this.style.color = 'red'
}
p[i].onmouseout = function(){
this.style.color = 'black'
}
}

Conclusion

Bien que cette prise en main du DOM scripting ne fasse qu’effleurer la surface des possibilités, nous pouvons comprednre rapidement les avantages d’une telle solution au sein de nos pages. L’ensemble de cette approche peut également s’appuyer sur des librairies comme jQuery et nous permettre ainsi d’aller encore plus simplement plus loin dans nos améliorations d’expériences utilisateurs. Rendant ainsi nos interfaces plus ergonomiques, plus intutive et adaptées aux internautes en fonction de leurs besoins. N’oublions pas cependnant que de telles fonctionnalités ne sont accessible que dans le cas ou la prise en charge de Javascript soit activé sur les navigateurs de consultation.

No comments