Changesets can be listed by changeset number.
The Git repository is here.
- Revision:
- 372
- Log:
Reinstated automatic section numbering JS code from I2. Although
manual numbering isn't possible since JavaScript isn't allowed
inside pages, the automatic code works fine.
- Author:
- rool
- Date:
- Mon Mar 21 12:10:24 +0000 2011
- Size:
- 7879 Bytes
1 | /* Variable depth automatic section numbering implemented by automatic |
2 | * document scanning, looking for headers. |
3 | * |
4 | * This code is derived from an example in O'Reilly, "JavaScript: The |
5 | * Definitive Guide" by David Flanagan, ISBN-10: 0-596-10199-6, ISBN-13: |
6 | * 978-0-596-10199-2, 5th edition, section 15.9, p336. |
7 | * |
8 | * History |
9 | * ======= |
10 | * |
11 | * 13-Jun-2007 (ADH): Imported into Wiki structure. |
12 | * 21-Mar-2011 (ADH): Imported into Instiki. |
13 | */ |
14 | |
15 | /* This module defines a single maketoc() function and registers an onload |
16 | * event handler so the function is automatically run when the document |
17 | * finishes loading. When it runs, maketoc() first looks for document |
18 | * elements with IDs of "toc" and "under_toc". If there are no such elements |
19 | * maketoc() does nothing. Otherwise, maketoc() traverses all child nodes |
20 | * of "under_toc" to find all <h2> through <h6> tags. It creates a table of |
21 | * contents, which it appends to the "toc" element. maketoc() adds section |
22 | * numbers to each section heading and inserts a link back to the table of |
23 | * contents before each heading. maketoc() generates links and anchors with |
24 | * names that begin with "TOC", so you should avoid this prefix in your own |
25 | * HTML. |
26 | * |
27 | * The entries in the generated TOC can be styled with CSS. All entries have |
28 | * a class "TOCEntry". Entries also have a class that corresponds to the level |
29 | * of the section heading. <h1> tags generate entries of class "TOCLevel1", |
30 | * <h2> tags generate entries of class "TOCLevel2", and so on. Section numbers |
31 | * inserted into headings have class "TOCSectNum" and the generated links back |
32 | * to the TOC have class "TOCBackLink". |
33 | * |
34 | * By default, the generated links back to the TOC read "Contents". |
35 | * Override this default (for internationalization, e.g.) by setting |
36 | * the maketoc.backlinkText property to the desired text. |
37 | */ |
38 | |
39 | function maketoc() { |
40 | // Find the containers. If either is missing, return silently. |
41 | var container = document.getElementById('toc'); |
42 | var searchNode = document.getElementById('under_toc'); |
43 | if (!searchNode) searchNode = container.parentNode; |
44 | if (!container || !searchNode) return; |
45 | |
46 | // Traverse the document, adding all <h1>...<h6> tags to an array |
47 | var sections = []; |
48 | findSections(searchNode, sections); |
49 | |
50 | // Insert an anchor before the container element so we can link back to it |
51 | var anchor = document.createElement("a"); // Create an <a> node |
52 | anchor.name = "TOCtop"; // Give it a name |
53 | anchor.id = "TOCtop"; // And an id (IE needs this) |
54 | container.parentNode.insertBefore(anchor, container); // add before toc |
55 | |
56 | // Initialize an array that keeps track of section numbers |
57 | var sectionNumbers = [0,0,0,0,0,0]; |
58 | var found = false; |
59 | |
60 | // Now loop through the section header elements we found |
61 | for(var s = 0; s < sections.length; s++) { |
62 | var section = sections[s]; |
63 | |
64 | // Figure out what level heading it is |
65 | var level = parseInt(section.tagName.charAt(1)); |
66 | if (isNaN(level) || level < 2 || level > 6) continue; |
67 | found = true; |
68 | |
69 | // Increment the section number for this heading level |
70 | // And reset all lower heading level numbers to zero |
71 | sectionNumbers[level-1]++; |
72 | for(var i = level; i < 6; i++) sectionNumbers[i] = 0; |
73 | |
74 | // Now combine section numbers for all heading levels |
75 | // to produce a section number like 2.3.1 |
76 | var sectionNumber = ""; |
77 | for(i = 1; i < level; i++) { |
78 | sectionNumber += sectionNumbers[i]; |
79 | if (i < level-1) sectionNumber += "."; |
80 | } |
81 | |
82 | // Add the section number and a space to the section header title. |
83 | // We place the number in a <span> to make it styleable. |
84 | var frag = document.createDocumentFragment(); // to hold span and space |
85 | var span = document.createElement("span"); // span to hold number |
86 | span.className = "TOCSectNum"; // make it styleable |
87 | span.appendChild(document.createTextNode(sectionNumber)); // add sect# |
88 | frag.appendChild(span); // Add span to fragment |
89 | frag.appendChild(document.createTextNode(". ")); // Then add a full stop and space |
90 | section.insertBefore(frag, section.firstChild); // Add both to header |
91 | |
92 | // Create an anchor to mark the beginning of this section. |
93 | var anchor = document.createElement("a"); |
94 | anchor.name = "TOC"+sectionNumber; // Name the anchor so we can link |
95 | anchor.id = "TOC"+sectionNumber; // In IE generated anchors need ids |
96 | |
97 | // Wrap the anchor around a link back to the TOC |
98 | var link = document.createElement("a"); |
99 | link.href = "#TOCtop"; |
100 | link.className = "TOCBackLink"; |
101 | link.appendChild(document.createTextNode(maketoc.backlinkText)); |
102 | anchor.appendChild(link); |
103 | |
104 | // Insert the anchor and link immediately before the section header |
105 | section.parentNode.insertBefore(anchor, section); |
106 | |
107 | // Now create a link to this section. |
108 | var link = document.createElement("a"); |
109 | link.href = "#TOC" + sectionNumber; // Set link destination |
110 | link.innerHTML = section.innerHTML; // Make link text same as heading |
111 | |
112 | // Place the link in a div that is styleable based on the level |
113 | var entry = document.createElement("div"); |
114 | entry.className = "TOCEntry TOCLevel" + level; // For CSS styling |
115 | entry.appendChild(link); |
116 | |
117 | // And add the div to the TOC container |
118 | container.appendChild(entry); |
119 | } |
120 | |
121 | // If we found anything, add the 'Contents' heading. |
122 | |
123 | if (found) { |
124 | var heading = document.getElementById('toc_heading'); |
125 | |
126 | if (heading) { |
127 | var h2 = document.createElement('h2'); |
128 | h2.appendChild(document.createTextNode(maketoc.headingText)); |
129 | heading.appendChild(h2); |
130 | heading.appendChild(document.createElement('p')); |
131 | } |
132 | |
133 | container.appendChild(document.createElement('p')); |
134 | } |
135 | |
136 | // This method recursively traverses the tree rooted at node n, looking |
137 | // for <h1> through <h6> tags and appends them to the sections array. |
138 | function findSections(n, sects) { |
139 | // Loop through all the children of n |
140 | for(var m = n.firstChild; m != null; m = m.nextSibling) { |
141 | // Skip any nodes that are not elements. |
142 | if (m.nodeType != 1 /* Node.Element_NODE */) continue; |
143 | // Skip the container element since it may have its own heading |
144 | if (m == container) continue; |
145 | // As an optimization, skip <p> tags since headings are not |
146 | // supposed to appear inside paragraphs. (We could also skip |
147 | // lists, <pre> tags, etc., but <p> is the most common one.) |
148 | // XHTML documents tend to return lower case elements, HTML |
149 | // documents tend to return upper case elements. |
150 | if (m.tagName == "p" || m.tagName == "P") continue; // optimization |
151 | |
152 | // If we didn't skip the child node, check whether it is a heading. |
153 | // If so, add it to the array. Otherwise, recurse on it. |
154 | // Note that the DOM is interface-based not class-based so we |
155 | // cannot simply test whether (m instanceof HTMLHeadingElement). |
156 | if (m.tagName.length==2 && (m.tagName.charAt(0)=="h" || m.tagName.charAt(0)=="H")) sects.push(m); |
157 | else findSections(m, sects); |
158 | } |
159 | } |
160 | } |
161 | |
162 | // Default text for the Contents section heading |
163 | maketoc.headingText = "Contents"; |
164 | // This is the default text of links back to the TOC |
165 | maketoc.backlinkText = "Contents"; |
166 | |
167 | // Register maketoc() to run automatically when the document finishes loading |
168 | if (window.addEventListener) window.addEventListener("load", maketoc, false); |
169 | else if (window.attachEvent) window.attachEvent("onload", maketoc); |