dom/tests/mochitest/ajax/mochikit/MochiKit/Base.js

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /***
     3 MochiKit.Base 1.4
     5 See <http://mochikit.com/> for documentation, downloads, license, etc.
     7 (c) 2005 Bob Ippolito.  All rights Reserved.
     9 ***/
    11 if (typeof(dojo) != 'undefined') {
    12     dojo.provide("MochiKit.Base");
    13 }
    14 if (typeof(MochiKit) == 'undefined') {
    15     MochiKit = {};
    16 }
    17 if (typeof(MochiKit.Base) == 'undefined') {
    18     MochiKit.Base = {};
    19 }
    20 if (typeof(MochiKit.__export__) == "undefined") {
    21     MochiKit.__export__ = (MochiKit.__compat__  ||
    22         (typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
    23     );
    24 }
    26 MochiKit.Base.VERSION = "1.4";
    27 MochiKit.Base.NAME = "MochiKit.Base";
    28 /** @id MochiKit.Base.update */
    29 MochiKit.Base.update = function (self, obj/*, ... */) {
    30     if (self === null) {
    31         self = {};
    32     }
    33     for (var i = 1; i < arguments.length; i++) {
    34         var o = arguments[i];
    35         if (typeof(o) != 'undefined' && o !== null) {
    36             for (var k in o) {
    37                 self[k] = o[k];
    38             }
    39         }
    40     }
    41     return self;
    42 };
    44 MochiKit.Base.update(MochiKit.Base, {
    45     __repr__: function () {
    46         return "[" + this.NAME + " " + this.VERSION + "]";
    47     },
    49     toString: function () {
    50         return this.__repr__();
    51     },
    53     /** @id MochiKit.Base.camelize */
    54     camelize: function (selector) {
    55         /* from dojo.style.toCamelCase */
    56         var arr = selector.split('-');
    57         var cc = arr[0];
    58         for (var i = 1; i < arr.length; i++) {
    59             cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
    60         }
    61         return cc;
    62     },
    64     /** @id MochiKit.Base.counter */
    65     counter: function (n/* = 1 */) {
    66         if (arguments.length === 0) {
    67             n = 1;
    68         }
    69         return function () {
    70             return n++;
    71         };
    72     },
    74     /** @id MochiKit.Base.clone */
    75     clone: function (obj) {
    76         var me = arguments.callee;
    77         if (arguments.length == 1) {
    78             me.prototype = obj;
    79             return new me();
    80         }
    81     },
    83     _flattenArray: function (res, lst) {
    84         for (var i = 0; i < lst.length; i++) {
    85             var o = lst[i];
    86             if (o instanceof Array) {
    87                 arguments.callee(res, o);
    88             } else {
    89                 res.push(o);
    90             }
    91         }
    92         return res;
    93     },
    95     /** @id MochiKit.Base.flattenArray */
    96     flattenArray: function (lst) {
    97         return MochiKit.Base._flattenArray([], lst);
    98     },
   100     /** @id MochiKit.Base.flattenArguments */
   101     flattenArguments: function (lst/* ...*/) {
   102         var res = [];
   103         var m = MochiKit.Base;
   104         var args = m.extend(null, arguments);
   105         while (args.length) {
   106             var o = args.shift();
   107             if (o && typeof(o) == "object" && typeof(o.length) == "number") {
   108                 for (var i = o.length - 1; i >= 0; i--) {
   109                     args.unshift(o[i]);
   110                 }
   111             } else {
   112                 res.push(o);
   113             }
   114         }
   115         return res;
   116     },
   118     /** @id MochiKit.Base.extend */
   119     extend: function (self, obj, /* optional */skip) {
   120         // Extend an array with an array-like object starting
   121         // from the skip index
   122         if (!skip) {
   123             skip = 0;
   124         }
   125         if (obj) {
   126             // allow iterable fall-through, but skip the full isArrayLike
   127             // check for speed, this is called often.
   128             var l = obj.length;
   129             if (typeof(l) != 'number' /* !isArrayLike(obj) */) {
   130                 if (typeof(MochiKit.Iter) != "undefined") {
   131                     obj = MochiKit.Iter.list(obj);
   132                     l = obj.length;
   133                 } else {
   134                     throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
   135                 }
   136             }
   137             if (!self) {
   138                 self = [];
   139             }
   140             for (var i = skip; i < l; i++) {
   141                 self.push(obj[i]);
   142             }
   143         }
   144         // This mutates, but it's convenient to return because
   145         // it's often used like a constructor when turning some
   146         // ghetto array-like to a real array
   147         return self;
   148     },
   151     /** @id MochiKit.Base.updatetree */
   152     updatetree: function (self, obj/*, ...*/) {
   153         if (self === null) {
   154             self = {};
   155         }
   156         for (var i = 1; i < arguments.length; i++) {
   157             var o = arguments[i];
   158             if (typeof(o) != 'undefined' && o !== null) {
   159                 for (var k in o) {
   160                     var v = o[k];
   161                     if (typeof(self[k]) == 'object' && typeof(v) == 'object') {
   162                         arguments.callee(self[k], v);
   163                     } else {
   164                         self[k] = v;
   165                     }
   166                 }
   167             }
   168         }
   169         return self;
   170     },
   172     /** @id MochiKit.Base.setdefault */
   173     setdefault: function (self, obj/*, ...*/) {
   174         if (self === null) {
   175             self = {};
   176         }
   177         for (var i = 1; i < arguments.length; i++) {
   178             var o = arguments[i];
   179             for (var k in o) {
   180                 if (!(k in self)) {
   181                     self[k] = o[k];
   182                 }
   183             }
   184         }
   185         return self;
   186     },
   188     /** @id MochiKit.Base.keys */
   189     keys: function (obj) {
   190         var rval = [];
   191         for (var prop in obj) {
   192             rval.push(prop);
   193         }
   194         return rval;
   195     },
   197     /** @id MochiKit.Base.values */
   198     values: function (obj) {
   199         var rval = [];
   200         for (var prop in obj) {
   201             rval.push(obj[prop]);
   202         }
   203         return rval;
   204     },
   206      /** @id MochiKit.Base.items */
   207     items: function (obj) {
   208         var rval = [];
   209         var e;
   210         for (var prop in obj) {
   211             var v;
   212             try {
   213                 v = obj[prop];
   214             } catch (e) {
   215                 continue;
   216             }
   217             rval.push([prop, v]);
   218         }
   219         return rval;
   220     },
   223     _newNamedError: function (module, name, func) {
   224         func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name);
   225         module[name] = func;
   226     },
   229     /** @id MochiKit.Base.operator */
   230     operator: {
   231         // unary logic operators
   232         /** @id MochiKit.Base.truth */
   233         truth: function (a) { return !!a; },
   234         /** @id MochiKit.Base.lognot */
   235         lognot: function (a) { return !a; },
   236         /** @id MochiKit.Base.identity */
   237         identity: function (a) { return a; },
   239         // bitwise unary operators
   240         /** @id MochiKit.Base.not */
   241         not: function (a) { return ~a; },
   242         /** @id MochiKit.Base.neg */
   243         neg: function (a) { return -a; },
   245         // binary operators
   246         /** @id MochiKit.Base.add */
   247         add: function (a, b) { return a + b; },
   248         /** @id MochiKit.Base.sub */
   249         sub: function (a, b) { return a - b; },
   250         /** @id MochiKit.Base.div */
   251         div: function (a, b) { return a / b; },
   252         /** @id MochiKit.Base.mod */
   253         mod: function (a, b) { return a % b; },
   254         /** @id MochiKit.Base.mul */
   255         mul: function (a, b) { return a * b; },
   257         // bitwise binary operators
   258         /** @id MochiKit.Base.and */
   259         and: function (a, b) { return a & b; },
   260         /** @id MochiKit.Base.or */
   261         or: function (a, b) { return a | b; },
   262         /** @id MochiKit.Base.xor */
   263         xor: function (a, b) { return a ^ b; },
   264         /** @id MochiKit.Base.lshift */
   265         lshift: function (a, b) { return a << b; },
   266         /** @id MochiKit.Base.rshift */
   267         rshift: function (a, b) { return a >> b; },
   268         /** @id MochiKit.Base.zrshift */
   269         zrshift: function (a, b) { return a >>> b; },
   271         // near-worthless built-in comparators
   272         /** @id MochiKit.Base.eq */
   273         eq: function (a, b) { return a == b; },
   274         /** @id MochiKit.Base.ne */
   275         ne: function (a, b) { return a != b; },
   276         /** @id MochiKit.Base.gt */
   277         gt: function (a, b) { return a > b; },
   278         /** @id MochiKit.Base.ge */
   279         ge: function (a, b) { return a >= b; },
   280         /** @id MochiKit.Base.lt */
   281         lt: function (a, b) { return a < b; },
   282         /** @id MochiKit.Base.le */
   283         le: function (a, b) { return a <= b; },
   285         // strict built-in comparators
   286         seq: function (a, b) { return a === b; },
   287         sne: function (a, b) { return a !== b; },
   289         // compare comparators
   290         /** @id MochiKit.Base.ceq */
   291         ceq: function (a, b) { return MochiKit.Base.compare(a, b) === 0; },
   292         /** @id MochiKit.Base.cne */
   293         cne: function (a, b) { return MochiKit.Base.compare(a, b) !== 0; },
   294         /** @id MochiKit.Base.cgt */
   295         cgt: function (a, b) { return MochiKit.Base.compare(a, b) == 1; },
   296         /** @id MochiKit.Base.cge */
   297         cge: function (a, b) { return MochiKit.Base.compare(a, b) != -1; },
   298         /** @id MochiKit.Base.clt */
   299         clt: function (a, b) { return MochiKit.Base.compare(a, b) == -1; },
   300         /** @id MochiKit.Base.cle */
   301         cle: function (a, b) { return MochiKit.Base.compare(a, b) != 1; },
   303         // binary logical operators
   304         /** @id MochiKit.Base.logand */
   305         logand: function (a, b) { return a && b; },
   306         /** @id MochiKit.Base.logor */
   307         logor: function (a, b) { return a || b; },
   308         /** @id MochiKit.Base.contains */
   309         contains: function (a, b) { return b in a; }
   310     },
   312     /** @id MochiKit.Base.forwardCall */
   313     forwardCall: function (func) {
   314         return function () {
   315             return this[func].apply(this, arguments);
   316         };
   317     },
   319     /** @id MochiKit.Base.itemgetter */
   320     itemgetter: function (func) {
   321         return function (arg) {
   322             return arg[func];
   323         };
   324     },
   326     /** @id MochiKit.Base.typeMatcher */
   327     typeMatcher: function (/* typ */) {
   328         var types = {};
   329         for (var i = 0; i < arguments.length; i++) {
   330             var typ = arguments[i];
   331             types[typ] = typ;
   332         }
   333         return function () {
   334             for (var i = 0; i < arguments.length; i++) {
   335                 if (!(typeof(arguments[i]) in types)) {
   336                     return false;
   337                 }
   338             }
   339             return true;
   340         };
   341     },
   343     /** @id MochiKit.Base.isNull */
   344     isNull: function (/* ... */) {
   345         for (var i = 0; i < arguments.length; i++) {
   346             if (arguments[i] !== null) {
   347                 return false;
   348             }
   349         }
   350         return true;
   351     },
   353     /** @id MochiKit.Base.isUndefinedOrNull */
   354     isUndefinedOrNull: function (/* ... */) {
   355         for (var i = 0; i < arguments.length; i++) {
   356             var o = arguments[i];
   357             if (!(typeof(o) == 'undefined' || o === null)) {
   358                 return false;
   359             }
   360         }
   361         return true;
   362     },
   364     /** @id MochiKit.Base.isEmpty */
   365     isEmpty: function (obj) {
   366         return !MochiKit.Base.isNotEmpty.apply(this, arguments);
   367     },
   369     /** @id MochiKit.Base.isNotEmpty */
   370     isNotEmpty: function (obj) {
   371         for (var i = 0; i < arguments.length; i++) {
   372             var o = arguments[i];
   373             if (!(o && o.length)) {
   374                 return false;
   375             }
   376         }
   377         return true;
   378     },
   380     /** @id MochiKit.Base.isArrayLike */
   381     isArrayLike: function () {
   382         for (var i = 0; i < arguments.length; i++) {
   383             var o = arguments[i];
   384             var typ = typeof(o);
   385             if (
   386                 (typ != 'object' && !(typ == 'function' && typeof(o.item) == 'function')) ||
   387                 o === null ||
   388                 typeof(o.length) != 'number' ||
   389                 o.nodeType === 3
   390             ) {
   391                 return false;
   392             }
   393         }
   394         return true;
   395     },
   397     /** @id MochiKit.Base.isDateLike */
   398     isDateLike: function () {
   399         for (var i = 0; i < arguments.length; i++) {
   400             var o = arguments[i];
   401             if (typeof(o) != "object" || o === null
   402                     || typeof(o.getTime) != 'function') {
   403                 return false;
   404             }
   405         }
   406         return true;
   407     },
   410     /** @id MochiKit.Base.xmap */
   411     xmap: function (fn/*, obj... */) {
   412         if (fn === null) {
   413             return MochiKit.Base.extend(null, arguments, 1);
   414         }
   415         var rval = [];
   416         for (var i = 1; i < arguments.length; i++) {
   417             rval.push(fn(arguments[i]));
   418         }
   419         return rval;
   420     },
   422     /** @id MochiKit.Base.map */
   423     map: function (fn, lst/*, lst... */) {
   424         var m = MochiKit.Base;
   425         var itr = MochiKit.Iter;
   426         var isArrayLike = m.isArrayLike;
   427         if (arguments.length <= 2) {
   428             // allow an iterable to be passed
   429             if (!isArrayLike(lst)) {
   430                 if (itr) {
   431                     // fast path for map(null, iterable)
   432                     lst = itr.list(lst);
   433                     if (fn === null) {
   434                         return lst;
   435                     }
   436                 } else {
   437                     throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
   438                 }
   439             }
   440             // fast path for map(null, lst)
   441             if (fn === null) {
   442                 return m.extend(null, lst);
   443             }
   444             // disabled fast path for map(fn, lst)
   445             /*
   446             if (false && typeof(Array.prototype.map) == 'function') {
   447                 // Mozilla fast-path
   448                 return Array.prototype.map.call(lst, fn);
   449             }
   450             */
   451             var rval = [];
   452             for (var i = 0; i < lst.length; i++) {
   453                 rval.push(fn(lst[i]));
   454             }
   455             return rval;
   456         } else {
   457             // default for map(null, ...) is zip(...)
   458             if (fn === null) {
   459                 fn = Array;
   460             }
   461             var length = null;
   462             for (i = 1; i < arguments.length; i++) {
   463                 // allow iterables to be passed
   464                 if (!isArrayLike(arguments[i])) {
   465                     if (itr) {
   466                         return itr.list(itr.imap.apply(null, arguments));
   467                     } else {
   468                         throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
   469                     }
   470                 }
   471                 // find the minimum length
   472                 var l = arguments[i].length;
   473                 if (length === null || length > l) {
   474                     length = l;
   475                 }
   476             }
   477             rval = [];
   478             for (i = 0; i < length; i++) {
   479                 var args = [];
   480                 for (var j = 1; j < arguments.length; j++) {
   481                     args.push(arguments[j][i]);
   482                 }
   483                 rval.push(fn.apply(this, args));
   484             }
   485             return rval;
   486         }
   487     },
   489     /** @id MochiKit.Base.xfilter */
   490     xfilter: function (fn/*, obj... */) {
   491         var rval = [];
   492         if (fn === null) {
   493             fn = MochiKit.Base.operator.truth;
   494         }
   495         for (var i = 1; i < arguments.length; i++) {
   496             var o = arguments[i];
   497             if (fn(o)) {
   498                 rval.push(o);
   499             }
   500         }
   501         return rval;
   502     },
   504     /** @id MochiKit.Base.filter */
   505     filter: function (fn, lst, self) {
   506         var rval = [];
   507         // allow an iterable to be passed
   508         var m = MochiKit.Base;
   509         if (!m.isArrayLike(lst)) {
   510             if (MochiKit.Iter) {
   511                 lst = MochiKit.Iter.list(lst);
   512             } else {
   513                 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
   514             }
   515         }
   516         if (fn === null) {
   517             fn = m.operator.truth;
   518         }
   519         if (typeof(Array.prototype.filter) == 'function') {
   520             // Mozilla fast-path
   521             return Array.prototype.filter.call(lst, fn, self);
   522         } else if (typeof(self) == 'undefined' || self === null) {
   523             for (var i = 0; i < lst.length; i++) {
   524                 var o = lst[i];
   525                 if (fn(o)) {
   526                     rval.push(o);
   527                 }
   528             }
   529         } else {
   530             for (i = 0; i < lst.length; i++) {
   531                 o = lst[i];
   532                 if (fn.call(self, o)) {
   533                     rval.push(o);
   534                 }
   535             }
   536         }
   537         return rval;
   538     },
   541     _wrapDumbFunction: function (func) {
   542         return function () {
   543             // fast path!
   544             switch (arguments.length) {
   545                 case 0: return func();
   546                 case 1: return func(arguments[0]);
   547                 case 2: return func(arguments[0], arguments[1]);
   548                 case 3: return func(arguments[0], arguments[1], arguments[2]);
   549             }
   550             var args = [];
   551             for (var i = 0; i < arguments.length; i++) {
   552                 args.push("arguments[" + i + "]");
   553             }
   554             return eval("(func(" + args.join(",") + "))");
   555         };
   556     },
   558     /** @id MochiKit.Base.methodcaller */
   559     methodcaller: function (func/*, args... */) {
   560         var args = MochiKit.Base.extend(null, arguments, 1);
   561         if (typeof(func) == "function") {
   562             return function (obj) {
   563                 return func.apply(obj, args);
   564             };
   565         } else {
   566             return function (obj) {
   567                 return obj[func].apply(obj, args);
   568             };
   569         }
   570     },
   572     /** @id MochiKit.Base.method */
   573     method: function (self, func) {
   574         var m = MochiKit.Base;
   575         return m.bind.apply(this, m.extend([func, self], arguments, 2));
   576     },
   578     /** @id MochiKit.Base.compose */
   579     compose: function (f1, f2/*, f3, ... fN */) {
   580         var fnlist = [];
   581         var m = MochiKit.Base;
   582         if (arguments.length === 0) {
   583             throw new TypeError("compose() requires at least one argument");
   584         }
   585         for (var i = 0; i < arguments.length; i++) {
   586             var fn = arguments[i];
   587             if (typeof(fn) != "function") {
   588                 throw new TypeError(m.repr(fn) + " is not a function");
   589             }
   590             fnlist.push(fn);
   591         }
   592         return function () {
   593             var args = arguments;
   594             for (var i = fnlist.length - 1; i >= 0; i--) {
   595                 args = [fnlist[i].apply(this, args)];
   596             }
   597             return args[0];
   598         };
   599     },
   601     /** @id MochiKit.Base.bind */
   602     bind: function (func, self/* args... */) {
   603         if (typeof(func) == "string") {
   604             func = self[func];
   605         }
   606         var im_func = func.im_func;
   607         var im_preargs = func.im_preargs;
   608         var im_self = func.im_self;
   609         var m = MochiKit.Base;
   610         if (typeof(func) == "function" && typeof(func.apply) == "undefined") {
   611             // this is for cases where JavaScript sucks ass and gives you a
   612             // really dumb built-in function like alert() that doesn't have
   613             // an apply
   614             func = m._wrapDumbFunction(func);
   615         }
   616         if (typeof(im_func) != 'function') {
   617             im_func = func;
   618         }
   619         if (typeof(self) != 'undefined') {
   620             im_self = self;
   621         }
   622         if (typeof(im_preargs) == 'undefined') {
   623             im_preargs = [];
   624         } else  {
   625             im_preargs = im_preargs.slice();
   626         }
   627         m.extend(im_preargs, arguments, 2);
   628         var newfunc = function () {
   629             var args = arguments;
   630             var me = arguments.callee;
   631             if (me.im_preargs.length > 0) {
   632                 args = m.concat(me.im_preargs, args);
   633             }
   634             var self = me.im_self;
   635             if (!self) {
   636                 self = this;
   637             }
   638             return me.im_func.apply(self, args);
   639         };
   640         newfunc.im_self = im_self;
   641         newfunc.im_func = im_func;
   642         newfunc.im_preargs = im_preargs;
   643         return newfunc;
   644     },
   646     /** @id MochiKit.Base.bindMethods */
   647     bindMethods: function (self) {
   648         var bind = MochiKit.Base.bind;
   649         for (var k in self) {
   650             var func = self[k];
   651             if (typeof(func) == 'function') {
   652                 self[k] = bind(func, self);
   653             }
   654         }
   655     },
   657     /** @id MochiKit.Base.registerComparator */
   658     registerComparator: function (name, check, comparator, /* optional */ override) {
   659         MochiKit.Base.comparatorRegistry.register(name, check, comparator, override);
   660     },
   662     _primitives: {'boolean': true, 'string': true, 'number': true},
   664     /** @id MochiKit.Base.compare */
   665     compare: function (a, b) {
   666         if (a == b) {
   667             return 0;
   668         }
   669         var aIsNull = (typeof(a) == 'undefined' || a === null);
   670         var bIsNull = (typeof(b) == 'undefined' || b === null);
   671         if (aIsNull && bIsNull) {
   672             return 0;
   673         } else if (aIsNull) {
   674             return -1;
   675         } else if (bIsNull) {
   676             return 1;
   677         }
   678         var m = MochiKit.Base;
   679         // bool, number, string have meaningful comparisons
   680         var prim = m._primitives;
   681         if (!(typeof(a) in prim && typeof(b) in prim)) {
   682             try {
   683                 return m.comparatorRegistry.match(a, b);
   684             } catch (e) {
   685                 if (e != m.NotFound) {
   686                     throw e;
   687                 }
   688             }
   689         }
   690         if (a < b) {
   691             return -1;
   692         } else if (a > b) {
   693             return 1;
   694         }
   695         // These types can't be compared
   696         var repr = m.repr;
   697         throw new TypeError(repr(a) + " and " + repr(b) + " can not be compared");
   698     },
   700     /** @id MochiKit.Base.compareDateLike */
   701     compareDateLike: function (a, b) {
   702         return MochiKit.Base.compare(a.getTime(), b.getTime());
   703     },
   705     /** @id MochiKit.Base.compareArrayLike */
   706     compareArrayLike: function (a, b) {
   707         var compare = MochiKit.Base.compare;
   708         var count = a.length;
   709         var rval = 0;
   710         if (count > b.length) {
   711             rval = 1;
   712             count = b.length;
   713         } else if (count < b.length) {
   714             rval = -1;
   715         }
   716         for (var i = 0; i < count; i++) {
   717             var cmp = compare(a[i], b[i]);
   718             if (cmp) {
   719                 return cmp;
   720             }
   721         }
   722         return rval;
   723     },
   725     /** @id MochiKit.Base.registerRepr */
   726     registerRepr: function (name, check, wrap, /* optional */override) {
   727         MochiKit.Base.reprRegistry.register(name, check, wrap, override);
   728     },
   730     /** @id MochiKit.Base.repr */
   731     repr: function (o) {
   732         if (typeof(o) == "undefined") {
   733             return "undefined";
   734         } else if (o === null) {
   735             return "null";
   736         }
   737         try {
   738             if (typeof(o.__repr__) == 'function') {
   739                 return o.__repr__();
   740             } else if (typeof(o.repr) == 'function' && o.repr != arguments.callee) {
   741                 return o.repr();
   742             }
   743             return MochiKit.Base.reprRegistry.match(o);
   744         } catch (e) {
   745             if (typeof(o.NAME) == 'string' && (
   746                     o.toString == Function.prototype.toString ||
   747                     o.toString == Object.prototype.toString
   748                 )) {
   749                 return o.NAME;
   750             }
   751         }
   752         try {
   753             var ostring = (o + "");
   754         } catch (e) {
   755             return "[" + typeof(o) + "]";
   756         }
   757         if (typeof(o) == "function") {
   758             o = ostring.replace(/^\s+/, "");
   759             var idx = o.indexOf("{");
   760             if (idx != -1) {
   761                 o = o.substr(0, idx) + "{...}";
   762             }
   763         }
   764         return ostring;
   765     },
   767     /** @id MochiKit.Base.reprArrayLike */
   768     reprArrayLike: function (o) {
   769         var m = MochiKit.Base;
   770         return "[" + m.map(m.repr, o).join(", ") + "]";
   771     },
   773     /** @id MochiKit.Base.reprString */
   774     reprString: function (o) {
   775         return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
   776             ).replace(/[\f]/g, "\\f"
   777             ).replace(/[\b]/g, "\\b"
   778             ).replace(/[\n]/g, "\\n"
   779             ).replace(/[\t]/g, "\\t"
   780             ).replace(/[\r]/g, "\\r");
   781     },
   783     /** @id MochiKit.Base.reprNumber */
   784     reprNumber: function (o) {
   785         return o + "";
   786     },
   788     /** @id MochiKit.Base.registerJSON */
   789     registerJSON: function (name, check, wrap, /* optional */override) {
   790         MochiKit.Base.jsonRegistry.register(name, check, wrap, override);
   791     },
   794     /** @id MochiKit.Base.evalJSON */
   795     evalJSON: function () {
   796         return eval("(" + MochiKit.Base._filterJSON(arguments[0]) + ")");
   797     },
   799     _filterJSON: function (s) {
   800         var m = s.match(/^\s*\/\*(.*)\*\/\s*$/);
   801         if (m) {
   802             return m[1];
   803         }
   804         return s;
   805     },
   807     /** @id MochiKit.Base.serializeJSON */
   808     serializeJSON: function (o) {
   809         var objtype = typeof(o);
   810         if (objtype == "number" || objtype == "boolean") {
   811             return o + "";
   812         } else if (o === null) {
   813             return "null";
   814         }
   815         var m = MochiKit.Base;
   816         var reprString = m.reprString;
   817         if (objtype == "string") {
   818             return reprString(o);
   819         }
   820         // recurse
   821         var me = arguments.callee;
   822         // short-circuit for objects that support "json" serialization
   823         // if they return "self" then just pass-through...
   824         var newObj;
   825         if (typeof(o.__json__) == "function") {
   826             newObj = o.__json__();
   827             if (o !== newObj) {
   828                 return me(newObj);
   829             }
   830         }
   831         if (typeof(o.json) == "function") {
   832             newObj = o.json();
   833             if (o !== newObj) {
   834                 return me(newObj);
   835             }
   836         }
   837         // array
   838         if (objtype != "function" && typeof(o.length) == "number") {
   839             var res = [];
   840             for (var i = 0; i < o.length; i++) {
   841                 var val = me(o[i]);
   842                 if (typeof(val) != "string") {
   843                     val = "undefined";
   844                 }
   845                 res.push(val);
   846             }
   847             return "[" + res.join(", ") + "]";
   848         }
   849         // look in the registry
   850         try {
   851             newObj = m.jsonRegistry.match(o);
   852             if (o !== newObj) {
   853                 return me(newObj);
   854             }
   855         } catch (e) {
   856             if (e != m.NotFound) {
   857                 // something really bad happened
   858                 throw e;
   859             }
   860         }
   861         // undefined is outside of the spec
   862         if (objtype == "undefined") {
   863             throw new TypeError("undefined can not be serialized as JSON");
   864         }
   865         // it's a function with no adapter, bad
   866         if (objtype == "function") {
   867             return null;
   868         }
   869         // generic object code path
   870         res = [];
   871         for (var k in o) {
   872             var useKey;
   873             if (typeof(k) == "number") {
   874                 useKey = '"' + k + '"';
   875             } else if (typeof(k) == "string") {
   876                 useKey = reprString(k);
   877             } else {
   878                 // skip non-string or number keys
   879                 continue;
   880             }
   881             val = me(o[k]);
   882             if (typeof(val) != "string") {
   883                 // skip non-serializable values
   884                 continue;
   885             }
   886             res.push(useKey + ":" + val);
   887         }
   888         return "{" + res.join(", ") + "}";
   889     },
   892     /** @id MochiKit.Base.objEqual */
   893     objEqual: function (a, b) {
   894         return (MochiKit.Base.compare(a, b) === 0);
   895     },
   897     /** @id MochiKit.Base.arrayEqual */
   898     arrayEqual: function (self, arr) {
   899         if (self.length != arr.length) {
   900             return false;
   901         }
   902         return (MochiKit.Base.compare(self, arr) === 0);
   903     },
   905     /** @id MochiKit.Base.concat */
   906     concat: function (/* lst... */) {
   907         var rval = [];
   908         var extend = MochiKit.Base.extend;
   909         for (var i = 0; i < arguments.length; i++) {
   910             extend(rval, arguments[i]);
   911         }
   912         return rval;
   913     },
   915     /** @id MochiKit.Base.keyComparator */
   916     keyComparator: function (key/* ... */) {
   917         // fast-path for single key comparisons
   918         var m = MochiKit.Base;
   919         var compare = m.compare;
   920         if (arguments.length == 1) {
   921             return function (a, b) {
   922                 return compare(a[key], b[key]);
   923             };
   924         }
   925         var compareKeys = m.extend(null, arguments);
   926         return function (a, b) {
   927             var rval = 0;
   928             // keep comparing until something is inequal or we run out of
   929             // keys to compare
   930             for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) {
   931                 var key = compareKeys[i];
   932                 rval = compare(a[key], b[key]);
   933             }
   934             return rval;
   935         };
   936     },
   938     /** @id MochiKit.Base.reverseKeyComparator */
   939     reverseKeyComparator: function (key) {
   940         var comparator = MochiKit.Base.keyComparator.apply(this, arguments);
   941         return function (a, b) {
   942             return comparator(b, a);
   943         };
   944     },
   946     /** @id MochiKit.Base.partial */
   947     partial: function (func) {
   948         var m = MochiKit.Base;
   949         return m.bind.apply(this, m.extend([func, undefined], arguments, 1));
   950     },
   952     /** @id MochiKit.Base.listMinMax */
   953     listMinMax: function (which, lst) {
   954         if (lst.length === 0) {
   955             return null;
   956         }
   957         var cur = lst[0];
   958         var compare = MochiKit.Base.compare;
   959         for (var i = 1; i < lst.length; i++) {
   960             var o = lst[i];
   961             if (compare(o, cur) == which) {
   962                 cur = o;
   963             }
   964         }
   965         return cur;
   966     },
   968     /** @id MochiKit.Base.objMax */
   969     objMax: function (/* obj... */) {
   970         return MochiKit.Base.listMinMax(1, arguments);
   971     },
   973     /** @id MochiKit.Base.objMin */
   974     objMin: function (/* obj... */) {
   975         return MochiKit.Base.listMinMax(-1, arguments);
   976     },
   978     /** @id MochiKit.Base.findIdentical */
   979     findIdentical: function (lst, value, start/* = 0 */, /* optional */end) {
   980         if (typeof(end) == "undefined" || end === null) {
   981             end = lst.length;
   982         }
   983         if (typeof(start) == "undefined" || start === null) {
   984             start = 0;
   985         }
   986         for (var i = start; i < end; i++) {
   987             if (lst[i] === value) {
   988                 return i;
   989             }
   990         }
   991         return -1;
   992     },
   994     /** @id MochiKit.Base.mean */
   995     mean: function(/* lst... */) {
   996         /* http://www.nist.gov/dads/HTML/mean.html */
   997         var sum = 0;
   999         var m = MochiKit.Base;
  1000         var args = m.extend(null, arguments);
  1001         var count = args.length;
  1003         while (args.length) {
  1004             var o = args.shift();
  1005             if (o && typeof(o) == "object" && typeof(o.length) == "number") {
  1006                 count += o.length - 1;
  1007                 for (var i = o.length - 1; i >= 0; i--) {
  1008                     sum += o[i];
  1010             } else {
  1011                 sum += o;
  1015         if (count <= 0) {
  1016             throw new TypeError('mean() requires at least one argument');
  1019         return sum/count;
  1020     },
  1022     /** @id MochiKit.Base.median */
  1023     median: function(/* lst... */) {
  1024         /* http://www.nist.gov/dads/HTML/median.html */
  1025         var data = MochiKit.Base.flattenArguments(arguments);
  1026         if (data.length === 0) {
  1027             throw new TypeError('median() requires at least one argument');
  1029         data.sort(compare);
  1030         if (data.length % 2 == 0) {
  1031             var upper = data.length / 2;
  1032             return (data[upper] + data[upper - 1]) / 2;
  1033         } else {
  1034             return data[(data.length - 1) / 2];
  1036     },
  1038     /** @id MochiKit.Base.findValue */
  1039     findValue: function (lst, value, start/* = 0 */, /* optional */end) {
  1040         if (typeof(end) == "undefined" || end === null) {
  1041             end = lst.length;
  1043         if (typeof(start) == "undefined" || start === null) {
  1044             start = 0;
  1046         var cmp = MochiKit.Base.compare;
  1047         for (var i = start; i < end; i++) {
  1048             if (cmp(lst[i], value) === 0) {
  1049                 return i;
  1052         return -1;
  1053     },
  1055     /** @id MochiKit.Base.nodeWalk */
  1056     nodeWalk: function (node, visitor) {
  1057         var nodes = [node];
  1058         var extend = MochiKit.Base.extend;
  1059         while (nodes.length) {
  1060             var res = visitor(nodes.shift());
  1061             if (res) {
  1062                 extend(nodes, res);
  1065     },
  1068     /** @id MochiKit.Base.nameFunctions */
  1069     nameFunctions: function (namespace) {
  1070         var base = namespace.NAME;
  1071         if (typeof(base) == 'undefined') {
  1072             base = '';
  1073         } else {
  1074             base = base + '.';
  1076         for (var name in namespace) {
  1077             var o = namespace[name];
  1078             if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
  1079                 try {
  1080                     o.NAME = base + name;
  1081                 } catch (e) {
  1082                     // pass
  1086     },
  1089     /** @id MochiKit.Base.queryString */
  1090     queryString: function (names, values) {
  1091         // check to see if names is a string or a DOM element, and if
  1092         // MochiKit.DOM is available.  If so, drop it like it's a form
  1093         // Ugliest conditional in MochiKit?  Probably!
  1094         if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1
  1095             && (typeof(names) == "string" || (
  1096                 typeof(names.nodeType) != "undefined" && names.nodeType > 0
  1097             ))
  1098         ) {
  1099             var kv = MochiKit.DOM.formContents(names);
  1100             names = kv[0];
  1101             values = kv[1];
  1102         } else if (arguments.length == 1) {
  1103             // Allow the return value of formContents to be passed directly
  1104             if (typeof(names.length) == "number" && names.length == 2) {
  1105                 return arguments.callee(names[0], names[1]);
  1107             var o = names;
  1108             names = [];
  1109             values = [];
  1110             for (var k in o) {
  1111                 var v = o[k];
  1112                 if (typeof(v) == "function") {
  1113                     continue;
  1114                 } else if (typeof(v) != "string" &&
  1115                         typeof(v.length) == "number") {
  1116                     for (var i = 0; i < v.length; i++) {
  1117                         names.push(k);
  1118                         values.push(v[i]);
  1120                 } else {
  1121                     names.push(k);
  1122                     values.push(v);
  1126         var rval = [];
  1127         var len = Math.min(names.length, values.length);
  1128         var urlEncode = MochiKit.Base.urlEncode;
  1129         for (var i = 0; i < len; i++) {
  1130             v = values[i];
  1131             if (typeof(v) != 'undefined' && v !== null) {
  1132                 rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
  1135         return rval.join("&");
  1136     },
  1139     /** @id MochiKit.Base.parseQueryString */
  1140     parseQueryString: function (encodedString, useArrays) {
  1141         // strip a leading '?' from the encoded string
  1142         var qstr = (encodedString.charAt(0) == "?")
  1143             ? encodedString.substring(1)
  1144             : encodedString;
  1145         var pairs = qstr.replace(/\+/g, "%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
  1146         var o = {};
  1147         var decode;
  1148         if (typeof(decodeURIComponent) != "undefined") {
  1149             decode = decodeURIComponent;
  1150         } else {
  1151             decode = unescape;
  1153         if (useArrays) {
  1154             for (var i = 0; i < pairs.length; i++) {
  1155                 var pair = pairs[i].split("=");
  1156                 var name = decode(pair.shift());
  1157                 if (!name) {
  1158                     continue;
  1160                 var arr = o[name];
  1161                 if (!(arr instanceof Array)) {
  1162                     arr = [];
  1163                     o[name] = arr;
  1165                 arr.push(decode(pair.join("=")));
  1167         } else {
  1168             for (i = 0; i < pairs.length; i++) {
  1169                 pair = pairs[i].split("=");
  1170                 var name = pair.shift();
  1171                 if (!name) {
  1172                     continue;
  1174                 o[decode(name)] = decode(pair.join("="));
  1177         return o;
  1179 });
  1181 /** @id MochiKit.Base.AdapterRegistry */
  1182 MochiKit.Base.AdapterRegistry = function () {
  1183     this.pairs = [];
  1184 };
  1186 MochiKit.Base.AdapterRegistry.prototype = {
  1187     /** @id MochiKit.Base.AdapterRegistry.prototype.register */
  1188     register: function (name, check, wrap, /* optional */ override) {
  1189         if (override) {
  1190             this.pairs.unshift([name, check, wrap]);
  1191         } else {
  1192             this.pairs.push([name, check, wrap]);
  1194     },
  1196     /** @id MochiKit.Base.AdapterRegistry.prototype.match */
  1197     match: function (/* ... */) {
  1198         for (var i = 0; i < this.pairs.length; i++) {
  1199             var pair = this.pairs[i];
  1200             if (pair[1].apply(this, arguments)) {
  1201                 return pair[2].apply(this, arguments);
  1204         throw MochiKit.Base.NotFound;
  1205     },
  1207     /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
  1208     unregister: function (name) {
  1209         for (var i = 0; i < this.pairs.length; i++) {
  1210             var pair = this.pairs[i];
  1211             if (pair[0] == name) {
  1212                 this.pairs.splice(i, 1);
  1213                 return true;
  1216         return false;
  1218 };
  1221 MochiKit.Base.EXPORT = [
  1222     "flattenArray",
  1223     "noop",
  1224     "camelize",
  1225     "counter",
  1226     "clone",
  1227     "extend",
  1228     "update",
  1229     "updatetree",
  1230     "setdefault",
  1231     "keys",
  1232     "values",
  1233     "items",
  1234     "NamedError",
  1235     "operator",
  1236     "forwardCall",
  1237     "itemgetter",
  1238     "typeMatcher",
  1239     "isCallable",
  1240     "isUndefined",
  1241     "isUndefinedOrNull",
  1242     "isNull",
  1243     "isEmpty",
  1244     "isNotEmpty",
  1245     "isArrayLike",
  1246     "isDateLike",
  1247     "xmap",
  1248     "map",
  1249     "xfilter",
  1250     "filter",
  1251     "methodcaller",
  1252     "compose",
  1253     "bind",
  1254     "bindMethods",
  1255     "NotFound",
  1256     "AdapterRegistry",
  1257     "registerComparator",
  1258     "compare",
  1259     "registerRepr",
  1260     "repr",
  1261     "objEqual",
  1262     "arrayEqual",
  1263     "concat",
  1264     "keyComparator",
  1265     "reverseKeyComparator",
  1266     "partial",
  1267     "merge",
  1268     "listMinMax",
  1269     "listMax",
  1270     "listMin",
  1271     "objMax",
  1272     "objMin",
  1273     "nodeWalk",
  1274     "zip",
  1275     "urlEncode",
  1276     "queryString",
  1277     "serializeJSON",
  1278     "registerJSON",
  1279     "evalJSON",
  1280     "parseQueryString",
  1281     "findValue",
  1282     "findIdentical",
  1283     "flattenArguments",
  1284     "method",
  1285     "average",
  1286     "mean",
  1287     "median"
  1288 ];
  1290 MochiKit.Base.EXPORT_OK = [
  1291     "nameFunctions",
  1292     "comparatorRegistry",
  1293     "reprRegistry",
  1294     "jsonRegistry",
  1295     "compareDateLike",
  1296     "compareArrayLike",
  1297     "reprArrayLike",
  1298     "reprString",
  1299     "reprNumber"
  1300 ];
  1302 MochiKit.Base._exportSymbols = function (globals, module) {
  1303     if (!MochiKit.__export__) {
  1304         return;
  1306     var all = module.EXPORT_TAGS[":all"];
  1307     for (var i = 0; i < all.length; i++) {
  1308         globals[all[i]] = module[all[i]];
  1310 };
  1312 MochiKit.Base.__new__ = function () {
  1313     // A singleton raised when no suitable adapter is found
  1314     var m = this;
  1316     // convenience
  1317     /** @id MochiKit.Base.noop */
  1318     m.noop = m.operator.identity;
  1320     // Backwards compat
  1321     m.forward = m.forwardCall;
  1322     m.find = m.findValue;
  1324     if (typeof(encodeURIComponent) != "undefined") {
  1325         /** @id MochiKit.Base.urlEncode */
  1326         m.urlEncode = function (unencoded) {
  1327             return encodeURIComponent(unencoded).replace(/\'/g, '%27');
  1328         };
  1329     } else {
  1330         m.urlEncode = function (unencoded) {
  1331             return escape(unencoded
  1332                 ).replace(/\+/g, '%2B'
  1333                 ).replace(/\"/g,'%22'
  1334                 ).rval.replace(/\'/g, '%27');
  1335         };
  1338     /** @id MochiKit.Base.NamedError */
  1339     m.NamedError = function (name) {
  1340         this.message = name;
  1341         this.name = name;
  1342     };
  1343     m.NamedError.prototype = new Error();
  1344     m.update(m.NamedError.prototype, {
  1345         repr: function () {
  1346             if (this.message && this.message != this.name) {
  1347                 return this.name + "(" + m.repr(this.message) + ")";
  1348             } else {
  1349                 return this.name + "()";
  1351         },
  1352         toString: m.forwardCall("repr")
  1353     });
  1355     /** @id MochiKit.Base.NotFound */
  1356     m.NotFound = new m.NamedError("MochiKit.Base.NotFound");
  1359     /** @id MochiKit.Base.listMax */
  1360     m.listMax = m.partial(m.listMinMax, 1);
  1361     /** @id MochiKit.Base.listMin */
  1362     m.listMin = m.partial(m.listMinMax, -1);
  1364     /** @id MochiKit.Base.isCallable */
  1365     m.isCallable = m.typeMatcher('function');
  1366     /** @id MochiKit.Base.isUndefined */
  1367     m.isUndefined = m.typeMatcher('undefined');
  1369     /** @id MochiKit.Base.merge */
  1370     m.merge = m.partial(m.update, null);
  1371     /** @id MochiKit.Base.zip */
  1372     m.zip = m.partial(m.map, null);
  1374     /** @id MochiKit.Base.average */
  1375     m.average = m.mean;
  1377     /** @id MochiKit.Base.comparatorRegistry */
  1378     m.comparatorRegistry = new m.AdapterRegistry();
  1379     m.registerComparator("dateLike", m.isDateLike, m.compareDateLike);
  1380     m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike);
  1382     /** @id MochiKit.Base.reprRegistry */
  1383     m.reprRegistry = new m.AdapterRegistry();
  1384     m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
  1385     m.registerRepr("string", m.typeMatcher("string"), m.reprString);
  1386     m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);
  1388     /** @id MochiKit.Base.jsonRegistry */
  1389     m.jsonRegistry = new m.AdapterRegistry();
  1391     var all = m.concat(m.EXPORT, m.EXPORT_OK);
  1392     m.EXPORT_TAGS = {
  1393         ":common": m.concat(m.EXPORT_OK),
  1394         ":all": all
  1395     };
  1397     m.nameFunctions(this);
  1399 };
  1401 MochiKit.Base.__new__();
  1403 //
  1404 // XXX: Internet Explorer blows
  1405 //
  1406 if (MochiKit.__export__) {
  1407     compare = MochiKit.Base.compare;
  1408     compose = MochiKit.Base.compose;
  1409     serializeJSON = MochiKit.Base.serializeJSON;
  1412 MochiKit.Base._exportSymbols(this, MochiKit.Base);

mercurial