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

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

mercurial