Merge branch 'pu/2013.10-mailto' into 2014.11-develop
[tine20] / tine20 / Tinebase / js / tineInit.js
1 /*
2  * Tine 2.0
3  * 
4  * @package     Tine
5  * @subpackage  Tinebase
6  * @license     http://www.gnu.org/licenses/agpl.html AGPL Version 3
7  * @author      Cornelius Weiss <c.weiss@metaways.de>
8  * @copyright   Copyright (c) 2007-2013 Metaways Infosystems GmbH (http://www.metaways.de)
9  *
10  * TODO         allow to add user defined part to Tine.title
11  */
12
13 /*global Ext, Tine, google, OpenLayers, Locale, */
14
15 /** ------------------------- Ext.ux Initialisation ------------------------ **/
16
17 Ext.ux.Printer.BaseRenderer.prototype.stylesheetPath = 'Tinebase/js/ux/Printer/print.css';
18
19
20 /** ------------------------ Tine 2.0 Initialisation ----------------------- **/
21
22 /**
23  * @class Tine
24  * @singleton
25  */
26 Ext.namespace('Tine', 'Tine.Tinebase', 'Tine.Calendar');
27
28 /**
29  * version of Tine 2.0 javascript client version, gets set a build / release time <br>
30  * <b>Supported Properties:</b>
31  * <table>
32  *   <tr><td><b>buildType</b></td><td> type of build</td></tr>
33  *   <tr><td><b>buildDate</b></td><td> date of build</td></tr>
34  *   <tr><td><b>buildRevision</b></td><td> revision of build</td></tr>
35  *   <tr><td><b>codeName</b></td><td> codename of release</td></tr>
36  *   <tr><td><b>packageString</b></td><td> packageString of release</td></tr>
37  *   <tr><td><b>releaseTime</b></td><td> releaseTime of release</td></tr>
38  * </table>
39  * @type {Object}
40  */
41 Tine.clientVersion = {};
42 Tine.clientVersion.buildType        = 'none';
43 Tine.clientVersion.buildDate        = 'none';
44 Tine.clientVersion.buildRevision    = 'none';
45 Tine.clientVersion.codeName         = 'none';
46 Tine.clientVersion.packageString    = 'none';
47 Tine.clientVersion.releaseTime      = 'none';
48
49 /**
50  * title of app (gets set at build time)
51  * 
52  * @type String
53  */
54 Tine.title = 'Tine 2.0<small>org</small>';
55 Tine.weburl = 'http://www.tine20.com/info/community.html';
56 Tine.helpUrl = 'http://www.tine20.org/wiki/index.php/Main_Page';
57
58 /**
59  * quiet logging in release mode
60  */
61 Ext.LOGLEVEL = Tine.clientVersion.buildType === 'RELEASE' ? 0 : 7;
62 Tine.log = Ext.ux.log;
63
64 Ext.namespace('Tine.Tinebase');
65
66 /**
67  * @class Tine.Tinebase.tineInit
68  * @namespace Tine.Tinebase
69  * @sigleton
70  * static tine init functions
71  */
72 Tine.Tinebase.tineInit = {
73     /**
74      * @cfg {String} getAllRegistryDataMethod
75      */
76     getAllRegistryDataMethod: 'Tinebase.getAllRegistryData',
77
78     /**
79      * @cfg {Boolean} stateful
80      */
81     stateful: true,
82
83     /**
84      * @cfg {String} requestUrl
85      */
86     requestUrl: 'index.php',
87     
88     /**
89      * prefix for localStorage keys
90      * @type String
91      */
92     lsPrefix: Tine.Tinebase.common.getUrl('path') + 'Tine',
93
94     initWindow: function () {
95         Ext.getBody().on('keydown', function (e) {
96             if (e.ctrlKey && e.getKey() === e.A && ! (e.getTarget('form') || e.getTarget('input') || e.getTarget('textarea'))) {
97                 // disable the native 'select all'
98                 e.preventDefault();
99             } else if (e.getKey() === e.BACKSPACE && ! (e.getTarget('form') || e.getTarget('input') || e.getTarget('textarea'))) {
100                 // disable the native 'history back'
101                 e.preventDefault();
102             } else if (!window.isMainWindow && e.ctrlKey && e.getKey() === e.T) {
103                 // disable the native 'new tab' if in popup window
104                 e.preventDefault();
105             } else if (window.isMainWindow && e.ctrlKey && e.getKey() === e.L) {
106                 // reload on ctrl-l
107                 Tine.Tinebase.common.reload({
108                     clearCache: true
109                 });
110             }
111         });
112         
113         // disable generic drops
114         Ext.getBody().on('dragover', function (e) {
115             e.stopPropagation();
116             e.preventDefault();
117             e.browserEvent.dataTransfer.dropEffect = 'none';
118         }, this);
119     },
120     
121     initDebugConsole: function () {
122         var map = new Ext.KeyMap(Ext.getDoc(), [{
123             key: [122], // F11
124             ctrl: true,
125             fn: Tine.Tinebase.common.showDebugConsole
126         }]);
127     },
128     
129     
130     /**
131      * Each window has exactly one viewport containing a card layout in its lifetime
132      * The default card is a splash screen.
133      * 
134      * defautl wait panel (picture only no string!)
135      */
136     initBootSplash: function () {
137         
138         this.splash = {
139             xtype: 'container',
140             id: 'tine-viewport-waitcycle',
141             border: false,
142             layout: 'fit',
143             width: 16,
144             height: 16,
145             // the content elements come from the initial html so they are displayed fastly
146             contentEl: Ext.select('div[class^=tine-viewport-]')
147         };
148         
149         Tine.Tinebase.viewport = new Ext.Viewport({
150             layout: 'fit',
151             border: false,
152             items: {
153                 xtype: 'container',
154                 id: 'tine-viewport-maincardpanel',
155                 ref: 'tineViewportMaincardpanel',
156                 isWindowMainCardPanel: true,
157                 layout: 'card',
158                 border: false,
159                 activeItem: 0,
160                 items: this.splash
161             }
162         });
163     },
164
165     initLoginPanel: function() {
166         if (window.isMainWindow && ! Tine.loginPanel) {
167             var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel;
168             Tine.loginPanel = new Tine.Tinebase.LoginPanel({
169                 defaultUsername: Tine.Tinebase.registry.get('defaultUsername'),
170                 defaultPassword: Tine.Tinebase.registry.get('defaultPassword')
171             });
172             mainCardPanel.add(Tine.loginPanel);
173         }
174
175         // handle logouts in other windows
176         Tine.Tinebase.registry.on('replace', function(key, oldValue, newValue) {
177             if (oldValue && !newValue) {
178                 if (window.isMainWindow) {
179                     Tine.Tinebase.common.reload();
180                 } else {
181                     Ext.ux.PopupWindow.close(window);
182                 }
183             }
184         }, this, 'currentAccount');
185     },
186
187     showLoginBox: function(cb, scope) {
188         var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel,
189             activeItem = mainCardPanel.layout.activeItem;
190
191         mainCardPanel.layout.setActiveItem(Tine.loginPanel.id);
192         Tine.loginPanel.doLayout();
193         Tine.loginPanel.onLogin = function(response) {
194             mainCardPanel.layout.setActiveItem(activeItem);
195             cb.call(scope||window, response);
196         }
197
198 //        //listen for other windows login?
199 //        Tine.Tinebase.registry.on('replace', function() {
200 //            mainCardPanel.layout.setActiveItem(activeItem);
201 //        }, this, 'currentAccount');
202
203     },
204
205     renderWindow: function () {
206         Tine.log.info('renderWindow::start');
207         
208         var mainCardPanel = Tine.Tinebase.viewport.tineViewportMaincardpanel;
209
210         // check if user is already logged in
211         if (! Tine.Tinebase.registry.get('currentAccount')) {
212             Tine.Tinebase.tineInit.showLoginBox(function(response){
213                 // fetch users registry
214                 Tine.Tinebase.tineInit.initRegistry(true, function() {
215                     Ext.MessageBox.hide();
216                     Tine.Tinebase.tineInit.initWindowMgr();
217                     Tine.Tinebase.tineInit.renderWindow();
218                 });
219             });
220             
221             return;
222         }
223
224         // experimental deep link
225         if (window.location.hash) {
226             var hash = window.location.hash.replace(/^#+/, ''),
227                 config;
228
229             if (hash.match(/\//)) {
230                 var args = hash.split('/'),
231                     app = Tine.Tinebase.appMgr.get(args.shift()),
232                     method = args.shift();
233
234                 var config = app.dispatchRoute(method, args);
235
236             } else {
237                 //http://tine.example.com/#{"name":"TimesheetEditWindow_0","contentPanelConstructor":"Tine.Timetracker.TimesheetEditDialog","recordId":0}
238                 config = Ext.decode(hash);
239             }
240
241             if (window.history && window.history.replaceState) {
242                 window.history.replaceState({}, document.title, Tine.Tinebase.common.getUrl());
243             }
244
245             // what about plugins?
246             Ext.applyIf(config, {
247                 name: window.name,
248                 popup: window
249             })
250
251             window.name = config.name;
252
253             // disable mainWindows per hash for the moment. MainWindow concept needs to be rethought
254             // in the context of window manager rewrite
255             window.isMainWindow = false;
256
257             Ext.ux.PopupWindowMgr.register(new Ext.ux.PopupWindow(config));
258         }
259
260         /**
261          * register MainWindow
262          */
263         else if (window.isMainWindow) {
264             Ext.ux.PopupWindowMgr.register({
265                 name: window.name,
266                 popup: window,
267                 contentPanelConstructor: 'Tine.Tinebase.MainScreenPanel'
268             });
269         }
270
271
272         Tine.log.info('renderWindow::before get window');
273         
274         // fetch window config from WindowMgr
275         var c = Ext.ux.PopupWindowMgr.get(window) || {};
276         
277         // set window title
278         window.document.title = Ext.util.Format.stripTags(c.title ? c.title : window.document.title);
279         
280         Tine.log.info('renderWindow::getCenterPanel');
281         
282         // finally render the window contents in a new card
283         var card = Tine.WindowFactory.getCenterPanel(c);
284         mainCardPanel.add(card);
285         mainCardPanel.layout.setActiveItem(card.id);
286         card.doLayout();
287         
288         window.initializationComplete = true;
289     },
290
291     initAjax: function () {
292         Ext.Ajax.url = Tine.Tinebase.tineInit.requestUrl;
293         Ext.Ajax.method = 'POST';
294         
295         Ext.Ajax.defaultHeaders = {
296             'X-Tine20-Request-Type' : 'JSON'
297         };
298         
299         Ext.Ajax.transactions = {};
300         
301         /**
302          * inspect all requests done via the ajax singleton
303          * 
304          * - send custom headers
305          * - send json key 
306          * - implicitly transform non jsonrpc requests
307          * 
308          * NOTE: implicitly transformed reqeusts get their callback fn's proxied 
309          *       through generic response inspectors as defined below
310          */
311         Ext.Ajax.on('beforerequest', function (connection, options) {
312             options.headers = options.headers || {};
313             options.headers['X-Tine20-JsonKey'] = Tine.Tinebase.registry && Tine.Tinebase.registry.get ? Tine.Tinebase.registry.get('jsonKey') : '';
314             options.headers['X-Tine20-TransactionId'] = Tine.Tinebase.data.Record.generateUID();
315             
316             options.url = Ext.urlAppend((options.url ? options.url : Tine.Tinebase.tineInit.requestUrl),  'transactionid=' + options.headers['X-Tine20-TransactionId']);
317             
318             // convert non Ext.Direct request to jsonrpc
319             // - convert params
320             // - convert error handling
321             if (options.params && !options.isUpload) {
322                 var params = {};
323                 
324                 var def = Tine.Tinebase.registry.get('serviceMap') ? Tine.Tinebase.registry.get('serviceMap').services[options.params.method] : false;
325                 if (def) {
326                     // sort parms according to def
327                     for (var i = 0, p; i < def.parameters.length; i += 1) {
328                         p = def.parameters[i].name;
329                         params[p] = options.params[p];
330                     }
331                 } else {
332                     for (var param in options.params) {
333                         if (options.params.hasOwnProperty(param) && param !== 'method') {
334                             params[param] = options.params[param];
335                         }
336                     }
337                 }
338                 
339                 options.jsonData = Ext.encode({
340                     jsonrpc: '2.0',
341                     method: options.params.method,
342                     params: params,
343                     id: ++Ext.Direct.TID
344                 });
345                 
346                 options.cbs = {};
347                 options.cbs.success  = options.success  || null;
348                 options.cbs.failure  = options.failure  || null;
349                 options.cbs.callback = options.callback || null;
350                 
351                 options.isImplicitJsonRpc = true;
352                 delete options.params;
353                 delete options.success;
354                 delete options.failure;
355                 delete options.callback;
356             }
357             
358             Ext.Ajax.transactions[options.headers['X-Tine20-TransactionId']] = {
359                 date: new Date(),
360                 json: options.jsonData
361             };
362         });
363         
364         /**
365          * inspect completed responses => staus code == 200
366          * 
367          * - detect resoponse errors (e.g. html from xdebug) and convert to exceptional states
368          * - implicitly transform requests from JSONRPC
369          * 
370          *  NOTE: All programatically catchable exceptions lead to successfull requests
371          *        with the jsonprc protocol. For implicitly converted jsonprc requests we 
372          *        transform error states here and route them to the error methods defined 
373          *        in the request options
374          *        
375          *  NOTE: Illegal json data responses are mapped to error code 530
376          *        Empty resonses (Ext.Decode can't deal with them) are maped to 540
377          *        Memory exhausted to 550
378          */
379         Ext.Ajax.on('requestcomplete', function (connection, response, options) {
380             delete Ext.Ajax.transactions[options.headers['X-Tine20-TransactionId']];
381             
382             // detect resoponse errors (e.g. html from xdebug) and convert into error response
383             if (! options.isUpload && ! response.responseText.match(/^([{\[])|(<\?xml)+/)) {
384                 var exception = {
385                     code: response.responseText !== "" ? 530 : 540,
386                     message: response.responseText !== "" ? 'illegal json data in response' : 'empty response',
387                     traceHTML: response.responseText,
388                     request: options.jsonData,
389                     response: response.responseText
390                 };
391                 
392                 // Fatal error: Allowed memory size of n bytes exhausted (tried to allocate m bytes) 
393                 if (response.responseText.match(/^Fatal error: Allowed memory size of /m)) {
394                     Ext.apply(exception, {
395                         code: 550,
396                         message: response.responseText
397                     });
398                 }
399                 
400                 // encapsulate as jsonrpc response
401                 var requestOptions = Ext.decode(options.jsonData);
402                 response.responseText = Ext.encode({
403                     jsonrpc: requestOptions.jsonrpc,
404                     id: requestOptions.id,
405                     error: {
406                         code: -32000,
407                         message: exception.message,
408                         data: exception
409                     }
410                 });
411             }
412             
413             // strip jsonrpc fragments for non Ext.Direct requests
414             if (options.isImplicitJsonRpc) {
415                 var jsonrpc = Ext.decode(response.responseText);
416                 if (jsonrpc.result) {
417                     response.responseText = Ext.encode(jsonrpc.result);
418                     
419                     if (options.cbs.success) {
420                         options.cbs.success.call(options.scope, response, options);
421                     }
422                     if (options.cbs.callback) {
423                         options.cbs.callback.call(options.scope, options, true, response);
424                     }
425                 } else {
426                     
427                     response.responseText = Ext.encode(jsonrpc.error);
428                     
429                     if (options.cbs.failure) {
430                         options.cbs.failure.call(options.scope, response, options);
431                     } else if (options.cbs.callback) {
432                         options.cbs.callback.call(options.scope, options, false, response);
433                     } else {
434                         var responseData = Ext.decode(response.responseText);
435                             
436                         exception = responseData.data ? responseData.data : responseData;
437                         exception.request = options.jsonData;
438                         exception.response = response.responseText;
439                         
440                         Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
441                     }
442                 }
443             }
444         });
445         
446         /**
447          * inspect request exceptions
448          *  - convert to jsonrpc compatiple exceptional states
449          *  - call generic exception handler if no handler is defined in request options
450          *  
451          * NOTE: Request exceptions are exceptional state from web-server:
452          *       -> status codes != 200 : This kind of exceptions are not part of the jsonrpc protocol
453          *       -> timeouts: status code 520
454          */
455         Ext.Ajax.on('requestexception', function (connection, response, options) {
456             delete Ext.Ajax.transactions[options.headers['X-Tine20-TransactionId']];
457             // map connection errors to errorcode 510 and timeouts to 520
458             var errorCode = response.status > 0 ? response.status :
459                             (response.status === 0 ? 510 : 520);
460                             
461             // convert into error response
462             if (! options.isUpload) {
463                 var exception = {
464                     code: errorCode,
465                     message: 'request exception: ' + response.statusText,
466                     traceHTML: response.responseText,
467                     request: options.jsonData,
468                     requestHeaders: options.headers,
469                     openTransactions: Ext.Ajax.transactions,
470                     response: response.responseText
471                 };
472                 
473                 // encapsulate as jsonrpc response
474                 var requestOptions = Ext.decode(options.jsonData);
475                 response.responseText = Ext.encode({
476                     jsonrpc: requestOptions.jsonrpc,
477                     id: requestOptions.id,
478                     error: {
479                         code: -32000,
480                         message: exception.message,
481                         data: exception
482                     }
483                 });
484             }
485             
486             // NOTE: Tine.data.RecordProxy is implicitRPC atm.
487             if (options.isImplicitJsonRpc) {
488                 var jsonrpc = Ext.decode(response.responseText);
489                 
490                 response.responseText = Ext.encode(jsonrpc.error);
491                     
492                 if (options.cbs.failure) {
493                     options.cbs.failure.call(options.scope, response, options);
494                 } else if (options.cbs.callback) {
495                     options.cbs.callback.call(options.scope, options, false, response);
496                 } else {
497                     var responseData = Ext.decode(response.responseText);
498                     
499                     exception = responseData.data ? responseData.data : responseData;
500                     
501                     Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
502                 }
503                 
504             } else if (! options.failure && ! options.callback) {
505                 Tine.Tinebase.ExceptionHandler.handleRequestException(exception);
506             }
507         });
508     },
509
510     /**
511      * init registry
512      *
513      * @param {Bool} forceReload
514      * @param {Function} cb
515      * @param {Object} scope
516      */
517     initRegistry: function (forceReload, cb, scope) {
518         Tine.Tinebase.registry = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + 'Tinebase.registry');
519
520         var version = Tine.Tinebase.registry.get('version'),
521             userApplications = Tine.Tinebase.registry.get('userApplications') || [];
522
523         var reloadNeeded =
524                !version
525             || !userApplications
526             || userApplications.length < 2;
527
528         if (forceReload || reloadNeeded) {
529             Ext.Ajax.request({
530                 timeout: 120000, // 2 minutes
531                 params: {
532                     method: Tine.Tinebase.tineInit.getAllRegistryDataMethod
533                 },
534                 failure: function () {
535                     // if registry could not be loaded, this is mostly due to missconfiguaration
536                     // don't send error reports for that!
537                     Tine.Tinebase.ExceptionHandler.handleRequestException({
538                         code: 503
539                     });
540                 },
541                 success: function (response, request) {
542                     var registryData = Ext.util.JSON.decode(response.responseText);
543                     for (var app in registryData) {
544                         if (registryData.hasOwnProperty(app)) {
545                             var appData = registryData[app];
546                             if (Tine[app]) {
547                                 Tine[app].registry = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.registry');
548
549                                 for (var key in appData) {
550                                     if (appData.hasOwnProperty(key)) {
551                                         if (key === 'preferences') {
552                                             Tine[app].preferences = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.preferences');
553                                             for (var pref in appData[key]) {
554                                                 if (appData[key].hasOwnProperty(pref)) {
555                                                     Tine[app].preferences.set(pref, appData[key][pref]);
556                                                 }
557                                             }
558
559                                         } else {
560                                             Tine[app].registry.set(key, appData[key]);
561                                         }
562                                     }
563                                 }
564                             }
565                         }
566                     }
567
568                     Tine.Tinebase.tineInit.onRegistryLoad();
569                     cb.call(scope);
570                 }
571             });
572         } else {
573             for (var app,i=0;i<userApplications.length;i++) {
574                 app = userApplications[i].name;
575                 if (Tine[app]) {
576                   Tine[app].registry = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.registry');
577                   Tine[app].preferences = store.namespace(Tine.Tinebase.tineInit.lsPrefix + '.' + app + '.preferences');
578                 }
579             }
580
581             Tine.Tinebase.tineInit.onRegistryLoad();
582             cb.call(scope);
583         }
584
585
586     },
587
588     /**
589      * apply registry data
590      */
591     onRegistryLoad: function() {
592         if (Tine.Tinebase.registry.get('preferences')) {
593             Tine.Tinebase.preferences.on('replace', Tine.Tinebase.tineInit.onPreferenceChange);
594         }
595
596         Tine.helpUrl = Tine.Tinebase.registry.get('helpUrl') || Tine.helpUrl;
597
598         Ext.override(Ext.ux.file.Upload, {
599             maxFileUploadSize: Tine.Tinebase.registry.get('maxFileUploadSize'),
600             maxPostSize: Tine.Tinebase.registry.get('maxPostSize')
601         });
602
603         Tine.Tinebase.tineInit.initExtDirect();
604
605         Tine.Tinebase.tineInit.initState();
606
607         if (Tine.Tinebase.registry.get('currentAccount')) {
608             Tine.Tinebase.tineInit.initAppMgr();
609         }
610
611         Tine.Tinebase.tineInit.initUploadMgr();
612
613         Tine.Tinebase.tineInit.initLoginPanel();
614     },
615
616     /**
617      * remove all registry data
618      */
619     clearRegistry: function() {
620         store.namespace(Tine.Tinebase.tineInit.lsPrefix).clearAll();
621     },
622
623     /**
624      * executed when a value in Tinebase registry/preferences changed
625      *
626      * @param {string} key
627      * @param {value} oldValue
628      * @param {value} newValue
629      */
630     onPreferenceChange: function (key, oldValue, newValue) {
631         switch (key) {
632             case 'windowtype':
633             case 'confirmLogout':
634             case 'timezone':
635             case 'locale':
636                 // reload mainscreen
637                 Tine.Tinebase.common.reload({
638                     clearCache: key == 'locale'
639                 });
640
641                 break;
642         }
643     },
644     
645     /**
646      * initialise window and windowMgr (only popup atm.)
647      */
648     initWindowMgr: function () {
649         /**
650          * initialise window types
651          */
652         var windowType = 'Browser';
653         Ext.ux.PopupWindow.prototype.url = 'index.php';
654
655         if (Tine.Tinebase.registry && Tine.Tinebase.registry.get('preferences')) {
656             // update window factory window type (required after login)
657             windowType = Tine.Tinebase.registry.get('preferences').get('windowtype');
658         }
659
660         Tine.WindowFactory = new Ext.ux.WindowFactory({
661             windowType: windowType
662         });
663
664         // init ApplicationStarter on Ext window once
665         if (windowType == 'Ext') {
666             Tine.Tinebase.ApplicationStarter.init();
667         }
668     },
669     /**
670      * initialise state provider
671      */
672     initState: function () {
673         if (Tine.Tinebase.tineInit.stateful === true) {
674             if (window.isMainWindow || Ext.isIE) {
675                 // NOTE: IE is as always pain in the ass! cross window issues prohibit serialisation of state objects
676                 Ext.state.Manager.setProvider(new Tine.Tinebase.StateProvider());
677             } else {
678                 var mainWindow = Ext.ux.PopupWindowMgr.getMainWindow();
679                 Ext.state.Manager = mainWindow.Ext.state.Manager;
680             }
681         }
682     },
683     
684     /**
685      * add provider to Ext.Direct based on Tine servicemap
686      */
687     initExtDirect: function () {
688         var sam = Tine.Tinebase.registry.get('serviceMap');
689         
690         Ext.Direct.addProvider(Ext.apply(sam, {
691             'type'     : 'jsonrpcprovider',
692             'namespace': 'Tine',
693             'url'      : sam.target
694         }));
695     },
696     
697     /**
698      * init external libraries
699      */
700     initLibs: function () {
701         if (OpenLayers) {
702             // fix OpenLayers script location to find images/themes/...
703             OpenLayers._getScriptLocation = function () {
704                 return 'library/OpenLayers/';
705             };
706         }
707     },
708     
709     /**
710      * initialise application manager
711      */
712     initAppMgr: function () {
713         if (! Ext.isIE9 && ! Ext.isIE && ! window.isMainWindow) {
714             // return app from main window for non-IE browsers
715             Tine.Tinebase.appMgr = Ext.ux.PopupWindowMgr.getMainWindow().Tine.Tinebase.appMgr;
716         } else {
717             Tine.Tinebase.appMgr = new Tine.Tinebase.AppManager();
718         }
719     },
720     
721     /**
722      * initialise upload manager
723      */
724     initUploadMgr: function () {
725         Tine.Tinebase.uploadManager = new Ext.ux.file.UploadManager();
726     },
727     
728     /**
729      * config locales
730      */
731     initLocale: function () {
732         //Locale.setlocale(Locale.LC_ALL, '');
733         Tine.Tinebase.translation = new Locale.Gettext();
734         Tine.Tinebase.translation.textdomain('Tinebase');
735         window._ = function (msgid) {
736             return Tine.Tinebase.translation.dgettext('Tinebase', msgid);
737         };
738         Tine.Tinebase.prototypeTranslation();
739     }
740 };
741
742 Ext.onReady(function () {
743     Tine.Tinebase.tineInit.initWindow();
744     Tine.Tinebase.tineInit.initDebugConsole();
745     Tine.Tinebase.tineInit.initBootSplash();
746     Tine.Tinebase.tineInit.initLocale();
747     Tine.Tinebase.tineInit.initAjax();
748     Tine.Tinebase.tineInit.initLibs();
749
750     Tine.Tinebase.tineInit.initRegistry(false, function() {
751         Tine.Tinebase.tineInit.initWindowMgr();
752         Tine.Tinebase.tineInit.renderWindow();
753     });
754 });