Attributs personnalisés en HTML5

HTML5, parce que je me suis souvenu que le brouillon de nome autorise depuis peu l'ajout de données au code via des attributs personnalisés. La spécification précise que toute balise HTML peut avoir des attributs personnalisés, ceux-ci se caractérisant par leur nom commençant par data-. Partant de ce principe, on peut donc ajouter des données à toute balise. Par exemple, pour mon W3C, écrire:

<span data-name="World Wide Web Consortium"
data-website="http://www.w3.org"
data-wikipedia="http://fr.wikipedia.org/wiki/W3C">W3C</span>

L'inconvénient c'est que cette syntaxe va être difficile à rendre en CSS. Il va falloir utiliser du JavaScript ou, plus propre si on ne peut pas ajouter de script dans la page, du XBL[1]. On peut imaginer transformer dynamiquement chacun de ces attributs en nouvel élément, et de n'afficher ces éléments qu'au survol du mot grâce à la magie de la pseudo-classe CSS :hover.

Pour associer l'élément à un comportement XML, on utilise la propriété css -moz-binding:

<style type="text/css">
.semantic{
-moz-binding: url(semantic.xml#semantic);
}
</style>
(...)
<span class="semantic"
data-name="World Wide Web Consortium"
data-website="http://www.w3.org"
data-wikipedia="http://fr.wikipedia.org/wiki/W3C">W3C</span>

Le XBL

La structure de base du fichier XBL est la suivante:

<?xml version="1.0"?>
<bindings
xmlns="http://www.mozilla.org/xbl"
xmlns:xhtml="http://www.w3.org/1999/xhtml"
>
<binding id="semantic">
<content>
</content>
<resources>
</resources>
<implementation>
<constructor>
</constructor>
</implementation>
</binding>
</bindings>

Commençons par ajouter quelques balises dans le contenu:

<xhtml:span class="semantic-container">
<children />
<xhtml:span class="semantic-items" bbid="semantic-items">
</xhtml:span>
</xhtml:span>

Le contenu de la balise liée sera insérée à la place de la balise XBL <children />

Rajoutons quelques styles:

/* des tirets sous le texte marqué */
span.semantic-container{
border-bottom: 1px dotted;
}
/* par défaut on n'affiche pas les balises supplémentaires */
span.semantic-container span.semantic-items
{
display: none;
}
/* On les affiche lorque la souris est au dessus du contenu */
span.semantic-container:hover
{
position: relative;
}
span.semantic-container:hover span.semantic-items
{
display: block;
position: absolute;
top: 1em;
left: 0px;
background-color: #FF8;
padding: 10px;
white-space: nowrap;
-moz-border-radius: 5px;
}
/* elles seront affichées les unes en dessous des autres */
.semantic-item
{
display: block;
}

On lie la feuille de style dans la section ressources:

<resources>
<stylesheet src="semantic.css"/>
</resources>

Dernier point: ajouter dynamiquement de nouvelles balises pour chaque attribut personnalisé. On ajoute pour cela du code dans le constructeur du composant. Pour chaque attribut dont le nom commence par "data-", on crée une balise span dont le contenu est la valeur de l'attribut.

var _attrs = this.attributes;
var _def = document.getAnonymousElementByAttribute(this, "bbid", "semantic-items");
for (var i=0, _attr; _attr = _attrs[i]; i++)
{
if (_attr.name.substr(0, 5) == 'data-')
{
var _span = document.createElementNS("http://www.w3.org/1999/xhtml", "span");
_span.setAttribute("class", "semantic-item");
_span.textContent = _attr.name.substr(5) + ' : ' + _attr.value;
_def.appendChild(_span);
}
}

Vous trouverez ci-dessous le fichier xbl et le css, avec ces 2 différences:

  • le :hover sur le contenu inséré via children semble mal géré, j'ai donc dû masquer ce contenu et le ré-insérer à l'intérieur d'un autre span.
  • pour faire plus joli, je gère également des attributs data-link- que je transforme en liens.
J'aurais bien fait une démo sur ce billet, malheureusement dotclear nettoie le code pour générer du xhtml valide et supprime donc mes attributs personnalisés :-( J'ai perdu. Voici ce que vous auriez dû voir:

Et les 2 fichiers:
Tout commentaire pour améliorer la chose sera le bienvenu.

Notes

[1] ok, ça ne sera visible que des navigateurs comprenant XBL, donc essentiellement ceux basés sur Gecko.