testing/mochitest/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.

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

mercurial