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