]> CyberLeo.Net >> Repos - Github/sugarcrm.git/blob - jssource/src_files/include/jsolait/init.js
Release 6.2.1
[Github/sugarcrm.git] / jssource / src_files / include / jsolait / init.js
1 /*
2
3 Modification information for LGPL compliance
4
5 r56990 - 2010-06-16 13:05:36 -0700 (Wed, 16 Jun 2010) - kjing - snapshot "Mango" svn branch to a new one for GitHub sync
6
7 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
8
9 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
10
11 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3  tags and updated the build system 
12
13 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
14
15 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
16
17 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
18
19 r11496 - 2006-02-03 12:16:49 -0800 (Fri, 03 Feb 2006) - chris - Bug 4538: found 2 non-breaking, IE specific JS errors in sugar_3.js and init.js, added some logic to detect whether the browser supports IE activeX stuff and to run code appropriately.
20 Touched sugar_3.js and include/jsolait/init.js
21
22 r4085 - 2005-04-13 17:30:42 -0700 (Wed, 13 Apr 2005) - robert - adding meeting scheduler and accept/decline
23
24
25 */
26
27 /*
28   Copyright (c) 2003 Jan-Klaas Kollhof
29   
30   This file is part of the JavaScript o lait library(jsolait).
31   
32   jsolait is free software; you can redistribute it and/or modify
33   it under the terms of the GNU Lesser General Public License as published by
34   the Free Software Foundation; either version 2.1 of the License, or
35   (at your option) any later version.
36  
37   This software is distributed in the hope that it will be useful,
38   but WITHOUT ANY WARRANTY; without even the implied warranty of
39   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
40   GNU Lesser General Public License for more details.
41  
42   You should have received a copy of the GNU Lesser General Public License
43   along with this software; if not, write to the Free Software
44   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
45 */
46
47
48 /**    
49     Evaluates script in a global scope.
50     @param [0]  The code to evaluate.
51 */
52 globalEval=function(){
53     return eval(arguments[0]);
54 }
55
56
57 /**
58     Creates a new class object which inherits from superClass.
59     @param className="anonymous"  The name of the new class.
60                                                   If the created class is a public member of a module then 
61                                                   the className is automatically set.
62     @param superClass=Object        The class to inherit from (super class).
63     @param classScope                  A function which is executed for class construction.
64                                                 As 1st parameter it will get the new class' protptype for 
65                                                 overrideing or extending the super class. As 2nd parameter it will get
66                                                 the super class' wrapper for calling inherited methods.
67 */
68 Class = function(className, superClass, classScope){
69     if(arguments.length == 2){
70         classScope = superClass;
71         if(typeof className != "string"){
72             superClass = className;
73             className = "anonymous";
74         }else{
75             superClass = Object;
76         }
77     }else if(arguments.length == 1){
78         classScope = className;
79         superClass = Object;
80         className = "anonymous";
81     }
82     
83     //this is the constructor for the new objects created from the new class.
84     //if and only if it is NOT used for prototyping/subclassing the init method of the newly created object will be called.
85     var NewClass = function(calledBy){
86         if(calledBy !== Class){
87             return this.init.apply(this, arguments);
88         }
89     }
90     //This will create a new prototype object of the new class.
91     NewClass.createPrototype = function(){
92         return new NewClass(Class);
93     }
94     //setting class properties for the new class.
95     NewClass.superClass = superClass;
96     NewClass.className=className; 
97     NewClass.toString = function(){
98         return "[class %s]".format(NewClass.className);
99     };
100     if(superClass.createPrototype!=null){//see if the super class can create prototypes. (creating an object without calling init())
101         NewClass.prototype = superClass.createPrototype();
102     }else{//just create an object of the super class
103         NewClass.prototype = new superClass();
104     }
105     //reset the constructor for new objects to the actual constructor.
106     NewClass.prototype.constructor = NewClass;
107     
108     if(superClass == Object){//all other objects already have a nice toString method.
109         NewClass.prototype.toString = function(){
110             return "[object %s]".format(this.constructor.className);
111         };
112     }
113     
114     if(NewClass.prototype.init==null){
115         NewClass.prototype.init=function(){
116         }
117     }
118    
119     
120     //create a supr  function to be used to call methods of the super class
121     var supr = function(self){
122         //set up super class functionality  so a call to super(this) will return an object with all super class methods 
123         //the methods can be called like super(this).foo and the this object will be bound to that method
124         var wrapper = {};
125         var superProto = superClass.prototype;
126         for(var n in superProto){
127             if(typeof superProto[n] == "function"){
128                  wrapper[n] = function(){
129                     var f = arguments.callee;
130                     return superProto[f._name].apply(self, arguments);
131                 }
132                 wrapper[n]._name = n;
133             }
134         }
135         return wrapper;
136     }
137         
138     //execute the scope of the class
139     classScope(NewClass.prototype, supr);
140     
141     return NewClass;
142 }    
143 Class.toString = function(){
144     return "[object Class]";
145 }
146 Class.createPrototype=function(){ 
147     throw "Can't use Class as a super class.";
148 }
149
150 /**
151     Creates a new module and registers it.
152     @param name              The name of the module.
153     @param version            The version of a module.
154     @param moduleScope    A function which is executed for module creation.
155                                      As 1st parameter it will get the module variable.                                     
156 */
157 Module = function(name, version, moduleScope){
158     var mod = new Object();
159     mod.version = version;
160     mod.name = name;
161     mod.toString=function(){
162         return "[module '%s' version: %s]".format(mod.name, mod.version);
163     }
164     
165     /**
166         Base class for all module-Exceptions.
167     */
168     mod.Exception=Class("Exception", function(publ){
169         /**
170             Initializes a new Exception.
171             @param msg           The error message for the user.
172             @param trace=null   The error causing this Exception if available.
173         */
174         publ.init=function(msg, trace){
175             this.name = this.constructor.className;
176             this.message = msg;
177             this.trace = trace;
178         }
179         
180         publ.toString=function(){
181             var s = "%s %s\n\n".format(this.name, this.module);
182             s += this.message;
183             return s;
184         }
185         /**
186             Returns the complete trace of the exception.
187             @return The error trace.
188         */
189         publ.toTraceString=function(){
190             var s = "%s %s:\n    ".format(this.name, this.module );
191             s+="%s\n\n".format(this.message);
192             if(this.trace){
193                 if(this.trace.toTraceString){
194                     s+= this.trace.toTraceString();
195                 }else{
196                     s+= this.trace;
197                 }
198             }
199             return s;
200         }
201         ///The name of the Exception(className).
202         publ.name;
203         ///The error message.
204         publ.message;
205         ///The module the Exception belongs to.
206         publ.module = mod;
207         ///The error which caused the Exception or null.
208         publ.trace;      
209     })
210     
211     //execute the scope of the module
212     moduleScope(mod);
213     
214     //todo: set classNames for anonymous classes.
215     for(var n in mod){
216         if(mod[n].className == "anonymous"){
217             mod[n].className = n;
218         }
219     }
220     
221     if(name != "jsolait"){
222         jsolait.registerModule(mod);
223     }
224     return mod;
225 }
226 Module.toString = function(){
227     return "[object Module]";
228 }
229 Module.createPrototype=function(){ 
230     throw "Can't use Module as a super class.";
231 }
232
233 //docstart
234 /**
235     The root module for jsolait.
236     It provides some global functionality for loading modules,
237     some String enhancements.
238 */
239 Module("jsolait", "0.1.0", function(mod){
240     ///The global jsolait object.
241     jsolait=mod;
242     
243     ///base url for user modules.
244     mod.baseURL=".";
245     ///The URL where jsolait is installed.
246     mod.libURL ="./jsolait";
247     ///Collection of all loaded modules.(module cache)
248     mod.modules = new Array();
249     ///The URLs of there the modules, part of jsolait.
250     mod.moduleURLs = {};
251 /*
252     mod.moduleURLs = {urllib:"%(libURL)s/lib/urllib.js",
253                                       xml:"%(libURL)s/lib/xml.js",
254                                       crypto:"%(libURL)s/lib/crypto.js",
255                                       codecs:"%(libURL)s/lib/codecs.js",
256                                       jsonrpc:"%(libURL)s/lib/jsonrpc.js",
257                                       lang:"%(libURL)s/lib/lang.js",
258                                       xmlrpc:"%(libURL)s/lib/xmlrpc.js"};
259 */
260    
261     mod.init=function(){
262         if(typeof(WScript) != 'undefined') {
263             initWS();
264                 }
265         
266 //        //make jsolait work with WScript
267 //        var ws = null;
268 //        try{//see if WScript is available
269 //            ws = WScript;
270 //        }catch(e){
271 //        }
272 //        if(ws != null){
273 //            initWS();
274 //        }
275     }
276     
277     ///initializes jsolait for using it with WScript
278     var initWS = function(){
279         print=function(msg){
280             WScript.echo(msg);
281         }
282         alert=function(msg){
283             print(msg);
284         }
285         var args = WScript.arguments;
286         try{
287             //get script to execute
288             var url = args(0);
289             url = url.replace(/\\/g, "/");
290             url = url.split("/");
291             url = url.slice(0, url.length-1);
292             //set base for user module loading
293             mod.baseURL = url.join("/");
294         }catch(e){
295             throw new mod.Exception("Missing script filename to be run.", e);
296         }
297         
298         //location of jsolait/init.js
299         url = WScript.ScriptFullName;
300         
301         if(args(0).replace("file://","").toLowerCase() == url.toLowerCase()){
302             WScript.stderr.write("Can't run myself! exiting ... \n");
303             return;
304         }
305         url = url.replace(/\\/g, "/");
306         url = url.split("/");
307         url = url.slice(0, url.length-1);
308         mod.libURL = "file://" + url.join("/");
309         try{
310             mod.loadScript(args(0));
311         }catch(e){
312             WScript.stdErr.write("%s(1,1) jsolait runtime error:\n%s\n".format(args(0).replace("file://",""), e.toTraceString()));
313         }
314     }
315     
316     
317     /**
318        Imports a module given its name(someModule.someSubModule).
319        A module's file location is determined by treating each module name as a directory.
320        Only the last one points to a file.
321        If the module's URL is not known to jsolait then it will be searched for in jsolait.baseURL which is "." by default.
322        @param name   The name of the module to load.
323        @return           The module object.
324     */
325     mod.importModule = function(name){
326
327         if (mod.modules[name]){ //module already loaded
328             return mod.modules[name];
329         }else{
330             var src,modURL;
331             //check if jsolait already knows the url of the module(moduleURLs contains urls to modules)
332             if(mod.moduleURLs[name]){
333                 modURL = mod.moduleURLs[name].format(mod);
334             }else{
335 /*
336                assume it's a user module and located at baseURL
337 */
338                 modURL = "%s/%s.js".format(mod.baseURL, name.split(".").join("/"));
339             }  
340             try{//to load module from location calculated above
341                 src = getFile(modURL);
342             }catch(e){//module could not be found at the location.
343                 throw new mod.ModuleImportFailed(name, modURL, e);
344             }
345             
346             try{//interpret the script
347                 globalEval(src);
348             }catch(e){
349                 throw new mod.ModuleImportFailed(name, modURL, e);
350             }
351             //the module should have registered itself
352             return mod.modules[name]; 
353         }
354     }
355     //make it global
356     importModule = mod.importModule;
357     
358     /**
359         Loads and interprets a script file.
360         @param url  The url of the script to load.
361     */
362     mod.loadScript=function(url){
363         var src = getFile(url);
364         try{//to interpret the source 
365             globalEval(src);
366         }catch(e){
367             throw new mod.EvalFailed(url, e);
368         }
369     }
370     /**
371         Registers a new module. 
372         Registered modules can be imported with importModule(...).
373         @param module  The module to register.
374     */
375     mod.registerModule = function(module){
376         this.modules[module.name] = module;
377     }
378     
379     /**
380         Creates an HTTP request object for retreiving files.
381         @return HTTP request object.
382     */
383     var getHTTP=function() {
384         var obj;
385         try{ //to get the mozilla httprequest object
386             obj = new XMLHttpRequest();
387         }catch(e){
388             try{ //to get MS HTTP request object
389                 obj=new ActiveXObject("Msxml2.XMLHTTP.4.0");
390             }catch(e){
391                 try{ //to get MS HTTP request object
392                     obj=new ActiveXObject("Msxml2.XMLHTTP");
393                 }catch(e){
394                     try{// to get the old MS HTTP request object
395                         obj = new ActiveXObject("microsoft.XMLHTTP"); 
396                     }catch(e){
397                         throw new mod.Exception("Unable to get an HTTP request object.");
398                     }
399                 }    
400             }
401         }
402         return obj;
403     }
404     /**
405         Retrieves a file given its URL.
406         @param url             The url to load.
407         @param headers=[]  The headers to use.
408         @return                 The content of the file.
409     */
410     var getFile=function(url, headers) { 
411         //if callback is defined then the operation is done async
412         headers = (headers != null) ? headers : [];
413         //setup the request
414         try{
415             var xmlhttp= getHTTP();
416             xmlhttp.open("GET", url, false);
417             for(var i=0;i< headers.length;i++){
418                 xmlhttp.setRequestHeader(headers[i][0], headers[i][1]);    
419             }
420             xmlhttp.send("");
421         }catch(e){
422             throw new mod.Exception("Unable to load URL: '%s'.".format(url), e);
423         }
424         if(xmlhttp.status == 200 || xmlhttp.status == 0){
425             return xmlhttp.responseText;
426         }else{
427              throw new mod.Exception("File not loaded: '%s'.".format(url));
428         }
429     }
430     
431     Error.prototype.toTraceString = function(){
432         if(this.message){
433             return "%s\n".format(this.message);
434         }
435         if (this.description){
436            return "%s\n".format(this.description);
437         }
438         return "unknown error\n"; 
439     }
440    
441     
442     /**
443         Thrown when a module could not be found.
444     */
445     mod.ModuleImportFailed=Class(mod.Exception, function(publ, supr){
446         /**
447             Initializes a new ModuleImportFailed Exception.
448             @param name      The name of the module.
449             @param url          The url of the module.
450             @param trace      The error cousing this Exception.
451         */
452         publ.init=function(moduleName, url, trace){
453             supr(this).init("Failed to import module: '%s' from URL:'%s'".format(moduleName, url), trace);
454             this.moduleName = moduleName;
455             this.url = url;
456         }
457         ///The  name of the module that was not found.
458         publ.moduleName;
459         ///The url the module was expected to be found at.
460         publ.url;
461     })
462     
463     /**
464         Thrown when a source could not be loaded due to an interpretation error.
465     */
466     mod.EvalFailed=Class(mod.Exception, function(publ, supr){
467         /**
468             Initializes a new EvalFailed exception.
469             @param url                   The url of the module.
470             @param trace               The exception that was thrown while interpreting the module's source code.
471         */
472         publ.init=function(url, trace){
473             supr(this).init("File '%s' Eval of script failed.".format(url), trace);
474             this.url = url;
475         }
476         ///The url the module was expected to be found at.
477         publ.url;
478     })
479     
480     /**
481         Displays an exception and it's trace.
482         This works better than alert(e) because traces are taken into account.
483         @param exception  The exception to display.
484     */
485     mod.reportException=function(exception){
486         if(exception.toTraceString){
487             var s= exception.toTraceString();
488         }else{
489             var s = exception.toString();
490         }
491         var ws = null;
492         try{//see if WScript is available
493             ws = WScript;
494         }catch(e){
495         }
496         if(ws != null){
497             WScript.stderr.write(s);
498         }else{
499             alert(s);
500         }
501     }    
502     ///The global exception report method;
503     reportException = mod.reportException;
504 })
505
506 //stringmod
507 /**
508     String formatting module.
509     It allows python like string formatting ("some text %s" % "something").
510     Also similar to sprintf from C.
511 */
512 Module("stringformat", "0.1.0", function(mod){
513     /**
514         Creates a format specifier object. 
515     */
516     var FormatSpecifier=function(s){
517         var s = s.match(/%(\(\w+\)){0,1}([ 0-]){0,1}(\+){0,1}(\d+){0,1}(\.\d+){0,1}(.)/);
518         if(s[1]){
519             this.key=s[1].slice(1,-1);
520         }else{
521             this.key = null;
522         }
523         this.paddingFlag = s[2];
524         if(this.paddingFlag==""){
525             this.paddingFlag =" " 
526         }
527         this.signed=(s[3] == "+");
528         this.minLength = parseInt(s[4]);
529         if(isNaN(this.minLength)){
530             this.minLength=0;
531         }
532         if(s[5]){
533             this.percision = parseInt(s[5].slice(1,s[5].length));
534         }else{
535             this.percision=-1;
536         }
537         this.type = s[6];
538     }
539
540     /**
541         Formats a string replacing formatting specifiers with values provided as arguments
542         which are formatted according to the specifier.
543         This is an implementation of  python's % operator for strings and is similar to sprintf from C.
544         Usage:
545             resultString = formatString.format(value1, v2, ...);
546         
547         Each formatString can contain any number of formatting specifiers which are
548         replaced with the formated values.
549         
550         specifier([...]-items are optional): 
551             "%(key)[flag][sign][min][percision]typeOfValue"
552             
553             (key)  If specified the 1st argument is treated as an object/associative array and the formating values 
554                      are retrieved from that object using the key.
555                 
556             flag:
557                 0      Use 0s for padding.
558                 -      Left justify result, padding it with spaces.
559                         Use spaces for padding.
560             sign:
561                 +      Numeric values will contain a +|- infront of the number.
562             min:
563                 l      The string will be padded with the padding character until it has a minimum length of l. 
564             percision:
565                .x     Where x is the percision for floating point numbers and the lenght for 0 padding for integers.
566             typeOfValue:
567                 d    Signed integer decimal.     
568                 i     Signed integer decimal.    
569                 b    Unsigned binary.                       //This does not exist in python!
570                 o    Unsigned octal.    
571                 u    Unsigned decimal.   
572                 x    Unsigned hexidecimal (lowercase).  
573                 X   Unsigned hexidecimal (uppercase).   
574                 e   Floating point exponential format (lowercase).       
575                 E   Floating point exponential format (uppercase).       
576                 f    Floating point decimal format.      
577                 F   Floating point decimal format.       
578                 c   Single character (accepts byte or single character string).          
579                 s   String (converts any object using object.toString()).       
580         
581         Examples:
582             "%02d".format(8) == "08"
583             "%05.2f".format(1.234) == "01.23"
584             "123 in binary is: %08b".format(123) == "123 in binary is: 01111011"
585             
586         @param *  Each parameter is treated as a formating value. 
587         @return The formated String.
588     */
589     String.prototype.format=function(){
590         var sf = this.match(/(%(\(\w+\)){0,1}[ 0-]{0,1}(\+){0,1}(\d+){0,1}(\.\d+){0,1}[dibouxXeEfFgGcrs%])|([^%]+)/g);
591         if(sf){
592             if(sf.join("") != this){
593                 throw new mod.Exception("Unsupported formating string.");
594             }
595         }else{
596             throw new mod.Exception("Unsupported formating string.");
597         }
598         var rslt ="";
599         var s;
600         var obj;
601         var cnt=0;
602         var frmt;
603         var sign="";
604         
605         for(var i=0;i<sf.length;i++){
606             s=sf[i];
607             if(s == "%%"){
608                 s = "%";
609             }else if(s.slice(0,1) == "%"){
610                 frmt = new FormatSpecifier(s);//get the formating object
611                 if(frmt.key){//an object was given as formating value
612                     if((typeof arguments[0]) == "object" && arguments.length == 1){
613                         obj = arguments[0][frmt.key];
614                     }else{
615                         throw new mod.Exception("Object or associative array expected as formating value.");
616                     }
617                 }else{//get the current value
618                     if(cnt>=arguments.length){
619                         throw new mod.Exception("Not enough arguments for format string");
620                     }else{
621                         obj=arguments[cnt];
622                         cnt++;
623                     }
624                 }
625                     
626                 if(frmt.type == "s"){//String
627                     if (obj == null){
628                         obj = "null";
629                     }
630                     s=obj.toString().pad(frmt.paddingFlag, frmt.minLength);
631                     
632                 }else if(frmt.type == "c"){//Character
633                     if(frmt.paddingFlag == "0"){
634                         frmt.paddingFlag=" ";//padding only spaces
635                     }
636                     if(typeof obj == "number"){//get the character code
637                         s = String.fromCharCode(obj).pad(frmt.paddingFlag , frmt.minLength) ;
638                     }else if(typeof obj == "string"){
639                         if(obj.length == 1){
640 /*
641 make sure it's a single character
642 */
643                             s=obj.pad(frmt.paddingFlag, frmt.minLength);
644                         }else{
645                             throw new mod.Exception("Character of length 1 required.");
646                         }
647                     }else{
648                         throw new mod.Exception("Character or Byte required.");
649                     }
650                 }else if(typeof obj == "number"){
651                     //get sign of the number
652                     if(obj < 0){
653                         obj = -obj;
654                         sign = "-"; //negative signs are always needed
655                     }else if(frmt.signed){
656                         sign = "+"; // if sign is always wanted add it 
657                     }else{
658                         sign = "";
659                     }
660                     //do percision padding and number conversions
661                     switch(frmt.type){
662                         case "f": //floats
663                         case "F":
664                             if(frmt.percision > -1){
665                                 s = obj.toFixed(frmt.percision).toString();
666                             }else{
667                                 s = obj.toString();
668                             }
669                             break;
670                         case "E"://exponential
671                         case "e":
672                             if(frmt.percision > -1){
673                                 s = obj.toExponential(frmt.percision);
674                             }else{
675                                 s = obj.toExponential();
676                             }
677                             s = s.replace("e", frmt.type);
678                             break;
679                         case "b"://binary
680                             s = obj.toString(2);
681                             s = s.pad("0", frmt.percision);
682                             break;
683                         case "o"://octal
684                             s = obj.toString(8);
685                             s = s.pad("0", frmt.percision);
686                             break;
687                         case "x"://hexadecimal
688                             s = obj.toString(16).toLowerCase();
689                             s = s.pad("0", frmt.percision);
690                             break;
691                         case "X"://hexadecimal
692                             s = obj.toString(16).toUpperCase();
693                             s = s.pad("0", frmt.percision);
694                             break;
695                         default://integers
696                             s = parseInt(obj).toString();
697                             s = s.pad("0", frmt.percision);
698                             break;
699                     }
700                     if(frmt.paddingFlag == "0"){//do 0-padding
701                         //make sure that the length of the possible sign is not ignored
702                         s=s.pad("0", frmt.minLength - sign.length);
703                     }
704                     s=sign + s;//add sign
705                     s=s.pad(frmt.paddingFlag, frmt.minLength);//do padding and justifiing
706                 }else{
707                     throw new mod.Exception("Number required.");
708                 }
709             }
710             rslt += s;
711         }
712         return rslt;
713     }
714     
715     /**
716         Padds a String with a character to have a minimum length.
717         
718         @param flag   "-":      to padd with " " and left justify the string.
719                             Other: the character to use for padding. 
720         @param len    The minimum length of the resulting string.
721     */
722     String.prototype.pad = function(flag, len){
723         var s = "";
724         if(flag == "-"){
725             var c = " ";
726         }else{
727             var c = flag;
728         }
729         for(var i=0;i<len-this.length;i++){
730             s += c;
731         }
732         if(flag == "-"){
733             s = this + s;
734         }else{
735             s += this;
736         }
737         return s;
738     }
739     
740     /**
741         Repeats a string.
742         @param c  The count how often the string should be repeated.
743     */
744     String.prototype.mul = function(c){
745         var a = new Array(this.length * c);
746         var s=""+ this;
747         for(var i=0;i<c;i++){
748             a[i] = s;
749         }
750         return a.join("");
751     }
752 })
753 //let jsolait do some startup initialization
754 jsolait.init();
755