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