@@ -0,0 +1,344 @@
1+// Haddock JavaScript utilities
2+
3+var rspace = /\s\s+/g,
4+ rtrim = /^\s+|\s+$/g;
5+
6+function spaced(s) { return (" " + s + " ").replace(rspace, " "); }
7+function trim(s) { return s.replace(rtrim, ""); }
8+
9+function hasClass(elem, value) {
10+ var className = spaced(elem.className || "");
11+ return className.indexOf( " " + value + " " ) >= 0;
12+}
13+
14+function addClass(elem, value) {
15+ var className = spaced(elem.className || "");
16+ if ( className.indexOf( " " + value + " " ) < 0 ) {
17+ elem.className = trim(className + " " + value);
18+ }
19+}
20+
21+function removeClass(elem, value) {
22+ var className = spaced(elem.className || "");
23+ className = className.replace(" " + value + " ", " ");
24+ elem.className = trim(className);
25+}
26+
27+function 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+
41+function makeClassToggle(valueOn, valueOff)
42+{
43+ return function(elem, bool) {
44+ return toggleClass(elem, valueOn, valueOff, bool);
45+ }
46+}
47+
48+toggleShow = makeClassToggle("show", "hide");
49+toggleCollapser = makeClassToggle("collapser", "expander");
50+
51+function 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+
59+var collapsed = {};
60+function 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+
77+function 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+
91+function setCookie(name, value) {
92+ document.cookie = name + "=" + escape(value) + ";path=/;";
93+}
94+
95+function clearCookie(name) {
96+ document.cookie = name + "=;path=/;expires=Thu, 01-Jan-1970 00:00:01 GMT;";
97+}
98+
99+function 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+
114+var max_results = 75; // 50 is not enough to search for map in the base libraries
115+var shown_range = null;
116+var last_search = null;
117+
118+function quick_search()
119+{
120+ perform_search(false);
121+}
122+
123+function full_search()
124+{
125+ perform_search(true);
126+}
127+
128+
129+function 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+
231+function 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+
242+function 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+
251+function 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+
265+function reframe() {
266+ setCookie("haddock-reframe", document.URL);
267+ window.location = "frames.html";
268+}
269+
270+function postReframe() {
271+ var s = getCookie("haddock-reframe");
272+ if (s) {
273+ parent.window.main.location = s;
274+ clearCookie("haddock-reframe");
275+ }
276+}
277+
278+function 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+
288+function 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 ▾</a>"
299+ + "<ul id='style-menu' class='hide'>" + btns + "</ul>"
300+ + "</div>";
301+ addMenuItem(h);
302+ }
303+}
304+
305+function 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+
326+function resetStyle() {
327+ var s = getCookie("haddock-style");
328+ if (s) setActiveStyleSheet(s);
329+}
330+
331+
332+function styleMenu(show) {
333+ var m = document.getElementById('style-menu');
334+ if (m) toggleShow(m, show);
335+}
336+
337+
338+function pageLoad() {
339+ addStyleMenu();
340+ adjustForFrames();
341+ resetStyle();
342+ restoreCollapsed();
343+}
344+