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

Tue, 06 Jan 2015 21:39:09 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Tue, 06 Jan 2015 21:39:09 +0100
branch
TOR_BUG_9701
changeset 8
97036ab72558
permissions
-rw-r--r--

Conditionally force memory storage according to privacy.thirdparty.isolate;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.

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 if (typeof(o.NAME) == 'string' && (
michael@0 746 o.toString == Function.prototype.toString ||
michael@0 747 o.toString == Object.prototype.toString
michael@0 748 )) {
michael@0 749 return o.NAME;
michael@0 750 }
michael@0 751 }
michael@0 752 try {
michael@0 753 var ostring = (o + "");
michael@0 754 } catch (e) {
michael@0 755 return "[" + typeof(o) + "]";
michael@0 756 }
michael@0 757 if (typeof(o) == "function") {
michael@0 758 o = ostring.replace(/^\s+/, "");
michael@0 759 var idx = o.indexOf("{");
michael@0 760 if (idx != -1) {
michael@0 761 o = o.substr(0, idx) + "{...}";
michael@0 762 }
michael@0 763 }
michael@0 764 return ostring;
michael@0 765 },
michael@0 766
michael@0 767 /** @id MochiKit.Base.reprArrayLike */
michael@0 768 reprArrayLike: function (o) {
michael@0 769 var m = MochiKit.Base;
michael@0 770 return "[" + m.map(m.repr, o).join(", ") + "]";
michael@0 771 },
michael@0 772
michael@0 773 /** @id MochiKit.Base.reprString */
michael@0 774 reprString: function (o) {
michael@0 775 return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
michael@0 776 ).replace(/[\f]/g, "\\f"
michael@0 777 ).replace(/[\b]/g, "\\b"
michael@0 778 ).replace(/[\n]/g, "\\n"
michael@0 779 ).replace(/[\t]/g, "\\t"
michael@0 780 ).replace(/[\r]/g, "\\r");
michael@0 781 },
michael@0 782
michael@0 783 /** @id MochiKit.Base.reprNumber */
michael@0 784 reprNumber: function (o) {
michael@0 785 return o + "";
michael@0 786 },
michael@0 787
michael@0 788 /** @id MochiKit.Base.registerJSON */
michael@0 789 registerJSON: function (name, check, wrap, /* optional */override) {
michael@0 790 MochiKit.Base.jsonRegistry.register(name, check, wrap, override);
michael@0 791 },
michael@0 792
michael@0 793
michael@0 794 /** @id MochiKit.Base.evalJSON */
michael@0 795 evalJSON: function () {
michael@0 796 return eval("(" + MochiKit.Base._filterJSON(arguments[0]) + ")");
michael@0 797 },
michael@0 798
michael@0 799 _filterJSON: function (s) {
michael@0 800 var m = s.match(/^\s*\/\*(.*)\*\/\s*$/);
michael@0 801 if (m) {
michael@0 802 return m[1];
michael@0 803 }
michael@0 804 return s;
michael@0 805 },
michael@0 806
michael@0 807 /** @id MochiKit.Base.serializeJSON */
michael@0 808 serializeJSON: function (o) {
michael@0 809 var objtype = typeof(o);
michael@0 810 if (objtype == "number" || objtype == "boolean") {
michael@0 811 return o + "";
michael@0 812 } else if (o === null) {
michael@0 813 return "null";
michael@0 814 }
michael@0 815 var m = MochiKit.Base;
michael@0 816 var reprString = m.reprString;
michael@0 817 if (objtype == "string") {
michael@0 818 return reprString(o);
michael@0 819 }
michael@0 820 // recurse
michael@0 821 var me = arguments.callee;
michael@0 822 // short-circuit for objects that support "json" serialization
michael@0 823 // if they return "self" then just pass-through...
michael@0 824 var newObj;
michael@0 825 if (typeof(o.__json__) == "function") {
michael@0 826 newObj = o.__json__();
michael@0 827 if (o !== newObj) {
michael@0 828 return me(newObj);
michael@0 829 }
michael@0 830 }
michael@0 831 if (typeof(o.json) == "function") {
michael@0 832 newObj = o.json();
michael@0 833 if (o !== newObj) {
michael@0 834 return me(newObj);
michael@0 835 }
michael@0 836 }
michael@0 837 // array
michael@0 838 if (objtype != "function" && typeof(o.length) == "number") {
michael@0 839 var res = [];
michael@0 840 for (var i = 0; i < o.length; i++) {
michael@0 841 var val = me(o[i]);
michael@0 842 if (typeof(val) != "string") {
michael@0 843 val = "undefined";
michael@0 844 }
michael@0 845 res.push(val);
michael@0 846 }
michael@0 847 return "[" + res.join(", ") + "]";
michael@0 848 }
michael@0 849 // look in the registry
michael@0 850 try {
michael@0 851 newObj = m.jsonRegistry.match(o);
michael@0 852 if (o !== newObj) {
michael@0 853 return me(newObj);
michael@0 854 }
michael@0 855 } catch (e) {
michael@0 856 if (e != m.NotFound) {
michael@0 857 // something really bad happened
michael@0 858 throw e;
michael@0 859 }
michael@0 860 }
michael@0 861 // undefined is outside of the spec
michael@0 862 if (objtype == "undefined") {
michael@0 863 throw new TypeError("undefined can not be serialized as JSON");
michael@0 864 }
michael@0 865 // it's a function with no adapter, bad
michael@0 866 if (objtype == "function") {
michael@0 867 return null;
michael@0 868 }
michael@0 869 // generic object code path
michael@0 870 res = [];
michael@0 871 for (var k in o) {
michael@0 872 var useKey;
michael@0 873 if (typeof(k) == "number") {
michael@0 874 useKey = '"' + k + '"';
michael@0 875 } else if (typeof(k) == "string") {
michael@0 876 useKey = reprString(k);
michael@0 877 } else {
michael@0 878 // skip non-string or number keys
michael@0 879 continue;
michael@0 880 }
michael@0 881 val = me(o[k]);
michael@0 882 if (typeof(val) != "string") {
michael@0 883 // skip non-serializable values
michael@0 884 continue;
michael@0 885 }
michael@0 886 res.push(useKey + ":" + val);
michael@0 887 }
michael@0 888 return "{" + res.join(", ") + "}";
michael@0 889 },
michael@0 890
michael@0 891
michael@0 892 /** @id MochiKit.Base.objEqual */
michael@0 893 objEqual: function (a, b) {
michael@0 894 return (MochiKit.Base.compare(a, b) === 0);
michael@0 895 },
michael@0 896
michael@0 897 /** @id MochiKit.Base.arrayEqual */
michael@0 898 arrayEqual: function (self, arr) {
michael@0 899 if (self.length != arr.length) {
michael@0 900 return false;
michael@0 901 }
michael@0 902 return (MochiKit.Base.compare(self, arr) === 0);
michael@0 903 },
michael@0 904
michael@0 905 /** @id MochiKit.Base.concat */
michael@0 906 concat: function (/* lst... */) {
michael@0 907 var rval = [];
michael@0 908 var extend = MochiKit.Base.extend;
michael@0 909 for (var i = 0; i < arguments.length; i++) {
michael@0 910 extend(rval, arguments[i]);
michael@0 911 }
michael@0 912 return rval;
michael@0 913 },
michael@0 914
michael@0 915 /** @id MochiKit.Base.keyComparator */
michael@0 916 keyComparator: function (key/* ... */) {
michael@0 917 // fast-path for single key comparisons
michael@0 918 var m = MochiKit.Base;
michael@0 919 var compare = m.compare;
michael@0 920 if (arguments.length == 1) {
michael@0 921 return function (a, b) {
michael@0 922 return compare(a[key], b[key]);
michael@0 923 };
michael@0 924 }
michael@0 925 var compareKeys = m.extend(null, arguments);
michael@0 926 return function (a, b) {
michael@0 927 var rval = 0;
michael@0 928 // keep comparing until something is inequal or we run out of
michael@0 929 // keys to compare
michael@0 930 for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) {
michael@0 931 var key = compareKeys[i];
michael@0 932 rval = compare(a[key], b[key]);
michael@0 933 }
michael@0 934 return rval;
michael@0 935 };
michael@0 936 },
michael@0 937
michael@0 938 /** @id MochiKit.Base.reverseKeyComparator */
michael@0 939 reverseKeyComparator: function (key) {
michael@0 940 var comparator = MochiKit.Base.keyComparator.apply(this, arguments);
michael@0 941 return function (a, b) {
michael@0 942 return comparator(b, a);
michael@0 943 };
michael@0 944 },
michael@0 945
michael@0 946 /** @id MochiKit.Base.partial */
michael@0 947 partial: function (func) {
michael@0 948 var m = MochiKit.Base;
michael@0 949 return m.bind.apply(this, m.extend([func, undefined], arguments, 1));
michael@0 950 },
michael@0 951
michael@0 952 /** @id MochiKit.Base.listMinMax */
michael@0 953 listMinMax: function (which, lst) {
michael@0 954 if (lst.length === 0) {
michael@0 955 return null;
michael@0 956 }
michael@0 957 var cur = lst[0];
michael@0 958 var compare = MochiKit.Base.compare;
michael@0 959 for (var i = 1; i < lst.length; i++) {
michael@0 960 var o = lst[i];
michael@0 961 if (compare(o, cur) == which) {
michael@0 962 cur = o;
michael@0 963 }
michael@0 964 }
michael@0 965 return cur;
michael@0 966 },
michael@0 967
michael@0 968 /** @id MochiKit.Base.objMax */
michael@0 969 objMax: function (/* obj... */) {
michael@0 970 return MochiKit.Base.listMinMax(1, arguments);
michael@0 971 },
michael@0 972
michael@0 973 /** @id MochiKit.Base.objMin */
michael@0 974 objMin: function (/* obj... */) {
michael@0 975 return MochiKit.Base.listMinMax(-1, arguments);
michael@0 976 },
michael@0 977
michael@0 978 /** @id MochiKit.Base.findIdentical */
michael@0 979 findIdentical: function (lst, value, start/* = 0 */, /* optional */end) {
michael@0 980 if (typeof(end) == "undefined" || end === null) {
michael@0 981 end = lst.length;
michael@0 982 }
michael@0 983 if (typeof(start) == "undefined" || start === null) {
michael@0 984 start = 0;
michael@0 985 }
michael@0 986 for (var i = start; i < end; i++) {
michael@0 987 if (lst[i] === value) {
michael@0 988 return i;
michael@0 989 }
michael@0 990 }
michael@0 991 return -1;
michael@0 992 },
michael@0 993
michael@0 994 /** @id MochiKit.Base.mean */
michael@0 995 mean: function(/* lst... */) {
michael@0 996 /* http://www.nist.gov/dads/HTML/mean.html */
michael@0 997 var sum = 0;
michael@0 998
michael@0 999 var m = MochiKit.Base;
michael@0 1000 var args = m.extend(null, arguments);
michael@0 1001 var count = args.length;
michael@0 1002
michael@0 1003 while (args.length) {
michael@0 1004 var o = args.shift();
michael@0 1005 if (o && typeof(o) == "object" && typeof(o.length) == "number") {
michael@0 1006 count += o.length - 1;
michael@0 1007 for (var i = o.length - 1; i >= 0; i--) {
michael@0 1008 sum += o[i];
michael@0 1009 }
michael@0 1010 } else {
michael@0 1011 sum += o;
michael@0 1012 }
michael@0 1013 }
michael@0 1014
michael@0 1015 if (count <= 0) {
michael@0 1016 throw new TypeError('mean() requires at least one argument');
michael@0 1017 }
michael@0 1018
michael@0 1019 return sum/count;
michael@0 1020 },
michael@0 1021
michael@0 1022 /** @id MochiKit.Base.median */
michael@0 1023 median: function(/* lst... */) {
michael@0 1024 /* http://www.nist.gov/dads/HTML/median.html */
michael@0 1025 var data = MochiKit.Base.flattenArguments(arguments);
michael@0 1026 if (data.length === 0) {
michael@0 1027 throw new TypeError('median() requires at least one argument');
michael@0 1028 }
michael@0 1029 data.sort(compare);
michael@0 1030 if (data.length % 2 == 0) {
michael@0 1031 var upper = data.length / 2;
michael@0 1032 return (data[upper] + data[upper - 1]) / 2;
michael@0 1033 } else {
michael@0 1034 return data[(data.length - 1) / 2];
michael@0 1035 }
michael@0 1036 },
michael@0 1037
michael@0 1038 /** @id MochiKit.Base.findValue */
michael@0 1039 findValue: function (lst, value, start/* = 0 */, /* optional */end) {
michael@0 1040 if (typeof(end) == "undefined" || end === null) {
michael@0 1041 end = lst.length;
michael@0 1042 }
michael@0 1043 if (typeof(start) == "undefined" || start === null) {
michael@0 1044 start = 0;
michael@0 1045 }
michael@0 1046 var cmp = MochiKit.Base.compare;
michael@0 1047 for (var i = start; i < end; i++) {
michael@0 1048 if (cmp(lst[i], value) === 0) {
michael@0 1049 return i;
michael@0 1050 }
michael@0 1051 }
michael@0 1052 return -1;
michael@0 1053 },
michael@0 1054
michael@0 1055 /** @id MochiKit.Base.nodeWalk */
michael@0 1056 nodeWalk: function (node, visitor) {
michael@0 1057 var nodes = [node];
michael@0 1058 var extend = MochiKit.Base.extend;
michael@0 1059 while (nodes.length) {
michael@0 1060 var res = visitor(nodes.shift());
michael@0 1061 if (res) {
michael@0 1062 extend(nodes, res);
michael@0 1063 }
michael@0 1064 }
michael@0 1065 },
michael@0 1066
michael@0 1067
michael@0 1068 /** @id MochiKit.Base.nameFunctions */
michael@0 1069 nameFunctions: function (namespace) {
michael@0 1070 var base = namespace.NAME;
michael@0 1071 if (typeof(base) == 'undefined') {
michael@0 1072 base = '';
michael@0 1073 } else {
michael@0 1074 base = base + '.';
michael@0 1075 }
michael@0 1076 for (var name in namespace) {
michael@0 1077 var o = namespace[name];
michael@0 1078 if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
michael@0 1079 try {
michael@0 1080 o.NAME = base + name;
michael@0 1081 } catch (e) {
michael@0 1082 // pass
michael@0 1083 }
michael@0 1084 }
michael@0 1085 }
michael@0 1086 },
michael@0 1087
michael@0 1088
michael@0 1089 /** @id MochiKit.Base.queryString */
michael@0 1090 queryString: function (names, values) {
michael@0 1091 // check to see if names is a string or a DOM element, and if
michael@0 1092 // MochiKit.DOM is available. If so, drop it like it's a form
michael@0 1093 // Ugliest conditional in MochiKit? Probably!
michael@0 1094 if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1
michael@0 1095 && (typeof(names) == "string" || (
michael@0 1096 typeof(names.nodeType) != "undefined" && names.nodeType > 0
michael@0 1097 ))
michael@0 1098 ) {
michael@0 1099 var kv = MochiKit.DOM.formContents(names);
michael@0 1100 names = kv[0];
michael@0 1101 values = kv[1];
michael@0 1102 } else if (arguments.length == 1) {
michael@0 1103 // Allow the return value of formContents to be passed directly
michael@0 1104 if (typeof(names.length) == "number" && names.length == 2) {
michael@0 1105 return arguments.callee(names[0], names[1]);
michael@0 1106 }
michael@0 1107 var o = names;
michael@0 1108 names = [];
michael@0 1109 values = [];
michael@0 1110 for (var k in o) {
michael@0 1111 var v = o[k];
michael@0 1112 if (typeof(v) == "function") {
michael@0 1113 continue;
michael@0 1114 } else if (typeof(v) != "string" &&
michael@0 1115 typeof(v.length) == "number") {
michael@0 1116 for (var i = 0; i < v.length; i++) {
michael@0 1117 names.push(k);
michael@0 1118 values.push(v[i]);
michael@0 1119 }
michael@0 1120 } else {
michael@0 1121 names.push(k);
michael@0 1122 values.push(v);
michael@0 1123 }
michael@0 1124 }
michael@0 1125 }
michael@0 1126 var rval = [];
michael@0 1127 var len = Math.min(names.length, values.length);
michael@0 1128 var urlEncode = MochiKit.Base.urlEncode;
michael@0 1129 for (var i = 0; i < len; i++) {
michael@0 1130 v = values[i];
michael@0 1131 if (typeof(v) != 'undefined' && v !== null) {
michael@0 1132 rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
michael@0 1133 }
michael@0 1134 }
michael@0 1135 return rval.join("&");
michael@0 1136 },
michael@0 1137
michael@0 1138
michael@0 1139 /** @id MochiKit.Base.parseQueryString */
michael@0 1140 parseQueryString: function (encodedString, useArrays) {
michael@0 1141 // strip a leading '?' from the encoded string
michael@0 1142 var qstr = (encodedString.charAt(0) == "?")
michael@0 1143 ? encodedString.substring(1)
michael@0 1144 : encodedString;
michael@0 1145 var pairs = qstr.replace(/\+/g, "%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
michael@0 1146 var o = {};
michael@0 1147 var decode;
michael@0 1148 if (typeof(decodeURIComponent) != "undefined") {
michael@0 1149 decode = decodeURIComponent;
michael@0 1150 } else {
michael@0 1151 decode = unescape;
michael@0 1152 }
michael@0 1153 if (useArrays) {
michael@0 1154 for (var i = 0; i < pairs.length; i++) {
michael@0 1155 var pair = pairs[i].split("=");
michael@0 1156 var name = decode(pair.shift());
michael@0 1157 if (!name) {
michael@0 1158 continue;
michael@0 1159 }
michael@0 1160 var arr = o[name];
michael@0 1161 if (!(arr instanceof Array)) {
michael@0 1162 arr = [];
michael@0 1163 o[name] = arr;
michael@0 1164 }
michael@0 1165 arr.push(decode(pair.join("=")));
michael@0 1166 }
michael@0 1167 } else {
michael@0 1168 for (i = 0; i < pairs.length; i++) {
michael@0 1169 pair = pairs[i].split("=");
michael@0 1170 var name = pair.shift();
michael@0 1171 if (!name) {
michael@0 1172 continue;
michael@0 1173 }
michael@0 1174 o[decode(name)] = decode(pair.join("="));
michael@0 1175 }
michael@0 1176 }
michael@0 1177 return o;
michael@0 1178 }
michael@0 1179 });
michael@0 1180
michael@0 1181 /** @id MochiKit.Base.AdapterRegistry */
michael@0 1182 MochiKit.Base.AdapterRegistry = function () {
michael@0 1183 this.pairs = [];
michael@0 1184 };
michael@0 1185
michael@0 1186 MochiKit.Base.AdapterRegistry.prototype = {
michael@0 1187 /** @id MochiKit.Base.AdapterRegistry.prototype.register */
michael@0 1188 register: function (name, check, wrap, /* optional */ override) {
michael@0 1189 if (override) {
michael@0 1190 this.pairs.unshift([name, check, wrap]);
michael@0 1191 } else {
michael@0 1192 this.pairs.push([name, check, wrap]);
michael@0 1193 }
michael@0 1194 },
michael@0 1195
michael@0 1196 /** @id MochiKit.Base.AdapterRegistry.prototype.match */
michael@0 1197 match: function (/* ... */) {
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[1].apply(this, arguments)) {
michael@0 1201 return pair[2].apply(this, arguments);
michael@0 1202 }
michael@0 1203 }
michael@0 1204 throw MochiKit.Base.NotFound;
michael@0 1205 },
michael@0 1206
michael@0 1207 /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
michael@0 1208 unregister: function (name) {
michael@0 1209 for (var i = 0; i < this.pairs.length; i++) {
michael@0 1210 var pair = this.pairs[i];
michael@0 1211 if (pair[0] == name) {
michael@0 1212 this.pairs.splice(i, 1);
michael@0 1213 return true;
michael@0 1214 }
michael@0 1215 }
michael@0 1216 return false;
michael@0 1217 }
michael@0 1218 };
michael@0 1219
michael@0 1220
michael@0 1221 MochiKit.Base.EXPORT = [
michael@0 1222 "flattenArray",
michael@0 1223 "noop",
michael@0 1224 "camelize",
michael@0 1225 "counter",
michael@0 1226 "clone",
michael@0 1227 "extend",
michael@0 1228 "update",
michael@0 1229 "updatetree",
michael@0 1230 "setdefault",
michael@0 1231 "keys",
michael@0 1232 "values",
michael@0 1233 "items",
michael@0 1234 "NamedError",
michael@0 1235 "operator",
michael@0 1236 "forwardCall",
michael@0 1237 "itemgetter",
michael@0 1238 "typeMatcher",
michael@0 1239 "isCallable",
michael@0 1240 "isUndefined",
michael@0 1241 "isUndefinedOrNull",
michael@0 1242 "isNull",
michael@0 1243 "isEmpty",
michael@0 1244 "isNotEmpty",
michael@0 1245 "isArrayLike",
michael@0 1246 "isDateLike",
michael@0 1247 "xmap",
michael@0 1248 "map",
michael@0 1249 "xfilter",
michael@0 1250 "filter",
michael@0 1251 "methodcaller",
michael@0 1252 "compose",
michael@0 1253 "bind",
michael@0 1254 "bindMethods",
michael@0 1255 "NotFound",
michael@0 1256 "AdapterRegistry",
michael@0 1257 "registerComparator",
michael@0 1258 "compare",
michael@0 1259 "registerRepr",
michael@0 1260 "repr",
michael@0 1261 "objEqual",
michael@0 1262 "arrayEqual",
michael@0 1263 "concat",
michael@0 1264 "keyComparator",
michael@0 1265 "reverseKeyComparator",
michael@0 1266 "partial",
michael@0 1267 "merge",
michael@0 1268 "listMinMax",
michael@0 1269 "listMax",
michael@0 1270 "listMin",
michael@0 1271 "objMax",
michael@0 1272 "objMin",
michael@0 1273 "nodeWalk",
michael@0 1274 "zip",
michael@0 1275 "urlEncode",
michael@0 1276 "queryString",
michael@0 1277 "serializeJSON",
michael@0 1278 "registerJSON",
michael@0 1279 "evalJSON",
michael@0 1280 "parseQueryString",
michael@0 1281 "findValue",
michael@0 1282 "findIdentical",
michael@0 1283 "flattenArguments",
michael@0 1284 "method",
michael@0 1285 "average",
michael@0 1286 "mean",
michael@0 1287 "median"
michael@0 1288 ];
michael@0 1289
michael@0 1290 MochiKit.Base.EXPORT_OK = [
michael@0 1291 "nameFunctions",
michael@0 1292 "comparatorRegistry",
michael@0 1293 "reprRegistry",
michael@0 1294 "jsonRegistry",
michael@0 1295 "compareDateLike",
michael@0 1296 "compareArrayLike",
michael@0 1297 "reprArrayLike",
michael@0 1298 "reprString",
michael@0 1299 "reprNumber"
michael@0 1300 ];
michael@0 1301
michael@0 1302 MochiKit.Base._exportSymbols = function (globals, module) {
michael@0 1303 if (!MochiKit.__export__) {
michael@0 1304 return;
michael@0 1305 }
michael@0 1306 var all = module.EXPORT_TAGS[":all"];
michael@0 1307 for (var i = 0; i < all.length; i++) {
michael@0 1308 globals[all[i]] = module[all[i]];
michael@0 1309 }
michael@0 1310 };
michael@0 1311
michael@0 1312 MochiKit.Base.__new__ = function () {
michael@0 1313 // A singleton raised when no suitable adapter is found
michael@0 1314 var m = this;
michael@0 1315
michael@0 1316 // convenience
michael@0 1317 /** @id MochiKit.Base.noop */
michael@0 1318 m.noop = m.operator.identity;
michael@0 1319
michael@0 1320 // Backwards compat
michael@0 1321 m.forward = m.forwardCall;
michael@0 1322 m.find = m.findValue;
michael@0 1323
michael@0 1324 if (typeof(encodeURIComponent) != "undefined") {
michael@0 1325 /** @id MochiKit.Base.urlEncode */
michael@0 1326 m.urlEncode = function (unencoded) {
michael@0 1327 return encodeURIComponent(unencoded).replace(/\'/g, '%27');
michael@0 1328 };
michael@0 1329 } else {
michael@0 1330 m.urlEncode = function (unencoded) {
michael@0 1331 return escape(unencoded
michael@0 1332 ).replace(/\+/g, '%2B'
michael@0 1333 ).replace(/\"/g,'%22'
michael@0 1334 ).rval.replace(/\'/g, '%27');
michael@0 1335 };
michael@0 1336 }
michael@0 1337
michael@0 1338 /** @id MochiKit.Base.NamedError */
michael@0 1339 m.NamedError = function (name) {
michael@0 1340 this.message = name;
michael@0 1341 this.name = name;
michael@0 1342 };
michael@0 1343 m.NamedError.prototype = new Error();
michael@0 1344 m.update(m.NamedError.prototype, {
michael@0 1345 repr: function () {
michael@0 1346 if (this.message && this.message != this.name) {
michael@0 1347 return this.name + "(" + m.repr(this.message) + ")";
michael@0 1348 } else {
michael@0 1349 return this.name + "()";
michael@0 1350 }
michael@0 1351 },
michael@0 1352 toString: m.forwardCall("repr")
michael@0 1353 });
michael@0 1354
michael@0 1355 /** @id MochiKit.Base.NotFound */
michael@0 1356 m.NotFound = new m.NamedError("MochiKit.Base.NotFound");
michael@0 1357
michael@0 1358
michael@0 1359 /** @id MochiKit.Base.listMax */
michael@0 1360 m.listMax = m.partial(m.listMinMax, 1);
michael@0 1361 /** @id MochiKit.Base.listMin */
michael@0 1362 m.listMin = m.partial(m.listMinMax, -1);
michael@0 1363
michael@0 1364 /** @id MochiKit.Base.isCallable */
michael@0 1365 m.isCallable = m.typeMatcher('function');
michael@0 1366 /** @id MochiKit.Base.isUndefined */
michael@0 1367 m.isUndefined = m.typeMatcher('undefined');
michael@0 1368
michael@0 1369 /** @id MochiKit.Base.merge */
michael@0 1370 m.merge = m.partial(m.update, null);
michael@0 1371 /** @id MochiKit.Base.zip */
michael@0 1372 m.zip = m.partial(m.map, null);
michael@0 1373
michael@0 1374 /** @id MochiKit.Base.average */
michael@0 1375 m.average = m.mean;
michael@0 1376
michael@0 1377 /** @id MochiKit.Base.comparatorRegistry */
michael@0 1378 m.comparatorRegistry = new m.AdapterRegistry();
michael@0 1379 m.registerComparator("dateLike", m.isDateLike, m.compareDateLike);
michael@0 1380 m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike);
michael@0 1381
michael@0 1382 /** @id MochiKit.Base.reprRegistry */
michael@0 1383 m.reprRegistry = new m.AdapterRegistry();
michael@0 1384 m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
michael@0 1385 m.registerRepr("string", m.typeMatcher("string"), m.reprString);
michael@0 1386 m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);
michael@0 1387
michael@0 1388 /** @id MochiKit.Base.jsonRegistry */
michael@0 1389 m.jsonRegistry = new m.AdapterRegistry();
michael@0 1390
michael@0 1391 var all = m.concat(m.EXPORT, m.EXPORT_OK);
michael@0 1392 m.EXPORT_TAGS = {
michael@0 1393 ":common": m.concat(m.EXPORT_OK),
michael@0 1394 ":all": all
michael@0 1395 };
michael@0 1396
michael@0 1397 m.nameFunctions(this);
michael@0 1398
michael@0 1399 };
michael@0 1400
michael@0 1401 MochiKit.Base.__new__();
michael@0 1402
michael@0 1403 //
michael@0 1404 // XXX: Internet Explorer blows
michael@0 1405 //
michael@0 1406 if (MochiKit.__export__) {
michael@0 1407 compare = MochiKit.Base.compare;
michael@0 1408 compose = MochiKit.Base.compose;
michael@0 1409 serializeJSON = MochiKit.Base.serializeJSON;
michael@0 1410 }
michael@0 1411
michael@0 1412 MochiKit.Base._exportSymbols(this, MochiKit.Base);

mercurial