Add 10.5 compatible DS_Store to DMG (thanks redFrik)
[supercollider.git] / HelpSource / scdoc.js
blob90066cc4a6e1849cae31ac7434d2ed6b08a6a558
1 function toggle_visibility(e) {
2 if(e.style.display == 'none') {
3 e.style.display = 'block';
4 return e;
5 } else {
6 e.style.display = 'none';
7 return undefined;
12 function createCookie(name,value,days) {
13 if (days) {
14 var date = new Date();
15 date.setTime(date.getTime()+(days*24*60*60*1000));
16 var expires = "; expires="+date.toGMTString();
18 else var expires = "";
19 document.cookie = name+"="+value+expires+"; path=/";
22 function readCookie(name) {
23 var nameEQ = name + "=";
24 var ca = document.cookie.split(';');
25 for(var i=0;i < ca.length;i++) {
26 var c = ca[i];
27 while (c.charAt(0)==' ') c = c.substring(1,c.length);
28 if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
30 return null;
34 var sidetoc;
35 var toc;
36 var menubar;
37 var allItems;
38 function popOutTOC(original_toc, p0) {
39 var t = original_toc.cloneNode(true);
40 t.id = "sidetoc";
41 var c = document.getElementsByClassName("contents")[0];
42 var left = c.style.marginLeft;
43 c.style.marginLeft = "20.5em";
44 document.body.insertBefore(t,c);
46 t.getElementsByClassName("toc_search")[0].getElementsByTagName("input")[0].onkeyup = toc_search;
48 t.style.top = menubar.clientHeight;
49 t.style.maxHeight = "none";
50 t.style.display = "block";
52 var p = t.getElementsByClassName("popoutlink")[0];
53 p.innerHTML = "close";
54 p.onclick = function() {
55 t.parentNode.removeChild(t);
56 c.style.marginLeft = left;
57 p0.style.display = "";
58 sidetoc = null;
59 allItems = toc.getElementsByTagName("ul")[0].getElementsByTagName("li");
60 sessionStorage.popToc = "no";
61 return false;
63 var x = document.createElement("div");
64 x.id = "toctitle";
65 x.innerHTML = "Table of contents";
66 t.insertBefore(x,p.nextSibling);
67 p0.style.display = "none";
69 sidetoc = t;
70 allItems = t.getElementsByTagName("ul")[0].getElementsByTagName("li");
71 resize_handler();
72 sessionStorage.popToc = "yes";
75 function resize_handler() {
76 var height = window.innerHeight - menubar.clientHeight - 20;
77 if(sidetoc)
78 sidetoc.style.height = height;
79 if(toc)
80 toc.style.maxHeight = height * 0.75;
83 function addInheritedMethods() {
84 if(! /\/Classes\/[^\/]+/.test(window.location.pathname)) return; // skip this if not a class doc
85 var doc = docmap["Classes/"+document.title];
86 if(!doc) return;
87 if(doc.implementor) {
88 var sups = docmap["Classes/"+doc.implementor].superclasses;
89 } else {
90 var sups = doc.superclasses;
92 if(!sups) return;
93 var divs = [document.getElementById("inheritedclassmets"), document.getElementById("inheritedinstmets")];
94 for(var i=0;i<sups.length;i++) {
95 var s = docmap["Classes/"+sups[i]];
96 var d = [];
97 for(var j=0;j<2;j++) {
98 d[j] = document.createElement("ul");
99 d[j].className = "inheritedmets";
100 d[j].style.display = "none";
102 var mets = s.methods.sort();
103 for(var j=0;j<mets.length;j++) {
104 var m = mets[j];
105 if(doc.methods.indexOf(m)<0) { // ignore methods already documented in this helpfile
106 var li = document.createElement("li");
107 li.innerHTML = "<a href='"+helpRoot+"/"+s.path+".html#"+m.slice(1)+"'>"+m.slice(2)+"</a>";
108 if(m[1]=="*") {
109 d[0].appendChild(li);
110 } else
111 if(m[1]=="-") {
112 d[1].appendChild(li);
116 for(var j=0;j<2;j++) {
117 var count = d[j].childElementCount;
118 if(count) {
119 var x = document.createElement("div");
120 var show = "&#9658; show";
121 var hide = "&#9660; hide";
122 x.className = "inheritedmets_class";
123 x.innerHTML = count+" methods from <a href='"+helpRoot+"/"+s.path+".html'>"+s.title+"</a> ";
124 divs[j].appendChild(x);
125 (function(z) {
126 var a = document.createElement("a");
127 a.className = "inheritedmets_toggle";
128 a.setAttribute("href","#");
129 a.innerHTML = show;
130 a.onclick = function() {
131 if(z.style.display == "none") {
132 z.style.display = "block";
133 a.innerHTML = hide;
134 } else {
135 z.style.display = "none";
136 a.innerHTML = show;
138 return false;
140 x.appendChild(a);
141 })(d[j]);
142 divs[j].appendChild(d[j]);
148 function showAllSubclasses(a) {
149 var e = document.getElementById("hiddensubclasses");
150 e.style.display = "";
151 a.style.display = "none";
155 This key event handler selects the whole line when pressing shift/ctrl-enter with no selection.
156 But the problem is that it does not update the selection sent to the client.
157 This is probably because the WebView catches the key event before javascript does!
158 A fix might be to expose a function to JS that evaluates selection, and call it here.
159 Or can the WebView make sure that JS has responded to all key events before getting the selection?
161 function selectLine() {
162 var s = window.getSelection();
163 var r = s.getRangeAt();
165 function findleft(p) {
166 var y, j;
167 while(p) {
168 if(p.nodeName == "BR")
169 return [p,j];
170 if(p.childNodes.length>0) {
171 for(var i=p.childNodes.length-1;i>=0;i--) {
172 y = findleft(p.childNodes[i]);
173 if(y) return y;
176 p = p.previousSibling;
178 return null;
181 function findright(p) {
182 var y, j;
183 while(p) {
184 if(p.nodeName == "BR")
185 return [p,j];
186 for(var i=0;i<p.childNodes.length;i++) {
187 y = findright(p.childNodes[i]);
188 if(y) return y;
190 p = p.nextSibling;
192 return null;
196 if(r.collapsed) {
197 var r2 = document.createRange();
198 var top = r.startContainer;
199 while(top && top.nodeName != "PRE")
200 top = top.parentNode;
202 var p = r.startContainer;
203 while(!p.previousSibling && p != top) {
204 p = p.parentNode;
206 if(p==top) {
207 r2.setStartBefore(top.firstChild);
208 } else {
209 var found = findleft(p.previousSibling);
210 if(found) {
211 r2.setStartAfter(found[0]);
212 } else {
213 r2.setStartBefore(top.firstChild);
216 var p = r.startContainer;
217 while(!p.nextSibling && p != top) {
218 p = p.parentNode;
220 if(p==top) {
221 r2.setEndAfter(top.lastChild);
222 } else {
223 var found = findright(p.nextSibling);
224 if(found) {
225 r2.setEndBefore(found[0]);
226 } else {
227 r2.setEndAfter(top.lastChild);
230 s.removeAllRanges();
231 s.addRange(r2);
235 function countChar(str,chr) {
236 var x = 0, a, b;
237 for(var i=0;i<str.length;i++) {
238 if(str[i]==chr) {
239 if(a==undefined) a = i;
240 b = i;
241 x++;
244 // return count, first occurence and last occurence
245 return [x,a,b];
248 function selectParens(ev) {
249 var s = window.getSelection();
250 var r = s.getRangeAt();
251 var r2 = document.createRange();
252 var j;
254 // FIXME: it always selects from the left paren, so clicking on the right-par does not select from the matching left-par
255 // need to abort lpar search if rpar was found and then start with the rpar to the right (or closest) instead
256 function findlpar(x) {
257 var p = x;
258 var y, j;
259 while(p) {
260 if(j = p.nodeValue) {
261 j = countChar(j,"(");
262 if(j[0]>0) {
263 return [p, j[2]];
266 for(var i=0;i<p.childNodes.length;i++) {
267 y = findlpar(p.childNodes[i]);
268 if(y) return y;
270 p = p.previousSibling;
272 return null;
275 function findrpar(x,count) {
276 var p = x;
277 var y, j;
278 count = count || [0];
279 while(p) {
280 if(j = p.nodeValue) {
281 count[0] += countChar(j,"(")[0];
282 j = countChar(j,")");
283 if(j[0]>0) {
284 if(count[0]==0)
285 return [p,j[1]];
286 else
287 count[0] -= j[0];
290 for(var i=0;i<p.childNodes.length;i++) {
291 y = findrpar(p.childNodes[i],count);
292 if(y) return y;
294 p = p.nextSibling;
296 return null;
299 var p = r.startContainer;
300 if(p.nodeValue && (j = p.nodeValue.indexOf("("))>=0) {
301 r2.setStart(p,j+1);
302 p = p.parentNode.nextSibling;
303 } else {
304 while(!p.previousSibling && p != ev.target) {
305 p = p.parentNode;
307 if(p==ev.target)
308 return;
309 var found = findlpar(p);
310 if(found)
311 r2.setStart(found[0],found[1]+1);
314 var found = findrpar(p);
315 if(found)
316 r2.setEnd(found[0],found[1]);
318 s.removeAllRanges();
319 s.addRange(r2);
322 escape_regexp = function(str) {
323 var specials = new RegExp("[.*+?|()\\[\\]{}\\\\]", "g"); // .*+?|()[]{}\
324 return str.replace(specials, "\\$&");
327 function toc_search(ev) {
328 //TODO: on enter, go to first match
329 var re = RegExp("^"+escape_regexp(ev.target.value),"i");
330 for(var i=0;i<allItems.length;i++) {
331 var li = allItems[i];
332 var a = li.firstChild;
333 if(re.test(a.innerHTML)) {
334 li.style.display = "";
335 var lev = li.className[3];
336 for(var i2 = i-1;i2>=0;i2--) {
337 var e = allItems[i2];
338 if(e.className[3]<lev) {
339 e.style.display = "";
340 lev -= 1;
342 if(e.className[3]==1) break;
344 } else {
345 li.style.display = "none";
350 function fixTOC() {
351 var x = document.getElementsByClassName("lang-sc");
352 for(var i=0;i<x.length;i++) {
353 var e = x[i];
355 // make all code examples editable!
356 e.setAttribute("contentEditable",true);
358 // select parenthesis on double-click
359 e.ondblclick = selectParens;
362 addInheritedMethods();
364 if(sessionStorage == undefined)
365 sessionStorage = {};
367 var openMenu;
368 var inMenu = false;
370 var toggleMenu = function(e) {
371 if(openMenu) {
372 openMenu.style.display = 'none';
374 if(e != openMenu) {
375 e.style.display = 'block';
376 openMenu = e;
377 } else {
378 openMenu = undefined;
380 inMenu = true;
383 document.onclick = function(e) {
384 if(openMenu && !inMenu && e.target.id!="toc_search") {
385 openMenu.style.display = 'none';
386 openMenu = undefined;
388 inMenu = false;
389 return true;
392 // make header menu
393 var bar = document.getElementById("menubar");
394 menubar = bar;
395 var nav = ["Home","Browse","Search"];
396 var url = ["Help.html","Browse.html","Search.html"];
397 for(var i=0;i<nav.length;i++) {
398 var li = document.createElement("li");
399 li.className = "menuitem";
400 var a = document.createElement("a");
401 a.innerHTML = nav[i];
402 a.setAttribute("href",helpRoot+"/"+url[i]);
403 a.className = "navLink";
404 li.appendChild(a);
405 bar.appendChild(li);
408 var li = document.createElement("li");
409 li.className = "menuitem";
410 var a = document.createElement("a");
411 a.innerHTML = "Indexes &#9660;";
412 a.setAttribute("href","#");
413 var m1 = document.createElement("div");
414 m1.className = "submenu";
415 m1.style.display = "none";
416 a.onclick = function() {
417 toggleMenu(m1);
418 return false;
420 var nav = ["Documents","Classes","Methods"];
421 for(var i=0;i<nav.length;i++) {
422 var b = document.createElement("a");
423 b.setAttribute("href",helpRoot+"/Overviews/"+nav[i]+".html");
424 b.innerHTML = nav[i];
425 m1.appendChild(b);
427 li.appendChild(a);
428 li.appendChild(m1);
429 bar.appendChild(li);
431 var li = document.createElement("li");
432 li.className = "menuitem";
433 var x = document.createElement("span");
434 x.id = "topdoctitle";
435 x.appendChild(document.createTextNode(document.title));
436 x.onclick = function() {
437 scroll(0,0);
438 return false;
440 li.appendChild(x)
441 bar.appendChild(li);
443 var t = document.getElementById("toc");
444 toc = t;
445 if(t) {
446 var div = document.createElement("span");
447 div.className = "toc_search";
448 var ts = document.createElement("input");
449 ts.type = "text";
450 ts.id = "toc_search";
451 ts.value = "";
452 ts.style.border = "1px solid #ddd";
453 allItems = toc.getElementsByTagName("ul")[0].getElementsByTagName("li");
454 ts.onkeyup = toc_search;
455 div.appendChild(document.createTextNode("Find:"));
456 div.appendChild(ts);
457 t.insertBefore(div,t.firstChild);
459 x.appendChild(document.createTextNode(" - "));
460 t.style.display = 'none';
462 var a = document.createElement("a");
463 a.setAttribute("href","#");
464 a.innerHTML = "Table of contents &#9660;";
465 li.appendChild(a);
466 a.onclick = function() {
467 ts.focus();
468 toggleMenu(t);
469 return false;
471 li.appendChild(t.parentNode.removeChild(t));
472 var p = document.createElement("a");
473 p.setAttribute("href","#");
474 p.className = "popoutlink";
475 p.innerHTML = "pop out";
476 p.onclick = function() {
477 if(!sidetoc)
478 popOutTOC(t,a);
479 return false;
481 t.insertBefore(p,t.firstChild);
482 resize_handler();
483 if(sessionStorage.popToc == "yes") {
484 popOutTOC(t,a);
487 window.onresize = resize_handler;