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 | } |
---|