5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005 Bob Ippolito. All rights Reserved.
11 if (typeof(dojo
) != 'undefined') {
12 dojo
.provide("MochiKit.Base");
14 if (typeof(MochiKit
) == 'undefined') {
17 if (typeof(MochiKit
.Base
) == 'undefined') {
20 if (typeof(MochiKit
.__export__
) == "undefined") {
21 MochiKit
.__export__
= (MochiKit
.__compat__
||
22 (typeof(JSAN
) == 'undefined' && typeof(dojo
) == 'undefined')
26 MochiKit
.Base
.VERSION
= "1.4";
27 MochiKit
.Base
.NAME
= "MochiKit.Base";
28 /** @id MochiKit.Base.update */
29 MochiKit
.Base
.update
= function (self
, obj
/*, ... */) {
33 for (var i
= 1; i
< arguments
.length
; i
++) {
35 if (typeof(o
) != 'undefined' && o
!== null) {
44 MochiKit
.Base
.update(MochiKit
.Base
, {
45 __repr__
: function () {
46 return "[" + this.NAME
+ " " + this.VERSION
+ "]";
49 toString
: function () {
50 return this.__repr__();
53 /** @id MochiKit.Base.camelize */
54 camelize
: function (selector
) {
55 /* from dojo.style.toCamelCase */
56 var arr
= selector
.split('-');
58 for (var i
= 1; i
< arr
.length
; i
++) {
59 cc
+= arr
[i
].charAt(0).toUpperCase() + arr
[i
].substring(1);
64 /** @id MochiKit.Base.counter */
65 counter
: function (n
/* = 1 */) {
66 if (arguments
.length
=== 0) {
74 /** @id MochiKit.Base.clone */
75 clone
: function (obj
) {
76 var me
= arguments
.callee
;
77 if (arguments
.length
== 1) {
83 _flattenArray
: function (res
, lst
) {
84 for (var i
= 0; i
< lst
.length
; i
++) {
86 if (o
instanceof Array
) {
87 arguments
.callee(res
, o
);
95 /** @id MochiKit.Base.flattenArray */
96 flattenArray
: function (lst
) {
97 return MochiKit
.Base
._flattenArray([], lst
);
100 /** @id MochiKit.Base.flattenArguments */
101 flattenArguments
: function (lst
/* ...*/) {
103 var m
= MochiKit
.Base
;
104 var args
= m
.extend(null, arguments
);
105 while (args
.length
) {
106 var o
= args
.shift();
107 if (o
&& typeof(o
) == "object" && typeof(o
.length
) == "number") {
108 for (var i
= o
.length
- 1; i
>= 0; i
--) {
118 /** @id MochiKit.Base.extend */
119 extend
: function (self
, obj
, /* optional */skip
) {
120 // Extend an array with an array-like object starting
121 // from the skip index
126 // allow iterable fall-through, but skip the full isArrayLike
127 // check for speed, this is called often.
129 if (typeof(l
) != 'number' /* !isArrayLike(obj) */) {
130 if (typeof(MochiKit
.Iter
) != "undefined") {
131 obj
= MochiKit
.Iter
.list(obj
);
134 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
140 for (var i
= skip
; i
< l
; i
++) {
144 // This mutates, but it's convenient to return because
145 // it's often used like a constructor when turning some
146 // ghetto array-like to a real array
151 /** @id MochiKit.Base.updatetree */
152 updatetree
: function (self
, obj
/*, ...*/) {
156 for (var i
= 1; i
< arguments
.length
; i
++) {
157 var o
= arguments
[i
];
158 if (typeof(o
) != 'undefined' && o
!== null) {
161 if (typeof(self
[k
]) == 'object' && typeof(v
) == 'object') {
162 arguments
.callee(self
[k
], v
);
172 /** @id MochiKit.Base.setdefault */
173 setdefault
: function (self
, obj
/*, ...*/) {
177 for (var i
= 1; i
< arguments
.length
; i
++) {
178 var o
= arguments
[i
];
188 /** @id MochiKit.Base.keys */
189 keys
: function (obj
) {
191 for (var prop
in obj
) {
197 /** @id MochiKit.Base.values */
198 values
: function (obj
) {
200 for (var prop
in obj
) {
201 rval
.push(obj
[prop
]);
206 /** @id MochiKit.Base.items */
207 items
: function (obj
) {
210 for (var prop
in obj
) {
217 rval
.push([prop
, v
]);
223 _newNamedError
: function (module
, name
, func
) {
224 func
.prototype = new MochiKit
.Base
.NamedError(module
.NAME
+ "." + name
);
229 /** @id MochiKit.Base.operator */
231 // unary logic operators
232 /** @id MochiKit.Base.truth */
233 truth
: function (a
) { return !!a
; },
234 /** @id MochiKit.Base.lognot */
235 lognot
: function (a
) { return !a
; },
236 /** @id MochiKit.Base.identity */
237 identity
: function (a
) { return a
; },
239 // bitwise unary operators
240 /** @id MochiKit.Base.not */
241 not
: function (a
) { return ~a
; },
242 /** @id MochiKit.Base.neg */
243 neg
: function (a
) { return -a
; },
246 /** @id MochiKit.Base.add */
247 add
: function (a
, b
) { return a
+ b
; },
248 /** @id MochiKit.Base.sub */
249 sub
: function (a
, b
) { return a
- b
; },
250 /** @id MochiKit.Base.div */
251 div
: function (a
, b
) { return a
/ b
; },
252 /** @id MochiKit.Base.mod */
253 mod
: function (a
, b
) { return a
% b
; },
254 /** @id MochiKit.Base.mul */
255 mul
: function (a
, b
) { return a
* b
; },
257 // bitwise binary operators
258 /** @id MochiKit.Base.and */
259 and
: function (a
, b
) { return a
& b
; },
260 /** @id MochiKit.Base.or */
261 or
: function (a
, b
) { return a
| b
; },
262 /** @id MochiKit.Base.xor */
263 xor
: function (a
, b
) { return a
^ b
; },
264 /** @id MochiKit.Base.lshift */
265 lshift
: function (a
, b
) { return a
<< b
; },
266 /** @id MochiKit.Base.rshift */
267 rshift
: function (a
, b
) { return a
>> b
; },
268 /** @id MochiKit.Base.zrshift */
269 zrshift
: function (a
, b
) { return a
>>> b
; },
271 // near-worthless built-in comparators
272 /** @id MochiKit.Base.eq */
273 eq
: function (a
, b
) { return a
== b
; },
274 /** @id MochiKit.Base.ne */
275 ne
: function (a
, b
) { return a
!= b
; },
276 /** @id MochiKit.Base.gt */
277 gt
: function (a
, b
) { return a
> b
; },
278 /** @id MochiKit.Base.ge */
279 ge
: function (a
, b
) { return a
>= b
; },
280 /** @id MochiKit.Base.lt */
281 lt
: function (a
, b
) { return a
< b
; },
282 /** @id MochiKit.Base.le */
283 le
: function (a
, b
) { return a
<= b
; },
285 // strict built-in comparators
286 seq
: function (a
, b
) { return a
=== b
; },
287 sne
: function (a
, b
) { return a
!== b
; },
289 // compare comparators
290 /** @id MochiKit.Base.ceq */
291 ceq
: function (a
, b
) { return MochiKit
.Base
.compare(a
, b
) === 0; },
292 /** @id MochiKit.Base.cne */
293 cne
: function (a
, b
) { return MochiKit
.Base
.compare(a
, b
) !== 0; },
294 /** @id MochiKit.Base.cgt */
295 cgt
: function (a
, b
) { return MochiKit
.Base
.compare(a
, b
) == 1; },
296 /** @id MochiKit.Base.cge */
297 cge
: function (a
, b
) { return MochiKit
.Base
.compare(a
, b
) != -1; },
298 /** @id MochiKit.Base.clt */
299 clt
: function (a
, b
) { return MochiKit
.Base
.compare(a
, b
) == -1; },
300 /** @id MochiKit.Base.cle */
301 cle
: function (a
, b
) { return MochiKit
.Base
.compare(a
, b
) != 1; },
303 // binary logical operators
304 /** @id MochiKit.Base.logand */
305 logand
: function (a
, b
) { return a
&& b
; },
306 /** @id MochiKit.Base.logor */
307 logor
: function (a
, b
) { return a
|| b
; },
308 /** @id MochiKit.Base.contains */
309 contains
: function (a
, b
) { return b
in a
; }
312 /** @id MochiKit.Base.forwardCall */
313 forwardCall
: function (func
) {
315 return this[func
].apply(this, arguments
);
319 /** @id MochiKit.Base.itemgetter */
320 itemgetter
: function (func
) {
321 return function (arg
) {
326 /** @id MochiKit.Base.typeMatcher */
327 typeMatcher
: function (/* typ */) {
329 for (var i
= 0; i
< arguments
.length
; i
++) {
330 var typ
= arguments
[i
];
334 for (var i
= 0; i
< arguments
.length
; i
++) {
335 if (!(typeof(arguments
[i
]) in types
)) {
343 /** @id MochiKit.Base.isNull */
344 isNull
: function (/* ... */) {
345 for (var i
= 0; i
< arguments
.length
; i
++) {
346 if (arguments
[i
] !== null) {
353 /** @id MochiKit.Base.isUndefinedOrNull */
354 isUndefinedOrNull
: function (/* ... */) {
355 for (var i
= 0; i
< arguments
.length
; i
++) {
356 var o
= arguments
[i
];
357 if (!(typeof(o
) == 'undefined' || o
=== null)) {
364 /** @id MochiKit.Base.isEmpty */
365 isEmpty
: function (obj
) {
366 return !MochiKit
.Base
.isNotEmpty
.apply(this, arguments
);
369 /** @id MochiKit.Base.isNotEmpty */
370 isNotEmpty
: function (obj
) {
371 for (var i
= 0; i
< arguments
.length
; i
++) {
372 var o
= arguments
[i
];
373 if (!(o
&& o
.length
)) {
380 /** @id MochiKit.Base.isArrayLike */
381 isArrayLike
: function () {
382 for (var i
= 0; i
< arguments
.length
; i
++) {
383 var o
= arguments
[i
];
386 (typ
!= 'object' && !(typ
== 'function' && typeof(o
.item
) == 'function')) ||
388 typeof(o
.length
) != 'number' ||
397 /** @id MochiKit.Base.isDateLike */
398 isDateLike
: function () {
399 for (var i
= 0; i
< arguments
.length
; i
++) {
400 var o
= arguments
[i
];
401 if (typeof(o
) != "object" || o
=== null
402 || typeof(o
.getTime
) != 'function') {
410 /** @id MochiKit.Base.xmap */
411 xmap
: function (fn
/*, obj... */) {
413 return MochiKit
.Base
.extend(null, arguments
, 1);
416 for (var i
= 1; i
< arguments
.length
; i
++) {
417 rval
.push(fn(arguments
[i
]));
422 /** @id MochiKit.Base.map */
423 map
: function (fn
, lst
/*, lst... */) {
424 var m
= MochiKit
.Base
;
425 var itr
= MochiKit
.Iter
;
426 var isArrayLike
= m
.isArrayLike
;
427 if (arguments
.length
<= 2) {
428 // allow an iterable to be passed
429 if (!isArrayLike(lst
)) {
431 // fast path for map(null, iterable)
437 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
440 // fast path for map(null, lst)
442 return m
.extend(null, lst
);
444 // disabled fast path for map(fn, lst)
446 if (false && typeof(Array.prototype.map) == 'function') {
448 return Array.prototype.map.call(lst, fn);
452 for (var i
= 0; i
< lst
.length
; i
++) {
453 rval
.push(fn(lst
[i
]));
457 // default for map(null, ...) is zip(...)
462 for (i
= 1; i
< arguments
.length
; i
++) {
463 // allow iterables to be passed
464 if (!isArrayLike(arguments
[i
])) {
466 return itr
.list(itr
.imap
.apply(null, arguments
));
468 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
471 // find the minimum length
472 var l
= arguments
[i
].length
;
473 if (length
=== null || length
> l
) {
478 for (i
= 0; i
< length
; i
++) {
480 for (var j
= 1; j
< arguments
.length
; j
++) {
481 args
.push(arguments
[j
][i
]);
483 rval
.push(fn
.apply(this, args
));
489 /** @id MochiKit.Base.xfilter */
490 xfilter
: function (fn
/*, obj... */) {
493 fn
= MochiKit
.Base
.operator
.truth
;
495 for (var i
= 1; i
< arguments
.length
; i
++) {
496 var o
= arguments
[i
];
504 /** @id MochiKit.Base.filter */
505 filter
: function (fn
, lst
, self
) {
507 // allow an iterable to be passed
508 var m
= MochiKit
.Base
;
509 if (!m
.isArrayLike(lst
)) {
511 lst
= MochiKit
.Iter
.list(lst
);
513 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
517 fn
= m
.operator
.truth
;
519 if (typeof(Array
.prototype.filter
) == 'function') {
521 return Array
.prototype.filter
.call(lst
, fn
, self
);
522 } else if (typeof(self
) == 'undefined' || self
=== null) {
523 for (var i
= 0; i
< lst
.length
; i
++) {
530 for (i
= 0; i
< lst
.length
; i
++) {
532 if (fn
.call(self
, o
)) {
541 _wrapDumbFunction
: function (func
) {
544 switch (arguments
.length
) {
545 case 0: return func();
546 case 1: return func(arguments
[0]);
547 case 2: return func(arguments
[0], arguments
[1]);
548 case 3: return func(arguments
[0], arguments
[1], arguments
[2]);
551 for (var i
= 0; i
< arguments
.length
; i
++) {
552 args
.push("arguments[" + i
+ "]");
554 return eval("(func(" + args
.join(",") + "))");
558 /** @id MochiKit.Base.methodcaller */
559 methodcaller
: function (func
/*, args... */) {
560 var args
= MochiKit
.Base
.extend(null, arguments
, 1);
561 if (typeof(func
) == "function") {
562 return function (obj
) {
563 return func
.apply(obj
, args
);
566 return function (obj
) {
567 return obj
[func
].apply(obj
, args
);
572 /** @id MochiKit.Base.method */
573 method
: function (self
, func
) {
574 var m
= MochiKit
.Base
;
575 return m
.bind
.apply(this, m
.extend([func
, self
], arguments
, 2));
578 /** @id MochiKit.Base.compose */
579 compose
: function (f1
, f2
/*, f3, ... fN */) {
581 var m
= MochiKit
.Base
;
582 if (arguments
.length
=== 0) {
583 throw new TypeError("compose() requires at least one argument");
585 for (var i
= 0; i
< arguments
.length
; i
++) {
586 var fn
= arguments
[i
];
587 if (typeof(fn
) != "function") {
588 throw new TypeError(m
.repr(fn
) + " is not a function");
593 var args
= arguments
;
594 for (var i
= fnlist
.length
- 1; i
>= 0; i
--) {
595 args
= [fnlist
[i
].apply(this, args
)];
601 /** @id MochiKit.Base.bind */
602 bind
: function (func
, self
/* args... */) {
603 if (typeof(func
) == "string") {
606 var im_func
= func
.im_func
;
607 var im_preargs
= func
.im_preargs
;
608 var im_self
= func
.im_self
;
609 var m
= MochiKit
.Base
;
610 if (typeof(func
) == "function" && typeof(func
.apply
) == "undefined") {
611 // this is for cases where JavaScript sucks ass and gives you a
612 // really dumb built-in function like alert() that doesn't have
614 func
= m
._wrapDumbFunction(func
);
616 if (typeof(im_func
) != 'function') {
619 if (typeof(self
) != 'undefined') {
622 if (typeof(im_preargs
) == 'undefined') {
625 im_preargs
= im_preargs
.slice();
627 m
.extend(im_preargs
, arguments
, 2);
628 var newfunc
= function () {
629 var args
= arguments
;
630 var me
= arguments
.callee
;
631 if (me
.im_preargs
.length
> 0) {
632 args
= m
.concat(me
.im_preargs
, args
);
634 var self
= me
.im_self
;
638 return me
.im_func
.apply(self
, args
);
640 newfunc
.im_self
= im_self
;
641 newfunc
.im_func
= im_func
;
642 newfunc
.im_preargs
= im_preargs
;
646 /** @id MochiKit.Base.bindMethods */
647 bindMethods
: function (self
) {
648 var bind
= MochiKit
.Base
.bind
;
649 for (var k
in self
) {
651 if (typeof(func
) == 'function') {
652 self
[k
] = bind(func
, self
);
657 /** @id MochiKit.Base.registerComparator */
658 registerComparator
: function (name
, check
, comparator
, /* optional */ override
) {
659 MochiKit
.Base
.comparatorRegistry
.register(name
, check
, comparator
, override
);
662 _primitives
: {'boolean': true, 'string': true, 'number': true},
664 /** @id MochiKit.Base.compare */
665 compare
: function (a
, b
) {
669 var aIsNull
= (typeof(a
) == 'undefined' || a
=== null);
670 var bIsNull
= (typeof(b
) == 'undefined' || b
=== null);
671 if (aIsNull
&& bIsNull
) {
673 } else if (aIsNull
) {
675 } else if (bIsNull
) {
678 var m
= MochiKit
.Base
;
679 // bool, number, string have meaningful comparisons
680 var prim
= m
._primitives
;
681 if (!(typeof(a
) in prim
&& typeof(b
) in prim
)) {
683 return m
.comparatorRegistry
.match(a
, b
);
685 if (e
!= m
.NotFound
) {
695 // These types can't be compared
697 throw new TypeError(repr(a
) + " and " + repr(b
) + " can not be compared");
700 /** @id MochiKit.Base.compareDateLike */
701 compareDateLike
: function (a
, b
) {
702 return MochiKit
.Base
.compare(a
.getTime(), b
.getTime());
705 /** @id MochiKit.Base.compareArrayLike */
706 compareArrayLike
: function (a
, b
) {
707 var compare
= MochiKit
.Base
.compare
;
708 var count
= a
.length
;
710 if (count
> b
.length
) {
713 } else if (count
< b
.length
) {
716 for (var i
= 0; i
< count
; i
++) {
717 var cmp
= compare(a
[i
], b
[i
]);
725 /** @id MochiKit.Base.registerRepr */
726 registerRepr
: function (name
, check
, wrap
, /* optional */override
) {
727 MochiKit
.Base
.reprRegistry
.register(name
, check
, wrap
, override
);
730 /** @id MochiKit.Base.repr */
732 if (typeof(o
) == "undefined") {
734 } else if (o
=== null) {
738 if (typeof(o
.__repr__
) == 'function') {
740 } else if (typeof(o
.repr
) == 'function' && o
.repr
!= arguments
.callee
) {
743 return MochiKit
.Base
.reprRegistry
.match(o
);
745 if (typeof(o
.NAME
) == 'string' && (
746 o
.toString
== Function
.prototype.toString
||
747 o
.toString
== Object
.prototype.toString
753 var ostring
= (o
+ "");
755 return "[" + typeof(o
) + "]";
757 if (typeof(o
) == "function") {
758 o
= ostring
.replace(/^\s+/, "");
759 var idx
= o
.indexOf("{");
761 o
= o
.substr(0, idx
) + "{...}";
767 /** @id MochiKit.Base.reprArrayLike */
768 reprArrayLike
: function (o
) {
769 var m
= MochiKit
.Base
;
770 return "[" + m
.map(m
.repr
, o
).join(", ") + "]";
773 /** @id MochiKit.Base.reprString */
774 reprString
: function (o
) {
775 return ('"' + o
.replace(/(["\\])/g, '\\$1') + '"'
776 ).replace(/[\f]/g, "\\f"
777 ).replace(/[\b]/g, "\\b"
778 ).replace(/[\n]/g, "\\n"
779 ).replace(/[\t]/g, "\\t"
780 ).replace(/[\r]/g, "\\r");
783 /** @id MochiKit.Base.reprNumber */
784 reprNumber
: function (o
) {
788 /** @id MochiKit.Base.registerJSON */
789 registerJSON
: function (name
, check
, wrap
, /* optional */override
) {
790 MochiKit
.Base
.jsonRegistry
.register(name
, check
, wrap
, override
);
794 /** @id MochiKit.Base.evalJSON */
795 evalJSON
: function () {
796 return eval("(" + arguments
[0] + ")");
799 /** @id MochiKit.Base.serializeJSON */
800 serializeJSON
: function (o
) {
801 var objtype
= typeof(o
);
802 if (objtype
== "number" || objtype
== "boolean") {
804 } else if (o
=== null) {
807 var m
= MochiKit
.Base
;
808 var reprString
= m
.reprString
;
809 if (objtype
== "string") {
810 return reprString(o
);
813 var me
= arguments
.callee
;
814 // short-circuit for objects that support "json" serialization
815 // if they return "self" then just pass-through...
817 if (typeof(o
.__json__
) == "function") {
818 newObj
= o
.__json__();
823 if (typeof(o
.json
) == "function") {
830 if (objtype
!= "function" && typeof(o
.length
) == "number") {
832 for (var i
= 0; i
< o
.length
; i
++) {
834 if (typeof(val
) != "string") {
839 return "[" + res
.join(", ") + "]";
841 // look in the registry
843 newObj
= m
.jsonRegistry
.match(o
);
848 if (e
!= m
.NotFound
) {
849 // something really bad happened
853 // undefined is outside of the spec
854 if (objtype
== "undefined") {
855 throw new TypeError("undefined can not be serialized as JSON");
857 // it's a function with no adapter, bad
858 if (objtype
== "function") {
861 // generic object code path
865 if (typeof(k
) == "number") {
866 useKey
= '"' + k
+ '"';
867 } else if (typeof(k
) == "string") {
868 useKey
= reprString(k
);
870 // skip non-string or number keys
874 if (typeof(val
) != "string") {
875 // skip non-serializable values
878 res
.push(useKey
+ ":" + val
);
880 return "{" + res
.join(", ") + "}";
884 /** @id MochiKit.Base.objEqual */
885 objEqual
: function (a
, b
) {
886 return (MochiKit
.Base
.compare(a
, b
) === 0);
889 /** @id MochiKit.Base.arrayEqual */
890 arrayEqual
: function (self
, arr
) {
891 if (self
.length
!= arr
.length
) {
894 return (MochiKit
.Base
.compare(self
, arr
) === 0);
897 /** @id MochiKit.Base.concat */
898 concat
: function (/* lst... */) {
900 var extend
= MochiKit
.Base
.extend
;
901 for (var i
= 0; i
< arguments
.length
; i
++) {
902 extend(rval
, arguments
[i
]);
907 /** @id MochiKit.Base.keyComparator */
908 keyComparator
: function (key
/* ... */) {
909 // fast-path for single key comparisons
910 var m
= MochiKit
.Base
;
911 var compare
= m
.compare
;
912 if (arguments
.length
== 1) {
913 return function (a
, b
) {
914 return compare(a
[key
], b
[key
]);
917 var compareKeys
= m
.extend(null, arguments
);
918 return function (a
, b
) {
920 // keep comparing until something is inequal or we run out of
922 for (var i
= 0; (rval
=== 0) && (i
< compareKeys
.length
); i
++) {
923 var key
= compareKeys
[i
];
924 rval
= compare(a
[key
], b
[key
]);
930 /** @id MochiKit.Base.reverseKeyComparator */
931 reverseKeyComparator
: function (key
) {
932 var comparator
= MochiKit
.Base
.keyComparator
.apply(this, arguments
);
933 return function (a
, b
) {
934 return comparator(b
, a
);
938 /** @id MochiKit.Base.partial */
939 partial
: function (func
) {
940 var m
= MochiKit
.Base
;
941 return m
.bind
.apply(this, m
.extend([func
, undefined
], arguments
, 1));
944 /** @id MochiKit.Base.listMinMax */
945 listMinMax
: function (which
, lst
) {
946 if (lst
.length
=== 0) {
950 var compare
= MochiKit
.Base
.compare
;
951 for (var i
= 1; i
< lst
.length
; i
++) {
953 if (compare(o
, cur
) == which
) {
960 /** @id MochiKit.Base.objMax */
961 objMax
: function (/* obj... */) {
962 return MochiKit
.Base
.listMinMax(1, arguments
);
965 /** @id MochiKit.Base.objMin */
966 objMin
: function (/* obj... */) {
967 return MochiKit
.Base
.listMinMax(-1, arguments
);
970 /** @id MochiKit.Base.findIdentical */
971 findIdentical
: function (lst
, value
, start
/* = 0 */, /* optional */end
) {
972 if (typeof(end
) == "undefined" || end
=== null) {
975 if (typeof(start
) == "undefined" || start
=== null) {
978 for (var i
= start
; i
< end
; i
++) {
979 if (lst
[i
] === value
) {
986 /** @id MochiKit.Base.mean */
987 mean
: function(/* lst... */) {
988 /* http://www.nist.gov/dads/HTML/mean.html */
991 var m
= MochiKit
.Base
;
992 var args
= m
.extend(null, arguments
);
993 var count
= args
.length
;
995 while (args
.length
) {
996 var o
= args
.shift();
997 if (o
&& typeof(o
) == "object" && typeof(o
.length
) == "number") {
998 count
+= o
.length
- 1;
999 for (var i
= o
.length
- 1; i
>= 0; i
--) {
1008 throw new TypeError('mean() requires at least one argument');
1014 /** @id MochiKit.Base.median */
1015 median
: function(/* lst... */) {
1016 /* http://www.nist.gov/dads/HTML/median.html */
1017 var data
= MochiKit
.Base
.flattenArguments(arguments
);
1018 if (data
.length
=== 0) {
1019 throw new TypeError('median() requires at least one argument');
1022 if (data
.length
% 2 == 0) {
1023 var upper
= data
.length
/ 2;
1024 return (data
[upper
] + data
[upper
- 1]) / 2;
1026 return data
[(data
.length
- 1) / 2];
1030 /** @id MochiKit.Base.findValue */
1031 findValue
: function (lst
, value
, start
/* = 0 */, /* optional */end
) {
1032 if (typeof(end
) == "undefined" || end
=== null) {
1035 if (typeof(start
) == "undefined" || start
=== null) {
1038 var cmp
= MochiKit
.Base
.compare
;
1039 for (var i
= start
; i
< end
; i
++) {
1040 if (cmp(lst
[i
], value
) === 0) {
1047 /** @id MochiKit.Base.nodeWalk */
1048 nodeWalk
: function (node
, visitor
) {
1050 var extend
= MochiKit
.Base
.extend
;
1051 while (nodes
.length
) {
1052 var res
= visitor(nodes
.shift());
1060 /** @id MochiKit.Base.nameFunctions */
1061 nameFunctions
: function (namespace) {
1062 var base
= namespace.NAME
;
1063 if (typeof(base
) == 'undefined') {
1068 for (var name
in namespace) {
1069 var o
= namespace[name
];
1070 if (typeof(o
) == 'function' && typeof(o
.NAME
) == 'undefined') {
1072 o
.NAME
= base
+ name
;
1081 /** @id MochiKit.Base.queryString */
1082 queryString
: function (names
, values
) {
1083 // check to see if names is a string or a DOM element, and if
1084 // MochiKit.DOM is available. If so, drop it like it's a form
1085 // Ugliest conditional in MochiKit? Probably!
1086 if (typeof(MochiKit
.DOM
) != "undefined" && arguments
.length
== 1
1087 && (typeof(names
) == "string" || (
1088 typeof(names
.nodeType
) != "undefined" && names
.nodeType
> 0
1091 var kv
= MochiKit
.DOM
.formContents(names
);
1094 } else if (arguments
.length
== 1) {
1095 // Allow the return value of formContents to be passed directly
1096 if (typeof(names
.length
) == "number" && names
.length
== 2) {
1097 return arguments
.callee(names
[0], names
[1]);
1104 if (typeof(v
) == "function") {
1106 } else if (typeof(v
) != "string" &&
1107 typeof(v
.length
) == "number") {
1108 for (var i
= 0; i
< v
.length
; i
++) {
1119 var len
= Math
.min(names
.length
, values
.length
);
1120 var urlEncode
= MochiKit
.Base
.urlEncode
;
1121 for (var i
= 0; i
< len
; i
++) {
1123 if (typeof(v
) != 'undefined' && v
!== null) {
1124 rval
.push(urlEncode(names
[i
]) + "=" + urlEncode(v
));
1127 return rval
.join("&");
1131 /** @id MochiKit.Base.parseQueryString */
1132 parseQueryString
: function (encodedString
, useArrays
) {
1133 // strip a leading '?' from the encoded string
1134 var qstr
= (encodedString
.charAt(0) == "?")
1135 ? encodedString
.substring(1)
1137 var pairs
= qstr
.replace(/\+/g, "%20").split(/(\&\;|\&\#38\;|\&|\&)/);
1140 if (typeof(decodeURIComponent
) != "undefined") {
1141 decode
= decodeURIComponent
;
1146 for (var i
= 0; i
< pairs
.length
; i
++) {
1147 var pair
= pairs
[i
].split("=");
1148 var name
= decode(pair
.shift());
1153 if (!(arr
instanceof Array
)) {
1157 arr
.push(decode(pair
.join("=")));
1160 for (i
= 0; i
< pairs
.length
; i
++) {
1161 pair
= pairs
[i
].split("=");
1162 var name
= pair
.shift();
1166 o
[decode(name
)] = decode(pair
.join("="));
1173 /** @id MochiKit.Base.AdapterRegistry */
1174 MochiKit
.Base
.AdapterRegistry
= function () {
1178 MochiKit
.Base
.AdapterRegistry
.prototype = {
1179 /** @id MochiKit.Base.AdapterRegistry.prototype.register */
1180 register
: function (name
, check
, wrap
, /* optional */ override
) {
1182 this.pairs
.unshift([name
, check
, wrap
]);
1184 this.pairs
.push([name
, check
, wrap
]);
1188 /** @id MochiKit.Base.AdapterRegistry.prototype.match */
1189 match
: function (/* ... */) {
1190 for (var i
= 0; i
< this.pairs
.length
; i
++) {
1191 var pair
= this.pairs
[i
];
1192 if (pair
[1].apply(this, arguments
)) {
1193 return pair
[2].apply(this, arguments
);
1196 throw MochiKit
.Base
.NotFound
;
1199 /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
1200 unregister
: function (name
) {
1201 for (var i
= 0; i
< this.pairs
.length
; i
++) {
1202 var pair
= this.pairs
[i
];
1203 if (pair
[0] == name
) {
1204 this.pairs
.splice(i
, 1);
1213 MochiKit
.Base
.EXPORT
= [
1233 "isUndefinedOrNull",
1249 "registerComparator",
1257 "reverseKeyComparator",
1282 MochiKit
.Base
.EXPORT_OK
= [
1284 "comparatorRegistry",
1294 MochiKit
.Base
._exportSymbols
= function (globals
, module
) {
1295 if (!MochiKit
.__export__
) {
1298 var all
= module
.EXPORT_TAGS
[":all"];
1299 for (var i
= 0; i
< all
.length
; i
++) {
1300 globals
[all
[i
]] = module
[all
[i
]];
1304 MochiKit
.Base
.__new__
= function () {
1305 // A singleton raised when no suitable adapter is found
1309 /** @id MochiKit.Base.noop */
1310 m
.noop
= m
.operator
.identity
;
1313 m
.forward
= m
.forwardCall
;
1314 m
.find
= m
.findValue
;
1316 if (typeof(encodeURIComponent
) != "undefined") {
1317 /** @id MochiKit.Base.urlEncode */
1318 m
.urlEncode
= function (unencoded
) {
1319 return encodeURIComponent(unencoded
).replace(/\'/g, '%27');
1322 m
.urlEncode
= function (unencoded
) {
1323 return escape(unencoded
1324 ).replace(/\+/g, '%2B'
1325 ).replace(/\"/g,'%22'
1326 ).rval
.replace(/\'/g, '%27');
1330 /** @id MochiKit.Base.NamedError */
1331 m
.NamedError
= function (name
) {
1332 this.message
= name
;
1335 m
.NamedError
.prototype = new Error();
1336 m
.update(m
.NamedError
.prototype, {
1338 if (this.message
&& this.message
!= this.name
) {
1339 return this.name
+ "(" + m
.repr(this.message
) + ")";
1341 return this.name
+ "()";
1344 toString
: m
.forwardCall("repr")
1347 /** @id MochiKit.Base.NotFound */
1348 m
.NotFound
= new m
.NamedError("MochiKit.Base.NotFound");
1351 /** @id MochiKit.Base.listMax */
1352 m
.listMax
= m
.partial(m
.listMinMax
, 1);
1353 /** @id MochiKit.Base.listMin */
1354 m
.listMin
= m
.partial(m
.listMinMax
, -1);
1356 /** @id MochiKit.Base.isCallable */
1357 m
.isCallable
= m
.typeMatcher('function');
1358 /** @id MochiKit.Base.isUndefined */
1359 m
.isUndefined
= m
.typeMatcher('undefined');
1361 /** @id MochiKit.Base.merge */
1362 m
.merge
= m
.partial(m
.update
, null);
1363 /** @id MochiKit.Base.zip */
1364 m
.zip
= m
.partial(m
.map
, null);
1366 /** @id MochiKit.Base.average */
1369 /** @id MochiKit.Base.comparatorRegistry */
1370 m
.comparatorRegistry
= new m
.AdapterRegistry();
1371 m
.registerComparator("dateLike", m
.isDateLike
, m
.compareDateLike
);
1372 m
.registerComparator("arrayLike", m
.isArrayLike
, m
.compareArrayLike
);
1374 /** @id MochiKit.Base.reprRegistry */
1375 m
.reprRegistry
= new m
.AdapterRegistry();
1376 m
.registerRepr("arrayLike", m
.isArrayLike
, m
.reprArrayLike
);
1377 m
.registerRepr("string", m
.typeMatcher("string"), m
.reprString
);
1378 m
.registerRepr("numbers", m
.typeMatcher("number", "boolean"), m
.reprNumber
);
1380 /** @id MochiKit.Base.jsonRegistry */
1381 m
.jsonRegistry
= new m
.AdapterRegistry();
1383 var all
= m
.concat(m
.EXPORT
, m
.EXPORT_OK
);
1385 ":common": m
.concat(m
.EXPORT_OK
),
1389 m
.nameFunctions(this);
1393 MochiKit
.Base
.__new__();
1396 // XXX: Internet Explorer blows
1398 if (MochiKit
.__export__
) {
1399 compare
= MochiKit
.Base
.compare
;
1400 compose
= MochiKit
.Base
.compose
;
1401 serializeJSON
= MochiKit
.Base
.serializeJSON
;
1404 MochiKit
.Base
._exportSymbols(this, MochiKit
.Base
);