Import src directory from OpenRico 2.1
[misc/kostenrechnung] / lib / rico / rico.js
1 /**
2   *
3   *  Copyright 2005 Sabre Airline Solutions
4   *
5   *  Licensed under the Apache License, Version 2.0 (the "License"); you may not use this
6   *  file except in compliance with the License. You may obtain a copy of the License at
7   *
8   *         http://www.apache.org/licenses/LICENSE-2.0
9   *
10   *  Unless required by applicable law or agreed to in writing, software distributed under the
11   *  License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
12   *  either express or implied. See the License for the specific language governing permissions
13   *  and limitations under the License.
14   **/
15
16
17 // This module does NOT depend on prototype.js
18
19 /**
20  * @namespace Main Rico object
21  */
22 var Rico = {
23   Version: '2.1',
24   loadRequested: 1,
25   loadComplete: 2,
26   init : function() {
27     try {  // fix IE background image flicker (credit: www.mister-pixel.com)
28       document.execCommand("BackgroundImageCache", false, true);
29     } catch(err) {}
30     this.preloadMsgs='';
31     var elements = document.getElementsByTagName('script');
32     this.baseHref= location.protocol + "//" + location.host;
33     this.loadedFiles={};
34     this.windowIsLoaded=false;
35     this.onLoadCallbacks=[];
36     var filename,ricoFilename;
37     for (var i=0; i<elements.length; i++) {
38       if (!elements[i].src) continue;
39       var src = elements[i].src;
40       var slashIdx = src.lastIndexOf('/');
41       var path = src.substring(0, slashIdx+1);
42       filename = src.substring(slashIdx+1);
43       var parmPos  = filename.indexOf('?');
44       if (parmPos > 0) filename = filename.substring(0, parmPos);
45       this.loadedFiles[filename]=this.loadComplete;
46       if (filename == 'rico.js' || filename == 'min.rico.js') {
47         ricoFilename=filename;
48         var isRailsPath = (path.indexOf("/javascripts") >= 0);
49         if (isRailsPath){
50           this.jsDir = "/javascripts/";
51           this.cssDir = "/stylesheets/";
52           this.imgDir = "/images/";
53           this.htmDir = "/";
54           this.xslDir = "/";
55         } else {
56           this.jsDir = path;
57           this.cssDir = path+'css/';
58           this.imgDir = path+'images/';
59           this.htmDir = path;
60           this.xslDir = path;
61         }
62       }
63     }
64     if (!ricoFilename) throw('unable to locate rico.js or min.rico.js script element');
65     if (typeof Prototype=='undefined') {
66       if (typeof(google)=='object' && google.load)
67         google.load('prototype', '1.6');
68       else
69         this.include('prototype.js');
70     }
71     if (ricoFilename == 'rico.js') {
72       this.include('ricoCommon.js');
73       this.languageInclude('en');   // in case a phrase is missing from a translation
74     }
75     var onloadAction=function() { Rico.windowLoaded(); };
76     if (window.addEventListener)
77       window.addEventListener('load', onloadAction, false);
78     else if (window.attachEvent)
79       window.attachEvent('onload', onloadAction);
80     this.onLoad(function() { Rico.writeDebugMsg('Pre-load messages:\n'+Rico.preloadMsgs); });
81   },
82
83   // Array entries can reference a javascript file or css stylesheet
84   // A dependency on another module can be indicated with a plus-sign prefix: '+DependsOnModule'
85   moduleDependencies : {
86     Accordion  : ['ricoBehaviors.js','ricoEffects.js','ricoComponents.js'],
87     Color      : ['ricoStyles.js'],
88     Corner     : ['ricoStyles.js'],
89     DragAndDrop: ['ricoStyles.js','ricoEffects.js','ricoDragDrop.js'],
90     Effect     : ['ricoEffects.js'],
91     Calendar   : ['ricoCalendar.js', 'ricoCalendar.css'],
92     Tree       : ['ricoTree.js', 'ricoTree.css'],
93     ColorPicker: ['ricoColorPicker.js', 'ricoStyles.js', 'ricoColorPicker.css'],
94     CustomMenu : ['ricoMenu.js', 'ricoMenu.css'],
95     SimpleGrid : ['+Effect', 'ricoGridCommon.js', 'ricoGrid.css', 'ricoSimpleGrid.js'],
96     LiveGridBasic : ['ricoGridCommon.js', 'ricoGrid.css', 'ricoBehaviors.js', 'ricoLiveGrid.js'],
97     LiveGrid      : ['+Effect', '+LiveGridBasic', 'ricoLiveGridControls.js'],
98     LiveGridMenu  : ['+CustomMenu', 'ricoLiveGridMenu.js'],
99     LiveGridAjax  : ['+LiveGrid', 'ricoLiveGridAjax.js'],
100     LiveGridJSON  : ['+LiveGridAjax', 'ricoLiveGridJSON.js'],
101     LiveGridForms : ['+LiveGridAjax', '+LiveGridMenu', '+Accordion', '+Corner', 'ricoLiveGridForms.js', 'ricoLiveGridForms.css'],
102     SpreadSheet   : ['+SimpleGrid', 'ricoSheet.js', 'ricoSheet.css']
103   },
104   
105   languages : {
106     de: "translations/ricoLocale_de.js",
107     en: "translations/ricoLocale_en.js",
108     es: "translations/ricoLocale_es.js",
109     fr: "translations/ricoLocale_fr.js",
110     it: "translations/ricoLocale_it.js",
111     ja: "translations/ricoLocale_ja.js",
112     ko: "translations/ricoLocale_ko.js",
113     pt: "translations/ricoLocale_pt.js",
114     zh: "translations/ricoLocale_zh.js"
115   },
116   
117   languageInclude : function(lang2) {
118     var filename=this.languages[lang2];
119     if (filename) this.include(filename);
120     return !!filename;
121   },
122   
123   acceptLanguage : function(acceptLang) {
124     var arLang=acceptLang.toLowerCase().split(',');
125     for (var i=0; i<arLang.length; i++) {
126       var lang2=arLang[i].match(/\w\w/);
127       if (!lang2) continue;
128       if (this.languageInclude(lang2)) return true;
129     }
130     return false;
131   },
132
133   // Expects one or more module or file names
134   loadModule : function() {
135     for (var a=0, length=arguments.length; a<length; a++) {
136       var name=arguments[a];
137       var dep=this.moduleDependencies[name];
138       if (dep) {
139         for (var i=0; i<dep.length; i++) {
140           if (dep[i].substring(0,1)=='+') {
141             this.loadModule(dep[i].slice(1));
142           } else {
143             this.include(dep[i]);
144           }
145         }
146       } else {
147         this.include(name);
148       }
149     }
150   },
151
152   include : function(filename) {
153     if (this.loadedFiles[filename]) return;
154     this.addPreloadMsg('include: '+filename);
155     var ext = filename.substr(filename.lastIndexOf('.')+1);
156     switch (ext.toLowerCase()) {
157       case 'js':
158         this.loadedFiles[filename]=filename.substring(0,4)=='rico' ? this.loadRequested : this.loadComplete;
159         document.write("<script type='text/javascript' src='"+this.jsDir+filename+"'><\/script>");
160         return;
161       case 'css':
162         var el = document.createElement('link');
163         el.type = 'text/css';
164         el.rel = 'stylesheet';
165         el.href = this.cssDir+filename;
166         this.loadedFiles[filename]=this.loadComplete;
167         document.getElementsByTagName('head')[0].appendChild(el);
168         return;
169     }
170   },
171
172   // called after a script file has finished loading
173   includeLoaded: function(filename) {
174     this.loadedFiles[filename]=this.loadComplete;
175     this.checkIfComplete();
176   },
177
178   // called by the document onload event
179   windowLoaded: function() {
180     this.windowIsLoaded=true;
181     this.checkIfComplete();
182   },
183
184   checkIfComplete: function() {
185     var waitingFor=this.windowIsLoaded ? '' : 'window';
186     for(var filename in  this.loadedFiles) {
187       if (this.loadedFiles[filename]==this.loadRequested)
188         waitingFor+=' '+filename;
189     }
190     //window.status='waitingFor: '+waitingFor;
191     this.addPreloadMsg('waitingFor: '+waitingFor);
192     if (waitingFor.length==0) {
193       this.addPreloadMsg('Processing callbacks');
194       while (this.onLoadCallbacks.length > 0) {
195         var callback=this.onLoadCallbacks.shift();
196         if (callback) callback();
197       }
198     }
199   },
200
201   onLoad: function(callback,frontOfQ) {
202     if (frontOfQ)
203       this.onLoadCallbacks.unshift(callback);
204     else
205       this.onLoadCallbacks.push(callback);
206     this.checkIfComplete();
207   },
208
209   isKonqueror : navigator.userAgent.toLowerCase().indexOf("konqueror") >= 0,
210
211   // logging funtions
212
213   startTime : new Date(),
214
215   timeStamp: function() {
216     var stamp = new Date();
217     return (stamp.getTime()-this.startTime.getTime())+": ";
218   },
219
220   setDebugArea: function(id, forceit) {
221     if (!this.debugArea || forceit) {
222       var newarea=document.getElementById(id);
223       if (!newarea) return;
224       this.debugArea=newarea;
225       newarea.value='';
226     }
227   },
228
229   addPreloadMsg: function(msg) {
230     this.preloadMsgs+=Rico.timeStamp()+msg+"\n";
231   },
232
233   writeDebugMsg: function(msg, resetFlag) {
234     if (this.debugArea) {
235       if (resetFlag) this.debugArea.value='';
236       this.debugArea.value+=this.timeStamp()+msg+"\n";
237     } else if (window.console) {
238       if (window.console.firebug)
239         window.console.log(this.timeStamp(),msg);
240       else
241         window.console.log(this.timeStamp()+msg);
242     } else if (window.opera) {
243       window.opera.postError(this.timeStamp()+msg);
244     }
245   }
246
247 }
248
249 Rico.init();