xref: /dokuwiki/lib/scripts/script.js (revision 20d062ca5220daf6606e2b1bcdd73d84eebafa45)
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//http://simon.incutio.com/archive/2004/05/26/addLoadEvent#comment2
20function addEvent(oTarget, sType, fpDest) {
21  var oOldEvent = oTarget[sType];
22  if (typeof oOldEvent != "function") {
23    oTarget[sType] = fpDest;
24  } else {
25    oTarget[sType] = function(e) {
26      oOldEvent(e);
27      fpDest(e);
28    }
29  }
30}
31
32/**
33 * Get the X offset of the top left corner of the given object
34 *
35 * @link http://www.quirksmode.org/index.html?/js/findpos.html
36 */
37function findPosX(object){
38  var curleft = 0;
39  if(typeof(object) == 'object'){
40    var obj = object;
41  }else{
42    var obj = document.getElementById(object);
43  }
44  if (obj.offsetParent){
45    while (obj.offsetParent){
46      curleft += obj.offsetLeft;
47      obj = obj.offsetParent;
48    }
49  }
50  else if (obj.x){
51    curleft += obj.x;
52  }
53  return curleft;
54} //end findPosX function
55
56/**
57 * Get the Y offset of the top left corner of the given object
58 *
59 * @link http://www.quirksmode.org/index.html?/js/findpos.html
60 */
61function findPosY(object){
62  var curtop = 0;
63  if(typeof(object) == 'object'){
64    var obj = object;
65  }else{
66    var obj = document.getElementById(object);
67  }
68  if (obj.offsetParent){
69    while (obj.offsetParent){
70      curtop += obj.offsetTop;
71      obj = obj.offsetParent;
72    }
73  }
74  else if (obj.y){
75    curtop += obj.y;
76  }
77  return curtop;
78} //end findPosY function
79
80/**
81 * Escape special chars in JavaScript
82 *
83 * @author Andreas Gohr <andi@splitbrain.org>
84 */
85function jsEscape(text){
86    var re=new RegExp("\\\\","g");
87    text=text.replace(re,"\\\\");
88    var re=new RegExp("'","g");
89    text=text.replace(re,"\\'");
90    re=new RegExp('"',"g");
91    text=text.replace(re,'&quot;');
92    re=new RegExp("\\\\\\\\n","g");
93    text=text.replace(re,"\\n");
94    return text;
95}
96
97/**
98 * This function escapes some special chars
99 * @deprecated by above function
100 */
101function escapeQuotes(text) {
102  var re=new RegExp("'","g");
103  text=text.replace(re,"\\'");
104  re=new RegExp('"',"g");
105  text=text.replace(re,'&quot;');
106  re=new RegExp("\\n","g");
107  text=text.replace(re,"\\n");
108  return text;
109}
110
111/**
112 * Prints a animated gif to show the search is performed
113 *
114 * @author Andreas Gohr <andi@splitbrain.org>
115 */
116function showLoadBar(){
117  if(document.getElementById){
118    document.write('<img src="'+DOKU_BASE+'lib/images/loading.gif" '+
119                   'width="150" height="12" id="loading" />');
120  }
121}
122
123/**
124 * Disables the animated gif to show the search is done
125 *
126 * @author Andreas Gohr <andi@splitbrain.org>
127 */
128function hideLoadBar(){
129  if(document.getElementById){
130    document.getElementById('loading').style.display="none";
131  }
132}
133
134/**
135 * Checks if a summary was entered - if not the style is changed
136 *
137 * @author Andreas Gohr <andi@splitbrain.org>
138 */
139function summaryCheck(){
140  if(document.getElementById){
141    var sum = document.getElementById('summary');
142    if(sum.value == ''){
143      sum.className='missing';
144    }else{
145      sum.className='edit';
146    }
147  }
148}
149
150/**
151 * This function generates the actual toolbar buttons with localized text
152 * we use it to avoid creating the toolbar where javascript is not enabled
153 * @deprecated
154 */
155function formatButton(imageFile, speedTip, tagOpen, tagClose, sampleText, accessKey) {
156  speedTip=escapeQuotes(speedTip);
157  tagOpen=escapeQuotes(tagOpen);
158  tagClose=escapeQuotes(tagClose);
159  sampleText=escapeQuotes(sampleText);
160
161  document.write("<a ");
162  if(accessKey){
163    document.write("accesskey=\""+accessKey+"\" ");
164    speedTip = speedTip+' [ALT+'+accessKey.toUpperCase()+']';
165  }
166  document.write("href=\"javascript:insertTags");
167  document.write("('"+tagOpen+"','"+tagClose+"','"+sampleText+"');\">");
168
169  document.write("<img width=\"24\" height=\"24\" src=\""+
170                DOKU_BASE+'lib/images/toolbar/'+imageFile+"\" border=\"0\" alt=\""+
171                speedTip+"\" title=\""+speedTip+"\">");
172  document.write("</a>");
173  return;
174}
175
176/**
177 * This function generates the actual toolbar buttons with localized text
178 * we use it to avoid creating the toolbar where javascript is not enabled
179 * @deprecated
180 */
181function insertButton(imageFile, speedTip, value, accessKey) {
182  speedTip=escapeQuotes(speedTip);
183  value=escapeQuotes(value);
184
185  document.write("<a ");
186  if(accessKey){
187    document.write("accesskey=\""+accessKey+"\" ");
188    speedTip = speedTip+' [ALT+'+accessKey.toUpperCase()+']';
189  }
190  document.write("href=\"javascript:insertAtCarret");
191  document.write("(document.editform.wikitext,'"+value+"');\">");
192
193  document.write("<img width=\"24\" height=\"24\" src=\""+
194                DOKU_BASE+'lib/images/toolbar/'+imageFile+"\" border=\"0\" alt=\""+
195                speedTip+"\" title=\""+speedTip+"\">");
196  document.write("</a>");
197  return;
198}
199
200/**
201 * This adds a button for the MediaSelection Popup
202 * @deprecated
203 */
204function mediaButton(imageFile, speedTip, accessKey, namespace) {
205  speedTip=escapeQuotes(speedTip);
206  document.write("<a ");
207  if(accessKey){
208    document.write("accesskey=\""+accessKey+"\" ");
209  }
210  document.write("href=\"javascript:void(window.open('"+DOKU_BASE+"lib/exe/media.php?ns="+
211                 namespace+"','mediaselect','width=600,height=320,left=70,top=50,scrollbars=yes,resizable=yes'));\">");
212  document.write("<img width=\"24\" height=\"24\" src=\""+
213                 DOKU_BASE+'lib/images/toolbar/'+imageFile+"\" border=\"0\" alt=\""+
214                 speedTip+"\" title=\""+speedTip+"\">");
215  document.write("</a>");
216  return;
217}
218
219/*
220 * Insert the selected filename and close the window
221 *
222 * @see http://www.alexking.org/index.php?content=software/javascript/content.php
223 */
224function mediaSelect(file){
225  insertAtCarret(opener.document.editform.wikitext,'{{'+file+'}}');
226  window.close();
227}
228
229
230/**
231 * For the upload Dialog. Prefills the wikiname.
232 */
233function suggestWikiname(){
234  var file = document.upload.upload.value;
235
236  file = file.substr(file.lastIndexOf('/')+1);
237  file = file.substr(file.lastIndexOf('\\')+1);
238
239  document.upload.id.value = file;
240}
241
242/**
243 * This prints the switch to toggle the Table of Contents
244 */
245function showTocToggle(showtxt,hidetxt) {
246  if(document.getElementById) {
247		show = '<img src="'+DOKU_BASE+'lib/images/arrow_down.gif" alt="'+showtxt+'">';
248		hide = '<img src="'+DOKU_BASE+'lib/images/arrow_up.gif" alt="'+hidetxt+'">';
249
250    document.writeln('<div class=\'toctoggle\'><a href="javascript:toggleToc()" class="toc">' +
251    '<span id="showlink" style="display:none;">' + show + '</span>' +
252    '<span id="hidelink">' + hide + '</span>'
253    + '</a></div>');
254  }
255}
256
257/**
258 * This toggles the visibility of the Table of Contents
259 */
260function toggleToc() {
261  var toc = document.getElementById('tocinside');
262  var showlink=document.getElementById('showlink');
263  var hidelink=document.getElementById('hidelink');
264  if(toc.style.display == 'none') {
265    toc.style.display = tocWas;
266    hidelink.style.display='';
267    showlink.style.display='none';
268  } else {
269    tocWas = toc.style.display;
270    toc.style.display = 'none';
271    hidelink.style.display='none';
272    showlink.style.display='';
273
274  }
275}
276
277
278/**
279 * global var used for not saved yet warning
280 */
281var textChanged = false;
282
283function svchk(){
284  if(textChanged){
285    return confirm(notSavedYet);
286  }else{
287    return true;
288  }
289}
290
291/**
292 * global variable for the locktimer
293 */
294var locktimerID;
295
296/**
297 * This starts a timer to remind the user of an expiring lock
298 * Accepts the delay in seconds and a text to display.
299 */
300function init_locktimer(delay,txt){
301  txt = escapeQuotes(txt);
302  locktimerID = self.setTimeout("locktimer('"+txt+"')", delay*1000);
303}
304
305/**
306 * This stops the timer and displays a message about the expiring lock
307 */
308function locktimer(txt){
309  clearTimeout(locktimerID);
310  alert(txt);
311}
312
313/*
314 * This sets a cookie by JavaScript
315 *
316 * @see http://www.webreference.com/js/column8/functions.html
317 */
318function setCookie(name, value, expires, path, domain, secure) {
319  var curCookie = name + "=" + escape(value) +
320      ((expires) ? "; expires=" + expires.toGMTString() : "") +
321      ((path) ? "; path=" + path : "") +
322      ((domain) ? "; domain=" + domain : "") +
323      ((secure) ? "; secure" : "");
324  document.cookie = curCookie;
325}
326
327/*
328 * This reads a cookie by JavaScript
329 *
330 * @see http://www.webreference.com/js/column8/functions.html
331 */
332function getCookie(name) {
333  var dc = document.cookie;
334  var prefix = name + "=";
335  var begin = dc.indexOf("; " + prefix);
336  if (begin == -1) {
337    begin = dc.indexOf(prefix);
338    if (begin != 0) return null;
339  } else
340    begin += 2;
341  var end = document.cookie.indexOf(";", begin);
342  if (end == -1)
343    end = dc.length;
344  return unescape(dc.substring(begin + prefix.length, end));
345}
346
347/*
348 * This is needed for the cookie functions
349 *
350 * @see http://www.webreference.com/js/column8/functions.html
351 */
352function fixDate(date) {
353  var base = new Date(0);
354  var skew = base.getTime();
355  if (skew > 0)
356    date.setTime(date.getTime() - skew);
357}
358
359/*
360 * This enables/disables checkboxes for acl-administration
361 *
362 * @author Frank Schubert <frank@schokilade.de>
363 */
364function checkAclLevel(){
365  if(document.getElementById) {
366    var scope = document.getElementById('acl_scope').value;
367
368    //check for namespace
369    if( (scope.indexOf(":*") > 0) || (scope == "*") ){
370      document.getElementsByName('acl_checkbox[4]')[0].disabled=false;
371      document.getElementsByName('acl_checkbox[8]')[0].disabled=false;
372    }else{
373      document.getElementsByName('acl_checkbox[4]')[0].checked=false;
374      document.getElementsByName('acl_checkbox[8]')[0].checked=false;
375
376      document.getElementsByName('acl_checkbox[4]')[0].disabled=true;
377      document.getElementsByName('acl_checkbox[8]')[0].disabled=true;
378    }
379  }
380}
381
382/* insitu footnote addition
383 * provide a wrapper for domTT javascript library
384 * this function is placed in the onmouseover event of footnote references in the main page
385 *
386 * @author Chris Smith <chris [at] jalakai [dot] co [dot] uk>
387 */
388var currentFootnote = 0;
389function fnt(id, e, evt) {
390
391    if (currentFootnote && id != currentFootnote) {
392        domTT_close(document.getElementById('insitu-fn'+currentFootnote));
393    }
394
395    // does the footnote tooltip already exist?
396    var fnt = document.getElementById('insitu-fn'+id);
397    if (!fnt) {
398        // if not create it...
399
400        // locate the footnote anchor element
401        var a = document.getElementById( "fn"+id );
402        if (!a) return;
403
404        // anchor parent is the footnote container, get its innerHTML
405        var footnote = new String (a.parentNode.innerHTML);
406
407        // strip the leading footnote anchors and their comma separators
408        footnote = footnote.replace(/<a\s.*?href=\".*\#fnt\d+\".*?<\/a>/gi, '');
409        footnote = footnote.replace(/^\s+(,\s+)+/,'');
410
411        // prefix ids on any elements with "insitu-" to ensure they remain unique
412        footnote = footnote.replace(/\bid=\"(.*?)\"/gi,'id="insitu-$1');
413   	} else {
414        var footnote = new String(fnt.innerHTML);
415    }
416
417    // activate the tooltip
418    domTT_activate(e, evt, 'content', footnote, 'type', 'velcro', 'id', 'insitu-fn'+id, 'styleClass', 'insitu-footnote', 'maxWidth', document.body.offsetWidth*0.4);
419    currentFootnote = id;
420}
421
422
423/**
424 * Add the edit window size controls
425 */
426function initSizeCtl(ctlid,edid){
427    var ctl      = document.getElementById(ctlid);
428    var textarea = document.getElementById(edid);
429
430    var hgt = getCookie('DokuWikisizeCtl');
431    if(hgt == null){
432      textarea.style.height = '300px';
433    }else{
434      textarea.style.height = hgt;
435    }
436
437    var l = document.createElement('img');
438    var s = document.createElement('img');
439    l.src = DOKU_BASE+'lib/images/larger.gif';
440    s.src = DOKU_BASE+'lib/images/smaller.gif';
441    l.onclick = function(){sizeCtl(edid,100);}
442    s.onclick = function(){sizeCtl(edid,-100);}
443    ctl.appendChild(l);
444    ctl.appendChild(s);
445}
446
447/**
448 * This sets the vertical size of the editbox
449 */
450function sizeCtl(edid,val){
451  var textarea = document.getElementById(edid);
452  var height = parseInt(textarea.style.height.substr(0,textarea.style.height.length-2));
453  height += val;
454  textarea.style.height = height+'px';
455
456  var now = new Date();
457  fixDate(now);
458  now.setTime(now.getTime() + 365 * 24 * 60 * 60 * 1000); //expire in a year
459  setCookie('DokuWikisizeCtl',textarea.style.height,now);
460}
461