class library: SynthDef - lazy implementation of removeUGen
[supercollider.git] / HelpSource / scdoc.js
blobbb3921bb5213766305639b7c051704b127615ff6
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;
8     }
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();
17     }
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);
29     }
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);
45     
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;
62     }
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;
91     }
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";
101         }
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);
113                 }
114             }
115         }
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;
137                         }
138                         return false;
139                     };
140                     x.appendChild(a);
141                 })(d[j]);
142                 divs[j].appendChild(d[j]);
143             }
144         }
145     }
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;
174                 }
175             }
176             p = p.previousSibling;
177         }
178         return null;
179     };
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;
189             }
190             p = p.nextSibling;
191         }
192         return null;
193     };
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;
205         }
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);
214             }
215         }
216         var p = r.startContainer;
217         while(!p.nextSibling && p != top) {
218             p = p.parentNode;
219         }
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);
228             }
229         }
230         s.removeAllRanges();
231         s.addRange(r2);
232     }
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++;
242         }
243     }
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]];
264                 }
265             }
266             for(var i=0;i<p.childNodes.length;i++) {
267                 y = findlpar(p.childNodes[i]);
268                 if(y) return y;
269             }
270             p = p.previousSibling;
271         }
272         return null;
273     }
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];
288                 }
289             }
290             for(var i=0;i<p.childNodes.length;i++) {
291                 y = findrpar(p.childNodes[i],count);
292                 if(y) return y;
293             }
294             p = p.nextSibling;
295         }
296         return null;
297     }
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;
306         }
307         if(p==ev.target)
308             return;
309         var found = findlpar(p);
310         if(found)
311             r2.setStart(found[0],found[1]+1);
312     }
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;
341                 }
342                 if(e.className[3]==1) break;
343             }
344         } else {
345             li.style.display = "none";
346         }
347     }
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;
360     }
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';
373         }
374         if(e != openMenu) {
375             e.style.display = 'block';
376             openMenu = e;
377         } else {
378             openMenu = undefined;
379         }
380         inMenu = true;
381     }
383     document.onclick = function(e) {
384         if(openMenu && !inMenu && e.target.id!="toc_search") {
385             openMenu.style.display = 'none';
386             openMenu = undefined;
387         }
388         inMenu = false;
389         return true;
390     }
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);
406     }
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;
419     };
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);
426     }
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;
439     }
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;
470         };
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;
480         }
481         t.insertBefore(p,t.firstChild);
482         resize_handler();
483         if(sessionStorage.popToc == "yes") {
484             popOutTOC(t,a);
485         }
486     }
487     window.onresize = resize_handler;