xref: /dokuwiki/lib/scripts/script.js (revision d88b5f049b763613b6c2953b8f21105639a53afc)
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 (domLib_isMac) { tip = 'CTRL+'; }
31  if (domLib_isOpera) { 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  var elements = domLib_getElementsByTagNames(['a', 'input', 'button']);
39  for (var i=0; i<elements.length; i++) {
40    if (elements[i].accessKey.length==1 && elements[i].title.length>0) {
41      elements[i].title = elements[i].title.replace(exp, rep);
42    }
43  }
44}
45
46/**
47 * Handy shortcut to document.getElementById
48 *
49 * This function was taken from the prototype library
50 *
51 * @link http://prototype.conio.net/
52 */
53function $() {
54  var elements = new Array();
55
56  for (var i = 0; i < arguments.length; i++) {
57    var element = arguments[i];
58    if (typeof element == 'string')
59      element = document.getElementById(element);
60
61    if (arguments.length == 1)
62      return element;
63
64    elements.push(element);
65  }
66
67  return elements;
68}
69
70/**
71 * Simple function to check if a global var is defined
72 *
73 * @author Kae Verens
74 * @link http://verens.com/archives/2005/07/25/isset-for-javascript/#comment-2835
75 */
76function isset(varname){
77  return(typeof(window[varname])!='undefined');
78}
79
80/**
81 * Get the X offset of the top left corner of the given object
82 *
83 * @link http://www.quirksmode.org/index.html?/js/findpos.html
84 */
85function findPosX(object){
86  var curleft = 0;
87  var obj = $(object);
88  if (obj.offsetParent){
89    while (obj.offsetParent){
90      curleft += obj.offsetLeft;
91      obj = obj.offsetParent;
92    }
93  }
94  else if (obj.x){
95    curleft += obj.x;
96  }
97  return curleft;
98} //end findPosX function
99
100/**
101 * Get the Y offset of the top left corner of the given object
102 *
103 * @link http://www.quirksmode.org/index.html?/js/findpos.html
104 */
105function findPosY(object){
106  var curtop = 0;
107  var obj = $(object);
108  if (obj.offsetParent){
109    while (obj.offsetParent){
110      curtop += obj.offsetTop;
111      obj = obj.offsetParent;
112    }
113  }
114  else if (obj.y){
115    curtop += obj.y;
116  }
117  return curtop;
118} //end findPosY function
119
120/**
121 * Escape special chars in JavaScript
122 *
123 * @author Andreas Gohr <andi@splitbrain.org>
124 */
125function jsEscape(text){
126    var re=new RegExp("\\\\","g");
127    text=text.replace(re,"\\\\");
128    re=new RegExp("'","g");
129    text=text.replace(re,"\\'");
130    re=new RegExp('"',"g");
131    text=text.replace(re,'&quot;');
132    re=new RegExp("\\\\\\\\n","g");
133    text=text.replace(re,"\\n");
134    return text;
135}
136
137/**
138 * This function escapes some special chars
139 * @deprecated by above function
140 */
141function escapeQuotes(text) {
142  var re=new RegExp("'","g");
143  text=text.replace(re,"\\'");
144  re=new RegExp('"',"g");
145  text=text.replace(re,'&quot;');
146  re=new RegExp("\\n","g");
147  text=text.replace(re,"\\n");
148  return text;
149}
150
151/**
152 * Adds a node as the first childenode to the given parent
153 *
154 * @see appendChild()
155 */
156function prependChild(parent,element) {
157    if(!parent.firstChild){
158        parent.appendChild(element);
159    }else{
160        parent.insertBefore(element,parent.firstChild);
161    }
162}
163
164/**
165 * Prints a animated gif to show the search is performed
166 *
167 * @author Andreas Gohr <andi@splitbrain.org>
168 */
169function showLoadBar(id){
170  obj = $(id);
171
172  if(obj){
173    obj.innerHTML = '<img src="'+DOKU_BASE+'lib/images/loading.gif" '+
174                    'width="150" height="12" alt="..." />';
175    obj.style.display="block";
176  }
177}
178
179/**
180 * Disables the animated gif to show the search is done
181 *
182 * @author Andreas Gohr <andi@splitbrain.org>
183 */
184function hideLoadBar(id){
185  obj = $(id);
186  if(obj) obj.style.display="none";
187}
188
189/*
190 * Insert the selected filename and close the window
191 *
192 * @see http://www.alexking.org/index.php?content=software/javascript/content.php
193 */
194function mediaSelect(file){
195  opener.insertTags('wiki__text','{{'+file+'|','}}',file);
196  window.close();
197}
198
199/**
200 * For the upload Dialog. Prefills the wikiname.
201 */
202function suggestWikiname(){
203  var form = $('dw__upload');
204  if(!form) return;
205
206  var file = form.elements.upload.value;
207
208  file = file.substr(file.lastIndexOf('/')+1);
209  file = file.substr(file.lastIndexOf('\\')+1);
210
211  form.elements.id.value = file;
212}
213
214/**
215 * Adds the toggle switch to the TOC
216 */
217function addTocToggle() {
218    if(!document.getElementById) return;
219    var header = $('toc__header');
220  if(!header) return;
221
222  var showimg     = document.createElement('img');
223    showimg.id      = 'toc__show';
224  showimg.src     = DOKU_BASE+'lib/images/arrow_down.gif';
225  showimg.alt     = '+';
226    showimg.onclick = toggleToc;
227  showimg.style.display = 'none';
228
229    var hideimg     = document.createElement('img');
230    hideimg.id      = 'toc__hide';
231  hideimg.src     = DOKU_BASE+'lib/images/arrow_up.gif';
232  hideimg.alt     = '-';
233    hideimg.onclick = toggleToc;
234
235  prependChild(header,showimg);
236  prependChild(header,hideimg);
237}
238
239/**
240 * This toggles the visibility of the Table of Contents
241 */
242function toggleToc() {
243  var toc = $('toc__inside');
244  var showimg = $('toc__show');
245  var hideimg = $('toc__hide');
246  if(toc.style.display == 'none') {
247    toc.style.display      = '';
248    hideimg.style.display = '';
249    showimg.style.display = 'none';
250  } else {
251    toc.style.display      = 'none';
252    hideimg.style.display = 'none';
253    showimg.style.display = '';
254  }
255}
256
257/*
258 * This sets a cookie by JavaScript
259 *
260 * @see http://www.webreference.com/js/column8/functions.html
261 */
262function setCookie(name, value, expires, path, domain, secure) {
263  var curCookie = name + "=" + escape(value) +
264      ((expires) ? "; expires=" + expires.toGMTString() : "") +
265      ((path) ? "; path=" + path : "") +
266      ((domain) ? "; domain=" + domain : "") +
267      ((secure) ? "; secure" : "");
268  document.cookie = curCookie;
269}
270
271/*
272 * This reads a cookie by JavaScript
273 *
274 * @see http://www.webreference.com/js/column8/functions.html
275 */
276function getCookie(name) {
277  var dc = document.cookie;
278  var prefix = name + "=";
279  var begin = dc.indexOf("; " + prefix);
280  if (begin == -1) {
281    begin = dc.indexOf(prefix);
282    if (begin !== 0){ return null; }
283  } else {
284    begin += 2;
285  }
286  var end = document.cookie.indexOf(";", begin);
287  if (end == -1){
288    end = dc.length;
289  }
290  return unescape(dc.substring(begin + prefix.length, end));
291}
292
293/*
294 * This is needed for the cookie functions
295 *
296 * @see http://www.webreference.com/js/column8/functions.html
297 */
298function fixDate(date) {
299  var base = new Date(0);
300  var skew = base.getTime();
301  if (skew > 0){
302    date.setTime(date.getTime() - skew);
303  }
304}
305
306/*
307 * This enables/disables checkboxes for acl-administration
308 *
309 * @author Frank Schubert <frank@schokilade.de>
310 */
311function checkAclLevel(){
312  if(document.getElementById) {
313    var scope = $('acl_scope').value;
314
315    //check for namespace
316    if( (scope.indexOf(":*") > 0) || (scope == "*") ){
317      document.getElementsByName('acl_checkbox[4]')[0].disabled=false;
318      document.getElementsByName('acl_checkbox[8]')[0].disabled=false;
319    }else{
320      document.getElementsByName('acl_checkbox[4]')[0].checked=false;
321      document.getElementsByName('acl_checkbox[8]')[0].checked=false;
322
323      document.getElementsByName('acl_checkbox[4]')[0].disabled=true;
324      document.getElementsByName('acl_checkbox[8]')[0].disabled=true;
325    }
326  }
327}
328
329/**
330 * insitu footnote addition
331 *
332 * provide a wrapper for domTT javascript library
333 * this function is placed in the onmouseover event of footnote references in the main page
334 *
335 * @author Chris Smith <chris [at] jalakai [dot] co [dot] uk>
336 */
337var currentFootnote = 0;
338function fnt(id, e, evt) {
339
340    if (currentFootnote && id != currentFootnote) {
341        domTT_close($('insitu__fn'+currentFootnote));
342    }
343
344    // does the footnote tooltip already exist?
345    var fnote = $('insitu__fn'+id);
346    var footnote;
347    if (!fnote) {
348        // if not create it...
349
350        // locate the footnote anchor element
351        var a = $( "fn__"+id );
352        if (!a){ return; }
353
354        // anchor parent is the footnote container, get its innerHTML
355        footnote = new String (a.parentNode.innerHTML);
356
357        // strip the leading footnote anchors and their comma separators
358        footnote = footnote.replace(/<a\s.*?href=\".*\#fnt__\d+\".*?<\/a>/gi, '');
359        footnote = footnote.replace(/^\s+(,\s+)+/,'');
360
361        // prefix ids on any elements with "insitu__" to ensure they remain unique
362        footnote = footnote.replace(/\bid=\"(.*?)\"/gi,'id="insitu__$1');
363    } else {
364        footnote = new String(fnt.innerHTML);
365    }
366
367    // activate the tooltip
368    domTT_activate(e, evt, 'content', footnote, 'type', 'velcro', 'id', 'insitu__fn'+id, 'styleClass', 'insitu-footnote JSpopup', 'maxWidth', document.body.offsetWidth*0.4);
369    currentFootnote = id;
370}
371
372
373/**
374 * Add the edit window size controls
375 */
376function initSizeCtl(ctlid,edid){
377        if(!document.getElementById){ return; }
378
379    var ctl      = $(ctlid);
380    var textarea = $(edid);
381
382    var hgt = getCookie('DokuWikisizeCtl');
383    if(hgt === null || hgt === ''){
384      textarea.style.height = '300px';
385    }else{
386      textarea.style.height = hgt;
387    }
388
389    var l = document.createElement('img');
390    var s = document.createElement('img');
391    l.src = DOKU_BASE+'lib/images/larger.gif';
392    s.src = DOKU_BASE+'lib/images/smaller.gif';
393        addEvent(l,'click',function(){sizeCtl(edid,100);});
394        addEvent(s,'click',function(){sizeCtl(edid,-100);});
395    ctl.appendChild(l);
396    ctl.appendChild(s);
397}
398
399/**
400 * This sets the vertical size of the editbox
401 */
402function sizeCtl(edid,val){
403  var textarea = $(edid);
404  var height = parseInt(textarea.style.height.substr(0,textarea.style.height.length-2));
405  height += val;
406  textarea.style.height = height+'px';
407
408  var now = new Date();
409  fixDate(now);
410  now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000); //expire in a year
411  setCookie('DokuWikisizeCtl',textarea.style.height,now);
412}
413
414/**
415 * Handler to close all open Popups
416 */
417function closePopups(){
418  if(!document.getElementById){ return; }
419
420  var divs = document.getElementsByTagName('div');
421  for(var i=0; i < divs.length; i++){
422    if(divs[i].className.indexOf('JSpopup') != -1){
423            divs[i].style.display = 'none';
424    }
425  }
426}
427
428/**
429 * Looks for an element with the ID scroll__here at scrolls to it
430 */
431function scrollToMarker(){
432    var obj = $('scroll__here');
433    if(obj) obj.scrollIntoView();
434}
435