testing/mochitest/tests/MochiKit-1.4.2/MochiKit/Base.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

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

mercurial