1 /**
  2  * @name shoogar
  3  * @overview  Javascript Application & Development Framework
  4  
  5  * @features 
  6  * 1. Enables autoload function with a configuration file. <br/>
  7  * 2. Enables the adding and removing of external stylesheets or javascript 
  8  *    files or internal styles. <br/>
  9  * 3. Includes an extensive browser check. <br/>
 10  * 4. Enables valid browser specific CSS fixes with Javacript: no more ugly 
 11  *    selector or property hacks! <br/>
 12  * 5. Contains more usefull functions (Ajax, Browser, Cookie, Debug, 
 13  *    Element, Event, Script and Style). 
 14  
 15  * @changelog <a href="http://jslib.bizmedia.de/shoogar/changelog.txt">changelog.txt</a>
 16  * @demo <a href="http://jslib.bizmedia.de/shoogar/demo.htm">demo.htm</a>
 17  * @tests <a href="http://jslib.bizmedia.de/shoogar/tests.htm">tests.htm</a>
 18  * @download <a href="http://jslib.bizmedia.de/downloads/shoogar.js">shoogar.js</a>
 19  * @apidoc <a href="http://jslib.bizmedia.de/">bizmedia jslib</a>
 20 
 21  * @status development 
 22  * @version 1.7.6
 23  * @last mod 2008/01/16
 24 
 25  * @supported<br/>browsers 
 26    Internet Explorer 6 higher <br/>
 27    Firefox 1.5 higher <br/>
 28    Opera 9.x higher <br/>
 29    Safari 2.x higher <br/>
 30 
 31  * @author Uli Preuss</a>
 32  * @copyright © 2007-2008 <a href="http://www.bizmedia.de">bizmedia</a>
 33  
 34  * @note 'Shoogar' is the name of a curious magus in the wonderful fantasy novel 
 35  * 'The Flying Sorcerers' by David Gerrold and Larry Niven. The conclusion of the
 36  * story: magic and sciences are only two modes of perception one and the same 
 37  * things - the reality.
 38 
 39  * @licence The MIT License:
 40    <br/><br/>
 41    Permission is hereby granted, free of charge, to any person obtaining a copy 
 42    of this software and associated documentation files (the "Software"), to deal 
 43    in the Software without restriction, including without limitation the rights 
 44    to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 
 45    copies of the Software, and to permit persons to whom the Software is 
 46    furnished to do so, subject to the following conditions:
 47    <br/><br/> 
 48    The above copyright notice and this permission notice shall be included in all 
 49    copies or substantial portions of the Software.
 50    <br/><br/> 
 51    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 
 52    IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 
 53    FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 
 54    AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 
 55    LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 
 56    OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 
 57    SOFTWARE.
 58    <br/><br/>
 59 */
 60 
 61 if ( typeof(SHO) == 'undefined' ) {
 62   /** 
 63   * @constructor 
 64   * @desc Base class
 65   * @property {object} isloaded Object with infos if subclasses are loaded
 66   * @property {object} metadata Infos about the Initer script
 67   * @example
 68   * var obj = new SC();
 69   * if( obj.isloaded.Browser == true) do something;
 70   * alert( obj.metadata.version );
 71   */ 
 72   SHO = function() {
 73     // Escape protocol (otherwise compression fails)
 74 	this.ptc = unescape('http%3A\/\/'),
 75 
 76     this.metadata = {
 77       'version'            : '1.7.6', 
 78       'lastmod'            : '2008/01/16', 
 79       'contact'            : 'up@bizmedia.de', 
 80       'urlscript'          : this.ptc + 'jslib.bizmedia.de/downloads',   
 81       'urldoc'             : this.ptc + 'jslib.bizmedia.de/shoogar.html'  
 82 	},
 83     this.dirnames = {
 84       'STYLESHEET'         : 'stylesheets' , 
 85       'STYLESHEET_AUTO'    :    'content/pages' , 
 86       'STYLESHEET_PATCHES' :    'content/patches' , 
 87       'STYLESHEET_APPS'    :    'content/apps' , 
 88       'STYLESHEET_ALTER'   :    'content/alternates' , 
 89       'JAVASCRIPT'         : 'javascripts' , 
 90       'JAVASCRIPT_LIB'     :    'lib' , 
 91       'JAVASCRIPT_DEV'     :    'dev' , 
 92       'JAVASCRIPT_APPS'    :    'apps' , 
 93       'IMAGES'             : 'images' , 
 94       'CONF'               : 'conf'
 95 	},
 96     this.isloaded = {
 97       'Ajax'    : false , 
 98       'Browser' : false , 
 99       'Cookie'  : false ,
100       'Config'  : false , 
101       'Debug'   : false , 
102       'Element' : false , 
103       'Event'   : false , 
104       'Script'  : false , 
105       'Style'   : false 
106 	}
107   };
108 
109   var _SHO = new SHO();
110 
111 };
112 
113 
114 /********************************************************************************
115  ***** AJAX_FUNCTIONS ***********************************************************/
116 
117 /** @constructor
118   * @desc Ajax functions
119   * @example
120   * var ajaxObj = new SHO.Ajax();
121  */
122 SHO.Ajax = function () {
123 
124   _SHO.isloaded.Ajax = true;
125 
126   /** 
127   * @memberOf SHO.Ajax
128   * @desc Load 
129   * @param {string} url JSON/XML Object Url 
130   * @example
131   * ajaxObj.simpleRequest(url);
132   */
133   this.simpleRequest = function(url) {
134     simple = {
135       request : 
136         (window.XMLHttpRequest) ? new XMLHttpRequest() : 
137         ((window.ActiveXObject) ? new ActiveXObject('Microsoft.XMLHTTP') : 
138         false),
139       getText: function (url) {
140         this.request.open("GET", url, false);
141           this.request.send(null);
142           if (this.request.status == 200 || this.request.status == 0)
143             return this.request.responseText;
144       }
145     };
146 	simple.getText(url);
147   };
148   /** 
149   * @memberOf SHO.Ajax
150   * @desc Load JSON/XML Object with JKL.ParseXML.
151   * @param {string} data_type JSON or XML
152   * @param {string} data_source JSON/XML Object Url 
153   * @param {string} rootElement Name of root element (optional/only XML)
154   * @example
155   * ajaxObj.parseData(url);
156   */
157   this.parseData = function(data_type, data_source, rootElement) {
158     onCreateHandler();
159 	if(data_type == "xml") {
160       PARSER = new JKL.ParseXML( data_source );
161     }
162     else if(data_type == "json") {
163       PARSER = new JKL.ParseXML.JSON( data_source );
164     }
165     var onSuccess = function(data) { 
166       onSuccessHandler();
167 	  if(data_type == "xml") http = eval('data.' + rootElement);
168       else if(data_type == "json")  http = data;
169 	}
170     PARSER.async(onSuccess);
171     PARSER.parse();
172   };
173   /** 
174   * @memberOf SHO.Ajax
175   * @desc Load JSON Object with prototype Ajax.Request.
176   * @param {string} url JSON Object Url 
177   * @example
178   * ajaxObj.loadJSON(url);
179   */
180   this.loadJSON = function(url) {
181     var oJSON = new Ajax.Request(url, {
182 	  method:'get', 
183 	  encoding:'UTF-8', 
184 	  asynchronous: true, 
185 	  onCreate: onCreateHandler,
186 	  onException: onExceptionHandler, 
187 	  onSuccess: onSuccessHandler
188 	});
189   };
190 };
191 
192 
193 
194 /********************************************************************************
195  ***** BROWSER_FUNCTIONS ********************************************************/
196 
197 /** 
198   * @constructor 
199   * @desc This function performs an extensive browser detection 
200     and stores all data in an object for later use. 
201   * @example
202   * var browserObj = new SHO.Browser();
203 */
204 SHO.Browser = function () {
205 	
206   _SHO.isloaded.Browser = true;
207 
208   var ua = navigator.userAgent.toLowerCase(); 
209 
210  /** 
211   * @memberOf SHO.Browser
212   * @desc Checks browser name
213   * @type bool
214   * @example
215   * if (browserObj.name == "Opera") do something 
216   */
217   this.name = null;
218   /** 
219   * @memberOf SHO.Browser
220   * @desc Checks browser platform
221   * @type bool
222   * @example
223   * if (browserObj.platform == "Mac") do something 
224   */
225   this.platform = null;
226   /** 
227   * @memberOf SHO.Browser
228   * @desc Checks if browser is Gecko
229   * @type bool
230   * @example
231   * if (browserObj.isGecko) do something 
232   */
233   this.isGecko = (ua.indexOf('gecko') != -1 && ua.indexOf('safari') == -1);
234   /** 
235   * @memberOf SHO.Browser
236   * @desc Checks if browser is AppleWebKit
237   * @type bool
238   * @example
239   * if (browserObj.isAppleWebKit) do something 
240   */
241   this.isAppleWebKit = (ua.indexOf('applewebkit') != -1);
242   if(ua.indexOf('opera') != -1) {
243     this.isOpera = true; 
244 	this.name = "Opera"
245   };
246   if((ua.indexOf('msie') != -1 && 
247     !this.isOpera && (ua.indexOf('webtv') == -1) )) {
248   /** 
249   * @memberOf SHO.Browser
250   * @desc Checks if browser is IE
251   * @type bool
252   * @example
253   * if (browserObj.isIE) do something 
254   */
255       this.isIE=true; 
256 	  this.name = "Internet Explorer"
257   };
258   if(this.isGecko && ua.indexOf('gecko/') + 14 == ua.length) {
259     this.isMozilla=true; 
260 	this.name = "Mozilla"
261   };
262   if((this.isGecko) ? (ua.indexOf('netscape') != -1) : 
263     ( (ua.indexOf('mozilla') != -1) &&
264     !this.isOpera && !this.isSafari && (ua.indexOf('spoofer') == -1) && 
265     (ua.indexOf('compatible') == -1) && (ua.indexOf('webtv') == -1) && 
266     (ua.indexOf('hotjava') == -1) )) {
267   /** 
268   * @memberOf SHO.Browser
269   * @desc Checks if browser is Netscape
270   * @type bool
271   * @example
272   * if (browserObj.isNS) do something 
273   */
274        this.isNS=true; 
275 	  this.name = "Netscape"
276   };
277   if(ua.indexOf('firebird/') != -1) {
278   /** 
279   * @memberOf SHO.Browser
280   * @desc Checks if browser is Firebird
281   * @type bool
282   * @example
283   * if (browserObj.isFirebird) do something 
284   */
285     this.isFirebird=true; 
286 	this.name = "Firebird"
287   };
288   if(ua.indexOf('firefox/') != -1) {
289   /** 
290   * @memberOf SHO.Browser
291   * @desc Checks if browser is Firefox
292   * @type bool
293   * @example
294   * if (browserObj.isFirefox) do something 
295   */
296     this.isFirefox=true; 
297 	this.name = "Firefox"
298   };
299   if(ua.indexOf('safari/') != -1) {
300   /** 
301   * @memberOf SHO.Browser
302   * @desc Checks if browser is Safari
303   * @type bool
304   * @example
305   * if (browserObj.isSafari) do something 
306   */
307     this.isSafari=true; 
308 	this.name = "Safari"
309   };
310   if(ua.indexOf('konqueror') != -1) {
311   /** 
312   * @memberOf SHO.Browser
313   * @desc Checks if browser is Konqueror
314   * @type bool
315   * @example
316   * if (browserObj.isKonqueror) do something 
317   */
318     this.isKonqueror=true; 
319 	this.name = "Konqueror"
320   };
321   if(ua.indexOf('omniweb') != -1) {
322   /** 
323   * @memberOf SHO.Browser
324   * @desc Checks if browser is Omniweb
325   * @type bool
326   * @example
327   * if (browserObj.isOmniweb) do something 
328   */
329     this.isOmniweb=true; 
330 	this.name = "Omniweb"
331   };
332   if(ua.indexOf('webtv') != -1) {
333   /** 
334   * @memberOf SHO.Browser
335   * @desc Checks if browser is Webtv
336   * @type bool
337   * @example
338   * if (browserObj.isWebtv) do something 
339   */
340     this.isWebtv=true; 
341 	this.name = "WebTV"
342   };
343   if(ua.indexOf('icab') != -1) {
344   /** 
345   * @memberOf SHO.Browser
346   * @desc Checks if browser is ICab
347   * @type bool
348   * @example
349   * if (browserObj.isICab) do something 
350   */
351     this.isICab=true; 
352 	this.name = "Icab"
353   };
354   if(ua.indexOf('camino') != -1) {
355   /** 
356   * @memberOf SHO.Browser
357   * @desc Checks if browser is Camino
358   * @type bool
359   * @example
360   * if (browserObj.isCamino) do something 
361   */
362     this.isCamino=true; 
363 	this.name = "Camino"
364   };
365   // spoofing and compatible browsers
366   /** 
367   * @memberOf SHO.Browser
368   * @desc Checks if browser is IE compatible
369   * @type bool
370   * @example
371   * if (browserObj.isIECompatible) do something 
372   */
373   this.isIECompatible = ( (ua.indexOf('msie') != -1) && !this.isIE);
374   /** 
375   * @memberOf SHO.Browser
376   * @desc Checks if browser is NS compatible
377   * @type bool
378   * @example
379   * if (browserObj.isNSCompatible) do something 
380   */
381   this.isNSCompatible = ( (ua.indexOf('mozilla') != -1) && 
382     !this.isNS && !this.isMozilla);
383   // rendering engine versions
384   /** 
385   * @memberOf SHO.Browser
386   * @desc Checks if browser is Gecko version
387   * @type bool
388   * @example
389   * if (browserObj.geckoVersion) do something 
390   */
391   this.geckoVersion = ( (this.isGecko) ? 
392     ua.substring( (ua.lastIndexOf('gecko/') + 6), (ua.lastIndexOf('gecko/') + 14) ) :
393 	-1 );
394   /** 
395   * @memberOf SHO.Browser
396   * @desc Checks if browser is equivalent Mozilla
397   * @type bool
398   * @example
399   * if (browserObj.isMozillaEquiv) do something 
400   */
401   this.isMozillaEquiv = ( (this.isGecko) ? 
402     parseFloat( ua.substring( ua.indexOf('rv:') + 3 ) ) : -1 );
403   // browser version
404   /** 
405   * @memberOf SHO.Browser
406   * @desc Checks browser version minor
407   * @type number
408   * @example
409   * if (browserObj.versionMinor) do something 
410   */
411   this.versionMinor = parseFloat(navigator.appVersion); 
412   // correct version number
413   if (this.isGecko && !this.isMozilla) {
414     if(this.isFirefox) {
415       this.versionMinor = parseFloat(ua.substring(ua.indexOf('firefox/')+8,ua.length));
416     } 
417     else {
418       this.versionMinor = parseFloat(ua.substring(ua.indexOf('/', ua.indexOf('gecko/')+6)+1));
419     }
420   }
421   else if (this.isMozilla) 
422     this.versionMinor = parseFloat(ua.substring( ua.indexOf('rv:') + 3 ) );
423   else if (this.isIE && this.versionMinor >= 4) 
424     this.versionMinor = parseFloat( ua.substring( ua.indexOf('msie ') + 5 ) );
425   else if(this.isSafari) 
426     this.versionMinor = parseFloat( ua.substring( ua.indexOf('safari/') + 7) );
427   else if(this.isOmniweb) 
428     this.versionMinor = parseFloat(ua.substring( ua.indexOf('omniweb/v') + 9));
429   else if(this.isOpera && !this.isMac) 
430     this.versionMinor = parseFloat(ua.substring( ua.indexOf('opera') + 6));
431      
432   /** 
433   * @memberOf SHO.Browser
434   * @desc Checks browser version major
435   * @type number
436   * @example
437   * if (browserObj.versionMajor) do something 
438   */
439   this.versionMajor = parseInt(this.versionMinor); 
440   // dom support 
441   /** 
442   * @memberOf SHO.Browser
443   * @desc Checks if browser support DOM
444   * @type bool
445   * @example
446   * if (browserObj.isDOM) do something 
447   */
448   this.isDOM = (document.getElementById && document.createElement?true:false);
449   /** 
450   * @memberOf SHO.Browser
451   * @desc Checks if browser support DOM 1
452   * @type bool
453   * @example
454   * if (browserObj.isDOM1) do something 
455   */
456   this.isDOM1 = (document.getElementById?true:false);
457   /** 
458   * @memberOf SHO.Browser
459   * @desc Checks if browser support DOM 2 Event
460   * @type bool
461   * @example
462   * if (browserObj.isDOM2Event) do something 
463   */
464   this.isDOM2Event = (document.addEventListener && 
465     document.removeEventListener?true:false);
466   // dhtml support
467   /** 
468   * @memberOf SHO.Browser
469   * @desc Checks if browser support DHTML
470   * @type bool
471   * @example
472   * if (browserObj.isDHTML) do something 
473   */
474   this.isDHTML = (document.getElementById || 
475     document.all || document.layers?true:false);
476   // css compatibility mode
477   /** 
478   * @memberOf SHO.Browser
479   * @desc Checks if browser mode is back compatible
480   * @type string
481   * @example
482   * if (browserObj.mode) do something 
483   */
484   this.mode = document.compatMode ? document.compatMode : 'BackCompat';
485   // platform
486   if(ua.indexOf('win') != -1) {
487   /** 
488   * @memberOf SHO.Browser
489   * @desc Checks if browser platform is Windows
490   * @type bool
491   * @example
492   * if (browserObj.isWin) do something 
493   */
494    this.isWin=true; 
495     this.platform="win"
496   }
497   if(this.isWin && ( ua.indexOf('95') != -1 || 
498     ua.indexOf('98') != -1 || 
499     ua.indexOf('nt') != -1 || 
500     ua.indexOf('win32') != -1 || 
501     ua.indexOf('32bit') != -1 || 
502     ua.indexOf('xp') != -1)){
503   /** 
504   * @memberOf SHO.Browser
505   * @desc Checks if browser platform is Windows 32
506   * @type bool
507   * @example
508   * if (browserObj.isWin32) do something 
509   */
510       this.isWin32=true; 
511       this.platform = "win32"
512   }
513   if(ua.indexOf('mac') != -1){
514   /** 
515   * @memberOf SHO.Browser
516   * @desc Checks if browser platform is Mac
517   * @type bool
518   * @example
519   * if (browserObj.isMac) do something 
520   */
521     this.isMac=true; 
522     this.platform = "mac"
523   }
524   if(ua.indexOf('x11') != -1){
525     this.isMac=true; 
526     this.platform = "unix"
527   }
528   if(ua.indexOf('linux') != -1){
529     this.isMac=true; 
530     this.platform = "linux"
531   }
532   // specific browser shortcuts
533   /** 
534   * @memberOf SHO.Browser
535   * @desc Checks if browser is NS6 x
536   * @type bool
537   * @example
538   * if (browserObj.isNS6x) do something 
539   */
540   this.isNS6x = (this.isNS && this.versionMajor == 6);
541   /** 
542   * @memberOf SHO.Browser
543   * @desc Checks if browser is NS6x
544   * @type bool
545   * @example
546   * if (browserObj.isNS6x) do something 
547   */
548   this.isNS6up = (this.isNS && this.versionMajor >= 6);
549   /** 
550   * @memberOf SHO.Browser
551   * @desc Checks if browser is NS7x
552   * @type bool
553   * @example
554   * if (browserObj.isNS7x) do something 
555   */
556   this.isNS7x = (this.isNS && this.versionMajor == 7);
557   /** 
558   * @memberOf SHO.Browser
559   * @desc Checks if browser is NS7 up
560   * @type bool
561   * @example
562   * if (browserObj.isNS7up) do something 
563   */
564   this.isNS7up = (this.isNS && this.versionMajor >= 7);
565   /** 
566   * @memberOf SHO.Browser
567   * @desc Checks if browser is IE5x
568   * @type bool
569   * @example
570   * if (browserObj.isIE5x) do something 
571   */
572   this.isIE5x = (this.isIE && this.versionMajor == 5);
573   /** 
574   * @memberOf SHO.Browser
575   * @desc Checks if browser is IE5.5
576   * @type bool
577   * @example
578   * if (browserObj.isIE55) do something 
579   */
580   this.isIE55 = (this.isIE && this.versionMinor == 5.5);
581   /** 
582   * @memberOf SHO.Browser
583   * @desc Checks if browser is IE5 up
584   * @type bool
585   * @example
586   * if (browserObj.isIE5up) do something 
587   */
588   this.isIE5up = (this.isIE && this.versionMajor >= 5);
589   /** 
590   * @memberOf SHO.Browser
591   * @desc Checks if browser is IE6x
592   * @type bool
593   * @example
594   * if (browserObj.isIE6x) do something 
595   */
596   this.isIE6x = (this.isIE && this.versionMajor == 6);
597   /** 
598   * @memberOf SHO.Browser
599   * @desc Checks if browser is IE6 up
600   * @type bool
601   * @example
602   * if (browserObj.isIE6up) do something 
603   */
604   this.isIE6up = (this.isIE && this.versionMajor >= 6);
605 
606  /** 
607   * @memberOf SHO.Browser
608   * @desc Checks if flash is installed
609     <br/>(0 = not installed, 1 = unknown, 2 = installed )
610   * @type number 
611   * @example
612   * if (browserObj.flashInstalled) do something 
613   */
614   this.flashInstalled = 0; 
615   /** 
616   * @memberOf SHO.Browser
617   * @desc Checks flash version
618   * @type number 
619   * @example
620   * if (browserObj.flashVersion) do something 
621   */
622   this.flashVersion = 0;      // Flash version, default 0
623   MSDetect = "false";        // MS IE detection, default false
624   if (navigator.plugins && navigator.plugins.length)  {
625     x = navigator.plugins["Shockwave Flash"];
626     if (x)  {
627       this.flashInstalled = 2;
628       if (x.description)  {
629         y = x.description;
630         this.flashVersion = y.charAt(y.indexOf('.')-1);
631       }
632     } 
633     else {
634       this.flashInstalled = 1;
635     }
636     if (navigator.plugins["Shockwave Flash 2.0"])  {
637       this.flashInstalled = 2;
638       this.flashVersion = 2;
639     }
640   } 
641   else if (navigator.mimeTypes && navigator.mimeTypes.length)  {
642     x = navigator.mimeTypes['application/x-shockwave-flash'];
643     if (x && x.enabledPlugin) {
644       this.flashInstalled = 2;
645      } 
646     else {
647       this.flashInstalled = 1;
648     }
649   } 
650   else {
651     MSDetect = "true";
652   }
653   // MS IE detect
654   if(MSDetect == "true") {
655     for(var i=9; i>0; i--){
656       this.flashVersion = 0;
657       try{
658         var flash = new ActiveXObject("ShockwaveFlash.ShockwaveFlash." + i);
659         this.flashVersion = i;
660         this.flashInstalled = 2;
661         break;
662       }
663       catch(e){
664       }
665     }
666   }
667   browser_info["browser_flash_installed"] = this.flashInstalled;
668   browser_info["browser_flash_version"] = this.flashVersion;
669   // Browser compliancy      
670   browser_info["browser_name"] = this.name;
671   browser_info["browser_version"] = this.versionMinor;
672   browser_info["browser_platform"] = this.platform;
673   browser_info["browser_dhtml"] = this.isDHTML;
674   browser_info["browser_dom"] = this.isDOM;
675   // Current browser supported
676   browser_support = new Array();
677   // Supported browsers  / == if equal
678   browser_support["1"] = [
679     ["win32","Internet Explorer",5.5],
680     ["win32","Internet Explorer",6],
681     ["win32","Netscape",6.2],
682     ["win32","Netscape",7],
683     ["win32","FireFox",1.0],
684     ["mac","Internet Explorer",5.23],
685     ["mac","Netscape",6.2],
686     ["mac","Netscape",7],
687     ["mac","Netscape",7.1]
688   ];                  
689   // Best-practise browsers  / => if equal or higher
690   browser_support["2"] = [
691     ["win32","Internet Explorer",5],
692     ["win32","Mozilla",1.6],
693     ["win32","Opera",7.54],
694     ["win32","Firefox",0.9],
695     ["mac","Internet Explorer",5],
696     ["mac","Firefox",0.9],
697     ["mac","Safari",1.2],
698     ["mac","Opera",7.54]
699   ];
700   var intBrowserSupported = 3; // Default not supported (1/2/3)
701   var fltMinBrowserVersion = parseFloat(this.versionMinor);
702   intBreak = false;
703   /*
704   for(id in browser_support) {
705     if(intBreak == false) {
706       for(intBrowser=0;intBrowser<=(browser_support[id].length-1);intBrowser++) {
707 		alert(browser_support[id][intBrowser][0]);
708         strBrowserPlatform = browser_support[id][intBrowser][0];
709         strBrowserName = browser_support[id][intBrowser][1];
710         fltBrowserVersion = parseFloat(browser_support[id][intBrowser][2]);
711         // Match platform and browser name
712         if((strBrowserName.toLowerCase() == this.name.toLowerCase()) && 
713           (strBrowserPlatform == this.platform)) { 
714           switch (id){
715           case "1": 
716             // Equal same version 
717             if( fltMinBrowserVersion == fltBrowserVersion) {
718               intBrowserSupported = id; 
719               intBreak = true
720             }; 
721             break;
722           case "2":
723             // Equal or higher version
724             if( fltMinBrowserVersion >= fltBrowserVersion) {
725               intBrowserSupported = id; 
726 			  intBreak = true
727             }; 
728             break;
729           }
730         }
731       }
732     }  
733   }
734   */
735   browser_info["browser_supported"] = intBrowserSupported;
736   
737   /** 
738   * @memberOf SHO.Browser
739   * @desc Returns available screen width
740   * @type number 
741   * @example
742   * alert(browserObj.availWidth)
743   */
744   this.availWidth = null;
745   if( typeof(self.innerWidth)!="undefined" ){ 
746     this.availWidth = self.innerWidth; 
747   }
748   else if( document.documentElement && 
749     document.documentElement.clientWidth ){ 
750       this.availWidth = document.documentElement.clientWidth; 
751   }
752   else if ( document.body ){ 
753 	this.availWidth = document.body.clientWidth; 
754   }
755 
756   /** 
757   * @memberOf SHO.Browser
758   * @desc Returns available screen height
759   * @type number 
760   * @example
761   * alert(browserObj.availHeight)
762   */
763   // 
764   this.availHeight = null;
765   if( typeof(self.innerHeight)!="undefined" ){ 
766     this.availHeight = self.innerHeight; 
767   }
768   else if( document.documentElement && 
769     document.documentElement.clientHeight ){ 
770       this.availHeight = document.documentElement.clientHeight; 
771   }
772   else if ( document.body ){ 
773     this.availHeight = document.body.clientHeight; 
774   }
775 
776   /** 
777   * @memberOf SHO.Browser
778   * @desc Returns top positon in scrolled browser window
779   * @type number 
780   * @example
781   * alert(browserObj.scrollTop)
782   */
783   this.scrollTop = null;
784   if( typeof(self.pageYOffset)!="undefined" ){ 
785     this.scrollTop = self.pageYOffset; 
786   }
787   else if( document.documentElement && 
788     document.documentElement.scrollTop ) { 
789       this.scrollTop = document.documentElement.scrollTop; 
790   }
791   else if( document.body ) { 
792     this.scrollTop = document.body.scrollTop; 
793   }
794  
795   
796 };
797 
798 
799 /********************************************************************************
800  ***** CONFIG_FUNCTIONS *********************************************************/
801 
802 /** @constructor
803   * @desc Configuration functions
804   * @example
805   * var confObj = new SHO.Config();
806  */
807 SHO.Config = function () {
808 	
809   _SHO.isloaded.Config = true;
810 /** @type const 
811   * @desc Path to the root folder */
812   this.PATH_ROOT      = get_root_path();                                          
813 
814 /** @type const 
815   * @desc Default value = "stylesheets" */
816   this.PATH_CSS       = this.PATH_ROOT + "/" + _SHO.dirnames.STYLESHEET;
817 /** @type const 
818   * @desc Default value = "stylesheets/pages" */
819   this.PATH_CSS_AUTO  = this.PATH_CSS + "/" + _SHO.dirnames.STYLESHEET_AUTO;
820 /** @type const 
821   * @desc Default value = "stylesheets/patches" */
822   this.PATH_CSS_PATCH = this.PATH_CSS + "/" + _SHO.dirnames.STYLESHEET_PATCHES;
823 /** @type const 
824   * @desc Default value = "stylesheets/apps" */
825   this.PATH_CSS_APPS  = this.PATH_CSS + "/" + _SHO.dirnames.STYLESHEET_APPS;
826 /** @type const 
827   * @desc Default value = "stylesheets/apps" */
828   this.PATH_CSS_ALTER  = this.PATH_CSS + "/" + _SHO.dirnames.STYLESHEET_ALTER;
829 
830 /** @type const 
831   * @desc Default value = "javascripts" */
832   this.PATH_JS        = this.PATH_ROOT + "/" + _SHO.dirnames.JAVASCRIPT; 
833 /** @type const 
834   * @desc Default value = "javascripts/lib" */
835   this.PATH_JS_LIB    = this.PATH_JS + "/" + _SHO.dirnames.JAVASCRIPT_LIB;
836 /** @type const 
837   * @desc Default value = "javascripts/dev" */
838   this.PATH_JS_DEV    = this.PATH_JS + "/" + _SHO.dirnames.JAVASCRIPT_DEV;
839 /** @type const 
840   * @desc Default value = "javascripts/apps" */
841   this.PATH_JS_APPS   = this.PATH_JS + "/" + _SHO.dirnames.JAVASCRIPT_APPS;
842 
843 /** @type const 
844   * @desc Default value = "images" */
845   this.PATH_IMG   = this.PATH_ROOT + "/" + _SHO.dirnames.IMAGES;
846 
847 
848 /** @type const 
849   * @desc Default value = "conf" */
850   this.PATH_CONF   = this.PATH_ROOT + "/" + _SHO.dirnames.CONF;
851 /* END PATH SHORTCUTS */ 
852 
853 /** @type const */
854   this.NAME_FILE_SELF               = "shoogar.js";
855 
856 }
857 
858 
859 /********************************************************************************
860  ***** COOKIE_FUNCTIONS *********************************************************/
861 
862 /** 
863  * @constructor
864  * @desc Cookie functions
865  * @example
866  * var cookieObj = new SHO.Cookie();
867 */
868 SHO.Cookie = function(){
869 
870   _SHO.isloaded.Cookie = true;
871 
872   /** 
873   * @memberOf SHO.Cookie
874   * @desc Function to create cookie
875   * @param {string} name Name of the cookie 
876   * @param {string} value Value of the cookie 
877   * @param {string} days Number of days until expires
878   * @example
879   * cookieObj.create('font-size','12px','100');
880   */
881   this.create = function( name, value, days) {
882     if (days) {
883       var date = new Date();
884       date.setTime(date.getTime()+(days*24*60*60*1000));
885       var expires = "; expires="+date.toGMTString();
886     } 
887     else { 
888       var expires = "";
889     }  
890     document.cookie = name+"="+value+expires+"; path=/";
891   };
892  
893  /** 
894   * @memberOf SHO.Cookie
895   * @desc Function to read cookie
896   * @param {string} name Name of the cookie 
897   * @example
898   * alert(cookieObj.read('font-size'))
899   */
900   this.read = function( name ) {
901     var nameEQ = name + "=";
902     var ca = document.cookie.split(';');
903     for(var i=0;i < ca.length;i++)  {
904       var c = ca[i];
905       while (c.charAt(0)==' ') {
906         // Remove spaces in front of cookie name
907         c = c.substring(1,c.length);
908 	  }
909       if (c.indexOf(nameEQ) == 0) {
910         return c.substring(nameEQ.length,c.length);
911 	  }
912     }
913     return null;
914   };
915  
916  /** 
917   * @memberOf SHO.Cookie
918   * @desc Function to erase cookie
919   * @param {string} name Name of the cookie 
920   * @example
921   * cookieObj.erase()
922   */
923   this.erase = function( name ) {
924     this.create( name, "", -1 );
925   };
926 };
927 
928 
929 /********************************************************************************
930  ***** DEBUG_FUNCTIONS **********************************************************/
931 
932 /** 
933   * @constructor 
934   * @desc Object with informations about shoogar.js
935     and stores all data in an object for later use. 
936   * @example
937   * var debugObj = new SHO.Debug();
938 */
939 
940 SHO.Debug = function () {
941   _SHO.isloaded.Debug = true;
942 
943 /** 
944   * @memberOf SHO.Debug
945   * @desc Version number
946   * @type string
947   * @example
948   * var version = debugObj.version;
949   */
950   this.version = _SHO.metadata.version;
951   /** 
952   * @memberOf SHO.Debug
953   * @desc Date of the last modification
954   * @type string
955   * @example
956   * var lastMod = Debug.lastmod;
957   */
958   this.lastmod = _SHO.metadata.lastmod; 
959   /** 
960   * @memberOf SHO.Debug
961   * @desc Author mail for contact
962   * @type string
963   * @example
964   * var author = Debug.author;
965   */
966   this.contact = _SHO.metadata.contact;
967   /** 
968   * @memberOf SHO.Debug
969   * @desc Link to the script archive
970   * @type string
971   * @example
972   * var scriptLink = Debug.UrlScript;
973   */
974   this.urlscript = _SHO.metadata.urlscript;
975   /** 
976   * @memberOf SHO.Debug
977   * @desc Link to the script documentation (this file)
978   * @type string
979   * @example
980   * var docLink = Debug.UrlDoc;
981   */
982   this.urldoc = _SHO.metadata.urldoc;
983   
984   /** 
985   * @memberOf SHO.Debug
986   * @desc Returns all browser informations in a formated string 
987   * @example
988   * alert(Debug.showBrowserInfo());
989   */
990   this.showBrowserInfo = function() {
991 	requireClass('Browser');
992     var bi = '';
993     bi += "[Browser info]";
994     bi += "\n\n";
995     for(id in browser_info) {
996 	  if(typeof(browser_info[id]) != 'function'){
997         bi += id +": ";
998         bi += browser_info[id];
999         bi += "\n";
1000 	  }
1001     }
1002 	return(bi);
1003   };
1004   this.oHead = document.getElementsByTagName('head')[0];
1005   this.oScript = document.getElementsByTagName('script');
1006   this.oLink = document.getElementsByTagName('link');
1007   this.oStyle = document.getElementsByTagName('style');
1008   this.scriptArr = new Array();
1009   this.styleArrInt = new Array();
1010   this.styleArrExt = new Array();
1011   /** 
1012     * @private
1013     * @memberOf SHO.Debug
1014     * @desc Show all internal styles 
1015     * @example
1016     * debugObj.showStylesInt();
1017   */
1018   this.showStylesInt = function() {
1019     for( var i = 0; i < this.oStyle.length; i++ ) {
1020       // Oops! Firefox put all styles from body to head
1021       // this.str+= (i+1) + ". [" + this.oStyle[i].parentNode.nodeName + "]\n";
1022       this.styleArrInt[i] = this.oStyle[i].innerHTML.trim();
1023     }
1024     return this.styleArrInt;
1025   };
1026   /** 
1027     * @private
1028     * @memberOf SHO.Debug
1029     * @desc Show all CSS files
1030     * @example
1031     * debugObj.showStylesExt();
1032   */
1033   this.showStylesExt = function() {
1034     for( var i = 0; i < this.oLink.length; i++ ) {
1035 		var sc = this.oLink[i].href.replace(sho.config.PATH_ROOT+'/', '');
1036 		if (i+1 < 10 ) num = ' ' + (i+1) + '. ';
1037 		else num = (i+1) + '. ';
1038 		try {
1039 			var url = this.oLink[i].href;
1040             var http = sho.ajax.simpleRequest(url);
1041             if (sc != '') this.styleArrExt[i]= num + sc;
1042 		}
1043 		catch(err) {
1044             if (sc != '') {
1045 				var errMsg = ' <span style="color:red">[error]</span>';
1046 				this.styleArrExt[i] = num + sc + errMsg;
1047 			}
1048 		}
1049     }
1050     return this.styleArrExt;
1051   };
1052   /** 
1053     * @private
1054     * @memberOf SHO.Debug
1055     * @desc Show all javascript included files per alert() function
1056     * @example
1057     * debugObj.showScripts();
1058    */
1059   this.showScripts = function() {
1060     for( var i = 0; i < this.oScript.length; i++ ) {
1061       var sc = this.oScript[i].src.replace(sho.config.PATH_ROOT+'/', '');
1062       if (i+1 < 10 ) num = ' ' + (i+1) + '. ';
1063       else num = (i+1) + '. ';
1064       try {
1065         var url = this.oScript[i].src;
1066         var http = sho.ajax.simpleRequest(url);
1067         if (sc != '') 
1068           this.scriptArr[i]= num + sc;
1069         else 
1070           this.scriptArr[i]= num + 'Inline Style';
1071       }
1072       catch(err) {
1073         if (sc != '') {
1074           var errMsg = ' <span style="color:red">[error]</span>';
1075           this.scriptArr[i]= num + sc + errMsg;
1076         }
1077         else {
1078           //alert(escape(this.oScript[i].text).replace(/\./g, '[dot]'));
1079           this.scriptArr[i]= num + 'Inline Style';
1080         }
1081       }
1082     }
1083     return this.scriptArr;
1084   };
1085   /** 
1086     * @memberOf SHO.Debug
1087     * @desc Show documentation
1088     * @example
1089     * debugObj.showDocs();
1090    */
1091   this.showDocs = function() {
1092     var popup, params = "";
1093 	params+= "scrollbars=yes, resizable=yes, menubar=no, toolbar=no, ";
1094 	params+= "location=no, directories=no, status=no, ";
1095 	params+= "width=" + screen.width + ", ";
1096 	params+= "height=" + screen.height + ", "; 
1097 	params+= "screenX=0, screenY=0, top=0, left=0";
1098 	popup = window.open( this.urldoc, "doc", params );
1099 	popup.focus();
1100   };
1101   /** 
1102     * @memberOf SHO.Debug
1103     * @desc Simple benchmark test function
1104     * @param {function} func Function 
1105     * @param {number} times Title of alternate stylesheet
1106     * @param {array} args Arguments
1107 	* @example
1108     * debugObj.benchmark(test, 1000000, [1,2,3]);
1109    */
1110   this.benchmark = function(func, times, args){
1111     var start = new Date();
1112     var iteration;
1113     for (iteration=0; iteration<times; iteration++) {
1114       if (args) {
1115         var result = func.apply(func, args);
1116       } 
1117       else {
1118         var result = func.apply(func);
1119       }
1120     }
1121     var end = new Date();
1122     var msg = "SIMPLE BENCHMARK TEST\n"; 
1123     msg    += "-----------------------------------------------------------------\n"; 
1124     msg    += "RESULT: " + (end-start) + " millisec\n"; 
1125     msg    += "-----------------------------------------------------------------\n"; 
1126     msg    += "ITERATIONS: " + times  + "\n"; 
1127     msg    += "-----------------------------------------------------------------\n"; 
1128     msg    += func; 
1129     alert(msg);
1130     return result;
1131   }
1132 };
1133 
1134 
1135 
1136 /********************************************************************************
1137  ***** ELEMENT_FUNCTIONS *********************************************************/
1138 
1139 /** @constructor
1140   * @desc Element functions
1141   * @example
1142   * var elemObj = new SHO.Element();
1143  */
1144 SHO.Element = function () {
1145 
1146   /** 
1147     * @memberOf SHO.Element
1148     * @inspired by Peter-Paul Koch (QuirksMode.org)
1149     * @desc Add Drag and Drop function to an element
1150     * @param {string} Id Element id
1151     * @example
1152     * elemObj.setDraggable('IdOfMyElement')
1153    */
1154   this.setDraggable = function(id) {
1155     // Peter-Paul Koch / QuirksMode.org
1156     var dragDrop = new Object();
1157     dragDrop = {
1158       initialMouseX: undefined,
1159       initialMouseY: undefined,
1160       startX: undefined,
1161       startY: undefined,
1162       dragObj: undefined,
1163       initElement: function (element) {
1164         element = document.getElementById(element);
1165         element.onmousedown = dragDrop.startDragMouse;
1166       },
1167      /** @private */
1168      startDragMouse: function (e) {
1169         dragDrop.startDrag(this);
1170         var evt = e || window.event;
1171         dragDrop.initialMouseX = evt.clientX;
1172         dragDrop.initialMouseY = evt.clientY;
1173         sho.event.add(document,'mousemove',dragDrop.dragMouse);
1174         sho.event.add(document,'mouseup',dragDrop.releaseElement);
1175         return false;
1176       },
1177      /** @private */
1178       startDrag: function (obj) {
1179         if (dragDrop.dragObj) dragDrop.releaseElement();
1180         dragDrop.startX = obj.offsetLeft;
1181         dragDrop.startY = obj.offsetTop;
1182         dragDrop.dragObj = obj;
1183         obj.className += ' dragged';
1184       },
1185      /** @private */
1186       dragMouse: function (e) {
1187         var evt = e || window.event;
1188         var dX = evt.clientX - dragDrop.initialMouseX;
1189         var dY = evt.clientY - dragDrop.initialMouseY;
1190         dragDrop.setPosition(dX,dY);
1191         return false;
1192       },
1193      /** @private */
1194       setPosition: function (dx,dy) {
1195         dragDrop.dragObj.style.left = dragDrop.startX + dx + 'px';
1196         dragDrop.dragObj.style.top = dragDrop.startY + dy + 'px';
1197       },
1198      /** @private */
1199       releaseElement: function() {
1200         sho.event.remove(document,'mousemove',dragDrop.dragMouse);
1201         sho.event.remove(document,'mouseup',dragDrop.releaseElement);
1202         dragDrop.dragObj.className = dragDrop.dragObj.className.replace(/dragged/,'');
1203         dragDrop.dragObj = null;
1204       }
1205     };
1206     dragDrop.initElement(id);
1207   };
1208   
1209   /** 
1210     * @memberOf SHO.Element
1211     * @desc Append an element to the BODY
1212     * @param {string} tagname New HTML element
1213     * @param {string} id New element id
1214     * @param {string} content New element content
1215     * @example
1216     * elemObj.appendToBody('div', 'myId', '<b>Hello!</b>');
1217    */
1218   this.appendToBody = function(tagname, id, content) {
1219     var newElement = document.createElement(tagname);
1220     newElement.id = id;
1221     if(content != '') newElement.innerHTML = content;
1222     var body = document.getElementsByTagName('body')[0];
1223     body.appendChild(newElement);
1224   };
1225   /** 
1226     * @memberOf SHO.Element
1227     * @desc Append an element to an existig Element by id
1228     * @param {string} id1 Target id
1229     * @param {string} tagname New HTML element
1230     * @param {string} id2 New element id
1231     * @param {string} content New element content
1232     * @example
1233     * elemObj.appendToElementById('myId1', 'div', 'myId2', '<b>Hello!</b>');
1234    */
1235   this.appendToElementById = function(id1, tagname, id2, content) {
1236     var newElement = document.createElement(tagname);
1237     newElement.id = id2;
1238     if(content != '') newElement.innerHTML = content;
1239     var oldElement = document.getElementById(id1);
1240     oldElement.appendChild(newElement);
1241   };
1242   /** 
1243     * @memberOf SHO.Element
1244     * @desc Remove an element
1245     * @param {string} id Element id
1246     * @example
1247     * elemObj.remove('IdOfMyElement');
1248    */
1249   this.remove = function(id) {
1250     var body = document.getElementsByTagName('body')[0];
1251     body.removeChild(document.getElementById(id));
1252   };
1253 }
1254 
1255 /********************************************************************************
1256  ***** EVENT_FUNCTIONS *********************************************************/
1257 
1258 /** @constructor
1259   * @desc Event functions
1260   * @example
1261   * var eventObj = new SHO.Event();
1262  */
1263 SHO.Event = function () {
1264 
1265   /** 
1266     * @memberOf SHO.Event
1267     * @desc Add an event
1268     * @inspired by Peter-Paul Koch (QuirksMode.org)
1269     * @param {string} obj Object (window, document , ..)
1270     * @param {string} evt Event (keypress, mouseover,..)
1271     * @param {string} fn Function name
1272     * @example
1273 	* eventObj.add(document, 'keypress', myKeypressFunction);
1274    */
1275   this.add = function( obj, evt, fn ) {
1276     if (obj.addEventListener) obj.addEventListener( evt, fn, false);
1277     else if (obj.attachEvent) obj.attachEvent( 'on'+evt, fn);
1278   };
1279   /** 
1280     * @memberOf SHO.Event
1281     * @desc Remove an event
1282     * @inspired by Peter-Paul Koch (QuirksMode.org)
1283     * @param {string} obj Object (window, document , ..)
1284     * @param {string} evt Event (keypress, mouseover,..)
1285     * @param {string} fn Function name
1286     * @example
1287 	* eventObj.remove(document, 'keypress', myKeypressFunction);
1288    */
1289   this.remove = function( obj, evt, fn ) {
1290     if (obj.removeEventListener) obj.removeEventListener(evt,fn,false);
1291     else if (obj.detachEvent) obj.detachEvent('on'+evt,fn);
1292   }
1293 
1294   /**
1295    * @memberOf SHO.Event
1296    * @desc Ensure the synchronous of data
1297    * @inspiredBy Kang-min Liu (gugod.org) JSAN.Wait
1298    * @example 
1299    * eventObj.sync(start, callback, max_wait)
1300    * eventObj.sync(start, callback, failure_callback, max_wait)
1301   */
1302   this.sync = function() {
1303     if ( typeof arguments[0] == 'function'
1304       && typeof arguments[1] == 'function'
1305       && typeof arguments[2] == 'function' ) {
1306       this.syncFailureCb(
1307 	    arguments[0], arguments[1], arguments[2], arguments[3]
1308 	  );
1309     }
1310     if ( typeof arguments[0] == 'function'
1311       && typeof arguments[1] == 'function'  ) {
1312       this.syncNoFailureCb(
1313 	    arguments[0], arguments[1], arguments[2]
1314 	  );
1315     }
1316   };
1317   /** 
1318     * @private
1319   */
1320   this.syncNoFailureCb = function(test, callback, max) {
1321     this.syncFailureCb(test, callback, function(){}, max);
1322   };
1323   /** 
1324     * @private
1325   */
1326   this.syncFailureCb = function(test, callback, failed_callback, max) {
1327     var func = function() {
1328       var interval = 100;
1329       var timer = 0;
1330       var intervalId;
1331       var check = function () {
1332          if ( test() ) {
1333            callback();
1334            clearInterval(intervalId);
1335          }
1336          timer += interval;
1337          if ( typeof max == 'number' ) {
1338             if ( timer >= max ) {
1339               if ( typeof failed_callback == 'function') {
1340                 failed_callback();
1341                 clearInterval(intervalId);
1342 			  }
1343             }
1344          }
1345       }
1346       intervalId = setInterval(check, interval);
1347     }
1348     func();
1349   }
1350   /**
1351    * @memberOf SHO.Event
1352    * @desc Disable selecting text elements (without input and textarea)
1353    * @example 
1354    * eventObj.disableSelecting()
1355   */
1356   this.disableSelecting = function() {
1357     /** 
1358       * @private
1359     */
1360     this.enable = function(e) {
1361       this.e = e ? e : window.event;
1362       if (this.e.button != 1) {
1363         if (this.e.target) {
1364           var target = this.e.target;
1365         } 
1366 		else if (this.e.srcElement) {
1367           var target = this.e.srcElement;
1368         }
1369         var tagName = target.tagName.toLowerCase();
1370         if ((tagName != "input") && (tagName != "textarea")) {
1371           return false;
1372         }
1373       }
1374     };
1375   /** 
1376     * @private
1377   */
1378     this.disable = function () {
1379       return true;
1380     };  
1381     if (typeof(document.onselectstart) != "undefined") {
1382       document.onselectstart = this.enable;
1383     } 
1384     else {
1385       document.onmousedown = this.enable;
1386       document.onmouseup = this.disable;
1387     };
1388   };
1389   /**
1390    * @desc       Disable Selecting Elements
1391    * @example 
1392    * eventObj.disableContextMenu()
1393   */
1394   this.disableContextMenu = function() {
1395     document.oncontextmenu=function(){
1396       return false;
1397     };
1398   }
1399 }
1400 
1401 
1402 
1403 
1404 /********************************************************************************
1405  ***** SCRIPT_FUNCTIONS *********************************************************/
1406 
1407 /** @constructor
1408   * @desc Script functions
1409   * @example
1410   * var scriptObj = new SHO.Script();
1411  */
1412 SHO.Script = function () {
1413   
1414   _SHO.isloaded.Script = true;
1415 
1416   this.oHead = document.getElementsByTagName('head').item(0);
1417   this.oScript = document.getElementsByTagName('script');
1418   this.oScript_new = document.createElement('script');
1419   /** 
1420     * @memberOf SHO.Script
1421     * @desc Append a javascript file (appendChild version) 
1422     * @param {string} filepath File path. 
1423     * @example
1424     * scriptObj.appendFile(PATH_JS + '/newscript.js');
1425    */
1426   this.appendFile = function( filepath ) {
1427 	this.oScript_new.src = filepath;
1428     this.oScript_new.type = 'text/javascript';
1429     //this.oScript_new.defer = 'defer';
1430 	//this.oScript_new.onload = function(){return true};
1431     this.oHead.appendChild(this.oScript_new);  
1432   };
1433   /** 
1434     * @memberOf SHO.Script
1435     * @desc Insert an empty script BEFORE page load 
1436     * @param {string} filepath File path. 
1437     * @example
1438     * scriptObj.addEmpty();
1439    */
1440   this.addEmpty = function() {
1441     this.script = "<scri"+"pt language='JavaScript' type='text/javascript'";
1442     this.script+= " id='emptyScript'></scr"+"ipt>";
1443     document.write( this.script );
1444   };
1445   /** 
1446     * @memberOf SHO.Script
1447     * @desc Load a javascript file AFTER page load -> usage of addEmpty()
1448     * @param {string} filepath File path. 
1449     * @example
1450     * scriptObj.loadFile(path/to/newscript.js');
1451    */
1452   this.loadFile = function( filepath ) {
1453     document.getElementById('emptyScript').src = filepath;
1454   };
1455   /** 
1456   * @memberOf SHO.Script
1457   * @desc Add a javascript file (document.write version) <br/>NOTE: Usage only before load!
1458   * @param {string} filepath File path
1459   * @example
1460   * scriptObj.addFile(PATH_JS_APPS + '/quiz.js');
1461   */
1462   this.addFile = function( filepath ) {
1463     this.script = "<scri"+"pt language='JavaScript' type='text/javascript'";
1464     this.script+= " src='" + filepath + "'></scr"+"ipt>";
1465     document.write( this.script );
1466   };
1467 /** 
1468   * @memberOf SHO.Script
1469   * @desc Load the javascript lib files 
1470   * @example
1471   * scriptObj.useLib();
1472  */ 
1473   this.useLib = function () {
1474 	for (var i = 0; i < arguments.length; i++) {
1475 		if(arguments[i].match('scriptaculous')) {
1476 			this.appendFile(sho.config.PATH_JS_LIB +  '/' + arguments[i] + '.js');
1477 		}
1478 		else {
1479 			this.addFile(sho.config.PATH_JS_LIB +  '/' + arguments[i] + '.js');
1480 		}
1481 		/*
1482 		this.oHead = document.getElementsByTagName('head')[0];
1483 		this.oScript_new = document.createElement('script');
1484 		this.oScript_new.src = sho.config.PATH_JS_LIB +  '/' + arguments[i] + '.js';
1485 		this.oScript_new.type = 'text/javascript';
1486 		this.oScript_new.defer = 'defer';
1487 		this.oHead.appendChild(this.oScript_new);
1488 		*/
1489 	}
1490   }
1491   
1492 }
1493 
1494 
1495 /********************************************************************************
1496  ***** STYLE_FUNCTIONS **********************************************************/
1497 
1498 /** @constructor
1499   * @desc Stylesheet function 
1500   * @example
1501   * var styleObj = new SHO.Style();
1502  */
1503 SHO.Style = function() {
1504 
1505   _SHO.isloaded.Style = true;
1506  
1507   this.oHead = document.getElementsByTagName('head')[0];
1508   this.oLink = document.getElementsByTagName('link');
1509   this.oStyle = document.getElementsByTagName('style');
1510   this.oStyle_new = document.createElement("style");
1511   this.styles = [];
1512   this.rules = [];
1513   this.ruleIndex = [];
1514   if (document.createStyleSheet)
1515     this.sheet = document.createStyleSheet();
1516   else {
1517     this.styleElement = document.createElement("style");
1518     document.getElementsByTagName("head")[0].appendChild(this.styleElement);
1519     this.sheet = this.styleElement.styleSheet ? 
1520       this.styleElement.styleSheet : this.styleElement.sheet;
1521   }
1522   /** 
1523     * @memberOf SHO.Style
1524     * @desc Enable alternate stylesheet
1525     * @param {string} styleTitle Title of alternate stylesheet
1526     * @example
1527     * styleObj.enableAlternateFile('alternateStyleTitle');
1528     * styleObj.enableAlternateFile('');
1529   */
1530   this.enableAlternateFile = function(styleTitle) {
1531     this.found = false;
1532     this.getStyles();
1533     for (var i in this.styles) {
1534       if (this.styles[i].title == styleTitle) {
1535         for (var j in this.styles) {
1536           if (this.styles[i].rel == "alternate stylesheet") this.styles[j].disabled = true;
1537         }
1538         this.styles[i].disabled = false;
1539         this.found = true;
1540         break;
1541       }
1542     }
1543     if(  this.found == false){
1544       for (var j in this.styles) {
1545         if (this.styles[i].rel == "alternate stylesheet") this.styles[j].disabled = true;
1546       }
1547     }
1548   };
1549   /** 
1550     * @memberOf SHO.Style
1551     * @desc Disable all alternate stylesheets
1552     * @example
1553     * styleObj.disableAlternates();
1554   */
1555   this.disableAlternates = function() {
1556     this.getStyles();
1557     for (var i in this.styles) {
1558       if (this.styles[i].rel != "stylesheet") {
1559         for (var j in this.styles) {
1560           this.styles[j].disabled = true;
1561         }
1562       }
1563     }
1564   };
1565   /** 
1566     * @memberOf SHO.Style
1567     * @desc Add a CSS file
1568     * @param {string} css Stylesheet name 
1569     * @param {string} id (otional)
1570     * @example
1571     * styleObj.addFile(PATH_CSS + '/xtra.css');
1572   */
1573   this.addFile = function(href, id, title, rel, disabled) {
1574     this.href = href;
1575     if(id) this.id = id;
1576     else this.id = "";
1577     if(title) this.title = title;
1578     else this.title = "";
1579     if(rel) this.rel = rel;
1580     else this.rel = "stylesheet";
1581     if(disabled) this.disabled = disabled;
1582     else this.disabled = false;
1583 
1584     if(document.createStyleSheet){
1585       // Create new stylesheet
1586       this.styleSheet = document.createStyleSheet(this.href);
1587       this.styleSheet.title = this.title;
1588 	  this.styleSheet.rel = this.rel;
1589 	  if(this.disabled == true)
1590         this.styleSheet.disabled = true;
1591       else {
1592 	    this.styleSheet.disabled = false; // Make sure the browser enables the stylesheet
1593 	  }
1594     } 
1595     else {          
1596       // Add new link object to header
1597       this.ref = document.createElement('link');
1598       this.ref.id = this.id;
1599       this.ref.title = this.title;
1600       this.ref.rel = this.rel;
1601 	  this.ref.type = "text/css";
1602       //this.ref.href = escape(this.href);
1603       this.ref.href = this.href;
1604       if (this.oHead){
1605           var objCSS = this.oHead.appendChild(this.ref);    
1606       }
1607 	  this.ref.disabled = false; // Make sure the browser enables the stylesheet
1608     }
1609   };
1610   /** 
1611     * @memberOf SHO.Style
1612     * @desc Remove a CSS file
1613     * @param {string} css Stylesheet name 
1614     * @example
1615     * styleObj.removeFile('xtra.css');
1616   */
1617   this.removeFile = function(css) {
1618     this.notfound = false;
1619     
1620     for( var i = 0; i < this.oLink.length; i++ ) {
1621         if(this.oLink[i].href.match(css)){
1622         this.oLink[i].removeAttribute("href")
1623         this.oHead.removeChild(this.oLink[i]);
1624         this.notfound = true;
1625       }
1626     }
1627     if(this.notfound == false) 
1628       alert(css + ' wurde nicht gefunden!');
1629   };
1630 
1631   /**
1632     * @memberOf SHO.Style
1633     * @desc Create a (crossbrowser) style rule
1634     * @param {string} selectorText The CSS selector text.
1635     * @param {string} ruleText The style specification with or without braces.
1636     * @example
1637     * styleObj.addRule("#myElement", "top:30px");
1638   */
1639   this.addRule = function(selectorText, ruleText) {
1640     var result;
1641     // Opera, and other browsers with no DOM stylesheet support
1642     if (!this.sheet) {
1643       // Remove braces.
1644       ruleText = ruleText.replace(/^\{?([^\}])/, "$1");
1645       // If it exists, modify it.
1646       if (!this.ruleIndex[selectorText])
1647         this.ruleIndex[selectorText] = this.rules.length;
1648       this.rules[this.ruleIndex[selectorText]] = ruleText;
1649       // Build the innerHTML of the <style> element from our rules.
1650       var cssText = "";
1651       for (var sel in this.ruleIndex)
1652         cssText = sel + " {" + this.rules[this.ruleIndex[sel]] + "}";
1653       this.styleElement.innerHTML = cssText;
1654     }
1655     // IE: Each rule object has a style property which 
1656     // contains the style attributes.
1657     else if (this.sheet.addRule) {
1658       // addRule() requires no braces
1659       ruleText = ruleText.replace(/^\{?([^\}])/, "$1");
1660       var r = this.sheet.rules.length;
1661       this.sheet.addRule(selectorText, ruleText);
1662       result = this.sheet.rules[r];
1663       this.ruleIndex[selectorText] = r;
1664       if (this.rules.length == 0)
1665       this.rules = this.sheet.rules;
1666     }
1667     // DOM standard. Result object contains looks like 
1668     // {cssText:selectorText + " " + ruleText}
1669     // cssText property is readonly. deleteRule(ruleIndex} 
1670     // must be used to remove.
1671     else if (this.sheet.insertRule) {
1672       // insertRule() requires braces
1673       if (!/^\{[^\}]*\}$/.test(ruleText))
1674         ruleText = "{" + ruleText + "}";
1675       var r = this.sheet.cssRules.length;
1676       this.sheet.insertRule(selectorText + " " + ruleText, r);
1677       result = this.sheet.cssRules[r];
1678       this.ruleIndex[selectorText] = r;
1679       if (this.rules.length == 0)
1680       this.rules = this.sheet.cssRules;
1681     }
1682     else {
1683       alert("Cannot create rule");
1684     }
1685     return result;
1686   };
1687   /** 
1688     * @memberOf SHO.Style
1689     * @param {string} elementId id of an element 
1690     * @param {string} className class name of an element 
1691     * @desc Add a class on an element by ID 
1692     * @example
1693     * styleObj.addClassById("sheet", "style2");
1694   */
1695   this.addClassById = function( elementId, className ) {
1696     var _elementId = document.getElementById( elementId );
1697     if(sho.browser.isIE){
1698       _elementId.setAttribute("className", className);
1699     } 
1700     else {
1701       _elementId.setAttribute("class", className);
1702     }
1703   };
1704   /** 
1705     * @memberOf SHO.Style
1706     * @param {string} elementId id of an element 
1707     * @param {string} strCssRule CSS rule of an element 
1708     * @desc Get the CSS rule of an element by ID 
1709     * @example
1710     * styleObj.getStyleById('sheet', 'background-color');
1711   */
1712   this.getStyleById = function( elementId, strCssRule ) {
1713     var strValue = "";
1714     var _elementId = document.getElementById( elementId );
1715     if(document.defaultView && document.defaultView.getComputedStyle){
1716       var computedStyle = document.defaultView.getComputedStyle(_elementId, "");
1717       strValue = computedStyle.getPropertyValue(strCssRule);
1718     }
1719     else if(_elementId.currentStyle){
1720       strCssRule = strCssRule.replace(/\-(\w)/g, function (strMatch, p1){
1721         return p1.toUpperCase();
1722       });
1723       strValue = _elementId.currentStyle[strCssRule];
1724     }
1725     return strValue;
1726   };
1727   /** 
1728     * @memberOf SHO.Style
1729     * @desc Get an Elements by class name
1730     * @param {string} className class name
1731     * @param {string} tag tag name
1732     * @param {string} elm (optional, default: document)
1733     * @example
1734     * var arrayOfElements = styleObj.getElementsByClassName();
1735   */
1736   this.getElementsByClassName = function (className, tag, elm) {
1737     var testClass = new RegExp("(^|\\\\s)" + className + "(\\\\s|$)");
1738     var tag = tag || "*";
1739     var elm = elm || document;
1740     var elements = (tag == "*" && elm.all)? elm.all : elm.getElementsByTagName(tag);
1741     var returnElements = [];
1742     var current;
1743     var length = elements.length;
1744     for(var i=0; i<length; i++){
1745       current = elements[i];
1746       if(testClass.test(current.className)){
1747         returnElements.push(current);
1748       }
1749     }
1750     return returnElements;
1751   };
1752 
1753   /** 
1754     * @memberOf SHO.Style
1755     * @desc Load page stylesheet from url
1756     * @example
1757     * styleObj.loadAuto();
1758   */
1759   this.loadAuto = function () {
1760     for(i=0;i<arguments.length;i++){
1761       if(check_if_in_path(arguments[i]) != null)
1762         this.addFile(p2.cssAuto + arguments[i] + ".css");
1763     }
1764   };
1765   /** 
1766     * @memberOf SHO.Style
1767     * @desc Load alternate stylesheets
1768     * @example
1769     * styleObj.loadAlternates('green', 'red');
1770   */
1771   this.loadAlternates = function () {
1772     for(i=0;i<arguments.length;i++){
1773         this.addFile(p2.cssAlter + arguments[i] + ".css", arguments[i], arguments[i], "alternate stylesheet", true);
1774     }
1775 	this.disableAlternates();
1776   };
1777 
1778   /** 
1779     * @private
1780 	* @todo check if similar function exists
1781   */
1782   this.getStyles = function() {
1783     var headnodes = document.getElementsByTagName('head')[0].childNodes;
1784     for(var i in headnodes) {
1785       var node = headnodes[i];
1786       if(node.nodeName != 'LINK') continue;
1787       if(node.rel != 'stylesheet' && 
1788         node.rel != 'alternate stylesheet') continue;
1789       if(node.title == '') continue;
1790       this.styles.push(node);
1791     }
1792     return this.styles;
1793   };
1794 };
1795 
1796 
1797 
1798 
1799 /********************************************************************************
1800  ***** PRIVATE_FUNCTIONS ********************************************************/
1801 /** 
1802  * @private
1803  * @desc Helper function: Toggle Infobox
1804  * @example
1805  * toggleInfo();
1806 */
1807 
1808 /** 
1809  * @private
1810  * @desc Helper function: Toggle Infobox
1811  * @example
1812  * toggleInfo();
1813 */
1814 var __sh = new SHO.Style();
1815 if(document.all && !window.opera) 
1816   __sh.addRule("#SHO", "position:absolute"); // IE<7
1817 else __sh.addRule("#SHO[id]", "position:fixed");
1818 __sh.addRule("#SHO", "top:10px");
1819 __sh.addRule("#SHO", "right:10px");
1820 __sh.addRule("#SHO", "width:32em");
1821 __sh.addRule("#SHO", "z-index:1000");
1822 __sh.addRule("#SHO", "border:1px #9DBDBD solid");
1823 __sh.addRule("#SHO", "font-family:'Lucida Grande',Helvetica,Arial");
1824 __sh.addRule("#SHO", "background-color:#4F8282");
1825 __sh.addRule("#SHO", "color:#ffffff");
1826 __sh.addRule("#SHO", "cursor:move");
1827 __sh.addRule("#SHO", "font-size:0.95em");
1828 __sh.addRule("#SHO", "opacity:0.98");
1829 __sh.addRule("#SHO #titlebar", "font-weight:bold");
1830 __sh.addRule("#SHO #titlebar", "font-size:1.2em");
1831 __sh.addRule("#SHO #titlebar", "color:#9DBDBD");
1832 __sh.addRule("#SHO #titlebar", "padding:3px 3px 3px 5px");
1833 __sh.addRule("#SHO #titlebar", "background-color:#467574");
1834 __sh.addRule("#SHO #titlebar", "border-bottom:1px #9DBDBD solid");
1835 __sh.addRule("#SHO #titlebar", "text-align:left");
1836 __sh.addRule("#SHO #closebox", "border:1px #9DBDBD solid");
1837 __sh.addRule("#SHO #closebox", "margin:3px");
1838 __sh.addRule("#SHO #closebox", "float:right");
1839 __sh.addRule("#SHO #closebox", "color:#9DBDBD");
1840 __sh.addRule("#SHO #closebox", "font-weight:bold");
1841 __sh.addRule("#SHO #closebox", "cursor:pointer");
1842 __sh.addRule("#SHO #closebox", "padding:0 2px 0 3px");
1843 __sh.addRule("#SHO .info", "clear:both");
1844 __sh.addRule("#SHO .info", "margin:5px 0 0 0");
1845 __sh.addRule("#SHO .info", "padding-bottom:3px");
1846 __sh.addRule("#SHO #about", "text-align:right");
1847 __sh.addRule("#SHO #about", "border-top:1px #9DBDBD solid");
1848 __sh.addRule("#SHO #about", "background-color:#467574");
1849 __sh.addRule("#SHO #about", "padding:4px");
1850 __sh.addRule("#SHO #about", "clear:both");
1851 __sh.addRule("#SHO a:link", "color:#9DBDBD");
1852 __sh.addRule("#SHO a:link", "text-decoration:none");
1853 __sh.addRule("#SHO a:visited", "color:#9DBDBD");
1854 __sh.addRule("#SHO a:visited", "text-decoration:none");
1855 __sh.addRule("#SHO a:hover", "color:#FFFFFF");
1856 __sh.addRule("#SHO a:hover", "text-decoration:underline");
1857 __sh.addRule("#SHO a:active", "color:#FFFFFF");
1858 __sh.addRule("#SHO a:active", "text-decoration:underline");
1859 __sh.addRule("#SHO p", "padding:0 5px");
1860 __sh.addRule("#SHO p", "margin:0");
1861 __sh.addRule("#SHO .group", "float:left");
1862 __sh.addRule("#SHO .group", "margin:5px auto auto");
1863 __sh.addRule("#SHO ul", "padding:0 5px");
1864 __sh.addRule("#SHO ul", "margin:0 0 5px 0");
1865 __sh.addRule("#SHO li", "list-style-type:none");
1866 __sh.addRule("#SHO .bold", "font-weight:bold");
1867 
1868 
1869 /** 
1870  * @private
1871  * @desc Helper function: Gets the root path
1872  * @example
1873  * var rootPath = get_root_path();
1874 */
1875 function get_root_path() {
1876   var htmlfile_location = window.location.href;
1877   var indexOflastSlash = htmlfile_location.lastIndexOf('\/');
1878   return htmlfile_location.substr(0,indexOflastSlash);
1879 };
1880 
1881 /** 
1882  * @private
1883  * @desc Helper function: Get the name of the ini file from SC script src
1884  * @example
1885  * var iniFileName = get_init_file();
1886 */
1887 function get_init_file() {
1888   // Get all script elements in page
1889   var script_files = document.getElementsByTagName("SCRIPT");
1890   for(i=0;i<script_files.length;i++){
1891     //Loop through all script elements
1892     global_location = script_files[i].src;
1893     var indexOflastQuestionmark = global_location.indexOf('\?');
1894     if(indexOflastQuestionmark!=-1){
1895       // Get location for Common Resources
1896       return global_location.substr(indexOflastQuestionmark+1);
1897     }
1898   }
1899 };
1900 
1901 /** 
1902  * @private
1903  * @desc Helper function: Check if a foldername is in path string
1904 */
1905 function check_if_in_path( foldername ) {
1906   return location.href.match( foldername );
1907 };
1908 
1909 /** 
1910  * @private
1911  * @desc Helper function: Insert whitespace to an comma separeted value (JSON-Helper)
1912  * @example
1913  * myStr.formatEnum();
1914 */
1915 var formatEnum = function () {
1916   return this.toString().split(',').join(', ');
1917 }  
1918 
1919 /** 
1920  * @private
1921  * @desc Helper function: Check if variable is definend
1922  * @example
1923  * isset(myValName)
1924 */
1925 function isset (val) {
1926 	return (typeof(val) != 'undefined') && (val != null);
1927 }
1928 
1929 /** 
1930  * @private
1931  * @desc Helper function: Load required classes
1932  * @example
1933  * requireClass('myClassName')
1934 */
1935 var requireClass = function(className) {
1936 	for (a in _SHO.isloaded) {
1937 		if( a == className && eval('_SHO.isloaded.' + className)!= true) {
1938 		    return eval('new SHO.' + className + '()');
1939 		}
1940 	}
1941 }
1942 
1943 /** 
1944  * @private
1945  * @desc Helper function: Remove Whitespace characters
1946  * @example
1947  * var withoutWhiteSpace = str.trim('   Hello ');
1948 */
1949 
1950 String.prototype.trim = function () {
1951   // Remove leading spaces and carriage returns
1952   this.s = this;
1953     while ((this.s.substring(0,1) == ' ') || 
1954       (this.s.substring(0,1) == '\n') || 
1955       (this.s.substring(0,1) == '\r')) {
1956         this.s = this.s.substring(1,this.s.length);
1957   };
1958    // Remove trailing spaces and carriage returns
1959     while ((this.s.substring(this.s.length-1,this.s.length) == ' ') || 
1960     (this.s.substring(this.s.length-1,this.s.length) == '\n') || 
1961     (this.s.substring(this.s.length-1,this.s.length) == '\r')) {
1962         this.s = this.s.substring(0,this.s.length-1);
1963     }
1964     return this.s;
1965   
1966 }  
1967 
1968 /** 
1969  * @private
1970  * @desc Helper function: string comparison
1971  * @example
1972  * var str = '<strong>Hello</strong>';
1973  * var result = stringComparison(str1, str2);
1974 */
1975 function stringComparison(a, b)  {
1976   a = a.toLowerCase();
1977   a = a.replace(/ä/g,"a");
1978   a = a.replace(/ö/g,"o");
1979   a = a.replace(/ü/g,"u");
1980   a = a.replace(/ß/g,"s");
1981 
1982   b = b.toLowerCase();
1983   b = b.replace(/ä/g,"a");
1984   b = b.replace(/ö/g,"o");
1985   b = b.replace(/ü/g,"u");
1986   b = b.replace(/ß/g,"s");
1987 
1988   return(a==b)?0:(a>b)?1:-1;
1989 }
1990 
1991 /** 
1992  * @private
1993  * @desc Helper function: Removes all tags from string
1994  * @example
1995  * var str = '<strong>Hello</strong>';
1996  * var withoutTags = str.removeTags();
1997 */
1998 var  remove_tags = function(xStr){
1999   var regExp = /<\/?[^>]+>/gi;
2000   xStr = xStr.replace(regExp,"");
2001   return xStr;
2002 };    
2003 
2004 /** 
2005   * @private 
2006   * @desc Helper function: Array Shuffle 
2007   * @example
2008   * myArray.fisherYatesShuffle();
2009  */
2010 function fisherYates ( myArray ) {
2011   var i = myArray.length;
2012   if ( i == 0 ) return false;
2013   while ( --i ) {
2014      var j = Math.floor( Math.random() * ( i + 1 ) );
2015      var tempi = myArray[i];
2016      var tempj = myArray[j];
2017      myArray[i] = tempj;
2018      myArray[j] = tempi;
2019    }
2020    return myArray;
2021 }
2022 
2023 
2024 // -------------
2025 var arrLoad = new Array();
2026 var arrDOMLoad = new Array();
2027 var browser_info = new Array();
2028 var http = new Object();
2029 var PARSER = new Object();
2030 
2031 
2032 
2033 /********************************************************************************
2034  ***** CREATE_SHORTCUTS *'*******************************************************/
2035 
2036 var sho = new Object();
2037 sho.ajax      = new SHO.Ajax();
2038 sho.browser   = new SHO.Browser();
2039 sho.cookie    = new SHO.Cookie();
2040 sho.config    = new SHO.Config();
2041 sho.debug     = new SHO.Debug();
2042 sho.element   = new SHO.Element();
2043 sho.event     = new SHO.Event();
2044 sho.script    = new SHO.Script();
2045 sho.style     = new SHO.Style();
2046 
2047 var p2 = new Object();
2048 p2.root       = sho.config.PATH_ROOT + '/';
2049 p2.js         = sho.config.PATH_JS + '/';
2050 p2.jsLib      = sho.config.PATH_JS_LIB + '/';
2051 p2.jsDev      = sho.config.PATH_JS_DEV + '/';
2052 p2.jsApps     = sho.config.PATH_JS_APPS + '/';
2053 p2.css        = sho.config.PATH_CSS + '/';
2054 p2.cssAuto    = sho.config.PATH_CSS_AUTO + '/';
2055 p2.cssAlter   = sho.config.PATH_CSS_ALTER + '/';
2056 p2.cssPatches = sho.config.PATH_CSS_PATCHES + '/';
2057 p2.cssApps    = sho.config.PATH_CSS_APPS + '/';
2058 p2.img        = sho.config.PATH_IMAGES + '/';
2059 p2.conf       = sho.config.PATH_CONF + '/';
2060 
2061 /* LOADING INIT FILE */
2062 var NAME_FILE_INIT = get_init_file();
2063 if(NAME_FILE_INIT != null ) {
2064   var initfile =sho.config.PATH_CONF + '/' + NAME_FILE_INIT + '.js';
2065   var new_script = "<scri"+"pt language='JavaScript' type='text/javascript'";
2066   new_script+= " src='" + initfile + "'></scr"+"ipt>";
2067   document.write( new_script );
2068 }
2069 
2070 /** 
2071  * @private
2072  * @desc Helper function: Toggle Infobox
2073  * @example
2074  * toggleInfo();
2075 */
2076 var toggleInfo = function (evt) {
2077 	
2078     evt = (evt) ? evt : ((event) ? event : null);
2079     //if (evt && window.location.search.substr(1,3) == "dev") {
2080     if (evt) {
2081         var charCode = (evt.charCode) ? evt.charCode : evt.keyCode;
2082         if (charCode==35) { // #
2083           if(document.getElementById('SHO') == undefined) {
2084 
2085              var SHOSTR = '<span id="closebox" title="remove" ';
2086 			 SHOSTR+= 'onClick="sho.element.remove(\'SHO\')">X</span>';
2087 			 SHOSTR+= '<p id="titlebar">Shoogar Infobox</p>';
2088 
2089              SHOSTR+= '<div class="info">';
2090 			 var arr = sho.debug.showScripts();
2091 			 SHOSTR+= '<p class="bold">Javascript files:</p>';
2092 			 for(var i=0; i<arr.length; i++) {
2093 			   SHOSTR+= '<p>' + arr[i]+ '</p>';
2094 			 }
2095 			 SHOSTR+= '</div>';
2096 
2097              SHOSTR+= '<div class="info">';
2098 			 var arr = sho.debug.showStylesExt();
2099 			 SHOSTR+= '<p class="bold">External Stylesheets:</p>';
2100 			 for(var i=0; i<arr.length; i++) {
2101 			   SHOSTR+= '<p>' + arr[i]+ '</p>';
2102 			 }
2103 			 SHOSTR+= '</div>';
2104 
2105              SHOSTR+= '<div class="info">';
2106 			 var arr = sho.debug.showStylesInt();
2107 			 SHOSTR+= '<p class="bold">Internal Stylesheets:</p>';
2108 			 for(var i=0; i<arr.length; i++) {
2109 			   SHOSTR+= '<p>' + arr[i]+ '</p>';
2110 			 }
2111 			 SHOSTR+= '</div>';
2112 
2113              SHOSTR+= '<div id="about">';
2114 			 SHOSTR+= '<span>Version ' + sho.debug.version + ' ( ' + sho.debug.lastmod + ' )';
2115 			 SHOSTR+= '    <a href="javascript:alert(sho.debug.showBrowserInfo())"><b>browserInfo</b></a></span>';
2116 			 SHOSTR+= ' |  <a href="javascript:sho.debug.showDocs()"><b>apidoc</b></a></span>';
2117 			 
2118 		     sho.element.appendToBody('div', 'SHO', SHOSTR); 
2119              sho.element.setDraggable('SHO');
2120 		  }
2121 		  else {
2122 			  sho.element.remove('SHO');
2123 		  }
2124 		}
2125 	}
2126 }
2127 sho.event.add(document,'keypress',toggleInfo);
2128