3 Modification information for LGPL compliance
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
7 r56989 - 2010-06-16 13:01:33 -0700 (Wed, 16 Jun 2010) - kjing - defunt "Mango" svn dev branch before github cutover
9 r55980 - 2010-04-19 13:31:28 -0700 (Mon, 19 Apr 2010) - kjing - create Mango (6.1) based on windex
11 r51719 - 2009-10-22 10:18:00 -0700 (Thu, 22 Oct 2009) - mitani - Converted to Build 3 tags and updated the build system
13 r51634 - 2009-10-19 13:32:22 -0700 (Mon, 19 Oct 2009) - mitani - Windex is the branch for Sugar Sales 1.0 development
15 r50375 - 2009-08-24 18:07:43 -0700 (Mon, 24 Aug 2009) - dwong - branch kobe2 from tokyo r50372
17 r42807 - 2008-12-29 11:16:59 -0800 (Mon, 29 Dec 2008) - dwong - Branch from trunk/sugarcrm r42806 to branches/tokyo/sugarcrm
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
22 r4085 - 2005-04-13 17:30:42 -0700 (Wed, 13 Apr 2005) - robert - adding meeting scheduler and accept/decline
28 Copyright (c) 2003 Jan-Klaas Kollhof
30 This file is part of the JavaScript o lait library(jsolait).
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.
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.
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
49 Evaluates script in a global scope.
50 @param [0] The code to evaluate.
52 globalEval=function(){
53 return eval(arguments[0]);
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.
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";
77 }else if(arguments.length == 1){
78 classScope = className;
80 className = "anonymous";
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);
90 //This will create a new prototype object of the new class.
91 NewClass.createPrototype = function(){
92 return new NewClass(Class);
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);
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();
105 //reset the constructor for new objects to the actual constructor.
106 NewClass.prototype.constructor = NewClass;
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);
114 if(NewClass.prototype.init==null){
115 NewClass.prototype.init=function(){
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
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);
132 wrapper[n]._name = n;
138 //execute the scope of the class
139 classScope(NewClass.prototype, supr);
143 Class.toString = function(){
144 return "[object Class]";
146 Class.createPrototype=function(){
147 throw "Can't use Class as a super class.";
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.
157 Module = function(name, version, moduleScope){
158 var mod = new Object();
159 mod.version = version;
161 mod.toString=function(){
162 return "[module '%s' version: %s]".format(mod.name, mod.version);
166 Base class for all module-Exceptions.
168 mod.Exception=Class("Exception", function(publ){
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.
174 publ.init=function(msg, trace){
175 this.name = this.constructor.className;
180 publ.toString=function(){
181 var s = "%s %s\n\n".format(this.name, this.module);
186 Returns the complete trace of the exception.
187 @return The error trace.
189 publ.toTraceString=function(){
190 var s = "%s %s:\n ".format(this.name, this.module );
191 s+="%s\n\n".format(this.message);
193 if(this.trace.toTraceString){
194 s+= this.trace.toTraceString();
201 ///The name of the Exception(className).
203 ///The error message.
205 ///The module the Exception belongs to.
207 ///The error which caused the Exception or null.
211 //execute the scope of the module
214 //todo: set classNames for anonymous classes.
216 if(mod[n].className == "anonymous"){
217 mod[n].className = n;
221 if(name != "jsolait"){
222 jsolait.registerModule(mod);
226 Module.toString = function(){
227 return "[object Module]";
229 Module.createPrototype=function(){
230 throw "Can't use Module as a super class.";
235 The root module for jsolait.
236 It provides some global functionality for loading modules,
237 some String enhancements.
239 Module("jsolait", "0.1.0", function(mod){
240 ///The global jsolait object.
243 ///base url for user modules.
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.
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"};
262 if(typeof(WScript) != 'undefined') {
266 // //make jsolait work with WScript
268 // try{//see if WScript is available
277 ///initializes jsolait for using it with WScript
278 var initWS = function(){
285 var args = WScript.arguments;
287 //get script to execute
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("/");
295 throw new mod.Exception("Missing script filename to be run.", e);
298 //location of jsolait/init.js
299 url = WScript.ScriptFullName;
301 if(args(0).replace("file://","").toLowerCase() == url.toLowerCase()){
302 WScript.stderr.write("Can't run myself! exiting ... \n");
305 url = url.replace(/\\/g, "/");
306 url = url.split("/");
307 url = url.slice(0, url.length-1);
308 mod.libURL = "file://" + url.join("/");
310 mod.loadScript(args(0));
312 WScript.stdErr.write("%s(1,1) jsolait runtime error:\n%s\n".format(args(0).replace("file://",""), e.toTraceString()));
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.
325 mod.importModule = function(name){
327 if (mod.modules[name]){ //module already loaded
328 return mod.modules[name];
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);
336 assume it's a user module and located at baseURL
338 modURL = "%s/%s.js".format(mod.baseURL, name.split(".").join("/"));
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);
346 try{//interpret the script
349 throw new mod.ModuleImportFailed(name, modURL, e);
351 //the module should have registered itself
352 return mod.modules[name];
356 importModule = mod.importModule;
359 Loads and interprets a script file.
360 @param url The url of the script to load.
362 mod.loadScript=function(url){
363 var src = getFile(url);
364 try{//to interpret the source
367 throw new mod.EvalFailed(url, e);
371 Registers a new module.
372 Registered modules can be imported with importModule(...).
373 @param module The module to register.
375 mod.registerModule = function(module){
376 this.modules[module.name] = module;
380 Creates an HTTP request object for retreiving files.
381 @return HTTP request object.
383 var getHTTP=function() {
385 try{ //to get the mozilla httprequest object
386 obj = new XMLHttpRequest();
388 try{ //to get MS HTTP request object
389 obj=new ActiveXObject("Msxml2.XMLHTTP.4.0");
391 try{ //to get MS HTTP request object
392 obj=new ActiveXObject("Msxml2.XMLHTTP");
394 try{// to get the old MS HTTP request object
395 obj = new ActiveXObject("microsoft.XMLHTTP");
397 throw new mod.Exception("Unable to get an HTTP request object.");
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.
410 var getFile=function(url, headers) {
411 //if callback is defined then the operation is done async
412 headers = (headers != null) ? headers : [];
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]);
422 throw new mod.Exception("Unable to load URL: '%s'.".format(url), e);
424 if(xmlhttp.status == 200 || xmlhttp.status == 0){
425 return xmlhttp.responseText;
427 throw new mod.Exception("File not loaded: '%s'.".format(url));
431 Error.prototype.toTraceString = function(){
433 return "%s\n".format(this.message);
435 if (this.description){
436 return "%s\n".format(this.description);
438 return "unknown error\n";
443 Thrown when a module could not be found.
445 mod.ModuleImportFailed=Class(mod.Exception, function(publ, supr){
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.
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;
457 ///The name of the module that was not found.
459 ///The url the module was expected to be found at.
464 Thrown when a source could not be loaded due to an interpretation error.
466 mod.EvalFailed=Class(mod.Exception, function(publ, supr){
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.
472 publ.init=function(url, trace){
473 supr(this).init("File '%s' Eval of script failed.".format(url), trace);
476 ///The url the module was expected to be found at.
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.
485 mod.reportException=function(exception){
486 if(exception.toTraceString){
487 var s= exception.toTraceString();
489 var s = exception.toString();
492 try{//see if WScript is available
497 WScript.stderr.write(s);
502 ///The global exception report method;
503 reportException = mod.reportException;
508 String formatting module.
509 It allows python like string formatting ("some text %s" % "something").
510 Also similar to sprintf from C.
512 Module("stringformat", "0.1.0", function(mod){
514 Creates a format specifier object.
516 var FormatSpecifier=function(s){
517 var s = s.match(/%(\(\w+\)){0,1}([ 0-]){0,1}(\+){0,1}(\d+){0,1}(\.\d+){0,1}(.)/);
519 this.key=s[1].slice(1,-1);
523 this.paddingFlag = s[2];
524 if(this.paddingFlag==""){
525 this.paddingFlag =" "
527 this.signed=(s[3] == "+");
528 this.minLength = parseInt(s[4]);
529 if(isNaN(this.minLength)){
533 this.percision = parseInt(s[5].slice(1,s[5].length));
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.
545 resultString = formatString.format(value1, v2, ...);
547 Each formatString can contain any number of formatting specifiers which are
548 replaced with the formated values.
550 specifier([...]-items are optional):
551 "%(key)[flag][sign][min][percision]typeOfValue"
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.
557 0 Use 0s for padding.
558 - Left justify result, padding it with spaces.
559 Use spaces for padding.
561 + Numeric values will contain a +|- infront of the number.
563 l The string will be padded with the padding character until it has a minimum length of l.
565 .x Where x is the percision for floating point numbers and the lenght for 0 padding for integers.
567 d Signed integer decimal.
568 i Signed integer decimal.
569 b Unsigned binary. //This does not exist in python!
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()).
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"
586 @param * Each parameter is treated as a formating value.
587 @return The formated String.
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);
592 if(sf.join("") != this){
593 throw new mod.Exception("Unsupported formating string.");
596 throw new mod.Exception("Unsupported formating string.");
605 for(var i=0;i<sf.length;i++){
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];
615 throw new mod.Exception("Object or associative array expected as formating value.");
617 }else{//get the current value
618 if(cnt>=arguments.length){
619 throw new mod.Exception("Not enough arguments for format string");
626 if(frmt.type == "s"){//String
630 s=obj.toString().pad(frmt.paddingFlag, frmt.minLength);
632 }else if(frmt.type == "c"){//Character
633 if(frmt.paddingFlag == "0"){
634 frmt.paddingFlag=" ";//padding only spaces
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"){
641 make sure it's a single character
643 s=obj.pad(frmt.paddingFlag, frmt.minLength);
645 throw new mod.Exception("Character of length 1 required.");
648 throw new mod.Exception("Character or Byte required.");
650 }else if(typeof obj == "number"){
651 //get sign of the number
654 sign = "-"; //negative signs are always needed
655 }else if(frmt.signed){
656 sign = "+"; // if sign is always wanted add it
660 //do percision padding and number conversions
664 if(frmt.percision > -1){
665 s = obj.toFixed(frmt.percision).toString();
670 case "E"://exponential
672 if(frmt.percision > -1){
673 s = obj.toExponential(frmt.percision);
675 s = obj.toExponential();
677 s = s.replace("e", frmt.type);
681 s = s.pad("0", frmt.percision);
685 s = s.pad("0", frmt.percision);
687 case "x"://hexadecimal
688 s = obj.toString(16).toLowerCase();
689 s = s.pad("0", frmt.percision);
691 case "X"://hexadecimal
692 s = obj.toString(16).toUpperCase();
693 s = s.pad("0", frmt.percision);
696 s = parseInt(obj).toString();
697 s = s.pad("0", frmt.percision);
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);
704 s=sign + s;//add sign
705 s=s.pad(frmt.paddingFlag, frmt.minLength);//do padding and justifiing
707 throw new mod.Exception("Number required.");
716 Padds a String with a character to have a minimum length.
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.
722 String.prototype.pad = function(flag, len){
729 for(var i=0;i<len-this.length;i++){
742 @param c The count how often the string should be repeated.
744 String.prototype.mul = function(c){
745 var a = new Array(this.length * c);
747 for(var i=0;i<c;i++){
753 //let jsolait do some startup initialization