Commit | Line | Data |
---|---|---|
7f918cf1 CE |
1 | var asciidoc = { // Namespace. |
2 | ||
3 | ///////////////////////////////////////////////////////////////////// | |
4 | // Table Of Contents generator | |
5 | ///////////////////////////////////////////////////////////////////// | |
6 | ||
7 | /* Author: Mihai Bazon, September 2002 | |
8 | * http://students.infoiasi.ro/~mishoo | |
9 | * | |
10 | * Table Of Content generator | |
11 | * Version: 0.4 | |
12 | * | |
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. | |
15 | */ | |
16 | ||
17 | /* modified by Troy D. Hanson, September 2006. License: GPL */ | |
18 | /* modified by Stuart Rackham, 2006, 2009. License: GPL */ | |
19 | ||
20 | // toclevels = 1..4. | |
21 | toc: function (toclevels) { | |
22 | ||
23 | function getText(el) { | |
24 | var text = ""; | |
25 | for (var i = el.firstChild; i != null; i = i.nextSibling) { | |
26 | if (i.nodeType == 3 /* Node.TEXT_NODE */) // IE doesn't speak constants. | |
27 | text += i.data; | |
28 | else if (i.firstChild != null) | |
29 | text += getText(i); | |
30 | } | |
31 | return text; | |
32 | } | |
33 | ||
34 | function TocEntry(el, text, toclevel) { | |
35 | this.element = el; | |
36 | this.text = text; | |
37 | this.toclevel = toclevel; | |
38 | } | |
39 | ||
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 | |
45 | // browsers). | |
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); | |
52 | } | |
53 | iterate(i); | |
54 | } | |
55 | } | |
56 | } | |
57 | iterate(el); | |
58 | return result; | |
59 | } | |
60 | ||
61 | var toc = document.getElementById("toc"); | |
62 | if (!toc) { | |
63 | return; | |
64 | } | |
65 | ||
66 | // Delete existing TOC entries in case we're reloading the TOC. | |
67 | var tocEntriesToRemove = []; | |
68 | var i; | |
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); | |
75 | } | |
76 | for (i = 0; i < tocEntriesToRemove.length; i++) { | |
77 | toc.removeChild(tocEntriesToRemove[i]); | |
78 | } | |
79 | ||
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"); | |
90 | div.appendChild(a); | |
91 | div.className = "toclevel" + entry.toclevel; | |
92 | toc.appendChild(div); | |
93 | } | |
94 | if (entries.length == 0) | |
95 | toc.parentNode.removeChild(toc); | |
96 | }, | |
97 | ||
98 | ||
99 | ///////////////////////////////////////////////////////////////////// | |
100 | // Footnotes generator | |
101 | ///////////////////////////////////////////////////////////////////// | |
102 | ||
103 | /* Based on footnote generation code from: | |
104 | * http://www.brandspankingnew.net/archive/2005/07/format_footnote.html | |
105 | */ | |
106 | ||
107 | footnotes: function () { | |
108 | // Delete existing footnote entries in case we're reloading the footnodes. | |
109 | var i; | |
110 | var noteholder = document.getElementById("footnotes"); | |
111 | if (!noteholder) { | |
112 | return; | |
113 | } | |
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); | |
119 | } | |
120 | for (i = 0; i < entriesToRemove.length; i++) { | |
121 | noteholder.removeChild(entriesToRemove[i]); | |
122 | } | |
123 | ||
124 | // Rebuild footnote entries. | |
125 | var cont = document.getElementById("content"); | |
126 | var spans = cont.getElementsByTagName("span"); | |
127 | var refs = {}; | |
128 | var n = 0; | |
129 | for (i=0; i<spans.length; i++) { | |
130 | if (spans[i].className == "footnote") { | |
131 | n++; | |
132 | var note = spans[i].getAttribute("data-note"); | |
133 | if (!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]; | |
137 | spans[i].innerHTML = | |
138 | "[<a id='_footnoteref_" + n + "' href='#_footnote_" + n + | |
139 | "' title='View footnote' class='footnote'>" + n + "</a>]"; | |
140 | spans[i].setAttribute("data-note", note); | |
141 | } | |
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; | |
148 | } | |
149 | } | |
150 | if (n == 0) | |
151 | noteholder.parentNode.removeChild(noteholder); | |
152 | else { | |
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. | |
158 | n = refs[href]; | |
159 | spans[i].innerHTML = | |
160 | "[<a href='#_footnote_" + n + | |
161 | "' title='View footnote' class='footnote'>" + n + "</a>]"; | |
162 | } | |
163 | } | |
164 | } | |
165 | }, | |
166 | ||
167 | install: function(toclevels) { | |
168 | var timerId; | |
169 | ||
170 | function reinstall() { | |
171 | asciidoc.footnotes(); | |
172 | if (toclevels) { | |
173 | asciidoc.toc(toclevels); | |
174 | } | |
175 | } | |
176 | ||
177 | function reinstallAndRemoveTimer() { | |
178 | clearInterval(timerId); | |
179 | reinstall(); | |
180 | } | |
181 | ||
182 | timerId = setInterval(reinstall, 500); | |
183 | if (document.addEventListener) | |
184 | document.addEventListener("DOMContentLoaded", reinstallAndRemoveTimer, false); | |
185 | else | |
186 | window.onload = reinstallAndRemoveTimer; | |
187 | } | |
188 | ||
189 | } |