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