aboutsummaryrefslogtreecommitdiffhomepage
path: root/haddock-util.js
diff options
context:
space:
mode:
Diffstat (limited to 'haddock-util.js')
-rw-r--r--haddock-util.js344
1 files changed, 344 insertions, 0 deletions
diff --git a/haddock-util.js b/haddock-util.js
new file mode 100644
index 0000000..9a6fccf
--- /dev/null
+++ b/haddock-util.js
@@ -0,0 +1,344 @@
1// Haddock JavaScript utilities
2
3var rspace = /\s\s+/g,
4 rtrim = /^\s+|\s+$/g;
5
6function spaced(s) { return (" " + s + " ").replace(rspace, " "); }
7function trim(s) { return s.replace(rtrim, ""); }
8
9function hasClass(elem, value) {
10 var className = spaced(elem.className || "");
11 return className.indexOf( " " + value + " " ) >= 0;
12}
13
14function addClass(elem, value) {
15 var className = spaced(elem.className || "");
16 if ( className.indexOf( " " + value + " " ) < 0 ) {
17 elem.className = trim(className + " " + value);
18 }
19}
20
21function removeClass(elem, value) {
22 var className = spaced(elem.className || "");
23 className = className.replace(" " + value + " ", " ");
24 elem.className = trim(className);
25}
26
27function toggleClass(elem, valueOn, valueOff, bool) {
28 if (bool == null) { bool = ! hasClass(elem, valueOn); }
29 if (bool) {
30 removeClass(elem, valueOff);
31 addClass(elem, valueOn);
32 }
33 else {
34 removeClass(elem, valueOn);
35 addClass(elem, valueOff);
36 }
37 return bool;
38}
39
40
41function makeClassToggle(valueOn, valueOff)
42{
43 return function(elem, bool) {
44 return toggleClass(elem, valueOn, valueOff, bool);
45 }
46}
47
48toggleShow = makeClassToggle("show", "hide");
49toggleCollapser = makeClassToggle("collapser", "expander");
50
51function toggleSection(id)
52{
53 var b = toggleShow(document.getElementById("section." + id));
54 toggleCollapser(document.getElementById("control." + id), b);
55 rememberCollapsed(id, b);
56 return b;
57}
58
59var collapsed = {};
60function rememberCollapsed(id, b)
61{
62 if(b)
63 delete collapsed[id]
64 else
65 collapsed[id] = null;
66
67 var sections = [];
68 for(var i in collapsed)
69 {
70 if(collapsed.hasOwnProperty(i))
71 sections.push(i);
72 }
73 // cookie specific to this page; don't use setCookie which sets path=/
74 document.cookie = "collapsed=" + escape(sections.join('+'));
75}
76
77function restoreCollapsed()
78{
79 var cookie = getCookie("collapsed");
80 if(!cookie)
81 return;
82
83 var ids = cookie.split('+');
84 for(var i in ids)
85 {
86 if(document.getElementById("section." + ids[i]))
87 toggleSection(ids[i]);
88 }
89}
90
91function setCookie(name, value) {
92 document.cookie = name + "=" + escape(value) + ";path=/;";
93}
94
95function clearCookie(name) {
96 document.cookie = name + "=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;";
97}
98
99function getCookie(name) {
100 var nameEQ = name + "=";
101 var ca = document.cookie.split(';');
102 for(var i=0;i < ca.length;i++) {
103 var c = ca[i];
104 while (c.charAt(0)==' ') c = c.substring(1,c.length);
105 if (c.indexOf(nameEQ) == 0) {
106 return unescape(c.substring(nameEQ.length,c.length));
107 }
108 }
109 return null;
110}
111
112
113
114var max_results = 75; // 50 is not enough to search for map in the base libraries
115var shown_range = null;
116var last_search = null;
117
118function quick_search()
119{
120 perform_search(false);
121}
122
123function full_search()
124{
125 perform_search(true);
126}
127
128
129function perform_search(full)
130{
131 var text = document.getElementById("searchbox").value.toLowerCase();
132 if (text == last_search && !full) return;
133 last_search = text;
134
135 var table = document.getElementById("indexlist");
136 var status = document.getElementById("searchmsg");
137 var children = table.firstChild.childNodes;
138
139 // first figure out the first node with the prefix
140 var first = bisect(-1);
141 var last = (first == -1 ? -1 : bisect(1));
142
143 if (first == -1)
144 {
145 table.className = "";
146 status.innerHTML = "No results found, displaying all";
147 }
148 else if (first == 0 && last == children.length - 1)
149 {
150 table.className = "";
151 status.innerHTML = "";
152 }
153 else if (last - first >= max_results && !full)
154 {
155 table.className = "";
156 status.innerHTML = "More than " + max_results + ", press Search to display";
157 }
158 else
159 {
160 // decide what you need to clear/show
161 if (shown_range)
162 setclass(shown_range[0], shown_range[1], "indexrow");
163 setclass(first, last, "indexshow");
164 shown_range = [first, last];
165 table.className = "indexsearch";
166 status.innerHTML = "";
167 }
168
169
170 function setclass(first, last, status)
171 {
172 for (var i = first; i <= last; i++)
173 {
174 children[i].className = status;
175 }
176 }
177
178
179 // do a binary search, treating 0 as ...
180 // return either -1 (no 0's found) or location of most far match
181 function bisect(dir)
182 {
183 var first = 0, finish = children.length - 1;
184 var mid, success = false;
185
186 while (finish - first > 3)
187 {
188 mid = Math.floor((finish + first) / 2);
189
190 var i = checkitem(mid);
191 if (i == 0) i = dir;
192 if (i == -1)
193 finish = mid;
194 else
195 first = mid;
196 }
197 var a = (dir == 1 ? first : finish);
198 var b = (dir == 1 ? finish : first);
199 for (var i = b; i != a - dir; i -= dir)
200 {
201 if (checkitem(i) == 0) return i;
202 }
203 return -1;
204 }
205
206
207 // from an index, decide what the result is
208 // 0 = match, -1 is lower, 1 is higher
209 function checkitem(i)
210 {
211 var s = getitem(i).toLowerCase().substr(0, text.length);
212 if (s == text) return 0;
213 else return (s > text ? -1 : 1);
214 }
215
216
217 // from an index, get its string
218 // this abstracts over alternates
219 function getitem(i)
220 {
221 for ( ; i >= 0; i--)
222 {
223 var s = children[i].firstChild.firstChild.data;
224 if (s.indexOf(' ') == -1)
225 return s;
226 }
227 return ""; // should never be reached
228 }
229}
230
231function setSynopsis(filename) {
232 if (parent.window.synopsis) {
233 if (parent.window.synopsis.location.replace) {
234 // In Firefox this avoids adding the change to the history.
235 parent.window.synopsis.location.replace(filename);
236 } else {
237 parent.window.synopsis.location = filename;
238 }
239 }
240}
241
242function addMenuItem(html) {
243 var menu = document.getElementById("page-menu");
244 if (menu) {
245 var btn = menu.firstChild.cloneNode(false);
246 btn.innerHTML = html;
247 menu.appendChild(btn);
248 }
249}
250
251function adjustForFrames() {
252 var bodyCls;
253
254 if (parent.location.href == window.location.href) {
255 // not in frames, so add Frames button
256 addMenuItem("<a href='#' onclick='reframe();return true;'>Frames</a>");
257 bodyCls = "no-frame";
258 }
259 else {
260 bodyCls = "in-frame";
261 }
262 addClass(document.body, bodyCls);
263}
264
265function reframe() {
266 setCookie("haddock-reframe", document.URL);
267 window.location = "frames.html";
268}
269
270function postReframe() {
271 var s = getCookie("haddock-reframe");
272 if (s) {
273 parent.window.main.location = s;
274 clearCookie("haddock-reframe");
275 }
276}
277
278function styles() {
279 var i, a, es = document.getElementsByTagName("link"), rs = [];
280 for (i = 0; a = es[i]; i++) {
281 if(a.rel.indexOf("style") != -1 && a.title) {
282 rs.push(a);
283 }
284 }
285 return rs;
286}
287
288function addStyleMenu() {
289 var as = styles();
290 var i, a, btns = "";
291 for(i=0; a = as[i]; i++) {
292 btns += "<li><a href='#' onclick=\"setActiveStyleSheet('"
293 + a.title + "'); return false;\">"
294 + a.title + "</a></li>"
295 }
296 if (as.length > 1) {
297 var h = "<div id='style-menu-holder'>"
298 + "<a href='#' onclick='styleMenu(); return false;'>Style &#9662;</a>"
299 + "<ul id='style-menu' class='hide'>" + btns + "</ul>"
300 + "</div>";
301 addMenuItem(h);
302 }
303}
304
305function setActiveStyleSheet(title) {
306 var as = styles();
307 var i, a, found;
308 for(i=0; a = as[i]; i++) {
309 a.disabled = true;
310 // need to do this always, some browsers are edge triggered
311 if(a.title == title) {
312 found = a;
313 }
314 }
315 if (found) {
316 found.disabled = false;
317 setCookie("haddock-style", title);
318 }
319 else {
320 as[0].disabled = false;
321 clearCookie("haddock-style");
322 }
323 styleMenu(false);
324}
325
326function resetStyle() {
327 var s = getCookie("haddock-style");
328 if (s) setActiveStyleSheet(s);
329}
330
331
332function styleMenu(show) {
333 var m = document.getElementById('style-menu');
334 if (m) toggleShow(m, show);
335}
336
337
338function pageLoad() {
339 addStyleMenu();
340 adjustForFrames();
341 resetStyle();
342 restoreCollapsed();
343}
344