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 if (pair.length !== 2) {
1151 var name = decode(pair[0]);
1153 if (!(arr instanceof Array)) {
1157 arr.push(decode(pair[1]));
1160 for (i = 0; i < pairs.length; i++) {
1161 pair = pairs[i].split("=");
1162 if (pair.length !== 2) {
1165 o[decode(pair[0])] = decode(pair[1]);
1172 /** @id MochiKit.Base.AdapterRegistry */
1173 MochiKit.Base.AdapterRegistry = function () {
1177 MochiKit.Base.AdapterRegistry.prototype = {
1178 /** @id MochiKit.Base.AdapterRegistry.prototype.register */
1179 register: function (name, check, wrap, /* optional */ override) {
1181 this.pairs.unshift([name, check, wrap]);
1183 this.pairs.push([name, check, wrap]);
1187 /** @id MochiKit.Base.AdapterRegistry.prototype.match */
1188 match: function (/* ... */) {
1189 for (var i = 0; i < this.pairs.length; i++) {
1190 var pair = this.pairs[i];
1191 if (pair[1].apply(this, arguments)) {
1192 return pair[2].apply(this, arguments);
1195 throw MochiKit.Base.NotFound;
1198 /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
1199 unregister: function (name) {
1200 for (var i = 0; i < this.pairs.length; i++) {
1201 var pair = this.pairs[i];
1202 if (pair[0] == name) {
1203 this.pairs.splice(i, 1);
1212 MochiKit.Base.EXPORT = [
1232 "isUndefinedOrNull",
1248 "registerComparator",
1256 "reverseKeyComparator",
1281 MochiKit.Base.EXPORT_OK = [
1283 "comparatorRegistry",
1293 MochiKit.Base._exportSymbols = function (globals, module) {
1294 if (!MochiKit.__export__) {
1297 var all = module.EXPORT_TAGS[":all"];
1298 for (var i = 0; i < all.length; i++) {
1299 globals[all[i]] = module[all[i]];
1303 MochiKit.Base.__new__ = function () {
1304 // A singleton raised when no suitable adapter is found
1308 /** @id MochiKit.Base.noop */
1309 m.noop = m.operator.identity;
1312 m.forward = m.forwardCall;
1313 m.find = m.findValue;
1315 if (typeof(encodeURIComponent) != "undefined") {
1316 /** @id MochiKit.Base.urlEncode */
1317 m.urlEncode = function (unencoded) {
1318 return encodeURIComponent(unencoded).replace(/\'/g, '%27');
1321 m.urlEncode = function (unencoded) {
1322 return escape(unencoded
1323 ).replace(/\+/g, '%2B'
1324 ).replace(/\"/g,'%22'
1325 ).rval.replace(/\'/g, '%27');
1329 /** @id MochiKit.Base.NamedError */
1330 m.NamedError = function (name) {
1331 this.message = name;
1334 m.NamedError.prototype = new Error();
1335 m.update(m.NamedError.prototype, {
1337 if (this.message && this.message != this.name) {
1338 return this.name + "(" + m.repr(this.message) + ")";
1340 return this.name + "()";
1343 toString: m.forwardCall("repr")
1346 /** @id MochiKit.Base.NotFound */
1347 m.NotFound = new m.NamedError("MochiKit.Base.NotFound");
1350 /** @id MochiKit.Base.listMax */
1351 m.listMax = m.partial(m.listMinMax, 1);
1352 /** @id MochiKit.Base.listMin */
1353 m.listMin = m.partial(m.listMinMax, -1);
1355 /** @id MochiKit.Base.isCallable */
1356 m.isCallable = m.typeMatcher('function');
1357 /** @id MochiKit.Base.isUndefined */
1358 m.isUndefined = m.typeMatcher('undefined');
1360 /** @id MochiKit.Base.merge */
1361 m.merge = m.partial(m.update, null);
1362 /** @id MochiKit.Base.zip */
1363 m.zip = m.partial(m.map, null);
1365 /** @id MochiKit.Base.average */
1368 /** @id MochiKit.Base.comparatorRegistry */
1369 m.comparatorRegistry = new m.AdapterRegistry();
1370 m.registerComparator("dateLike", m.isDateLike, m.compareDateLike);
1371 m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike);
1373 /** @id MochiKit.Base.reprRegistry */
1374 m.reprRegistry = new m.AdapterRegistry();
1375 m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
1376 m.registerRepr("string", m.typeMatcher("string"), m.reprString);
1377 m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);
1379 /** @id MochiKit.Base.jsonRegistry */
1380 m.jsonRegistry = new m.AdapterRegistry();
1382 var all = m.concat(m.EXPORT, m.EXPORT_OK);
1384 ":common": m.concat(m.EXPORT_OK),
1388 m.nameFunctions(this);
1392 MochiKit.Base.__new__();
1395 // XXX: Internet Explorer blows
1397 if (MochiKit.__export__) {
1398 compare = MochiKit.Base.compare;
1399 compose = MochiKit.Base.compose;
1400 serializeJSON = MochiKit.Base.serializeJSON;
1403 MochiKit.Base._exportSymbols(this, MochiKit.Base);