Wed, 31 Dec 2014 06:09:35 +0100
Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.
1 /***
3 MochiKit.Base 1.4
5 See <http://mochikit.com/> for documentation, downloads, license, etc.
7 (c) 2005 Bob Ippolito. All rights Reserved.
9 ***/
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 }
26 MochiKit.Base.VERSION = "1.4";
27 MochiKit.Base.NAME = "MochiKit.Base";
28 /** @id MochiKit.Base.update */
29 MochiKit.Base.update = function (self, obj/*, ... */) {
30 if (self === null) {
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 };
44 MochiKit.Base.update(MochiKit.Base, {
45 __repr__: function () {
46 return "[" + this.NAME + " " + this.VERSION + "]";
47 },
49 toString: function () {
50 return this.__repr__();
51 },
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 },
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 },
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 },
83 _flattenArray: function (res, lst) {
84 for (var i = 0; i < lst.length; i++) {
85 var o = lst[i];
86 if (o instanceof Array) {
87 arguments.callee(res, o);
88 } else {
89 res.push(o);
90 }
91 }
92 return res;
93 },
95 /** @id MochiKit.Base.flattenArray */
96 flattenArray: function (lst) {
97 return MochiKit.Base._flattenArray([], lst);
98 },
100 /** @id MochiKit.Base.flattenArguments */
101 flattenArguments: function (lst/* ...*/) {
102 var res = [];
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--) {
109 args.unshift(o[i]);
110 }
111 } else {
112 res.push(o);
113 }
114 }
115 return res;
116 },
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
122 if (!skip) {
123 skip = 0;
124 }
125 if (obj) {
126 // allow iterable fall-through, but skip the full isArrayLike
127 // check for speed, this is called often.
128 var l = obj.length;
129 if (typeof(l) != 'number' /* !isArrayLike(obj) */) {
130 if (typeof(MochiKit.Iter) != "undefined") {
131 obj = MochiKit.Iter.list(obj);
132 l = obj.length;
133 } else {
134 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
135 }
136 }
137 if (!self) {
138 self = [];
139 }
140 for (var i = skip; i < l; i++) {
141 self.push(obj[i]);
142 }
143 }
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
147 return self;
148 },
151 /** @id MochiKit.Base.updatetree */
152 updatetree: function (self, obj/*, ...*/) {
153 if (self === null) {
154 self = {};
155 }
156 for (var i = 1; i < arguments.length; i++) {
157 var o = arguments[i];
158 if (typeof(o) != 'undefined' && o !== null) {
159 for (var k in o) {
160 var v = o[k];
161 if (typeof(self[k]) == 'object' && typeof(v) == 'object') {
162 arguments.callee(self[k], v);
163 } else {
164 self[k] = v;
165 }
166 }
167 }
168 }
169 return self;
170 },
172 /** @id MochiKit.Base.setdefault */
173 setdefault: function (self, obj/*, ...*/) {
174 if (self === null) {
175 self = {};
176 }
177 for (var i = 1; i < arguments.length; i++) {
178 var o = arguments[i];
179 for (var k in o) {
180 if (!(k in self)) {
181 self[k] = o[k];
182 }
183 }
184 }
185 return self;
186 },
188 /** @id MochiKit.Base.keys */
189 keys: function (obj) {
190 var rval = [];
191 for (var prop in obj) {
192 rval.push(prop);
193 }
194 return rval;
195 },
197 /** @id MochiKit.Base.values */
198 values: function (obj) {
199 var rval = [];
200 for (var prop in obj) {
201 rval.push(obj[prop]);
202 }
203 return rval;
204 },
206 /** @id MochiKit.Base.items */
207 items: function (obj) {
208 var rval = [];
209 var e;
210 for (var prop in obj) {
211 var v;
212 try {
213 v = obj[prop];
214 } catch (e) {
215 continue;
216 }
217 rval.push([prop, v]);
218 }
219 return rval;
220 },
223 _newNamedError: function (module, name, func) {
224 func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name);
225 module[name] = func;
226 },
229 /** @id MochiKit.Base.operator */
230 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; },
245 // binary operators
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; }
310 },
312 /** @id MochiKit.Base.forwardCall */
313 forwardCall: function (func) {
314 return function () {
315 return this[func].apply(this, arguments);
316 };
317 },
319 /** @id MochiKit.Base.itemgetter */
320 itemgetter: function (func) {
321 return function (arg) {
322 return arg[func];
323 };
324 },
326 /** @id MochiKit.Base.typeMatcher */
327 typeMatcher: function (/* typ */) {
328 var types = {};
329 for (var i = 0; i < arguments.length; i++) {
330 var typ = arguments[i];
331 types[typ] = typ;
332 }
333 return function () {
334 for (var i = 0; i < arguments.length; i++) {
335 if (!(typeof(arguments[i]) in types)) {
336 return false;
337 }
338 }
339 return true;
340 };
341 },
343 /** @id MochiKit.Base.isNull */
344 isNull: function (/* ... */) {
345 for (var i = 0; i < arguments.length; i++) {
346 if (arguments[i] !== null) {
347 return false;
348 }
349 }
350 return true;
351 },
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)) {
358 return false;
359 }
360 }
361 return true;
362 },
364 /** @id MochiKit.Base.isEmpty */
365 isEmpty: function (obj) {
366 return !MochiKit.Base.isNotEmpty.apply(this, arguments);
367 },
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)) {
374 return false;
375 }
376 }
377 return true;
378 },
380 /** @id MochiKit.Base.isArrayLike */
381 isArrayLike: function () {
382 for (var i = 0; i < arguments.length; i++) {
383 var o = arguments[i];
384 var typ = typeof(o);
385 if (
386 (typ != 'object' && !(typ == 'function' && typeof(o.item) == 'function')) ||
387 o === null ||
388 typeof(o.length) != 'number' ||
389 o.nodeType === 3
390 ) {
391 return false;
392 }
393 }
394 return true;
395 },
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') {
403 return false;
404 }
405 }
406 return true;
407 },
410 /** @id MochiKit.Base.xmap */
411 xmap: function (fn/*, obj... */) {
412 if (fn === null) {
413 return MochiKit.Base.extend(null, arguments, 1);
414 }
415 var rval = [];
416 for (var i = 1; i < arguments.length; i++) {
417 rval.push(fn(arguments[i]));
418 }
419 return rval;
420 },
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)) {
430 if (itr) {
431 // fast path for map(null, iterable)
432 lst = itr.list(lst);
433 if (fn === null) {
434 return lst;
435 }
436 } else {
437 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
438 }
439 }
440 // fast path for map(null, lst)
441 if (fn === null) {
442 return m.extend(null, lst);
443 }
444 // disabled fast path for map(fn, lst)
445 /*
446 if (false && typeof(Array.prototype.map) == 'function') {
447 // Mozilla fast-path
448 return Array.prototype.map.call(lst, fn);
449 }
450 */
451 var rval = [];
452 for (var i = 0; i < lst.length; i++) {
453 rval.push(fn(lst[i]));
454 }
455 return rval;
456 } else {
457 // default for map(null, ...) is zip(...)
458 if (fn === null) {
459 fn = Array;
460 }
461 var length = null;
462 for (i = 1; i < arguments.length; i++) {
463 // allow iterables to be passed
464 if (!isArrayLike(arguments[i])) {
465 if (itr) {
466 return itr.list(itr.imap.apply(null, arguments));
467 } else {
468 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
469 }
470 }
471 // find the minimum length
472 var l = arguments[i].length;
473 if (length === null || length > l) {
474 length = l;
475 }
476 }
477 rval = [];
478 for (i = 0; i < length; i++) {
479 var args = [];
480 for (var j = 1; j < arguments.length; j++) {
481 args.push(arguments[j][i]);
482 }
483 rval.push(fn.apply(this, args));
484 }
485 return rval;
486 }
487 },
489 /** @id MochiKit.Base.xfilter */
490 xfilter: function (fn/*, obj... */) {
491 var rval = [];
492 if (fn === null) {
493 fn = MochiKit.Base.operator.truth;
494 }
495 for (var i = 1; i < arguments.length; i++) {
496 var o = arguments[i];
497 if (fn(o)) {
498 rval.push(o);
499 }
500 }
501 return rval;
502 },
504 /** @id MochiKit.Base.filter */
505 filter: function (fn, lst, self) {
506 var rval = [];
507 // allow an iterable to be passed
508 var m = MochiKit.Base;
509 if (!m.isArrayLike(lst)) {
510 if (MochiKit.Iter) {
511 lst = MochiKit.Iter.list(lst);
512 } else {
513 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
514 }
515 }
516 if (fn === null) {
517 fn = m.operator.truth;
518 }
519 if (typeof(Array.prototype.filter) == 'function') {
520 // Mozilla fast-path
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++) {
524 var o = lst[i];
525 if (fn(o)) {
526 rval.push(o);
527 }
528 }
529 } else {
530 for (i = 0; i < lst.length; i++) {
531 o = lst[i];
532 if (fn.call(self, o)) {
533 rval.push(o);
534 }
535 }
536 }
537 return rval;
538 },
541 _wrapDumbFunction: function (func) {
542 return function () {
543 // fast path!
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]);
549 }
550 var args = [];
551 for (var i = 0; i < arguments.length; i++) {
552 args.push("arguments[" + i + "]");
553 }
554 return eval("(func(" + args.join(",") + "))");
555 };
556 },
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);
564 };
565 } else {
566 return function (obj) {
567 return obj[func].apply(obj, args);
568 };
569 }
570 },
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));
576 },
578 /** @id MochiKit.Base.compose */
579 compose: function (f1, f2/*, f3, ... fN */) {
580 var fnlist = [];
581 var m = MochiKit.Base;
582 if (arguments.length === 0) {
583 throw new TypeError("compose() requires at least one argument");
584 }
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");
589 }
590 fnlist.push(fn);
591 }
592 return function () {
593 var args = arguments;
594 for (var i = fnlist.length - 1; i >= 0; i--) {
595 args = [fnlist[i].apply(this, args)];
596 }
597 return args[0];
598 };
599 },
601 /** @id MochiKit.Base.bind */
602 bind: function (func, self/* args... */) {
603 if (typeof(func) == "string") {
604 func = self[func];
605 }
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
613 // an apply
614 func = m._wrapDumbFunction(func);
615 }
616 if (typeof(im_func) != 'function') {
617 im_func = func;
618 }
619 if (typeof(self) != 'undefined') {
620 im_self = self;
621 }
622 if (typeof(im_preargs) == 'undefined') {
623 im_preargs = [];
624 } else {
625 im_preargs = im_preargs.slice();
626 }
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);
633 }
634 var self = me.im_self;
635 if (!self) {
636 self = this;
637 }
638 return me.im_func.apply(self, args);
639 };
640 newfunc.im_self = im_self;
641 newfunc.im_func = im_func;
642 newfunc.im_preargs = im_preargs;
643 return newfunc;
644 },
646 /** @id MochiKit.Base.bindMethods */
647 bindMethods: function (self) {
648 var bind = MochiKit.Base.bind;
649 for (var k in self) {
650 var func = self[k];
651 if (typeof(func) == 'function') {
652 self[k] = bind(func, self);
653 }
654 }
655 },
657 /** @id MochiKit.Base.registerComparator */
658 registerComparator: function (name, check, comparator, /* optional */ override) {
659 MochiKit.Base.comparatorRegistry.register(name, check, comparator, override);
660 },
662 _primitives: {'boolean': true, 'string': true, 'number': true},
664 /** @id MochiKit.Base.compare */
665 compare: function (a, b) {
666 if (a == b) {
667 return 0;
668 }
669 var aIsNull = (typeof(a) == 'undefined' || a === null);
670 var bIsNull = (typeof(b) == 'undefined' || b === null);
671 if (aIsNull && bIsNull) {
672 return 0;
673 } else if (aIsNull) {
674 return -1;
675 } else if (bIsNull) {
676 return 1;
677 }
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)) {
682 try {
683 return m.comparatorRegistry.match(a, b);
684 } catch (e) {
685 if (e != m.NotFound) {
686 throw e;
687 }
688 }
689 }
690 if (a < b) {
691 return -1;
692 } else if (a > b) {
693 return 1;
694 }
695 // These types can't be compared
696 var repr = m.repr;
697 throw new TypeError(repr(a) + " and " + repr(b) + " can not be compared");
698 },
700 /** @id MochiKit.Base.compareDateLike */
701 compareDateLike: function (a, b) {
702 return MochiKit.Base.compare(a.getTime(), b.getTime());
703 },
705 /** @id MochiKit.Base.compareArrayLike */
706 compareArrayLike: function (a, b) {
707 var compare = MochiKit.Base.compare;
708 var count = a.length;
709 var rval = 0;
710 if (count > b.length) {
711 rval = 1;
712 count = b.length;
713 } else if (count < b.length) {
714 rval = -1;
715 }
716 for (var i = 0; i < count; i++) {
717 var cmp = compare(a[i], b[i]);
718 if (cmp) {
719 return cmp;
720 }
721 }
722 return rval;
723 },
725 /** @id MochiKit.Base.registerRepr */
726 registerRepr: function (name, check, wrap, /* optional */override) {
727 MochiKit.Base.reprRegistry.register(name, check, wrap, override);
728 },
730 /** @id MochiKit.Base.repr */
731 repr: function (o) {
732 if (typeof(o) == "undefined") {
733 return "undefined";
734 } else if (o === null) {
735 return "null";
736 }
737 try {
738 if (typeof(o.__repr__) == 'function') {
739 return o.__repr__();
740 } else if (typeof(o.repr) == 'function' && o.repr != arguments.callee) {
741 return o.repr();
742 }
743 return MochiKit.Base.reprRegistry.match(o);
744 } catch (e) {
745 try {
746 if (typeof(o.NAME) == 'string' && (
747 o.toString == Function.prototype.toString ||
748 o.toString == Object.prototype.toString
749 )) {
750 return o.NAME;
751 }
752 } catch (e) {
753 }
754 }
755 try {
756 var ostring = (o + "");
757 } catch (e) {
758 return "[" + typeof(o) + "]";
759 }
760 if (typeof(o) == "function") {
761 o = ostring.replace(/^\s+/, "");
762 var idx = o.indexOf("{");
763 if (idx != -1) {
764 o = o.substr(0, idx) + "{...}";
765 }
766 }
767 return ostring;
768 },
770 /** @id MochiKit.Base.reprArrayLike */
771 reprArrayLike: function (o) {
772 var m = MochiKit.Base;
773 return "[" + m.map(m.repr, o).join(", ") + "]";
774 },
776 /** @id MochiKit.Base.reprString */
777 reprString: function (o) {
778 return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
779 ).replace(/[\f]/g, "\\f"
780 ).replace(/[\b]/g, "\\b"
781 ).replace(/[\n]/g, "\\n"
782 ).replace(/[\t]/g, "\\t"
783 ).replace(/[\r]/g, "\\r");
784 },
786 /** @id MochiKit.Base.reprNumber */
787 reprNumber: function (o) {
788 return o + "";
789 },
791 /** @id MochiKit.Base.registerJSON */
792 registerJSON: function (name, check, wrap, /* optional */override) {
793 MochiKit.Base.jsonRegistry.register(name, check, wrap, override);
794 },
797 /** @id MochiKit.Base.evalJSON */
798 evalJSON: function () {
799 return eval("(" + arguments[0] + ")");
800 },
802 /** @id MochiKit.Base.serializeJSON */
803 serializeJSON: function (o) {
804 var objtype = typeof(o);
805 if (objtype == "number" || objtype == "boolean") {
806 return o + "";
807 } else if (o === null) {
808 return "null";
809 }
810 var m = MochiKit.Base;
811 var reprString = m.reprString;
812 if (objtype == "string") {
813 return reprString(o);
814 }
815 // recurse
816 var me = arguments.callee;
817 // short-circuit for objects that support "json" serialization
818 // if they return "self" then just pass-through...
819 var newObj;
820 if (typeof(o.__json__) == "function") {
821 newObj = o.__json__();
822 if (o !== newObj) {
823 return me(newObj);
824 }
825 }
826 if (typeof(o.json) == "function") {
827 newObj = o.json();
828 if (o !== newObj) {
829 return me(newObj);
830 }
831 }
832 // array
833 if (objtype != "function" && typeof(o.length) == "number") {
834 var res = [];
835 for (var i = 0; i < o.length; i++) {
836 var val = me(o[i]);
837 if (typeof(val) != "string") {
838 val = "undefined";
839 }
840 res.push(val);
841 }
842 return "[" + res.join(", ") + "]";
843 }
844 // look in the registry
845 try {
846 newObj = m.jsonRegistry.match(o);
847 if (o !== newObj) {
848 return me(newObj);
849 }
850 } catch (e) {
851 if (e != m.NotFound) {
852 // something really bad happened
853 throw e;
854 }
855 }
856 // undefined is outside of the spec
857 if (objtype == "undefined") {
858 throw new TypeError("undefined can not be serialized as JSON");
859 }
860 // it's a function with no adapter, bad
861 if (objtype == "function") {
862 return null;
863 }
864 // generic object code path
865 res = [];
866 for (var k in o) {
867 var useKey;
868 if (typeof(k) == "number") {
869 useKey = '"' + k + '"';
870 } else if (typeof(k) == "string") {
871 useKey = reprString(k);
872 } else {
873 // skip non-string or number keys
874 continue;
875 }
876 val = me(o[k]);
877 if (typeof(val) != "string") {
878 // skip non-serializable values
879 continue;
880 }
881 res.push(useKey + ":" + val);
882 }
883 return "{" + res.join(", ") + "}";
884 },
887 /** @id MochiKit.Base.objEqual */
888 objEqual: function (a, b) {
889 return (MochiKit.Base.compare(a, b) === 0);
890 },
892 /** @id MochiKit.Base.arrayEqual */
893 arrayEqual: function (self, arr) {
894 if (self.length != arr.length) {
895 return false;
896 }
897 return (MochiKit.Base.compare(self, arr) === 0);
898 },
900 /** @id MochiKit.Base.concat */
901 concat: function (/* lst... */) {
902 var rval = [];
903 var extend = MochiKit.Base.extend;
904 for (var i = 0; i < arguments.length; i++) {
905 extend(rval, arguments[i]);
906 }
907 return rval;
908 },
910 /** @id MochiKit.Base.keyComparator */
911 keyComparator: function (key/* ... */) {
912 // fast-path for single key comparisons
913 var m = MochiKit.Base;
914 var compare = m.compare;
915 if (arguments.length == 1) {
916 return function (a, b) {
917 return compare(a[key], b[key]);
918 };
919 }
920 var compareKeys = m.extend(null, arguments);
921 return function (a, b) {
922 var rval = 0;
923 // keep comparing until something is inequal or we run out of
924 // keys to compare
925 for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) {
926 var key = compareKeys[i];
927 rval = compare(a[key], b[key]);
928 }
929 return rval;
930 };
931 },
933 /** @id MochiKit.Base.reverseKeyComparator */
934 reverseKeyComparator: function (key) {
935 var comparator = MochiKit.Base.keyComparator.apply(this, arguments);
936 return function (a, b) {
937 return comparator(b, a);
938 };
939 },
941 /** @id MochiKit.Base.partial */
942 partial: function (func) {
943 var m = MochiKit.Base;
944 return m.bind.apply(this, m.extend([func, undefined], arguments, 1));
945 },
947 /** @id MochiKit.Base.listMinMax */
948 listMinMax: function (which, lst) {
949 if (lst.length === 0) {
950 return null;
951 }
952 var cur = lst[0];
953 var compare = MochiKit.Base.compare;
954 for (var i = 1; i < lst.length; i++) {
955 var o = lst[i];
956 if (compare(o, cur) == which) {
957 cur = o;
958 }
959 }
960 return cur;
961 },
963 /** @id MochiKit.Base.objMax */
964 objMax: function (/* obj... */) {
965 return MochiKit.Base.listMinMax(1, arguments);
966 },
968 /** @id MochiKit.Base.objMin */
969 objMin: function (/* obj... */) {
970 return MochiKit.Base.listMinMax(-1, arguments);
971 },
973 /** @id MochiKit.Base.findIdentical */
974 findIdentical: function (lst, value, start/* = 0 */, /* optional */end) {
975 if (typeof(end) == "undefined" || end === null) {
976 end = lst.length;
977 }
978 if (typeof(start) == "undefined" || start === null) {
979 start = 0;
980 }
981 for (var i = start; i < end; i++) {
982 if (lst[i] === value) {
983 return i;
984 }
985 }
986 return -1;
987 },
989 /** @id MochiKit.Base.mean */
990 mean: function(/* lst... */) {
991 /* http://www.nist.gov/dads/HTML/mean.html */
992 var sum = 0;
994 var m = MochiKit.Base;
995 var args = m.extend(null, arguments);
996 var count = args.length;
998 while (args.length) {
999 var o = args.shift();
1000 if (o && typeof(o) == "object" && typeof(o.length) == "number") {
1001 count += o.length - 1;
1002 for (var i = o.length - 1; i >= 0; i--) {
1003 sum += o[i];
1004 }
1005 } else {
1006 sum += o;
1007 }
1008 }
1010 if (count <= 0) {
1011 throw new TypeError('mean() requires at least one argument');
1012 }
1014 return sum/count;
1015 },
1017 /** @id MochiKit.Base.median */
1018 median: function(/* lst... */) {
1019 /* http://www.nist.gov/dads/HTML/median.html */
1020 var data = MochiKit.Base.flattenArguments(arguments);
1021 if (data.length === 0) {
1022 throw new TypeError('median() requires at least one argument');
1023 }
1024 data.sort(compare);
1025 if (data.length % 2 == 0) {
1026 var upper = data.length / 2;
1027 return (data[upper] + data[upper - 1]) / 2;
1028 } else {
1029 return data[(data.length - 1) / 2];
1030 }
1031 },
1033 /** @id MochiKit.Base.findValue */
1034 findValue: function (lst, value, start/* = 0 */, /* optional */end) {
1035 if (typeof(end) == "undefined" || end === null) {
1036 end = lst.length;
1037 }
1038 if (typeof(start) == "undefined" || start === null) {
1039 start = 0;
1040 }
1041 var cmp = MochiKit.Base.compare;
1042 for (var i = start; i < end; i++) {
1043 if (cmp(lst[i], value) === 0) {
1044 return i;
1045 }
1046 }
1047 return -1;
1048 },
1050 /** @id MochiKit.Base.nodeWalk */
1051 nodeWalk: function (node, visitor) {
1052 var nodes = [node];
1053 var extend = MochiKit.Base.extend;
1054 while (nodes.length) {
1055 var res = visitor(nodes.shift());
1056 if (res) {
1057 extend(nodes, res);
1058 }
1059 }
1060 },
1063 /** @id MochiKit.Base.nameFunctions */
1064 nameFunctions: function (namespace) {
1065 var base = namespace.NAME;
1066 if (typeof(base) == 'undefined') {
1067 base = '';
1068 } else {
1069 base = base + '.';
1070 }
1071 for (var name in namespace) {
1072 var o = namespace[name];
1073 if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
1074 try {
1075 o.NAME = base + name;
1076 } catch (e) {
1077 // pass
1078 }
1079 }
1080 }
1081 },
1084 /** @id MochiKit.Base.queryString */
1085 queryString: function (names, values) {
1086 // check to see if names is a string or a DOM element, and if
1087 // MochiKit.DOM is available. If so, drop it like it's a form
1088 // Ugliest conditional in MochiKit? Probably!
1089 if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1
1090 && (typeof(names) == "string" || (
1091 typeof(names.nodeType) != "undefined" && names.nodeType > 0
1092 ))
1093 ) {
1094 var kv = MochiKit.DOM.formContents(names);
1095 names = kv[0];
1096 values = kv[1];
1097 } else if (arguments.length == 1) {
1098 var o = names;
1099 names = [];
1100 values = [];
1101 for (var k in o) {
1102 var v = o[k];
1103 if (typeof(v) == "function") {
1104 continue;
1105 } else if (typeof(v) != "string" &&
1106 typeof(v.length) == "number") {
1107 for (var i = 0; i < v.length; i++) {
1108 names.push(k);
1109 values.push(v[i]);
1110 }
1111 } else {
1112 names.push(k);
1113 values.push(v);
1114 }
1115 }
1116 }
1117 var rval = [];
1118 var len = Math.min(names.length, values.length);
1119 var urlEncode = MochiKit.Base.urlEncode;
1120 for (var i = 0; i < len; i++) {
1121 v = values[i];
1122 if (typeof(v) != 'undefined' && v !== null) {
1123 rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
1124 }
1125 }
1126 return rval.join("&");
1127 },
1130 /** @id MochiKit.Base.parseQueryString */
1131 parseQueryString: function (encodedString, useArrays) {
1132 // strip a leading '?' from the encoded string
1133 var qstr = (encodedString[0] == "?") ? encodedString.substring(1) :
1134 encodedString;
1135 var pairs = qstr.replace(/\+/g, "%20").split(/(\&\;|\&\#38\;|\&|\&)/);
1136 var o = {};
1137 var decode;
1138 if (typeof(decodeURIComponent) != "undefined") {
1139 decode = decodeURIComponent;
1140 } else {
1141 decode = unescape;
1142 }
1143 if (useArrays) {
1144 for (var i = 0; i < pairs.length; i++) {
1145 var pair = pairs[i].split("=");
1146 if (pair.length !== 2) {
1147 continue;
1148 }
1149 var name = decode(pair[0]);
1150 var arr = o[name];
1151 if (!(arr instanceof Array)) {
1152 arr = [];
1153 o[name] = arr;
1154 }
1155 arr.push(decode(pair[1]));
1156 }
1157 } else {
1158 for (i = 0; i < pairs.length; i++) {
1159 pair = pairs[i].split("=");
1160 if (pair.length !== 2) {
1161 continue;
1162 }
1163 o[decode(pair[0])] = decode(pair[1]);
1164 }
1165 }
1166 return o;
1167 }
1168 });
1170 /** @id MochiKit.Base.AdapterRegistry */
1171 MochiKit.Base.AdapterRegistry = function () {
1172 this.pairs = [];
1173 };
1175 MochiKit.Base.AdapterRegistry.prototype = {
1176 /** @id MochiKit.Base.AdapterRegistry.prototype.register */
1177 register: function (name, check, wrap, /* optional */ override) {
1178 if (override) {
1179 this.pairs.unshift([name, check, wrap]);
1180 } else {
1181 this.pairs.push([name, check, wrap]);
1182 }
1183 },
1185 /** @id MochiKit.Base.AdapterRegistry.prototype.match */
1186 match: function (/* ... */) {
1187 for (var i = 0; i < this.pairs.length; i++) {
1188 var pair = this.pairs[i];
1189 if (pair[1].apply(this, arguments)) {
1190 return pair[2].apply(this, arguments);
1191 }
1192 }
1193 throw MochiKit.Base.NotFound;
1194 },
1196 /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
1197 unregister: function (name) {
1198 for (var i = 0; i < this.pairs.length; i++) {
1199 var pair = this.pairs[i];
1200 if (pair[0] == name) {
1201 this.pairs.splice(i, 1);
1202 return true;
1203 }
1204 }
1205 return false;
1206 }
1207 };
1210 MochiKit.Base.EXPORT = [
1211 "flattenArray",
1212 "noop",
1213 "camelize",
1214 "counter",
1215 "clone",
1216 "extend",
1217 "update",
1218 "updatetree",
1219 "setdefault",
1220 "keys",
1221 "values",
1222 "items",
1223 "NamedError",
1224 "operator",
1225 "forwardCall",
1226 "itemgetter",
1227 "typeMatcher",
1228 "isCallable",
1229 "isUndefined",
1230 "isUndefinedOrNull",
1231 "isNull",
1232 "isEmpty",
1233 "isNotEmpty",
1234 "isArrayLike",
1235 "isDateLike",
1236 "xmap",
1237 "map",
1238 "xfilter",
1239 "filter",
1240 "methodcaller",
1241 "compose",
1242 "bind",
1243 "bindMethods",
1244 "NotFound",
1245 "AdapterRegistry",
1246 "registerComparator",
1247 "compare",
1248 "registerRepr",
1249 "repr",
1250 "objEqual",
1251 "arrayEqual",
1252 "concat",
1253 "keyComparator",
1254 "reverseKeyComparator",
1255 "partial",
1256 "merge",
1257 "listMinMax",
1258 "listMax",
1259 "listMin",
1260 "objMax",
1261 "objMin",
1262 "nodeWalk",
1263 "zip",
1264 "urlEncode",
1265 "queryString",
1266 "serializeJSON",
1267 "registerJSON",
1268 "evalJSON",
1269 "parseQueryString",
1270 "findValue",
1271 "findIdentical",
1272 "flattenArguments",
1273 "method",
1274 "average",
1275 "mean",
1276 "median"
1277 ];
1279 MochiKit.Base.EXPORT_OK = [
1280 "nameFunctions",
1281 "comparatorRegistry",
1282 "reprRegistry",
1283 "jsonRegistry",
1284 "compareDateLike",
1285 "compareArrayLike",
1286 "reprArrayLike",
1287 "reprString",
1288 "reprNumber"
1289 ];
1291 MochiKit.Base._exportSymbols = function (globals, module) {
1292 if (!MochiKit.__export__) {
1293 return;
1294 }
1295 var all = module.EXPORT_TAGS[":all"];
1296 for (var i = 0; i < all.length; i++) {
1297 globals[all[i]] = module[all[i]];
1298 }
1299 };
1301 MochiKit.Base.__new__ = function () {
1302 // A singleton raised when no suitable adapter is found
1303 var m = this;
1305 // convenience
1306 /** @id MochiKit.Base.noop */
1307 m.noop = m.operator.identity;
1309 // Backwards compat
1310 m.forward = m.forwardCall;
1311 m.find = m.findValue;
1313 if (typeof(encodeURIComponent) != "undefined") {
1314 /** @id MochiKit.Base.urlEncode */
1315 m.urlEncode = function (unencoded) {
1316 return encodeURIComponent(unencoded).replace(/\'/g, '%27');
1317 };
1318 } else {
1319 m.urlEncode = function (unencoded) {
1320 return escape(unencoded
1321 ).replace(/\+/g, '%2B'
1322 ).replace(/\"/g,'%22'
1323 ).rval.replace(/\'/g, '%27');
1324 };
1325 }
1327 /** @id MochiKit.Base.NamedError */
1328 m.NamedError = function (name) {
1329 this.message = name;
1330 this.name = name;
1331 };
1332 m.NamedError.prototype = new Error();
1333 m.update(m.NamedError.prototype, {
1334 repr: function () {
1335 if (this.message && this.message != this.name) {
1336 return this.name + "(" + m.repr(this.message) + ")";
1337 } else {
1338 return this.name + "()";
1339 }
1340 },
1341 toString: m.forwardCall("repr")
1342 });
1344 /** @id MochiKit.Base.NotFound */
1345 m.NotFound = new m.NamedError("MochiKit.Base.NotFound");
1348 /** @id MochiKit.Base.listMax */
1349 m.listMax = m.partial(m.listMinMax, 1);
1350 /** @id MochiKit.Base.listMin */
1351 m.listMin = m.partial(m.listMinMax, -1);
1353 /** @id MochiKit.Base.isCallable */
1354 m.isCallable = m.typeMatcher('function');
1355 /** @id MochiKit.Base.isUndefined */
1356 m.isUndefined = m.typeMatcher('undefined');
1358 /** @id MochiKit.Base.merge */
1359 m.merge = m.partial(m.update, null);
1360 /** @id MochiKit.Base.zip */
1361 m.zip = m.partial(m.map, null);
1363 /** @id MochiKit.Base.average */
1364 m.average = m.mean;
1366 /** @id MochiKit.Base.comparatorRegistry */
1367 m.comparatorRegistry = new m.AdapterRegistry();
1368 m.registerComparator("dateLike", m.isDateLike, m.compareDateLike);
1369 m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike);
1371 /** @id MochiKit.Base.reprRegistry */
1372 m.reprRegistry = new m.AdapterRegistry();
1373 m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
1374 m.registerRepr("string", m.typeMatcher("string"), m.reprString);
1375 m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);
1377 /** @id MochiKit.Base.jsonRegistry */
1378 m.jsonRegistry = new m.AdapterRegistry();
1380 var all = m.concat(m.EXPORT, m.EXPORT_OK);
1381 m.EXPORT_TAGS = {
1382 ":common": m.concat(m.EXPORT_OK),
1383 ":all": all
1384 };
1386 m.nameFunctions(this);
1388 };
1390 MochiKit.Base.__new__();
1392 //
1393 // XXX: Internet Explorer blows
1394 //
1395 if (MochiKit.__export__) {
1396 compare = MochiKit.Base.compare;
1397 compose = MochiKit.Base.compose;
1398 serializeJSON = MochiKit.Base.serializeJSON;
1399 }
1401 MochiKit.Base._exportSymbols(this, MochiKit.Base);