Pman.js
[Pman.Core] / Pman.js
1 //<script type="text/javascript">
2
3 /**
4  * 
5  * >>> Pman.layout.getRegion('center').tabs.stripWrap
6  * ==> tab.???
7  * var tbh = Pman.layout.getRegion('center').tabs.stripWrap.child('div').createChild(
8  * 
9  * {tag: 'div', style: 'display:block;position:absolute;top:2;left:300;width:100%;height:25px'});
10  * 
11  */
12  
13 if (typeof(_T) == 'undefined') { _T={};}
14  
15
16   
17
18 Pman = new Roo.Document(
19 {
20    /// appVersion: '1.7', // fixme = needs to be removed - use Global AppVersion
21     subMenuItems : [],
22     topMenuItems : [],
23     rightNames: { }, /// register right names here - so they can be translated and rendered.
24     buildCompleted : false, // flag to say if we are building interface..
25     events : {
26         'beforeload' : true, // fired after page ready, before module building.
27         'load' : true, // fired after module building
28         'authrefreshed' : true // fire on auth updated?? - should be on Login?!?!?
29     },
30     
31     listeners : {
32         'ready' : function()
33         {
34             // kludge to fix firebug debugger
35             if (typeof(console) == 'undefined') {
36                 console = { log : function() {  } };
37             }
38             
39             // remove loader..
40             if (Ext.get('loading')) {
41                 Ext.get('loading').remove();
42             }
43             
44             Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
45             
46             // link errors...
47             
48             if (AppLinkError.length) {
49                 Ext.MessageBox.alert("Error", AppLinkError, function() {
50                     Pman.Login.onLoad();
51                 });
52                 return;
53             }
54             
55             
56             // reset password!!!!
57             if (showNewPass.length) {
58                 Pman.PasswordChange.show(  { passwordReset : showNewPass },
59                     function(data) {
60                         // fail and success we do  a load...
61                         Pman.Login.onLoad();
62                     }
63                 );
64                 return;
65             }
66              
67             Pman.Login.onLoad();
68             
69         },
70         'load' : function()
71         {
72             if (Roo.get('loading-logo-tile')) {
73                 Roo.get('loading-logo-tile').remove();
74             }
75             if (Roo.get('loading-logo-tile-top')) {
76                 Roo.get('loading-logo-tile-top').remove();
77             }
78             if (Roo.get('loading-logo-bottom')) {
79                 Roo.get('loading-logo-bottom').remove();
80             }
81             if (Roo.get('loading-logo-center')) {
82                 Roo.get('loading-logo-center').remove();
83             }
84         }   
85         
86     },
87    
88
89     
90     layout: false,
91     
92     onload: function() {
93         //this.fireEvent('beforeload',this);
94         
95         
96         
97         if (this.layout) {
98             return; // already loaded
99         } 
100         if (Ext.get('loading')) {
101             Ext.get('loading').remove();
102         }
103         if (Ext.get('loading-mask')) {
104             Ext.get('loading-mask').show();
105         }
106         
107         
108        
109         
110         /*
111         Ext.MessageBox.show({
112            title: "Please wait...",
113            msg: "Building Interface...",
114            width:340,
115            progress:true,
116            closable:false
117           
118         });
119         */
120         //Pman.onLoadBuild();
121         //Ext.get(document.body).mask("Building Interface");
122         //Pman.onLoadBuild.defer(100, Pman);
123        //Pman.onLoadBuild();
124                     
125    // },
126     //onLoadBuild : function() {
127         
128         var _this = this;
129         this.stime = new Date();
130         this.layout = new Ext.BorderLayout(document.body, {
131             north: {
132                 split:false,
133                 initialSize: 25,
134                 titlebar: false
135             },
136          
137              
138             center: {
139                 titlebar: false,
140                 autoScroll:false,
141                 closeOnTab: true,
142                 tabPosition: 'top',
143                 //resizeTabs: true,
144                 alwaysShowTabs: true,
145                 minTabWidth: 140
146             } /*,
147             south: {
148                 split:false,
149                 initialSize: 25,
150                 titlebar: false
151             }
152             */
153         });
154         
155         this.fireEvent('beforeload',this);
156         
157         
158         
159         this.layout.beginUpdate();
160         this.layout.add('north', new Ext.ContentPanel('title', 'North'));
161         var au = Pman.Login.authUser;
162         if (au.id > 0 && au.company_id_background_color.length) {
163             Ext.get('title').dom.style.backgroundColor = '#' + au.company_id_background_color;
164             Ext.get('headerInformation').dom.style.color = this.invertColor('#' + au.company_id_background_color);
165         }
166         if (au.id > 0 && au.company_id_logo_id * 1 > 0) {
167             Ext.get('headerInformation-company-logo').dom.src =  baseURL + 
168                 '/Images/' + au.company_id_logo_id + '/' + au.company_id_logo_id_filename;
169         } else {
170             Ext.get('headerInformation-company-logo').dom.src = Roo.BLANK_IMAGE_URL;
171         }
172         
173         Ext.get('headerInformation').dom.innerHTML = String.format(
174                 "You are Logged in as <b>{0} ({1})</b>", // to {4} v{3}", // for <b>{2}</b>",
175                 au.name, au.email, au.company_id_name, 
176                 AppVersion , appNameShort
177         );
178         
179         
180         document.title = appName + ' v' + AppVersion + ' - ' + au.company_id_name;
181         Ext.QuickTips.init(); 
182         if (Ext.isGecko) {
183            Ext.useShims = true;
184         }
185        
186         //this.mainLayout.beginUpdate();
187         //var maskDom = Ext.get(document.body)._maskMsg.dom
188         this.layout.beginUpdate();
189         
190         Pman.building = true;
191         
192         this.buildModules(this, 
193             function() {
194                 
195                 _this.layout.getRegion('center').showPanel(0);
196                 _this.layout.endUpdate(); 
197                 _this.addTopToolbar();  
198                 _this.finalize();
199                 _this.fireEvent('load',this);
200             }
201         );
202         
203         
204      
205     },
206     
207     addTopToolbar : function()
208     {
209           //console.log( "t6:" + ((new Date())-stime));
210         //this.mainLayout.endUpdate();
211         // make a new tab to hold administration stuff...
212         
213        
214         //console.log( "t7:" + ((new Date())-stime));
215         var se = Pman.layout.getRegion('center').tabs.stripEl;
216         var tbh = se.createChild( 
217                 { tag: 'td', style: 'width:100%;'  });
218         
219         var lotb = new Ext.Toolbar(tbh);
220         
221         if (Roo.isSafari) {
222             var tbl = se.child('table', true);
223             tbl.setAttribute('width', '100%');
224         }
225         lotb.add(
226             new Ext.Toolbar.Fill(), 
227      
228             {
229                 text: "Change Password",
230                 cls: 'x-btn-text-icon',
231                 icon: rootURL + '/Pman/templates/images/change-password.gif',
232                 handler : function(){
233                     Pman.PasswordChange.show({});
234                 }
235             }, '-'
236         );
237          
238         
239         if (this.topMenuItems.length) {
240             
241             Roo.each(this.topMenuItems, function (mi) {
242                 lotb.add(mi);
243             });
244             lotb.add('-');
245         }
246         
247         
248         
249         if (this.subMenuItems.length) {
250             
251             this.subMenuItems.sort(function (a,b) {
252                 return a.seqid > b.seqid ? 1 : -1;
253             });
254             // chop off last seperator.
255             // since we always add it.. just chop of last item
256             this.subMenuItems.pop(); 
257             
258             lotb.add(
259                 {
260                      
261                     text: "Add New Item",
262                     cls: 'x-btn-text-icon',
263                     icon: Ext.rootURL + 'images/default/dd/drop-add.gif',
264                     menu : {
265                         items : this.subMenuItems
266                     }     
267                 } ,'-'
268             );
269         }
270        
271         lotb.add(
272             {
273                 text: "Logout",
274                 cls: 'x-btn-text-icon',
275                 icon: rootURL + '/Pman/templates/images/logout.gif',
276                 handler: function() {
277                     Pman.Login.logout();
278                 }
279                  
280             }
281         );
282       
283        // this.layout.endUpdate();
284     },
285     
286     
287     finalize : function() {
288         
289       
290        
291         window.onbeforeunload = function(e) { 
292             var e = e || window.event;
293             var r = "Closing this window will loose changes, are you sure you want to do that?";
294
295             // For IE and Firefox
296             if (e) {
297                 e.returnValue = r;
298             }
299
300             // For Safari
301             return r;
302             
303         };
304         
305         Ext.MessageBox.hide();
306         if (Ext.get('loading-mask')) {
307            Ext.get('loading-mask').remove();
308         }
309         
310         
311         this.buildCompleted = true; // now we can force refreshes on everything..
312         
313         
314         // does the URL indicate we want to see a system..
315         if (AppTrackOnLoad * 1 > 0) {
316             this.onLoadTrack(AppTrackOnLoad,false);
317         }
318         
319         // Open system..
320         
321         var forceAdmin = function(data)
322         {
323             if (!data || !data.id) {
324                 Pman.Dialog.PersonStaff.show( 
325                     { 
326                         id : 0, 
327                         company_id : Pman.Login.authUser.company_id * 1, 
328                         company_id_name : Pman.Login.authUser.company_id_name
329                     }, function(data) {
330                         forceAdmin(data);
331                     }
332                 );
333                 return;
334             }
335             Ext.state.Manager.set('Pman.Login.username', data.email),
336             window.onbeforeunload = false;
337             document.location = baseURL + '?ts=' + Math.random();
338         }
339         
340         var forceCompany = function(data) {
341             if (Pman.Login.authUser.company_id * 1 > 0) {
342                 forceAdmin();
343                 return;
344             }
345             if (!data || !data.id) {
346                 Pman.Dialog.Companies.show( { id : 0, isOwner : 1, comptype: 'OWNER' }, function(data) {
347                     forceCompany(data);
348                 });
349                 return;
350             }
351             Pman.Login.authUser.company_id  = data.id;
352             Pman.Login.authUser.company_id_name  = data.name;
353             forceAdmin();
354         }
355         
356         if (Pman.Login.authUser.id < 0) {
357             forceCompany();
358             /// create account..
359             
360             
361         }
362         
363
364     },
365     
366     
367     
368     
369      
370     onLoadTrack : function(id,cb) {
371         this.onLoadTrackCall(id, cb, 'DocumentsCirc_');
372     },
373     onLoadTrackEdit : function(id,cb) {
374         this.onLoadTrackCall(id, cb, 'Documents_');
375     },
376     
377     
378     /// ----------- FIXME -----
379     
380     
381     onLoadTrackCall : function(id,cb, cls) {
382         Ext.get(document.body).mask("Loading Document details");
383
384         Pman.request({
385             url: baseURL + '/Roo/Documents.html',  
386             params: {
387                 _id: id
388             },  
389             method: 'GET',  
390             success : function(data) {
391                 Ext.get(document.body).unmask();
392              
393                 
394                 switch(data.in_out) {
395                     case 'IN' : cls+='In';break;
396                     case 'OUT' : cls+='Out';break;
397                     case 'WIP' : cls+='Wip';break;
398                     default: 
399                         Ext.MessageBox.alert("Error", "invalid in_out");
400                         return;
401                 }
402                 Pman.Dialog[cls].show(data, cb ? cb : Pman.refreshActivePanel);
403             }, 
404             
405             failure: function() {
406                 Ext.get(document.body).unmask();
407                 //if (cb) {
408                 //    cb.call(false);
409                 //}
410                  
411            }
412         });
413           
414     },
415     
416     /**
417      * eg. has Pman.hasPerm('Admin.Admin_Tab', 'S') == showlist..
418      * 
419      */
420     hasPerm: function(name, lvl) {
421         if (typeof(Pman.Login.authUser) != 'object') {
422             return false;
423         }
424         if (typeof(Pman.Login.authUser.perms[name]) != 'string') {
425             return false;
426         }
427         return Pman.Login.authUser.perms[name].indexOf(lvl) > -1;
428         
429     },
430     
431     
432     
433     
434     
435     
436     
437     
438     Readers : {},
439     ColModels : {},
440     Forms : {},
441     Tab : {},
442     Dialog : {},
443     
444     processResponse : function (response)
445     {
446         var res = '';
447         try {
448             res = Ext.decode(response.responseText);
449             // oops...
450             if (typeof(res) != 'object') {
451                 res = { success : false, errorMsg : res, errors : true };
452             }
453             if (typeof(res.success) == 'undefined') {
454                 res.success = false;
455             }
456             
457         } catch(e) {
458             res = { success : false,  errorMsg : response.responseText, errors : true };
459         }
460         return res;
461     },
462     genericDelete : function(tab,tbl) {
463         
464         var r = [];
465         
466             
467         var s = tab.grid.getSelectionModel().getSelections();
468         if (!s.length)  {
469             Ext.MessageBox.alert("Error", "Select at least one Row to delete" );
470             return '';
471         }
472         
473         for(var i = 0; i < s.length; i++) {
474             r.push(s[i].data.id);
475         }
476     
477         Ext.MessageBox.confirm("Confirm", "Are you sure you want to delete that?",
478             function(btn) {
479                 if (btn != 'yes') {
480                     return;
481                 }
482                 // what about the toolbar??
483                 tab.grid.getView().mainWrap.mask("Deleting");
484                 Pman.request({
485                     url: baseURL + '/Roo/'+tbl+'.php',
486                     method: 'GET',
487                     params: {
488                         _delete : r.join(',')
489                     },
490                     success: function(response) {
491                         tab.grid.getView().mainWrap.unmask();
492                         if ( tab.paging ) {
493                             tab.paging.onClick('refresh');   
494                         } else if (tab.refresh) {
495                             tab.refresh();
496                         } else if (tab.grid.footer && tab.grid.footer.onClick) {
497                             // new xtype built grids
498                             tab.grid.footer.onClick('refresh');   
499                         } else {
500                             tab.grid.getDataSource().load();
501                         }
502                         
503                         
504                         
505                     },
506                     failure: function(act) {
507                         tab.grid.getView().mainWrap.unmask();
508                         Ext.MessageBox.alert("Error", "Error Deleting");
509                     }
510                     
511                 });
512             }
513         );
514     },
515     refreshActivePanel : function() {
516         var actpan = this.layout.getRegion('center').getActivePanel();
517         if (actpan.controller && actpan.controller.paging) {
518             actpan.controller.paging.onClick('refresh');
519             return;
520         }
521         
522         var agid = Pman.layout.getRegion('center').getActivePanel().id;
523         if (!agid) {
524             return;
525         }
526         Pman.Tab[agid].paging.onClick('refresh');
527     },
528     toCidV : function(data) {
529         return 'C' + data.in_out.substring(0,1) + data.cid;
530     },
531     
532     standardActionFailed :  function(f, act, cb) {
533     
534         if (act.failureType == 'client') {
535             Ext.MessageBox.alert("Error", "Please Correct all the errors in red", cb);
536             return;
537         }
538         if (act.failureType == 'connect') {
539             Ext.MessageBox.alert("Error", "Problem Connecting to Server - please try again.", cb);
540             return;
541         }
542         
543         if (act.type == 'submit') {
544             
545             Ext.MessageBox.alert("Error", typeof(act.result.errorMsg) == 'string' ?
546                 String.format('{0}', act.result.errorMsg) : 
547                 "Saving failed = fix errors and try again", cb);
548             return;
549         }
550         
551         // what about load failing..
552         Ext.MessageBox.alert("Error", "Error loading details",cb); 
553     },
554     /**
555      * 
556      * similar to Ext.Ajax, but handles our responses better...
557      * c.url
558      * c.method
559      * c.params
560      * c.failure() == failure function..
561      * c.success(data) == success function..
562      * 
563      * 
564      */
565     request : function(c) {
566         var r= new Roo.data.Connection({
567             timeout : typeof(c.timeout) == 'undefined' ?  30000 c.timeout
568         });
569         r.request({
570             url: c.url,
571             method : c.method,
572             params: c.params,
573             xmlData : c.xmlData,
574             success:  function(response, opts)  {  // check successfull...
575                
576                 var res = Pman.processResponse(response);
577                 
578                 if (!res.success) { // error!
579                     if (c.failure) {
580                         if (true === c.failure.call(this,response, opts)) {
581                             return;
582                         }
583                     }
584                     Roo.MessageBox.hide();
585                     Ext.MessageBox.alert("Error", res.errorMsg ? res.errorMsg : "Error Sending");
586                     return;
587                 }
588                 
589                 c.success.call(this, res.data);
590                 
591                 return; 
592             },
593             failure :  function(response, opts)  {  // check successfull...
594                 
595                 if (c.failure) {
596                     if (true === c.failure.call(this,response, opts)) {
597                         return;
598                     }
599                 }
600                 Roo.MessageBox.hide();
601                 Roo.MessageBox.alert("Error", "Connection timed out sending");
602                 console.log(response);
603                 
604             },
605             scope: this
606             
607         });
608     },
609     csvFrame : false,
610     
611     createCsvFrame: function()
612     {
613         
614         if (this.csvFrame) {
615             document.body.removeChild(this.csvFrame);
616         }
617             
618         var id = Ext.id();
619         this.csvFrame = document.createElement('iframe');
620         this.csvFrame.id = id;
621         this.csvFrame.name = id;
622         this.csvFrame.className = 'x-hidden';
623         if(Ext.isIE){
624             this.csvFrame.src = Ext.SSL_SECURE_URL;
625         }
626         document.body.appendChild(this.csvFrame);
627
628         if(Ext.isIE){
629             document.frames[id].name = id;
630         }
631         
632     },
633     /**
634      * download({
635           url: 
636          })
637      * 
638      * 
639      */
640     
641     
642     download : function(c) {
643         
644         if (c.newWindow) {
645             // as ie seems buggy...
646             window.open( c.url + '?' + Roo.urlEncode(c.params || {}), '_blank');
647             return;
648             
649         }
650         
651         this.createCsvFrame();
652         function cb(){
653             var r = { responseText : "", responseXML : null };
654
655             var frame = this.csvFrame;
656
657             try { 
658                 var doc = Ext.isIE ? 
659                     frame.contentWindow.document : 
660                     (frame.contentDocument || window.frames[this.csvFrame.id].document);
661                 
662                 if(doc && doc.body && doc.body.innerHTML.length){
663                   //  alert(doc.body.innerHTML);
664                     Ext.MessageBox.alert("Error download",doc.body.innerHTML);
665                 }
666                  
667             }
668             catch(e) {
669             }
670
671             Ext.EventManager.removeListener(frame, 'load', cb, this);
672  
673         }
674         Ext.EventManager.on( this.csvFrame, 'load', cb, this);
675         this.csvFrame.src = c.url;
676     },
677     downloadRevision : function(doc, rev)
678     {
679         this.download({
680             url: baseURL + '/Documents/Doc/DownloadRev/'+ doc.id + '/' + rev + '/' +
681                 doc.project_id_code + '-' + doc.cidV + '-' + rev  + '-' +  doc.filename
682         }); 
683                     
684     },
685     exportCSV : function(c) {
686         //this.createCsvFrame(); 
687         for(var i=0;i < c.csvFormat.length;i++) {
688             c.params['csvCols['+i+']'] = c.csvFormat[i][0];
689             c.params['csvTitles['+i+']'] = c.csvFormat[i][1];
690         }
691         
692         
693         c.url +=  '?' + Ext.urlEncode(c.params);
694         this.download(c);
695
696     },
697     prettyDate : function (value) 
698     {
699         if (typeof(value) == 'string') {
700             var ds = Date.parseDate(value, 'Y-m-d H:i:s');
701             if (ds) {
702                 return this.prettyDate(ds);
703             }
704             ds = Date.parseDate(value, 'Y-m-d');
705             if (ds) {
706                 return this.prettyDate(ds);
707             }
708             return '';
709         }
710 // last 7 days...
711         if (!value) {
712             return '';
713         }
714         var td = new Date();
715         var daysSince = Math.floor(td.getElapsed(value) / (1000 * 60*60*24));
716         if (daysSince < 7) {
717             return value.dateFormat('D H:i');
718         }
719         
720         // same month
721         if (td.dateFormat('m') == value.dateFormat('m')) {
722             return value.dateFormat('dS D');
723         }
724         // same year?
725         if (td.dateFormat('Y') == value.dateFormat('Y')) {
726             return value.dateFormat('dS M');
727         }
728         return value.dateFormat('d M Y');
729     },
730     loadException : function(a,b,c,d)
731     {
732         if (d && d.authFailure) {
733             Pman.Login.show();
734             return;
735         }
736         Roo.MessageBox.alert("Problem Loading Data", a.message || c.statusText);
737     },
738     
739     
740     /**
741      * 
742      * Routine to flash alerts in the title bar..
743      * 
744      * 
745      */
746     
747     notifyActive : false,
748     
749     notifyTitle: function(msg)
750     {
751         if (this.notifyActive ) {
752             return;
753         }
754         var stop = false;
755         
756         var stopper = function() {
757             stop = true;
758              document.title = oldtitle;
759         };
760         
761         Roo.get(document.body).on('mousemove', stopper, this);
762         var oldtitle = document.title;
763         var s = 1;
764         var _this = this;
765         var ivl = window.setInterval(function() {
766             
767             if (stop) {
768                 Roo.get(document.body).un('mousemove', stopper, this);
769                 _this.notifyActive = false;
770                 document.title = oldtitle;
771                 window.clearInterval(ivl);
772                 return true;
773             }
774             s = !s;
775             document.title = s ? msg : oldtitle;
776                   
777         }, 1000); // every 120 secs = 2mins..
778          document.title =   msg;
779         
780         
781         
782     },
783     
784     modules : false,
785     /**
786      * example:
787      * 
788      * Pman.register({
789           modKey : '00-admin-xxxx',
790           module : Pman.Tab.projectMgr,
791           region : 'center',
792           parent : Pman.layout
793         })
794      * 
795      */
796     register : function(obj) {
797         if (!obj.parent) {
798             if (obj.parent === false) {
799                 //console.log('skip module (no parent)' + obj.modkey);
800                 return;
801             }
802             
803             console.log(obj);
804         }
805         if (!obj.parent.modules) {
806             obj.parent.modules = new Roo.util.MixedCollection(false, function(o) { return o.modKey });
807         }
808         
809         obj.parent.modules.add(obj);
810         
811     },
812     
813     buildModules : function(parent, onComplete) 
814     {
815         
816         var _this = this;
817         var cmp = function(a,b) {   
818             return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
819             
820         };
821         if (!parent.modules) {
822             return;
823         }
824         parent.modules.keySort('ASC',  cmp );
825         var mods = [];
826         
827         
828         // add modules to their parents..
829         var addMod = function(m) {
830            // console.log(m.modKey);
831             
832             mods.push(m);
833             if (m.module.modules) {
834                 m.module.modules.keySort('ASC',  cmp );
835                 m.module.modules.each(addMod);
836             }
837             if (m.finalize) {
838                 m.finalize.name = m.name + " (clean up) ";
839                 mods.push(m.finalize);
840             }
841             
842         }
843  
844         parent.modules.each(addMod);
845         //this.allmods = mods;
846         //console.log(mods);
847         //return;
848         if (!mods.length) {
849             if (onComplete) onComplete();
850             return;
851         }
852         // flash it up as modal - so we store the mask!?
853         Ext.MessageBox.show({ title: 'loading' });
854         Ext.MessageBox.show({
855            title: "Please wait...",
856            msg: "Building Interface...",
857            width:450,
858            progress:true,
859            closable:false,
860            modal: false
861           
862         });
863         var n = 0;
864         var progressRun = function() {
865             
866             var mod = mods[n];
867             
868             
869             Ext.MessageBox.updateProgress(
870                 (n+1)/mods.length,  "Building Interface " + (n+1) + 
871                     " of " + mods.length + 
872                     (mod.name ? (' - ' + mod.name) : '')
873                     );
874             
875             
876             
877             if (typeof(mod) == 'function') {
878                 mod();
879                 
880             } else {
881                 if (mod.parent.layout && !mod.module.disabled) {
882                     mod.module.add(mod.parent.layout, mod.region);    
883                 }
884                 
885             }
886             
887             
888             n++;
889             if (n >= mods.length) {
890                 onComplete();  
891                 return;
892             }
893                 
894             
895             progressRun.defer(10, Pman);    
896         }
897         progressRun.defer(1, Pman);
898      
899         
900         
901     },
902     
903     gtranslate : function(str, src, dest, cb) {
904         // load script: 
905         
906         
907         var x = new Roo.data.ScriptTagProxy({ 
908             url:  'http://ajax.googleapis.com/ajax/services/language/translate', 
909             callbackParam : 'callback' 
910         });
911         x.load(
912             {
913                 v: '1.0',
914                 q : str,
915                 langpair : src + '|' +dest
916             }, // end params.
917             { // reader
918                 readRecords : function (o) {
919                     if (!o.responseData) {
920                         return o;
921                     }
922                     return o.responseData.translatedText;
923                 }
924             }, 
925             function (result) {
926                 cb(result);
927             },
928             this,
929             []
930         );
931         
932             
933         
934     } ,
935     invertColor : function(c)
936     {
937         // read..
938         var ca = [];
939         for(var i = 0; i < 3; i++){
940             ca[i] = parseInt(c.charAt((i*2)+1) + c.charAt((i*2)+2), 16);
941         }
942             
943         // invert..
944         var col = '';
945         Roo.each(ca, function(hi) {
946             var h = parseInt(255-hi).toString(16);
947             if(h < 16){
948                 h = '0' + h;
949             }
950             col += h;
951         });
952         return '#' + col;
953         
954     }
955     
956     
957     
958     
959     
960     
961     
962 });
963