fixed formatting error
[dokuwiki/radio.git] / lib / scripts / script.js
blobd863e6ceb618411fdcbf17f6d473d926b829dd83
1 /**
2  * Some of these scripts were taken from wikipedia.org and were modified for DokuWiki
3  */
5 /**
6  * Some browser detection
7  */
8 var clientPC  = navigator.userAgent.toLowerCase(); // Get client info
9 var is_macos  = navigator.appVersion.indexOf('Mac') != -1;
10 var is_gecko  = ((clientPC.indexOf('gecko')!=-1) && (clientPC.indexOf('spoofer')==-1) &&
11                 (clientPC.indexOf('khtml') == -1) && (clientPC.indexOf('netscape/7.0')==-1));
12 var is_safari = ((clientPC.indexOf('AppleWebKit')!=-1) && (clientPC.indexOf('spoofer')==-1));
13 var is_khtml  = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled ));
14 if (clientPC.indexOf('opera')!=-1) {
15     var is_opera = true;
16     var is_opera_preseven = (window.opera && !document.childNodes);
17     var is_opera_seven = (window.opera && document.childNodes);
20 /**
21  * Handy shortcut to document.getElementById
22  *
23  * This function was taken from the prototype library
24  *
25  * @link http://prototype.conio.net/
26  */
27 function $() {
28   var elements = new Array();
30   for (var i = 0; i < arguments.length; i++) {
31     var element = arguments[i];
32     if (typeof element == 'string')
33       element = document.getElementById(element);
35     if (arguments.length == 1)
36       return element;
38     elements.push(element);
39   }
41   return elements;
44 /**
45  * Simple function to check if a global var is defined
46  *
47  * @author Kae Verens
48  * @link http://verens.com/archives/2005/07/25/isset-for-javascript/#comment-2835
49  */
50 function isset(varname){
51   return(typeof(window[varname])!='undefined');
54 /**
55  * Select elements by their class name
56  *
57  * @author Dustin Diaz <dustin [at] dustindiaz [dot] com>
58  * @link   http://www.dustindiaz.com/getelementsbyclass/
59  */
60 function getElementsByClass(searchClass,node,tag) {
61     var classElements = new Array();
62     if ( node == null )
63         node = document;
64     if ( tag == null )
65         tag = '*';
66     var els = node.getElementsByTagName(tag);
67     var elsLen = els.length;
68     var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
69     for (var i = 0, j = 0; i < elsLen; i++) {
70         if ( pattern.test(els[i].className) ) {
71             classElements[j] = els[i];
72             j++;
73         }
74     }
75     return classElements;
78 /**
79  * Get the X offset of the top left corner of the given object
80  *
81  * @link http://www.quirksmode.org/index.html?/js/findpos.html
82  */
83 function findPosX(object){
84   var curleft = 0;
85   var obj = $(object);
86   if (obj.offsetParent){
87     while (obj.offsetParent){
88       curleft += obj.offsetLeft;
89       obj = obj.offsetParent;
90     }
91   }
92   else if (obj.x){
93     curleft += obj.x;
94   }
95   return curleft;
96 } //end findPosX function
98 /**
99  * Get the Y offset of the top left corner of the given object
101  * @link http://www.quirksmode.org/index.html?/js/findpos.html
102  */
103 function findPosY(object){
104   var curtop = 0;
105   var obj = $(object);
106   if (obj.offsetParent){
107     while (obj.offsetParent){
108       curtop += obj.offsetTop;
109       obj = obj.offsetParent;
110     }
111   }
112   else if (obj.y){
113     curtop += obj.y;
114   }
115   return curtop;
116 } //end findPosY function
119  * Escape special chars in JavaScript
121  * @author Andreas Gohr <andi@splitbrain.org>
122  */
123 function jsEscape(text){
124     var re=new RegExp("\\\\","g");
125     text=text.replace(re,"\\\\");
126     re=new RegExp("'","g");
127     text=text.replace(re,"\\'");
128     re=new RegExp('"',"g");
129     text=text.replace(re,'&quot;');
130     re=new RegExp("\\\\\\\\n","g");
131     text=text.replace(re,"\\n");
132     return text;
136  * This function escapes some special chars
137  * @deprecated by above function
138  */
139 function escapeQuotes(text) {
140   var re=new RegExp("'","g");
141   text=text.replace(re,"\\'");
142   re=new RegExp('"',"g");
143   text=text.replace(re,'&quot;');
144   re=new RegExp("\\n","g");
145   text=text.replace(re,"\\n");
146   return text;
150  * Adds a node as the first childenode to the given parent
152  * @see appendChild()
153  */
154 function prependChild(parent,element) {
155     if(!parent.firstChild){
156         parent.appendChild(element);
157     }else{
158         parent.insertBefore(element,parent.firstChild);
159     }
163  * Prints a animated gif to show the search is performed
165  * Because we need to modify the DOM here before the document is loaded
166  * and parsed completely we have to rely on document.write()
168  * @author Andreas Gohr <andi@splitbrain.org>
169  */
170 function showLoadBar(){
172   document.write('<img src="'+DOKU_BASE+'lib/images/loading.gif" '+
173                  'width="150" height="12" alt="..." />');
175   /* this does not work reliable in IE
176   obj = $(id);
178   if(obj){
179     obj.innerHTML = '<img src="'+DOKU_BASE+'lib/images/loading.gif" '+
180                     'width="150" height="12" alt="..." />';
181     obj.style.display="block";
182   }
183   */
187  * Disables the animated gif to show the search is done
189  * @author Andreas Gohr <andi@splitbrain.org>
190  */
191 function hideLoadBar(id){
192   obj = $(id);
193   if(obj) obj.style.display="none";
197  * Adds the toggle switch to the TOC
198  */
199 function addTocToggle() {
200     if(!document.getElementById) return;
201     var header = $('toc__header');
202     if(!header) return;
203     var toc = $('toc__inside');
205     var obj          = document.createElement('span');
206     obj.id           = 'toc__toggle';
207     obj.style.cursor = 'pointer';
208     if (toc && toc.style.display == 'none') {
209         obj.innerHTML    = '<span>+</span>';
210         obj.className    = 'toc_open';
211     } else {
212         obj.innerHTML    = '<span>&minus;</span>';
213         obj.className    = 'toc_close';
214     }
216     prependChild(header,obj);
217     obj.parentNode.onclick = toggleToc;
218     try {
219        obj.parentNode.style.cursor = 'pointer';
220        obj.parentNode.style.cursor = 'hand';
221     }catch(e){}
225  * This toggles the visibility of the Table of Contents
226  */
227 function toggleToc() {
228   var toc = $('toc__inside');
229   var obj = $('toc__toggle');
230   if(toc.style.display == 'none') {
231     toc.style.display   = '';
232     obj.innerHTML       = '<span>&minus;</span>';
233     obj.className       = 'toc_close';
234   } else {
235     toc.style.display   = 'none';
236     obj.innerHTML       = '<span>+</span>';
237     obj.className       = 'toc_open';
238   }
242  * This enables/disables checkboxes for acl-administration
244  * @author Frank Schubert <frank@schokilade.de>
245  */
246 function checkAclLevel(){
247   if(document.getElementById) {
248     var scope = $('acl_scope').value;
250     //check for namespace
251     if( (scope.indexOf(":*") > 0) || (scope == "*") ){
252       document.getElementsByName('acl_checkbox[4]')[0].disabled=false;
253       document.getElementsByName('acl_checkbox[8]')[0].disabled=false;
254     }else{
255       document.getElementsByName('acl_checkbox[4]')[0].checked=false;
256       document.getElementsByName('acl_checkbox[8]')[0].checked=false;
258       document.getElementsByName('acl_checkbox[4]')[0].disabled=true;
259       document.getElementsByName('acl_checkbox[8]')[0].disabled=true;
260     }
261   }
265  * Display an insitu footnote popup
267  * @author Andreas Gohr <andi@splitbrain.org>
268  * @author Chris Smith <chris@jalakai.co.uk>
269  */
270 function footnote(e){
271     var obj = e.target;
272     var id = obj.id.substr(5);
274     // get or create the footnote popup div
275     var fndiv = $('insitu__fn');
276     if(!fndiv){
277         fndiv = document.createElement('div');
278         fndiv.id        = 'insitu__fn';
279         fndiv.className = 'insitu-footnote JSpopup dokuwiki';
281         // autoclose on mouseout - ignoring bubbled up events
282         addEvent(fndiv,'mouseout',function(e){
283             if(e.target != fndiv){
284                 e.stopPropagation();
285                 return;
286             }
287             // check if the element was really left
288             if(e.pageX){        // Mozilla
289                 var bx1 = findPosX(fndiv);
290                 var bx2 = bx1 + fndiv.offsetWidth;
291                 var by1 = findPosY(fndiv);
292                 var by2 = by1 + fndiv.offsetHeight;
293                 var x = e.pageX;
294                 var y = e.pageY;
295                 if(x > bx1 && x < bx2 && y > by1 && y < by2){
296                     // we're still inside boundaries
297                     e.stopPropagation();
298                     return;
299                 }
300             }else{              // IE
301                 if(e.offsetX > 0 && e.offsetX < fndiv.offsetWidth-1 &&
302                    e.offsetY > 0 && e.offsetY < fndiv.offsetHeight-1){
303                     // we're still inside boundaries
304                     e.stopPropagation();
305                     return;
306                 }
307             }
308             // okay, hide it
309             fndiv.style.display='none';
310         });
311         document.body.appendChild(fndiv);
312     }
314     // locate the footnote anchor element
315     var a = $( "fn__"+id );
316     if (!a){ return; }
318     // anchor parent is the footnote container, get its innerHTML
319     var content = new String (a.parentNode.parentNode.innerHTML);
321     // strip the leading content anchors and their comma separators
322     content = content.replace(/<sup>.*<\/sup>/gi, '');
323     content = content.replace(/^\s+(,\s+)+/,'');
325     // prefix ids on any elements with "insitu__" to ensure they remain unique
326     content = content.replace(/\bid=\"(.*?)\"/gi,'id="insitu__$1');
328     // now put the content into the wrapper
329     fndiv.innerHTML = content;
331     // position the div and make it visible
332     var x; var y;
333     if(e.pageX){        // Mozilla
334         x = e.pageX;
335         y = e.pageY;
336     }else{              // IE
337         x = e.offsetX;
338         y = e.offsetY;
339     }
340     fndiv.style.position = 'absolute';
341     fndiv.style.left = (x+2)+'px';
342     fndiv.style.top  = (y+2)+'px';
343     fndiv.style.display = '';
347  * Add the event handlers to footnotes
349  * @author Andreas Gohr <andi@splitbrain.org>
350  */
351 addInitEvent(function(){
352     var elems = getElementsByClass('fn_top',null,'a');
353     for(var i=0; i<elems.length; i++){
354         addEvent(elems[i],'mouseover',function(e){footnote(e);});
355     }
359  * Add the edit window size controls
360  */
361 function initSizeCtl(ctlid,edid){
362     if(!document.getElementById){ return; }
364     var ctl      = $(ctlid);
365     var textarea = $(edid);
366     if(!ctl || !textarea) return;
368     var hgt = DokuCookie.getValue('sizeCtl');
369     if(hgt){
370       textarea.style.height = hgt;
371     }else{
372       textarea.style.height = '300px';
373     }
375     var wrp = DokuCookie.getValue('wrapCtl');
376     if(wrp){
377       setWrap(textarea, wrp);
378     } // else use default value
380     var l = document.createElement('img');
381     var s = document.createElement('img');
382     var w = document.createElement('img');
383     l.src = DOKU_BASE+'lib/images/larger.gif';
384     s.src = DOKU_BASE+'lib/images/smaller.gif';
385     w.src = DOKU_BASE+'lib/images/wrap.gif';
386     addEvent(l,'click',function(){sizeCtl(edid,100);});
387     addEvent(s,'click',function(){sizeCtl(edid,-100);});
388     addEvent(w,'click',function(){toggleWrap(edid);});
389     ctl.appendChild(l);
390     ctl.appendChild(s);
391     ctl.appendChild(w);
395  * This sets the vertical size of the editbox
396  */
397 function sizeCtl(edid,val){
398   var textarea = $(edid);
399   var height = parseInt(textarea.style.height.substr(0,textarea.style.height.length-2));
400   height += val;
401   textarea.style.height = height+'px';
403   DokuCookie.setValue('sizeCtl',textarea.style.height);
407  * Toggle the wrapping mode of a textarea
408  */
409 function toggleWrap(edid){
410     var textarea = $(edid);
411     var wrap = textarea.getAttribute('wrap');
412     if(wrap && wrap.toLowerCase() == 'off'){
413         setWrap(textarea, 'soft');
414     }else{
415         setWrap(textarea, 'off');
416     }
418     DokuCookie.setValue('wrapCtl',textarea.getAttribute('wrap'));
422  * Set the wrapping mode of a textarea
424  * @author Fluffy Convict <fluffyconvict@hotmail.com>
425  * @author <shutdown@flashmail.com>
426  * @link   http://news.hping.org/comp.lang.javascript.archive/12265.html
427  * @link   https://bugzilla.mozilla.org/show_bug.cgi?id=41464
428  */
429 function setWrap(textarea, wrapAttrValue){
430     textarea.setAttribute('wrap', wrapAttrValue);
432     // Fix display for mozilla
433     var parNod = textarea.parentNode;
434     var nxtSib = textarea.nextSibling;
435     parNod.removeChild(textarea);
436     parNod.insertBefore(textarea, nxtSib);
440  * Handler to close all open Popups
441  */
442 function closePopups(){
443   if(!document.getElementById){ return; }
445   var divs = document.getElementsByTagName('div');
446   for(var i=0; i < divs.length; i++){
447     if(divs[i].className.indexOf('JSpopup') != -1){
448             divs[i].style.display = 'none';
449     }
450   }
454  * Looks for an element with the ID scroll__here at scrolls to it
455  */
456 function scrollToMarker(){
457     var obj = $('scroll__here');
458     if(obj) obj.scrollIntoView();
462  * Looks for an element with the ID focus__this at sets focus to it
463  */
464 function focusMarker(){
465     var obj = $('focus__this');
466     if(obj) obj.focus();
470  * Remove messages
471  */
472 function cleanMsgArea(){
473     var elems = getElementsByClass('(success|info|error)',document,'div');
474     if(elems){
475         for(var i=0; i<elems.length; i++){
476             elems[i].style.display = 'none';
477         }
478     }
482  * disable multiple revisions checkboxes if two are checked
484  * @author Anika Henke <anika@selfthinker.org>
485  */
486 addInitEvent(function(){
487     var revForm = $('page__revisions');
488     if (!revForm) return;
489     var elems = revForm.elements;
490     var countTicks = 0;
491     for (var i=0; i<elems.length; i++) {
492         var input1 = elems[i];
493         if (input1.type=='checkbox') {
494             addEvent(input1,'click',function(e){
495                 if (this.checked) countTicks++;
496                 else countTicks--;
497                 for (var j=0; j<elems.length; j++) {
498                     var input2 = elems[j];
499                     if (countTicks >= 2) input2.disabled = (input2.type=='checkbox' && !input2.checked);
500                     else input2.disabled = (input2.type!='checkbox');
501                 }
502             });
503         } else if(input1.type=='submit'){
504             input1.disabled = true;
505         }
506     }
510  * Add the event handler to the actiondropdown
512  * @author Andreas Gohr <andi@splitbrain.org>
513  */
514 addInitEvent(function(){
515     var selector = $('action__selector');
516     if(!selector) return;
518     addEvent(selector,'change',function(e){
519         this.form.submit();
520     });
522     $('action__selectorbtn').style.display = 'none';
526  * Display error for Windows Shares on browsers other than IE
528  * @author Michael Klier <chi@chimeric.de>
529  */
530 function checkWindowsShares() {
531     if(!LANG['nosmblinks']) return true;
532     var elems = getElementsByClass('windows',document,'a');
533     if(elems){
534         for(var i=0; i<elems.length; i++){
535             var share = elems[i];
536             addEvent(share,'click',function(){
537                 if(document.all == null) {
538                     alert(LANG['nosmblinks']);
539                 }
540             });
541         }
542     }
546  * Add the event handler for the Windows Shares check
548  * @author Michael Klier <chi@chimeric.de>
549  */
550 addInitEvent(function(){
551     checkWindowsShares();
555  * Highlight the section when hovering over the appropriate section edit button
557  * @author Andreas Gohr <andi@splitbrain.org>
558  */
559 addInitEvent(function(){
560     var break_classes = new RegExp('secedit|toc|page');
561     var btns = getElementsByClass('btn_secedit',document,'form');
562     for(var i=0; i<btns.length; i++){
563         addEvent(btns[i],'mouseover',function(e){
564             var tgt = e.target;
565             if(tgt.form) tgt = tgt.form;
566             tgt = tgt.parentNode.previousSibling;
567             if(tgt.nodeName != "DIV") tgt = tgt.previousSibling;
568             while(!break_classes.test(tgt.className)) {
569                 tgt.className += ' section_highlight';
570                 if (tgt.tagName == 'H1') break;
571                 tgt = (tgt.previousSibling != null) ? tgt.previousSibling : tgt.parentNode;
572             }
573         });
575         addEvent(btns[i],'mouseout',function(e){
576             var secs = getElementsByClass('section_highlight');
577             for(var j=0; j<secs.length; j++){
578                 secs[j].className = secs[j].className.replace(/section_highlight/,'');
579             }
580             var secs = getElementsByClass('section_highlight');
581         });
582     }