RSS feeds using {{rss}} notation.
[cocanwiki.git] / html / _js / folding.js
1 /* Folding headings.
2  * Copyright (C) 2006 Merjis Ltd.
3  * $Id: folding.js,v 1.1 2006/08/17 11:19:58 rich Exp $
4  *
5  * For very long pages, you can use this Javascript to provide
6  * folding headings to make viewing the page more manageable.
7  *
8  * To install this code:
9  * (1) You must have the "manage site" permission.
10  * (2) Go to Sitewide settings, click Edit these settings, and in
11  *     the Page bug section, add or append the following Javascript
12  *     code:
13  *       <script src="/_js/folding.js" type="text/javascript"></script>
14  * (3) Edit the page where you want folding to appear, and set
15  *     the CSS class to "folding".
16  */
17
18 // http://domscripting.com/blog/display/18
19 function getElementsByClass (node, searchClass, tag)
20 {
21   var classElements = new Array();
22   var els = node.getElementsByTagName (tag);
23   var pattern = new RegExp ("\\b"+searchClass+"\\b");
24   for (i = 0, j = 0; i < els.length; i++) {
25     if (pattern.test (els[i].className)) {
26       classElements[j] = els[i];
27       j++;
28     }
29   }
30   return classElements;
31 }
32
33 function setTextContent (text, content)
34 {
35   // Not sure if this is even possible in IE6.
36   if (text.textContent) text.textContent = content;
37 }
38
39 function setOnClick (node, f)
40 {
41   //  if (!node.attachEvent) node.onclick = f;
42   //  else node.attachEvent ("onclick", f);
43   node.onclick = f;
44 }
45
46 // http://joust.kano.net/weblog/archive/2005/08/08/a-huge-gotcha-with-javascript-closures/
47 // http://calculist.blogspot.com/2005/12/gotcha-gotcha.html
48 function createShowFunction (text, plus, nodes)
49 {
50   return function (evt) {
51     // Restore the old display style.
52     for (var k = 0; k < nodes.length; ++k) {
53       var node = nodes[k];
54       if (node.style)
55         node.style.display = node.getAttribute ("displayold");
56     }
57     setTextContent (text, "[-]");
58     setOnClick (plus, createHideFunction (text, plus, nodes));
59   }
60 }
61
62 function createHideFunction (text, plus, nodes)
63 {
64   return function (evt) {
65     // Set all the nodes to display none, but remember the old
66     // display style.
67     for (var k = 0; k < nodes.length; ++k) {
68       var node = nodes[k];
69       if (node.style) {
70         node.setAttribute ("displayold", node.style.display);
71         node.style.display = "none";
72       }
73     }
74     setTextContent (text, "[+]");
75     setOnClick (plus, createShowFunction (text, plus, nodes));
76   }
77 }
78
79 function set_up_folding ()
80 {
81   var divs = getElementsByClass (document, "folding", "div");
82   for (var d = 0; d < divs.length; ++d) {
83     var div = divs[d];
84     var children = div.childNodes;
85     // List of child nodes is something like H3, n, n, H3, n, n, n, ...
86     // Add a button before each H3 which hides/shows the subsequent
87     // nodes up to but not including the next H3.
88     for (var i = 0; i < children.length; ++i) {
89       var h3 = children[i];
90       if (h3.nodeName == "H3") {
91         var j = i+1;
92         while (j < children.length && children[j].nodeName != "H3") j++;
93         // children i to j exclusive should be shown/hidden.
94         // Copy them to an array called 'nodes'.
95         var nodes = new Array ();
96         for (var k = i+1; k < j; ++k) {
97           var child = children[k];
98           nodes[k-(i+1)] = child;
99         }
100
101         // Create the +/- control.
102         var plus = document.createElement ("div");
103         plus.setAttribute ("class", "foldingcontrol");
104         var text = document.createTextNode ("[+]");
105         plus.appendChild (text);
106
107         // Create functions to show/hide the nodes.
108         var show = createShowFunction (text, plus, nodes);
109         var hide = createHideFunction (text, plus, nodes);
110
111         hide ();
112
113         // Place the '+' button before the h3.
114         div.insertBefore (plus, h3);
115         setOnClick (plus, show);
116
117         // Skip directly to next h3.
118         i = j-1;
119       }
120     }
121   }
122 }
123
124 set_up_folding ();