Informatique
Table des matières (TOC) dynamique

Table des matières

Généralités

Plusieurs des pages, en particulier dans la rubrique Informatique, contiennent un long contenu. Aussi, afin de faciliter la lecture je voulais inclure une table des matières, et pour me faciliter l'édition, qu'elle soit générée dynamiquement.
J'ai donc intégré un script de Matt Whitlock qui répond à ce besoin ! Et j'ai fait apparaitre le contenu dans un panel flottant.


Fonctionnement

Structure HTML

Le contenu est intégré sous cette forme, en utilisant les nouvelles balises HTML 5 details et summary.

<details id="toc" class="toolbox">
<summary>Table des matières</summary>
<a id="toc-open" onClick="toggleToc()">+</a>
<a id="toc-close" onClick="toggleToc()">X</a>
</details>

La TOC sera ajoutée par le script sous forme d'un UL, à la fin du noeud DOM details#toc.

CSS

Pour l'affichage, j'utilise position:fixed. On évite que le contenu déborde de l'écran avec max-width et max-height ainsi qu'un overflow: auto.


.toolbox
{
position: fixed;
top: 0;
right: 0;

padding: 0.3em;

border: 1px dotted black;
border-radius: 0 0 0 10px;
background-color: gray;
opacity: 0.85;
}

details#toc
{
max-width: 50%;
max-height: 80%;
overflow: auto;
text-align: center;
}

JavaScript

L'initialisation est faite en JavaScript : appel au script, et également masquage du lien de fermeture et de la toc générée. On utilise le onDomReady déjà présent par ailleurs.
La fonction toggleToc() est cablée sur les liens d'ouverture / fermeture et va permettre d'afficher ou masquer la table.


<script src="..."></script> // librairie de Matt Whitlock
<script>
var HIDE_CLASS = "hide";

function getTocElement() {
	return document.getElementById("toc").getElementsByTagName("ul")[0];
}

// Affiche ou masque la TOC à chaque appel
function toggleToc() {
	var ul = getTocElement();
	var newDispValue = (ul.className == HIDE_CLASS) ? "" : HIDE_CLASS;

	if (newDispValue == HIDE_CLASS) {
		// on ferme la TOC
		document.getElementById("toc-open").style.display = "";
		document.getElementById("toc-close").style.display = "none";
	} else {
		// on ouvre la TOC
		document.getElementById("toc-open").style.display = "none";
		document.getElementById("toc-close").style.display = "";
	}
	ul.className = newDispValue;
}

onDomReady(function() {
	generateTOC(document.getElementById("toc"));
	getTocElement().className = HIDE_CLASS;
	document.getElementById("toc-close").style.display="none";
});
</script>

CSS transition

La partie une peu délicate... L'intégration de transitions CSS !
Au départ j'ai masqué la TOC par un simple display: none. Erreur ! C'est une propriété qui n'est pas gérée dans les CSS Transition...

Une solution possible est présentée sur ce chouette article : Hiding elements and CSS animations | Rhumaric, pixel distiller. Mais c'est quand même assez "overkill"...
Une autre ici : Créer un volet coulissant en CSS3 avec :target et transition - Alsacreations. Mais difficilement applicable dans mon cas...
J'ai tenté d'utiliser une classe nommée "hide" comme ci-dessous, qui joue sur width, height et opacity plutôt que display. L'affichage et le masquage de la TOC se fait donc en jouant sur la valeur de l'attribut className du noeud (vide ou avec la valeur "hide").


details#toc>ul
{
transition: all .7s ease-in-out;
}

details#toc>ul.hide, details#toc>ul.hide *
{
width: 0;
height: 0;
opacity: 0;
}

Il ne s'agit clairement pas d'une solution idéale : la transition ne s'exécutant pas à la fermeture, des artefacts de liens restant après fermeture, et des problèmes apparaissant avec le overflow: auto !... Ca sera à améliorer plus tard, et donc pour l'instant pas de transitions !


Création le 13/08/2014
Dernière mise à jour le 14/08/2014

Un oubli, une erreur, une suggestion ? Rendez-vous sur le dépôt GitHub !