Mes impressions sur le web, les standards et autres…


DOM Core : Nœuds et position

Il y a quelques mois de cela, je travaillais sur mon script show-quote.js, et j’étais confronté à un problème insoluble : Il me fallait déterminer, à chaque fois que l’évènement mouseout était déclenché, si la cible de destination du curseur (Event.relatedTarget) se trouvait dans le bloc de citation, et si ce n’était pas le cas, masquer le bloc affichant le lien source de la citation (attribut cite de l’élément BLOCKQUOTE).

MSIE dispose de la méthode Element.contains() (non-standard) pour cela :

// Renvoie true si otherElt est un descendant de myElt, false sinon.
var result = myElt.contains(otherElt);

Je n’avais toutefois pas trouvé d’équivalent standard à l’époque et je m’étais rabattu sur une solution un peu barbare dans le cadre de mon script :

var result = ( citation.parentNode.parentNode == evt.relatedTarget );

Ignoble, n’est-ce pas ? J’ai enfin trouvé une méthode standard pour gérer cela : Node.compareDocumentPosition(). Elle a été ajoutée dans le DOM niveau 3. Cette méthode est utilisable sur tous types de nœud contrairement à la méthode Element.contains() et renvoit un bitmask du positionnement entre les deux nœuds. On peut ainsi savoir si l’un est descendant ou ancêtre de l’autre, lequel suit l’autre dans l’ordre logique du document, …

J’ai donc modifié mon script pour utiliser cette méthode (c’est beaucoup plus propre à mon goût) et créé une page d’ exemple d’utilisation de Node.compareDocumentPosition(). Enfin, pour ceux qui n’auraient pas de scrupules à simuler Element.contains() sur Mozilla (et donc utiliser du code propriétaire, même si derrière, c'est standard), voilà le morceau de code :

Element.prototype.contains = function(otherElt) {
    return (this.compareDocumentPosition(otherElt) & this.DOCUMENT_POSITION_CONTAINED_BY) ? true : false;
};

Ce bout de code rendra disponible une méthode Element.contains() sur tous les nœuds de type élément et au fonctionnement similaire à celle de l’API de Microsoft.