initial
[www.git] / www / psensor / doc / asciidoc.js
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 }