|
1 // all utility functions go in here |
|
2 |
|
3 function makeUrl(page, query, html_friendly) |
|
4 { |
|
5 url = contentPath+page; |
|
6 if(url.indexOf('?') > 0) sep = '&'; |
|
7 else sep = '?'; |
|
8 if(query) |
|
9 { |
|
10 url = url + sep + query; |
|
11 } |
|
12 if(html_friendly) |
|
13 { |
|
14 url = url.replace('&', '&'); |
|
15 url = url.replace('<', '<'); |
|
16 url = url.replace('>', '>'); |
|
17 } |
|
18 return url; |
|
19 } |
|
20 |
|
21 function makeUrlNS(namespace, page, query, html_friendly) |
|
22 { |
|
23 var url = contentPath+namespace_list[namespace]+(page.replace(/ /g, '_')); |
|
24 if(url.indexOf('?') > 0) sep = '&'; |
|
25 else sep = '?'; |
|
26 if(query) |
|
27 { |
|
28 url = url + sep + query; |
|
29 } |
|
30 if(html_friendly) |
|
31 { |
|
32 url = url.replace('&', '&'); |
|
33 url = url.replace('<', '<'); |
|
34 url = url.replace('>', '>'); |
|
35 } |
|
36 return append_sid(url); |
|
37 } |
|
38 |
|
39 function strToPageID(string) |
|
40 { |
|
41 // Convert Special:UploadFile to ['UploadFile', 'Special'], but convert 'Image:Enano.png' to ['Enano.png', 'File'] |
|
42 for(var i in namespace_list) |
|
43 if(namespace_list[i] != '') |
|
44 if(namespace_list[i] == string.substr(0, namespace_list[i].length)) |
|
45 return [string.substr(namespace_list[i].length), i]; |
|
46 return [string, 'Article']; |
|
47 } |
|
48 |
|
49 function append_sid(url) |
|
50 { |
|
51 sep = ( url.indexOf('?') > 0 ) ? '&' : '?'; |
|
52 if(ENANO_SID.length > 10) |
|
53 { |
|
54 url = url + sep + 'auth=' + ENANO_SID; |
|
55 sep = '&'; |
|
56 } |
|
57 if ( pagepass.length > 0 ) |
|
58 { |
|
59 url = url + sep + 'pagepass=' + pagepass; |
|
60 } |
|
61 return url; |
|
62 } |
|
63 |
|
64 var stdAjaxPrefix = append_sid(scriptPath+'/ajax.php?title='+title); |
|
65 |
|
66 /** |
|
67 * Core AJAX library |
|
68 */ |
|
69 |
|
70 function ajaxMakeXHR() |
|
71 { |
|
72 var ajax; |
|
73 if (window.XMLHttpRequest) { |
|
74 ajax = new XMLHttpRequest(); |
|
75 } else { |
|
76 if (window.ActiveXObject) { |
|
77 ajax = new ActiveXObject("Microsoft.XMLHTTP"); |
|
78 } else { |
|
79 alert('Enano client-side runtime error: No AJAX support, unable to continue'); |
|
80 return; |
|
81 } |
|
82 } |
|
83 return ajax; |
|
84 } |
|
85 |
|
86 function ajaxGet(uri, f, call_editor_safe) { |
|
87 // Is the editor open? |
|
88 if ( editor_open && !call_editor_safe ) |
|
89 { |
|
90 // Make sure the user is willing to close the editor |
|
91 var conf = confirm($lang.get('editor_msg_confirm_ajax')); |
|
92 if ( !conf ) |
|
93 { |
|
94 // Kill off any "loading" windows, etc. and cancel the request |
|
95 unsetAjaxLoading(); |
|
96 return false; |
|
97 } |
|
98 // The user allowed the editor to be closed. Reset flags and knock out the on-close confirmation. |
|
99 editor_open = false; |
|
100 enableUnload(); |
|
101 } |
|
102 ajax = ajaxMakeXHR(); |
|
103 if ( !ajax ) |
|
104 { |
|
105 console.error('ajaxMakeXHR() failed'); |
|
106 return false; |
|
107 } |
|
108 ajax.onreadystatechange = f; |
|
109 ajax.open('GET', uri, true); |
|
110 ajax.setRequestHeader( "If-Modified-Since", "Sat, 1 Jan 2000 00:00:00 GMT" ); |
|
111 ajax.send(null); |
|
112 } |
|
113 |
|
114 function ajaxPost(uri, parms, f, call_editor_safe) { |
|
115 // Is the editor open? |
|
116 if ( editor_open && !call_editor_safe ) |
|
117 { |
|
118 // Make sure the user is willing to close the editor |
|
119 var conf = confirm($lang.get('editor_msg_confirm_ajax')); |
|
120 if ( !conf ) |
|
121 { |
|
122 // Kill off any "loading" windows, etc. and cancel the request |
|
123 unsetAjaxLoading(); |
|
124 return false; |
|
125 } |
|
126 // The user allowed the editor to be closed. Reset flags and knock out the on-close confirmation. |
|
127 editor_open = false; |
|
128 enableUnload(); |
|
129 } |
|
130 ajax = ajaxMakeXHR(); |
|
131 if ( !ajax ) |
|
132 { |
|
133 console.error('ajaxMakeXHR() failed'); |
|
134 return false; |
|
135 } |
|
136 ajax.onreadystatechange = f; |
|
137 ajax.open('POST', uri, true); |
|
138 ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); |
|
139 // Setting Content-length in Safari triggers a warning |
|
140 if ( !is_Safari ) |
|
141 { |
|
142 ajax.setRequestHeader("Content-length", parms.length); |
|
143 } |
|
144 ajax.setRequestHeader("Connection", "close"); |
|
145 ajax.send(parms); |
|
146 } |
|
147 |
|
148 /** |
|
149 * Show a friendly error message depicting an AJAX response that is not valid JSON |
|
150 * @param string Response text |
|
151 * @param string Custom error message. If omitted, the default will be shown. |
|
152 */ |
|
153 |
|
154 function handle_invalid_json(response, customerror) |
|
155 { |
|
156 var mainwin = $dynano('ajaxEditContainer').object; |
|
157 mainwin.innerHTML = ''; |
|
158 |
|
159 // Title |
|
160 var h3 = document.createElement('h3'); |
|
161 h3.appendChild(document.createTextNode('The site encountered an error while processing your request.')); |
|
162 mainwin.appendChild(h3); |
|
163 |
|
164 if ( typeof(customerror) == 'string' ) |
|
165 { |
|
166 var el = document.createElement('p'); |
|
167 el.appendChild(document.createTextNode(customerror)); |
|
168 mainwin.appendChild(el); |
|
169 } |
|
170 else |
|
171 { |
|
172 customerror = 'We unexpectedly received the following response from the server. The response should have been in the JSON '; |
|
173 customerror += 'serialization format, but the response wasn\'t composed only of the JSON response. There are three possible triggers '; |
|
174 customerror += 'for this problem:'; |
|
175 var el = document.createElement('p'); |
|
176 el.appendChild(document.createTextNode(customerror)); |
|
177 mainwin.appendChild(el); |
|
178 var ul = document.createElement('ul'); |
|
179 var li1 = document.createElement('li'); |
|
180 var li2 = document.createElement('li'); |
|
181 var li3 = document.createElement('li'); |
|
182 li1.appendChild(document.createTextNode('The server sent back a bad HTTP response code and thus sent an error page instead of running Enano. This indicates a possible problem with your server, and is not likely to be a bug with Enano.')); |
|
183 var osc_exception = ( window.location.hostname == 'demo.opensourcecms.com' ) ? ' This is KNOWN to be the case with the OpenSourceCMS.com demo version of Enano.' : ''; |
|
184 li2.appendChild(document.createTextNode('The server sent back the expected JSON response, but also injected some code into the response that should not be there. Typically this consists of advertisement code. In this case, the administrator of this site will have to contact their web host to have advertisements disabled.' + osc_exception)); |
|
185 li3.appendChild(document.createTextNode('It\'s possible that Enano triggered a PHP error or warning. In this case, you may be looking at a bug in Enano.')); |
|
186 |
|
187 ul.appendChild(li1); |
|
188 ul.appendChild(li2); |
|
189 ul.appendChild(li3); |
|
190 mainwin.appendChild(ul); |
|
191 } |
|
192 |
|
193 var p2 = document.createElement('p'); |
|
194 p2.appendChild(document.createTextNode('The response received from the server is as follows:')); |
|
195 mainwin.appendChild(p2); |
|
196 |
|
197 var pre = document.createElement('pre'); |
|
198 pre.appendChild(document.createTextNode(response)); |
|
199 mainwin.appendChild(pre); |
|
200 |
|
201 var p3 = document.createElement('p'); |
|
202 p3.appendChild(document.createTextNode('You may also choose to view the response as HTML. ')); |
|
203 var a = document.createElement('a'); |
|
204 a.appendChild(document.createTextNode('View as HTML...')); |
|
205 a._resp = response; |
|
206 a.id = 'invalidjson_link'; |
|
207 a.onclick = function() |
|
208 { |
|
209 var mb = new MessageBox(MB_YESNO | MB_ICONEXCLAMATION, 'Do you really want to view this response as HTML?', 'If the response was changed during transmission to include malicious code, you may be allowing that malicious code to run by viewing the response as HTML. Only do this if you have reviewed the response text and have found no suspicious code in it.'); |
|
210 mb.onclick['Yes'] = function() |
|
211 { |
|
212 var html = $dynano('invalidjson_link').object._resp; |
|
213 var win = window.open('about:blank', 'invalidjson_htmlwin', 'width=550,height=400,status=no,toolbars=no,toolbar=no,address=no,scroll=yes'); |
|
214 win.document.write(html); |
|
215 } |
|
216 return false; |
|
217 } |
|
218 a.href = '#'; |
|
219 p3.appendChild(a); |
|
220 mainwin.appendChild(p3); |
|
221 } |
|
222 |
|
223 function ajaxEscape(text) |
|
224 { |
|
225 /* |
|
226 text = escape(text); |
|
227 text = text.replace(/\+/g, '%2B', text); |
|
228 */ |
|
229 text = window.encodeURIComponent(text); |
|
230 return text; |
|
231 } |
|
232 |
|
233 /** |
|
234 * String functions |
|
235 */ |
|
236 |
|
237 // Equivalent to PHP trim() function |
|
238 function trim(text) |
|
239 { |
|
240 text = text.replace(/^([\s]+)/, ''); |
|
241 text = text.replace(/([\s]+)$/, ''); |
|
242 return text; |
|
243 } |
|
244 |
|
245 // Equivalent to PHP implode() function |
|
246 function implode(chr, arr) |
|
247 { |
|
248 if ( typeof ( arr.toJSONString ) == 'function' ) |
|
249 delete(arr.toJSONString); |
|
250 |
|
251 var ret = ''; |
|
252 var c = 0; |
|
253 for ( var i in arr ) |
|
254 { |
|
255 if(i=='toJSONString')continue; |
|
256 if ( c > 0 ) |
|
257 ret += chr; |
|
258 ret += arr[i]; |
|
259 c++; |
|
260 } |
|
261 return ret; |
|
262 } |
|
263 |
|
264 function form_fetch_field(form, name) |
|
265 { |
|
266 var fields = form.getElementsByTagName('input'); |
|
267 if ( fields.length < 1 ) |
|
268 return false; |
|
269 for ( var i = 0; i < fields.length; i++ ) |
|
270 { |
|
271 var field = fields[i]; |
|
272 if ( field.name == name ) |
|
273 return field; |
|
274 } |
|
275 return false; |
|
276 } |
|
277 |
|
278 function get_parent_form(o) |
|
279 { |
|
280 if ( !o.parentNode ) |
|
281 return false; |
|
282 if ( o.tagName == 'FORM' ) |
|
283 return o; |
|
284 var p = o.parentNode; |
|
285 while(true) |
|
286 { |
|
287 if ( p.tagName == 'FORM' ) |
|
288 return p; |
|
289 else if ( !p ) |
|
290 return false; |
|
291 else |
|
292 p = p.parentNode; |
|
293 } |
|
294 } |
|
295 |
|
296 function findParentForm(o) |
|
297 { |
|
298 return get_parent_form(o); |
|
299 } |
|
300 |
|
301 function domObjChangeOpac(opacity, id) { |
|
302 var object = id.style; |
|
303 object.opacity = (opacity / 100); |
|
304 object.MozOpacity = (opacity / 100); |
|
305 object.KhtmlOpacity = (opacity / 100); |
|
306 object.filter = "alpha(opacity=" + opacity + ")"; |
|
307 } |
|
308 |
|
309 function getScrollOffset() |
|
310 { |
|
311 var position; |
|
312 if (self.pageYOffset) |
|
313 { |
|
314 position = self.pageYOffset; |
|
315 } |
|
316 else if (document.documentElement && document.documentElement.scrollTop) |
|
317 { |
|
318 position = document.documentElement.scrollTop; |
|
319 } |
|
320 else if (document.body) |
|
321 { |
|
322 position = document.body.scrollTop; |
|
323 } |
|
324 return position; |
|
325 } |
|
326 |
|
327 // Function to fade classes info-box, warning-box, error-box, etc. |
|
328 |
|
329 function fadeInfoBoxes() |
|
330 { |
|
331 var divs = new Array(); |
|
332 d = document.getElementsByTagName('div'); |
|
333 j = 0; |
|
334 for(var i in d) |
|
335 { |
|
336 if ( !d[i] ) |
|
337 continue; |
|
338 if ( !d[i].tagName ) |
|
339 continue; |
|
340 if(d[i].className=='info-box' || d[i].className=='error-box' || d[i].className=='warning-box' || d[i].className=='question-box') |
|
341 { |
|
342 divs[j] = d[i]; |
|
343 j++; |
|
344 } |
|
345 } |
|
346 if(divs.length < 1) return; |
|
347 load_component('fat'); |
|
348 for(i in divs) |
|
349 { |
|
350 if(!divs[i].id) divs[i].id = 'autofade_'+Math.floor(Math.random() * 100000); |
|
351 switch(divs[i].className) |
|
352 { |
|
353 case 'info-box': |
|
354 default: |
|
355 from = '#3333FF'; |
|
356 break; |
|
357 case 'error-box': |
|
358 from = '#FF3333'; |
|
359 break; |
|
360 case 'warning-box': |
|
361 from = '#FFFF33'; |
|
362 break; |
|
363 case 'question-box': |
|
364 from = '#33FF33'; |
|
365 break; |
|
366 } |
|
367 Fat.fade_element(divs[i].id,30,2000,from,Fat.get_bgcolor(divs[i].id)); |
|
368 } |
|
369 } |
|
370 |
|
371 addOnloadHook(fadeInfoBoxes); |
|
372 |
|
373 // Alpha fades |
|
374 |
|
375 function opacity(id, opacStart, opacEnd, millisec) |
|
376 { |
|
377 var object = document.getElementById(id); |
|
378 domOpacity(object, opacStart, opacEnd, millisec); |
|
379 } |
|
380 |
|
381 var opacityDOMCache = new Object(); |
|
382 function domOpacity(obj, opacStart, opacEnd, millisec) { |
|
383 //speed for each frame |
|
384 var speed = Math.round(millisec / 100); |
|
385 var timer = 0; |
|
386 |
|
387 // unique ID for this animation |
|
388 var uniqid = Math.floor(Math.random() * 1000000); |
|
389 opacityDOMCache[uniqid] = obj; |
|
390 |
|
391 //determine the direction for the blending, if start and end are the same nothing happens |
|
392 if(opacStart > opacEnd) { |
|
393 for(i = opacStart; i >= opacEnd; i--) { |
|
394 setTimeout("var obj = opacityDOMCache["+uniqid+"]; domObjChangeOpac(" + i + ",obj)",(timer * speed)); |
|
395 timer++; |
|
396 } |
|
397 } else if(opacStart < opacEnd) { |
|
398 for(i = opacStart; i <= opacEnd; i++) |
|
399 { |
|
400 setTimeout("var obj = opacityDOMCache["+uniqid+"]; domObjChangeOpac(" + i + ",obj)",(timer * speed)); |
|
401 timer++; |
|
402 } |
|
403 } |
|
404 setTimeout("delete(opacityDOMCache["+uniqid+"]);",(timer * speed)); |
|
405 } |
|
406 |
|
407 // change the opacity for different browsers |
|
408 function changeOpac(opacity, id) |
|
409 { |
|
410 var object = document.getElementById(id); |
|
411 return domObjChangeOpac(opacity, object); |
|
412 } |
|
413 |
|
414 // draw a white ajax-ey "loading" box over an object |
|
415 function whiteOutElement(el) |
|
416 { |
|
417 var top = $(el).Top(); |
|
418 var left = $(el).Left(); |
|
419 var width = $(el).Width(); |
|
420 var height = $(el).Height(); |
|
421 |
|
422 var blackout = document.createElement('div'); |
|
423 blackout.style.position = 'absolute'; |
|
424 blackout.style.top = top + 'px'; |
|
425 blackout.style.left = left + 'px'; |
|
426 blackout.style.width = width + 'px'; |
|
427 blackout.style.height = height + 'px'; |
|
428 |
|
429 blackout.style.backgroundColor = '#FFFFFF'; |
|
430 domObjChangeOpac(60, blackout); |
|
431 blackout.style.backgroundImage = 'url(' + scriptPath + '/includes/clientside/tinymce/themes/advanced/skins/default/img/progress.gif)'; |
|
432 blackout.style.backgroundPosition = 'center center'; |
|
433 blackout.style.backgroundRepeat = 'no-repeat'; |
|
434 blackout.style.zIndex = getHighestZ() + 2; |
|
435 |
|
436 var body = document.getElementsByTagName('body')[0]; |
|
437 body.appendChild(blackout); |
|
438 |
|
439 return blackout; |
|
440 } |
|
441 |
|
442 // other DHTML functions |
|
443 |
|
444 function fetch_offset(obj) |
|
445 { |
|
446 var left_offset = obj.offsetLeft; |
|
447 var top_offset = obj.offsetTop; |
|
448 while ((obj = obj.offsetParent) != null) { |
|
449 left_offset += obj.offsetLeft; |
|
450 top_offset += obj.offsetTop; |
|
451 } |
|
452 return { 'left' : left_offset, 'top' : top_offset }; |
|
453 } |
|
454 |
|
455 function fetch_dimensions(o) { |
|
456 var w = o.offsetWidth; |
|
457 var h = o.offsetHeight; |
|
458 return { 'w' : w, 'h' : h }; |
|
459 } |
|
460 |
|
461 function findParentForm(o) |
|
462 { |
|
463 if ( o.tagName == 'FORM' ) |
|
464 return o; |
|
465 while(true) |
|
466 { |
|
467 o = o.parentNode; |
|
468 if ( !o ) |
|
469 return false; |
|
470 if ( o.tagName == 'FORM' ) |
|
471 return o; |
|
472 } |
|
473 return false; |
|
474 } |
|
475 |
|
476 function bannerOn(text) |
|
477 { |
|
478 darken(true); |
|
479 var thediv = document.createElement('div'); |
|
480 thediv.className = 'mdg-comment'; |
|
481 thediv.style.padding = '0'; |
|
482 thediv.style.marginLeft = '0'; |
|
483 thediv.style.position = 'absolute'; |
|
484 thediv.style.display = 'none'; |
|
485 thediv.style.padding = '4px'; |
|
486 thediv.style.fontSize = '14pt'; |
|
487 thediv.id = 'mdgDynamic_bannerDiv_'+Math.floor(Math.random() * 1000000); |
|
488 thediv.innerHTML = text; |
|
489 |
|
490 var body = document.getElementsByTagName('body'); |
|
491 body = body[0]; |
|
492 body.appendChild(thediv); |
|
493 body.style.cursor = 'wait'; |
|
494 |
|
495 thediv.style.display = 'block'; |
|
496 dim = fetch_dimensions(thediv); |
|
497 thediv.style.display = 'none'; |
|
498 bdim = { 'w' : getWidth(), 'h' : getHeight() }; |
|
499 so = getScrollOffset(); |
|
500 |
|
501 var left = (bdim['w'] / 2) - ( dim['w'] / 2 ); |
|
502 |
|
503 var top = (bdim['h'] / 2); |
|
504 top = top - ( dim['h'] / 2 ); |
|
505 |
|
506 top = top + so; |
|
507 |
|
508 thediv.style.top = top + 'px'; |
|
509 thediv.style.left = left + 'px'; |
|
510 |
|
511 thediv.style.display = 'block'; |
|
512 |
|
513 return thediv.id; |
|
514 } |
|
515 |
|
516 function bannerOff(id) |
|
517 { |
|
518 e = document.getElementById(id); |
|
519 if(!e) return; |
|
520 e.innerHTML = ''; |
|
521 e.style.display = 'none'; |
|
522 var body = document.getElementsByTagName('body'); |
|
523 body = body[0]; |
|
524 body.style.cursor = 'default'; |
|
525 enlighten(true); |
|
526 } |
|
527 |
|
528 function disableUnload(message) |
|
529 { |
|
530 if(typeof message != 'string') message = 'You may want to save your changes first.'; |
|
531 window._unloadmsg = message; |
|
532 window.onbeforeunload = function(e) |
|
533 { |
|
534 if ( !e ) |
|
535 e = window.event; |
|
536 e.returnValue = window._unloadmsg; |
|
537 } |
|
538 } |
|
539 |
|
540 function enableUnload() |
|
541 { |
|
542 window._unloadmsg = null; |
|
543 window.onbeforeunload = null; |
|
544 } |
|
545 |
|
546 /** |
|
547 * Gets the highest z-index of all divs in the document |
|
548 * @return integer |
|
549 */ |
|
550 function getHighestZ() |
|
551 { |
|
552 z = 0; |
|
553 var divs = document.getElementsByTagName('div'); |
|
554 for(var i = 0; i < divs.length; i++) |
|
555 { |
|
556 if(divs[i].style.zIndex > z) z = divs[i].style.zIndex; |
|
557 } |
|
558 return z; |
|
559 } |
|
560 |
|
561 function isKeyPressed(event) |
|
562 { |
|
563 if (event.shiftKey==1) |
|
564 { |
|
565 shift = true; |
|
566 } |
|
567 else |
|
568 { |
|
569 shift = false; |
|
570 } |
|
571 } |
|
572 |
|
573 function moveDiv(div, newparent) |
|
574 { |
|
575 var backup = div; |
|
576 var oldparent = div.parentNode; |
|
577 oldparent.removeChild(div); |
|
578 newparent.appendChild(backup); |
|
579 } |
|
580 |
|
581 var busyBannerID; |
|
582 function goBusy(msg) |
|
583 { |
|
584 if(!msg) msg = 'Please wait...'; |
|
585 body = document.getElementsByTagName('body'); |
|
586 body = body[0]; |
|
587 body.style.cursor = 'wait'; |
|
588 busyBannerID = bannerOn(msg); |
|
589 } |
|
590 |
|
591 function unBusy() |
|
592 { |
|
593 body = document.getElementsByTagName('body'); |
|
594 body = body[0]; |
|
595 body.style.cursor = 'default'; |
|
596 bannerOff(busyBannerID); |
|
597 } |
|
598 |
|
599 function setAjaxLoading() |
|
600 { |
|
601 if ( document.getElementById('ajaxloadicon') ) |
|
602 { |
|
603 document.getElementById('ajaxloadicon').src=ajax_load_icon; |
|
604 } |
|
605 } |
|
606 |
|
607 function unsetAjaxLoading() |
|
608 { |
|
609 if ( document.getElementById('ajaxloadicon') ) |
|
610 { |
|
611 document.getElementById('ajaxloadicon').src=scriptPath + '/images/spacer.gif'; |
|
612 } |
|
613 } |
|
614 |
|
615 function readCookie(name) {var nameEQ = name + "=";var ca = document.cookie.split(';');for(var i=0;i < ca.length;i++){var c = ca[i];while (c.charAt(0)==' ') c = c.substring(1,c.length);if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);}return null;} |
|
616 function createCookie(name,value,days){if (days){var date = new Date();date.setTime(date.getTime()+(days*24*60*60*1000));var expires = "; expires="+date.toGMTString();}else var expires = "";document.cookie = name+"="+value+expires+"; path=/";} |
|
617 function eraseCookie(name) {createCookie(name,"",-1);} |
|
618 |
|
619 /* |
|
620 * AJAX login box (experimental) |
|
621 * Moved / rewritten in login.js |
|
622 */ |
|
623 |
|
624 // Included only for API-compatibility |
|
625 function ajaxPromptAdminAuth(call_on_ok, level) |
|
626 { |
|
627 ajaxLogonInit(call_on_ok, level); |
|
628 } |
|
629 |
|
630 /** |
|
631 * Insert a DOM object _after_ the specified child. |
|
632 * @param object Parent node |
|
633 * @param object Node to insert |
|
634 * @param object Node to insert after |
|
635 */ |
|
636 |
|
637 function insertAfter(parent, baby, bigsister) |
|
638 { |
|
639 try |
|
640 { |
|
641 if ( parent.childNodes[parent.childNodes.length-1] == bigsister ) |
|
642 parent.appendChild(baby); |
|
643 else |
|
644 parent.insertBefore(baby, bigsister.nextSibling); |
|
645 } |
|
646 catch(e) |
|
647 { |
|
648 alert(e.toString()); |
|
649 if ( window.console ) |
|
650 { |
|
651 // Firebug support |
|
652 window.console.warn(e); |
|
653 } |
|
654 } |
|
655 } |
|
656 |
|
657 /** |
|
658 * Validates an e-mail address. |
|
659 * @param string E-mail address |
|
660 * @return bool |
|
661 */ |
|
662 |
|
663 function validateEmail(email) |
|
664 { |
|
665 return ( email.match(/^(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*|(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*(?:(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[^()<>@,;:".\\\[\]\x80-\xff\000-\010\012-\037]*)*<[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*(?:,[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*)*:[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)?(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|"[^\\\x80-\xff\n\015"]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015"]*)*")[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*@[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:\.[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*(?:[^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff]+(?![^(\040)<>@,;:".\\\[\]\000-\037\x80-\xff])|\[(?:[^\\\x80-\xff\n\015\[\]]|\\[^\x80-\xff])*\])[\040\t]*(?:\([^\\\x80-\xff\n\015()]*(?:(?:\\[^\x80-\xff]|\([^\\\x80-\xff\n\015()]*(?:\\[^\x80-\xff][^\\\x80-\xff\n\015()]*)*\))[^\\\x80-\xff\n\015()]*)*\)[\040\t]*)*)*>)$/) ) ? true : false; |
|
666 } |
|
667 |
|
668 /** |
|
669 * Validates a username. |
|
670 * @param string Username to test |
|
671 * @return bool |
|
672 */ |
|
673 |
|
674 function validateUsername(username) |
|
675 { |
|
676 var regex = new RegExp('^[^<>&\?\'"%\n\r/]+$', ''); |
|
677 return ( username.match(regex) ) ? true : false; |
|
678 } |
|
679 |
|
680 /* |
|
681 * Utility functions, moved from windows.js |
|
682 */ |
|
683 |
|
684 function getHeight() { |
|
685 var myHeight = 0; |
|
686 if( typeof( window.innerWidth ) == 'number' ) { |
|
687 myHeight = window.innerHeight; |
|
688 } else if( document.documentElement && |
|
689 ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) { |
|
690 myHeight = document.documentElement.clientHeight; |
|
691 } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) { |
|
692 myHeight = document.body.clientHeight; |
|
693 } |
|
694 return myHeight; |
|
695 } |
|
696 |
|
697 function getWidth() { |
|
698 var myWidth = 0; |
|
699 if( typeof( window.innerWidth ) == 'number' ) { |
|
700 myWidth = window.innerWidth; |
|
701 } else if( document.documentElement && |
|
702 ( document.documentElement.clientWidth || document.documentElement.clientWidth ) ) { |
|
703 myWidth = document.documentElement.clientWidth; |
|
704 } else if( document.body && ( document.body.clientWidth || document.body.clientWidth ) ) { |
|
705 myWidth = document.body.clientWidth; |
|
706 } |
|
707 return myWidth; |
|
708 } |
|
709 |
|
710 /** |
|
711 * Sanitizes a page URL string so that it can safely be stored in the database. |
|
712 * @param string Page ID to sanitize |
|
713 * @return string Cleaned text |
|
714 */ |
|
715 |
|
716 function sanitize_page_id(page_id) |
|
717 { |
|
718 // Remove character escapes |
|
719 page_id = dirtify_page_id(page_id); |
|
720 |
|
721 var regex = new RegExp('[A-Za-z0-9\\[\\]\./:;\(\)@_-]', 'g'); |
|
722 pid_clean = page_id.replace(regex, 'X'); |
|
723 var pid_dirty = []; |
|
724 for ( var i = 0; i < pid_clean.length; i++ ) |
|
725 pid_dirty[i] = pid_clean.substr(i, 1); |
|
726 |
|
727 for ( var i = 0; i < pid_dirty.length; i++ ) |
|
728 { |
|
729 var chr = pid_dirty[i]; |
|
730 if ( chr == 'X' ) |
|
731 continue; |
|
732 var cid = chr.charCodeAt(0); |
|
733 cid = cid.toString(16).toUpperCase(); |
|
734 if ( cid.length < 2 ) |
|
735 { |
|
736 cid = '0' + cid; |
|
737 } |
|
738 pid_dirty[i] = "." + cid; |
|
739 } |
|
740 |
|
741 var pid_chars = []; |
|
742 for ( var i = 0; i < page_id.length; i++ ) |
|
743 pid_chars[i] = page_id.substr(i, 1); |
|
744 |
|
745 var page_id_cleaned = ''; |
|
746 |
|
747 for ( var id in pid_chars ) |
|
748 { |
|
749 var chr = pid_chars[id]; |
|
750 if ( pid_dirty[id] == 'X' ) |
|
751 page_id_cleaned += chr; |
|
752 else |
|
753 page_id_cleaned += pid_dirty[id]; |
|
754 } |
|
755 |
|
756 return page_id_cleaned; |
|
757 } |
|
758 |
|
759 /** |
|
760 * Removes character escapes in a page ID string |
|
761 * @param string Page ID string to dirty up |
|
762 * @return string |
|
763 */ |
|
764 |
|
765 function dirtify_page_id(page_id) |
|
766 { |
|
767 // First, replace spaces with underscores |
|
768 page_id = page_id.replace(/ /g, '_'); |
|
769 |
|
770 var matches = page_id.match(/\.[A-Fa-f0-9][A-Fa-f0-9]/g); |
|
771 |
|
772 if ( matches != null ) |
|
773 { |
|
774 for ( var i = 0; i < matches.length; i++ ) |
|
775 { |
|
776 var match = matches[i]; |
|
777 var byt = (match.substr(1)).toUpperCase(); |
|
778 var code = eval("0x" + byt); |
|
779 var regex = new RegExp('\\.' + byt, 'g'); |
|
780 page_id = page_id.replace(regex, String.fromCharCode(code)); |
|
781 } |
|
782 } |
|
783 |
|
784 return page_id; |
|
785 } |
|
786 |
|
787 /** |
|
788 * Equivalent to PHP's in_array function. |
|
789 */ |
|
790 |
|
791 function in_array(needle, haystack) |
|
792 { |
|
793 for(var i in haystack) |
|
794 { |
|
795 if(haystack[i] == needle) return i; |
|
796 } |
|
797 return false; |
|
798 } |