Skip to content

Instantly share code, notes, and snippets.

@hsablonniere
Created May 15, 2012 16:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hsablonniere/2703281 to your computer and use it in GitHub Desktop.
Save hsablonniere/2703281 to your computer and use it in GitHub Desktop.
HTML headings to JavaScript table of contents : getJsToc

HTML headings to JavaScript table of contents : getJsToc

Build a JavaScript table of contents from an HTML document.

If you need to build and/or exchange the table of contents of an HTML document you've come to the right place. If you don't need that, well... good day to you ;-)

What's the effin point?

Well I needed to exchange the TOC of an HTML document. I thought JSON was the best choice. It can be send to another party and be parsed and traversed...

Usage

Just add the getJsToc function in your web page and call it like one of these examples :

var jsToc = getJsToc();
// On the first article
var jsToc = getJsToc('article');
// On a wikipedia page for example
var jsToc = getJsToc('#content', function (node) {
  if (node.lastElementChild) {
    return node.lastElementChild.innerHTML;
  } else {
    return node.innerHTML;
  }
});

?/!

If you have any ideas to improve this code or if you think something is wrong, feel free to start a discussion...

Hubert SABLONNIÈRE @hsablonniere

/**
* Create a JavaScript object representing the TOC of an HTML document
*
* @param rootSelector Selector for the root node where to start computing the TOC (defaults : 'body')
* @param titleTextFct Function to retrieve the text content from a heading node (defaults : returns innerHTML on the node)
*/
var getJsToc = function (rootSelector, titleTextFct) {
rootSelector = rootSelector || 'body';
titleTextFct = titleTextFct || function (node) {
return node.innerHTML;
};
var nodes = document.querySelector(rootSelector).querySelectorAll('h1, h2, h3, h4, h5, h6'),
i,
type,
title,
item,
tree = {type: '', title: 'toc', children: []},
lasts = [tree];
for (i = 0; i < nodes.length; i++) {
type = nodes[i].nodeName.toLowerCase();
title = titleTextFct(nodes[i]);
item = {
type: type,
title: title,
children: []
};
if (lasts[0].type < type) {
lasts.unshift(item);
lasts[1].children.push(item);
} else if (lasts[0].type === type) {
lasts[0] = item;
lasts[1].children.push(item);
} else if (lasts[0].type > type) {
while (lasts[0].type > type) {
lasts.shift();
}
lasts[0] = item;
lasts[1].children.push(item);
}
}
delete tree.type;
return tree;
};
<!DOCTYPE html>
<title>getJsToc test page</title>
<style type="text/css">
#content,
#json-reference,
#json-result {
border: 1px solid #CCC;
height: 200px;
margin-bottom: 10px;
overflow: auto;
width: 80%;
}
#json-result.ok {
color: green;
}
#json-result.nok {
color: red;
}
</style>
<h1>getJsToc test page</h1>
<h2>HTML reference</h2>
<div id="content">
<h1>Hoc non est positum in nostra actione.</h1>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Si longus, levis. At eum nihili facit; Videsne, ut haec
concinant? Itaque fecimus. Restatis igitur vos; Duo Reges: constructio interrete. Quid nunc honeste dicit? Istic
sum, inquit. </p>
<h2>Quis non odit sordidos, vanos, leves, futtiles?</h2>
<p>Si quicquam extra virtutem habeatur in bonis. Refert tamen, quo modo. Certe, nisi voluptatem tanti aestimaretis.
Istam voluptatem, inquit, Epicurus ignorat? </p>
<p>Tibi hoc incredibile, quod beatissimum. Non est igitur voluptas bonum. Velut ego nunc moveor. Tibi hoc incredibile,
quod beatissimum. </p>
<p>Nihil sane. Non est igitur voluptas bonum. Tubulo putas dicere? Negare non possum. </p>
<h3>Quam ob rem tandem, inquit, non satisfacit?</h3>
<p>Haeret in salebra. Sint ista Graecorum; Nos cum te, M. Sullae consulatum? Itaque ad tempus ad Pisonem omnes. Dici
enim nihil potest verius. </p>
<p>Egone quaeris, inquit, quid sentiam? Tum mihi Piso: Quid ergo? Urgent tamen et nihil remittunt. Qui-vere falsone,
quaerere mittimus-dicitur oculis se privasse; An tu me de L. Quonam modo? </p>
<p>Haec dicuntur inconstantissime. Nescio quo modo praetervolavit oratio. Frater et T. Deinde dolorem quem maximum? Et
nemo nimium beatus est; Comprehensum, quod cognitum non habet? </p>
<h4>Conclusum est enim contra Cyrenaicos satis acute, nihil ad Epicurum.</h4>
<p>Quorum sine causa fieri nihil putandum est. Si quicquam extra virtutem habeatur in bonis. Sed quod proximum fuit
non vidit. Qui convenit? Zenonis est, inquam, hoc Stoici. </p>
<p>Cur deinde Metrodori liberos commendas? Nam ante Aristippus, et ille melius. Quae cum dixisset paulumque
institisset, Quid est? Quantum Aristoxeni ingenium consumptum videmus in musicis? </p>
<p>Videsne quam sit magna dissensio? Laboro autem non sine causa; Si quidem, inquit, tollerem, sed relinquo. Honesta
oratio, Socratica, Platonis etiam. Quae duo sunt, unum facit. Quis istud possit, inquit, negare? </p>
<h3>Dolere malum est: in crucem qui agitur, beatus esse non potest.</h3>
<p>Quae sequuntur igitur? Praeteritis, inquit, gaudeo. An nisi populari fama? Stoicos roga. </p>
<p>Vestri haec verecundius, illi fortasse constantius. Rationis enim perfectio est virtus; Si enim ad populum me
vocas, eum. Quae contraria sunt his, malane? </p>
<p>Quid, quod res alia tota est? Erit enim mecum, si tecum erit. Sed fortuna fortis; </p>
<h3>Ut in geometria, prima si dederis, danda sunt omnia.</h3>
<p>Quis negat? Quae cum essent dicta, discessimus. Apparet statim, quae sint officia, quae actiones. Tibi hoc
incredibile, quod beatissimum. </p>
<h5>Conferam tecum, quam cuique verso rem subicias;</h5>
<p>Quid sequatur, quid repugnet, vident. Itaque his sapiens semper vacabit. </p>
<p>Quare attende, quaeso. Non risu potius quam oratione eiciendum? Scrupulum, inquam, abeunti; </p>
<h5>Dicimus aliquem hilare vivere;</h5>
<p>Etiam beatissimum? Sumenda potius quam expetenda. Nemo igitur esse beatus potest. Proclivi currit oratio. </p>
<h6>An vero, inquit, quisquam potest probare, quod perceptfum, quod.</h6>
<p>Quae cum dixisset, finem ille. Sequitur disserendi ratio cognitioque naturae; Satis est ad hoc responsum. </p>
<h6>Theophrastus mediocriterne delectat, cum tractat locos ab Aristotele ante tractatos?</h6>
<p>Iam in altera philosophiae parte. Hoc simile tandem est? Avaritiamne minuis? Tuo vero id quidem, inquam, arbitratu.
Summae mihi videtur inscitiae. Quis negat? </p>
<p>At eum nihili facit; Huius ego nunc auctoritatem sequens idem faciam. </p>
<p>Sint modo partes vitae beatae. Proclivi currit oratio. Aufert enim sensus actionemque tollit omnem. Quae duo sunt,
unum facit. Sed haec omittamus; Equidem e Cn. </p>
<p>Suo enim quisque studio maxime ducitur. Urgent tamen et nihil remittunt. Quod vestri non item. Fortemne possumus
dicere eundem illum Torquatum? Scaevolam M. Cave putes quicquam esse verius. Nulla erit controversia. </p>
<p>Videsne quam sit magna dissensio? Minime vero, inquit ille, consentit. Omnia peccata paria dicitis. Igitur ne
dolorem quidem. </p>
<p>Primum Theophrasti, Strato, physicum se voluit; Et nemo nimium beatus est; Facete M. Bonum patria: miserum exilium.
Quid Zeno? </p>
<p>Ipse Epicurus fortasse redderet, ut Sextus Peducaeus, Sex. Qui convenit? Summus dolor plures dies manere non
potest? Sed ad bona praeterita redeamus. </p>
<h3>Qui autem esse poteris, nisi te amor ipse ceperit?</h3>
<p>Age, inquies, ista parva sunt. At enim sequor utilitatem. Cur iustitia laudatur? Si longus, levis dictata sunt.
Memini vero, inquam; Sed quot homines, tot sententiae; </p>
<p>Hunc vos beatum; Quae duo sunt, unum facit. Honesta oratio, Socratica, Platonis etiam. Praeclare hoc quidem. Minime
vero, inquit ille, consentit. </p>
<h3>Profectus in exilium Tubulus statim nec respondere ausus;</h3>
<p>Tum Torquatus: Prorsus, inquit, assentior; Illa tamen simplicia, vestra versuta. Confecta res esset. Tollenda est
atque extrahenda radicitus. Non semper, inquam; Itaque fecimus. </p>
<h2>Hoc non est positum in nostra actione.</h2>
<p>Non quam nostram quidem, inquit Pomponius iocans; Quo modo autem philosophus loquitur? Restatis igitur vos;
Moriatur, inquit. </p>
<h2>Laelius clamores sofow ille so lebat Edere compellans gumias ex ordine nostros.</h2>
<p>Cave putes quicquam esse verius. Nihil ad rem! Ne sit sane; Erat enim Polemonis. Hos contra singulos dici est
melius. Suo genere perveniant ad extremum; At certe gravius. Poterat autem inpune; Illa tamen simplicia, vestra
versuta. </p>
<p>Cur iustitia laudatur? Age sane, inquam. Certe non potest. Ut pulsi recurrant? Certe, nisi voluptatem tanti
aestimaretis. Non quam nostram quidem, inquit Pomponius iocans; </p>
<p>Vide, quaeso, rectumne sit. Res enim concurrent contrariae. Sed fortuna fortis; Sed fortuna fortis; Quis hoc dicit?
Nunc de hominis summo bono quaeritur; Refert tamen, quo modo. </p>
<h2>Expectoque quid ad id, quod quaerebam, respondeas.</h2>
<p>Immo videri fortasse. Prave, nequiter, turpiter cenabat; Omnia peccata paria dicitis. Quonam modo? </p>
<p>Pugnant Stoici cum Peripateticis. Si enim ad populum me vocas, eum. An tu me de L. Istic sum, inquit. </p>
<h3>Certe, nisi voluptatem tanti aestimaretis.</h3>
<p>De illis, cum volemus. Sed ad bona praeterita redeamus. In schola desinis. Quae duo sunt, unum facit. At enim hic
etiam dolore. Hoc simile tandem est? Istam voluptatem, inquit, Epicurus ignorat? Quis istud possit, inquit,
negare? </p>
<h3>Suo genere perveniant ad extremum;</h3>
<p>Si quidem, inquit, tollerem, sed relinquo. Istic sum, inquit. Nescio quo modo praetervolavit oratio. Oratio me
istius philosophi non offendit; Occultum facinus esse potuerit, gaudebit; Sullae consulatum? </p>
<p>Proclivi currit oratio. Quod vestri non item. Moriatur, inquit. Proclivi currit oratio. Quis istud possit, inquit,
negare? Sed ad bona praeterita redeamus. Nullus est igitur cuiusquam dies natalis. </p>
<h4>Itaque hic ipse iam pridem est reiectus;</h4>
<p>Mihi enim satis est, ipsis non satis. Quae cum dixisset, finem ille. De illis, cum volemus. Hoc simile tandem est?
Itaque his sapiens semper vacabit. Quo modo autem philosophus loquitur? Nihil illinc huc pervenit. Bonum incolumis
acies: misera caecitas. Videsne, ut haec concinant? </p>
<h4>Quod autem magnum dolorem brevem, longinquum levem esse dicitis, id non intellego quale sit.</h4>
<p>Ea possunt paria non esse. Tum Torquatus: Prorsus, inquit, assentior; Occultum facinus esse potuerit, gaudebit;
Quod cum dixissent, ille contra. Quibusnam praeteritis? Nam de isto magna dissensio est. </p>
<p>Urgent tamen et nihil remittunt. Ecce aliud simile dissimile. Sit sane ista voluptas. </p>
<p>Ille incendat? Invidiosum nomen est, infame, suspectum. Proclivi currit oratio. Memini me adesse P. Cave putes
quicquam esse verius. Quo tandem modo? Quis hoc dicit? </p>
<p>Quod quidem nobis non saepe contingit. Compensabatur, inquit, cum summis doloribus laetitia. </p>
<h2>Et ille ridens: Video, inquit, quid agas;</h2>
<p>Facillimum id quidem est, inquam. Haec dicuntur fortasse ieiunius; Nescio quo modo praetervolavit oratio. Sed
mehercule pergrata mihi oratio tua. </p>
<h3>Ergo ita: non posse honeste vivi, nisi honeste vivatur?</h3>
<p>Frater et T. Scaevolam M. Equidem e Cn. </p>
<p>Rationis enim perfectio est virtus; Is es profecto tu. Prodest, inquit, mihi eo esse animo. Aliter enim explicari,
quod quaeritur, non potest. Aliter homines, aliter philosophos loqui putas oportere? Nos commodius agimus. Sed ad
bona praeterita redeamus. </p>
<p>Atqui reperies, inquit, in hoc quidem pertinacem; De illis, cum volemus. In schola desinis. At hoc in eo M. Qui est
in parvis malis. Eadem fortitudinis ratio reperietur. Iam contemni non poteris. Efficiens dici potest. </p>
<h4>Possumusne ergo in vita summum bonum dicere, cum id ne in cena quidem posse videamur?</h4>
<p>Quo modo autem philosophus loquitur? Hoc mihi cum tuo fratre convenit. Nulla erit controversia. Ita prorsus,
inquam; </p>
<p>Quod vestri non item. Sed videbimus. Si longus, levis; Quid ad utilitatem tantae pecuniae? At enim hic etiam
dolore. Nos commodius agimus. </p>
<p>Zenonis est, inquam, hoc Stoici. Est enim effectrix multarum et magnarum voluptatum. Itaque contra est, ac dicitis;
Quis hoc dicit? An tu me de L. Nihil illinc huc pervenit. </p>
<p>Ille enim occurrentia nescio quae comminiscebatur; Nihil sane. An tu me de L. Quae est igitur causa istarum
angustiarum? Quid est enim aliud esse versutum? Nunc agendum est subtilius. </p>
</div>
<h2>JSON reference</h2>
<textarea id="json-reference">
{
"title":"toc",
"children":[
{
"type":"h1",
"title":"Hoc non est positum in nostra actione.",
"children":[
{
"type":"h2",
"title":"Quis non odit sordidos, vanos, leves, futtiles?",
"children":[
{
"type":"h3",
"title":"Quam ob rem tandem, inquit, non satisfacit?",
"children":[
{
"type":"h4",
"title":"Conclusum est enim contra Cyrenaicos satis acute, nihil ad Epicurum.",
"children":[]
}
]
},
{
"type":"h3",
"title":"Dolere malum est: in crucem qui agitur, beatus esse non potest.",
"children":[]
},
{
"type":"h3",
"title":"Ut in geometria, prima si dederis, danda sunt omnia.",
"children":[
{
"type":"h5",
"title":"Conferam tecum, quam cuique verso rem subicias;",
"children":[]
},
{
"type":"h5",
"title":"Dicimus aliquem hilare vivere;",
"children":[
{
"type":"h6",
"title":"An vero, inquit, quisquam potest probare, quod perceptfum, quod.",
"children":[]
},
{
"type":"h6",
"title":"Theophrastus mediocriterne delectat, cum tractat locos ab Aristotele ante tractatos?",
"children":[]
}
]
}
]
},
{
"type":"h3",
"title":"Qui autem esse poteris, nisi te amor ipse ceperit?",
"children":[]
},
{
"type":"h3",
"title":"Profectus in exilium Tubulus statim nec respondere ausus;",
"children":[]
}
]
},
{
"type":"h2",
"title":"Hoc non est positum in nostra actione.",
"children":[]
},
{
"type":"h2",
"title":"Laelius clamores sofow ille so lebat Edere compellans gumias ex ordine nostros.",
"children":[]
},
{
"type":"h2",
"title":"Expectoque quid ad id, quod quaerebam, respondeas.",
"children":[
{
"type":"h3",
"title":"Certe, nisi voluptatem tanti aestimaretis.",
"children":[]
},
{
"type":"h3",
"title":"Suo genere perveniant ad extremum;",
"children":[
{
"type":"h4",
"title":"Itaque hic ipse iam pridem est reiectus;",
"children":[]
},
{
"type":"h4",
"title":"Quod autem magnum dolorem brevem, longinquum levem esse dicitis, id non intellego quale sit.",
"children":[]
}
]
}
]
},
{
"type":"h2",
"title":"Et ille ridens: Video, inquit, quid agas;",
"children":[
{
"type":"h3",
"title":"Ergo ita: non posse honeste vivi, nisi honeste vivatur?",
"children":[
{
"type":"h4",
"title":"Possumusne ergo in vita summum bonum dicere, cum id ne in cena quidem posse videamur?",
"children":[]
}
]
}
]
}
]
}
]
}
</textarea>
<h2>JSON result</h2>
<textarea id="json-result"></textarea>
<script src="index.js"></script>
<script>
window.addEventListener('load', function () {
var jsonTocReference = JSON.stringify(JSON.parse(document.getElementById('json-reference').value)),
jsonToc = JSON.stringify(getJsToc('#content')),
jsonResult = document.getElementById('json-result');
for (var i = 0; i < 2077; i++) {
console.log(jsonTocReference[i], jsonToc[i]);
}
if (jsonTocReference === jsonToc) {
jsonResult.value = jsonToc;
jsonResult.className = 'ok';
} else {
jsonResult.value = 'Test failed!';
jsonResult.className = 'nok';
}
}, false);
</script>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment