1 var asciidoc = { // Namespace.
3 /////////////////////////////////////////////////////////////////////
4 // Table Of Contents generator
5 /////////////////////////////////////////////////////////////////////
7 /* Author: Mihai Bazon, September 2002
8 * http://students.infoiasi.ro/~mishoo
10 * Table Of Content generator
13 * Feel free to use this script under the terms of the GNU General Public
14 * License, as long as you do not remove or alter this notice.
17 /* modified by Troy D. Hanson, September 2006. License: GPL */
18 /* modified by Stuart Rackham, 2006, 2009. License: GPL */
21 toc: function (toclevels) {
23 function getText(el) {
25 for (var i = el.firstChild; i != null; i = i.nextSibling) {
26 if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants.
28 else if (i.firstChild != null)
34 function TocEntry(el, text, toclevel) {
37 this.toclevel = toclevel;
40 function tocEntries(el, toclevels) {
41 var result = new Array;
42 var re = new RegExp('[hH]([1-'+(toclevels+1)+'])');
43 // Function that scans the DOM tree for header elements (the DOM2
44 // nodeIterator API would be a better technique but not supported by all
46 var iterate = function (el) {
47 for (var i = el.firstChild; i != null; i = i.nextSibling) {
48 if (i.nodeType == 1 /* Node.ELEMENT_NODE */) {
49 var mo = re.exec(i.tagName);
50 if (mo && (i.getAttribute("class") || i.getAttribute("className")) != "float") {
51 result[result.length] = new TocEntry(i, getText(i), mo[1]-1);
61 var toc = document.getElementById("toc");
66 // Delete existing TOC entries in case we're reloading the TOC.
67 var tocEntriesToRemove = [];
69 for (i = 0; i < toc.childNodes.length; i++) {
70 var entry = toc.childNodes[i];
71 if (entry.nodeName.toLowerCase() == 'div'
72 && entry.getAttribute("class")
73 && entry.getAttribute("class").match(/^toclevel/))
74 tocEntriesToRemove.push(entry);
76 for (i = 0; i < tocEntriesToRemove.length; i++) {
77 toc.removeChild(tocEntriesToRemove[i]);
80 // Rebuild TOC entries.
81 var entries = tocEntries(document.getElementById("content"), toclevels);
82 for (var i = 0; i < entries.length; ++i) {
83 var entry = entries[i];
84 if (entry.element.id == "")
85 entry.element.id = "_toc_" + i;
86 var a = document.createElement("a");
87 a.href = "#" + entry.element.id;
88 a.appendChild(document.createTextNode(entry.text));
89 var div = document.createElement("div");
91 div.className = "toclevel" + entry.toclevel;
94 if (entries.length == 0)
95 toc.parentNode.removeChild(toc);
99 /////////////////////////////////////////////////////////////////////
100 // Footnotes generator
101 /////////////////////////////////////////////////////////////////////
103 /* Based on footnote generation code from:
104 * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html
107 footnotes: function () {
108 // Delete existing footnote entries in case we're reloading the footnodes.
110 var noteholder = document.getElementById("footnotes");
114 var entriesToRemove = [];
115 for (i = 0; i < noteholder.childNodes.length; i++) {
116 var entry = noteholder.childNodes[i];
117 if (entry.nodeName.toLowerCase() == 'div' && entry.getAttribute("class") == "footnote")
118 entriesToRemove.push(entry);
120 for (i = 0; i < entriesToRemove.length; i++) {
121 noteholder.removeChild(entriesToRemove[i]);
124 // Rebuild footnote entries.
125 var cont = document.getElementById("content");
126 var spans = cont.getElementsByTagName("span");
129 for (i=0; i<spans.length; i++) {
130 if (spans[i].className == "footnote") {
132 var note = spans[i].getAttribute("data-note");
134 // Use [\s\S] in place of . so multi-line matches work.
135 // Because JavaScript has no s (dotall) regex flag.
136 note = spans[i].innerHTML.match(/\s*\[([\s\S]*)]\s*/)[1];
138 "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n +
139 "' title='View footnote' class='footnote'>" + n + "</a>]";
140 spans[i].setAttribute("data-note", note);
142 noteholder.innerHTML +=
143 "<div class='footnote' id='_footnote_" + n + "'>" +
144 "<a href='#_footnoteref_" + n + "' title='Return to text'>" +
145 n + "</a>. " + note + "</div>";
146 var id =spans[i].getAttribute("id");
147 if (id != null) refs["#"+id] = n;
151 noteholder.parentNode.removeChild(noteholder);
153 // Process footnoterefs.
154 for (i=0; i<spans.length; i++) {
155 if (spans[i].className == "footnoteref") {
156 var href = spans[i].getElementsByTagName("a")[0].getAttribute("href");
157 href = href.match(/#.*/)[0]; // Because IE return full URL.
160 "[<a href='#_footnote_" + n +
161 "' title='View footnote' class='footnote'>" + n + "</a>]";
167 install: function(toclevels) {
170 function reinstall() {
171 asciidoc.footnotes();
173 asciidoc.toc(toclevels);
177 function reinstallAndRemoveTimer() {
178 clearInterval(timerId);
182 timerId = setInterval(reinstall, 500);
183 if (document.addEventListener)
184 document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false);
186 window.onload = reinstallAndRemoveTimer;