1/** 2 * Some of these scripts were taken from wikipedia.org and were modified for DokuWiki 3 */ 4 5/** 6 * Some browser detection 7 */ 8var clientPC = navigator.userAgent.toLowerCase(); // Get client info 9var is_gecko = ((clientPC.indexOf('gecko')!=-1) && (clientPC.indexOf('spoofer')==-1) && 10 (clientPC.indexOf('khtml') == -1) && (clientPC.indexOf('netscape/7.0')==-1)); 11var is_safari = ((clientPC.indexOf('AppleWebKit')!=-1) && (clientPC.indexOf('spoofer')==-1)); 12var is_khtml = (navigator.vendor == 'KDE' || ( document.childNodes && !document.all && !navigator.taintEnabled )); 13if (clientPC.indexOf('opera')!=-1) { 14 var is_opera = true; 15 var is_opera_preseven = (window.opera && !document.childNodes); 16 var is_opera_seven = (window.opera && document.childNodes); 17} 18 19/** 20 * Rewrite the accesskey tooltips to be more browser and OS specific. 21 * 22 * Accesskey tooltips are still only a best-guess of what will work 23 * on well known systems. 24 * 25 * @author Ben Coburn <btcoburn@silicodon.net> 26 */ 27function updateAccessKeyTooltip() { 28 // determin tooltip text (order matters) 29 var tip = 'ALT+'; //default 30 if (is_safari) { tip = 'CTRL+'; } 31 if (is_opera) { tip = 'SHIFT+ESC '; } 32 // add other cases here... 33 34 // do tooltip update 35 if (tip=='ALT+') { return; } 36 var exp = /\[ALT\+/i; 37 var rep = '['+tip; 38 39 var elements = document.getElementsByTagName('a'); 40 for (var i=0; i<elements.length; i++) { 41 if (elements[i].accessKey.length==1 && elements[i].title.length>0) { 42 elements[i].title = elements[i].title.replace(exp, rep); 43 } 44 } 45 46 elements = document.getElementsByTagName('input'); 47 for (var i=0; i<elements.length; i++) { 48 if (elements[i].accessKey.length==1 && elements[i].title.length>0) { 49 elements[i].title = elements[i].title.replace(exp, rep); 50 } 51 } 52 53 elements = document.getElementsByTagName('button'); 54 for (var i=0; i<elements.length; i++) { 55 if (elements[i].accessKey.length==1 && elements[i].title.length>0) { 56 elements[i].title = elements[i].title.replace(exp, rep); 57 } 58 } 59} 60 61/** 62 * Handy shortcut to document.getElementById 63 * 64 * This function was taken from the prototype library 65 * 66 * @link http://prototype.conio.net/ 67 */ 68function $() { 69 var elements = new Array(); 70 71 for (var i = 0; i < arguments.length; i++) { 72 var element = arguments[i]; 73 if (typeof element == 'string') 74 element = document.getElementById(element); 75 76 if (arguments.length == 1) 77 return element; 78 79 elements.push(element); 80 } 81 82 return elements; 83} 84 85/** 86 * Simple function to check if a global var is defined 87 * 88 * @author Kae Verens 89 * @link http://verens.com/archives/2005/07/25/isset-for-javascript/#comment-2835 90 */ 91function isset(varname){ 92 return(typeof(window[varname])!='undefined'); 93} 94 95/** 96 * Select elements by their class name 97 * 98 * @author Dustin Diaz <dustin [at] dustindiaz [dot] com> 99 * @link http://www.dustindiaz.com/getelementsbyclass/ 100 */ 101function getElementsByClass(searchClass,node,tag) { 102 var classElements = new Array(); 103 if ( node == null ) 104 node = document; 105 if ( tag == null ) 106 tag = '*'; 107 var els = node.getElementsByTagName(tag); 108 var elsLen = els.length; 109 var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)"); 110 for (i = 0, j = 0; i < elsLen; i++) { 111 if ( pattern.test(els[i].className) ) { 112 classElements[j] = els[i]; 113 j++; 114 } 115 } 116 return classElements; 117} 118 119/** 120 * Get the X offset of the top left corner of the given object 121 * 122 * @link http://www.quirksmode.org/index.html?/js/findpos.html 123 */ 124function findPosX(object){ 125 var curleft = 0; 126 var obj = $(object); 127 if (obj.offsetParent){ 128 while (obj.offsetParent){ 129 curleft += obj.offsetLeft; 130 obj = obj.offsetParent; 131 } 132 } 133 else if (obj.x){ 134 curleft += obj.x; 135 } 136 return curleft; 137} //end findPosX function 138 139/** 140 * Get the Y offset of the top left corner of the given object 141 * 142 * @link http://www.quirksmode.org/index.html?/js/findpos.html 143 */ 144function findPosY(object){ 145 var curtop = 0; 146 var obj = $(object); 147 if (obj.offsetParent){ 148 while (obj.offsetParent){ 149 curtop += obj.offsetTop; 150 obj = obj.offsetParent; 151 } 152 } 153 else if (obj.y){ 154 curtop += obj.y; 155 } 156 return curtop; 157} //end findPosY function 158 159/** 160 * Escape special chars in JavaScript 161 * 162 * @author Andreas Gohr <andi@splitbrain.org> 163 */ 164function jsEscape(text){ 165 var re=new RegExp("\\\\","g"); 166 text=text.replace(re,"\\\\"); 167 re=new RegExp("'","g"); 168 text=text.replace(re,"\\'"); 169 re=new RegExp('"',"g"); 170 text=text.replace(re,'"'); 171 re=new RegExp("\\\\\\\\n","g"); 172 text=text.replace(re,"\\n"); 173 return text; 174} 175 176/** 177 * This function escapes some special chars 178 * @deprecated by above function 179 */ 180function escapeQuotes(text) { 181 var re=new RegExp("'","g"); 182 text=text.replace(re,"\\'"); 183 re=new RegExp('"',"g"); 184 text=text.replace(re,'"'); 185 re=new RegExp("\\n","g"); 186 text=text.replace(re,"\\n"); 187 return text; 188} 189 190/** 191 * Adds a node as the first childenode to the given parent 192 * 193 * @see appendChild() 194 */ 195function prependChild(parent,element) { 196 if(!parent.firstChild){ 197 parent.appendChild(element); 198 }else{ 199 parent.insertBefore(element,parent.firstChild); 200 } 201} 202 203/** 204 * Prints a animated gif to show the search is performed 205 * 206 * Because we need to modify the DOM here before the document is loaded 207 * and parsed completely we have to rely on document.write() 208 * 209 * @author Andreas Gohr <andi@splitbrain.org> 210 */ 211function showLoadBar(){ 212 213 document.write('<img src="'+DOKU_BASE+'lib/images/loading.gif" '+ 214 'width="150" height="12" alt="..." />'); 215 216 /* this does not work reliable in IE 217 obj = $(id); 218 219 if(obj){ 220 obj.innerHTML = '<img src="'+DOKU_BASE+'lib/images/loading.gif" '+ 221 'width="150" height="12" alt="..." />'; 222 obj.style.display="block"; 223 } 224 */ 225} 226 227/** 228 * Disables the animated gif to show the search is done 229 * 230 * @author Andreas Gohr <andi@splitbrain.org> 231 */ 232function hideLoadBar(id){ 233 obj = $(id); 234 if(obj) obj.style.display="none"; 235} 236 237/** 238 * Adds the toggle switch to the TOC 239 */ 240function addTocToggle() { 241 if(!document.getElementById) return; 242 var header = $('toc__header'); 243 if(!header) return; 244 245 var showimg = document.createElement('img'); 246 showimg.id = 'toc__show'; 247 showimg.src = DOKU_BASE+'lib/images/arrow_down.gif'; 248 showimg.alt = '+'; 249 showimg.onclick = toggleToc; 250 showimg.style.display = 'none'; 251 252 var hideimg = document.createElement('img'); 253 hideimg.id = 'toc__hide'; 254 hideimg.src = DOKU_BASE+'lib/images/arrow_up.gif'; 255 hideimg.alt = '-'; 256 hideimg.onclick = toggleToc; 257 258 prependChild(header,showimg); 259 prependChild(header,hideimg); 260} 261 262/** 263 * This toggles the visibility of the Table of Contents 264 */ 265function toggleToc() { 266 var toc = $('toc__inside'); 267 var showimg = $('toc__show'); 268 var hideimg = $('toc__hide'); 269 if(toc.style.display == 'none') { 270 toc.style.display = ''; 271 hideimg.style.display = ''; 272 showimg.style.display = 'none'; 273 } else { 274 toc.style.display = 'none'; 275 hideimg.style.display = 'none'; 276 showimg.style.display = ''; 277 } 278} 279 280/** 281 * This enables/disables checkboxes for acl-administration 282 * 283 * @author Frank Schubert <frank@schokilade.de> 284 */ 285function checkAclLevel(){ 286 if(document.getElementById) { 287 var scope = $('acl_scope').value; 288 289 //check for namespace 290 if( (scope.indexOf(":*") > 0) || (scope == "*") ){ 291 document.getElementsByName('acl_checkbox[4]')[0].disabled=false; 292 document.getElementsByName('acl_checkbox[8]')[0].disabled=false; 293 }else{ 294 document.getElementsByName('acl_checkbox[4]')[0].checked=false; 295 document.getElementsByName('acl_checkbox[8]')[0].checked=false; 296 297 document.getElementsByName('acl_checkbox[4]')[0].disabled=true; 298 document.getElementsByName('acl_checkbox[8]')[0].disabled=true; 299 } 300 } 301} 302 303/** 304 * Display an insitu footnote popup 305 * 306 * @author Andreas Gohr <andi@splitbrain.org> 307 * @author Chris Smith <chris@jalakai.co.uk> 308 */ 309function footnote(e){ 310 var obj = e.target; 311 var id = obj.id.substr(5); 312 313 // get or create the footnote popup div 314 var fndiv = $('insitu__fn'); 315 if(!fndiv){ 316 fndiv = document.createElement('div'); 317 fndiv.id = 'insitu__fn'; 318 fndiv.className = 'insitu-footnote JSpopup dokuwiki'; 319 320 // autoclose on mouseout - ignoring bubbled up events 321 addEvent(fndiv,'mouseout',function(e){ 322 if(e.target != fndiv){ 323 e.stopPropagation(); 324 return; 325 } 326 // check if the element was really left 327 if(e.pageX){ // Mozilla 328 var bx1 = findPosX(fndiv); 329 var bx2 = bx1 + fndiv.offsetWidth; 330 var by1 = findPosY(fndiv); 331 var by2 = by1 + fndiv.offsetHeight; 332 var x = e.pageX; 333 var y = e.pageY; 334 if(x > bx1 && x < bx2 && y > by1 && y < by2){ 335 // we're still inside boundaries 336 e.stopPropagation(); 337 return; 338 } 339 }else{ // IE 340 if(e.offsetX > 0 && e.offsetX < fndiv.offsetWidth-1 && 341 e.offsetY > 0 && e.offsetY < fndiv.offsetHeight-1){ 342 // we're still inside boundaries 343 e.stopPropagation(); 344 return; 345 } 346 } 347 // okay, hide it 348 fndiv.style.display='none'; 349 }); 350 document.body.appendChild(fndiv); 351 } 352 353 // locate the footnote anchor element 354 var a = $( "fn__"+id ); 355 if (!a){ return; } 356 357 // anchor parent is the footnote container, get its innerHTML 358 var content = new String (a.parentNode.innerHTML); 359 360 // strip the leading content anchors and their comma separators 361 content = content.replace(/<a\s.*?href=\".*\#fnt__\d+\".*?<\/a>/gi, ''); 362 content = content.replace(/^\s+(,\s+)+/,''); 363 364 // prefix ids on any elements with "insitu__" to ensure they remain unique 365 content = content.replace(/\bid=\"(.*?)\"/gi,'id="insitu__$1'); 366 367 // now put the content into the wrapper 368 fndiv.innerHTML = content; 369 370 // position the div and make it visible 371 var x; var y; 372 if(e.pageX){ // Mozilla 373 x = e.pageX; 374 y = e.pageY; 375 }else{ // IE 376 x = e.offsetX; 377 y = e.offsetY; 378 } 379 fndiv.style.position = 'absolute'; 380 fndiv.style.left = (x+2)+'px'; 381 fndiv.style.top = (y+2)+'px'; 382 fndiv.style.display = ''; 383} 384 385/** 386 * Add the event handlers to footnotes 387 * 388 * @author Andreas Gohr <andi@splitbrain.org> 389 */ 390addInitEvent(function(){ 391 var elems = getElementsByClass('fn_top',null,'a'); 392 for(var i=0; i<elems.length; i++){ 393 addEvent(elems[i],'mouseover',function(e){footnote(e);}); 394 } 395}); 396 397/** 398 * Add the edit window size controls 399 */ 400function initSizeCtl(ctlid,edid){ 401 if(!document.getElementById){ return; } 402 403 var ctl = $(ctlid); 404 var textarea = $(edid); 405 if(!ctl || !textarea) return; 406 407 var hgt = DokuCookie.getValue('sizeCtl'); 408 if(hgt){ 409 textarea.style.height = hgt; 410 }else{ 411 textarea.style.height = '300px'; 412 } 413 414 var l = document.createElement('img'); 415 var s = document.createElement('img'); 416 var w = document.createElement('img'); 417 l.src = DOKU_BASE+'lib/images/larger.gif'; 418 s.src = DOKU_BASE+'lib/images/smaller.gif'; 419 w.src = DOKU_BASE+'lib/images/wrap.gif'; 420 addEvent(l,'click',function(){sizeCtl(edid,100);}); 421 addEvent(s,'click',function(){sizeCtl(edid,-100);}); 422 addEvent(w,'click',function(){toggleWrap(edid);}); 423 ctl.appendChild(l); 424 ctl.appendChild(s); 425 ctl.appendChild(w); 426} 427 428/** 429 * This sets the vertical size of the editbox 430 */ 431function sizeCtl(edid,val){ 432 var textarea = $(edid); 433 var height = parseInt(textarea.style.height.substr(0,textarea.style.height.length-2)); 434 height += val; 435 textarea.style.height = height+'px'; 436 437 DokuCookie.setValue('sizeCtl',textarea.style.height); 438} 439 440/** 441 * Toggle the wrapping mode of a textarea 442 * 443 * @author Fluffy Convict <fluffyconvict@hotmail.com> 444 * @link http://news.hping.org/comp.lang.javascript.archive/12265.html 445 * @author <shutdown@flashmail.com> 446 * @link https://bugzilla.mozilla.org/show_bug.cgi?id=302710#c2 447 */ 448function toggleWrap(edid){ 449 var txtarea = $(edid); 450 var wrap = txtarea.getAttribute('wrap'); 451 if(wrap && wrap.toLowerCase() == 'off'){ 452 txtarea.setAttribute('wrap', 'soft'); 453 }else{ 454 txtarea.setAttribute('wrap', 'off'); 455 } 456 // Fix display for mozilla 457 var parNod = txtarea.parentNode; 458 var nxtSib = txtarea.nextSibling; 459 parNod.removeChild(txtarea); 460 parNod.insertBefore(txtarea, nxtSib); 461} 462 463/** 464 * Handler to close all open Popups 465 */ 466function closePopups(){ 467 if(!document.getElementById){ return; } 468 469 var divs = document.getElementsByTagName('div'); 470 for(var i=0; i < divs.length; i++){ 471 if(divs[i].className.indexOf('JSpopup') != -1){ 472 divs[i].style.display = 'none'; 473 } 474 } 475} 476 477/** 478 * Looks for an element with the ID scroll__here at scrolls to it 479 */ 480function scrollToMarker(){ 481 var obj = $('scroll__here'); 482 if(obj) obj.scrollIntoView(); 483} 484 485/** 486 * Looks for an element with the ID focus__this at sets focus to it 487 */ 488function focusMarker(){ 489 var obj = $('focus__this'); 490 if(obj) obj.focus(); 491} 492 493/** 494 * Remove messages 495 */ 496function cleanMsgArea(){ 497 var elems = getElementsByClass('(success|info|error)',document,'div'); 498 if(elems){ 499 for(var i=0; i<elems.length; i++){ 500 elems[i].style.display = 'none'; 501 } 502 } 503} 504