summaryrefslogtreecommitdiff
path: root/frontend/beta/js/MochiKit
Unidiff
Diffstat (limited to 'frontend/beta/js/MochiKit') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/beta/js/MochiKit/Async.js683
-rw-r--r--frontend/beta/js/MochiKit/Base.js1403
-rw-r--r--frontend/beta/js/MochiKit/Color.js902
-rw-r--r--frontend/beta/js/MochiKit/Controls.js1388
-rw-r--r--frontend/beta/js/MochiKit/DOM.js1267
-rw-r--r--frontend/beta/js/MochiKit/DateTime.js216
-rw-r--r--frontend/beta/js/MochiKit/DragAndDrop.js824
-rw-r--r--frontend/beta/js/MochiKit/Format.js304
-rw-r--r--frontend/beta/js/MochiKit/Iter.js843
-rw-r--r--frontend/beta/js/MochiKit/Logging.js321
-rw-r--r--frontend/beta/js/MochiKit/LoggingPane.js374
-rw-r--r--frontend/beta/js/MochiKit/MochiKit.js154
-rw-r--r--frontend/beta/js/MochiKit/MockDOM.js115
-rw-r--r--frontend/beta/js/MochiKit/New.js1
-rw-r--r--frontend/beta/js/MochiKit/Position.js246
-rw-r--r--frontend/beta/js/MochiKit/Selector.js431
-rw-r--r--frontend/beta/js/MochiKit/Signal.js864
-rw-r--r--frontend/beta/js/MochiKit/Sortable.js589
-rw-r--r--frontend/beta/js/MochiKit/Style.js444
-rw-r--r--frontend/beta/js/MochiKit/Test.js181
-rw-r--r--frontend/beta/js/MochiKit/Visual.js1976
-rw-r--r--frontend/beta/js/MochiKit/__package__.js18
22 files changed, 13544 insertions, 0 deletions
diff --git a/frontend/beta/js/MochiKit/Async.js b/frontend/beta/js/MochiKit/Async.js
new file mode 100644
index 0000000..7f575aa
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Async.js
@@ -0,0 +1,683 @@
1/***
2
3MochiKit.Async 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide("MochiKit.Async");
13 dojo.require("MochiKit.Base");
14}
15if (typeof(JSAN) != 'undefined') {
16 JSAN.use("MochiKit.Base", []);
17}
18
19try {
20 if (typeof(MochiKit.Base) == 'undefined') {
21 throw "";
22 }
23} catch (e) {
24 throw "MochiKit.Async depends on MochiKit.Base!";
25}
26
27if (typeof(MochiKit.Async) == 'undefined') {
28 MochiKit.Async = {};
29}
30
31MochiKit.Async.NAME = "MochiKit.Async";
32MochiKit.Async.VERSION = "1.4";
33MochiKit.Async.__repr__ = function () {
34 return "[" + this.NAME + " " + this.VERSION + "]";
35};
36MochiKit.Async.toString = function () {
37 return this.__repr__();
38};
39
40/** @id MochiKit.Async.Deferred */
41MochiKit.Async.Deferred = function (/* optional */ canceller) {
42 this.chain = [];
43 this.id = this._nextId();
44 this.fired = -1;
45 this.paused = 0;
46 this.results = [null, null];
47 this.canceller = canceller;
48 this.silentlyCancelled = false;
49 this.chained = false;
50};
51
52MochiKit.Async.Deferred.prototype = {
53 /** @id MochiKit.Async.Deferred.prototype.repr */
54 repr: function () {
55 var state;
56 if (this.fired == -1) {
57 state = 'unfired';
58 } else if (this.fired === 0) {
59 state = 'success';
60 } else {
61 state = 'error';
62 }
63 return 'Deferred(' + this.id + ', ' + state + ')';
64 },
65
66 toString: MochiKit.Base.forwardCall("repr"),
67
68 _nextId: MochiKit.Base.counter(),
69
70 /** @id MochiKit.Async.Deferred.prototype.cancel */
71 cancel: function () {
72 var self = MochiKit.Async;
73 if (this.fired == -1) {
74 if (this.canceller) {
75 this.canceller(this);
76 } else {
77 this.silentlyCancelled = true;
78 }
79 if (this.fired == -1) {
80 this.errback(new self.CancelledError(this));
81 }
82 } else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) {
83 this.results[0].cancel();
84 }
85 },
86
87 _resback: function (res) {
88 /***
89
90 The primitive that means either callback or errback
91
92 ***/
93 this.fired = ((res instanceof Error) ? 1 : 0);
94 this.results[this.fired] = res;
95 this._fire();
96 },
97
98 _check: function () {
99 if (this.fired != -1) {
100 if (!this.silentlyCancelled) {
101 throw new MochiKit.Async.AlreadyCalledError(this);
102 }
103 this.silentlyCancelled = false;
104 return;
105 }
106 },
107
108 /** @id MochiKit.Async.Deferred.prototype.callback */
109 callback: function (res) {
110 this._check();
111 if (res instanceof MochiKit.Async.Deferred) {
112 throw new Error("Deferred instances can only be chained if they are the result of a callback");
113 }
114 this._resback(res);
115 },
116
117 /** @id MochiKit.Async.Deferred.prototype.errback */
118 errback: function (res) {
119 this._check();
120 var self = MochiKit.Async;
121 if (res instanceof self.Deferred) {
122 throw new Error("Deferred instances can only be chained if they are the result of a callback");
123 }
124 if (!(res instanceof Error)) {
125 res = new self.GenericError(res);
126 }
127 this._resback(res);
128 },
129
130 /** @id MochiKit.Async.Deferred.prototype.addBoth */
131 addBoth: function (fn) {
132 if (arguments.length > 1) {
133 fn = MochiKit.Base.partial.apply(null, arguments);
134 }
135 return this.addCallbacks(fn, fn);
136 },
137
138 /** @id MochiKit.Async.Deferred.prototype.addCallback */
139 addCallback: function (fn) {
140 if (arguments.length > 1) {
141 fn = MochiKit.Base.partial.apply(null, arguments);
142 }
143 return this.addCallbacks(fn, null);
144 },
145
146 /** @id MochiKit.Async.Deferred.prototype.addErrback */
147 addErrback: function (fn) {
148 if (arguments.length > 1) {
149 fn = MochiKit.Base.partial.apply(null, arguments);
150 }
151 return this.addCallbacks(null, fn);
152 },
153
154 /** @id MochiKit.Async.Deferred.prototype.addCallbacks */
155 addCallbacks: function (cb, eb) {
156 if (this.chained) {
157 throw new Error("Chained Deferreds can not be re-used");
158 }
159 this.chain.push([cb, eb]);
160 if (this.fired >= 0) {
161 this._fire();
162 }
163 return this;
164 },
165
166 _fire: function () {
167 /***
168
169 Used internally to exhaust the callback sequence when a result
170 is available.
171
172 ***/
173 var chain = this.chain;
174 var fired = this.fired;
175 var res = this.results[fired];
176 var self = this;
177 var cb = null;
178 while (chain.length > 0 && this.paused === 0) {
179 // Array
180 var pair = chain.shift();
181 var f = pair[fired];
182 if (f === null) {
183 continue;
184 }
185 try {
186 res = f(res);
187 fired = ((res instanceof Error) ? 1 : 0);
188 if (res instanceof MochiKit.Async.Deferred) {
189 cb = function (res) {
190 self._resback(res);
191 self.paused--;
192 if ((self.paused === 0) && (self.fired >= 0)) {
193 self._fire();
194 }
195 };
196 this.paused++;
197 }
198 } catch (err) {
199 fired = 1;
200 if (!(err instanceof Error)) {
201 err = new MochiKit.Async.GenericError(err);
202 }
203 res = err;
204 }
205 }
206 this.fired = fired;
207 this.results[fired] = res;
208 if (cb && this.paused) {
209 // this is for "tail recursion" in case the dependent deferred
210 // is already fired
211 res.addBoth(cb);
212 res.chained = true;
213 }
214 }
215};
216
217MochiKit.Base.update(MochiKit.Async, {
218 /** @id MochiKit.Async.evalJSONRequest */
219 evalJSONRequest: function (/* req */) {
220 return eval('(' + arguments[0].responseText + ')');
221 },
222
223 /** @id MochiKit.Async.succeed */
224 succeed: function (/* optional */result) {
225 var d = new MochiKit.Async.Deferred();
226 d.callback.apply(d, arguments);
227 return d;
228 },
229
230 /** @id MochiKit.Async.fail */
231 fail: function (/* optional */result) {
232 var d = new MochiKit.Async.Deferred();
233 d.errback.apply(d, arguments);
234 return d;
235 },
236
237 /** @id MochiKit.Async.getXMLHttpRequest */
238 getXMLHttpRequest: function () {
239 var self = arguments.callee;
240 if (!self.XMLHttpRequest) {
241 var tryThese = [
242 function () { return new XMLHttpRequest(); },
243 function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
244 function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
245 function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
246 function () {
247 throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
248 }
249 ];
250 for (var i = 0; i < tryThese.length; i++) {
251 var func = tryThese[i];
252 try {
253 self.XMLHttpRequest = func;
254 return func();
255 } catch (e) {
256 // pass
257 }
258 }
259 }
260 return self.XMLHttpRequest();
261 },
262
263 _xhr_onreadystatechange: function (d) {
264 // MochiKit.Logging.logDebug('this.readyState', this.readyState);
265 var m = MochiKit.Base;
266 if (this.readyState == 4) {
267 // IE SUCKS
268 try {
269 this.onreadystatechange = null;
270 } catch (e) {
271 try {
272 this.onreadystatechange = m.noop;
273 } catch (e) {
274 }
275 }
276 var status = null;
277 try {
278 status = this.status;
279 if (!status && m.isNotEmpty(this.responseText)) {
280 // 0 or undefined seems to mean cached or local
281 status = 304;
282 }
283 } catch (e) {
284 // pass
285 // MochiKit.Logging.logDebug('error getting status?', repr(items(e)));
286 }
287 // 200 is OK, 201 is CREATED, 204 is NO CONTENT
288 // 304 is NOT MODIFIED, 1223 is apparently a bug in IE
289 if (status == 200 || status == 201 || status == 204 ||
290 status == 304 || status == 1223) {
291 d.callback(this);
292 } else {
293 var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed");
294 if (err.number) {
295 // XXX: This seems to happen on page change
296 d.errback(err);
297 } else {
298 // XXX: this seems to happen when the server is unreachable
299 d.errback(err);
300 }
301 }
302 }
303 },
304
305 _xhr_canceller: function (req) {
306 // IE SUCKS
307 try {
308 req.onreadystatechange = null;
309 } catch (e) {
310 try {
311 req.onreadystatechange = MochiKit.Base.noop;
312 } catch (e) {
313 }
314 }
315 req.abort();
316 },
317
318
319 /** @id MochiKit.Async.sendXMLHttpRequest */
320 sendXMLHttpRequest: function (req, /* optional */ sendContent) {
321 if (typeof(sendContent) == "undefined" || sendContent === null) {
322 sendContent = "";
323 }
324
325 var m = MochiKit.Base;
326 var self = MochiKit.Async;
327 var d = new self.Deferred(m.partial(self._xhr_canceller, req));
328
329 try {
330 req.onreadystatechange = m.bind(self._xhr_onreadystatechange,
331 req, d);
332 req.send(sendContent);
333 } catch (e) {
334 try {
335 req.onreadystatechange = null;
336 } catch (ignore) {
337 // pass
338 }
339 d.errback(e);
340 }
341
342 return d;
343
344 },
345
346 /** @id MochiKit.Async.doXHR */
347 doXHR: function (url, opts) {
348 var m = MochiKit.Base;
349 opts = m.update({
350 method: 'GET',
351 sendContent: ''
352 /*
353 queryString: undefined,
354 username: undefined,
355 password: undefined,
356 headers: undefined,
357 mimeType: undefined
358 */
359 }, opts);
360 var self = MochiKit.Async;
361 var req = self.getXMLHttpRequest();
362 if (opts.queryString) {
363 var qs = m.queryString(opts.queryString);
364 if (qs) {
365 url += "?" + qs;
366 }
367 }
368 req.open(opts.method, url, true, opts.username, opts.password);
369 if (req.overrideMimeType && opts.mimeType) {
370 req.overrideMimeType(opts.mimeType);
371 }
372 if (opts.headers) {
373 var headers = opts.headers;
374 if (!m.isArrayLike(headers)) {
375 headers = m.items(headers);
376 }
377 for (var i = 0; i < headers.length; i++) {
378 var header = headers[i];
379 var name = header[0];
380 var value = header[1];
381 req.setRequestHeader(name, value);
382 }
383 }
384 return self.sendXMLHttpRequest(req, opts.sendContent);
385 },
386
387 _buildURL: function (url/*, ...*/) {
388 if (arguments.length > 1) {
389 var m = MochiKit.Base;
390 var qs = m.queryString.apply(null, m.extend(null, arguments, 1));
391 if (qs) {
392 return url + "?" + qs;
393 }
394 }
395 return url;
396 },
397
398 /** @id MochiKit.Async.doSimpleXMLHttpRequest */
399 doSimpleXMLHttpRequest: function (url/*, ...*/) {
400 var self = MochiKit.Async;
401 url = self._buildURL.apply(self, arguments);
402 return self.doXHR(url);
403 },
404
405 /** @id MochiKit.Async.loadJSONDoc */
406 loadJSONDoc: function (url/*, ...*/) {
407 var self = MochiKit.Async;
408 url = self._buildURL.apply(self, arguments);
409 var d = self.doXHR(url, {
410 'mimeType': 'text/plain',
411 'headers': [['Accept', 'application/json']]
412 });
413 d = d.addCallback(self.evalJSONRequest);
414 return d;
415 },
416
417 /** @id MochiKit.Async.wait */
418 wait: function (seconds, /* optional */value) {
419 var d = new MochiKit.Async.Deferred();
420 var m = MochiKit.Base;
421 if (typeof(value) != 'undefined') {
422 d.addCallback(function () { return value; });
423 }
424 var timeout = setTimeout(
425 m.bind("callback", d),
426 Math.floor(seconds * 1000));
427 d.canceller = function () {
428 try {
429 clearTimeout(timeout);
430 } catch (e) {
431 // pass
432 }
433 };
434 return d;
435 },
436
437 /** @id MochiKit.Async.callLater */
438 callLater: function (seconds, func) {
439 var m = MochiKit.Base;
440 var pfunc = m.partial.apply(m, m.extend(null, arguments, 1));
441 return MochiKit.Async.wait(seconds).addCallback(
442 function (res) { return pfunc(); }
443 );
444 }
445});
446
447
448/** @id MochiKit.Async.DeferredLock */
449MochiKit.Async.DeferredLock = function () {
450 this.waiting = [];
451 this.locked = false;
452 this.id = this._nextId();
453};
454
455MochiKit.Async.DeferredLock.prototype = {
456 __class__: MochiKit.Async.DeferredLock,
457 /** @id MochiKit.Async.DeferredLock.prototype.acquire */
458 acquire: function () {
459 var d = new MochiKit.Async.Deferred();
460 if (this.locked) {
461 this.waiting.push(d);
462 } else {
463 this.locked = true;
464 d.callback(this);
465 }
466 return d;
467 },
468 /** @id MochiKit.Async.DeferredLock.prototype.release */
469 release: function () {
470 if (!this.locked) {
471 throw TypeError("Tried to release an unlocked DeferredLock");
472 }
473 this.locked = false;
474 if (this.waiting.length > 0) {
475 this.locked = true;
476 this.waiting.shift().callback(this);
477 }
478 },
479 _nextId: MochiKit.Base.counter(),
480 repr: function () {
481 var state;
482 if (this.locked) {
483 state = 'locked, ' + this.waiting.length + ' waiting';
484 } else {
485 state = 'unlocked';
486 }
487 return 'DeferredLock(' + this.id + ', ' + state + ')';
488 },
489 toString: MochiKit.Base.forwardCall("repr")
490
491};
492
493/** @id MochiKit.Async.DeferredList */
494MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {
495
496 // call parent constructor
497 MochiKit.Async.Deferred.apply(this, [canceller]);
498
499 this.list = list;
500 var resultList = [];
501 this.resultList = resultList;
502
503 this.finishedCount = 0;
504 this.fireOnOneCallback = fireOnOneCallback;
505 this.fireOnOneErrback = fireOnOneErrback;
506 this.consumeErrors = consumeErrors;
507
508 var cb = MochiKit.Base.bind(this._cbDeferred, this);
509 for (var i = 0; i < list.length; i++) {
510 var d = list[i];
511 resultList.push(undefined);
512 d.addCallback(cb, i, true);
513 d.addErrback(cb, i, false);
514 }
515
516 if (list.length === 0 && !fireOnOneCallback) {
517 this.callback(this.resultList);
518 }
519
520};
521
522MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred();
523
524MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) {
525 this.resultList[index] = [succeeded, result];
526 this.finishedCount += 1;
527 if (this.fired == -1) {
528 if (succeeded && this.fireOnOneCallback) {
529 this.callback([index, result]);
530 } else if (!succeeded && this.fireOnOneErrback) {
531 this.errback(result);
532 } else if (this.finishedCount == this.list.length) {
533 this.callback(this.resultList);
534 }
535 }
536 if (!succeeded && this.consumeErrors) {
537 result = null;
538 }
539 return result;
540};
541
542/** @id MochiKit.Async.gatherResults */
543MochiKit.Async.gatherResults = function (deferredList) {
544 var d = new MochiKit.Async.DeferredList(deferredList, false, true, false);
545 d.addCallback(function (results) {
546 var ret = [];
547 for (var i = 0; i < results.length; i++) {
548 ret.push(results[i][1]);
549 }
550 return ret;
551 });
552 return d;
553};
554
555/** @id MochiKit.Async.maybeDeferred */
556MochiKit.Async.maybeDeferred = function (func) {
557 var self = MochiKit.Async;
558 var result;
559 try {
560 var r = func.apply(null, MochiKit.Base.extend([], arguments, 1));
561 if (r instanceof self.Deferred) {
562 result = r;
563 } else if (r instanceof Error) {
564 result = self.fail(r);
565 } else {
566 result = self.succeed(r);
567 }
568 } catch (e) {
569 result = self.fail(e);
570 }
571 return result;
572};
573
574
575MochiKit.Async.EXPORT = [
576 "AlreadyCalledError",
577 "CancelledError",
578 "BrowserComplianceError",
579 "GenericError",
580 "XMLHttpRequestError",
581 "Deferred",
582 "succeed",
583 "fail",
584 "getXMLHttpRequest",
585 "doSimpleXMLHttpRequest",
586 "loadJSONDoc",
587 "wait",
588 "callLater",
589 "sendXMLHttpRequest",
590 "DeferredLock",
591 "DeferredList",
592 "gatherResults",
593 "maybeDeferred",
594 "doXHR"
595];
596
597MochiKit.Async.EXPORT_OK = [
598 "evalJSONRequest"
599];
600
601MochiKit.Async.__new__ = function () {
602 var m = MochiKit.Base;
603 var ne = m.partial(m._newNamedError, this);
604
605 ne("AlreadyCalledError",
606 /** @id MochiKit.Async.AlreadyCalledError */
607 function (deferred) {
608 /***
609
610 Raised by the Deferred if callback or errback happens
611 after it was already fired.
612
613 ***/
614 this.deferred = deferred;
615 }
616 );
617
618 ne("CancelledError",
619 /** @id MochiKit.Async.CancelledError */
620 function (deferred) {
621 /***
622
623 Raised by the Deferred cancellation mechanism.
624
625 ***/
626 this.deferred = deferred;
627 }
628 );
629
630 ne("BrowserComplianceError",
631 /** @id MochiKit.Async.BrowserComplianceError */
632 function (msg) {
633 /***
634
635 Raised when the JavaScript runtime is not capable of performing
636 the given function. Technically, this should really never be
637 raised because a non-conforming JavaScript runtime probably
638 isn't going to support exceptions in the first place.
639
640 ***/
641 this.message = msg;
642 }
643 );
644
645 ne("GenericError",
646 /** @id MochiKit.Async.GenericError */
647 function (msg) {
648 this.message = msg;
649 }
650 );
651
652 ne("XMLHttpRequestError",
653 /** @id MochiKit.Async.XMLHttpRequestError */
654 function (req, msg) {
655 /***
656
657 Raised when an XMLHttpRequest does not complete for any reason.
658
659 ***/
660 this.req = req;
661 this.message = msg;
662 try {
663 // Strange but true that this can raise in some cases.
664 this.number = req.status;
665 } catch (e) {
666 // pass
667 }
668 }
669 );
670
671
672 this.EXPORT_TAGS = {
673 ":common": this.EXPORT,
674 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
675 };
676
677 m.nameFunctions(this);
678
679};
680
681MochiKit.Async.__new__();
682
683MochiKit.Base._exportSymbols(this, MochiKit.Async);
diff --git a/frontend/beta/js/MochiKit/Base.js b/frontend/beta/js/MochiKit/Base.js
new file mode 100644
index 0000000..67f4499
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Base.js
@@ -0,0 +1,1403 @@
1/***
2
3MochiKit.Base 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide("MochiKit.Base");
13}
14if (typeof(MochiKit) == 'undefined') {
15 MochiKit = {};
16}
17if (typeof(MochiKit.Base) == 'undefined') {
18 MochiKit.Base = {};
19}
20if (typeof(MochiKit.__export__) == "undefined") {
21 MochiKit.__export__ = (MochiKit.__compat__ ||
22 (typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
23 );
24}
25
26MochiKit.Base.VERSION = "1.4";
27MochiKit.Base.NAME = "MochiKit.Base";
28/** @id MochiKit.Base.update */
29MochiKit.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};
43
44MochiKit.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 _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 },
94
95 /** @id MochiKit.Base.flattenArray */
96 flattenArray: function (lst) {
97 return MochiKit.Base._flattenArray([], lst);
98 },
99
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 },
117
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 },
149
150
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 },
171
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 },
187
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 },
196
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 },
205
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 },
221
222
223 _newNamedError: function (module, name, func) {
224 func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name);
225 module[name] = func;
226 },
227
228
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; },
238
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; },
244
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; },
256
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; },
270
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; },
284
285 // strict built-in comparators
286 seq: function (a, b) { return a === b; },
287 sne: function (a, b) { return a !== b; },
288
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; },
302
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 },
311
312 /** @id MochiKit.Base.forwardCall */
313 forwardCall: function (func) {
314 return function () {
315 return this[func].apply(this, arguments);
316 };
317 },
318
319 /** @id MochiKit.Base.itemgetter */
320 itemgetter: function (func) {
321 return function (arg) {
322 return arg[func];
323 };
324 },
325
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 },
342
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 },
352
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 },
363
364 /** @id MochiKit.Base.isEmpty */
365 isEmpty: function (obj) {
366 return !MochiKit.Base.isNotEmpty.apply(this, arguments);
367 },
368
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 },
379
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 },
396
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 },
408
409
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 },
421
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 },
488
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 },
503
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 },
539
540
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 },
557
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 },
571
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 },
577
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 },
600
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 },
645
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 },
656
657 /** @id MochiKit.Base.registerComparator */
658 registerComparator: function (name, check, comparator, /* optional */ override) {
659 MochiKit.Base.comparatorRegistry.register(name, check, comparator, override);
660 },
661
662 _primitives: {'boolean': true, 'string': true, 'number': true},
663
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 },
699
700 /** @id MochiKit.Base.compareDateLike */
701 compareDateLike: function (a, b) {
702 return MochiKit.Base.compare(a.getTime(), b.getTime());
703 },
704
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 },
724
725 /** @id MochiKit.Base.registerRepr */
726 registerRepr: function (name, check, wrap, /* optional */override) {
727 MochiKit.Base.reprRegistry.register(name, check, wrap, override);
728 },
729
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 if (typeof(o.NAME) == 'string' && (
746 o.toString == Function.prototype.toString ||
747 o.toString == Object.prototype.toString
748 )) {
749 return o.NAME;
750 }
751 }
752 try {
753 var ostring = (o + "");
754 } catch (e) {
755 return "[" + typeof(o) + "]";
756 }
757 if (typeof(o) == "function") {
758 o = ostring.replace(/^\s+/, "");
759 var idx = o.indexOf("{");
760 if (idx != -1) {
761 o = o.substr(0, idx) + "{...}";
762 }
763 }
764 return ostring;
765 },
766
767 /** @id MochiKit.Base.reprArrayLike */
768 reprArrayLike: function (o) {
769 var m = MochiKit.Base;
770 return "[" + m.map(m.repr, o).join(", ") + "]";
771 },
772
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");
781 },
782
783 /** @id MochiKit.Base.reprNumber */
784 reprNumber: function (o) {
785 return o + "";
786 },
787
788 /** @id MochiKit.Base.registerJSON */
789 registerJSON: function (name, check, wrap, /* optional */override) {
790 MochiKit.Base.jsonRegistry.register(name, check, wrap, override);
791 },
792
793
794 /** @id MochiKit.Base.evalJSON */
795 evalJSON: function () {
796 return eval("(" + arguments[0] + ")");
797 },
798
799 /** @id MochiKit.Base.serializeJSON */
800 serializeJSON: function (o) {
801 var objtype = typeof(o);
802 if (objtype == "number" || objtype == "boolean") {
803 return o + "";
804 } else if (o === null) {
805 return "null";
806 }
807 var m = MochiKit.Base;
808 var reprString = m.reprString;
809 if (objtype == "string") {
810 return reprString(o);
811 }
812 // recurse
813 var me = arguments.callee;
814 // short-circuit for objects that support "json" serialization
815 // if they return "self" then just pass-through...
816 var newObj;
817 if (typeof(o.__json__) == "function") {
818 newObj = o.__json__();
819 if (o !== newObj) {
820 return me(newObj);
821 }
822 }
823 if (typeof(o.json) == "function") {
824 newObj = o.json();
825 if (o !== newObj) {
826 return me(newObj);
827 }
828 }
829 // array
830 if (objtype != "function" && typeof(o.length) == "number") {
831 var res = [];
832 for (var i = 0; i < o.length; i++) {
833 var val = me(o[i]);
834 if (typeof(val) != "string") {
835 val = "undefined";
836 }
837 res.push(val);
838 }
839 return "[" + res.join(", ") + "]";
840 }
841 // look in the registry
842 try {
843 newObj = m.jsonRegistry.match(o);
844 if (o !== newObj) {
845 return me(newObj);
846 }
847 } catch (e) {
848 if (e != m.NotFound) {
849 // something really bad happened
850 throw e;
851 }
852 }
853 // undefined is outside of the spec
854 if (objtype == "undefined") {
855 throw new TypeError("undefined can not be serialized as JSON");
856 }
857 // it's a function with no adapter, bad
858 if (objtype == "function") {
859 return null;
860 }
861 // generic object code path
862 res = [];
863 for (var k in o) {
864 var useKey;
865 if (typeof(k) == "number") {
866 useKey = '"' + k + '"';
867 } else if (typeof(k) == "string") {
868 useKey = reprString(k);
869 } else {
870 // skip non-string or number keys
871 continue;
872 }
873 val = me(o[k]);
874 if (typeof(val) != "string") {
875 // skip non-serializable values
876 continue;
877 }
878 res.push(useKey + ":" + val);
879 }
880 return "{" + res.join(", ") + "}";
881 },
882
883
884 /** @id MochiKit.Base.objEqual */
885 objEqual: function (a, b) {
886 return (MochiKit.Base.compare(a, b) === 0);
887 },
888
889 /** @id MochiKit.Base.arrayEqual */
890 arrayEqual: function (self, arr) {
891 if (self.length != arr.length) {
892 return false;
893 }
894 return (MochiKit.Base.compare(self, arr) === 0);
895 },
896
897 /** @id MochiKit.Base.concat */
898 concat: function (/* lst... */) {
899 var rval = [];
900 var extend = MochiKit.Base.extend;
901 for (var i = 0; i < arguments.length; i++) {
902 extend(rval, arguments[i]);
903 }
904 return rval;
905 },
906
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]);
915 };
916 }
917 var compareKeys = m.extend(null, arguments);
918 return function (a, b) {
919 var rval = 0;
920 // keep comparing until something is inequal or we run out of
921 // keys to compare
922 for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) {
923 var key = compareKeys[i];
924 rval = compare(a[key], b[key]);
925 }
926 return rval;
927 };
928 },
929
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);
935 };
936 },
937
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));
942 },
943
944 /** @id MochiKit.Base.listMinMax */
945 listMinMax: function (which, lst) {
946 if (lst.length === 0) {
947 return null;
948 }
949 var cur = lst[0];
950 var compare = MochiKit.Base.compare;
951 for (var i = 1; i < lst.length; i++) {
952 var o = lst[i];
953 if (compare(o, cur) == which) {
954 cur = o;
955 }
956 }
957 return cur;
958 },
959
960 /** @id MochiKit.Base.objMax */
961 objMax: function (/* obj... */) {
962 return MochiKit.Base.listMinMax(1, arguments);
963 },
964
965 /** @id MochiKit.Base.objMin */
966 objMin: function (/* obj... */) {
967 return MochiKit.Base.listMinMax(-1, arguments);
968 },
969
970 /** @id MochiKit.Base.findIdentical */
971 findIdentical: function (lst, value, start/* = 0 */, /* optional */end) {
972 if (typeof(end) == "undefined" || end === null) {
973 end = lst.length;
974 }
975 if (typeof(start) == "undefined" || start === null) {
976 start = 0;
977 }
978 for (var i = start; i < end; i++) {
979 if (lst[i] === value) {
980 return i;
981 }
982 }
983 return -1;
984 },
985
986 /** @id MochiKit.Base.mean */
987 mean: function(/* lst... */) {
988 /* http://www.nist.gov/dads/HTML/mean.html */
989 var sum = 0;
990
991 var m = MochiKit.Base;
992 var args = m.extend(null, arguments);
993 var count = args.length;
994
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--) {
1000 sum += o[i];
1001 }
1002 } else {
1003 sum += o;
1004 }
1005 }
1006
1007 if (count <= 0) {
1008 throw new TypeError('mean() requires at least one argument');
1009 }
1010
1011 return sum/count;
1012 },
1013
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');
1020 }
1021 data.sort(compare);
1022 if (data.length % 2 == 0) {
1023 var upper = data.length / 2;
1024 return (data[upper] + data[upper - 1]) / 2;
1025 } else {
1026 return data[(data.length - 1) / 2];
1027 }
1028 },
1029
1030 /** @id MochiKit.Base.findValue */
1031 findValue: function (lst, value, start/* = 0 */, /* optional */end) {
1032 if (typeof(end) == "undefined" || end === null) {
1033 end = lst.length;
1034 }
1035 if (typeof(start) == "undefined" || start === null) {
1036 start = 0;
1037 }
1038 var cmp = MochiKit.Base.compare;
1039 for (var i = start; i < end; i++) {
1040 if (cmp(lst[i], value) === 0) {
1041 return i;
1042 }
1043 }
1044 return -1;
1045 },
1046
1047 /** @id MochiKit.Base.nodeWalk */
1048 nodeWalk: function (node, visitor) {
1049 var nodes = [node];
1050 var extend = MochiKit.Base.extend;
1051 while (nodes.length) {
1052 var res = visitor(nodes.shift());
1053 if (res) {
1054 extend(nodes, res);
1055 }
1056 }
1057 },
1058
1059
1060 /** @id MochiKit.Base.nameFunctions */
1061 nameFunctions: function (namespace) {
1062 var base = namespace.NAME;
1063 if (typeof(base) == 'undefined') {
1064 base = '';
1065 } else {
1066 base = base + '.';
1067 }
1068 for (var name in namespace) {
1069 var o = namespace[name];
1070 if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
1071 try {
1072 o.NAME = base + name;
1073 } catch (e) {
1074 // pass
1075 }
1076 }
1077 }
1078 },
1079
1080
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
1089 ))
1090 ) {
1091 var kv = MochiKit.DOM.formContents(names);
1092 names = kv[0];
1093 values = kv[1];
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]);
1098 }
1099 var o = names;
1100 names = [];
1101 values = [];
1102 for (var k in o) {
1103 var v = o[k];
1104 if (typeof(v) == "function") {
1105 continue;
1106 } else if (typeof(v) != "string" &&
1107 typeof(v.length) == "number") {
1108 for (var i = 0; i < v.length; i++) {
1109 names.push(k);
1110 values.push(v[i]);
1111 }
1112 } else {
1113 names.push(k);
1114 values.push(v);
1115 }
1116 }
1117 }
1118 var rval = [];
1119 var len = Math.min(names.length, values.length);
1120 var urlEncode = MochiKit.Base.urlEncode;
1121 for (var i = 0; i < len; i++) {
1122 v = values[i];
1123 if (typeof(v) != 'undefined' && v !== null) {
1124 rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
1125 }
1126 }
1127 return rval.join("&");
1128 },
1129
1130
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)
1136 : encodedString;
1137 var pairs = qstr.replace(/\+/g, "%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
1138 var o = {};
1139 var decode;
1140 if (typeof(decodeURIComponent) != "undefined") {
1141 decode = decodeURIComponent;
1142 } else {
1143 decode = unescape;
1144 }
1145 if (useArrays) {
1146 for (var i = 0; i < pairs.length; i++) {
1147 var pair = pairs[i].split("=");
1148 if (pair.length !== 2) {
1149 continue;
1150 }
1151 var name = decode(pair[0]);
1152 var arr = o[name];
1153 if (!(arr instanceof Array)) {
1154 arr = [];
1155 o[name] = arr;
1156 }
1157 arr.push(decode(pair[1]));
1158 }
1159 } else {
1160 for (i = 0; i < pairs.length; i++) {
1161 pair = pairs[i].split("=");
1162 if (pair.length !== 2) {
1163 continue;
1164 }
1165 o[decode(pair[0])] = decode(pair[1]);
1166 }
1167 }
1168 return o;
1169 }
1170});
1171
1172/** @id MochiKit.Base.AdapterRegistry */
1173MochiKit.Base.AdapterRegistry = function () {
1174 this.pairs = [];
1175};
1176
1177MochiKit.Base.AdapterRegistry.prototype = {
1178 /** @id MochiKit.Base.AdapterRegistry.prototype.register */
1179 register: function (name, check, wrap, /* optional */ override) {
1180 if (override) {
1181 this.pairs.unshift([name, check, wrap]);
1182 } else {
1183 this.pairs.push([name, check, wrap]);
1184 }
1185 },
1186
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);
1193 }
1194 }
1195 throw MochiKit.Base.NotFound;
1196 },
1197
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);
1204 return true;
1205 }
1206 }
1207 return false;
1208 }
1209};
1210
1211
1212MochiKit.Base.EXPORT = [
1213 "flattenArray",
1214 "noop",
1215 "camelize",
1216 "counter",
1217 "clone",
1218 "extend",
1219 "update",
1220 "updatetree",
1221 "setdefault",
1222 "keys",
1223 "values",
1224 "items",
1225 "NamedError",
1226 "operator",
1227 "forwardCall",
1228 "itemgetter",
1229 "typeMatcher",
1230 "isCallable",
1231 "isUndefined",
1232 "isUndefinedOrNull",
1233 "isNull",
1234 "isEmpty",
1235 "isNotEmpty",
1236 "isArrayLike",
1237 "isDateLike",
1238 "xmap",
1239 "map",
1240 "xfilter",
1241 "filter",
1242 "methodcaller",
1243 "compose",
1244 "bind",
1245 "bindMethods",
1246 "NotFound",
1247 "AdapterRegistry",
1248 "registerComparator",
1249 "compare",
1250 "registerRepr",
1251 "repr",
1252 "objEqual",
1253 "arrayEqual",
1254 "concat",
1255 "keyComparator",
1256 "reverseKeyComparator",
1257 "partial",
1258 "merge",
1259 "listMinMax",
1260 "listMax",
1261 "listMin",
1262 "objMax",
1263 "objMin",
1264 "nodeWalk",
1265 "zip",
1266 "urlEncode",
1267 "queryString",
1268 "serializeJSON",
1269 "registerJSON",
1270 "evalJSON",
1271 "parseQueryString",
1272 "findValue",
1273 "findIdentical",
1274 "flattenArguments",
1275 "method",
1276 "average",
1277 "mean",
1278 "median"
1279];
1280
1281MochiKit.Base.EXPORT_OK = [
1282 "nameFunctions",
1283 "comparatorRegistry",
1284 "reprRegistry",
1285 "jsonRegistry",
1286 "compareDateLike",
1287 "compareArrayLike",
1288 "reprArrayLike",
1289 "reprString",
1290 "reprNumber"
1291];
1292
1293MochiKit.Base._exportSymbols = function (globals, module) {
1294 if (!MochiKit.__export__) {
1295 return;
1296 }
1297 var all = module.EXPORT_TAGS[":all"];
1298 for (var i = 0; i < all.length; i++) {
1299 globals[all[i]] = module[all[i]];
1300 }
1301};
1302
1303MochiKit.Base.__new__ = function () {
1304 // A singleton raised when no suitable adapter is found
1305 var m = this;
1306
1307 // convenience
1308 /** @id MochiKit.Base.noop */
1309 m.noop = m.operator.identity;
1310
1311 // Backwards compat
1312 m.forward = m.forwardCall;
1313 m.find = m.findValue;
1314
1315 if (typeof(encodeURIComponent) != "undefined") {
1316 /** @id MochiKit.Base.urlEncode */
1317 m.urlEncode = function (unencoded) {
1318 return encodeURIComponent(unencoded).replace(/\'/g, '%27');
1319 };
1320 } else {
1321 m.urlEncode = function (unencoded) {
1322 return escape(unencoded
1323 ).replace(/\+/g, '%2B'
1324 ).replace(/\"/g,'%22'
1325 ).rval.replace(/\'/g, '%27');
1326 };
1327 }
1328
1329 /** @id MochiKit.Base.NamedError */
1330 m.NamedError = function (name) {
1331 this.message = name;
1332 this.name = name;
1333 };
1334 m.NamedError.prototype = new Error();
1335 m.update(m.NamedError.prototype, {
1336 repr: function () {
1337 if (this.message && this.message != this.name) {
1338 return this.name + "(" + m.repr(this.message) + ")";
1339 } else {
1340 return this.name + "()";
1341 }
1342 },
1343 toString: m.forwardCall("repr")
1344 });
1345
1346 /** @id MochiKit.Base.NotFound */
1347 m.NotFound = new m.NamedError("MochiKit.Base.NotFound");
1348
1349
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);
1354
1355 /** @id MochiKit.Base.isCallable */
1356 m.isCallable = m.typeMatcher('function');
1357 /** @id MochiKit.Base.isUndefined */
1358 m.isUndefined = m.typeMatcher('undefined');
1359
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);
1364
1365 /** @id MochiKit.Base.average */
1366 m.average = m.mean;
1367
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);
1372
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);
1378
1379 /** @id MochiKit.Base.jsonRegistry */
1380 m.jsonRegistry = new m.AdapterRegistry();
1381
1382 var all = m.concat(m.EXPORT, m.EXPORT_OK);
1383 m.EXPORT_TAGS = {
1384 ":common": m.concat(m.EXPORT_OK),
1385 ":all": all
1386 };
1387
1388 m.nameFunctions(this);
1389
1390};
1391
1392MochiKit.Base.__new__();
1393
1394//
1395// XXX: Internet Explorer blows
1396//
1397if (MochiKit.__export__) {
1398 compare = MochiKit.Base.compare;
1399 compose = MochiKit.Base.compose;
1400 serializeJSON = MochiKit.Base.serializeJSON;
1401}
1402
1403MochiKit.Base._exportSymbols(this, MochiKit.Base);
diff --git a/frontend/beta/js/MochiKit/Color.js b/frontend/beta/js/MochiKit/Color.js
new file mode 100644
index 0000000..37cb43b
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Color.js
@@ -0,0 +1,902 @@
1/***
2
3MochiKit.Color 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito and others. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Color');
13 dojo.require('MochiKit.Base');
14 dojo.require('MochiKit.DOM');
15 dojo.require('MochiKit.Style');
16}
17
18if (typeof(JSAN) != 'undefined') {
19 JSAN.use("MochiKit.Base", []);
20 JSAN.use("MochiKit.DOM", []);
21 JSAN.use("MochiKit.Style", []);
22}
23
24try {
25 if (typeof(MochiKit.Base) == 'undefined') {
26 throw "";
27 }
28} catch (e) {
29 throw "MochiKit.Color depends on MochiKit.Base";
30}
31
32try {
33 if (typeof(MochiKit.DOM) == 'undefined') {
34 throw "";
35 }
36} catch (e) {
37 throw "MochiKit.Color depends on MochiKit.DOM";
38}
39
40try {
41 if (typeof(MochiKit.Style) == 'undefined') {
42 throw "";
43 }
44} catch (e) {
45 throw "MochiKit.Color depends on MochiKit.Style";
46}
47
48if (typeof(MochiKit.Color) == "undefined") {
49 MochiKit.Color = {};
50}
51
52MochiKit.Color.NAME = "MochiKit.Color";
53MochiKit.Color.VERSION = "1.4";
54
55MochiKit.Color.__repr__ = function () {
56 return "[" + this.NAME + " " + this.VERSION + "]";
57};
58
59MochiKit.Color.toString = function () {
60 return this.__repr__();
61};
62
63
64/** @id MochiKit.Color.Color */
65MochiKit.Color.Color = function (red, green, blue, alpha) {
66 if (typeof(alpha) == 'undefined' || alpha === null) {
67 alpha = 1.0;
68 }
69 this.rgb = {
70 r: red,
71 g: green,
72 b: blue,
73 a: alpha
74 };
75};
76
77
78// Prototype methods
79
80MochiKit.Color.Color.prototype = {
81
82 __class__: MochiKit.Color.Color,
83
84 /** @id MochiKit.Color.Color.prototype.colorWithAlpha */
85 colorWithAlpha: function (alpha) {
86 var rgb = this.rgb;
87 var m = MochiKit.Color;
88 return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha);
89 },
90
91 /** @id MochiKit.Color.Color.prototype.colorWithHue */
92 colorWithHue: function (hue) {
93 // get an HSL model, and set the new hue...
94 var hsl = this.asHSL();
95 hsl.h = hue;
96 var m = MochiKit.Color;
97 // convert back to RGB...
98 return m.Color.fromHSL(hsl);
99 },
100
101 /** @id MochiKit.Color.Color.prototype.colorWithSaturation */
102 colorWithSaturation: function (saturation) {
103 // get an HSL model, and set the new hue...
104 var hsl = this.asHSL();
105 hsl.s = saturation;
106 var m = MochiKit.Color;
107 // convert back to RGB...
108 return m.Color.fromHSL(hsl);
109 },
110
111 /** @id MochiKit.Color.Color.prototype.colorWithLightness */
112 colorWithLightness: function (lightness) {
113 // get an HSL model, and set the new hue...
114 var hsl = this.asHSL();
115 hsl.l = lightness;
116 var m = MochiKit.Color;
117 // convert back to RGB...
118 return m.Color.fromHSL(hsl);
119 },
120
121 /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */
122 darkerColorWithLevel: function (level) {
123 var hsl = this.asHSL();
124 hsl.l = Math.max(hsl.l - level, 0);
125 var m = MochiKit.Color;
126 return m.Color.fromHSL(hsl);
127 },
128
129 /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
130 lighterColorWithLevel: function (level) {
131 var hsl = this.asHSL();
132 hsl.l = Math.min(hsl.l + level, 1);
133 var m = MochiKit.Color;
134 return m.Color.fromHSL(hsl);
135 },
136
137 /** @id MochiKit.Color.Color.prototype.blendedColor */
138 blendedColor: function (other, /* optional */ fraction) {
139 if (typeof(fraction) == 'undefined' || fraction === null) {
140 fraction = 0.5;
141 }
142 var sf = 1.0 - fraction;
143 var s = this.rgb;
144 var d = other.rgb;
145 var df = fraction;
146 return MochiKit.Color.Color.fromRGB(
147 (s.r * sf) + (d.r * df),
148 (s.g * sf) + (d.g * df),
149 (s.b * sf) + (d.b * df),
150 (s.a * sf) + (d.a * df)
151 );
152 },
153
154 /** @id MochiKit.Color.Color.prototype.compareRGB */
155 compareRGB: function (other) {
156 var a = this.asRGB();
157 var b = other.asRGB();
158 return MochiKit.Base.compare(
159 [a.r, a.g, a.b, a.a],
160 [b.r, b.g, b.b, b.a]
161 );
162 },
163
164 /** @id MochiKit.Color.Color.prototype.isLight */
165 isLight: function () {
166 return this.asHSL().b > 0.5;
167 },
168
169 /** @id MochiKit.Color.Color.prototype.isDark */
170 isDark: function () {
171 return (!this.isLight());
172 },
173
174 /** @id MochiKit.Color.Color.prototype.toHSLString */
175 toHSLString: function () {
176 var c = this.asHSL();
177 var ccc = MochiKit.Color.clampColorComponent;
178 var rval = this._hslString;
179 if (!rval) {
180 var mid = (
181 ccc(c.h, 360).toFixed(0)
182 + "," + ccc(c.s, 100).toPrecision(4) + "%"
183 + "," + ccc(c.l, 100).toPrecision(4) + "%"
184 );
185 var a = c.a;
186 if (a >= 1) {
187 a = 1;
188 rval = "hsl(" + mid + ")";
189 } else {
190 if (a <= 0) {
191 a = 0;
192 }
193 rval = "hsla(" + mid + "," + a + ")";
194 }
195 this._hslString = rval;
196 }
197 return rval;
198 },
199
200 /** @id MochiKit.Color.Color.prototype.toRGBString */
201 toRGBString: function () {
202 var c = this.rgb;
203 var ccc = MochiKit.Color.clampColorComponent;
204 var rval = this._rgbString;
205 if (!rval) {
206 var mid = (
207 ccc(c.r, 255).toFixed(0)
208 + "," + ccc(c.g, 255).toFixed(0)
209 + "," + ccc(c.b, 255).toFixed(0)
210 );
211 if (c.a != 1) {
212 rval = "rgba(" + mid + "," + c.a + ")";
213 } else {
214 rval = "rgb(" + mid + ")";
215 }
216 this._rgbString = rval;
217 }
218 return rval;
219 },
220
221 /** @id MochiKit.Color.Color.prototype.asRGB */
222 asRGB: function () {
223 return MochiKit.Base.clone(this.rgb);
224 },
225
226 /** @id MochiKit.Color.Color.prototype.toHexString */
227 toHexString: function () {
228 var m = MochiKit.Color;
229 var c = this.rgb;
230 var ccc = MochiKit.Color.clampColorComponent;
231 var rval = this._hexString;
232 if (!rval) {
233 rval = ("#" +
234 m.toColorPart(ccc(c.r, 255)) +
235 m.toColorPart(ccc(c.g, 255)) +
236 m.toColorPart(ccc(c.b, 255))
237 );
238 this._hexString = rval;
239 }
240 return rval;
241 },
242
243 /** @id MochiKit.Color.Color.prototype.asHSV */
244 asHSV: function () {
245 var hsv = this.hsv;
246 var c = this.rgb;
247 if (typeof(hsv) == 'undefined' || hsv === null) {
248 hsv = MochiKit.Color.rgbToHSV(this.rgb);
249 this.hsv = hsv;
250 }
251 return MochiKit.Base.clone(hsv);
252 },
253
254 /** @id MochiKit.Color.Color.prototype.asHSL */
255 asHSL: function () {
256 var hsl = this.hsl;
257 var c = this.rgb;
258 if (typeof(hsl) == 'undefined' || hsl === null) {
259 hsl = MochiKit.Color.rgbToHSL(this.rgb);
260 this.hsl = hsl;
261 }
262 return MochiKit.Base.clone(hsl);
263 },
264
265 /** @id MochiKit.Color.Color.prototype.toString */
266 toString: function () {
267 return this.toRGBString();
268 },
269
270 /** @id MochiKit.Color.Color.prototype.repr */
271 repr: function () {
272 var c = this.rgb;
273 var col = [c.r, c.g, c.b, c.a];
274 return this.__class__.NAME + "(" + col.join(", ") + ")";
275 }
276
277};
278
279// Constructor methods
280
281MochiKit.Base.update(MochiKit.Color.Color, {
282 /** @id MochiKit.Color.Color.fromRGB */
283 fromRGB: function (red, green, blue, alpha) {
284 // designated initializer
285 var Color = MochiKit.Color.Color;
286 if (arguments.length == 1) {
287 var rgb = red;
288 red = rgb.r;
289 green = rgb.g;
290 blue = rgb.b;
291 if (typeof(rgb.a) == 'undefined') {
292 alpha = undefined;
293 } else {
294 alpha = rgb.a;
295 }
296 }
297 return new Color(red, green, blue, alpha);
298 },
299
300 /** @id MochiKit.Color.Color.fromHSL */
301 fromHSL: function (hue, saturation, lightness, alpha) {
302 var m = MochiKit.Color;
303 return m.Color.fromRGB(m.hslToRGB.apply(m, arguments));
304 },
305
306 /** @id MochiKit.Color.Color.fromHSV */
307 fromHSV: function (hue, saturation, value, alpha) {
308 var m = MochiKit.Color;
309 return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments));
310 },
311
312 /** @id MochiKit.Color.Color.fromName */
313 fromName: function (name) {
314 var Color = MochiKit.Color.Color;
315 // Opera 9 seems to "quote" named colors(?!)
316 if (name.charAt(0) == '"') {
317 name = name.substr(1, name.length - 2);
318 }
319 var htmlColor = Color._namedColors[name.toLowerCase()];
320 if (typeof(htmlColor) == 'string') {
321 return Color.fromHexString(htmlColor);
322 } else if (name == "transparent") {
323 return Color.transparentColor();
324 }
325 return null;
326 },
327
328 /** @id MochiKit.Color.Color.fromString */
329 fromString: function (colorString) {
330 var self = MochiKit.Color.Color;
331 var three = colorString.substr(0, 3);
332 if (three == "rgb") {
333 return self.fromRGBString(colorString);
334 } else if (three == "hsl") {
335 return self.fromHSLString(colorString);
336 } else if (colorString.charAt(0) == "#") {
337 return self.fromHexString(colorString);
338 }
339 return self.fromName(colorString);
340 },
341
342
343 /** @id MochiKit.Color.Color.fromHexString */
344 fromHexString: function (hexCode) {
345 if (hexCode.charAt(0) == '#') {
346 hexCode = hexCode.substring(1);
347 }
348 var components = [];
349 var i, hex;
350 if (hexCode.length == 3) {
351 for (i = 0; i < 3; i++) {
352 hex = hexCode.substr(i, 1);
353 components.push(parseInt(hex + hex, 16) / 255.0);
354 }
355 } else {
356 for (i = 0; i < 6; i += 2) {
357 hex = hexCode.substr(i, 2);
358 components.push(parseInt(hex, 16) / 255.0);
359 }
360 }
361 var Color = MochiKit.Color.Color;
362 return Color.fromRGB.apply(Color, components);
363 },
364
365
366 _fromColorString: function (pre, method, scales, colorCode) {
367 // parses either HSL or RGB
368 if (colorCode.indexOf(pre) === 0) {
369 colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1);
370 }
371 var colorChunks = colorCode.split(/\s*,\s*/);
372 var colorFloats = [];
373 for (var i = 0; i < colorChunks.length; i++) {
374 var c = colorChunks[i];
375 var val;
376 var three = c.substring(c.length - 3);
377 if (c.charAt(c.length - 1) == '%') {
378 val = 0.01 * parseFloat(c.substring(0, c.length - 1));
379 } else if (three == "deg") {
380 val = parseFloat(c) / 360.0;
381 } else if (three == "rad") {
382 val = parseFloat(c) / (Math.PI * 2);
383 } else {
384 val = scales[i] * parseFloat(c);
385 }
386 colorFloats.push(val);
387 }
388 return this[method].apply(this, colorFloats);
389 },
390
391 /** @id MochiKit.Color.Color.fromComputedStyle */
392 fromComputedStyle: function (elem, style) {
393 var d = MochiKit.DOM;
394 var cls = MochiKit.Color.Color;
395 for (elem = d.getElement(elem); elem; elem = elem.parentNode) {
396 var actualColor = MochiKit.Style.getStyle.apply(d, arguments);
397 if (!actualColor) {
398 continue;
399 }
400 var color = cls.fromString(actualColor);
401 if (!color) {
402 break;
403 }
404 if (color.asRGB().a > 0) {
405 return color;
406 }
407 }
408 return null;
409 },
410
411 /** @id MochiKit.Color.Color.fromBackground */
412 fromBackground: function (elem) {
413 var cls = MochiKit.Color.Color;
414 return cls.fromComputedStyle(
415 elem, "backgroundColor", "background-color") || cls.whiteColor();
416 },
417
418 /** @id MochiKit.Color.Color.fromText */
419 fromText: function (elem) {
420 var cls = MochiKit.Color.Color;
421 return cls.fromComputedStyle(
422 elem, "color", "color") || cls.blackColor();
423 },
424
425 /** @id MochiKit.Color.Color.namedColors */
426 namedColors: function () {
427 return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
428 }
429});
430
431
432// Module level functions
433
434MochiKit.Base.update(MochiKit.Color, {
435 /** @id MochiKit.Color.clampColorComponent */
436 clampColorComponent: function (v, scale) {
437 v *= scale;
438 if (v < 0) {
439 return 0;
440 } else if (v > scale) {
441 return scale;
442 } else {
443 return v;
444 }
445 },
446
447 _hslValue: function (n1, n2, hue) {
448 if (hue > 6.0) {
449 hue -= 6.0;
450 } else if (hue < 0.0) {
451 hue += 6.0;
452 }
453 var val;
454 if (hue < 1.0) {
455 val = n1 + (n2 - n1) * hue;
456 } else if (hue < 3.0) {
457 val = n2;
458 } else if (hue < 4.0) {
459 val = n1 + (n2 - n1) * (4.0 - hue);
460 } else {
461 val = n1;
462 }
463 return val;
464 },
465
466 /** @id MochiKit.Color.hsvToRGB */
467 hsvToRGB: function (hue, saturation, value, alpha) {
468 if (arguments.length == 1) {
469 var hsv = hue;
470 hue = hsv.h;
471 saturation = hsv.s;
472 value = hsv.v;
473 alpha = hsv.a;
474 }
475 var red;
476 var green;
477 var blue;
478 if (saturation === 0) {
479 red = 0;
480 green = 0;
481 blue = 0;
482 } else {
483 var i = Math.floor(hue * 6);
484 var f = (hue * 6) - i;
485 var p = value * (1 - saturation);
486 var q = value * (1 - (saturation * f));
487 var t = value * (1 - (saturation * (1 - f)));
488 switch (i) {
489 case 1: red = q; green = value; blue = p; break;
490 case 2: red = p; green = value; blue = t; break;
491 case 3: red = p; green = q; blue = value; break;
492 case 4: red = t; green = p; blue = value; break;
493 case 5: red = value; green = p; blue = q; break;
494 case 6: // fall through
495 case 0: red = value; green = t; blue = p; break;
496 }
497 }
498 return {
499 r: red,
500 g: green,
501 b: blue,
502 a: alpha
503 };
504 },
505
506 /** @id MochiKit.Color.hslToRGB */
507 hslToRGB: function (hue, saturation, lightness, alpha) {
508 if (arguments.length == 1) {
509 var hsl = hue;
510 hue = hsl.h;
511 saturation = hsl.s;
512 lightness = hsl.l;
513 alpha = hsl.a;
514 }
515 var red;
516 var green;
517 var blue;
518 if (saturation === 0) {
519 red = lightness;
520 green = lightness;
521 blue = lightness;
522 } else {
523 var m2;
524 if (lightness <= 0.5) {
525 m2 = lightness * (1.0 + saturation);
526 } else {
527 m2 = lightness + saturation - (lightness * saturation);
528 }
529 var m1 = (2.0 * lightness) - m2;
530 var f = MochiKit.Color._hslValue;
531 var h6 = hue * 6.0;
532 red = f(m1, m2, h6 + 2);
533 green = f(m1, m2, h6);
534 blue = f(m1, m2, h6 - 2);
535 }
536 return {
537 r: red,
538 g: green,
539 b: blue,
540 a: alpha
541 };
542 },
543
544 /** @id MochiKit.Color.rgbToHSV */
545 rgbToHSV: function (red, green, blue, alpha) {
546 if (arguments.length == 1) {
547 var rgb = red;
548 red = rgb.r;
549 green = rgb.g;
550 blue = rgb.b;
551 alpha = rgb.a;
552 }
553 var max = Math.max(Math.max(red, green), blue);
554 var min = Math.min(Math.min(red, green), blue);
555 var hue;
556 var saturation;
557 var value = max;
558 if (min == max) {
559 hue = 0;
560 saturation = 0;
561 } else {
562 var delta = (max - min);
563 saturation = delta / max;
564
565 if (red == max) {
566 hue = (green - blue) / delta;
567 } else if (green == max) {
568 hue = 2 + ((blue - red) / delta);
569 } else {
570 hue = 4 + ((red - green) / delta);
571 }
572 hue /= 6;
573 if (hue < 0) {
574 hue += 1;
575 }
576 if (hue > 1) {
577 hue -= 1;
578 }
579 }
580 return {
581 h: hue,
582 s: saturation,
583 v: value,
584 a: alpha
585 };
586 },
587
588 /** @id MochiKit.Color.rgbToHSL */
589 rgbToHSL: function (red, green, blue, alpha) {
590 if (arguments.length == 1) {
591 var rgb = red;
592 red = rgb.r;
593 green = rgb.g;
594 blue = rgb.b;
595 alpha = rgb.a;
596 }
597 var max = Math.max(red, Math.max(green, blue));
598 var min = Math.min(red, Math.min(green, blue));
599 var hue;
600 var saturation;
601 var lightness = (max + min) / 2.0;
602 var delta = max - min;
603 if (delta === 0) {
604 hue = 0;
605 saturation = 0;
606 } else {
607 if (lightness <= 0.5) {
608 saturation = delta / (max + min);
609 } else {
610 saturation = delta / (2 - max - min);
611 }
612 if (red == max) {
613 hue = (green - blue) / delta;
614 } else if (green == max) {
615 hue = 2 + ((blue - red) / delta);
616 } else {
617 hue = 4 + ((red - green) / delta);
618 }
619 hue /= 6;
620 if (hue < 0) {
621 hue += 1;
622 }
623 if (hue > 1) {
624 hue -= 1;
625 }
626
627 }
628 return {
629 h: hue,
630 s: saturation,
631 l: lightness,
632 a: alpha
633 };
634 },
635
636 /** @id MochiKit.Color.toColorPart */
637 toColorPart: function (num) {
638 num = Math.round(num);
639 var digits = num.toString(16);
640 if (num < 16) {
641 return '0' + digits;
642 }
643 return digits;
644 },
645
646 __new__: function () {
647 var m = MochiKit.Base;
648 /** @id MochiKit.Color.fromRGBString */
649 this.Color.fromRGBString = m.bind(
650 this.Color._fromColorString, this.Color, "rgb", "fromRGB",
651 [1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
652 );
653 /** @id MochiKit.Color.fromHSLString */
654 this.Color.fromHSLString = m.bind(
655 this.Color._fromColorString, this.Color, "hsl", "fromHSL",
656 [1.0/360.0, 0.01, 0.01, 1]
657 );
658
659 var third = 1.0 / 3.0;
660 /** @id MochiKit.Color.colors */
661 var colors = {
662 // NSColor colors plus transparent
663 /** @id MochiKit.Color.blackColor */
664 black: [0, 0, 0],
665 /** @id MochiKit.Color.blueColor */
666 blue: [0, 0, 1],
667 /** @id MochiKit.Color.brownColor */
668 brown: [0.6, 0.4, 0.2],
669 /** @id MochiKit.Color.cyanColor */
670 cyan: [0, 1, 1],
671 /** @id MochiKit.Color.darkGrayColor */
672 darkGray: [third, third, third],
673 /** @id MochiKit.Color.grayColor */
674 gray: [0.5, 0.5, 0.5],
675 /** @id MochiKit.Color.greenColor */
676 green: [0, 1, 0],
677 /** @id MochiKit.Color.lightGrayColor */
678 lightGray: [2 * third, 2 * third, 2 * third],
679 /** @id MochiKit.Color.magentaColor */
680 magenta: [1, 0, 1],
681 /** @id MochiKit.Color.orangeColor */
682 orange: [1, 0.5, 0],
683 /** @id MochiKit.Color.purpleColor */
684 purple: [0.5, 0, 0.5],
685 /** @id MochiKit.Color.redColor */
686 red: [1, 0, 0],
687 /** @id MochiKit.Color.transparentColor */
688 transparent: [0, 0, 0, 0],
689 /** @id MochiKit.Color.whiteColor */
690 white: [1, 1, 1],
691 /** @id MochiKit.Color.yellowColor */
692 yellow: [1, 1, 0]
693 };
694
695 var makeColor = function (name, r, g, b, a) {
696 var rval = this.fromRGB(r, g, b, a);
697 this[name] = function () { return rval; };
698 return rval;
699 };
700
701 for (var k in colors) {
702 var name = k + "Color";
703 var bindArgs = m.concat(
704 [makeColor, this.Color, name],
705 colors[k]
706 );
707 this.Color[name] = m.bind.apply(null, bindArgs);
708 }
709
710 var isColor = function () {
711 for (var i = 0; i < arguments.length; i++) {
712 if (!(arguments[i] instanceof Color)) {
713 return false;
714 }
715 }
716 return true;
717 };
718
719 var compareColor = function (a, b) {
720 return a.compareRGB(b);
721 };
722
723 m.nameFunctions(this);
724
725 m.registerComparator(this.Color.NAME, isColor, compareColor);
726
727 this.EXPORT_TAGS = {
728 ":common": this.EXPORT,
729 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
730 };
731
732 }
733});
734
735MochiKit.Color.EXPORT = [
736 "Color"
737];
738
739MochiKit.Color.EXPORT_OK = [
740 "clampColorComponent",
741 "rgbToHSL",
742 "hslToRGB",
743 "rgbToHSV",
744 "hsvToRGB",
745 "toColorPart"
746];
747
748MochiKit.Color.__new__();
749
750MochiKit.Base._exportSymbols(this, MochiKit.Color);
751
752// Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
753
754MochiKit.Color.Color._namedColors = {
755 aliceblue: "#f0f8ff",
756 antiquewhite: "#faebd7",
757 aqua: "#00ffff",
758 aquamarine: "#7fffd4",
759 azure: "#f0ffff",
760 beige: "#f5f5dc",
761 bisque: "#ffe4c4",
762 black: "#000000",
763 blanchedalmond: "#ffebcd",
764 blue: "#0000ff",
765 blueviolet: "#8a2be2",
766 brown: "#a52a2a",
767 burlywood: "#deb887",
768 cadetblue: "#5f9ea0",
769 chartreuse: "#7fff00",
770 chocolate: "#d2691e",
771 coral: "#ff7f50",
772 cornflowerblue: "#6495ed",
773 cornsilk: "#fff8dc",
774 crimson: "#dc143c",
775 cyan: "#00ffff",
776 darkblue: "#00008b",
777 darkcyan: "#008b8b",
778 darkgoldenrod: "#b8860b",
779 darkgray: "#a9a9a9",
780 darkgreen: "#006400",
781 darkgrey: "#a9a9a9",
782 darkkhaki: "#bdb76b",
783 darkmagenta: "#8b008b",
784 darkolivegreen: "#556b2f",
785 darkorange: "#ff8c00",
786 darkorchid: "#9932cc",
787 darkred: "#8b0000",
788 darksalmon: "#e9967a",
789 darkseagreen: "#8fbc8f",
790 darkslateblue: "#483d8b",
791 darkslategray: "#2f4f4f",
792 darkslategrey: "#2f4f4f",
793 darkturquoise: "#00ced1",
794 darkviolet: "#9400d3",
795 deeppink: "#ff1493",
796 deepskyblue: "#00bfff",
797 dimgray: "#696969",
798 dimgrey: "#696969",
799 dodgerblue: "#1e90ff",
800 firebrick: "#b22222",
801 floralwhite: "#fffaf0",
802 forestgreen: "#228b22",
803 fuchsia: "#ff00ff",
804 gainsboro: "#dcdcdc",
805 ghostwhite: "#f8f8ff",
806 gold: "#ffd700",
807 goldenrod: "#daa520",
808 gray: "#808080",
809 green: "#008000",
810 greenyellow: "#adff2f",
811 grey: "#808080",
812 honeydew: "#f0fff0",
813 hotpink: "#ff69b4",
814 indianred: "#cd5c5c",
815 indigo: "#4b0082",
816 ivory: "#fffff0",
817 khaki: "#f0e68c",
818 lavender: "#e6e6fa",
819 lavenderblush: "#fff0f5",
820 lawngreen: "#7cfc00",
821 lemonchiffon: "#fffacd",
822 lightblue: "#add8e6",
823 lightcoral: "#f08080",
824 lightcyan: "#e0ffff",
825 lightgoldenrodyellow: "#fafad2",
826 lightgray: "#d3d3d3",
827 lightgreen: "#90ee90",
828 lightgrey: "#d3d3d3",
829 lightpink: "#ffb6c1",
830 lightsalmon: "#ffa07a",
831 lightseagreen: "#20b2aa",
832 lightskyblue: "#87cefa",
833 lightslategray: "#778899",
834 lightslategrey: "#778899",
835 lightsteelblue: "#b0c4de",
836 lightyellow: "#ffffe0",
837 lime: "#00ff00",
838 limegreen: "#32cd32",
839 linen: "#faf0e6",
840 magenta: "#ff00ff",
841 maroon: "#800000",
842 mediumaquamarine: "#66cdaa",
843 mediumblue: "#0000cd",
844 mediumorchid: "#ba55d3",
845 mediumpurple: "#9370db",
846 mediumseagreen: "#3cb371",
847 mediumslateblue: "#7b68ee",
848 mediumspringgreen: "#00fa9a",
849 mediumturquoise: "#48d1cc",
850 mediumvioletred: "#c71585",
851 midnightblue: "#191970",
852 mintcream: "#f5fffa",
853 mistyrose: "#ffe4e1",
854 moccasin: "#ffe4b5",
855 navajowhite: "#ffdead",
856 navy: "#000080",
857 oldlace: "#fdf5e6",
858 olive: "#808000",
859 olivedrab: "#6b8e23",
860 orange: "#ffa500",
861 orangered: "#ff4500",
862 orchid: "#da70d6",
863 palegoldenrod: "#eee8aa",
864 palegreen: "#98fb98",
865 paleturquoise: "#afeeee",
866 palevioletred: "#db7093",
867 papayawhip: "#ffefd5",
868 peachpuff: "#ffdab9",
869 peru: "#cd853f",
870 pink: "#ffc0cb",
871 plum: "#dda0dd",
872 powderblue: "#b0e0e6",
873 purple: "#800080",
874 red: "#ff0000",
875 rosybrown: "#bc8f8f",
876 royalblue: "#4169e1",
877 saddlebrown: "#8b4513",
878 salmon: "#fa8072",
879 sandybrown: "#f4a460",
880 seagreen: "#2e8b57",
881 seashell: "#fff5ee",
882 sienna: "#a0522d",
883 silver: "#c0c0c0",
884 skyblue: "#87ceeb",
885 slateblue: "#6a5acd",
886 slategray: "#708090",
887 slategrey: "#708090",
888 snow: "#fffafa",
889 springgreen: "#00ff7f",
890 steelblue: "#4682b4",
891 tan: "#d2b48c",
892 teal: "#008080",
893 thistle: "#d8bfd8",
894 tomato: "#ff6347",
895 turquoise: "#40e0d0",
896 violet: "#ee82ee",
897 wheat: "#f5deb3",
898 white: "#ffffff",
899 whitesmoke: "#f5f5f5",
900 yellow: "#ffff00",
901 yellowgreen: "#9acd32"
902};
diff --git a/frontend/beta/js/MochiKit/Controls.js b/frontend/beta/js/MochiKit/Controls.js
new file mode 100644
index 0000000..b0bc5bf
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Controls.js
@@ -0,0 +1,1388 @@
1/***
2Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
3 (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
4 (c) 2005 Jon Tirsen (http://www.tirsen.com)
5Contributors:
6 Richard Livsey
7 Rahul Bhargava
8 Rob Wills
9 Mochi-ized By Thomas Herve (_firstname_@nimail.org)
10
11See scriptaculous.js for full license.
12
13Autocompleter.Base handles all the autocompletion functionality
14that's independent of the data source for autocompletion. This
15includes drawing the autocompletion menu, observing keyboard
16and mouse events, and similar.
17
18Specific autocompleters need to provide, at the very least,
19a getUpdatedChoices function that will be invoked every time
20the text inside the monitored textbox changes. This method
21should get the text for which to provide autocompletion by
22invoking this.getToken(), NOT by directly accessing
23this.element.value. This is to allow incremental tokenized
24autocompletion. Specific auto-completion logic (AJAX, etc)
25belongs in getUpdatedChoices.
26
27Tokenized incremental autocompletion is enabled automatically
28when an autocompleter is instantiated with the 'tokens' option
29in the options parameter, e.g.:
30new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
31will incrementally autocomplete with a comma as the token.
32Additionally, ',' in the above example can be replaced with
33a token array, e.g. { tokens: [',', '\n'] } which
34enables autocompletion on multiple tokens. This is most
35useful when one of the tokens is \n (a newline), as it
36allows smart autocompletion after linebreaks.
37
38***/
39
40MochiKit.Base.update(MochiKit.Base, {
41 ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
42
43/** @id MochiKit.Base.stripScripts */
44 stripScripts: function (str) {
45 return str.replace(new RegExp(MochiKit.Base.ScriptFragment, 'img'), '');
46 },
47
48/** @id MochiKit.Base.stripTags */
49 stripTags: function(str) {
50 return str.replace(/<\/?[^>]+>/gi, '');
51 },
52
53/** @id MochiKit.Base.extractScripts */
54 extractScripts: function (str) {
55 var matchAll = new RegExp(MochiKit.Base.ScriptFragment, 'img');
56 var matchOne = new RegExp(MochiKit.Base.ScriptFragment, 'im');
57 return MochiKit.Base.map(function (scriptTag) {
58 return (scriptTag.match(matchOne) || ['', ''])[1];
59 }, str.match(matchAll) || []);
60 },
61
62/** @id MochiKit.Base.evalScripts */
63 evalScripts: function (str) {
64 return MochiKit.Base.map(function (scr) {
65 eval(scr);
66 }, MochiKit.Base.extractScripts(str));
67 }
68});
69
70MochiKit.Form = {
71
72/** @id MochiKit.Form.serialize */
73 serialize: function (form) {
74 var elements = MochiKit.Form.getElements(form);
75 var queryComponents = [];
76
77 for (var i = 0; i < elements.length; i++) {
78 var queryComponent = MochiKit.Form.serializeElement(elements[i]);
79 if (queryComponent) {
80 queryComponents.push(queryComponent);
81 }
82 }
83
84 return queryComponents.join('&');
85 },
86
87/** @id MochiKit.Form.getElements */
88 getElements: function (form) {
89 form = MochiKit.DOM.getElement(form);
90 var elements = [];
91
92 for (tagName in MochiKit.Form.Serializers) {
93 var tagElements = form.getElementsByTagName(tagName);
94 for (var j = 0; j < tagElements.length; j++) {
95 elements.push(tagElements[j]);
96 }
97 }
98 return elements;
99 },
100
101/** @id MochiKit.Form.serializeElement */
102 serializeElement: function (element) {
103 element = MochiKit.DOM.getElement(element);
104 var method = element.tagName.toLowerCase();
105 var parameter = MochiKit.Form.Serializers[method](element);
106
107 if (parameter) {
108 var key = encodeURIComponent(parameter[0]);
109 if (key.length === 0) {
110 return;
111 }
112
113 if (!(parameter[1] instanceof Array)) {
114 parameter[1] = [parameter[1]];
115 }
116
117 return parameter[1].map(function (value) {
118 return key + '=' + encodeURIComponent(value);
119 }).join('&');
120 }
121 }
122};
123
124MochiKit.Form.Serializers = {
125
126/** @id MochiKit.Form.Serializers.input */
127 input: function (element) {
128 switch (element.type.toLowerCase()) {
129 case 'submit':
130 case 'hidden':
131 case 'password':
132 case 'text':
133 return MochiKit.Form.Serializers.textarea(element);
134 case 'checkbox':
135 case 'radio':
136 return MochiKit.Form.Serializers.inputSelector(element);
137 }
138 return false;
139 },
140
141/** @id MochiKit.Form.Serializers.inputSelector */
142 inputSelector: function (element) {
143 if (element.checked) {
144 return [element.name, element.value];
145 }
146 },
147
148/** @id MochiKit.Form.Serializers.textarea */
149 textarea: function (element) {
150 return [element.name, element.value];
151 },
152
153/** @id MochiKit.Form.Serializers.select */
154 select: function (element) {
155 return MochiKit.Form.Serializers[element.type == 'select-one' ?
156 'selectOne' : 'selectMany'](element);
157 },
158
159/** @id MochiKit.Form.Serializers.selectOne */
160 selectOne: function (element) {
161 var value = '', opt, index = element.selectedIndex;
162 if (index >= 0) {
163 opt = element.options[index];
164 value = opt.value;
165 if (!value && !('value' in opt)) {
166 value = opt.text;
167 }
168 }
169 return [element.name, value];
170 },
171
172/** @id MochiKit.Form.Serializers.selectMany */
173 selectMany: function (element) {
174 var value = [];
175 for (var i = 0; i < element.length; i++) {
176 var opt = element.options[i];
177 if (opt.selected) {
178 var optValue = opt.value;
179 if (!optValue && !('value' in opt)) {
180 optValue = opt.text;
181 }
182 value.push(optValue);
183 }
184 }
185 return [element.name, value];
186 }
187};
188
189/** @id Ajax */
190var Ajax = {
191 activeRequestCount: 0
192};
193
194Ajax.Responders = {
195 responders: [],
196
197/** @id Ajax.Responders.register */
198 register: function (responderToAdd) {
199 if (MochiKit.Base.find(this.responders, responderToAdd) == -1) {
200 this.responders.push(responderToAdd);
201 }
202 },
203
204/** @id Ajax.Responders.unregister */
205 unregister: function (responderToRemove) {
206 this.responders = this.responders.without(responderToRemove);
207 },
208
209/** @id Ajax.Responders.dispatch */
210 dispatch: function (callback, request, transport, json) {
211 MochiKit.Iter.forEach(this.responders, function (responder) {
212 if (responder[callback] &&
213 typeof(responder[callback]) == 'function') {
214 try {
215 responder[callback].apply(responder, [request, transport, json]);
216 } catch (e) {}
217 }
218 });
219 }
220};
221
222Ajax.Responders.register({
223
224/** @id Ajax.Responders.onCreate */
225 onCreate: function () {
226 Ajax.activeRequestCount++;
227 },
228
229/** @id Ajax.Responders.onComplete */
230 onComplete: function () {
231 Ajax.activeRequestCount--;
232 }
233});
234
235/** @id Ajax.Base */
236Ajax.Base = function () {};
237
238Ajax.Base.prototype = {
239
240/** @id Ajax.Base.prototype.setOptions */
241 setOptions: function (options) {
242 this.options = {
243 method: 'post',
244 asynchronous: true,
245 parameters: ''
246 }
247 MochiKit.Base.update(this.options, options || {});
248 },
249
250/** @id Ajax.Base.prototype.responseIsSuccess */
251 responseIsSuccess: function () {
252 return this.transport.status == undefined
253 || this.transport.status === 0
254 || (this.transport.status >= 200 && this.transport.status < 300);
255 },
256
257/** @id Ajax.Base.prototype.responseIsFailure */
258 responseIsFailure: function () {
259 return !this.responseIsSuccess();
260 }
261};
262
263/** @id Ajax.Request */
264Ajax.Request = function (url, options) {
265 this.__init__(url, options);
266};
267
268/** @id Ajax.Events */
269Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded',
270 'Interactive', 'Complete'];
271
272MochiKit.Base.update(Ajax.Request.prototype, Ajax.Base.prototype);
273
274MochiKit.Base.update(Ajax.Request.prototype, {
275 __init__: function (url, options) {
276 this.transport = MochiKit.Async.getXMLHttpRequest();
277 this.setOptions(options);
278 this.request(url);
279 },
280
281/** @id Ajax.Request.prototype.request */
282 request: function (url) {
283 var parameters = this.options.parameters || '';
284 if (parameters.length > 0){
285 parameters += '&_=';
286 }
287
288 try {
289 this.url = url;
290 if (this.options.method == 'get' && parameters.length > 0) {
291 this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
292 }
293 Ajax.Responders.dispatch('onCreate', this, this.transport);
294
295 this.transport.open(this.options.method, this.url,
296 this.options.asynchronous);
297
298 if (this.options.asynchronous) {
299 this.transport.onreadystatechange = MochiKit.Base.bind(this.onStateChange, this);
300 setTimeout(MochiKit.Base.bind(function () {
301 this.respondToReadyState(1);
302 }, this), 10);
303 }
304
305 this.setRequestHeaders();
306
307 var body = this.options.postBody ? this.options.postBody : parameters;
308 this.transport.send(this.options.method == 'post' ? body : null);
309
310 } catch (e) {
311 this.dispatchException(e);
312 }
313 },
314
315/** @id Ajax.Request.prototype.setRequestHeaders */
316 setRequestHeaders: function () {
317 var requestHeaders = ['X-Requested-With', 'XMLHttpRequest'];
318
319 if (this.options.method == 'post') {
320 requestHeaders.push('Content-type',
321 'application/x-www-form-urlencoded');
322
323 /* Force 'Connection: close' for Mozilla browsers to work around
324 * a bug where XMLHttpRequest sends an incorrect Content-length
325 * header. See Mozilla Bugzilla #246651.
326 */
327 if (this.transport.overrideMimeType) {
328 requestHeaders.push('Connection', 'close');
329 }
330 }
331
332 if (this.options.requestHeaders) {
333 requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
334 }
335
336 for (var i = 0; i < requestHeaders.length; i += 2) {
337 this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
338 }
339 },
340
341/** @id Ajax.Request.prototype.onStateChange */
342 onStateChange: function () {
343 var readyState = this.transport.readyState;
344 if (readyState != 1) {
345 this.respondToReadyState(this.transport.readyState);
346 }
347 },
348
349/** @id Ajax.Request.prototype.header */
350 header: function (name) {
351 try {
352 return this.transport.getResponseHeader(name);
353 } catch (e) {}
354 },
355
356/** @id Ajax.Request.prototype.evalJSON */
357 evalJSON: function () {
358 try {
359 return eval(this.header('X-JSON'));
360 } catch (e) {}
361 },
362
363/** @id Ajax.Request.prototype.evalResponse */
364 evalResponse: function () {
365 try {
366 return eval(this.transport.responseText);
367 } catch (e) {
368 this.dispatchException(e);
369 }
370 },
371
372/** @id Ajax.Request.prototype.respondToReadyState */
373 respondToReadyState: function (readyState) {
374 var event = Ajax.Request.Events[readyState];
375 var transport = this.transport, json = this.evalJSON();
376
377 if (event == 'Complete') {
378 try {
379 (this.options['on' + this.transport.status]
380 || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
381 || MochiKit.Base.noop)(transport, json);
382 } catch (e) {
383 this.dispatchException(e);
384 }
385
386 if ((this.header('Content-type') || '').match(/^text\/javascript/i)) {
387 this.evalResponse();
388 }
389 }
390
391 try {
392 (this.options['on' + event] || MochiKit.Base.noop)(transport, json);
393 Ajax.Responders.dispatch('on' + event, this, transport, json);
394 } catch (e) {
395 this.dispatchException(e);
396 }
397
398 /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
399 if (event == 'Complete') {
400 this.transport.onreadystatechange = MochiKit.Base.noop;
401 }
402 },
403
404/** @id Ajax.Request.prototype.dispatchException */
405 dispatchException: function (exception) {
406 (this.options.onException || MochiKit.Base.noop)(this, exception);
407 Ajax.Responders.dispatch('onException', this, exception);
408 }
409});
410
411/** @id Ajax.Updater */
412Ajax.Updater = function (container, url, options) {
413 this.__init__(container, url, options);
414};
415
416MochiKit.Base.update(Ajax.Updater.prototype, Ajax.Request.prototype);
417
418MochiKit.Base.update(Ajax.Updater.prototype, {
419 __init__: function (container, url, options) {
420 this.containers = {
421 success: container.success ? MochiKit.DOM.getElement(container.success) : MochiKit.DOM.getElement(container),
422 failure: container.failure ? MochiKit.DOM.getElement(container.failure) :
423 (container.success ? null : MochiKit.DOM.getElement(container))
424 }
425 this.transport = MochiKit.Async.getXMLHttpRequest();
426 this.setOptions(options);
427
428 var onComplete = this.options.onComplete || MochiKit.Base.noop;
429 this.options.onComplete = MochiKit.Base.bind(function (transport, object) {
430 this.updateContent();
431 onComplete(transport, object);
432 }, this);
433
434 this.request(url);
435 },
436
437/** @id Ajax.Updater.prototype.updateContent */
438 updateContent: function () {
439 var receiver = this.responseIsSuccess() ?
440 this.containers.success : this.containers.failure;
441 var response = this.transport.responseText;
442
443 if (!this.options.evalScripts) {
444 response = MochiKit.Base.stripScripts(response);
445 }
446
447 if (receiver) {
448 if (this.options.insertion) {
449 new this.options.insertion(receiver, response);
450 } else {
451 MochiKit.DOM.getElement(receiver).innerHTML =
452 MochiKit.Base.stripScripts(response);
453 setTimeout(function () {
454 MochiKit.Base.evalScripts(response);
455 }, 10);
456 }
457 }
458
459 if (this.responseIsSuccess()) {
460 if (this.onComplete) {
461 setTimeout(MochiKit.Base.bind(this.onComplete, this), 10);
462 }
463 }
464 }
465});
466
467/** @id Field */
468var Field = {
469
470/** @id clear */
471 clear: function () {
472 for (var i = 0; i < arguments.length; i++) {
473 MochiKit.DOM.getElement(arguments[i]).value = '';
474 }
475 },
476
477/** @id focus */
478 focus: function (element) {
479 MochiKit.DOM.getElement(element).focus();
480 },
481
482/** @id present */
483 present: function () {
484 for (var i = 0; i < arguments.length; i++) {
485 if (MochiKit.DOM.getElement(arguments[i]).value == '') {
486 return false;
487 }
488 }
489 return true;
490 },
491
492/** @id select */
493 select: function (element) {
494 MochiKit.DOM.getElement(element).select();
495 },
496
497/** @id activate */
498 activate: function (element) {
499 element = MochiKit.DOM.getElement(element);
500 element.focus();
501 if (element.select) {
502 element.select();
503 }
504 },
505
506/** @id scrollFreeActivate */
507 scrollFreeActivate: function (field) {
508 setTimeout(function () {
509 Field.activate(field);
510 }, 1);
511 }
512};
513
514
515/** @id Autocompleter */
516var Autocompleter = {};
517
518/** @id Autocompleter.Base */
519Autocompleter.Base = function () {};
520
521Autocompleter.Base.prototype = {
522
523/** @id Autocompleter.Base.prototype.baseInitialize */
524 baseInitialize: function (element, update, options) {
525 this.element = MochiKit.DOM.getElement(element);
526 this.update = MochiKit.DOM.getElement(update);
527 this.hasFocus = false;
528 this.changed = false;
529 this.active = false;
530 this.index = 0;
531 this.entryCount = 0;
532
533 if (this.setOptions) {
534 this.setOptions(options);
535 }
536 else {
537 this.options = options || {};
538 }
539
540 this.options.paramName = this.options.paramName || this.element.name;
541 this.options.tokens = this.options.tokens || [];
542 this.options.frequency = this.options.frequency || 0.4;
543 this.options.minChars = this.options.minChars || 1;
544 this.options.onShow = this.options.onShow || function (element, update) {
545 if (!update.style.position || update.style.position == 'absolute') {
546 update.style.position = 'absolute';
547 MochiKit.Position.clone(element, update, {
548 setHeight: false,
549 offsetTop: element.offsetHeight
550 });
551 }
552 MochiKit.Visual.appear(update, {duration:0.15});
553 };
554 this.options.onHide = this.options.onHide || function (element, update) {
555 MochiKit.Visual.fade(update, {duration: 0.15});
556 };
557
558 if (typeof(this.options.tokens) == 'string') {
559 this.options.tokens = new Array(this.options.tokens);
560 }
561
562 this.observer = null;
563
564 this.element.setAttribute('autocomplete', 'off');
565
566 MochiKit.Style.hideElement(this.update);
567
568 MochiKit.Signal.connect(this.element, 'onblur', this, this.onBlur);
569 MochiKit.Signal.connect(this.element, 'onkeypress', this, this.onKeyPress, this);
570 },
571
572/** @id Autocompleter.Base.prototype.show */
573 show: function () {
574 if (MochiKit.Style.getStyle(this.update, 'display') == 'none') {
575 this.options.onShow(this.element, this.update);
576 }
577 if (!this.iefix && /MSIE/.test(navigator.userAgent &&
578 (MochiKit.Style.getStyle(this.update, 'position') == 'absolute'))) {
579 new Insertion.After(this.update,
580 '<iframe id="' + this.update.id + '_iefix" '+
581 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
582 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
583 this.iefix = MochiKit.DOM.getElement(this.update.id + '_iefix');
584 }
585 if (this.iefix) {
586 setTimeout(MochiKit.Base.bind(this.fixIEOverlapping, this), 50);
587 }
588 },
589
590/** @id Autocompleter.Base.prototype.fixIEOverlapping */
591 fixIEOverlapping: function () {
592 MochiKit.Position.clone(this.update, this.iefix);
593 this.iefix.style.zIndex = 1;
594 this.update.style.zIndex = 2;
595 MochiKit.Style.showElement(this.iefix);
596 },
597
598/** @id Autocompleter.Base.prototype.hide */
599 hide: function () {
600 this.stopIndicator();
601 if (MochiKit.Style.getStyle(this.update, 'display') != 'none') {
602 this.options.onHide(this.element, this.update);
603 }
604 if (this.iefix) {
605 MochiKit.Style.hideElement(this.iefix);
606 }
607 },
608
609/** @id Autocompleter.Base.prototype.startIndicator */
610 startIndicator: function () {
611 if (this.options.indicator) {
612 MochiKit.Style.showElement(this.options.indicator);
613 }
614 },
615
616/** @id Autocompleter.Base.prototype.stopIndicator */
617 stopIndicator: function () {
618 if (this.options.indicator) {
619 MochiKit.Style.hideElement(this.options.indicator);
620 }
621 },
622
623/** @id Autocompleter.Base.prototype.onKeyPress */
624 onKeyPress: function (event) {
625 if (this.active) {
626 if (event.key().string == "KEY_TAB" || event.key().string == "KEY_RETURN") {
627 this.selectEntry();
628 MochiKit.Event.stop(event);
629 } else if (event.key().string == "KEY_ESCAPE") {
630 this.hide();
631 this.active = false;
632 MochiKit.Event.stop(event);
633 return;
634 } else if (event.key().string == "KEY_LEFT" || event.key().string == "KEY_RIGHT") {
635 return;
636 } else if (event.key().string == "KEY_UP") {
637 this.markPrevious();
638 this.render();
639 if (/AppleWebKit'/.test(navigator.appVersion)) {
640 event.stop();
641 }
642 return;
643 } else if (event.key().string == "KEY_DOWN") {
644 this.markNext();
645 this.render();
646 if (/AppleWebKit'/.test(navigator.appVersion)) {
647 event.stop();
648 }
649 return;
650 }
651 } else {
652 if (event.key().string == "KEY_TAB" || event.key().string == "KEY_RETURN") {
653 return;
654 }
655 }
656
657 this.changed = true;
658 this.hasFocus = true;
659
660 if (this.observer) {
661 clearTimeout(this.observer);
662 }
663 this.observer = setTimeout(MochiKit.Base.bind(this.onObserverEvent, this),
664 this.options.frequency*1000);
665 },
666
667/** @id Autocompleter.Base.prototype.findElement */
668 findElement: function (event, tagName) {
669 var element = event.target;
670 while (element.parentNode && (!element.tagName ||
671 (element.tagName.toUpperCase() != tagName.toUpperCase()))) {
672 element = element.parentNode;
673 }
674 return element;
675 },
676
677/** @id Autocompleter.Base.prototype.hover */
678 onHover: function (event) {
679 var element = this.findElement(event, 'LI');
680 if (this.index != element.autocompleteIndex) {
681 this.index = element.autocompleteIndex;
682 this.render();
683 }
684 event.stop();
685 },
686
687/** @id Autocompleter.Base.prototype.onClick */
688 onClick: function (event) {
689 var element = this.findElement(event, 'LI');
690 this.index = element.autocompleteIndex;
691 this.selectEntry();
692 this.hide();
693 },
694
695/** @id Autocompleter.Base.prototype.onBlur */
696 onBlur: function (event) {
697 // needed to make click events working
698 setTimeout(MochiKit.Base.bind(this.hide, this), 250);
699 this.hasFocus = false;
700 this.active = false;
701 },
702
703/** @id Autocompleter.Base.prototype.render */
704 render: function () {
705 if (this.entryCount > 0) {
706 for (var i = 0; i < this.entryCount; i++) {
707 this.index == i ?
708 MochiKit.DOM.addElementClass(this.getEntry(i), 'selected') :
709 MochiKit.DOM.removeElementClass(this.getEntry(i), 'selected');
710 }
711 if (this.hasFocus) {
712 this.show();
713 this.active = true;
714 }
715 } else {
716 this.active = false;
717 this.hide();
718 }
719 },
720
721/** @id Autocompleter.Base.prototype.markPrevious */
722 markPrevious: function () {
723 if (this.index > 0) {
724 this.index--
725 } else {
726 this.index = this.entryCount-1;
727 }
728 },
729
730/** @id Autocompleter.Base.prototype.markNext */
731 markNext: function () {
732 if (this.index < this.entryCount-1) {
733 this.index++
734 } else {
735 this.index = 0;
736 }
737 },
738
739/** @id Autocompleter.Base.prototype.getEntry */
740 getEntry: function (index) {
741 return this.update.firstChild.childNodes[index];
742 },
743
744/** @id Autocompleter.Base.prototype.getCurrentEntry */
745 getCurrentEntry: function () {
746 return this.getEntry(this.index);
747 },
748
749/** @id Autocompleter.Base.prototype.selectEntry */
750 selectEntry: function () {
751 this.active = false;
752 this.updateElement(this.getCurrentEntry());
753 },
754
755/** @id Autocompleter.Base.prototype.collectTextNodesIgnoreClass */
756 collectTextNodesIgnoreClass: function (element, className) {
757 return MochiKit.Base.flattenArray(MochiKit.Base.map(function (node) {
758 if (node.nodeType == 3) {
759 return node.nodeValue;
760 } else if (node.hasChildNodes() && !MochiKit.DOM.hasElementClass(node, className)) {
761 return this.collectTextNodesIgnoreClass(node, className);
762 }
763 return '';
764 }, MochiKit.DOM.getElement(element).childNodes)).join('');
765 },
766
767/** @id Autocompleter.Base.prototype.updateElement */
768 updateElement: function (selectedElement) {
769 if (this.options.updateElement) {
770 this.options.updateElement(selectedElement);
771 return;
772 }
773 var value = '';
774 if (this.options.select) {
775 var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
776 if (nodes.length > 0) {
777 value = MochiKit.DOM.scrapeText(nodes[0]);
778 }
779 } else {
780 value = this.collectTextNodesIgnoreClass(selectedElement, 'informal');
781 }
782 var lastTokenPos = this.findLastToken();
783 if (lastTokenPos != -1) {
784 var newValue = this.element.value.substr(0, lastTokenPos + 1);
785 var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
786 if (whitespace) {
787 newValue += whitespace[0];
788 }
789 this.element.value = newValue + value;
790 } else {
791 this.element.value = value;
792 }
793 this.element.focus();
794
795 if (this.options.afterUpdateElement) {
796 this.options.afterUpdateElement(this.element, selectedElement);
797 }
798 },
799
800/** @id Autocompleter.Base.prototype.updateChoices */
801 updateChoices: function (choices) {
802 if (!this.changed && this.hasFocus) {
803 this.update.innerHTML = choices;
804 var d = MochiKit.DOM;
805 d.removeEmptyTextNodes(this.update);
806 d.removeEmptyTextNodes(this.update.firstChild);
807
808 if (this.update.firstChild && this.update.firstChild.childNodes) {
809 this.entryCount = this.update.firstChild.childNodes.length;
810 for (var i = 0; i < this.entryCount; i++) {
811 var entry = this.getEntry(i);
812 entry.autocompleteIndex = i;
813 this.addObservers(entry);
814 }
815 } else {
816 this.entryCount = 0;
817 }
818
819 this.stopIndicator();
820
821 this.index = 0;
822 this.render();
823 }
824 },
825
826/** @id Autocompleter.Base.prototype.addObservers */
827 addObservers: function (element) {
828 MochiKit.Signal.connect(element, 'onmouseover', this, this.onHover);
829 MochiKit.Signal.connect(element, 'onclick', this, this.onClick);
830 },
831
832/** @id Autocompleter.Base.prototype.onObserverEvent */
833 onObserverEvent: function () {
834 this.changed = false;
835 if (this.getToken().length >= this.options.minChars) {
836 this.startIndicator();
837 this.getUpdatedChoices();
838 } else {
839 this.active = false;
840 this.hide();
841 }
842 },
843
844/** @id Autocompleter.Base.prototype.getToken */
845 getToken: function () {
846 var tokenPos = this.findLastToken();
847 if (tokenPos != -1) {
848 var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
849 } else {
850 var ret = this.element.value;
851 }
852 return /\n/.test(ret) ? '' : ret;
853 },
854
855/** @id Autocompleter.Base.prototype.findLastToken */
856 findLastToken: function () {
857 var lastTokenPos = -1;
858
859 for (var i = 0; i < this.options.tokens.length; i++) {
860 var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
861 if (thisTokenPos > lastTokenPos) {
862 lastTokenPos = thisTokenPos;
863 }
864 }
865 return lastTokenPos;
866 }
867}
868
869/** @id Ajax.Autocompleter */
870Ajax.Autocompleter = function (element, update, url, options) {
871 this.__init__(element, update, url, options);
872};
873
874MochiKit.Base.update(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype);
875
876MochiKit.Base.update(Ajax.Autocompleter.prototype, {
877 __init__: function (element, update, url, options) {
878 this.baseInitialize(element, update, options);
879 this.options.asynchronous = true;
880 this.options.onComplete = MochiKit.Base.bind(this.onComplete, this);
881 this.options.defaultParams = this.options.parameters || null;
882 this.url = url;
883 },
884
885/** @id Ajax.Autocompleter.prototype.getUpdatedChoices */
886 getUpdatedChoices: function () {
887 var entry = encodeURIComponent(this.options.paramName) + '=' +
888 encodeURIComponent(this.getToken());
889
890 this.options.parameters = this.options.callback ?
891 this.options.callback(this.element, entry) : entry;
892
893 if (this.options.defaultParams) {
894 this.options.parameters += '&' + this.options.defaultParams;
895 }
896 new Ajax.Request(this.url, this.options);
897 },
898
899/** @id Ajax.Autocompleter.prototype.onComplete */
900 onComplete: function (request) {
901 this.updateChoices(request.responseText);
902 }
903});
904
905/***
906
907The local array autocompleter. Used when you'd prefer to
908inject an array of autocompletion options into the page, rather
909than sending out Ajax queries, which can be quite slow sometimes.
910
911The constructor takes four parameters. The first two are, as usual,
912the id of the monitored textbox, and id of the autocompletion menu.
913The third is the array you want to autocomplete from, and the fourth
914is the options block.
915
916Extra local autocompletion options:
917- choices - How many autocompletion choices to offer
918
919- partialSearch - If false, the autocompleter will match entered
920 text only at the beginning of strings in the
921 autocomplete array. Defaults to true, which will
922 match text at the beginning of any *word* in the
923 strings in the autocomplete array. If you want to
924 search anywhere in the string, additionally set
925 the option fullSearch to true (default: off).
926
927- fullSsearch - Search anywhere in autocomplete array strings.
928
929- partialChars - How many characters to enter before triggering
930 a partial match (unlike minChars, which defines
931 how many characters are required to do any match
932 at all). Defaults to 2.
933
934- ignoreCase - Whether to ignore case when autocompleting.
935 Defaults to true.
936
937It's possible to pass in a custom function as the 'selector'
938option, if you prefer to write your own autocompletion logic.
939In that case, the other options above will not apply unless
940you support them.
941
942***/
943
944/** @id Autocompleter.Local */
945Autocompleter.Local = function (element, update, array, options) {
946 this.__init__(element, update, array, options);
947};
948
949MochiKit.Base.update(Autocompleter.Local.prototype, Autocompleter.Base.prototype);
950
951MochiKit.Base.update(Autocompleter.Local.prototype, {
952 __init__: function (element, update, array, options) {
953 this.baseInitialize(element, update, options);
954 this.options.array = array;
955 },
956
957/** @id Autocompleter.Local.prototype.getUpdatedChoices */
958 getUpdatedChoices: function () {
959 this.updateChoices(this.options.selector(this));
960 },
961
962/** @id Autocompleter.Local.prototype.setOptions */
963 setOptions: function (options) {
964 this.options = MochiKit.Base.update({
965 choices: 10,
966 partialSearch: true,
967 partialChars: 2,
968 ignoreCase: true,
969 fullSearch: false,
970 selector: function (instance) {
971 var ret = []; // Beginning matches
972 var partial = []; // Inside matches
973 var entry = instance.getToken();
974 var count = 0;
975
976 for (var i = 0; i < instance.options.array.length &&
977 ret.length < instance.options.choices ; i++) {
978
979 var elem = instance.options.array[i];
980 var foundPos = instance.options.ignoreCase ?
981 elem.toLowerCase().indexOf(entry.toLowerCase()) :
982 elem.indexOf(entry);
983
984 while (foundPos != -1) {
985 if (foundPos === 0 && elem.length != entry.length) {
986 ret.push('<li><strong>' + elem.substr(0, entry.length) + '</strong>' +
987 elem.substr(entry.length) + '</li>');
988 break;
989 } else if (entry.length >= instance.options.partialChars &&
990 instance.options.partialSearch && foundPos != -1) {
991 if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos - 1, 1))) {
992 partial.push('<li>' + elem.substr(0, foundPos) + '<strong>' +
993 elem.substr(foundPos, entry.length) + '</strong>' + elem.substr(
994 foundPos + entry.length) + '</li>');
995 break;
996 }
997 }
998
999 foundPos = instance.options.ignoreCase ?
1000 elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
1001 elem.indexOf(entry, foundPos + 1);
1002
1003 }
1004 }
1005 if (partial.length) {
1006 ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
1007 }
1008 return '<ul>' + ret.join('') + '</ul>';
1009 }
1010 }, options || {});
1011 }
1012});
1013
1014/***
1015
1016AJAX in-place editor
1017
1018see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
1019
1020Use this if you notice weird scrolling problems on some browsers,
1021the DOM might be a bit confused when this gets called so do this
1022waits 1 ms (with setTimeout) until it does the activation
1023
1024***/
1025
1026/** @id Ajax.InPlaceEditor */
1027Ajax.InPlaceEditor = function (element, url, options) {
1028 this.__init__(element, url, options);
1029};
1030
1031/** @id Ajax.InPlaceEditor.defaultHighlightColor */
1032Ajax.InPlaceEditor.defaultHighlightColor = '#FFFF99';
1033
1034Ajax.InPlaceEditor.prototype = {
1035 __init__: function (element, url, options) {
1036 this.url = url;
1037 this.element = MochiKit.DOM.getElement(element);
1038
1039 this.options = MochiKit.Base.update({
1040 okButton: true,
1041 okText: 'ok',
1042 cancelLink: true,
1043 cancelText: 'cancel',
1044 savingText: 'Saving...',
1045 clickToEditText: 'Click to edit',
1046 okText: 'ok',
1047 rows: 1,
1048 onComplete: function (transport, element) {
1049 new MochiKit.Visual.Highlight(element, {startcolor: this.options.highlightcolor});
1050 },
1051 onFailure: function (transport) {
1052 alert('Error communicating with the server: ' + MochiKit.Base.stripTags(transport.responseText));
1053 },
1054 callback: function (form) {
1055 return MochiKit.DOM.formContents(form);
1056 },
1057 handleLineBreaks: true,
1058 loadingText: 'Loading...',
1059 savingClassName: 'inplaceeditor-saving',
1060 loadingClassName: 'inplaceeditor-loading',
1061 formClassName: 'inplaceeditor-form',
1062 highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
1063 highlightendcolor: '#FFFFFF',
1064 externalControl: null,
1065 submitOnBlur: false,
1066 ajaxOptions: {}
1067 }, options || {});
1068
1069 if (!this.options.formId && this.element.id) {
1070 this.options.formId = this.element.id + '-inplaceeditor';
1071 if (MochiKit.DOM.getElement(this.options.formId)) {
1072 // there's already a form with that name, don't specify an id
1073 this.options.formId = null;
1074 }
1075 }
1076
1077 if (this.options.externalControl) {
1078 this.options.externalControl = MochiKit.DOM.getElement(this.options.externalControl);
1079 }
1080
1081 this.originalBackground = MochiKit.Style.getStyle(this.element, 'background-color');
1082 if (!this.originalBackground) {
1083 this.originalBackground = 'transparent';
1084 }
1085
1086 this.element.title = this.options.clickToEditText;
1087
1088 this.onclickListener = MochiKit.Signal.connect(this.element, 'onclick', this, this.enterEditMode);
1089 this.mouseoverListener = MochiKit.Signal.connect(this.element, 'onmouseover', this, this.enterHover);
1090 this.mouseoutListener = MochiKit.Signal.connect(this.element, 'onmouseout', this, this.leaveHover);
1091 if (this.options.externalControl) {
1092 this.onclickListenerExternal = MochiKit.Signal.connect(this.options.externalControl,
1093 'onclick', this, this.enterEditMode);
1094 this.mouseoverListenerExternal = MochiKit.Signal.connect(this.options.externalControl,
1095 'onmouseover', this, this.enterHover);
1096 this.mouseoutListenerExternal = MochiKit.Signal.connect(this.options.externalControl,
1097 'onmouseout', this, this.leaveHover);
1098 }
1099 },
1100
1101/** @id Ajax.InPlaceEditor.prototype.enterEditMode */
1102 enterEditMode: function (evt) {
1103 if (this.saving) {
1104 return;
1105 }
1106 if (this.editing) {
1107 return;
1108 }
1109 this.editing = true;
1110 this.onEnterEditMode();
1111 if (this.options.externalControl) {
1112 MochiKit.Style.hideElement(this.options.externalControl);
1113 }
1114 MochiKit.Style.hideElement(this.element);
1115 this.createForm();
1116 this.element.parentNode.insertBefore(this.form, this.element);
1117 Field.scrollFreeActivate(this.editField);
1118 // stop the event to avoid a page refresh in Safari
1119 if (evt) {
1120 evt.stop();
1121 }
1122 return false;
1123 },
1124
1125/** @id Ajax.InPlaceEditor.prototype.createForm */
1126 createForm: function () {
1127 this.form = document.createElement('form');
1128 this.form.id = this.options.formId;
1129 MochiKit.DOM.addElementClass(this.form, this.options.formClassName)
1130 this.form.onsubmit = MochiKit.Base.bind(this.onSubmit, this);
1131
1132 this.createEditField();
1133
1134 if (this.options.textarea) {
1135 var br = document.createElement('br');
1136 this.form.appendChild(br);
1137 }
1138
1139 if (this.options.okButton) {
1140 okButton = document.createElement('input');
1141 okButton.type = 'submit';
1142 okButton.value = this.options.okText;
1143 this.form.appendChild(okButton);
1144 }
1145
1146 if (this.options.cancelLink) {
1147 cancelLink = document.createElement('a');
1148 cancelLink.href = '#';
1149 cancelLink.appendChild(document.createTextNode(this.options.cancelText));
1150 cancelLink.onclick = MochiKit.Base.bind(this.onclickCancel, this);
1151 this.form.appendChild(cancelLink);
1152 }
1153 },
1154
1155/** @id Ajax.InPlaceEditor.prototype.hasHTMLLineBreaks */
1156 hasHTMLLineBreaks: function (string) {
1157 if (!this.options.handleLineBreaks) {
1158 return false;
1159 }
1160 return string.match(/<br/i) || string.match(/<p>/i);
1161 },
1162
1163/** @id Ajax.InPlaceEditor.prototype.convertHTMLLineBreaks */
1164 convertHTMLLineBreaks: function (string) {
1165 return string.replace(/<br>/gi, '\n').replace(/<br\/>/gi, '\n').replace(/<\/p>/gi, '\n').replace(/<p>/gi, '');
1166 },
1167
1168/** @id Ajax.InPlaceEditor.prototype.createEditField */
1169 createEditField: function () {
1170 var text;
1171 if (this.options.loadTextURL) {
1172 text = this.options.loadingText;
1173 } else {
1174 text = this.getText();
1175 }
1176
1177 var obj = this;
1178
1179 if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
1180 this.options.textarea = false;
1181 var textField = document.createElement('input');
1182 textField.obj = this;
1183 textField.type = 'text';
1184 textField.name = 'value';
1185 textField.value = text;
1186 textField.style.backgroundColor = this.options.highlightcolor;
1187 var size = this.options.size || this.options.cols || 0;
1188 if (size !== 0) {
1189 textField.size = size;
1190 }
1191 if (this.options.submitOnBlur) {
1192 textField.onblur = MochiKit.Base.bind(this.onSubmit, this);
1193 }
1194 this.editField = textField;
1195 } else {
1196 this.options.textarea = true;
1197 var textArea = document.createElement('textarea');
1198 textArea.obj = this;
1199 textArea.name = 'value';
1200 textArea.value = this.convertHTMLLineBreaks(text);
1201 textArea.rows = this.options.rows;
1202 textArea.cols = this.options.cols || 40;
1203 if (this.options.submitOnBlur) {
1204 textArea.onblur = MochiKit.Base.bind(this.onSubmit, this);
1205 }
1206 this.editField = textArea;
1207 }
1208
1209 if (this.options.loadTextURL) {
1210 this.loadExternalText();
1211 }
1212 this.form.appendChild(this.editField);
1213 },
1214
1215/** @id Ajax.InPlaceEditor.prototype.getText */
1216 getText: function () {
1217 return this.element.innerHTML;
1218 },
1219
1220/** @id Ajax.InPlaceEditor.prototype.loadExternalText */
1221 loadExternalText: function () {
1222 MochiKit.DOM.addElementClass(this.form, this.options.loadingClassName);
1223 this.editField.disabled = true;
1224 new Ajax.Request(
1225 this.options.loadTextURL,
1226 MochiKit.Base.update({
1227 asynchronous: true,
1228 onComplete: MochiKit.Base.bind(this.onLoadedExternalText, this)
1229 }, this.options.ajaxOptions)
1230 );
1231 },
1232
1233/** @id Ajax.InPlaceEditor.prototype.onLoadedExternalText */
1234 onLoadedExternalText: function (transport) {
1235 MochiKit.DOM.removeElementClass(this.form, this.options.loadingClassName);
1236 this.editField.disabled = false;
1237 this.editField.value = MochiKit.Base.stripTags(transport);
1238 },
1239
1240/** @id Ajax.InPlaceEditor.prototype.onclickCancel */
1241 onclickCancel: function () {
1242 this.onComplete();
1243 this.leaveEditMode();
1244 return false;
1245 },
1246
1247/** @id Ajax.InPlaceEditor.prototype.onFailure */
1248 onFailure: function (transport) {
1249 this.options.onFailure(transport);
1250 if (this.oldInnerHTML) {
1251 this.element.innerHTML = this.oldInnerHTML;
1252 this.oldInnerHTML = null;
1253 }
1254 return false;
1255 },
1256
1257/** @id Ajax.InPlaceEditor.prototype.onSubmit */
1258 onSubmit: function () {
1259 // onLoading resets these so we need to save them away for the Ajax call
1260 var form = this.form;
1261 var value = this.editField.value;
1262
1263 // do this first, sometimes the ajax call returns before we get a
1264 // chance to switch on Saving which means this will actually switch on
1265 // Saving *after* we have left edit mode causing Saving to be
1266 // displayed indefinitely
1267 this.onLoading();
1268
1269 new Ajax.Updater(
1270 {
1271 success: this.element,
1272 // dont update on failure (this could be an option)
1273 failure: null
1274 },
1275 this.url,
1276 MochiKit.Base.update({
1277 parameters: this.options.callback(form, value),
1278 onComplete: MochiKit.Base.bind(this.onComplete, this),
1279 onFailure: MochiKit.Base.bind(this.onFailure, this)
1280 }, this.options.ajaxOptions)
1281 );
1282 // stop the event to avoid a page refresh in Safari
1283 if (arguments.length > 1) {
1284 arguments[0].stop();
1285 }
1286 return false;
1287 },
1288
1289/** @id Ajax.InPlaceEditor.prototype.onLoading */
1290 onLoading: function () {
1291 this.saving = true;
1292 this.removeForm();
1293 this.leaveHover();
1294 this.showSaving();
1295 },
1296
1297/** @id Ajax.InPlaceEditor.prototype.onSaving */
1298 showSaving: function () {
1299 this.oldInnerHTML = this.element.innerHTML;
1300 this.element.innerHTML = this.options.savingText;
1301 MochiKit.DOM.addElementClass(this.element, this.options.savingClassName);
1302 this.element.style.backgroundColor = this.originalBackground;
1303 MochiKit.Style.showElement(this.element);
1304 },
1305
1306/** @id Ajax.InPlaceEditor.prototype.removeForm */
1307 removeForm: function () {
1308 if (this.form) {
1309 if (this.form.parentNode) {
1310 MochiKit.DOM.removeElement(this.form);
1311 }
1312 this.form = null;
1313 }
1314 },
1315
1316/** @id Ajax.InPlaceEditor.prototype.enterHover */
1317 enterHover: function () {
1318 if (this.saving) {
1319 return;
1320 }
1321 this.element.style.backgroundColor = this.options.highlightcolor;
1322 if (this.effect) {
1323 this.effect.cancel();
1324 }
1325 MochiKit.DOM.addElementClass(this.element, this.options.hoverClassName)
1326 },
1327
1328/** @id Ajax.InPlaceEditor.prototype.leaveHover */
1329 leaveHover: function () {
1330 if (this.options.backgroundColor) {
1331 this.element.style.backgroundColor = this.oldBackground;
1332 }
1333 MochiKit.DOM.removeElementClass(this.element, this.options.hoverClassName)
1334 if (this.saving) {
1335 return;
1336 }
1337 this.effect = new MochiKit.Visual.Highlight(this.element, {
1338 startcolor: this.options.highlightcolor,
1339 endcolor: this.options.highlightendcolor,
1340 restorecolor: this.originalBackground
1341 });
1342 },
1343
1344/** @id Ajax.InPlaceEditor.prototype.leaveEditMode */
1345 leaveEditMode: function () {
1346 MochiKit.DOM.removeElementClass(this.element, this.options.savingClassName);
1347 this.removeForm();
1348 this.leaveHover();
1349 this.element.style.backgroundColor = this.originalBackground;
1350 MochiKit.Style.showElement(this.element);
1351 if (this.options.externalControl) {
1352 MochiKit.Style.showElement(this.options.externalControl);
1353 }
1354 this.editing = false;
1355 this.saving = false;
1356 this.oldInnerHTML = null;
1357 this.onLeaveEditMode();
1358 },
1359
1360/** @id Ajax.InPlaceEditor.prototype.onComplete */
1361 onComplete: function (transport) {
1362 this.leaveEditMode();
1363 MochiKit.Base.bind(this.options.onComplete, this)(transport, this.element);
1364 },
1365
1366/** @id Ajax.InPlaceEditor.prototype.onEnterEditMode */
1367 onEnterEditMode: function () {},
1368
1369/** @id Ajax.InPlaceEditor.prototype.onLeaveEditMode */
1370 onLeaveEditMode: function () {},
1371
1372 /** @id Ajax.InPlaceEditor.prototype.dispose */
1373 dispose: function () {
1374 if (this.oldInnerHTML) {
1375 this.element.innerHTML = this.oldInnerHTML;
1376 }
1377 this.leaveEditMode();
1378 MochiKit.Signal.disconnect(this.onclickListener);
1379 MochiKit.Signal.disconnect(this.mouseoverListener);
1380 MochiKit.Signal.disconnect(this.mouseoutListener);
1381 if (this.options.externalControl) {
1382 MochiKit.Signal.disconnect(this.onclickListenerExternal);
1383 MochiKit.Signal.disconnect(this.mouseoverListenerExternal);
1384 MochiKit.Signal.disconnect(this.mouseoutListenerExternal);
1385 }
1386 }
1387};
1388
diff --git a/frontend/beta/js/MochiKit/DOM.js b/frontend/beta/js/MochiKit/DOM.js
new file mode 100644
index 0000000..591c597
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/DOM.js
@@ -0,0 +1,1267 @@
1/***
2
3MochiKit.DOM 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide("MochiKit.DOM");
13 dojo.require("MochiKit.Base");
14}
15if (typeof(JSAN) != 'undefined') {
16 JSAN.use("MochiKit.Base", []);
17}
18
19try {
20 if (typeof(MochiKit.Base) == 'undefined') {
21 throw "";
22 }
23} catch (e) {
24 throw "MochiKit.DOM depends on MochiKit.Base!";
25}
26
27if (typeof(MochiKit.DOM) == 'undefined') {
28 MochiKit.DOM = {};
29}
30
31MochiKit.DOM.NAME = "MochiKit.DOM";
32MochiKit.DOM.VERSION = "1.4";
33MochiKit.DOM.__repr__ = function () {
34 return "[" + this.NAME + " " + this.VERSION + "]";
35};
36MochiKit.DOM.toString = function () {
37 return this.__repr__();
38};
39
40MochiKit.DOM.EXPORT = [
41 "removeEmptyTextNodes",
42 "formContents",
43 "currentWindow",
44 "currentDocument",
45 "withWindow",
46 "withDocument",
47 "registerDOMConverter",
48 "coerceToDOM",
49 "createDOM",
50 "createDOMFunc",
51 "isChildNode",
52 "getNodeAttribute",
53 "removeNodeAttribute",
54 "setNodeAttribute",
55 "updateNodeAttributes",
56 "appendChildNodes",
57 "insertSiblingNodesAfter",
58 "insertSiblingNodesBefore",
59 "replaceChildNodes",
60 "removeElement",
61 "swapDOM",
62 "BUTTON",
63 "TT",
64 "PRE",
65 "H1",
66 "H2",
67 "H3",
68 "BR",
69 "CANVAS",
70 "HR",
71 "LABEL",
72 "TEXTAREA",
73 "FORM",
74 "STRONG",
75 "SELECT",
76 "OPTION",
77 "OPTGROUP",
78 "LEGEND",
79 "FIELDSET",
80 "P",
81 "UL",
82 "OL",
83 "LI",
84 "TD",
85 "TR",
86 "THEAD",
87 "TBODY",
88 "TFOOT",
89 "TABLE",
90 "TH",
91 "INPUT",
92 "SPAN",
93 "A",
94 "DIV",
95 "IMG",
96 "getElement",
97 "$",
98 "getElementsByTagAndClassName",
99 "addToCallStack",
100 "addLoadEvent",
101 "focusOnLoad",
102 "setElementClass",
103 "toggleElementClass",
104 "addElementClass",
105 "removeElementClass",
106 "swapElementClass",
107 "hasElementClass",
108 "escapeHTML",
109 "toHTML",
110 "emitHTML",
111 "scrapeText",
112 "isParent",
113 "getFirstParentByTagAndClassName",
114 "makeClipping",
115 "undoClipping",
116 "makePositioned",
117 "undoPositioned",
118 "getFirstElementByTagAndClassName"
119];
120
121MochiKit.DOM.EXPORT_OK = [
122 "domConverters"
123];
124
125MochiKit.DOM.DEPRECATED = [
126 ['computedStyle', 'MochiKit.Style.getStyle', '1.4'],
127 /** @id MochiKit.DOM.elementDimensions */
128 ['elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4'],
129 /** @id MochiKit.DOM.elementPosition */
130 ['elementPosition', 'MochiKit.Style.getElementPosition', '1.4'],
131 ['hideElement', 'MochiKit.Style.hideElement', '1.4'],
132 /** @id MochiKit.DOM.setElementDimensions */
133 ['setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4'],
134 /** @id MochiKit.DOM.setElementPosition */
135 ['setElementPosition', 'MochiKit.Style.setElementPosition', '1.4'],
136 ['setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4'],
137 /** @id MochiKit.DOM.setOpacity */
138 ['setOpacity', 'MochiKit.Style.setOpacity', '1.4'],
139 ['showElement', 'MochiKit.Style.showElement', '1.4'],
140 /** @id MochiKit.DOM.Coordinates */
141 ['Coordinates', 'MochiKit.Style.Coordinates', '1.4'], // FIXME: broken
142 /** @id MochiKit.DOM.Dimensions */
143 ['Dimensions', 'MochiKit.Style.Dimensions', '1.4'] // FIXME: broken
144];
145
146/** @id MochiKit.DOM.getViewportDimensions */
147MochiKit.DOM.getViewportDimensions = new Function('' +
148 'if (!MochiKit["Style"]) {' +
149 ' throw new Error("This function has been deprecated and depends on MochiKit.Style.");' +
150 '}' +
151 'return MochiKit.Style.getViewportDimensions.apply(this, arguments);');
152
153MochiKit.Base.update(MochiKit.DOM, {
154
155 /** @id MochiKit.DOM.currentWindow */
156 currentWindow: function () {
157 return MochiKit.DOM._window;
158 },
159
160 /** @id MochiKit.DOM.currentDocument */
161 currentDocument: function () {
162 return MochiKit.DOM._document;
163 },
164
165 /** @id MochiKit.DOM.withWindow */
166 withWindow: function (win, func) {
167 var self = MochiKit.DOM;
168 var oldDoc = self._document;
169 var oldWin = self._window;
170 var rval;
171 try {
172 self._window = win;
173 self._document = win.document;
174 rval = func();
175 } catch (e) {
176 self._window = oldWin;
177 self._document = oldDoc;
178 throw e;
179 }
180 self._window = oldWin;
181 self._document = oldDoc;
182 return rval;
183 },
184
185 /** @id MochiKit.DOM.formContents */
186 formContents: function (elem/* = document.body */) {
187 var names = [];
188 var values = [];
189 var m = MochiKit.Base;
190 var self = MochiKit.DOM;
191 if (typeof(elem) == "undefined" || elem === null) {
192 elem = self._document.body;
193 } else {
194 elem = self.getElement(elem);
195 }
196 m.nodeWalk(elem, function (elem) {
197 var name = elem.name;
198 if (m.isNotEmpty(name)) {
199 var tagName = elem.tagName.toUpperCase();
200 if (tagName === "INPUT"
201 && (elem.type == "radio" || elem.type == "checkbox")
202 && !elem.checked
203 ) {
204 return null;
205 }
206 if (tagName === "SELECT") {
207 if (elem.type == "select-one") {
208 if (elem.selectedIndex >= 0) {
209 var opt = elem.options[elem.selectedIndex];
210 var v = opt.value;
211 if (!v) {
212 var h = opt.outerHTML;
213 // internet explorer sure does suck.
214 if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
215 v = opt.text;
216 }
217 }
218 names.push(name);
219 values.push(v);
220 return null;
221 }
222 // no form elements?
223 names.push(name);
224 values.push("");
225 return null;
226 } else {
227 var opts = elem.options;
228 if (!opts.length) {
229 names.push(name);
230 values.push("");
231 return null;
232 }
233 for (var i = 0; i < opts.length; i++) {
234 var opt = opts[i];
235 if (!opt.selected) {
236 continue;
237 }
238 var v = opt.value;
239 if (!v) {
240 var h = opt.outerHTML;
241 // internet explorer sure does suck.
242 if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
243 v = opt.text;
244 }
245 }
246 names.push(name);
247 values.push(v);
248 }
249 return null;
250 }
251 }
252 if (tagName === "FORM" || tagName === "P" || tagName === "SPAN"
253 || tagName === "DIV"
254 ) {
255 return elem.childNodes;
256 }
257 names.push(name);
258 values.push(elem.value || '');
259 return null;
260 }
261 return elem.childNodes;
262 });
263 return [names, values];
264 },
265
266 /** @id MochiKit.DOM.withDocument */
267 withDocument: function (doc, func) {
268 var self = MochiKit.DOM;
269 var oldDoc = self._document;
270 var rval;
271 try {
272 self._document = doc;
273 rval = func();
274 } catch (e) {
275 self._document = oldDoc;
276 throw e;
277 }
278 self._document = oldDoc;
279 return rval;
280 },
281
282 /** @id MochiKit.DOM.registerDOMConverter */
283 registerDOMConverter: function (name, check, wrap, /* optional */override) {
284 MochiKit.DOM.domConverters.register(name, check, wrap, override);
285 },
286
287 /** @id MochiKit.DOM.coerceToDOM */
288 coerceToDOM: function (node, ctx) {
289 var m = MochiKit.Base;
290 var im = MochiKit.Iter;
291 var self = MochiKit.DOM;
292 if (im) {
293 var iter = im.iter;
294 var repeat = im.repeat;
295 var map = m.map;
296 }
297 var domConverters = self.domConverters;
298 var coerceToDOM = arguments.callee;
299 var NotFound = m.NotFound;
300 while (true) {
301 if (typeof(node) == 'undefined' || node === null) {
302 return null;
303 }
304 if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) {
305 return node;
306 }
307 if (typeof(node) == 'number' || typeof(node) == 'boolean') {
308 node = node.toString();
309 // FALL THROUGH
310 }
311 if (typeof(node) == 'string') {
312 return self._document.createTextNode(node);
313 }
314 if (typeof(node.__dom__) == 'function') {
315 node = node.__dom__(ctx);
316 continue;
317 }
318 if (typeof(node.dom) == 'function') {
319 node = node.dom(ctx);
320 continue;
321 }
322 if (typeof(node) == 'function') {
323 node = node.apply(ctx, [ctx]);
324 continue;
325 }
326
327 if (im) {
328 // iterable
329 var iterNodes = null;
330 try {
331 iterNodes = iter(node);
332 } catch (e) {
333 // pass
334 }
335 if (iterNodes) {
336 return map(coerceToDOM, iterNodes, repeat(ctx));
337 }
338 }
339
340 // adapter
341 try {
342 node = domConverters.match(node, ctx);
343 continue;
344 } catch (e) {
345 if (e != NotFound) {
346 throw e;
347 }
348 }
349
350 // fallback
351 return self._document.createTextNode(node.toString());
352 }
353 // mozilla warnings aren't too bright
354 return undefined;
355 },
356
357 /** @id MochiKit.DOM.isChildNode */
358 isChildNode: function (node, maybeparent) {
359 var self = MochiKit.DOM;
360 if (typeof(node) == "string") {
361 node = self.getElement(node);
362 }
363 if (typeof(maybeparent) == "string") {
364 maybeparent = self.getElement(maybeparent);
365 }
366 if (node === maybeparent) {
367 return true;
368 }
369 while (node && node.tagName.toUpperCase() != "BODY") {
370 node = node.parentNode;
371 if (node === maybeparent) {
372 return true;
373 }
374 }
375 return false;
376 },
377
378 /** @id MochiKit.DOM.setNodeAttribute */
379 setNodeAttribute: function (node, attr, value) {
380 var o = {};
381 o[attr] = value;
382 try {
383 return MochiKit.DOM.updateNodeAttributes(node, o);
384 } catch (e) {
385 // pass
386 }
387 return null;
388 },
389
390 /** @id MochiKit.DOM.getNodeAttribute */
391 getNodeAttribute: function (node, attr) {
392 var self = MochiKit.DOM;
393 var rename = self.attributeArray.renames[attr];
394 node = self.getElement(node);
395 try {
396 if (rename) {
397 return node[rename];
398 }
399 return node.getAttribute(attr);
400 } catch (e) {
401 // pass
402 }
403 return null;
404 },
405
406 /** @id MochiKit.DOM.removeNodeAttribute */
407 removeNodeAttribute: function (node, attr) {
408 var self = MochiKit.DOM;
409 var rename = self.attributeArray.renames[attr];
410 node = self.getElement(node);
411 try {
412 if (rename) {
413 return node[rename];
414 }
415 return node.removeAttribute(attr);
416 } catch (e) {
417 // pass
418 }
419 return null;
420 },
421
422 /** @id MochiKit.DOM.updateNodeAttributes */
423 updateNodeAttributes: function (node, attrs) {
424 var elem = node;
425 var self = MochiKit.DOM;
426 if (typeof(node) == 'string') {
427 elem = self.getElement(node);
428 }
429 if (attrs) {
430 var updatetree = MochiKit.Base.updatetree;
431 if (self.attributeArray.compliant) {
432 // not IE, good.
433 for (var k in attrs) {
434 var v = attrs[k];
435 if (typeof(v) == 'object' && typeof(elem[k]) == 'object') {
436 if (k == "style" && MochiKit.Style) {
437 MochiKit.Style.setStyle(elem, v);
438 } else {
439 updatetree(elem[k], v);
440 }
441 } else if (k.substring(0, 2) == "on") {
442 if (typeof(v) == "string") {
443 v = new Function(v);
444 }
445 elem[k] = v;
446 } else {
447 elem.setAttribute(k, v);
448 }
449 }
450 } else {
451 // IE is insane in the membrane
452 var renames = self.attributeArray.renames;
453 for (k in attrs) {
454 v = attrs[k];
455 var renamed = renames[k];
456 if (k == "style" && typeof(v) == "string") {
457 elem.style.cssText = v;
458 } else if (typeof(renamed) == "string") {
459 elem[renamed] = v;
460 } else if (typeof(elem[k]) == 'object'
461 && typeof(v) == 'object') {
462 if (k == "style" && MochiKit.Style) {
463 MochiKit.Style.setStyle(elem, v);
464 } else {
465 updatetree(elem[k], v);
466 }
467 } else if (k.substring(0, 2) == "on") {
468 if (typeof(v) == "string") {
469 v = new Function(v);
470 }
471 elem[k] = v;
472 } else {
473 elem.setAttribute(k, v);
474 }
475 }
476 }
477 }
478 return elem;
479 },
480
481 /** @id MochiKit.DOM.appendChildNodes */
482 appendChildNodes: function (node/*, nodes...*/) {
483 var elem = node;
484 var self = MochiKit.DOM;
485 if (typeof(node) == 'string') {
486 elem = self.getElement(node);
487 }
488 var nodeStack = [
489 self.coerceToDOM(
490 MochiKit.Base.extend(null, arguments, 1),
491 elem
492 )
493 ];
494 var concat = MochiKit.Base.concat;
495 while (nodeStack.length) {
496 var n = nodeStack.shift();
497 if (typeof(n) == 'undefined' || n === null) {
498 // pass
499 } else if (typeof(n.nodeType) == 'number') {
500 elem.appendChild(n);
501 } else {
502 nodeStack = concat(n, nodeStack);
503 }
504 }
505 return elem;
506 },
507
508
509 /** @id MochiKit.DOM.insertSiblingNodesBefore */
510 insertSiblingNodesBefore: function (node/*, nodes...*/) {
511 var elem = node;
512 var self = MochiKit.DOM;
513 if (typeof(node) == 'string') {
514 elem = self.getElement(node);
515 }
516 var nodeStack = [
517 self.coerceToDOM(
518 MochiKit.Base.extend(null, arguments, 1),
519 elem
520 )
521 ];
522 var parentnode = elem.parentNode;
523 var concat = MochiKit.Base.concat;
524 while (nodeStack.length) {
525 var n = nodeStack.shift();
526 if (typeof(n) == 'undefined' || n === null) {
527 // pass
528 } else if (typeof(n.nodeType) == 'number') {
529 parentnode.insertBefore(n, elem);
530 } else {
531 nodeStack = concat(n, nodeStack);
532 }
533 }
534 return parentnode;
535 },
536
537 /** @id MochiKit.DOM.insertSiblingNodesAfter */
538 insertSiblingNodesAfter: function (node/*, nodes...*/) {
539 var elem = node;
540 var self = MochiKit.DOM;
541
542 if (typeof(node) == 'string') {
543 elem = self.getElement(node);
544 }
545 var nodeStack = [
546 self.coerceToDOM(
547 MochiKit.Base.extend(null, arguments, 1),
548 elem
549 )
550 ];
551
552 if (elem.nextSibling) {
553 return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack);
554 }
555 else {
556 return self.appendChildNodes(elem.parentNode, nodeStack);
557 }
558 },
559
560 /** @id MochiKit.DOM.replaceChildNodes */
561 replaceChildNodes: function (node/*, nodes...*/) {
562 var elem = node;
563 var self = MochiKit.DOM;
564 if (typeof(node) == 'string') {
565 elem = self.getElement(node);
566 arguments[0] = elem;
567 }
568 var child;
569 while ((child = elem.firstChild)) {
570 elem.removeChild(child);
571 }
572 if (arguments.length < 2) {
573 return elem;
574 } else {
575 return self.appendChildNodes.apply(this, arguments);
576 }
577 },
578
579 /** @id MochiKit.DOM.createDOM */
580 createDOM: function (name, attrs/*, nodes... */) {
581 var elem;
582 var self = MochiKit.DOM;
583 var m = MochiKit.Base;
584 if (typeof(attrs) == "string" || typeof(attrs) == "number") {
585 var args = m.extend([name, null], arguments, 1);
586 return arguments.callee.apply(this, args);
587 }
588 if (typeof(name) == 'string') {
589 // Internet Explorer is dumb
590 var xhtml = self._xhtml;
591 if (attrs && !self.attributeArray.compliant) {
592 // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp
593 var contents = "";
594 if ('name' in attrs) {
595 contents += ' name="' + self.escapeHTML(attrs.name) + '"';
596 }
597 if (name == 'input' && 'type' in attrs) {
598 contents += ' type="' + self.escapeHTML(attrs.type) + '"';
599 }
600 if (contents) {
601 name = "<" + name + contents + ">";
602 xhtml = false;
603 }
604 }
605 var d = self._document;
606 if (xhtml && d === document) {
607 elem = d.createElementNS("http://www.w3.org/1999/xhtml", name);
608 } else {
609 elem = d.createElement(name);
610 }
611 } else {
612 elem = name;
613 }
614 if (attrs) {
615 self.updateNodeAttributes(elem, attrs);
616 }
617 if (arguments.length <= 2) {
618 return elem;
619 } else {
620 var args = m.extend([elem], arguments, 2);
621 return self.appendChildNodes.apply(this, args);
622 }
623 },
624
625 /** @id MochiKit.DOM.createDOMFunc */
626 createDOMFunc: function (/* tag, attrs, *nodes */) {
627 var m = MochiKit.Base;
628 return m.partial.apply(
629 this,
630 m.extend([MochiKit.DOM.createDOM], arguments)
631 );
632 },
633
634 /** @id MochiKit.DOM.removeElement */
635 removeElement: function (elem) {
636 var e = MochiKit.DOM.getElement(elem);
637 e.parentNode.removeChild(e);
638 return e;
639 },
640
641 /** @id MochiKit.DOM.swapDOM */
642 swapDOM: function (dest, src) {
643 var self = MochiKit.DOM;
644 dest = self.getElement(dest);
645 var parent = dest.parentNode;
646 if (src) {
647 src = self.getElement(src);
648 parent.replaceChild(src, dest);
649 } else {
650 parent.removeChild(dest);
651 }
652 return src;
653 },
654
655 /** @id MochiKit.DOM.getElement */
656 getElement: function (id) {
657 var self = MochiKit.DOM;
658 if (arguments.length == 1) {
659 return ((typeof(id) == "string") ?
660 self._document.getElementById(id) : id);
661 } else {
662 return MochiKit.Base.map(self.getElement, arguments);
663 }
664 },
665
666 /** @id MochiKit.DOM.getElementsByTagAndClassName */
667 getElementsByTagAndClassName: function (tagName, className,
668 /* optional */parent) {
669 var self = MochiKit.DOM;
670 if (typeof(tagName) == 'undefined' || tagName === null) {
671 tagName = '*';
672 }
673 if (typeof(parent) == 'undefined' || parent === null) {
674 parent = self._document;
675 }
676 parent = self.getElement(parent);
677 var children = (parent.getElementsByTagName(tagName)
678 || self._document.all);
679 if (typeof(className) == 'undefined' || className === null) {
680 return MochiKit.Base.extend(null, children);
681 }
682
683 var elements = [];
684 for (var i = 0; i < children.length; i++) {
685 var child = children[i];
686 var cls = child.className;
687 if (!cls) {
688 continue;
689 }
690 var classNames = cls.split(' ');
691 for (var j = 0; j < classNames.length; j++) {
692 if (classNames[j] == className) {
693 elements.push(child);
694 break;
695 }
696 }
697 }
698
699 return elements;
700 },
701
702 _newCallStack: function (path, once) {
703 var rval = function () {
704 var callStack = arguments.callee.callStack;
705 for (var i = 0; i < callStack.length; i++) {
706 if (callStack[i].apply(this, arguments) === false) {
707 break;
708 }
709 }
710 if (once) {
711 try {
712 this[path] = null;
713 } catch (e) {
714 // pass
715 }
716 }
717 };
718 rval.callStack = [];
719 return rval;
720 },
721
722 /** @id MochiKit.DOM.addToCallStack */
723 addToCallStack: function (target, path, func, once) {
724 var self = MochiKit.DOM;
725 var existing = target[path];
726 var regfunc = existing;
727 if (!(typeof(existing) == 'function'
728 && typeof(existing.callStack) == "object"
729 && existing.callStack !== null)) {
730 regfunc = self._newCallStack(path, once);
731 if (typeof(existing) == 'function') {
732 regfunc.callStack.push(existing);
733 }
734 target[path] = regfunc;
735 }
736 regfunc.callStack.push(func);
737 },
738
739 /** @id MochiKit.DOM.addLoadEvent */
740 addLoadEvent: function (func) {
741 var self = MochiKit.DOM;
742 self.addToCallStack(self._window, "onload", func, true);
743
744 },
745
746 /** @id MochiKit.DOM.focusOnLoad */
747 focusOnLoad: function (element) {
748 var self = MochiKit.DOM;
749 self.addLoadEvent(function () {
750 element = self.getElement(element);
751 if (element) {
752 element.focus();
753 }
754 });
755 },
756
757 /** @id MochiKit.DOM.setElementClass */
758 setElementClass: function (element, className) {
759 var self = MochiKit.DOM;
760 var obj = self.getElement(element);
761 if (self.attributeArray.compliant) {
762 obj.setAttribute("class", className);
763 } else {
764 obj.setAttribute("className", className);
765 }
766 },
767
768 /** @id MochiKit.DOM.toggleElementClass */
769 toggleElementClass: function (className/*, element... */) {
770 var self = MochiKit.DOM;
771 for (var i = 1; i < arguments.length; i++) {
772 var obj = self.getElement(arguments[i]);
773 if (!self.addElementClass(obj, className)) {
774 self.removeElementClass(obj, className);
775 }
776 }
777 },
778
779 /** @id MochiKit.DOM.addElementClass */
780 addElementClass: function (element, className) {
781 var self = MochiKit.DOM;
782 var obj = self.getElement(element);
783 var cls = obj.className;
784 // trivial case, no className yet
785 if (cls == undefined || cls.length === 0) {
786 self.setElementClass(obj, className);
787 return true;
788 }
789 // the other trivial case, already set as the only class
790 if (cls == className) {
791 return false;
792 }
793 var classes = cls.split(" ");
794 for (var i = 0; i < classes.length; i++) {
795 // already present
796 if (classes[i] == className) {
797 return false;
798 }
799 }
800 // append class
801 self.setElementClass(obj, cls + " " + className);
802 return true;
803 },
804
805 /** @id MochiKit.DOM.removeElementClass */
806 removeElementClass: function (element, className) {
807 var self = MochiKit.DOM;
808 var obj = self.getElement(element);
809 var cls = obj.className;
810 // trivial case, no className yet
811 if (cls == undefined || cls.length === 0) {
812 return false;
813 }
814 // other trivial case, set only to className
815 if (cls == className) {
816 self.setElementClass(obj, "");
817 return true;
818 }
819 var classes = cls.split(" ");
820 for (var i = 0; i < classes.length; i++) {
821 // already present
822 if (classes[i] == className) {
823 // only check sane case where the class is used once
824 classes.splice(i, 1);
825 self.setElementClass(obj, classes.join(" "));
826 return true;
827 }
828 }
829 // not found
830 return false;
831 },
832
833 /** @id MochiKit.DOM.swapElementClass */
834 swapElementClass: function (element, fromClass, toClass) {
835 var obj = MochiKit.DOM.getElement(element);
836 var res = MochiKit.DOM.removeElementClass(obj, fromClass);
837 if (res) {
838 MochiKit.DOM.addElementClass(obj, toClass);
839 }
840 return res;
841 },
842
843 /** @id MochiKit.DOM.hasElementClass */
844 hasElementClass: function (element, className/*...*/) {
845 var obj = MochiKit.DOM.getElement(element);
846 var cls = obj.className;
847 if (!cls) {
848 return false;
849 }
850 var classes = cls.split(" ");
851 for (var i = 1; i < arguments.length; i++) {
852 var good = false;
853 for (var j = 0; j < classes.length; j++) {
854 if (classes[j] == arguments[i]) {
855 good = true;
856 break;
857 }
858 }
859 if (!good) {
860 return false;
861 }
862 }
863 return true;
864 },
865
866 /** @id MochiKit.DOM.escapeHTML */
867 escapeHTML: function (s) {
868 return s.replace(/&/g, "&amp;"
869 ).replace(/"/g, "&quot;"
870 ).replace(/</g, "&lt;"
871 ).replace(/>/g, "&gt;");
872 },
873
874 /** @id MochiKit.DOM.toHTML */
875 toHTML: function (dom) {
876 return MochiKit.DOM.emitHTML(dom).join("");
877 },
878
879 /** @id MochiKit.DOM.emitHTML */
880 emitHTML: function (dom, /* optional */lst) {
881 if (typeof(lst) == 'undefined' || lst === null) {
882 lst = [];
883 }
884 // queue is the call stack, we're doing this non-recursively
885 var queue = [dom];
886 var self = MochiKit.DOM;
887 var escapeHTML = self.escapeHTML;
888 var attributeArray = self.attributeArray;
889 while (queue.length) {
890 dom = queue.pop();
891 if (typeof(dom) == 'string') {
892 lst.push(dom);
893 } else if (dom.nodeType == 1) {
894 // we're not using higher order stuff here
895 // because safari has heisenbugs.. argh.
896 //
897 // I think it might have something to do with
898 // garbage collection and function calls.
899 lst.push('<' + dom.tagName.toLowerCase());
900 var attributes = [];
901 var domAttr = attributeArray(dom);
902 for (var i = 0; i < domAttr.length; i++) {
903 var a = domAttr[i];
904 attributes.push([
905 " ",
906 a.name,
907 '="',
908 escapeHTML(a.value),
909 '"'
910 ]);
911 }
912 attributes.sort();
913 for (i = 0; i < attributes.length; i++) {
914 var attrs = attributes[i];
915 for (var j = 0; j < attrs.length; j++) {
916 lst.push(attrs[j]);
917 }
918 }
919 if (dom.hasChildNodes()) {
920 lst.push(">");
921 // queue is the FILO call stack, so we put the close tag
922 // on first
923 queue.push("</" + dom.tagName.toLowerCase() + ">");
924 var cnodes = dom.childNodes;
925 for (i = cnodes.length - 1; i >= 0; i--) {
926 queue.push(cnodes[i]);
927 }
928 } else {
929 lst.push('/>');
930 }
931 } else if (dom.nodeType == 3) {
932 lst.push(escapeHTML(dom.nodeValue));
933 }
934 }
935 return lst;
936 },
937
938 /** @id MochiKit.DOM.scrapeText */
939 scrapeText: function (node, /* optional */asArray) {
940 var rval = [];
941 (function (node) {
942 var cn = node.childNodes;
943 if (cn) {
944 for (var i = 0; i < cn.length; i++) {
945 arguments.callee.call(this, cn[i]);
946 }
947 }
948 var nodeValue = node.nodeValue;
949 if (typeof(nodeValue) == 'string') {
950 rval.push(nodeValue);
951 }
952 })(MochiKit.DOM.getElement(node));
953 if (asArray) {
954 return rval;
955 } else {
956 return rval.join("");
957 }
958 },
959
960 /** @id MochiKit.DOM.removeEmptyTextNodes */
961 removeEmptyTextNodes: function (element) {
962 element = MochiKit.DOM.getElement(element);
963 for (var i = 0; i < element.childNodes.length; i++) {
964 var node = element.childNodes[i];
965 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
966 node.parentNode.removeChild(node);
967 }
968 }
969 },
970
971 /** @id MochiKit.DOM.makeClipping */
972 makeClipping: function (element) {
973 element = MochiKit.DOM.getElement(element);
974 var oldOverflow = element.style.overflow;
975 if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
976 element.style.overflow = 'hidden';
977 }
978 return oldOverflow;
979 },
980
981 /** @id MochiKit.DOM.undoClipping */
982 undoClipping: function (element, overflow) {
983 element = MochiKit.DOM.getElement(element);
984 if (!overflow) {
985 return;
986 }
987 element.style.overflow = overflow;
988 },
989
990 /** @id MochiKit.DOM.makePositioned */
991 makePositioned: function (element) {
992 element = MochiKit.DOM.getElement(element);
993 var pos = MochiKit.Style.getStyle(element, 'position');
994 if (pos == 'static' || !pos) {
995 element.style.position = 'relative';
996 // Opera returns the offset relative to the positioning context,
997 // when an element is position relative but top and left have
998 // not been defined
999 if (/Opera/.test(navigator.userAgent)) {
1000 element.style.top = 0;
1001 element.style.left = 0;
1002 }
1003 }
1004 },
1005
1006 /** @id MochiKit.DOM.undoPositioned */
1007 undoPositioned: function (element) {
1008 element = MochiKit.DOM.getElement(element);
1009 if (element.style.position == 'relative') {
1010 element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
1011 }
1012 },
1013
1014 /** @id MochiKit.DOM.getFirstElementByTagAndClassName */
1015 getFirstElementByTagAndClassName: function (tagName, className,
1016 /* optional */parent) {
1017 var self = MochiKit.DOM;
1018 if (typeof(tagName) == 'undefined' || tagName === null) {
1019 tagName = '*';
1020 }
1021 if (typeof(parent) == 'undefined' || parent === null) {
1022 parent = self._document;
1023 }
1024 parent = self.getElement(parent);
1025 var children = (parent.getElementsByTagName(tagName)
1026 || self._document.all);
1027 if (typeof(className) == 'undefined' || className === null) {
1028 return children[0];
1029 }
1030
1031 for (var i = 0; i < children.length; i++) {
1032 var child = children[i];
1033 var classNames = child.className.split(' ');
1034 for (var j = 0; j < classNames.length; j++) {
1035 if (classNames[j] == className) {
1036 return child;
1037 }
1038 }
1039 }
1040 },
1041
1042 /** @id MochiKit.DOM.getFirstParentByTagAndClassName */
1043 getFirstParentByTagAndClassName: function (elem, tagName, className) {
1044 var self = MochiKit.DOM;
1045 elem = self.getElement(elem);
1046 if (typeof(tagName) == 'undefined' || tagName === null) {
1047 tagName = '*';
1048 } else {
1049 tagName = tagName.toUpperCase();
1050 }
1051 if (typeof(className) == 'undefined' || className === null) {
1052 className = null;
1053 }
1054
1055 var classList = '';
1056 var curTagName = '';
1057 while (elem && elem.tagName) {
1058 elem = elem.parentNode;
1059 if (tagName == '*' && className === null) {
1060 return elem;
1061 }
1062 classList = elem.className.split(' ');
1063 curTagName = elem.tagName.toUpperCase();
1064 if (className === null && tagName == curTagName) {
1065 return elem;
1066 } else if (className !== null) {
1067 for (var i = 0; i < classList.length; i++) {
1068 if (tagName == '*' && classList[i] == className) {
1069 return elem;
1070 } else if (tagName == curTagName && classList[i] == className) {
1071 return elem;
1072 }
1073 }
1074 }
1075 }
1076 return elem;
1077 },
1078
1079 /** @id MochiKit.DOM.isParent */
1080 isParent: function (child, element) {
1081 if (!child.parentNode || child == element) {
1082 return false;
1083 }
1084
1085 if (child.parentNode == element) {
1086 return true;
1087 }
1088
1089 return MochiKit.DOM.isParent(child.parentNode, element);
1090 },
1091
1092 __new__: function (win) {
1093
1094 var m = MochiKit.Base;
1095 if (typeof(document) != "undefined") {
1096 this._document = document;
1097 var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
1098 this._xhtml = (document.documentElement &&
1099 document.createElementNS &&
1100 document.documentElement.namespaceURI === kXULNSURI);
1101 } else if (MochiKit.MockDOM) {
1102 this._document = MochiKit.MockDOM.document;
1103 }
1104 this._window = win;
1105
1106 this.domConverters = new m.AdapterRegistry();
1107
1108 var __tmpElement = this._document.createElement("span");
1109 var attributeArray;
1110 if (__tmpElement && __tmpElement.attributes &&
1111 __tmpElement.attributes.length > 0) {
1112 // for braindead browsers (IE) that insert extra junk
1113 var filter = m.filter;
1114 attributeArray = function (node) {
1115 return filter(attributeArray.ignoreAttrFilter, node.attributes);
1116 };
1117 attributeArray.ignoreAttr = {};
1118 var attrs = __tmpElement.attributes;
1119 var ignoreAttr = attributeArray.ignoreAttr;
1120 for (var i = 0; i < attrs.length; i++) {
1121 var a = attrs[i];
1122 ignoreAttr[a.name] = a.value;
1123 }
1124 attributeArray.ignoreAttrFilter = function (a) {
1125 return (attributeArray.ignoreAttr[a.name] != a.value);
1126 };
1127 attributeArray.compliant = false;
1128 attributeArray.renames = {
1129 "class": "className",
1130 "checked": "defaultChecked",
1131 "usemap": "useMap",
1132 "for": "htmlFor",
1133 "readonly": "readOnly",
1134 "colspan": "colSpan",
1135 "bgcolor": "bgColor"
1136 };
1137 } else {
1138 attributeArray = function (node) {
1139 /***
1140
1141 Return an array of attributes for a given node,
1142 filtering out attributes that don't belong for
1143 that are inserted by "Certain Browsers".
1144
1145 ***/
1146 return node.attributes;
1147 };
1148 attributeArray.compliant = true;
1149 attributeArray.renames = {};
1150 }
1151 this.attributeArray = attributeArray;
1152
1153 // FIXME: this really belongs in Base, and could probably be cleaner
1154 var _deprecated = function(fromModule, arr) {
1155 var modules = arr[1].split('.');
1156 var str = '';
1157 var obj = {};
1158
1159 str += 'if (!MochiKit.' + modules[1] + ') { throw new Error("';
1160 str += 'This function has been deprecated and depends on MochiKit.';
1161 str += modules[1] + '.");}';
1162 str += 'return MochiKit.' + modules[1] + '.' + arr[0];
1163 str += '.apply(this, arguments);';
1164
1165 obj[modules[2]] = new Function(str);
1166 MochiKit.Base.update(MochiKit[fromModule], obj);
1167 }
1168 for (var i; i < MochiKit.DOM.DEPRECATED.length; i++) {
1169 _deprecated('DOM', MochiKit.DOM.DEPRECATED[i]);
1170 }
1171
1172 // shorthand for createDOM syntax
1173 var createDOMFunc = this.createDOMFunc;
1174 /** @id MochiKit.DOM.UL */
1175 this.UL = createDOMFunc("ul");
1176 /** @id MochiKit.DOM.OL */
1177 this.OL = createDOMFunc("ol");
1178 /** @id MochiKit.DOM.LI */
1179 this.LI = createDOMFunc("li");
1180 /** @id MochiKit.DOM.TD */
1181 this.TD = createDOMFunc("td");
1182 /** @id MochiKit.DOM.TR */
1183 this.TR = createDOMFunc("tr");
1184 /** @id MochiKit.DOM.TBODY */
1185 this.TBODY = createDOMFunc("tbody");
1186 /** @id MochiKit.DOM.THEAD */
1187 this.THEAD = createDOMFunc("thead");
1188 /** @id MochiKit.DOM.TFOOT */
1189 this.TFOOT = createDOMFunc("tfoot");
1190 /** @id MochiKit.DOM.TABLE */
1191 this.TABLE = createDOMFunc("table");
1192 /** @id MochiKit.DOM.TH */
1193 this.TH = createDOMFunc("th");
1194 /** @id MochiKit.DOM.INPUT */
1195 this.INPUT = createDOMFunc("input");
1196 /** @id MochiKit.DOM.SPAN */
1197 this.SPAN = createDOMFunc("span");
1198 /** @id MochiKit.DOM.A */
1199 this.A = createDOMFunc("a");
1200 /** @id MochiKit.DOM.DIV */
1201 this.DIV = createDOMFunc("div");
1202 /** @id MochiKit.DOM.IMG */
1203 this.IMG = createDOMFunc("img");
1204 /** @id MochiKit.DOM.BUTTON */
1205 this.BUTTON = createDOMFunc("button");
1206 /** @id MochiKit.DOM.TT */
1207 this.TT = createDOMFunc("tt");
1208 /** @id MochiKit.DOM.PRE */
1209 this.PRE = createDOMFunc("pre");
1210 /** @id MochiKit.DOM.H1 */
1211 this.H1 = createDOMFunc("h1");
1212 /** @id MochiKit.DOM.H2 */
1213 this.H2 = createDOMFunc("h2");
1214 /** @id MochiKit.DOM.H3 */
1215 this.H3 = createDOMFunc("h3");
1216 /** @id MochiKit.DOM.BR */
1217 this.BR = createDOMFunc("br");
1218 /** @id MochiKit.DOM.HR */
1219 this.HR = createDOMFunc("hr");
1220 /** @id MochiKit.DOM.LABEL */
1221 this.LABEL = createDOMFunc("label");
1222 /** @id MochiKit.DOM.TEXTAREA */
1223 this.TEXTAREA = createDOMFunc("textarea");
1224 /** @id MochiKit.DOM.FORM */
1225 this.FORM = createDOMFunc("form");
1226 /** @id MochiKit.DOM.P */
1227 this.P = createDOMFunc("p");
1228 /** @id MochiKit.DOM.SELECT */
1229 this.SELECT = createDOMFunc("select");
1230 /** @id MochiKit.DOM.OPTION */
1231 this.OPTION = createDOMFunc("option");
1232 /** @id MochiKit.DOM.OPTGROUP */
1233 this.OPTGROUP = createDOMFunc("optgroup");
1234 /** @id MochiKit.DOM.LEGEND */
1235 this.LEGEND = createDOMFunc("legend");
1236 /** @id MochiKit.DOM.FIELDSET */
1237 this.FIELDSET = createDOMFunc("fieldset");
1238 /** @id MochiKit.DOM.STRONG */
1239 this.STRONG = createDOMFunc("strong");
1240 /** @id MochiKit.DOM.CANVAS */
1241 this.CANVAS = createDOMFunc("canvas");
1242
1243 /** @id MochiKit.DOM.$ */
1244 this.$ = this.getElement;
1245
1246 this.EXPORT_TAGS = {
1247 ":common": this.EXPORT,
1248 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
1249 };
1250
1251 m.nameFunctions(this);
1252
1253 }
1254});
1255
1256
1257MochiKit.DOM.__new__(((typeof(window) == "undefined") ? this : window));
1258
1259//
1260// XXX: Internet Explorer blows
1261//
1262if (MochiKit.__export__) {
1263 withWindow = MochiKit.DOM.withWindow;
1264 withDocument = MochiKit.DOM.withDocument;
1265}
1266
1267MochiKit.Base._exportSymbols(this, MochiKit.DOM);
diff --git a/frontend/beta/js/MochiKit/DateTime.js b/frontend/beta/js/MochiKit/DateTime.js
new file mode 100644
index 0000000..c0b03ee
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/DateTime.js
@@ -0,0 +1,216 @@
1/***
2
3MochiKit.DateTime 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.DateTime');
13}
14
15if (typeof(MochiKit) == 'undefined') {
16 MochiKit = {};
17}
18
19if (typeof(MochiKit.DateTime) == 'undefined') {
20 MochiKit.DateTime = {};
21}
22
23MochiKit.DateTime.NAME = "MochiKit.DateTime";
24MochiKit.DateTime.VERSION = "1.4";
25MochiKit.DateTime.__repr__ = function () {
26 return "[" + this.NAME + " " + this.VERSION + "]";
27};
28MochiKit.DateTime.toString = function () {
29 return this.__repr__();
30};
31
32/** @id MochiKit.DateTime.isoDate */
33MochiKit.DateTime.isoDate = function (str) {
34 str = str + "";
35 if (typeof(str) != "string" || str.length === 0) {
36 return null;
37 }
38 var iso = str.split('-');
39 if (iso.length === 0) {
40 return null;
41 }
42 return new Date(iso[0], iso[1] - 1, iso[2]);
43};
44
45MochiKit.DateTime._isoRegexp = /(\d{4,})(?:-(\d{1,2})(?:-(\d{1,2})(?:[T ](\d{1,2}):(\d{1,2})(?::(\d{1,2})(?:\.(\d+))?)?(?:(Z)|([+-])(\d{1,2})(?::(\d{1,2}))?)?)?)?)?/;
46
47/** @id MochiKit.DateTime.isoTimestamp */
48MochiKit.DateTime.isoTimestamp = function (str) {
49 str = str + "";
50 if (typeof(str) != "string" || str.length === 0) {
51 return null;
52 }
53 var res = str.match(MochiKit.DateTime._isoRegexp);
54 if (typeof(res) == "undefined" || res === null) {
55 return null;
56 }
57 var year, month, day, hour, min, sec, msec;
58 year = parseInt(res[1], 10);
59 if (typeof(res[2]) == "undefined" || res[2] === '') {
60 return new Date(year);
61 }
62 month = parseInt(res[2], 10) - 1;
63 day = parseInt(res[3], 10);
64 if (typeof(res[4]) == "undefined" || res[4] === '') {
65 return new Date(year, month, day);
66 }
67 hour = parseInt(res[4], 10);
68 min = parseInt(res[5], 10);
69 sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0;
70 if (typeof(res[7]) != "undefined" && res[7] !== '') {
71 msec = Math.round(1000.0 * parseFloat("0." + res[7]));
72 } else {
73 msec = 0;
74 }
75 if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) {
76 return new Date(year, month, day, hour, min, sec, msec);
77 }
78 var ofs;
79 if (typeof(res[9]) != "undefined" && res[9] !== '') {
80 ofs = parseInt(res[10], 10) * 3600000;
81 if (typeof(res[11]) != "undefined" && res[11] !== '') {
82 ofs += parseInt(res[11], 10) * 60000;
83 }
84 if (res[9] == "-") {
85 ofs = -ofs;
86 }
87 } else {
88 ofs = 0;
89 }
90 return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs);
91};
92
93/** @id MochiKit.DateTime.toISOTime */
94MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) {
95 if (typeof(date) == "undefined" || date === null) {
96 return null;
97 }
98 var hh = date.getHours();
99 var mm = date.getMinutes();
100 var ss = date.getSeconds();
101 var lst = [
102 ((realISO && (hh < 10)) ? "0" + hh : hh),
103 ((mm < 10) ? "0" + mm : mm),
104 ((ss < 10) ? "0" + ss : ss)
105 ];
106 return lst.join(":");
107};
108
109/** @id MochiKit.DateTime.toISOTimeStamp */
110MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) {
111 if (typeof(date) == "undefined" || date === null) {
112 return null;
113 }
114 var sep = realISO ? "T" : " ";
115 var foot = realISO ? "Z" : "";
116 if (realISO) {
117 date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
118 }
119 return MochiKit.DateTime.toISODate(date) + sep + MochiKit.DateTime.toISOTime(date, realISO) + foot;
120};
121
122/** @id MochiKit.DateTime.toISODate */
123MochiKit.DateTime.toISODate = function (date) {
124 if (typeof(date) == "undefined" || date === null) {
125 return null;
126 }
127 var _padTwo = MochiKit.DateTime._padTwo;
128 return [
129 date.getFullYear(),
130 _padTwo(date.getMonth() + 1),
131 _padTwo(date.getDate())
132 ].join("-");
133};
134
135/** @id MochiKit.DateTime.americanDate */
136MochiKit.DateTime.americanDate = function (d) {
137 d = d + "";
138 if (typeof(d) != "string" || d.length === 0) {
139 return null;
140 }
141 var a = d.split('/');
142 return new Date(a[2], a[0] - 1, a[1]);
143};
144
145MochiKit.DateTime._padTwo = function (n) {
146 return (n > 9) ? n : "0" + n;
147};
148
149/** @id MochiKit.DateTime.toPaddedAmericanDate */
150MochiKit.DateTime.toPaddedAmericanDate = function (d) {
151 if (typeof(d) == "undefined" || d === null) {
152 return null;
153 }
154 var _padTwo = MochiKit.DateTime._padTwo;
155 return [
156 _padTwo(d.getMonth() + 1),
157 _padTwo(d.getDate()),
158 d.getFullYear()
159 ].join('/');
160};
161
162/** @id MochiKit.DateTime.toAmericanDate */
163MochiKit.DateTime.toAmericanDate = function (d) {
164 if (typeof(d) == "undefined" || d === null) {
165 return null;
166 }
167 return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/');
168};
169
170MochiKit.DateTime.EXPORT = [
171 "isoDate",
172 "isoTimestamp",
173 "toISOTime",
174 "toISOTimestamp",
175 "toISODate",
176 "americanDate",
177 "toPaddedAmericanDate",
178 "toAmericanDate"
179];
180
181MochiKit.DateTime.EXPORT_OK = [];
182MochiKit.DateTime.EXPORT_TAGS = {
183 ":common": MochiKit.DateTime.EXPORT,
184 ":all": MochiKit.DateTime.EXPORT
185};
186
187MochiKit.DateTime.__new__ = function () {
188 // MochiKit.Base.nameFunctions(this);
189 var base = this.NAME + ".";
190 for (var k in this) {
191 var o = this[k];
192 if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
193 try {
194 o.NAME = base + k;
195 } catch (e) {
196 // pass
197 }
198 }
199 }
200};
201
202MochiKit.DateTime.__new__();
203
204if (typeof(MochiKit.Base) != "undefined") {
205 MochiKit.Base._exportSymbols(this, MochiKit.DateTime);
206} else {
207 (function (globals, module) {
208 if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
209 || (MochiKit.__export__ === false)) {
210 var all = module.EXPORT_TAGS[":all"];
211 for (var i = 0; i < all.length; i++) {
212 globals[all[i]] = module[all[i]];
213 }
214 }
215 })(this, MochiKit.DateTime);
216}
diff --git a/frontend/beta/js/MochiKit/DragAndDrop.js b/frontend/beta/js/MochiKit/DragAndDrop.js
new file mode 100644
index 0000000..c471ffe
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/DragAndDrop.js
@@ -0,0 +1,824 @@
1/***
2MochiKit.DragAndDrop 1.4
3
4See <http://mochikit.com/> for documentation, downloads, license, etc.
5
6Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
7 Mochi-ized By Thomas Herve (_firstname_@nimail.org)
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.DragAndDrop');
13 dojo.require('MochiKit.Base');
14 dojo.require('MochiKit.DOM');
15 dojo.require('MochiKit.Iter');
16 dojo.require('MochiKit.Visual');
17 dojo.require('MochiKit.Signal');
18}
19
20if (typeof(JSAN) != 'undefined') {
21 JSAN.use("MochiKit.Base", []);
22 JSAN.use("MochiKit.DOM", []);
23 JSAN.use("MochiKit.Visual", []);
24 JSAN.use("MochiKit.Iter", []);
25 JSAN.use("MochiKit.Signal", []);
26}
27
28try {
29 if (typeof(MochiKit.Base) == 'undefined' ||
30 typeof(MochiKit.DOM) == 'undefined' ||
31 typeof(MochiKit.Visual) == 'undefined' ||
32 typeof(MochiKit.Signal) == 'undefined' ||
33 typeof(MochiKit.Iter) == 'undefined') {
34 throw "";
35 }
36} catch (e) {
37 throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM, MochiKit.Visual, MochiKit.Signal and MochiKit.Iter!";
38}
39
40if (typeof(MochiKit.DragAndDrop) == 'undefined') {
41 MochiKit.DragAndDrop = {};
42}
43
44MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop';
45MochiKit.DragAndDrop.VERSION = '1.4';
46
47MochiKit.DragAndDrop.__repr__ = function () {
48 return '[' + this.NAME + ' ' + this.VERSION + ']';
49};
50
51MochiKit.DragAndDrop.toString = function () {
52 return this.__repr__();
53};
54
55MochiKit.DragAndDrop.EXPORT = [
56 "Droppable",
57 "Draggable"
58];
59
60MochiKit.DragAndDrop.EXPORT_OK = [
61 "Droppables",
62 "Draggables"
63];
64
65MochiKit.DragAndDrop.Droppables = {
66 /***
67
68 Manage all droppables. Shouldn't be used, use the Droppable object instead.
69
70 ***/
71 drops: [],
72
73 remove: function (element) {
74 this.drops = MochiKit.Base.filter(function (d) {
75 return d.element != MochiKit.DOM.getElement(element);
76 }, this.drops);
77 },
78
79 register: function (drop) {
80 this.drops.push(drop);
81 },
82
83 unregister: function (drop) {
84 this.drops = MochiKit.Base.filter(function (d) {
85 return d != drop;
86 }, this.drops);
87 },
88
89 prepare: function (element) {
90 MochiKit.Base.map(function (drop) {
91 if (drop.isAccepted(element)) {
92 if (drop.options.activeclass) {
93 MochiKit.DOM.addElementClass(drop.element,
94 drop.options.activeclass);
95 }
96 drop.options.onactive(drop.element, element);
97 }
98 }, this.drops);
99 },
100
101 findDeepestChild: function (drops) {
102 deepest = drops[0];
103
104 for (i = 1; i < drops.length; ++i) {
105 if (MochiKit.DOM.isParent(drops[i].element, deepest.element)) {
106 deepest = drops[i];
107 }
108 }
109 return deepest;
110 },
111
112 show: function (point, element) {
113 if (!this.drops.length) {
114 return;
115 }
116 var affected = [];
117
118 if (this.last_active) {
119 this.last_active.deactivate();
120 }
121 MochiKit.Iter.forEach(this.drops, function (drop) {
122 if (drop.isAffected(point, element)) {
123 affected.push(drop);
124 }
125 });
126 if (affected.length > 0) {
127 drop = this.findDeepestChild(affected);
128 MochiKit.Position.within(drop.element, point.page.x, point.page.y);
129 drop.options.onhover(element, drop.element,
130 MochiKit.Position.overlap(drop.options.overlap, drop.element));
131 drop.activate();
132 }
133 },
134
135 fire: function (event, element) {
136 if (!this.last_active) {
137 return;
138 }
139 MochiKit.Position.prepare();
140
141 if (this.last_active.isAffected(event.mouse(), element)) {
142 this.last_active.options.ondrop(element,
143 this.last_active.element, event);
144 }
145 },
146
147 reset: function (element) {
148 MochiKit.Base.map(function (drop) {
149 if (drop.options.activeclass) {
150 MochiKit.DOM.removeElementClass(drop.element,
151 drop.options.activeclass);
152 }
153 drop.options.ondesactive(drop.element, element);
154 }, this.drops);
155 if (this.last_active) {
156 this.last_active.deactivate();
157 }
158 }
159};
160
161/** @id MochiKit.DragAndDrop.Droppable */
162MochiKit.DragAndDrop.Droppable = function (element, options) {
163 var cls = arguments.callee;
164 if (!(this instanceof cls)) {
165 return new cls(element, options);
166 }
167 this.__init__(element, options);
168};
169
170MochiKit.DragAndDrop.Droppable.prototype = {
171 /***
172
173 A droppable object. Simple use is to create giving an element:
174
175 new MochiKit.DragAndDrop.Droppable('myelement');
176
177 Generally you'll want to define the 'ondrop' function and maybe the
178 'accept' option to filter draggables.
179
180 ***/
181 __class__: MochiKit.DragAndDrop.Droppable,
182
183 __init__: function (element, /* optional */options) {
184 var d = MochiKit.DOM;
185 var b = MochiKit.Base;
186 this.element = d.getElement(element);
187 this.options = b.update({
188
189 /** @id MochiKit.DragAndDrop.greedy */
190 greedy: true,
191
192 /** @id MochiKit.DragAndDrop.hoverclass */
193 hoverclass: null,
194
195 /** @id MochiKit.DragAndDrop.activeclass */
196 activeclass: null,
197
198 /** @id MochiKit.DragAndDrop.hoverfunc */
199 hoverfunc: b.noop,
200
201 /** @id MochiKit.DragAndDrop.accept */
202 accept: null,
203
204 /** @id MochiKit.DragAndDrop.onactive */
205 onactive: b.noop,
206
207 /** @id MochiKit.DragAndDrop.ondesactive */
208 ondesactive: b.noop,
209
210 /** @id MochiKit.DragAndDrop.onhover */
211 onhover: b.noop,
212
213 /** @id MochiKit.DragAndDrop.ondrop */
214 ondrop: b.noop,
215
216 /** @id MochiKit.DragAndDrop.containment */
217 containment: [],
218 tree: false
219 }, options || {});
220
221 // cache containers
222 this.options._containers = [];
223 b.map(MochiKit.Base.bind(function (c) {
224 this.options._containers.push(d.getElement(c));
225 }, this), this.options.containment);
226
227 d.makePositioned(this.element); // fix IE
228
229 MochiKit.DragAndDrop.Droppables.register(this);
230 },
231
232 /** @id MochiKit.DragAndDrop.isContained */
233 isContained: function (element) {
234 if (this.options._containers.length) {
235 var containmentNode;
236 if (this.options.tree) {
237 containmentNode = element.treeNode;
238 } else {
239 containmentNode = element.parentNode;
240 }
241 return MochiKit.Iter.some(this.options._containers, function (c) {
242 return containmentNode == c;
243 });
244 } else {
245 return true;
246 }
247 },
248
249 /** @id MochiKit.DragAndDrop.isAccepted */
250 isAccepted: function (element) {
251 return ((!this.options.accept) || MochiKit.Iter.some(
252 this.options.accept, function (c) {
253 return MochiKit.DOM.hasElementClass(element, c);
254 }));
255 },
256
257 /** @id MochiKit.DragAndDrop.isAffected */
258 isAffected: function (point, element) {
259 return ((this.element != element) &&
260 this.isContained(element) &&
261 this.isAccepted(element) &&
262 MochiKit.Position.within(this.element, point.page.x,
263 point.page.y));
264 },
265
266 /** @id MochiKit.DragAndDrop.deactivate */
267 deactivate: function () {
268 /***
269
270 A droppable is deactivate when a draggable has been over it and left.
271
272 ***/
273 if (this.options.hoverclass) {
274 MochiKit.DOM.removeElementClass(this.element,
275 this.options.hoverclass);
276 }
277 this.options.hoverfunc(this.element, false);
278 MochiKit.DragAndDrop.Droppables.last_active = null;
279 },
280
281 /** @id MochiKit.DragAndDrop.activate */
282 activate: function () {
283 /***
284
285 A droppable is active when a draggable is over it.
286
287 ***/
288 if (this.options.hoverclass) {
289 MochiKit.DOM.addElementClass(this.element, this.options.hoverclass);
290 }
291 this.options.hoverfunc(this.element, true);
292 MochiKit.DragAndDrop.Droppables.last_active = this;
293 },
294
295 /** @id MochiKit.DragAndDrop.destroy */
296 destroy: function () {
297 /***
298
299 Delete this droppable.
300
301 ***/
302 MochiKit.DragAndDrop.Droppables.unregister(this);
303 },
304
305 /** @id MochiKit.DragAndDrop.repr */
306 repr: function () {
307 return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
308 }
309};
310
311MochiKit.DragAndDrop.Draggables = {
312 /***
313
314 Manage draggables elements. Not intended to direct use.
315
316 ***/
317 drags: [],
318
319 register: function (draggable) {
320 if (this.drags.length === 0) {
321 var conn = MochiKit.Signal.connect;
322 this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
323 this.eventMouseMove = conn(document, 'onmousemove', this,
324 this.updateDrag);
325 this.eventKeypress = conn(document, 'onkeypress', this,
326 this.keyPress);
327 }
328 this.drags.push(draggable);
329 },
330
331 unregister: function (draggable) {
332 this.drags = MochiKit.Base.filter(function (d) {
333 return d != draggable;
334 }, this.drags);
335 if (this.drags.length === 0) {
336 var disc = MochiKit.Signal.disconnect;
337 disc(this.eventMouseUp);
338 disc(this.eventMouseMove);
339 disc(this.eventKeypress);
340 }
341 },
342
343 activate: function (draggable) {
344 // allows keypress events if window is not currently focused
345 // fails for Safari
346 window.focus();
347 this.activeDraggable = draggable;
348 },
349
350 deactivate: function () {
351 this.activeDraggable = null;
352 },
353
354 updateDrag: function (event) {
355 if (!this.activeDraggable) {
356 return;
357 }
358 var pointer = event.mouse();
359 // Mozilla-based browsers fire successive mousemove events with
360 // the same coordinates, prevent needless redrawing (moz bug?)
361 if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) ==
362 MochiKit.Base.repr(pointer.page))) {
363 return;
364 }
365 this._lastPointer = pointer;
366 this.activeDraggable.updateDrag(event, pointer);
367 },
368
369 endDrag: function (event) {
370 if (!this.activeDraggable) {
371 return;
372 }
373 this._lastPointer = null;
374 this.activeDraggable.endDrag(event);
375 this.activeDraggable = null;
376 },
377
378 keyPress: function (event) {
379 if (this.activeDraggable) {
380 this.activeDraggable.keyPress(event);
381 }
382 },
383
384 notify: function (eventName, draggable, event) {
385 MochiKit.Signal.signal(this, eventName, draggable, event);
386 }
387};
388
389/** @id MochiKit.DragAndDrop.Draggable */
390MochiKit.DragAndDrop.Draggable = function (element, options) {
391 var cls = arguments.callee;
392 if (!(this instanceof cls)) {
393 return new cls(element, options);
394 }
395 this.__init__(element, options);
396};
397
398MochiKit.DragAndDrop.Draggable.prototype = {
399 /***
400
401 A draggable object. Simple instantiate :
402
403 new MochiKit.DragAndDrop.Draggable('myelement');
404
405 ***/
406 __class__ : MochiKit.DragAndDrop.Draggable,
407
408 __init__: function (element, /* optional */options) {
409 var v = MochiKit.Visual;
410 var b = MochiKit.Base;
411 options = b.update({
412
413 /** @id MochiKit.DragAndDrop.handle */
414 handle: false,
415
416 /** @id MochiKit.DragAndDrop.starteffect */
417 starteffect: function (innerelement) {
418 this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0;
419 new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7});
420 },
421 /** @id MochiKit.DragAndDrop.reverteffect */
422 reverteffect: function (innerelement, top_offset, left_offset) {
423 var dur = Math.sqrt(Math.abs(top_offset^2) +
424 Math.abs(left_offset^2))*0.02;
425 return new v.Move(innerelement,
426 {x: -left_offset, y: -top_offset, duration: dur});
427 },
428
429 /** @id MochiKit.DragAndDrop.endeffect */
430 endeffect: function (innerelement) {
431 new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
432 },
433
434 /** @id MochiKit.DragAndDrop.onchange */
435 onchange: b.noop,
436
437 /** @id MochiKit.DragAndDrop.zindex */
438 zindex: 1000,
439
440 /** @id MochiKit.DragAndDrop.revert */
441 revert: false,
442
443 /** @id MochiKit.DragAndDrop.scroll */
444 scroll: false,
445
446 /** @id MochiKit.DragAndDrop.scrollSensitivity */
447 scrollSensitivity: 20,
448
449 /** @id MochiKit.DragAndDrop.scrollSpeed */
450 scrollSpeed: 15,
451 // false, or xy or [x, y] or function (x, y){return [x, y];}
452
453 /** @id MochiKit.DragAndDrop.snap */
454 snap: false
455 }, options || {});
456
457 var d = MochiKit.DOM;
458 this.element = d.getElement(element);
459
460 if (options.handle && (typeof(options.handle) == 'string')) {
461 this.handle = d.getFirstElementByTagAndClassName(null,
462 options.handle, this.element);
463 }
464 if (!this.handle) {
465 this.handle = d.getElement(options.handle);
466 }
467 if (!this.handle) {
468 this.handle = this.element;
469 }
470
471 if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
472 options.scroll = d.getElement(options.scroll);
473 this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll);
474 }
475
476 d.makePositioned(this.element); // fix IE
477
478 this.delta = this.currentDelta();
479 this.options = options;
480 this.dragging = false;
481
482 this.eventMouseDown = MochiKit.Signal.connect(this.handle,
483 'onmousedown', this, this.initDrag);
484 MochiKit.DragAndDrop.Draggables.register(this);
485 },
486
487 /** @id MochiKit.DragAndDrop.destroy */
488 destroy: function () {
489 MochiKit.Signal.disconnect(this.eventMouseDown);
490 MochiKit.DragAndDrop.Draggables.unregister(this);
491 },
492
493 /** @id MochiKit.DragAndDrop.currentDelta */
494 currentDelta: function () {
495 var s = MochiKit.Style.getStyle;
496 return [
497 parseInt(s(this.element, 'left') || '0'),
498 parseInt(s(this.element, 'top') || '0')];
499 },
500
501 /** @id MochiKit.DragAndDrop.initDrag */
502 initDrag: function (event) {
503 if (!event.mouse().button.left) {
504 return;
505 }
506 // abort on form elements, fixes a Firefox issue
507 var src = event.target();
508 var tagName = (src.tagName || '').toUpperCase();
509 if (tagName === 'INPUT' || tagName === 'SELECT' ||
510 tagName === 'OPTION' || tagName === 'BUTTON' ||
511 tagName === 'TEXTAREA') {
512 return;
513 }
514
515 if (this._revert) {
516 this._revert.cancel();
517 this._revert = null;
518 }
519
520 var pointer = event.mouse();
521 var pos = MochiKit.Position.cumulativeOffset(this.element);
522 this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y];
523
524 MochiKit.DragAndDrop.Draggables.activate(this);
525 event.stop();
526 },
527
528 /** @id MochiKit.DragAndDrop.startDrag */
529 startDrag: function (event) {
530 this.dragging = true;
531 if (this.options.selectclass) {
532 MochiKit.DOM.addElementClass(this.element,
533 this.options.selectclass);
534 }
535 if (this.options.zindex) {
536 this.originalZ = parseInt(MochiKit.Style.getStyle(this.element,
537 'z-index') || '0');
538 this.element.style.zIndex = this.options.zindex;
539 }
540
541 if (this.options.ghosting) {
542 this._clone = this.element.cloneNode(true);
543 this.ghostPosition = MochiKit.Position.absolutize(this.element);
544 this.element.parentNode.insertBefore(this._clone, this.element);
545 }
546
547 if (this.options.scroll) {
548 if (this.options.scroll == window) {
549 var where = this._getWindowScroll(this.options.scroll);
550 this.originalScrollLeft = where.left;
551 this.originalScrollTop = where.top;
552 } else {
553 this.originalScrollLeft = this.options.scroll.scrollLeft;
554 this.originalScrollTop = this.options.scroll.scrollTop;
555 }
556 }
557
558 MochiKit.DragAndDrop.Droppables.prepare(this.element);
559 MochiKit.DragAndDrop.Draggables.notify('start', this, event);
560 if (this.options.starteffect) {
561 this.options.starteffect(this.element);
562 }
563 },
564
565 /** @id MochiKit.DragAndDrop.updateDrag */
566 updateDrag: function (event, pointer) {
567 if (!this.dragging) {
568 this.startDrag(event);
569 }
570 MochiKit.Position.prepare();
571 MochiKit.DragAndDrop.Droppables.show(pointer, this.element);
572 MochiKit.DragAndDrop.Draggables.notify('drag', this, event);
573 this.draw(pointer);
574 this.options.onchange(this);
575
576 if (this.options.scroll) {
577 this.stopScrolling();
578 var p, q;
579 if (this.options.scroll == window) {
580 var s = this._getWindowScroll(this.options.scroll);
581 p = new MochiKit.Style.Coordinates(s.left, s.top);
582 q = new MochiKit.Style.Coordinates(s.left + s.width,
583 s.top + s.height);
584 } else {
585 p = MochiKit.Position.page(this.options.scroll);
586 p.x += this.options.scroll.scrollLeft;
587 p.y += this.options.scroll.scrollTop;
588 p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);
589 p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
590 q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth,
591 p.y + this.options.scroll.offsetHeight);
592 }
593 var speed = [0, 0];
594 if (pointer.page.x > (q.x - this.options.scrollSensitivity)) {
595 speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity);
596 } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) {
597 speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity);
598 }
599 if (pointer.page.y > (q.y - this.options.scrollSensitivity)) {
600 speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity);
601 } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) {
602 speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity);
603 }
604 this.startScrolling(speed);
605 }
606
607 // fix AppleWebKit rendering
608 if (/AppleWebKit'/.test(navigator.appVersion)) {
609 window.scrollBy(0, 0);
610 }
611 event.stop();
612 },
613
614 /** @id MochiKit.DragAndDrop.finishDrag */
615 finishDrag: function (event, success) {
616 var dr = MochiKit.DragAndDrop;
617 this.dragging = false;
618 if (this.options.selectclass) {
619 MochiKit.DOM.removeElementClass(this.element,
620 this.options.selectclass);
621 }
622
623 if (this.options.ghosting) {
624 // XXX: from a user point of view, it would be better to remove
625 // the node only *after* the MochiKit.Visual.Move end when used
626 // with revert.
627 MochiKit.Position.relativize(this.element, this.ghostPosition);
628 MochiKit.DOM.removeElement(this._clone);
629 this._clone = null;
630 }
631
632 if (success) {
633 dr.Droppables.fire(event, this.element);
634 }
635 dr.Draggables.notify('end', this, event);
636
637 var revert = this.options.revert;
638 if (revert && typeof(revert) == 'function') {
639 revert = revert(this.element);
640 }
641
642 var d = this.currentDelta();
643 if (revert && this.options.reverteffect) {
644 this._revert = this.options.reverteffect(this.element,
645 d[1] - this.delta[1], d[0] - this.delta[0]);
646 } else {
647 this.delta = d;
648 }
649
650 if (this.options.zindex) {
651 this.element.style.zIndex = this.originalZ;
652 }
653
654 if (this.options.endeffect) {
655 this.options.endeffect(this.element);
656 }
657
658 dr.Draggables.deactivate();
659 dr.Droppables.reset(this.element);
660 },
661
662 /** @id MochiKit.DragAndDrop.keyPress */
663 keyPress: function (event) {
664 if (event.key().string != "KEY_ESCAPE") {
665 return;
666 }
667 this.finishDrag(event, false);
668 event.stop();
669 },
670
671 /** @id MochiKit.DragAndDrop.endDrag */
672 endDrag: function (event) {
673 if (!this.dragging) {
674 return;
675 }
676 this.stopScrolling();
677 this.finishDrag(event, true);
678 event.stop();
679 },
680
681 /** @id MochiKit.DragAndDrop.draw */
682 draw: function (point) {
683 var pos = MochiKit.Position.cumulativeOffset(this.element);
684 var d = this.currentDelta();
685 pos.x -= d[0];
686 pos.y -= d[1];
687
688 if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
689 pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft;
690 pos.y -= this.options.scroll.scrollTop - this.originalScrollTop;
691 }
692
693 var p = [point.page.x - pos.x - this.offset[0],
694 point.page.y - pos.y - this.offset[1]];
695
696 if (this.options.snap) {
697 if (typeof(this.options.snap) == 'function') {
698 p = this.options.snap(p[0], p[1]);
699 } else {
700 if (this.options.snap instanceof Array) {
701 var i = -1;
702 p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
703 i += 1;
704 return Math.round(v/this.options.snap[i]) *
705 this.options.snap[i];
706 }, this), p);
707 } else {
708 p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
709 return Math.round(v/this.options.snap) *
710 this.options.snap;
711 }, this), p);
712 }
713 }
714 }
715 var style = this.element.style;
716 if ((!this.options.constraint) ||
717 (this.options.constraint == 'horizontal')) {
718 style.left = p[0] + 'px';
719 }
720 if ((!this.options.constraint) ||
721 (this.options.constraint == 'vertical')) {
722 style.top = p[1] + 'px';
723 }
724 if (style.visibility == 'hidden') {
725 style.visibility = ''; // fix gecko rendering
726 }
727 },
728
729 /** @id MochiKit.DragAndDrop.stopScrolling */
730 stopScrolling: function () {
731 if (this.scrollInterval) {
732 clearInterval(this.scrollInterval);
733 this.scrollInterval = null;
734 MochiKit.DragAndDrop.Draggables._lastScrollPointer = null;
735 }
736 },
737
738 /** @id MochiKit.DragAndDrop.startScrolling */
739 startScrolling: function (speed) {
740 if (!speed[0] && !speed[1]) {
741 return;
742 }
743 this.scrollSpeed = [speed[0] * this.options.scrollSpeed,
744 speed[1] * this.options.scrollSpeed];
745 this.lastScrolled = new Date();
746 this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10);
747 },
748
749 /** @id MochiKit.DragAndDrop.scroll */
750 scroll: function () {
751 var current = new Date();
752 var delta = current - this.lastScrolled;
753 this.lastScrolled = current;
754
755 if (this.options.scroll == window) {
756 var s = this._getWindowScroll(this.options.scroll);
757 if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
758 var dm = delta / 1000;
759 this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0],
760 s.top + dm * this.scrollSpeed[1]);
761 }
762 } else {
763 this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
764 this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
765 }
766
767 var d = MochiKit.DragAndDrop;
768
769 MochiKit.Position.prepare();
770 d.Droppables.show(d.Draggables._lastPointer, this.element);
771 d.Draggables.notify('drag', this);
772 if (this._isScrollChild) {
773 d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer;
774 d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000;
775 d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000;
776 if (d.Draggables._lastScrollPointer.x < 0) {
777 d.Draggables._lastScrollPointer.x = 0;
778 }
779 if (d.Draggables._lastScrollPointer.y < 0) {
780 d.Draggables._lastScrollPointer.y = 0;
781 }
782 this.draw(d.Draggables._lastScrollPointer);
783 }
784
785 this.options.onchange(this);
786 },
787
788 _getWindowScroll: function (win) {
789 var vp, w, h;
790 MochiKit.DOM.withWindow(win, function () {
791 vp = MochiKit.Style.getViewportPosition(win.document);
792 });
793 if (win.innerWidth) {
794 w = win.innerWidth;
795 h = win.innerHeight;
796 } else if (win.document.documentElement && win.document.documentElement.clientWidth) {
797 w = win.document.documentElement.clientWidth;
798 h = win.document.documentElement.clientHeight;
799 } else {
800 w = win.document.body.offsetWidth;
801 h = win.document.body.offsetHeight;
802 }
803 return {top: vp.x, left: vp.y, width: w, height: h};
804 },
805
806 /** @id MochiKit.DragAndDrop.repr */
807 repr: function () {
808 return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
809 }
810};
811
812MochiKit.DragAndDrop.__new__ = function () {
813 MochiKit.Base.nameFunctions(this);
814
815 this.EXPORT_TAGS = {
816 ":common": this.EXPORT,
817 ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
818 };
819};
820
821MochiKit.DragAndDrop.__new__();
822
823MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);
824
diff --git a/frontend/beta/js/MochiKit/Format.js b/frontend/beta/js/MochiKit/Format.js
new file mode 100644
index 0000000..937b681
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Format.js
@@ -0,0 +1,304 @@
1/***
2
3MochiKit.Format 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Format');
13}
14
15if (typeof(MochiKit) == 'undefined') {
16 MochiKit = {};
17}
18
19if (typeof(MochiKit.Format) == 'undefined') {
20 MochiKit.Format = {};
21}
22
23MochiKit.Format.NAME = "MochiKit.Format";
24MochiKit.Format.VERSION = "1.4";
25MochiKit.Format.__repr__ = function () {
26 return "[" + this.NAME + " " + this.VERSION + "]";
27};
28MochiKit.Format.toString = function () {
29 return this.__repr__();
30};
31
32MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) {
33 return function (num) {
34 num = parseFloat(num);
35 if (typeof(num) == "undefined" || num === null || isNaN(num)) {
36 return placeholder;
37 }
38 var curheader = header;
39 var curfooter = footer;
40 if (num < 0) {
41 num = -num;
42 } else {
43 curheader = curheader.replace(/-/, "");
44 }
45 var me = arguments.callee;
46 var fmt = MochiKit.Format.formatLocale(locale);
47 if (isPercent) {
48 num = num * 100.0;
49 curfooter = fmt.percent + curfooter;
50 }
51 num = MochiKit.Format.roundToFixed(num, precision);
52 var parts = num.split(/\./);
53 var whole = parts[0];
54 var frac = (parts.length == 1) ? "" : parts[1];
55 var res = "";
56 while (whole.length < leadingZeros) {
57 whole = "0" + whole;
58 }
59 if (separatorAt) {
60 while (whole.length > separatorAt) {
61 var i = whole.length - separatorAt;
62 //res = res + fmt.separator + whole.substring(i, whole.length);
63 res = fmt.separator + whole.substring(i, whole.length) + res;
64 whole = whole.substring(0, i);
65 }
66 }
67 res = whole + res;
68 if (precision > 0) {
69 while (frac.length < trailingZeros) {
70 frac = frac + "0";
71 }
72 res = res + fmt.decimal + frac;
73 }
74 return curheader + res + curfooter;
75 };
76};
77
78/** @id MochiKit.Format.numberFormatter */
79MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) {
80 // http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
81 // | 0 | leading or trailing zeros
82 // | # | just the number
83 // | , | separator
84 // | . | decimal separator
85 // | % | Multiply by 100 and format as percent
86 if (typeof(placeholder) == "undefined") {
87 placeholder = "";
88 }
89 var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
90 if (!match) {
91 throw TypeError("Invalid pattern");
92 }
93 var header = pattern.substr(0, match.index);
94 var footer = pattern.substr(match.index + match[0].length);
95 if (header.search(/-/) == -1) {
96 header = header + "-";
97 }
98 var whole = match[1];
99 var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : "";
100 var isPercent = (typeof(match[3]) == "string" && match[3] != "");
101 var tmp = whole.split(/,/);
102 var separatorAt;
103 if (typeof(locale) == "undefined") {
104 locale = "default";
105 }
106 if (tmp.length == 1) {
107 separatorAt = null;
108 } else {
109 separatorAt = tmp[1].length;
110 }
111 var leadingZeros = whole.length - whole.replace(/0/g, "").length;
112 var trailingZeros = frac.length - frac.replace(/0/g, "").length;
113 var precision = frac.length;
114 var rval = MochiKit.Format._numberFormatter(
115 placeholder, header, footer, locale, isPercent, precision,
116 leadingZeros, separatorAt, trailingZeros
117 );
118 var m = MochiKit.Base;
119 if (m) {
120 var fn = arguments.callee;
121 var args = m.concat(arguments);
122 rval.repr = function () {
123 return [
124 self.NAME,
125 "(",
126 map(m.repr, args).join(", "),
127 ")"
128 ].join("");
129 };
130 }
131 return rval;
132};
133
134/** @id MochiKit.Format.formatLocale */
135MochiKit.Format.formatLocale = function (locale) {
136 if (typeof(locale) == "undefined" || locale === null) {
137 locale = "default";
138 }
139 if (typeof(locale) == "string") {
140 var rval = MochiKit.Format.LOCALE[locale];
141 if (typeof(rval) == "string") {
142 rval = arguments.callee(rval);
143 MochiKit.Format.LOCALE[locale] = rval;
144 }
145 return rval;
146 } else {
147 return locale;
148 }
149};
150
151/** @id MochiKit.Format.twoDigitAverage */
152MochiKit.Format.twoDigitAverage = function (numerator, denominator) {
153 if (denominator) {
154 var res = numerator / denominator;
155 if (!isNaN(res)) {
156 return MochiKit.Format.twoDigitFloat(numerator / denominator);
157 }
158 }
159 return "0";
160};
161
162/** @id MochiKit.Format.twoDigitFloat */
163MochiKit.Format.twoDigitFloat = function (someFloat) {
164 var sign = (someFloat < 0 ? '-' : '');
165 var s = Math.floor(Math.abs(someFloat) * 100).toString();
166 if (s == '0') {
167 return s;
168 }
169 if (s.length < 3) {
170 while (s.charAt(s.length - 1) == '0') {
171 s = s.substring(0, s.length - 1);
172 }
173 return sign + '0.' + s;
174 }
175 var head = sign + s.substring(0, s.length - 2);
176 var tail = s.substring(s.length - 2, s.length);
177 if (tail == '00') {
178 return head;
179 } else if (tail.charAt(1) == '0') {
180 return head + '.' + tail.charAt(0);
181 } else {
182 return head + '.' + tail;
183 }
184};
185
186/** @id MochiKit.Format.lstrip */
187MochiKit.Format.lstrip = function (str, /* optional */chars) {
188 str = str + "";
189 if (typeof(str) != "string") {
190 return null;
191 }
192 if (!chars) {
193 return str.replace(/^\s+/, "");
194 } else {
195 return str.replace(new RegExp("^[" + chars + "]+"), "");
196 }
197};
198
199/** @id MochiKit.Format.rstrip */
200MochiKit.Format.rstrip = function (str, /* optional */chars) {
201 str = str + "";
202 if (typeof(str) != "string") {
203 return null;
204 }
205 if (!chars) {
206 return str.replace(/\s+$/, "");
207 } else {
208 return str.replace(new RegExp("[" + chars + "]+$"), "");
209 }
210};
211
212/** @id MochiKit.Format.strip */
213MochiKit.Format.strip = function (str, /* optional */chars) {
214 var self = MochiKit.Format;
215 return self.rstrip(self.lstrip(str, chars), chars);
216};
217
218/** @id MochiKit.Format.truncToFixed */
219MochiKit.Format.truncToFixed = function (aNumber, precision) {
220 aNumber = Math.floor(aNumber * Math.pow(10, precision));
221 var res = (aNumber * Math.pow(10, -precision)).toFixed(precision);
222 if (res.charAt(0) == ".") {
223 res = "0" + res;
224 }
225 return res;
226};
227
228/** @id MochiKit.Format.roundToFixed */
229MochiKit.Format.roundToFixed = function (aNumber, precision) {
230 return MochiKit.Format.truncToFixed(
231 aNumber + 0.5 * Math.pow(10, -precision),
232 precision
233 );
234};
235
236/** @id MochiKit.Format.percentFormat */
237MochiKit.Format.percentFormat = function (someFloat) {
238 return MochiKit.Format.twoDigitFloat(100 * someFloat) + '%';
239};
240
241MochiKit.Format.EXPORT = [
242 "truncToFixed",
243 "roundToFixed",
244 "numberFormatter",
245 "formatLocale",
246 "twoDigitAverage",
247 "twoDigitFloat",
248 "percentFormat",
249 "lstrip",
250 "rstrip",
251 "strip"
252];
253
254MochiKit.Format.LOCALE = {
255 en_US: {separator: ",", decimal: ".", percent: "%"},
256 de_DE: {separator: ".", decimal: ",", percent: "%"},
257 fr_FR: {separator: " ", decimal: ",", percent: "%"},
258 "default": "en_US"
259};
260
261MochiKit.Format.EXPORT_OK = [];
262MochiKit.Format.EXPORT_TAGS = {
263 ':all': MochiKit.Format.EXPORT,
264 ':common': MochiKit.Format.EXPORT
265};
266
267MochiKit.Format.__new__ = function () {
268 // MochiKit.Base.nameFunctions(this);
269 var base = this.NAME + ".";
270 var k, v, o;
271 for (k in this.LOCALE) {
272 o = this.LOCALE[k];
273 if (typeof(o) == "object") {
274 o.repr = function () { return this.NAME; };
275 o.NAME = base + "LOCALE." + k;
276 }
277 }
278 for (k in this) {
279 o = this[k];
280 if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
281 try {
282 o.NAME = base + k;
283 } catch (e) {
284 // pass
285 }
286 }
287 }
288};
289
290MochiKit.Format.__new__();
291
292if (typeof(MochiKit.Base) != "undefined") {
293 MochiKit.Base._exportSymbols(this, MochiKit.Format);
294} else {
295 (function (globals, module) {
296 if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
297 || (MochiKit.__export__ === false)) {
298 var all = module.EXPORT_TAGS[":all"];
299 for (var i = 0; i < all.length; i++) {
300 globals[all[i]] = module[all[i]];
301 }
302 }
303 })(this, MochiKit.Format);
304}
diff --git a/frontend/beta/js/MochiKit/Iter.js b/frontend/beta/js/MochiKit/Iter.js
new file mode 100644
index 0000000..1d008e2
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Iter.js
@@ -0,0 +1,843 @@
1/***
2
3MochiKit.Iter 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Iter');
13 dojo.require('MochiKit.Base');
14}
15
16if (typeof(JSAN) != 'undefined') {
17 JSAN.use("MochiKit.Base", []);
18}
19
20try {
21 if (typeof(MochiKit.Base) == 'undefined') {
22 throw "";
23 }
24} catch (e) {
25 throw "MochiKit.Iter depends on MochiKit.Base!";
26}
27
28if (typeof(MochiKit.Iter) == 'undefined') {
29 MochiKit.Iter = {};
30}
31
32MochiKit.Iter.NAME = "MochiKit.Iter";
33MochiKit.Iter.VERSION = "1.4";
34MochiKit.Base.update(MochiKit.Iter, {
35 __repr__: function () {
36 return "[" + this.NAME + " " + this.VERSION + "]";
37 },
38 toString: function () {
39 return this.__repr__();
40 },
41
42 /** @id MochiKit.Iter.registerIteratorFactory */
43 registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
44 MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
45 },
46
47 /** @id MochiKit.Iter.iter */
48 iter: function (iterable, /* optional */ sentinel) {
49 var self = MochiKit.Iter;
50 if (arguments.length == 2) {
51 return self.takewhile(
52 function (a) { return a != sentinel; },
53 iterable
54 );
55 }
56 if (typeof(iterable.next) == 'function') {
57 return iterable;
58 } else if (typeof(iterable.iter) == 'function') {
59 return iterable.iter();
60 /*
61 } else if (typeof(iterable.__iterator__) == 'function') {
62 //
63 // XXX: We can't support JavaScript 1.7 __iterator__ directly
64 // because of Object.prototype.__iterator__
65 //
66 return iterable.__iterator__();
67 */
68 }
69
70 try {
71 return self.iteratorRegistry.match(iterable);
72 } catch (e) {
73 var m = MochiKit.Base;
74 if (e == m.NotFound) {
75 e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
76 }
77 throw e;
78 }
79 },
80
81 /** @id MochiKit.Iter.count */
82 count: function (n) {
83 if (!n) {
84 n = 0;
85 }
86 var m = MochiKit.Base;
87 return {
88 repr: function () { return "count(" + n + ")"; },
89 toString: m.forwardCall("repr"),
90 next: m.counter(n)
91 };
92 },
93
94 /** @id MochiKit.Iter.cycle */
95 cycle: function (p) {
96 var self = MochiKit.Iter;
97 var m = MochiKit.Base;
98 var lst = [];
99 var iterator = self.iter(p);
100 return {
101 repr: function () { return "cycle(...)"; },
102 toString: m.forwardCall("repr"),
103 next: function () {
104 try {
105 var rval = iterator.next();
106 lst.push(rval);
107 return rval;
108 } catch (e) {
109 if (e != self.StopIteration) {
110 throw e;
111 }
112 if (lst.length === 0) {
113 this.next = function () {
114 throw self.StopIteration;
115 };
116 } else {
117 var i = -1;
118 this.next = function () {
119 i = (i + 1) % lst.length;
120 return lst[i];
121 };
122 }
123 return this.next();
124 }
125 }
126 };
127 },
128
129 /** @id MochiKit.Iter.repeat */
130 repeat: function (elem, /* optional */n) {
131 var m = MochiKit.Base;
132 if (typeof(n) == 'undefined') {
133 return {
134 repr: function () {
135 return "repeat(" + m.repr(elem) + ")";
136 },
137 toString: m.forwardCall("repr"),
138 next: function () {
139 return elem;
140 }
141 };
142 }
143 return {
144 repr: function () {
145 return "repeat(" + m.repr(elem) + ", " + n + ")";
146 },
147 toString: m.forwardCall("repr"),
148 next: function () {
149 if (n <= 0) {
150 throw MochiKit.Iter.StopIteration;
151 }
152 n -= 1;
153 return elem;
154 }
155 };
156 },
157
158 /** @id MochiKit.Iter.next */
159 next: function (iterator) {
160 return iterator.next();
161 },
162
163 /** @id MochiKit.Iter.izip */
164 izip: function (p, q/*, ...*/) {
165 var m = MochiKit.Base;
166 var self = MochiKit.Iter;
167 var next = self.next;
168 var iterables = m.map(self.iter, arguments);
169 return {
170 repr: function () { return "izip(...)"; },
171 toString: m.forwardCall("repr"),
172 next: function () { return m.map(next, iterables); }
173 };
174 },
175
176 /** @id MochiKit.Iter.ifilter */
177 ifilter: function (pred, seq) {
178 var m = MochiKit.Base;
179 seq = MochiKit.Iter.iter(seq);
180 if (pred === null) {
181 pred = m.operator.truth;
182 }
183 return {
184 repr: function () { return "ifilter(...)"; },
185 toString: m.forwardCall("repr"),
186 next: function () {
187 while (true) {
188 var rval = seq.next();
189 if (pred(rval)) {
190 return rval;
191 }
192 }
193 // mozilla warnings aren't too bright
194 return undefined;
195 }
196 };
197 },
198
199 /** @id MochiKit.Iter.ifilterfalse */
200 ifilterfalse: function (pred, seq) {
201 var m = MochiKit.Base;
202 seq = MochiKit.Iter.iter(seq);
203 if (pred === null) {
204 pred = m.operator.truth;
205 }
206 return {
207 repr: function () { return "ifilterfalse(...)"; },
208 toString: m.forwardCall("repr"),
209 next: function () {
210 while (true) {
211 var rval = seq.next();
212 if (!pred(rval)) {
213 return rval;
214 }
215 }
216 // mozilla warnings aren't too bright
217 return undefined;
218 }
219 };
220 },
221
222 /** @id MochiKit.Iter.islice */
223 islice: function (seq/*, [start,] stop[, step] */) {
224 var self = MochiKit.Iter;
225 var m = MochiKit.Base;
226 seq = self.iter(seq);
227 var start = 0;
228 var stop = 0;
229 var step = 1;
230 var i = -1;
231 if (arguments.length == 2) {
232 stop = arguments[1];
233 } else if (arguments.length == 3) {
234 start = arguments[1];
235 stop = arguments[2];
236 } else {
237 start = arguments[1];
238 stop = arguments[2];
239 step = arguments[3];
240 }
241 return {
242 repr: function () {
243 return "islice(" + ["...", start, stop, step].join(", ") + ")";
244 },
245 toString: m.forwardCall("repr"),
246 next: function () {
247 var rval;
248 while (i < start) {
249 rval = seq.next();
250 i++;
251 }
252 if (start >= stop) {
253 throw self.StopIteration;
254 }
255 start += step;
256 return rval;
257 }
258 };
259 },
260
261 /** @id MochiKit.Iter.imap */
262 imap: function (fun, p, q/*, ...*/) {
263 var m = MochiKit.Base;
264 var self = MochiKit.Iter;
265 var iterables = m.map(self.iter, m.extend(null, arguments, 1));
266 var map = m.map;
267 var next = self.next;
268 return {
269 repr: function () { return "imap(...)"; },
270 toString: m.forwardCall("repr"),
271 next: function () {
272 return fun.apply(this, map(next, iterables));
273 }
274 };
275 },
276
277 /** @id MochiKit.Iter.applymap */
278 applymap: function (fun, seq, self) {
279 seq = MochiKit.Iter.iter(seq);
280 var m = MochiKit.Base;
281 return {
282 repr: function () { return "applymap(...)"; },
283 toString: m.forwardCall("repr"),
284 next: function () {
285 return fun.apply(self, seq.next());
286 }
287 };
288 },
289
290 /** @id MochiKit.Iter.chain */
291 chain: function (p, q/*, ...*/) {
292 // dumb fast path
293 var self = MochiKit.Iter;
294 var m = MochiKit.Base;
295 if (arguments.length == 1) {
296 return self.iter(arguments[0]);
297 }
298 var argiter = m.map(self.iter, arguments);
299 return {
300 repr: function () { return "chain(...)"; },
301 toString: m.forwardCall("repr"),
302 next: function () {
303 while (argiter.length > 1) {
304 try {
305 return argiter[0].next();
306 } catch (e) {
307 if (e != self.StopIteration) {
308 throw e;
309 }
310 argiter.shift();
311 }
312 }
313 if (argiter.length == 1) {
314 // optimize last element
315 var arg = argiter.shift();
316 this.next = m.bind("next", arg);
317 return this.next();
318 }
319 throw self.StopIteration;
320 }
321 };
322 },
323
324 /** @id MochiKit.Iter.takewhile */
325 takewhile: function (pred, seq) {
326 var self = MochiKit.Iter;
327 seq = self.iter(seq);
328 return {
329 repr: function () { return "takewhile(...)"; },
330 toString: MochiKit.Base.forwardCall("repr"),
331 next: function () {
332 var rval = seq.next();
333 if (!pred(rval)) {
334 this.next = function () {
335 throw self.StopIteration;
336 };
337 this.next();
338 }
339 return rval;
340 }
341 };
342 },
343
344 /** @id MochiKit.Iter.dropwhile */
345 dropwhile: function (pred, seq) {
346 seq = MochiKit.Iter.iter(seq);
347 var m = MochiKit.Base;
348 var bind = m.bind;
349 return {
350 "repr": function () { return "dropwhile(...)"; },
351 "toString": m.forwardCall("repr"),
352 "next": function () {
353 while (true) {
354 var rval = seq.next();
355 if (!pred(rval)) {
356 break;
357 }
358 }
359 this.next = bind("next", seq);
360 return rval;
361 }
362 };
363 },
364
365 _tee: function (ident, sync, iterable) {
366 sync.pos[ident] = -1;
367 var m = MochiKit.Base;
368 var listMin = m.listMin;
369 return {
370 repr: function () { return "tee(" + ident + ", ...)"; },
371 toString: m.forwardCall("repr"),
372 next: function () {
373 var rval;
374 var i = sync.pos[ident];
375
376 if (i == sync.max) {
377 rval = iterable.next();
378 sync.deque.push(rval);
379 sync.max += 1;
380 sync.pos[ident] += 1;
381 } else {
382 rval = sync.deque[i - sync.min];
383 sync.pos[ident] += 1;
384 if (i == sync.min && listMin(sync.pos) != sync.min) {
385 sync.min += 1;
386 sync.deque.shift();
387 }
388 }
389 return rval;
390 }
391 };
392 },
393
394 /** @id MochiKit.Iter.tee */
395 tee: function (iterable, n/* = 2 */) {
396 var rval = [];
397 var sync = {
398 "pos": [],
399 "deque": [],
400 "max": -1,
401 "min": -1
402 };
403 if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
404 n = 2;
405 }
406 var self = MochiKit.Iter;
407 iterable = self.iter(iterable);
408 var _tee = self._tee;
409 for (var i = 0; i < n; i++) {
410 rval.push(_tee(i, sync, iterable));
411 }
412 return rval;
413 },
414
415 /** @id MochiKit.Iter.list */
416 list: function (iterable) {
417 // Fast-path for Array and Array-like
418 var m = MochiKit.Base;
419 if (typeof(iterable.slice) == 'function') {
420 return iterable.slice();
421 } else if (m.isArrayLike(iterable)) {
422 return m.concat(iterable);
423 }
424
425 var self = MochiKit.Iter;
426 iterable = self.iter(iterable);
427 var rval = [];
428 try {
429 while (true) {
430 rval.push(iterable.next());
431 }
432 } catch (e) {
433 if (e != self.StopIteration) {
434 throw e;
435 }
436 return rval;
437 }
438 // mozilla warnings aren't too bright
439 return undefined;
440 },
441
442
443 /** @id MochiKit.Iter.reduce */
444 reduce: function (fn, iterable, /* optional */initial) {
445 var i = 0;
446 var x = initial;
447 var self = MochiKit.Iter;
448 iterable = self.iter(iterable);
449 if (arguments.length < 3) {
450 try {
451 x = iterable.next();
452 } catch (e) {
453 if (e == self.StopIteration) {
454 e = new TypeError("reduce() of empty sequence with no initial value");
455 }
456 throw e;
457 }
458 i++;
459 }
460 try {
461 while (true) {
462 x = fn(x, iterable.next());
463 }
464 } catch (e) {
465 if (e != self.StopIteration) {
466 throw e;
467 }
468 }
469 return x;
470 },
471
472 /** @id MochiKit.Iter.range */
473 range: function (/* [start,] stop[, step] */) {
474 var start = 0;
475 var stop = 0;
476 var step = 1;
477 if (arguments.length == 1) {
478 stop = arguments[0];
479 } else if (arguments.length == 2) {
480 start = arguments[0];
481 stop = arguments[1];
482 } else if (arguments.length == 3) {
483 start = arguments[0];
484 stop = arguments[1];
485 step = arguments[2];
486 } else {
487 throw new TypeError("range() takes 1, 2, or 3 arguments!");
488 }
489 if (step === 0) {
490 throw new TypeError("range() step must not be 0");
491 }
492 return {
493 next: function () {
494 if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
495 throw MochiKit.Iter.StopIteration;
496 }
497 var rval = start;
498 start += step;
499 return rval;
500 },
501 repr: function () {
502 return "range(" + [start, stop, step].join(", ") + ")";
503 },
504 toString: MochiKit.Base.forwardCall("repr")
505 };
506 },
507
508 /** @id MochiKit.Iter.sum */
509 sum: function (iterable, start/* = 0 */) {
510 if (typeof(start) == "undefined" || start === null) {
511 start = 0;
512 }
513 var x = start;
514 var self = MochiKit.Iter;
515 iterable = self.iter(iterable);
516 try {
517 while (true) {
518 x += iterable.next();
519 }
520 } catch (e) {
521 if (e != self.StopIteration) {
522 throw e;
523 }
524 }
525 return x;
526 },
527
528 /** @id MochiKit.Iter.exhaust */
529 exhaust: function (iterable) {
530 var self = MochiKit.Iter;
531 iterable = self.iter(iterable);
532 try {
533 while (true) {
534 iterable.next();
535 }
536 } catch (e) {
537 if (e != self.StopIteration) {
538 throw e;
539 }
540 }
541 },
542
543 /** @id MochiKit.Iter.forEach */
544 forEach: function (iterable, func, /* optional */self) {
545 var m = MochiKit.Base;
546 if (arguments.length > 2) {
547 func = m.bind(func, self);
548 }
549 // fast path for array
550 if (m.isArrayLike(iterable)) {
551 try {
552 for (var i = 0; i < iterable.length; i++) {
553 func(iterable[i]);
554 }
555 } catch (e) {
556 if (e != MochiKit.Iter.StopIteration) {
557 throw e;
558 }
559 }
560 } else {
561 self = MochiKit.Iter;
562 self.exhaust(self.imap(func, iterable));
563 }
564 },
565
566 /** @id MochiKit.Iter.every */
567 every: function (iterable, func) {
568 var self = MochiKit.Iter;
569 try {
570 self.ifilterfalse(func, iterable).next();
571 return false;
572 } catch (e) {
573 if (e != self.StopIteration) {
574 throw e;
575 }
576 return true;
577 }
578 },
579
580 /** @id MochiKit.Iter.sorted */
581 sorted: function (iterable, /* optional */cmp) {
582 var rval = MochiKit.Iter.list(iterable);
583 if (arguments.length == 1) {
584 cmp = MochiKit.Base.compare;
585 }
586 rval.sort(cmp);
587 return rval;
588 },
589
590 /** @id MochiKit.Iter.reversed */
591 reversed: function (iterable) {
592 var rval = MochiKit.Iter.list(iterable);
593 rval.reverse();
594 return rval;
595 },
596
597 /** @id MochiKit.Iter.some */
598 some: function (iterable, func) {
599 var self = MochiKit.Iter;
600 try {
601 self.ifilter(func, iterable).next();
602 return true;
603 } catch (e) {
604 if (e != self.StopIteration) {
605 throw e;
606 }
607 return false;
608 }
609 },
610
611 /** @id MochiKit.Iter.iextend */
612 iextend: function (lst, iterable) {
613 if (MochiKit.Base.isArrayLike(iterable)) {
614 // fast-path for array-like
615 for (var i = 0; i < iterable.length; i++) {
616 lst.push(iterable[i]);
617 }
618 } else {
619 var self = MochiKit.Iter;
620 iterable = self.iter(iterable);
621 try {
622 while (true) {
623 lst.push(iterable.next());
624 }
625 } catch (e) {
626 if (e != self.StopIteration) {
627 throw e;
628 }
629 }
630 }
631 return lst;
632 },
633
634 /** @id MochiKit.Iter.groupby */
635 groupby: function(iterable, /* optional */ keyfunc) {
636 var m = MochiKit.Base;
637 var self = MochiKit.Iter;
638 if (arguments.length < 2) {
639 keyfunc = m.operator.identity;
640 }
641 iterable = self.iter(iterable);
642
643 // shared
644 var pk = undefined;
645 var k = undefined;
646 var v;
647
648 function fetch() {
649 v = iterable.next();
650 k = keyfunc(v);
651 };
652
653 function eat() {
654 var ret = v;
655 v = undefined;
656 return ret;
657 };
658
659 var first = true;
660 var compare = m.compare;
661 return {
662 repr: function () { return "groupby(...)"; },
663 next: function() {
664 // iterator-next
665
666 // iterate until meet next group
667 while (compare(k, pk) === 0) {
668 fetch();
669 if (first) {
670 first = false;
671 break;
672 }
673 }
674 pk = k;
675 return [k, {
676 next: function() {
677 // subiterator-next
678 if (v == undefined) { // Is there something to eat?
679 fetch();
680 }
681 if (compare(k, pk) !== 0) {
682 throw self.StopIteration;
683 }
684 return eat();
685 }
686 }];
687 }
688 };
689 },
690
691 /** @id MochiKit.Iter.groupby_as_array */
692 groupby_as_array: function (iterable, /* optional */ keyfunc) {
693 var m = MochiKit.Base;
694 var self = MochiKit.Iter;
695 if (arguments.length < 2) {
696 keyfunc = m.operator.identity;
697 }
698
699 iterable = self.iter(iterable);
700 var result = [];
701 var first = true;
702 var prev_key;
703 var compare = m.compare;
704 while (true) {
705 try {
706 var value = iterable.next();
707 var key = keyfunc(value);
708 } catch (e) {
709 if (e == self.StopIteration) {
710 break;
711 }
712 throw e;
713 }
714 if (first || compare(key, prev_key) !== 0) {
715 var values = [];
716 result.push([key, values]);
717 }
718 values.push(value);
719 first = false;
720 prev_key = key;
721 }
722 return result;
723 },
724
725 /** @id MochiKit.Iter.arrayLikeIter */
726 arrayLikeIter: function (iterable) {
727 var i = 0;
728 return {
729 repr: function () { return "arrayLikeIter(...)"; },
730 toString: MochiKit.Base.forwardCall("repr"),
731 next: function () {
732 if (i >= iterable.length) {
733 throw MochiKit.Iter.StopIteration;
734 }
735 return iterable[i++];
736 }
737 };
738 },
739
740 /** @id MochiKit.Iter.hasIterateNext */
741 hasIterateNext: function (iterable) {
742 return (iterable && typeof(iterable.iterateNext) == "function");
743 },
744
745 /** @id MochiKit.Iter.iterateNextIter */
746 iterateNextIter: function (iterable) {
747 return {
748 repr: function () { return "iterateNextIter(...)"; },
749 toString: MochiKit.Base.forwardCall("repr"),
750 next: function () {
751 var rval = iterable.iterateNext();
752 if (rval === null || rval === undefined) {
753 throw MochiKit.Iter.StopIteration;
754 }
755 return rval;
756 }
757 };
758 }
759});
760
761
762MochiKit.Iter.EXPORT_OK = [
763 "iteratorRegistry",
764 "arrayLikeIter",
765 "hasIterateNext",
766 "iterateNextIter",
767];
768
769MochiKit.Iter.EXPORT = [
770 "StopIteration",
771 "registerIteratorFactory",
772 "iter",
773 "count",
774 "cycle",
775 "repeat",
776 "next",
777 "izip",
778 "ifilter",
779 "ifilterfalse",
780 "islice",
781 "imap",
782 "applymap",
783 "chain",
784 "takewhile",
785 "dropwhile",
786 "tee",
787 "list",
788 "reduce",
789 "range",
790 "sum",
791 "exhaust",
792 "forEach",
793 "every",
794 "sorted",
795 "reversed",
796 "some",
797 "iextend",
798 "groupby",
799 "groupby_as_array"
800];
801
802MochiKit.Iter.__new__ = function () {
803 var m = MochiKit.Base;
804 // Re-use StopIteration if exists (e.g. SpiderMonkey)
805 if (typeof(StopIteration) != "undefined") {
806 this.StopIteration = StopIteration;
807 } else {
808 /** @id MochiKit.Iter.StopIteration */
809 this.StopIteration = new m.NamedError("StopIteration");
810 }
811 this.iteratorRegistry = new m.AdapterRegistry();
812 // Register the iterator factory for arrays
813 this.registerIteratorFactory(
814 "arrayLike",
815 m.isArrayLike,
816 this.arrayLikeIter
817 );
818
819 this.registerIteratorFactory(
820 "iterateNext",
821 this.hasIterateNext,
822 this.iterateNextIter
823 );
824
825 this.EXPORT_TAGS = {
826 ":common": this.EXPORT,
827 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
828 };
829
830 m.nameFunctions(this);
831
832};
833
834MochiKit.Iter.__new__();
835
836//
837// XXX: Internet Explorer blows
838//
839if (MochiKit.__export__) {
840 reduce = MochiKit.Iter.reduce;
841}
842
843MochiKit.Base._exportSymbols(this, MochiKit.Iter);
diff --git a/frontend/beta/js/MochiKit/Logging.js b/frontend/beta/js/MochiKit/Logging.js
new file mode 100644
index 0000000..4d25c3e
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Logging.js
@@ -0,0 +1,321 @@
1/***
2
3MochiKit.Logging 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Logging');
13 dojo.require('MochiKit.Base');
14}
15
16if (typeof(JSAN) != 'undefined') {
17 JSAN.use("MochiKit.Base", []);
18}
19
20try {
21 if (typeof(MochiKit.Base) == 'undefined') {
22 throw "";
23 }
24} catch (e) {
25 throw "MochiKit.Logging depends on MochiKit.Base!";
26}
27
28if (typeof(MochiKit.Logging) == 'undefined') {
29 MochiKit.Logging = {};
30}
31
32MochiKit.Logging.NAME = "MochiKit.Logging";
33MochiKit.Logging.VERSION = "1.4";
34MochiKit.Logging.__repr__ = function () {
35 return "[" + this.NAME + " " + this.VERSION + "]";
36};
37
38MochiKit.Logging.toString = function () {
39 return this.__repr__();
40};
41
42
43MochiKit.Logging.EXPORT = [
44 "LogLevel",
45 "LogMessage",
46 "Logger",
47 "alertListener",
48 "logger",
49 "log",
50 "logError",
51 "logDebug",
52 "logFatal",
53 "logWarning"
54];
55
56
57MochiKit.Logging.EXPORT_OK = [
58 "logLevelAtLeast",
59 "isLogMessage",
60 "compareLogMessage"
61];
62
63
64/** @id MochiKit.Logging.LogMessage */
65MochiKit.Logging.LogMessage = function (num, level, info) {
66 this.num = num;
67 this.level = level;
68 this.info = info;
69 this.timestamp = new Date();
70};
71
72MochiKit.Logging.LogMessage.prototype = {
73 /** @id MochiKit.Logging.LogMessage.prototype.repr */
74 repr: function () {
75 var m = MochiKit.Base;
76 return 'LogMessage(' +
77 m.map(
78 m.repr,
79 [this.num, this.level, this.info]
80 ).join(', ') + ')';
81 },
82 /** @id MochiKit.Logging.LogMessage.prototype.toString */
83 toString: MochiKit.Base.forwardCall("repr")
84};
85
86MochiKit.Base.update(MochiKit.Logging, {
87 /** @id MochiKit.Logging.logLevelAtLeast */
88 logLevelAtLeast: function (minLevel) {
89 var self = MochiKit.Logging;
90 if (typeof(minLevel) == 'string') {
91 minLevel = self.LogLevel[minLevel];
92 }
93 return function (msg) {
94 var msgLevel = msg.level;
95 if (typeof(msgLevel) == 'string') {
96 msgLevel = self.LogLevel[msgLevel];
97 }
98 return msgLevel >= minLevel;
99 };
100 },
101
102 /** @id MochiKit.Logging.isLogMessage */
103 isLogMessage: function (/* ... */) {
104 var LogMessage = MochiKit.Logging.LogMessage;
105 for (var i = 0; i < arguments.length; i++) {
106 if (!(arguments[i] instanceof LogMessage)) {
107 return false;
108 }
109 }
110 return true;
111 },
112
113 /** @id MochiKit.Logging.compareLogMessage */
114 compareLogMessage: function (a, b) {
115 return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]);
116 },
117
118 /** @id MochiKit.Logging.alertListener */
119 alertListener: function (msg) {
120 alert(
121 "num: " + msg.num +
122 "\nlevel: " + msg.level +
123 "\ninfo: " + msg.info.join(" ")
124 );
125 }
126
127});
128
129/** @id MochiKit.Logging.Logger */
130MochiKit.Logging.Logger = function (/* optional */maxSize) {
131 this.counter = 0;
132 if (typeof(maxSize) == 'undefined' || maxSize === null) {
133 maxSize = -1;
134 }
135 this.maxSize = maxSize;
136 this._messages = [];
137 this.listeners = {};
138 this.useNativeConsole = false;
139};
140
141MochiKit.Logging.Logger.prototype = {
142 /** @id MochiKit.Logging.Logger.prototype.clear */
143 clear: function () {
144 this._messages.splice(0, this._messages.length);
145 },
146
147 /** @id MochiKit.Logging.Logger.prototype.logToConsole */
148 logToConsole: function (msg) {
149 if (typeof(window) != "undefined" && window.console
150 && window.console.log) {
151 // Safari and FireBug 0.4
152 // Percent replacement is a workaround for cute Safari crashing bug
153 window.console.log(msg.replace(/%/g, '\uFF05'));
154 } else if (typeof(opera) != "undefined" && opera.postError) {
155 // Opera
156 opera.postError(msg);
157 } else if (typeof(printfire) == "function") {
158 // FireBug 0.3 and earlier
159 printfire(msg);
160 } else if (typeof(Debug) != "undefined" && Debug.writeln) {
161 // IE Web Development Helper (?)
162 // http://www.nikhilk.net/Entry.aspx?id=93
163 Debug.writeln(msg);
164 } else if (typeof(debug) != "undefined" && debug.trace) {
165 // Atlas framework (?)
166 // http://www.nikhilk.net/Entry.aspx?id=93
167 debug.trace(msg);
168 }
169 },
170
171 /** @id MochiKit.Logging.Logger.prototype.dispatchListeners */
172 dispatchListeners: function (msg) {
173 for (var k in this.listeners) {
174 var pair = this.listeners[k];
175 if (pair.ident != k || (pair[0] && !pair[0](msg))) {
176 continue;
177 }
178 pair[1](msg);
179 }
180 },
181
182 /** @id MochiKit.Logging.Logger.prototype.addListener */
183 addListener: function (ident, filter, listener) {
184 if (typeof(filter) == 'string') {
185 filter = MochiKit.Logging.logLevelAtLeast(filter);
186 }
187 var entry = [filter, listener];
188 entry.ident = ident;
189 this.listeners[ident] = entry;
190 },
191
192 /** @id MochiKit.Logging.Logger.prototype.removeListener */
193 removeListener: function (ident) {
194 delete this.listeners[ident];
195 },
196
197 /** @id MochiKit.Logging.Logger.prototype.baseLog */
198 baseLog: function (level, message/*, ...*/) {
199 var msg = new MochiKit.Logging.LogMessage(
200 this.counter,
201 level,
202 MochiKit.Base.extend(null, arguments, 1)
203 );
204 this._messages.push(msg);
205 this.dispatchListeners(msg);
206 if (this.useNativeConsole) {
207 this.logToConsole(msg.level + ": " + msg.info.join(" "));
208 }
209 this.counter += 1;
210 while (this.maxSize >= 0 && this._messages.length > this.maxSize) {
211 this._messages.shift();
212 }
213 },
214
215 /** @id MochiKit.Logging.Logger.prototype.getMessages */
216 getMessages: function (howMany) {
217 var firstMsg = 0;
218 if (!(typeof(howMany) == 'undefined' || howMany === null)) {
219 firstMsg = Math.max(0, this._messages.length - howMany);
220 }
221 return this._messages.slice(firstMsg);
222 },
223
224 /** @id MochiKit.Logging.Logger.prototype.getMessageText */
225 getMessageText: function (howMany) {
226 if (typeof(howMany) == 'undefined' || howMany === null) {
227 howMany = 30;
228 }
229 var messages = this.getMessages(howMany);
230 if (messages.length) {
231 var lst = map(function (m) {
232 return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' ');
233 }, messages);
234 lst.unshift('LAST ' + messages.length + ' MESSAGES:');
235 return lst.join('');
236 }
237 return '';
238 },
239
240 /** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */
241 debuggingBookmarklet: function (inline) {
242 if (typeof(MochiKit.LoggingPane) == "undefined") {
243 alert(this.getMessageText());
244 } else {
245 MochiKit.LoggingPane.createLoggingPane(inline || false);
246 }
247 }
248};
249
250MochiKit.Logging.__new__ = function () {
251 this.LogLevel = {
252 ERROR: 40,
253 FATAL: 50,
254 WARNING: 30,
255 INFO: 20,
256 DEBUG: 10
257 };
258
259 var m = MochiKit.Base;
260 m.registerComparator("LogMessage",
261 this.isLogMessage,
262 this.compareLogMessage
263 );
264
265 var partial = m.partial;
266
267 var Logger = this.Logger;
268 var baseLog = Logger.prototype.baseLog;
269 m.update(this.Logger.prototype, {
270 debug: partial(baseLog, 'DEBUG'),
271 log: partial(baseLog, 'INFO'),
272 error: partial(baseLog, 'ERROR'),
273 fatal: partial(baseLog, 'FATAL'),
274 warning: partial(baseLog, 'WARNING')
275 });
276
277 // indirectly find logger so it can be replaced
278 var self = this;
279 var connectLog = function (name) {
280 return function () {
281 self.logger[name].apply(self.logger, arguments);
282 };
283 };
284
285 /** @id MochiKit.Logging.log */
286 this.log = connectLog('log');
287 /** @id MochiKit.Logging.logError */
288 this.logError = connectLog('error');
289 /** @id MochiKit.Logging.logDebug */
290 this.logDebug = connectLog('debug');
291 /** @id MochiKit.Logging.logFatal */
292 this.logFatal = connectLog('fatal');
293 /** @id MochiKit.Logging.logWarning */
294 this.logWarning = connectLog('warning');
295 this.logger = new Logger();
296 this.logger.useNativeConsole = true;
297
298 this.EXPORT_TAGS = {
299 ":common": this.EXPORT,
300 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
301 };
302
303 m.nameFunctions(this);
304
305};
306
307if (typeof(printfire) == "undefined" &&
308 typeof(document) != "undefined" && document.createEvent &&
309 typeof(dispatchEvent) != "undefined") {
310 // FireBug really should be less lame about this global function
311 printfire = function () {
312 printfire.args = arguments;
313 var ev = document.createEvent("Events");
314 ev.initEvent("printfire", false, true);
315 dispatchEvent(ev);
316 };
317}
318
319MochiKit.Logging.__new__();
320
321MochiKit.Base._exportSymbols(this, MochiKit.Logging);
diff --git a/frontend/beta/js/MochiKit/LoggingPane.js b/frontend/beta/js/MochiKit/LoggingPane.js
new file mode 100644
index 0000000..3798ae4
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/LoggingPane.js
@@ -0,0 +1,374 @@
1/***
2
3MochiKit.LoggingPane 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.LoggingPane');
13 dojo.require('MochiKit.Logging');
14 dojo.require('MochiKit.Base');
15}
16
17if (typeof(JSAN) != 'undefined') {
18 JSAN.use("MochiKit.Logging", []);
19 JSAN.use("MochiKit.Base", []);
20}
21
22try {
23 if (typeof(MochiKit.Base) == 'undefined' || typeof(MochiKit.Logging) == 'undefined') {
24 throw "";
25 }
26} catch (e) {
27 throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!";
28}
29
30if (typeof(MochiKit.LoggingPane) == 'undefined') {
31 MochiKit.LoggingPane = {};
32}
33
34MochiKit.LoggingPane.NAME = "MochiKit.LoggingPane";
35MochiKit.LoggingPane.VERSION = "1.4";
36MochiKit.LoggingPane.__repr__ = function () {
37 return "[" + this.NAME + " " + this.VERSION + "]";
38};
39
40MochiKit.LoggingPane.toString = function () {
41 return this.__repr__();
42};
43
44/** @id MochiKit.LoggingPane.createLoggingPane */
45MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) {
46 var m = MochiKit.LoggingPane;
47 inline = !(!inline);
48 if (m._loggingPane && m._loggingPane.inline != inline) {
49 m._loggingPane.closePane();
50 m._loggingPane = null;
51 }
52 if (!m._loggingPane || m._loggingPane.closed) {
53 m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger);
54 }
55 return m._loggingPane;
56};
57
58/** @id MochiKit.LoggingPane.LoggingPane */
59MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) {
60
61 /* Use a div if inline, pop up a window if not */
62 /* Create the elements */
63 if (typeof(logger) == "undefined" || logger === null) {
64 logger = MochiKit.Logging.logger;
65 }
66 this.logger = logger;
67 var update = MochiKit.Base.update;
68 var updatetree = MochiKit.Base.updatetree;
69 var bind = MochiKit.Base.bind;
70 var clone = MochiKit.Base.clone;
71 var win = window;
72 var uid = "_MochiKit_LoggingPane";
73 if (typeof(MochiKit.DOM) != "undefined") {
74 win = MochiKit.DOM.currentWindow();
75 }
76 if (!inline) {
77 // name the popup with the base URL for uniqueness
78 var url = win.location.href.split("?")[0].replace(/[#:\/.><&-]/g, "_");
79 var name = uid + "_" + url;
80 var nwin = win.open("", name, "dependent,resizable,height=200");
81 if (!nwin) {
82 alert("Not able to open debugging window due to pop-up blocking.");
83 return undefined;
84 }
85 nwin.document.write(
86 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
87 + '"http://www.w3.org/TR/html4/loose.dtd">'
88 + '<html><head><title>[MochiKit.LoggingPane]</title></head>'
89 + '<body></body></html>'
90 );
91 nwin.document.close();
92 nwin.document.title += ' ' + win.document.title;
93 win = nwin;
94 }
95 var doc = win.document;
96 this.doc = doc;
97
98 // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
99 var debugPane = doc.getElementById(uid);
100 var existing_pane = !!debugPane;
101 if (debugPane && typeof(debugPane.loggingPane) != "undefined") {
102 debugPane.loggingPane.logger = this.logger;
103 debugPane.loggingPane.buildAndApplyFilter();
104 return debugPane.loggingPane;
105 }
106
107 if (existing_pane) {
108 // clear any existing contents
109 var child;
110 while ((child = debugPane.firstChild)) {
111 debugPane.removeChild(child);
112 }
113 } else {
114 debugPane = doc.createElement("div");
115 debugPane.id = uid;
116 }
117 debugPane.loggingPane = this;
118 var levelFilterField = doc.createElement("input");
119 var infoFilterField = doc.createElement("input");
120 var filterButton = doc.createElement("button");
121 var loadButton = doc.createElement("button");
122 var clearButton = doc.createElement("button");
123 var closeButton = doc.createElement("button");
124 var logPaneArea = doc.createElement("div");
125 var logPane = doc.createElement("div");
126
127 /* Set up the functions */
128 var listenerId = uid + "_Listener";
129 this.colorTable = clone(this.colorTable);
130 var messages = [];
131 var messageFilter = null;
132
133 /** @id MochiKit.LoggingPane.messageLevel */
134 var messageLevel = function (msg) {
135 var level = msg.level;
136 if (typeof(level) == "number") {
137 level = MochiKit.Logging.LogLevel[level];
138 }
139 return level;
140 };
141
142 /** @id MochiKit.LoggingPane.messageText */
143 var messageText = function (msg) {
144 return msg.info.join(" ");
145 };
146
147 /** @id MochiKit.LoggingPane.addMessageText */
148 var addMessageText = bind(function (msg) {
149 var level = messageLevel(msg);
150 var text = messageText(msg);
151 var c = this.colorTable[level];
152 var p = doc.createElement("span");
153 p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level;
154 p.style.cssText = "margin: 0px; white-space: -moz-pre-wrap; white-space: -o-pre-wrap; white-space: pre-wrap; white-space: pre-line; word-wrap: break-word; wrap-option: emergency; color: " + c;
155 p.appendChild(doc.createTextNode(level + ": " + text));
156 logPane.appendChild(p);
157 logPane.appendChild(doc.createElement("br"));
158 if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) {
159 logPaneArea.scrollTop = 0;
160 } else {
161 logPaneArea.scrollTop = logPaneArea.scrollHeight;
162 }
163 }, this);
164
165 /** @id MochiKit.LoggingPane.addMessage */
166 var addMessage = function (msg) {
167 messages[messages.length] = msg;
168 addMessageText(msg);
169 };
170
171 /** @id MochiKit.LoggingPane.buildMessageFilter */
172 var buildMessageFilter = function () {
173 var levelre, infore;
174 try {
175 /* Catch any exceptions that might arise due to invalid regexes */
176 levelre = new RegExp(levelFilterField.value);
177 infore = new RegExp(infoFilterField.value);
178 } catch(e) {
179 /* If there was an error with the regexes, do no filtering */
180 logDebug("Error in filter regex: " + e.message);
181 return null;
182 }
183
184 return function (msg) {
185 return (
186 levelre.test(messageLevel(msg)) &&
187 infore.test(messageText(msg))
188 );
189 };
190 };
191
192 /** @id MochiKit.LoggingPane.clearMessagePane */
193 var clearMessagePane = function () {
194 while (logPane.firstChild) {
195 logPane.removeChild(logPane.firstChild);
196 }
197 };
198
199 /** @id MochiKit.LoggingPane.clearMessages */
200 var clearMessages = function () {
201 messages = [];
202 clearMessagePane();
203 };
204
205 /** @id MochiKit.LoggingPane.closePane */
206 var closePane = bind(function () {
207 if (this.closed) {
208 return;
209 }
210 this.closed = true;
211 if (MochiKit.LoggingPane._loggingPane == this) {
212 MochiKit.LoggingPane._loggingPane = null;
213 }
214 this.logger.removeListener(listenerId);
215 try {
216 try {
217 debugPane.loggingPane = null;
218 } catch(e) { logFatal("Bookmarklet was closed incorrectly."); }
219 if (inline) {
220 debugPane.parentNode.removeChild(debugPane);
221 } else {
222 this.win.close();
223 }
224 } catch(e) {}
225 }, this);
226
227 /** @id MochiKit.LoggingPane.filterMessages */
228 var filterMessages = function () {
229 clearMessagePane();
230
231 for (var i = 0; i < messages.length; i++) {
232 var msg = messages[i];
233 if (messageFilter === null || messageFilter(msg)) {
234 addMessageText(msg);
235 }
236 }
237 };
238
239 this.buildAndApplyFilter = function () {
240 messageFilter = buildMessageFilter();
241
242 filterMessages();
243
244 this.logger.removeListener(listenerId);
245 this.logger.addListener(listenerId, messageFilter, addMessage);
246 };
247
248
249 /** @id MochiKit.LoggingPane.loadMessages */
250 var loadMessages = bind(function () {
251 messages = this.logger.getMessages();
252 filterMessages();
253 }, this);
254
255 /** @id MochiKit.LoggingPane.filterOnEnter */
256 var filterOnEnter = bind(function (event) {
257 event = event || window.event;
258 key = event.which || event.keyCode;
259 if (key == 13) {
260 this.buildAndApplyFilter();
261 }
262 }, this);
263
264 /* Create the debug pane */
265 var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont;
266 if (inline) {
267 style += "; height: 10em; border-top: 2px solid black";
268 } else {
269 style += "; height: 100%;";
270 }
271 debugPane.style.cssText = style;
272
273 if (!existing_pane) {
274 doc.body.appendChild(debugPane);
275 }
276
277 /* Create the filter fields */
278 style = {"cssText": "width: 33%; display: inline; font: " + this.logFont};
279
280 updatetree(levelFilterField, {
281 "value": "FATAL|ERROR|WARNING|INFO|DEBUG",
282 "onkeypress": filterOnEnter,
283 "style": style
284 });
285 debugPane.appendChild(levelFilterField);
286
287 updatetree(infoFilterField, {
288 "value": ".*",
289 "onkeypress": filterOnEnter,
290 "style": style
291 });
292 debugPane.appendChild(infoFilterField);
293
294 /* Create the buttons */
295 style = "width: 8%; display:inline; font: " + this.logFont;
296
297 filterButton.appendChild(doc.createTextNode("Filter"));
298 filterButton.onclick = bind("buildAndApplyFilter", this);
299 filterButton.style.cssText = style;
300 debugPane.appendChild(filterButton);
301
302 loadButton.appendChild(doc.createTextNode("Load"));
303 loadButton.onclick = loadMessages;
304 loadButton.style.cssText = style;
305 debugPane.appendChild(loadButton);
306
307 clearButton.appendChild(doc.createTextNode("Clear"));
308 clearButton.onclick = clearMessages;
309 clearButton.style.cssText = style;
310 debugPane.appendChild(clearButton);
311
312 closeButton.appendChild(doc.createTextNode("Close"));
313 closeButton.onclick = closePane;
314 closeButton.style.cssText = style;
315 debugPane.appendChild(closeButton);
316
317 /* Create the logging pane */
318 logPaneArea.style.cssText = "overflow: auto; width: 100%";
319 logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%");
320
321 logPaneArea.appendChild(logPane);
322 debugPane.appendChild(logPaneArea);
323
324 this.buildAndApplyFilter();
325 loadMessages();
326
327 if (inline) {
328 this.win = undefined;
329 } else {
330 this.win = win;
331 }
332 this.inline = inline;
333 this.closePane = closePane;
334 this.closed = false;
335
336
337 return this;
338};
339
340MochiKit.LoggingPane.LoggingPane.prototype = {
341 "logFont": "8pt Verdana,sans-serif",
342 "colorTable": {
343 "ERROR": "red",
344 "FATAL": "darkred",
345 "WARNING": "blue",
346 "INFO": "black",
347 "DEBUG": "green"
348 }
349};
350
351
352MochiKit.LoggingPane.EXPORT_OK = [
353 "LoggingPane"
354];
355
356MochiKit.LoggingPane.EXPORT = [
357 "createLoggingPane"
358];
359
360MochiKit.LoggingPane.__new__ = function () {
361 this.EXPORT_TAGS = {
362 ":common": this.EXPORT,
363 ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
364 };
365
366 MochiKit.Base.nameFunctions(this);
367
368 MochiKit.LoggingPane._loggingPane = null;
369
370};
371
372MochiKit.LoggingPane.__new__();
373
374MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane);
diff --git a/frontend/beta/js/MochiKit/MochiKit.js b/frontend/beta/js/MochiKit/MochiKit.js
new file mode 100644
index 0000000..3a13b24
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/MochiKit.js
@@ -0,0 +1,154 @@
1/***
2
3MochiKit.MochiKit 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(MochiKit) == 'undefined') {
12 MochiKit = {};
13}
14
15if (typeof(MochiKit.MochiKit) == 'undefined') {
16 /** @id MochiKit.MochiKit */
17 MochiKit.MochiKit = {};
18}
19
20MochiKit.MochiKit.NAME = "MochiKit.MochiKit";
21MochiKit.MochiKit.VERSION = "1.4";
22MochiKit.MochiKit.__repr__ = function () {
23 return "[" + this.NAME + " " + this.VERSION + "]";
24};
25
26/** @id MochiKit.MochiKit.toString */
27MochiKit.MochiKit.toString = function () {
28 return this.__repr__();
29};
30
31/** @id MochiKit.MochiKit.SUBMODULES */
32MochiKit.MochiKit.SUBMODULES = [
33 "Base",
34 "Iter",
35 "Logging",
36 "DateTime",
37 "Format",
38 "Async",
39 "DOM",
40 "Selector",
41 "Style",
42 "LoggingPane",
43 "Color",
44 "Signal",
45 "Position",
46 "Visual"
47];
48
49if (typeof(JSAN) != 'undefined' || typeof(dojo) != 'undefined') {
50 if (typeof(dojo) != 'undefined') {
51 dojo.provide('MochiKit.MochiKit');
52 dojo.require("MochiKit.*");
53 }
54 if (typeof(JSAN) != 'undefined') {
55 (function (lst) {
56 for (var i = 0; i < lst.length; i++) {
57 JSAN.use("MochiKit." + lst[i], []);
58 }
59 })(MochiKit.MochiKit.SUBMODULES);
60 }
61 (function () {
62 var extend = MochiKit.Base.extend;
63 var self = MochiKit.MochiKit;
64 var modules = self.SUBMODULES;
65 var EXPORT = [];
66 var EXPORT_OK = [];
67 var EXPORT_TAGS = {};
68 var i, k, m, all;
69 for (i = 0; i < modules.length; i++) {
70 m = MochiKit[modules[i]];
71 extend(EXPORT, m.EXPORT);
72 extend(EXPORT_OK, m.EXPORT_OK);
73 for (k in m.EXPORT_TAGS) {
74 EXPORT_TAGS[k] = extend(EXPORT_TAGS[k], m.EXPORT_TAGS[k]);
75 }
76 all = m.EXPORT_TAGS[":all"];
77 if (!all) {
78 all = extend(null, m.EXPORT, m.EXPORT_OK);
79 }
80 var j;
81 for (j = 0; j < all.length; j++) {
82 k = all[j];
83 self[k] = m[k];
84 }
85 }
86 self.EXPORT = EXPORT;
87 self.EXPORT_OK = EXPORT_OK;
88 self.EXPORT_TAGS = EXPORT_TAGS;
89 }());
90
91} else {
92 if (typeof(MochiKit.__compat__) == 'undefined') {
93 MochiKit.__compat__ = true;
94 }
95 (function () {
96 if (typeof(document) == "undefined") {
97 return;
98 }
99 var scripts = document.getElementsByTagName("script");
100 var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
101 var base = null;
102 var baseElem = null;
103 var allScripts = {};
104 var i;
105 for (i = 0; i < scripts.length; i++) {
106 var src = scripts[i].getAttribute("src");
107 if (!src) {
108 continue;
109 }
110 allScripts[src] = true;
111 if (src.match(/MochiKit.js$/)) {
112 base = src.substring(0, src.lastIndexOf('MochiKit.js'));
113 baseElem = scripts[i];
114 }
115 }
116 if (base === null) {
117 return;
118 }
119 var modules = MochiKit.MochiKit.SUBMODULES;
120 for (var i = 0; i < modules.length; i++) {
121 if (MochiKit[modules[i]]) {
122 continue;
123 }
124 var uri = base + modules[i] + '.js';
125 if (uri in allScripts) {
126 continue;
127 }
128 if (document.documentElement &&
129 document.documentElement.namespaceURI == kXULNSURI) {
130 // XUL
131 var s = document.createElementNS(kXULNSURI, 'script');
132 s.setAttribute("id", "MochiKit_" + base + modules[i]);
133 s.setAttribute("src", uri);
134 s.setAttribute("type", "application/x-javascript");
135 baseElem.parentNode.appendChild(s);
136 } else {
137 // HTML
138 /*
139 DOM can not be used here because Safari does
140 deferred loading of scripts unless they are
141 in the document or inserted with document.write
142
143 This is not XHTML compliant. If you want XHTML
144 compliance then you must use the packed version of MochiKit
145 or include each script individually (basically unroll
146 these document.write calls into your XHTML source)
147
148 */
149 document.write('<script src="' + uri +
150 '" type="text/javascript"></script>');
151 }
152 };
153 })();
154}
diff --git a/frontend/beta/js/MochiKit/MockDOM.js b/frontend/beta/js/MochiKit/MockDOM.js
new file mode 100644
index 0000000..92558cb
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/MockDOM.js
@@ -0,0 +1,115 @@
1/***
2
3MochiKit.MockDOM 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(MochiKit) == "undefined") {
12 MochiKit = {};
13}
14
15if (typeof(MochiKit.MockDOM) == "undefined") {
16 MochiKit.MockDOM = {};
17}
18
19MochiKit.MockDOM.NAME = "MochiKit.MockDOM";
20MochiKit.MockDOM.VERSION = "1.4";
21
22MochiKit.MockDOM.__repr__ = function () {
23 return "[" + this.NAME + " " + this.VERSION + "]";
24};
25
26/** @id MochiKit.MockDOM.toString */
27MochiKit.MockDOM.toString = function () {
28 return this.__repr__();
29};
30
31/** @id MochiKit.MockDOM.createDocument */
32MochiKit.MockDOM.createDocument = function () {
33 var doc = new MochiKit.MockDOM.MockElement("DOCUMENT");
34 doc.body = doc.createElement("BODY");
35 doc.appendChild(doc.body);
36 return doc;
37};
38
39/** @id MochiKit.MockDOM.MockElement */
40MochiKit.MockDOM.MockElement = function (name, data, ownerDocument) {
41 this.tagName = this.nodeName = name.toUpperCase();
42 this.ownerDocument = ownerDocument || null;
43 if (name == "DOCUMENT") {
44 this.nodeType = 9;
45 this.childNodes = [];
46 } else if (typeof(data) == "string") {
47 this.nodeValue = data;
48 this.nodeType = 3;
49 } else {
50 this.nodeType = 1;
51 this.childNodes = [];
52 }
53 if (name.substring(0, 1) == "<") {
54 var nameattr = name.substring(
55 name.indexOf('"') + 1, name.lastIndexOf('"'));
56 name = name.substring(1, name.indexOf(" "));
57 this.tagName = this.nodeName = name.toUpperCase();
58 this.setAttribute("name", nameattr);
59 }
60};
61
62MochiKit.MockDOM.MockElement.prototype = {
63 /** @id MochiKit.MockDOM.MockElement.prototype.createElement */
64 createElement: function (tagName) {
65 return new MochiKit.MockDOM.MockElement(tagName, null, this.nodeType == 9 ? this : this.ownerDocument);
66 },
67 /** @id MochiKit.MockDOM.MockElement.prototype.createTextNode */
68 createTextNode: function (text) {
69 return new MochiKit.MockDOM.MockElement("text", text, this.nodeType == 9 ? this : this.ownerDocument);
70 },
71 /** @id MochiKit.MockDOM.MockElement.prototype.setAttribute */
72 setAttribute: function (name, value) {
73 this[name] = value;
74 },
75 /** @id MochiKit.MockDOM.MockElement.prototype.getAttribute */
76 getAttribute: function (name) {
77 return this[name];
78 },
79 /** @id MochiKit.MockDOM.MockElement.prototype.appendChild */
80 appendChild: function (child) {
81 this.childNodes.push(child);
82 },
83 /** @id MochiKit.MockDOM.MockElement.prototype.toString */
84 toString: function () {
85 return "MockElement(" + this.tagName + ")";
86 },
87 /** @id MochiKit.MockDOM.MockElement.prototype.getElementsByTagName */
88 getElementsByTagName: function (tagName) {
89 var foundElements = [];
90 MochiKit.Base.nodeWalk(this, function(node){
91 if (tagName == '*' || tagName == node.tagName) {
92 foundElements.push(node);
93 return node.childNodes;
94 }
95 });
96 return foundElements;
97 }
98};
99
100 /** @id MochiKit.MockDOM.EXPORT_OK */
101MochiKit.MockDOM.EXPORT_OK = [
102 "mockElement",
103 "createDocument"
104];
105
106 /** @id MochiKit.MockDOM.EXPORT */
107MochiKit.MockDOM.EXPORT = [
108 "document"
109];
110
111MochiKit.MockDOM.__new__ = function () {
112 this.document = this.createDocument();
113};
114
115MochiKit.MockDOM.__new__();
diff --git a/frontend/beta/js/MochiKit/New.js b/frontend/beta/js/MochiKit/New.js
new file mode 100644
index 0000000..8b13789
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/New.js
@@ -0,0 +1 @@
diff --git a/frontend/beta/js/MochiKit/Position.js b/frontend/beta/js/MochiKit/Position.js
new file mode 100644
index 0000000..6092fe9
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Position.js
@@ -0,0 +1,246 @@
1/***
2
3MochiKit.Position 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005-2006 Bob Ippolito and others. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Position');
13 dojo.require('MochiKit.Base');
14 dojo.require('MochiKit.DOM');
15 dojo.require('MochiKit.Style');
16}
17if (typeof(JSAN) != 'undefined') {
18 JSAN.use('MochiKit.Base', []);
19 JSAN.use('MochiKit.DOM', []);
20 JSAN.use('MochiKit.Style', []);
21}
22
23try {
24 if (typeof(MochiKit.Base) == 'undefined' ||
25 typeof(MochiKit.Style) == 'undefined' ||
26 typeof(MochiKit.DOM) == 'undefined') {
27 throw '';
28 }
29} catch (e) {
30 throw 'MochiKit.Style depends on MochiKit.Base, MochiKit.DOM, and MochiKit.Style!';
31}
32
33if (typeof(MochiKit.Position) == 'undefined') {
34 MochiKit.Position = {};
35}
36
37MochiKit.Position.NAME = 'MochiKit.Position';
38MochiKit.Position.VERSION = '1.4';
39MochiKit.Position.__repr__ = function () {
40 return '[' + this.NAME + ' ' + this.VERSION + ']';
41};
42MochiKit.Position.toString = function () {
43 return this.__repr__();
44};
45
46MochiKit.Position.EXPORT_OK = [];
47
48MochiKit.Position.EXPORT = [
49];
50
51
52MochiKit.Base.update(MochiKit.Position, {
53 // set to true if needed, warning: firefox performance problems
54 // NOT neeeded for page scrolling, only if draggable contained in
55 // scrollable elements
56 includeScrollOffsets: false,
57
58 /** @id MochiKit.Position.prepare */
59 prepare: function () {
60 var deltaX = window.pageXOffset
61 || document.documentElement.scrollLeft
62 || document.body.scrollLeft
63 || 0;
64 var deltaY = window.pageYOffset
65 || document.documentElement.scrollTop
66 || document.body.scrollTop
67 || 0;
68 this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY);
69 },
70
71 /** @id MochiKit.Position.cumulativeOffset */
72 cumulativeOffset: function (element) {
73 var valueT = 0;
74 var valueL = 0;
75 do {
76 valueT += element.offsetTop || 0;
77 valueL += element.offsetLeft || 0;
78 element = element.offsetParent;
79 } while (element);
80 return new MochiKit.Style.Coordinates(valueL, valueT);
81 },
82
83 /** @id MochiKit.Position.realOffset */
84 realOffset: function (element) {
85 var valueT = 0;
86 var valueL = 0;
87 do {
88 valueT += element.scrollTop || 0;
89 valueL += element.scrollLeft || 0;
90 element = element.parentNode;
91 } while (element);
92 return new MochiKit.Style.Coordinates(valueL, valueT);
93 },
94
95 /** @id MochiKit.Position.within */
96 within: function (element, x, y) {
97 if (this.includeScrollOffsets) {
98 return this.withinIncludingScrolloffsets(element, x, y);
99 }
100 this.xcomp = x;
101 this.ycomp = y;
102 this.offset = this.cumulativeOffset(element);
103 if (element.style.position == "fixed") {
104 this.offset.x += this.windowOffset.x;
105 this.offset.y += this.windowOffset.y;
106 }
107
108 return (y >= this.offset.y &&
109 y < this.offset.y + element.offsetHeight &&
110 x >= this.offset.x &&
111 x < this.offset.x + element.offsetWidth);
112 },
113
114 /** @id MochiKit.Position.withinIncludingScrolloffsets */
115 withinIncludingScrolloffsets: function (element, x, y) {
116 var offsetcache = this.realOffset(element);
117
118 this.xcomp = x + offsetcache.x - this.windowOffset.x;
119 this.ycomp = y + offsetcache.y - this.windowOffset.y;
120 this.offset = this.cumulativeOffset(element);
121
122 return (this.ycomp >= this.offset.y &&
123 this.ycomp < this.offset.y + element.offsetHeight &&
124 this.xcomp >= this.offset.x &&
125 this.xcomp < this.offset.x + element.offsetWidth);
126 },
127
128 // within must be called directly before
129 /** @id MochiKit.Position.overlap */
130 overlap: function (mode, element) {
131 if (!mode) {
132 return 0;
133 }
134 if (mode == 'vertical') {
135 return ((this.offset.y + element.offsetHeight) - this.ycomp) /
136 element.offsetHeight;
137 }
138 if (mode == 'horizontal') {
139 return ((this.offset.x + element.offsetWidth) - this.xcomp) /
140 element.offsetWidth;
141 }
142 },
143
144 /** @id MochiKit.Position.absolutize */
145 absolutize: function (element) {
146 element = MochiKit.DOM.getElement(element);
147 if (element.style.position == 'absolute') {
148 return;
149 }
150 MochiKit.Position.prepare();
151
152 var offsets = MochiKit.Position.positionedOffset(element);
153 var width = element.clientWidth;
154 var height = element.clientHeight;
155
156 var oldStyle = {
157 'position': element.style.position,
158 'left': offsets.x - parseFloat(element.style.left || 0),
159 'top': offsets.y - parseFloat(element.style.top || 0),
160 'width': element.style.width,
161 'height': element.style.height
162 };
163
164 element.style.position = 'absolute';
165 element.style.top = offsets.y + 'px';
166 element.style.left = offsets.x + 'px';
167 element.style.width = width + 'px';
168 element.style.height = height + 'px';
169
170 return oldStyle;
171 },
172
173 /** @id MochiKit.Position.positionedOffset */
174 positionedOffset: function (element) {
175 var valueT = 0, valueL = 0;
176 do {
177 valueT += element.offsetTop || 0;
178 valueL += element.offsetLeft || 0;
179 element = element.offsetParent;
180 if (element) {
181 p = MochiKit.Style.getStyle(element, 'position');
182 if (p == 'relative' || p == 'absolute') {
183 break;
184 }
185 }
186 } while (element);
187 return new MochiKit.Style.Coordinates(valueL, valueT);
188 },
189
190 /** @id MochiKit.Position.relativize */
191 relativize: function (element, oldPos) {
192 element = MochiKit.DOM.getElement(element);
193 if (element.style.position == 'relative') {
194 return;
195 }
196 MochiKit.Position.prepare();
197
198 var top = parseFloat(element.style.top || 0) -
199 (oldPos['top'] || 0);
200 var left = parseFloat(element.style.left || 0) -
201 (oldPos['left'] || 0);
202
203 element.style.position = oldPos['position'];
204 element.style.top = top + 'px';
205 element.style.left = left + 'px';
206 element.style.width = oldPos['width'];
207 element.style.height = oldPos['height'];
208 },
209
210 /** @id MochiKit.Position.clone */
211 clone: function (source, target) {
212 source = MochiKit.DOM.getElement(source);
213 target = MochiKit.DOM.getElement(target);
214 target.style.position = 'absolute';
215 var offsets = this.cumulativeOffset(source);
216 target.style.top = offsets.y + 'px';
217 target.style.left = offsets.x + 'px';
218 target.style.width = source.offsetWidth + 'px';
219 target.style.height = source.offsetHeight + 'px';
220 },
221
222 /** @id MochiKit.Position.page */
223 page: function (forElement) {
224 var valueT = 0;
225 var valueL = 0;
226
227 var element = forElement;
228 do {
229 valueT += element.offsetTop || 0;
230 valueL += element.offsetLeft || 0;
231
232 // Safari fix
233 if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') {
234 break;
235 }
236 } while (element = element.offsetParent);
237
238 element = forElement;
239 do {
240 valueT -= element.scrollTop || 0;
241 valueL -= element.scrollLeft || 0;
242 } while (element = element.parentNode);
243
244 return new MochiKit.Style.Coordinates(valueL, valueT);
245 }
246});
diff --git a/frontend/beta/js/MochiKit/Selector.js b/frontend/beta/js/MochiKit/Selector.js
new file mode 100644
index 0000000..c385df7
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Selector.js
@@ -0,0 +1,431 @@
1/***
2
3MochiKit.Selector 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito and others. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Selector');
13 dojo.require('MochiKit.Base');
14 dojo.require('MochiKit.DOM');
15 dojo.require('MochiKit.Iter');
16}
17
18if (typeof(JSAN) != 'undefined') {
19 JSAN.use("MochiKit.Base", []);
20 JSAN.use("MochiKit.DOM", []);
21 JSAN.use("MochiKit.Iter", []);
22}
23
24try {
25 if (typeof(MochiKit.Base) === 'undefined' ||
26 typeof(MochiKit.DOM) === 'undefined' ||
27 typeof(MochiKit.Iter) === 'undefined') {
28 throw "";
29 }
30} catch (e) {
31 throw "MochiKit.Selector depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!";
32}
33
34if (typeof(MochiKit.Selector) == 'undefined') {
35 MochiKit.Selector = {};
36}
37
38MochiKit.Selector.NAME = "MochiKit.Selector";
39
40MochiKit.Selector.VERSION = "1.4";
41
42MochiKit.Selector.__repr__ = function () {
43 return "[" + this.NAME + " " + this.VERSION + "]";
44};
45
46MochiKit.Selector.toString = function () {
47 return this.__repr__();
48};
49
50MochiKit.Selector.EXPORT = [
51 "Selector",
52 "findChildElements",
53 "findDocElements",
54 "$$"
55];
56
57MochiKit.Selector.EXPORT_OK = [
58];
59
60MochiKit.Selector.Selector = function (expression) {
61 this.params = {classNames: [], pseudoClassNames: []};
62 this.expression = expression.toString().replace(/(^\s+|\s+$)/g, '');
63 this.parseExpression();
64 this.compileMatcher();
65};
66
67MochiKit.Selector.Selector.prototype = {
68 /***
69
70 Selector class: convenient object to make CSS selections.
71
72 ***/
73 __class__: MochiKit.Selector.Selector,
74
75 /** @id MochiKit.Selector.Selector.prototype.parseExpression */
76 parseExpression: function () {
77 function abort(message) {
78 throw 'Parse error in selector: ' + message;
79 }
80
81 if (this.expression == '') {
82 abort('empty expression');
83 }
84
85 var repr = MochiKit.Base.repr;
86 var params = this.params;
87 var expr = this.expression;
88 var match, modifier, clause, rest;
89 while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
90 params.attributes = params.attributes || [];
91 params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
92 expr = match[1];
93 }
94
95 if (expr == '*') {
96 return this.params.wildcard = true;
97 }
98
99 while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)) {
100 modifier = match[1];
101 clause = match[2];
102 rest = match[3];
103 switch (modifier) {
104 case '#':
105 params.id = clause;
106 break;
107 case '.':
108 params.classNames.push(clause);
109 break;
110 case ':':
111 params.pseudoClassNames.push(clause);
112 break;
113 case '':
114 case undefined:
115 params.tagName = clause.toUpperCase();
116 break;
117 default:
118 abort(repr(expr));
119 }
120 expr = rest;
121 }
122
123 if (expr.length > 0) {
124 abort(repr(expr));
125 }
126 },
127
128 /** @id MochiKit.Selector.Selector.prototype.buildMatchExpression */
129 buildMatchExpression: function () {
130 var repr = MochiKit.Base.repr;
131 var params = this.params;
132 var conditions = [];
133 var clause, i;
134
135 function childElements(element) {
136 return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, " + element + ".childNodes)";
137 }
138
139 if (params.wildcard) {
140 conditions.push('true');
141 }
142 if (clause = params.id) {
143 conditions.push('element.id == ' + repr(clause));
144 }
145 if (clause = params.tagName) {
146 conditions.push('element.tagName.toUpperCase() == ' + repr(clause));
147 }
148 if ((clause = params.classNames).length > 0) {
149 for (i = 0; i < clause.length; i++) {
150 conditions.push('MochiKit.DOM.hasElementClass(element, ' + repr(clause[i]) + ')');
151 }
152 }
153 if ((clause = params.pseudoClassNames).length > 0) {
154 for (i = 0; i < clause.length; i++) {
155 var match = clause[i].match(/^([^(]+)(?:\((.*)\))?$/);
156 var pseudoClass = match[1];
157 var pseudoClassArgument = match[2];
158 switch (pseudoClass) {
159 case 'root':
160 conditions.push('element.nodeType == 9 || element === element.ownerDocument.documentElement'); break;
161 case 'nth-child':
162 case 'nth-last-child':
163 case 'nth-of-type':
164 case 'nth-last-of-type':
165 match = pseudoClassArgument.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
166 if (!match) {
167 throw "Invalid argument to pseudo element nth-child: " + pseudoClassArgument;
168 }
169 var a, b;
170 if (match[0] == 'odd') {
171 a = 2;
172 b = 1;
173 } else if (match[0] == 'even') {
174 a = 2;
175 b = 0;
176 } else {
177 a = match[2] && parseInt(match) || null;
178 b = parseInt(match[3]);
179 }
180 conditions.push('this.nthChild(element,' + a + ',' + b
181 + ',' + !!pseudoClass.match('^nth-last') // Reverse
182 + ',' + !!pseudoClass.match('of-type$') // Restrict to same tagName
183 + ')');
184 break;
185 case 'first-child':
186 conditions.push('this.nthChild(element, null, 1)');
187 break;
188 case 'last-child':
189 conditions.push('this.nthChild(element, null, 1, true)');
190 break;
191 case 'first-of-type':
192 conditions.push('this.nthChild(element, null, 1, false, true)');
193 break;
194 case 'last-of-type':
195 conditions.push('this.nthChild(element, null, 1, true, true)');
196 break;
197 case 'only-child':
198 conditions.push(childElements('element.parentNode') + '.length == 1');
199 break;
200 case 'only-of-type':
201 conditions.push('MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, ' + childElements('element.parentNode') + ').length == 1');
202 break;
203 case 'empty':
204 conditions.push('element.childNodes.length == 0');
205 break;
206 case 'enabled':
207 conditions.push('(this.isUIElement(element) && element.disabled === false)');
208 break;
209 case 'disabled':
210 conditions.push('(this.isUIElement(element) && element.disabled === true)');
211 break;
212 case 'checked':
213 conditions.push('(this.isUIElement(element) && element.checked === true)');
214 break;
215 case 'not':
216 var subselector = new MochiKit.Selector.Selector(pseudoClassArgument);
217 conditions.push('!( ' + subselector.buildMatchExpression() + ')')
218 break;
219 }
220 }
221 }
222 if (clause = params.attributes) {
223 MochiKit.Base.map(function (attribute) {
224 var value = 'MochiKit.DOM.getNodeAttribute(element, ' + repr(attribute.name) + ')';
225 var splitValueBy = function (delimiter) {
226 return value + ' && ' + value + '.split(' + repr(delimiter) + ')';
227 }
228
229 switch (attribute.operator) {
230 case '=':
231 conditions.push(value + ' == ' + repr(attribute.value));
232 break;
233 case '~=':
234 conditions.push('MochiKit.Base.findValue(' + splitValueBy(' ') + ', ' + repr(attribute.value) + ') > -1');
235 break;
236 case '^=':
237 conditions.push(value + '.substring(0, ' + attribute.value.length + ') == ' + repr(attribute.value));
238 break;
239 case '$=':
240 conditions.push(value + '.substring(' + value + '.length - ' + attribute.value.length + ') == ' + repr(attribute.value));
241 break;
242 case '*=':
243 conditions.push(value + '.match(' + repr(attribute.value) + ')');
244 break;
245 case '|=':
246 conditions.push(
247 splitValueBy('-') + '[0].toUpperCase() == ' + repr(attribute.value.toUpperCase())
248 );
249 break;
250 case '!=':
251 conditions.push(value + ' != ' + repr(attribute.value));
252 break;
253 case '':
254 case undefined:
255 conditions.push(value + ' != null');
256 break;
257 default:
258 throw 'Unknown operator ' + attribute.operator + ' in selector';
259 }
260 }, clause);
261 }
262
263 return conditions.join(' && ');
264 },
265
266 /** @id MochiKit.Selector.Selector.prototype.compileMatcher */
267 compileMatcher: function () {
268 this.match = new Function('element', 'if (!element.tagName) return false; \
269 return ' + this.buildMatchExpression());
270 },
271
272 /** @id MochiKit.Selector.Selector.prototype.nthChild */
273 nthChild: function (element, a, b, reverse, sametag){
274 var siblings = MochiKit.Base.filter(function (node) {
275 return node.nodeType == 1;
276 }, element.parentNode.childNodes);
277 if (sametag) {
278 siblings = MochiKit.Base.filter(function (node) {
279 return node.tagName == element.tagName;
280 }, siblings);
281 }
282 if (reverse) {
283 siblings = MochiKit.Iter.reversed(siblings);
284 }
285 if (a) {
286 var actualIndex = MochiKit.Base.findIdentical(siblings, element);
287 return ((actualIndex + 1 - b) / a) % 1 == 0;
288 } else {
289 return b == MochiKit.Base.findIdentical(siblings, element) + 1;
290 }
291 },
292
293 /** @id MochiKit.Selector.Selector.prototype.isUIElement */
294 isUIElement: function (element) {
295 return findValue(['input', 'button', 'select', 'option', 'textarea', 'object'],
296 element.tagName.toLowerCase()) > -1;
297 },
298
299 /** @id MochiKit.Selector.Selector.prototype.findElements */
300 findElements: function (scope, axis) {
301 var element;
302
303 if (axis == undefined) {
304 axis = "";
305 }
306
307 function inScope(element, scope) {
308 if (axis == "") {
309 return MochiKit.DOM.isChildNode(element, scope);
310 } else if (axis == ">") {
311 return element.parentNode == scope;
312 } else if (axis == "+") {
313 return element == nextSiblingElement(scope);
314 } else if (axis == "~") {
315 var sibling = scope;
316 while (sibling = nextSiblingElement(sibling)) {
317 if (element == sibling) {
318 return true;
319 }
320 }
321 return false;
322 } else {
323 throw "Invalid axis: " + axis;
324 }
325 }
326
327 if (element = MochiKit.DOM.getElement(this.params.id)) {
328 if (this.match(element)) {
329 if (!scope || inScope(element, scope)) {
330 return [element];
331 }
332 }
333 }
334
335 function nextSiblingElement(node) {
336 node = node.nextSibling;
337 while (node && node.nodeType != 1) {
338 node = node.nextSibling;
339 }
340 return node;
341 }
342
343 if (axis == "") {
344 scope = (scope || currentDocument()).getElementsByTagName(this.params.tagName || '*');
345 } else if (axis == ">") {
346 if (!scope) {
347 throw "> combinator not allowed without preceeding expression";
348 }
349 scope = MochiKit.Base.filter(function (node) {
350 return node.nodeType == 1;
351 }, scope.childNodes);
352 } else if (axis == "+") {
353 if (!scope) {
354 throw "+ combinator not allowed without preceeding expression";
355 }
356 scope = nextSiblingElement(scope) && [nextSiblingElement(scope)];
357 } else if (axis == "~") {
358 if (!scope) {
359 throw "~ combinator not allowed without preceeding expression";
360 }
361 var newscope = [];
362 while (nextSiblingElement(scope)) {
363 scope = nextSiblingElement(scope);
364 newscope.push(scope);
365 }
366 scope = newscope;
367 }
368
369 if (!scope) {
370 return [];
371 }
372
373 var results = MochiKit.Base.filter(MochiKit.Base.bind(function (scopeElt) {
374 return this.match(scopeElt);
375 }, this), scope);
376
377 return results;
378 },
379
380 /** @id MochiKit.Selector.Selector.prototype.repr */
381 repr: function () {
382 return 'Selector(' + this.expression + ')';
383 },
384
385 toString: MochiKit.Base.forwardCall("repr")
386};
387
388MochiKit.Base.update(MochiKit.Selector, {
389
390 /** @id MochiKit.Selector.findChildElements */
391 findChildElements: function (element, expressions) {
392 return MochiKit.Base.flattenArray(MochiKit.Base.map(function (expression) {
393 var nextScope = "";
394 return MochiKit.Iter.reduce(function (results, expr) {
395 if (match = expr.match(/^[>+~]$/)) {
396 nextScope = match[0];
397 return results;
398 } else {
399 var selector = new MochiKit.Selector.Selector(expr);
400 var elements = MochiKit.Iter.reduce(function (elements, result) {
401 return MochiKit.Base.extend(elements, selector.findElements(result || element, nextScope));
402 }, results, []);
403 nextScope = "";
404 return elements;
405 }
406 }, expression.replace(/(^\s+|\s+$)/g, '').split(/\s+/), [null]);
407 }, expressions));
408 },
409
410 findDocElements: function () {
411 return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(), arguments);
412 },
413
414 __new__: function () {
415 var m = MochiKit.Base;
416
417 this.$$ = this.findDocElements;
418
419 this.EXPORT_TAGS = {
420 ":common": this.EXPORT,
421 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
422 };
423
424 m.nameFunctions(this);
425 }
426});
427
428MochiKit.Selector.__new__();
429
430MochiKit.Base._exportSymbols(this, MochiKit.Selector);
431
diff --git a/frontend/beta/js/MochiKit/Signal.js b/frontend/beta/js/MochiKit/Signal.js
new file mode 100644
index 0000000..a11a3de
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Signal.js
@@ -0,0 +1,864 @@
1/***
2
3MochiKit.Signal 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Signal');
13 dojo.require('MochiKit.Base');
14 dojo.require('MochiKit.DOM');
15 dojo.require('MochiKit.Style');
16}
17if (typeof(JSAN) != 'undefined') {
18 JSAN.use('MochiKit.Base', []);
19 JSAN.use('MochiKit.DOM', []);
20 JSAN.use('MochiKit.Style', []);
21}
22
23try {
24 if (typeof(MochiKit.Base) == 'undefined') {
25 throw '';
26 }
27} catch (e) {
28 throw 'MochiKit.Signal depends on MochiKit.Base!';
29}
30
31try {
32 if (typeof(MochiKit.DOM) == 'undefined') {
33 throw '';
34 }
35} catch (e) {
36 throw 'MochiKit.Signal depends on MochiKit.DOM!';
37}
38
39try {
40 if (typeof(MochiKit.Style) == 'undefined') {
41 throw '';
42 }
43} catch (e) {
44 throw 'MochiKit.Signal depends on MochiKit.Style!';
45}
46
47if (typeof(MochiKit.Signal) == 'undefined') {
48 MochiKit.Signal = {};
49}
50
51MochiKit.Signal.NAME = 'MochiKit.Signal';
52MochiKit.Signal.VERSION = '1.4';
53
54MochiKit.Signal._observers = [];
55
56/** @id MochiKit.Signal.Event */
57MochiKit.Signal.Event = function (src, e) {
58 this._event = e || window.event;
59 this._src = src;
60};
61
62MochiKit.Base.update(MochiKit.Signal.Event.prototype, {
63
64 __repr__: function () {
65 var repr = MochiKit.Base.repr;
66 var str = '{event(): ' + repr(this.event()) +
67 ', src(): ' + repr(this.src()) +
68 ', type(): ' + repr(this.type()) +
69 ', target(): ' + repr(this.target());
70
71 if (this.type() &&
72 this.type().indexOf('key') === 0 ||
73 this.type().indexOf('mouse') === 0 ||
74 this.type().indexOf('click') != -1 ||
75 this.type() == 'contextmenu') {
76 str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) +
77 ', ctrl: ' + repr(this.modifier().ctrl) +
78 ', meta: ' + repr(this.modifier().meta) +
79 ', shift: ' + repr(this.modifier().shift) +
80 ', any: ' + repr(this.modifier().any) + '}';
81 }
82
83 if (this.type() && this.type().indexOf('key') === 0) {
84 str += ', key(): {code: ' + repr(this.key().code) +
85 ', string: ' + repr(this.key().string) + '}';
86 }
87
88 if (this.type() && (
89 this.type().indexOf('mouse') === 0 ||
90 this.type().indexOf('click') != -1 ||
91 this.type() == 'contextmenu')) {
92
93 str += ', mouse(): {page: ' + repr(this.mouse().page) +
94 ', client: ' + repr(this.mouse().client);
95
96 if (this.type() != 'mousemove') {
97 str += ', button: {left: ' + repr(this.mouse().button.left) +
98 ', middle: ' + repr(this.mouse().button.middle) +
99 ', right: ' + repr(this.mouse().button.right) + '}}';
100 } else {
101 str += '}';
102 }
103 }
104 if (this.type() == 'mouseover' || this.type() == 'mouseout') {
105 str += ', relatedTarget(): ' + repr(this.relatedTarget());
106 }
107 str += '}';
108 return str;
109 },
110
111 /** @id MochiKit.Signal.Event.prototype.toString */
112 toString: function () {
113 return this.__repr__();
114 },
115
116 /** @id MochiKit.Signal.Event.prototype.src */
117 src: function () {
118 return this._src;
119 },
120
121 /** @id MochiKit.Signal.Event.prototype.event */
122 event: function () {
123 return this._event;
124 },
125
126 /** @id MochiKit.Signal.Event.prototype.type */
127 type: function () {
128 return this._event.type || undefined;
129 },
130
131 /** @id MochiKit.Signal.Event.prototype.target */
132 target: function () {
133 return this._event.target || this._event.srcElement;
134 },
135
136 _relatedTarget: null,
137 /** @id MochiKit.Signal.Event.prototype.relatedTarget */
138 relatedTarget: function () {
139 if (this._relatedTarget !== null) {
140 return this._relatedTarget;
141 }
142
143 var elem = null;
144 if (this.type() == 'mouseover') {
145 elem = (this._event.relatedTarget ||
146 this._event.fromElement);
147 } else if (this.type() == 'mouseout') {
148 elem = (this._event.relatedTarget ||
149 this._event.toElement);
150 }
151 if (elem !== null) {
152 this._relatedTarget = elem;
153 return elem;
154 }
155
156 return undefined;
157 },
158
159 _modifier: null,
160 /** @id MochiKit.Signal.Event.prototype.modifier */
161 modifier: function () {
162 if (this._modifier !== null) {
163 return this._modifier;
164 }
165 var m = {};
166 m.alt = this._event.altKey;
167 m.ctrl = this._event.ctrlKey;
168 m.meta = this._event.metaKey || false; // IE and Opera punt here
169 m.shift = this._event.shiftKey;
170 m.any = m.alt || m.ctrl || m.shift || m.meta;
171 this._modifier = m;
172 return m;
173 },
174
175 _key: null,
176 /** @id MochiKit.Signal.Event.prototype.key */
177 key: function () {
178 if (this._key !== null) {
179 return this._key;
180 }
181 var k = {};
182 if (this.type() && this.type().indexOf('key') === 0) {
183
184 /*
185
186 If you're looking for a special key, look for it in keydown or
187 keyup, but never keypress. If you're looking for a Unicode
188 chracter, look for it with keypress, but never keyup or
189 keydown.
190
191 Notes:
192
193 FF key event behavior:
194 key event charCode keyCode
195 DOWN ku,kd 0 40
196 DOWN kp 0 40
197 ESC ku,kd 0 27
198 ESC kp 0 27
199 a ku,kd 0 65
200 a kp 97 0
201 shift+a ku,kd 0 65
202 shift+a kp 65 0
203 1 ku,kd 0 49
204 1 kp 49 0
205 shift+1 ku,kd 0 0
206 shift+1 kp 33 0
207
208 IE key event behavior:
209 (IE doesn't fire keypress events for special keys.)
210 key event keyCode
211 DOWN ku,kd 40
212 DOWN kp undefined
213 ESC ku,kd 27
214 ESC kp 27
215 a ku,kd 65
216 a kp 97
217 shift+a ku,kd 65
218 shift+a kp 65
219 1 ku,kd 49
220 1 kp 49
221 shift+1 ku,kd 49
222 shift+1 kp 33
223
224 Safari key event behavior:
225 (Safari sets charCode and keyCode to something crazy for
226 special keys.)
227 key event charCode keyCode
228 DOWN ku,kd 63233 40
229 DOWN kp 63233 63233
230 ESC ku,kd 27 27
231 ESC kp 27 27
232 a ku,kd 97 65
233 a kp 97 97
234 shift+a ku,kd 65 65
235 shift+a kp 65 65
236 1 ku,kd 49 49
237 1 kp 49 49
238 shift+1 ku,kd 33 49
239 shift+1 kp 33 33
240
241 */
242
243 /* look for special keys here */
244 if (this.type() == 'keydown' || this.type() == 'keyup') {
245 k.code = this._event.keyCode;
246 k.string = (MochiKit.Signal._specialKeys[k.code] ||
247 'KEY_UNKNOWN');
248 this._key = k;
249 return k;
250
251 /* look for characters here */
252 } else if (this.type() == 'keypress') {
253
254 /*
255
256 Special key behavior:
257
258 IE: does not fire keypress events for special keys
259 FF: sets charCode to 0, and sets the correct keyCode
260 Safari: sets keyCode and charCode to something stupid
261
262 */
263
264 k.code = 0;
265 k.string = '';
266
267 if (typeof(this._event.charCode) != 'undefined' &&
268 this._event.charCode !== 0 &&
269 !MochiKit.Signal._specialMacKeys[this._event.charCode]) {
270 k.code = this._event.charCode;
271 k.string = String.fromCharCode(k.code);
272 } else if (this._event.keyCode &&
273 typeof(this._event.charCode) == 'undefined') { // IE
274 k.code = this._event.keyCode;
275 k.string = String.fromCharCode(k.code);
276 }
277
278 this._key = k;
279 return k;
280 }
281 }
282 return undefined;
283 },
284
285 _mouse: null,
286 /** @id MochiKit.Signal.Event.prototype.mouse */
287 mouse: function () {
288 if (this._mouse !== null) {
289 return this._mouse;
290 }
291
292 var m = {};
293 var e = this._event;
294
295 if (this.type() && (
296 this.type().indexOf('mouse') === 0 ||
297 this.type().indexOf('click') != -1 ||
298 this.type() == 'contextmenu')) {
299
300 m.client = new MochiKit.Style.Coordinates(0, 0);
301 if (e.clientX || e.clientY) {
302 m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX;
303 m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY;
304 }
305
306 m.page = new MochiKit.Style.Coordinates(0, 0);
307 if (e.pageX || e.pageY) {
308 m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX;
309 m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY;
310 } else {
311 /*
312
313 The IE shortcut can be off by two. We fix it. See:
314 http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
315
316 This is similar to the method used in
317 MochiKit.Style.getElementPosition().
318
319 */
320 var de = MochiKit.DOM._document.documentElement;
321 var b = MochiKit.DOM._document.body;
322
323 m.page.x = e.clientX +
324 (de.scrollLeft || b.scrollLeft) -
325 (de.clientLeft || 0);
326
327 m.page.y = e.clientY +
328 (de.scrollTop || b.scrollTop) -
329 (de.clientTop || 0);
330
331 }
332 if (this.type() != 'mousemove') {
333 m.button = {};
334 m.button.left = false;
335 m.button.right = false;
336 m.button.middle = false;
337
338 /* we could check e.button, but which is more consistent */
339 if (e.which) {
340 m.button.left = (e.which == 1);
341 m.button.middle = (e.which == 2);
342 m.button.right = (e.which == 3);
343
344 /*
345
346 Mac browsers and right click:
347
348 - Safari doesn't fire any click events on a right
349 click:
350 http://bugs.webkit.org/show_bug.cgi?id=6595
351
352 - Firefox fires the event, and sets ctrlKey = true
353
354 - Opera fires the event, and sets metaKey = true
355
356 oncontextmenu is fired on right clicks between
357 browsers and across platforms.
358
359 */
360
361 } else {
362 m.button.left = !!(e.button & 1);
363 m.button.right = !!(e.button & 2);
364 m.button.middle = !!(e.button & 4);
365 }
366 }
367 this._mouse = m;
368 return m;
369 }
370 return undefined;
371 },
372
373 /** @id MochiKit.Signal.Event.prototype.stop */
374 stop: function () {
375 this.stopPropagation();
376 this.preventDefault();
377 },
378
379 /** @id MochiKit.Signal.Event.prototype.stopPropagation */
380 stopPropagation: function () {
381 if (this._event.stopPropagation) {
382 this._event.stopPropagation();
383 } else {
384 this._event.cancelBubble = true;
385 }
386 },
387
388 /** @id MochiKit.Signal.Event.prototype.preventDefault */
389 preventDefault: function () {
390 if (this._event.preventDefault) {
391 this._event.preventDefault();
392 } else if (this._confirmUnload === null) {
393 this._event.returnValue = false;
394 }
395 },
396
397 _confirmUnload: null,
398
399 /** @id MochiKit.Signal.Event.prototype.confirmUnload */
400 confirmUnload: function (msg) {
401 if (this.type() == 'beforeunload') {
402 this._confirmUnload = msg;
403 this._event.returnValue = msg;
404 }
405 }
406});
407
408/* Safari sets keyCode to these special values onkeypress. */
409MochiKit.Signal._specialMacKeys = {
410 3: 'KEY_ENTER',
411 63289: 'KEY_NUM_PAD_CLEAR',
412 63276: 'KEY_PAGE_UP',
413 63277: 'KEY_PAGE_DOWN',
414 63275: 'KEY_END',
415 63273: 'KEY_HOME',
416 63234: 'KEY_ARROW_LEFT',
417 63232: 'KEY_ARROW_UP',
418 63235: 'KEY_ARROW_RIGHT',
419 63233: 'KEY_ARROW_DOWN',
420 63302: 'KEY_INSERT',
421 63272: 'KEY_DELETE'
422};
423
424/* for KEY_F1 - KEY_F12 */
425(function () {
426 var _specialMacKeys = MochiKit.Signal._specialMacKeys;
427 for (i = 63236; i <= 63242; i++) {
428 // no F0
429 _specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1);
430 }
431})();
432
433/* Standard keyboard key codes. */
434MochiKit.Signal._specialKeys = {
435 8: 'KEY_BACKSPACE',
436 9: 'KEY_TAB',
437 12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only
438 13: 'KEY_ENTER',
439 16: 'KEY_SHIFT',
440 17: 'KEY_CTRL',
441 18: 'KEY_ALT',
442 19: 'KEY_PAUSE',
443 20: 'KEY_CAPS_LOCK',
444 27: 'KEY_ESCAPE',
445 32: 'KEY_SPACEBAR',
446 33: 'KEY_PAGE_UP',
447 34: 'KEY_PAGE_DOWN',
448 35: 'KEY_END',
449 36: 'KEY_HOME',
450 37: 'KEY_ARROW_LEFT',
451 38: 'KEY_ARROW_UP',
452 39: 'KEY_ARROW_RIGHT',
453 40: 'KEY_ARROW_DOWN',
454 44: 'KEY_PRINT_SCREEN',
455 45: 'KEY_INSERT',
456 46: 'KEY_DELETE',
457 59: 'KEY_SEMICOLON', // weird, for Safari and IE only
458 91: 'KEY_WINDOWS_LEFT',
459 92: 'KEY_WINDOWS_RIGHT',
460 93: 'KEY_SELECT',
461 106: 'KEY_NUM_PAD_ASTERISK',
462 107: 'KEY_NUM_PAD_PLUS_SIGN',
463 109: 'KEY_NUM_PAD_HYPHEN-MINUS',
464 110: 'KEY_NUM_PAD_FULL_STOP',
465 111: 'KEY_NUM_PAD_SOLIDUS',
466 144: 'KEY_NUM_LOCK',
467 145: 'KEY_SCROLL_LOCK',
468 186: 'KEY_SEMICOLON',
469 187: 'KEY_EQUALS_SIGN',
470 188: 'KEY_COMMA',
471 189: 'KEY_HYPHEN-MINUS',
472 190: 'KEY_FULL_STOP',
473 191: 'KEY_SOLIDUS',
474 192: 'KEY_GRAVE_ACCENT',
475 219: 'KEY_LEFT_SQUARE_BRACKET',
476 220: 'KEY_REVERSE_SOLIDUS',
477 221: 'KEY_RIGHT_SQUARE_BRACKET',
478 222: 'KEY_APOSTROPHE'
479 // undefined: 'KEY_UNKNOWN'
480};
481
482(function () {
483 /* for KEY_0 - KEY_9 */
484 var _specialKeys = MochiKit.Signal._specialKeys;
485 for (var i = 48; i <= 57; i++) {
486 _specialKeys[i] = 'KEY_' + (i - 48);
487 }
488
489 /* for KEY_A - KEY_Z */
490 for (i = 65; i <= 90; i++) {
491 _specialKeys[i] = 'KEY_' + String.fromCharCode(i);
492 }
493
494 /* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */
495 for (i = 96; i <= 105; i++) {
496 _specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96);
497 }
498
499 /* for KEY_F1 - KEY_F12 */
500 for (i = 112; i <= 123; i++) {
501 // no F0
502 _specialKeys[i] = 'KEY_F' + (i - 112 + 1);
503 }
504})();
505
506MochiKit.Base.update(MochiKit.Signal, {
507
508 __repr__: function () {
509 return '[' + this.NAME + ' ' + this.VERSION + ']';
510 },
511
512 toString: function () {
513 return this.__repr__();
514 },
515
516 _unloadCache: function () {
517 var self = MochiKit.Signal;
518 var observers = self._observers;
519
520 for (var i = 0; i < observers.length; i++) {
521 self._disconnect(observers[i]);
522 }
523
524 delete self._observers;
525
526 try {
527 window.onload = undefined;
528 } catch(e) {
529 // pass
530 }
531
532 try {
533 window.onunload = undefined;
534 } catch(e) {
535 // pass
536 }
537 },
538
539 _listener: function (src, func, obj, isDOM) {
540 var self = MochiKit.Signal;
541 var E = self.Event;
542 if (!isDOM) {
543 return MochiKit.Base.bind(func, obj);
544 }
545 obj = obj || src;
546 if (typeof(func) == "string") {
547 return function (nativeEvent) {
548 obj[func].apply(obj, [new E(src, nativeEvent)]);
549 };
550 } else {
551 return function (nativeEvent) {
552 func.apply(obj, [new E(src, nativeEvent)]);
553 };
554 }
555 },
556
557 _browserAlreadyHasMouseEnterAndLeave: function () {
558 return /MSIE/.test(navigator.userAgent);
559 },
560
561 _mouseEnterListener: function (src, sig, func, obj) {
562 var E = MochiKit.Signal.Event;
563 return function (nativeEvent) {
564 var e = new E(src, nativeEvent);
565 try {
566 e.relatedTarget().nodeName;
567 } catch (err) {
568 /* probably hit a permission denied error; possibly one of
569 * firefox's screwy anonymous DIVs inside an input element.
570 * Allow this event to propogate up.
571 */
572 return;
573 }
574 e.stop();
575 if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) {
576 /* We've moved between our node and a child. Ignore. */
577 return;
578 }
579 e.type = function () { return sig; };
580 if (typeof(func) == "string") {
581 return obj[func].apply(obj, [e]);
582 } else {
583 return func.apply(obj, [e]);
584 }
585 };
586 },
587
588 _getDestPair: function (objOrFunc, funcOrStr) {
589 var obj = null;
590 var func = null;
591 if (typeof(funcOrStr) != 'undefined') {
592 obj = objOrFunc;
593 func = funcOrStr;
594 if (typeof(funcOrStr) == 'string') {
595 if (typeof(objOrFunc[funcOrStr]) != "function") {
596 throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
597 }
598 } else if (typeof(funcOrStr) != 'function') {
599 throw new Error("'funcOrStr' must be a function or string");
600 }
601 } else if (typeof(objOrFunc) != "function") {
602 throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
603 } else {
604 func = objOrFunc;
605 }
606 return [obj, func];
607
608 },
609
610 /** @id MochiKit.Signal.connect */
611 connect: function (src, sig, objOrFunc/* optional */, funcOrStr) {
612 src = MochiKit.DOM.getElement(src);
613 var self = MochiKit.Signal;
614
615 if (typeof(sig) != 'string') {
616 throw new Error("'sig' must be a string");
617 }
618
619 var destPair = self._getDestPair(objOrFunc, funcOrStr);
620 var obj = destPair[0];
621 var func = destPair[1];
622 if (typeof(obj) == 'undefined' || obj === null) {
623 obj = src;
624 }
625
626 var isDOM = !!(src.addEventListener || src.attachEvent);
627 if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave")
628 && !self._browserAlreadyHasMouseEnterAndLeave()) {
629 var listener = self._mouseEnterListener(src, sig.substr(2), func, obj);
630 if (sig === "onmouseenter") {
631 sig = "onmouseover";
632 } else {
633 sig = "onmouseout";
634 }
635 } else {
636 var listener = self._listener(src, func, obj, isDOM);
637 }
638
639 if (src.addEventListener) {
640 src.addEventListener(sig.substr(2), listener, false);
641 } else if (src.attachEvent) {
642 src.attachEvent(sig, listener); // useCapture unsupported
643 }
644
645 var ident = [src, sig, listener, isDOM, objOrFunc, funcOrStr, true];
646 self._observers.push(ident);
647
648
649 if (!isDOM && typeof(src.__connect__) == 'function') {
650 var args = MochiKit.Base.extend([ident], arguments, 1);
651 src.__connect__.apply(src, args);
652 }
653
654
655 return ident;
656 },
657
658 _disconnect: function (ident) {
659 // already disconnected
660 if (!ident[6]) { return; }
661 ident[6] = false;
662 // check isDOM
663 if (!ident[3]) { return; }
664 var src = ident[0];
665 var sig = ident[1];
666 var listener = ident[2];
667 if (src.removeEventListener) {
668 src.removeEventListener(sig.substr(2), listener, false);
669 } else if (src.detachEvent) {
670 src.detachEvent(sig, listener); // useCapture unsupported
671 } else {
672 throw new Error("'src' must be a DOM element");
673 }
674 },
675
676 /** @id MochiKit.Signal.disconnect */
677 disconnect: function (ident) {
678 var self = MochiKit.Signal;
679 var observers = self._observers;
680 var m = MochiKit.Base;
681 if (arguments.length > 1) {
682 // compatibility API
683 var src = MochiKit.DOM.getElement(arguments[0]);
684 var sig = arguments[1];
685 var obj = arguments[2];
686 var func = arguments[3];
687 for (var i = observers.length - 1; i >= 0; i--) {
688 var o = observers[i];
689 if (o[0] === src && o[1] === sig && o[4] === obj && o[5] === func) {
690 self._disconnect(o);
691 if (!self._lock) {
692 observers.splice(i, 1);
693 } else {
694 self._dirty = true;
695 }
696 return true;
697 }
698 }
699 } else {
700 var idx = m.findIdentical(observers, ident);
701 if (idx >= 0) {
702 self._disconnect(ident);
703 if (!self._lock) {
704 observers.splice(idx, 1);
705 } else {
706 self._dirty = true;
707 }
708 return true;
709 }
710 }
711 return false;
712 },
713
714 /** @id MochiKit.Signal.disconnectAllTo */
715 disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) {
716 var self = MochiKit.Signal;
717 var observers = self._observers;
718 var disconnect = self._disconnect;
719 var locked = self._lock;
720 var dirty = self._dirty;
721 if (typeof(funcOrStr) === 'undefined') {
722 funcOrStr = null;
723 }
724 for (var i = observers.length - 1; i >= 0; i--) {
725 var ident = observers[i];
726 if (ident[4] === objOrFunc &&
727 (funcOrStr === null || ident[5] === funcOrStr)) {
728 disconnect(ident);
729 if (locked) {
730 dirty = true;
731 } else {
732 observers.splice(i, 1);
733 }
734 }
735 }
736 self._dirty = dirty;
737 },
738
739 /** @id MochiKit.Signal.disconnectAll */
740 disconnectAll: function (src/* optional */, sig) {
741 src = MochiKit.DOM.getElement(src);
742 var m = MochiKit.Base;
743 var signals = m.flattenArguments(m.extend(null, arguments, 1));
744 var self = MochiKit.Signal;
745 var disconnect = self._disconnect;
746 var observers = self._observers;
747 var i, ident;
748 var locked = self._lock;
749 var dirty = self._dirty;
750 if (signals.length === 0) {
751 // disconnect all
752 for (i = observers.length - 1; i >= 0; i--) {
753 ident = observers[i];
754 if (ident[0] === src) {
755 disconnect(ident);
756 if (!locked) {
757 observers.splice(i, 1);
758 } else {
759 dirty = true;
760 }
761 }
762 }
763 } else {
764 var sigs = {};
765 for (i = 0; i < signals.length; i++) {
766 sigs[signals[i]] = true;
767 }
768 for (i = observers.length - 1; i >= 0; i--) {
769 ident = observers[i];
770 if (ident[0] === src && ident[1] in sigs) {
771 disconnect(ident);
772 if (!locked) {
773 observers.splice(i, 1);
774 } else {
775 dirty = true;
776 }
777 }
778 }
779 }
780 self._dirty = dirty;
781 },
782
783 /** @id MochiKit.Signal.signal */
784 signal: function (src, sig) {
785 var self = MochiKit.Signal;
786 var observers = self._observers;
787 src = MochiKit.DOM.getElement(src);
788 var args = MochiKit.Base.extend(null, arguments, 2);
789 var errors = [];
790 self._lock = true;
791 for (var i = 0; i < observers.length; i++) {
792 var ident = observers[i];
793 if (ident[0] === src && ident[1] === sig) {
794 try {
795 ident[2].apply(src, args);
796 } catch (e) {
797 errors.push(e);
798 }
799 }
800 }
801 self._lock = false;
802 if (self._dirty) {
803 self._dirty = false;
804 for (var i = observers.length - 1; i >= 0; i--) {
805 if (!observers[i][6]) {
806 observers.splice(i, 1);
807 }
808 }
809 }
810 if (errors.length == 1) {
811 throw errors[0];
812 } else if (errors.length > 1) {
813 var e = new Error("Multiple errors thrown in handling 'sig', see errors property");
814 e.errors = errors;
815 throw e;
816 }
817 }
818
819});
820
821MochiKit.Signal.EXPORT_OK = [];
822
823MochiKit.Signal.EXPORT = [
824 'connect',
825 'disconnect',
826 'signal',
827 'disconnectAll',
828 'disconnectAllTo'
829];
830
831MochiKit.Signal.__new__ = function (win) {
832 var m = MochiKit.Base;
833 this._document = document;
834 this._window = win;
835 this._lock = false;
836 this._dirty = false;
837
838 try {
839 this.connect(window, 'onunload', this._unloadCache);
840 } catch (e) {
841 // pass: might not be a browser
842 }
843
844 this.EXPORT_TAGS = {
845 ':common': this.EXPORT,
846 ':all': m.concat(this.EXPORT, this.EXPORT_OK)
847 };
848
849 m.nameFunctions(this);
850};
851
852MochiKit.Signal.__new__(this);
853
854//
855// XXX: Internet Explorer blows
856//
857if (MochiKit.__export__) {
858 connect = MochiKit.Signal.connect;
859 disconnect = MochiKit.Signal.disconnect;
860 disconnectAll = MochiKit.Signal.disconnectAll;
861 signal = MochiKit.Signal.signal;
862}
863
864MochiKit.Base._exportSymbols(this, MochiKit.Signal);
diff --git a/frontend/beta/js/MochiKit/Sortable.js b/frontend/beta/js/MochiKit/Sortable.js
new file mode 100644
index 0000000..8976ec0
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Sortable.js
@@ -0,0 +1,589 @@
1/***
2Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
3 Mochi-ized By Thomas Herve (_firstname_@nimail.org)
4
5See scriptaculous.js for full license.
6
7***/
8
9if (typeof(dojo) != 'undefined') {
10 dojo.provide('MochiKit.Sortable');
11 dojo.require('MochiKit.Base');
12 dojo.require('MochiKit.DOM');
13 dojo.require('MochiKit.Iter');
14}
15
16if (typeof(JSAN) != 'undefined') {
17 JSAN.use("MochiKit.Base", []);
18 JSAN.use("MochiKit.DOM", []);
19 JSAN.use("MochiKit.Iter", []);
20}
21
22try {
23 if (typeof(MochiKit.Base) == 'undefined' ||
24 typeof(MochiKit.DOM) == 'undefined' ||
25 typeof(MochiKit.Iter) == 'undefined') {
26 throw "";
27 }
28} catch (e) {
29 throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!";
30}
31
32if (typeof(MochiKit.Sortable) == 'undefined') {
33 MochiKit.Sortable = {};
34}
35
36MochiKit.Sortable.NAME = 'MochiKit.Sortable';
37MochiKit.Sortable.VERSION = '1.4';
38
39MochiKit.Sortable.__repr__ = function () {
40 return '[' + this.NAME + ' ' + this.VERSION + ']';
41};
42
43MochiKit.Sortable.toString = function () {
44 return this.__repr__();
45};
46
47MochiKit.Sortable.EXPORT = [
48];
49
50MochiKit.Sortable.EXPORT_OK = [
51];
52
53MochiKit.Base.update(MochiKit.Sortable, {
54 /***
55
56 Manage sortables. Mainly use the create function to add a sortable.
57
58 ***/
59 sortables: {},
60
61 _findRootElement: function (element) {
62 while (element.tagName.toUpperCase() != "BODY") {
63 if (element.id && MochiKit.Sortable.sortables[element.id]) {
64 return element;
65 }
66 element = element.parentNode;
67 }
68 },
69
70 /** @id MochiKit.Sortable.options */
71 options: function (element) {
72 element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element));
73 if (!element) {
74 return;
75 }
76 return MochiKit.Sortable.sortables[element.id];
77 },
78
79 /** @id MochiKit.Sortable.destroy */
80 destroy: function (element){
81 var s = MochiKit.Sortable.options(element);
82 var b = MochiKit.Base;
83 var d = MochiKit.DragAndDrop;
84
85 if (s) {
86 MochiKit.Signal.disconnect(s.startHandle);
87 MochiKit.Signal.disconnect(s.endHandle);
88 b.map(function (dr) {
89 d.Droppables.remove(dr);
90 }, s.droppables);
91 b.map(function (dr) {
92 dr.destroy();
93 }, s.draggables);
94
95 delete MochiKit.Sortable.sortables[s.element.id];
96 }
97 },
98
99 /** @id MochiKit.Sortable.create */
100 create: function (element, options) {
101 element = MochiKit.DOM.getElement(element);
102 var self = MochiKit.Sortable;
103
104 /** @id MochiKit.Sortable.options */
105 options = MochiKit.Base.update({
106
107 /** @id MochiKit.Sortable.element */
108 element: element,
109
110 /** @id MochiKit.Sortable.tag */
111 tag: 'li', // assumes li children, override with tag: 'tagname'
112
113 /** @id MochiKit.Sortable.dropOnEmpty */
114 dropOnEmpty: false,
115
116 /** @id MochiKit.Sortable.tree */
117 tree: false,
118
119 /** @id MochiKit.Sortable.treeTag */
120 treeTag: 'ul',
121
122 /** @id MochiKit.Sortable.overlap */
123 overlap: 'vertical', // one of 'vertical', 'horizontal'
124
125 /** @id MochiKit.Sortable.constraint */
126 constraint: 'vertical', // one of 'vertical', 'horizontal', false
127 // also takes array of elements (or ids); or false
128
129 /** @id MochiKit.Sortable.containment */
130 containment: [element],
131
132 /** @id MochiKit.Sortable.handle */
133 handle: false, // or a CSS class
134
135 /** @id MochiKit.Sortable.only */
136 only: false,
137
138 /** @id MochiKit.Sortable.hoverclass */
139 hoverclass: null,
140
141 /** @id MochiKit.Sortable.ghosting */
142 ghosting: false,
143
144 /** @id MochiKit.Sortable.scroll */
145 scroll: false,
146
147 /** @id MochiKit.Sortable.scrollSensitivity */
148 scrollSensitivity: 20,
149
150 /** @id MochiKit.Sortable.scrollSpeed */
151 scrollSpeed: 15,
152
153 /** @id MochiKit.Sortable.format */
154 format: /^[^_]*_(.*)$/,
155
156 /** @id MochiKit.Sortable.onChange */
157 onChange: MochiKit.Base.noop,
158
159 /** @id MochiKit.Sortable.onUpdate */
160 onUpdate: MochiKit.Base.noop,
161
162 /** @id MochiKit.Sortable.accept */
163 accept: null
164 }, options);
165
166 // clear any old sortable with same element
167 self.destroy(element);
168
169 // build options for the draggables
170 var options_for_draggable = {
171 revert: true,
172 ghosting: options.ghosting,
173 scroll: options.scroll,
174 scrollSensitivity: options.scrollSensitivity,
175 scrollSpeed: options.scrollSpeed,
176 constraint: options.constraint,
177 handle: options.handle
178 };
179
180 if (options.starteffect) {
181 options_for_draggable.starteffect = options.starteffect;
182 }
183
184 if (options.reverteffect) {
185 options_for_draggable.reverteffect = options.reverteffect;
186 } else if (options.ghosting) {
187 options_for_draggable.reverteffect = function (innerelement) {
188 innerelement.style.top = 0;
189 innerelement.style.left = 0;
190 };
191 }
192
193 if (options.endeffect) {
194 options_for_draggable.endeffect = options.endeffect;
195 }
196
197 if (options.zindex) {
198 options_for_draggable.zindex = options.zindex;
199 }
200
201 // build options for the droppables
202 var options_for_droppable = {
203 overlap: options.overlap,
204 containment: options.containment,
205 hoverclass: options.hoverclass,
206 onhover: self.onHover,
207 tree: options.tree,
208 accept: options.accept
209 }
210
211 var options_for_tree = {
212 onhover: self.onEmptyHover,
213 overlap: options.overlap,
214 containment: options.containment,
215 hoverclass: options.hoverclass,
216 accept: options.accept
217 }
218
219 // fix for gecko engine
220 MochiKit.DOM.removeEmptyTextNodes(element);
221
222 options.draggables = [];
223 options.droppables = [];
224
225 // drop on empty handling
226 if (options.dropOnEmpty || options.tree) {
227 new MochiKit.DragAndDrop.Droppable(element, options_for_tree);
228 options.droppables.push(element);
229 }
230 MochiKit.Base.map(function (e) {
231 // handles are per-draggable
232 var handle = options.handle ?
233 MochiKit.DOM.getFirstElementByTagAndClassName(null,
234 options.handle, e) : e;
235 options.draggables.push(
236 new MochiKit.DragAndDrop.Draggable(e,
237 MochiKit.Base.update(options_for_draggable,
238 {handle: handle})));
239 new MochiKit.DragAndDrop.Droppable(e, options_for_droppable);
240 if (options.tree) {
241 e.treeNode = element;
242 }
243 options.droppables.push(e);
244 }, (self.findElements(element, options) || []));
245
246 if (options.tree) {
247 MochiKit.Base.map(function (e) {
248 new MochiKit.DragAndDrop.Droppable(e, options_for_tree);
249 e.treeNode = element;
250 options.droppables.push(e);
251 }, (self.findTreeElements(element, options) || []));
252 }
253
254 // keep reference
255 self.sortables[element.id] = options;
256
257 options.lastValue = self.serialize(element);
258 options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start',
259 MochiKit.Base.partial(self.onStart, element));
260 options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
261 MochiKit.Base.partial(self.onEnd, element));
262 },
263
264 /** @id MochiKit.Sortable.onStart */
265 onStart: function (element, draggable) {
266 var self = MochiKit.Sortable;
267 var options = self.options(element);
268 options.lastValue = self.serialize(options.element);
269 },
270
271 /** @id MochiKit.Sortable.onEnd */
272 onEnd: function (element, draggable) {
273 var self = MochiKit.Sortable;
274 self.unmark();
275 var options = self.options(element);
276 if (options.lastValue != self.serialize(options.element)) {
277 options.onUpdate(options.element);
278 }
279 },
280
281 // return all suitable-for-sortable elements in a guaranteed order
282
283 /** @id MochiKit.Sortable.findElements */
284 findElements: function (element, options) {
285 return MochiKit.Sortable.findChildren(
286 element, options.only, options.tree ? true : false, options.tag);
287 },
288
289 /** @id MochiKit.Sortable.findTreeElements */
290 findTreeElements: function (element, options) {
291 return MochiKit.Sortable.findChildren(
292 element, options.only, options.tree ? true : false, options.treeTag);
293 },
294
295 /** @id MochiKit.Sortable.findChildren */
296 findChildren: function (element, only, recursive, tagName) {
297 if (!element.hasChildNodes()) {
298 return null;
299 }
300 tagName = tagName.toUpperCase();
301 if (only) {
302 only = MochiKit.Base.flattenArray([only]);
303 }
304 var elements = [];
305 MochiKit.Base.map(function (e) {
306 if (e.tagName &&
307 e.tagName.toUpperCase() == tagName &&
308 (!only ||
309 MochiKit.Iter.some(only, function (c) {
310 return MochiKit.DOM.hasElementClass(e, c);
311 }))) {
312 elements.push(e);
313 }
314 if (recursive) {
315 var grandchildren = MochiKit.Sortable.findChildren(e, only, recursive, tagName);
316 if (grandchildren && grandchildren.length > 0) {
317 elements = elements.concat(grandchildren);
318 }
319 }
320 }, element.childNodes);
321 return elements;
322 },
323
324 /** @id MochiKit.Sortable.onHover */
325 onHover: function (element, dropon, overlap) {
326 if (MochiKit.DOM.isParent(dropon, element)) {
327 return;
328 }
329 var self = MochiKit.Sortable;
330
331 if (overlap > .33 && overlap < .66 && self.options(dropon).tree) {
332 return;
333 } else if (overlap > 0.5) {
334 self.mark(dropon, 'before');
335 if (dropon.previousSibling != element) {
336 var oldParentNode = element.parentNode;
337 element.style.visibility = 'hidden'; // fix gecko rendering
338 dropon.parentNode.insertBefore(element, dropon);
339 if (dropon.parentNode != oldParentNode) {
340 self.options(oldParentNode).onChange(element);
341 }
342 self.options(dropon.parentNode).onChange(element);
343 }
344 } else {
345 self.mark(dropon, 'after');
346 var nextElement = dropon.nextSibling || null;
347 if (nextElement != element) {
348 var oldParentNode = element.parentNode;
349 element.style.visibility = 'hidden'; // fix gecko rendering
350 dropon.parentNode.insertBefore(element, nextElement);
351 if (dropon.parentNode != oldParentNode) {
352 self.options(oldParentNode).onChange(element);
353 }
354 self.options(dropon.parentNode).onChange(element);
355 }
356 }
357 },
358
359 _offsetSize: function (element, type) {
360 if (type == 'vertical' || type == 'height') {
361 return element.offsetHeight;
362 } else {
363 return element.offsetWidth;
364 }
365 },
366
367 /** @id MochiKit.Sortable.onEmptyHover */
368 onEmptyHover: function (element, dropon, overlap) {
369 var oldParentNode = element.parentNode;
370 var self = MochiKit.Sortable;
371 var droponOptions = self.options(dropon);
372
373 if (!MochiKit.DOM.isParent(dropon, element)) {
374 var index;
375
376 var children = self.findElements(dropon, {tag: droponOptions.tag,
377 only: droponOptions.only});
378 var child = null;
379
380 if (children) {
381 var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
382
383 for (index = 0; index < children.length; index += 1) {
384 if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) {
385 offset -= self._offsetSize(children[index], droponOptions.overlap);
386 } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
387 child = index + 1 < children.length ? children[index + 1] : null;
388 break;
389 } else {
390 child = children[index];
391 break;
392 }
393 }
394 }
395
396 dropon.insertBefore(element, child);
397
398 self.options(oldParentNode).onChange(element);
399 droponOptions.onChange(element);
400 }
401 },
402
403 /** @id MochiKit.Sortable.unmark */
404 unmark: function () {
405 var m = MochiKit.Sortable._marker;
406 if (m) {
407 MochiKit.Style.hideElement(m);
408 }
409 },
410
411 /** @id MochiKit.Sortable.mark */
412 mark: function (dropon, position) {
413 // mark on ghosting only
414 var d = MochiKit.DOM;
415 var self = MochiKit.Sortable;
416 var sortable = self.options(dropon.parentNode);
417 if (sortable && !sortable.ghosting) {
418 return;
419 }
420
421 if (!self._marker) {
422 self._marker = d.getElement('dropmarker') ||
423 document.createElement('DIV');
424 MochiKit.Style.hideElement(self._marker);
425 d.addElementClass(self._marker, 'dropmarker');
426 self._marker.style.position = 'absolute';
427 document.getElementsByTagName('body').item(0).appendChild(self._marker);
428 }
429 var offsets = MochiKit.Position.cumulativeOffset(dropon);
430 self._marker.style.left = offsets.x + 'px';
431 self._marker.style.top = offsets.y + 'px';
432
433 if (position == 'after') {
434 if (sortable.overlap == 'horizontal') {
435 self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px';
436 } else {
437 self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px';
438 }
439 }
440 MochiKit.Style.showElement(self._marker);
441 },
442
443 _tree: function (element, options, parent) {
444 var self = MochiKit.Sortable;
445 var children = self.findElements(element, options) || [];
446
447 for (var i = 0; i < children.length; ++i) {
448 var match = children[i].id.match(options.format);
449
450 if (!match) {
451 continue;
452 }
453
454 var child = {
455 id: encodeURIComponent(match ? match[1] : null),
456 element: element,
457 parent: parent,
458 children: [],
459 position: parent.children.length,
460 container: self._findChildrenElement(children[i], options.treeTag.toUpperCase())
461 }
462
463 /* Get the element containing the children and recurse over it */
464 if (child.container) {
465 self._tree(child.container, options, child)
466 }
467
468 parent.children.push (child);
469 }
470
471 return parent;
472 },
473
474 /* Finds the first element of the given tag type within a parent element.
475 Used for finding the first LI[ST] within a L[IST]I[TEM].*/
476 _findChildrenElement: function (element, containerTag) {
477 if (element && element.hasChildNodes) {
478 containerTag = containerTag.toUpperCase();
479 for (var i = 0; i < element.childNodes.length; ++i) {
480 if (element.childNodes[i].tagName.toUpperCase() == containerTag) {
481 return element.childNodes[i];
482 }
483 }
484 }
485 return null;
486 },
487
488 /** @id MochiKit.Sortable.tree */
489 tree: function (element, options) {
490 element = MochiKit.DOM.getElement(element);
491 var sortableOptions = MochiKit.Sortable.options(element);
492 options = MochiKit.Base.update({
493 tag: sortableOptions.tag,
494 treeTag: sortableOptions.treeTag,
495 only: sortableOptions.only,
496 name: element.id,
497 format: sortableOptions.format
498 }, options || {});
499
500 var root = {
501 id: null,
502 parent: null,
503 children: new Array,
504 container: element,
505 position: 0
506 }
507
508 return MochiKit.Sortable._tree(element, options, root);
509 },
510
511 /**
512 * Specifies the sequence for the Sortable.
513 * @param {Node} element Element to use as the Sortable.
514 * @param {Object} newSequence New sequence to use.
515 * @param {Object} options Options to use fro the Sortable.
516 */
517 setSequence: function (element, newSequence, options) {
518 var self = MochiKit.Sortable;
519 var b = MochiKit.Base;
520 element = MochiKit.DOM.getElement(element);
521 options = b.update(self.options(element), options || {});
522
523 var nodeMap = {};
524 b.map(function (n) {
525 var m = n.id.match(options.format);
526 if (m) {
527 nodeMap[m[1]] = [n, n.parentNode];
528 }
529 n.parentNode.removeChild(n);
530 }, self.findElements(element, options));
531
532 b.map(function (ident) {
533 var n = nodeMap[ident];
534 if (n) {
535 n[1].appendChild(n[0]);
536 delete nodeMap[ident];
537 }
538 }, newSequence);
539 },
540
541 /* Construct a [i] index for a particular node */
542 _constructIndex: function (node) {
543 var index = '';
544 do {
545 if (node.id) {
546 index = '[' + node.position + ']' + index;
547 }
548 } while ((node = node.parent) != null);
549 return index;
550 },
551
552 /** @id MochiKit.Sortable.sequence */
553 sequence: function (element, options) {
554 element = MochiKit.DOM.getElement(element);
555 var self = MochiKit.Sortable;
556 var options = MochiKit.Base.update(self.options(element), options || {});
557
558 return MochiKit.Base.map(function (item) {
559 return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
560 }, MochiKit.DOM.getElement(self.findElements(element, options) || []));
561 },
562
563 /**
564 * Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest.
565 * These options override the Sortable options for the serialization only.
566 * @param {Node} element Element to serialize.
567 * @param {Object} options Serialization options.
568 */
569 serialize: function (element, options) {
570 element = MochiKit.DOM.getElement(element);
571 var self = MochiKit.Sortable;
572 options = MochiKit.Base.update(self.options(element), options || {});
573 var name = encodeURIComponent(options.name || element.id);
574
575 if (options.tree) {
576 return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) {
577 return [name + self._constructIndex(item) + "[id]=" +
578 encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
579 }, self.tree(element, options).children)).join('&');
580 } else {
581 return MochiKit.Base.map(function (item) {
582 return name + "[]=" + encodeURIComponent(item);
583 }, self.sequence(element, options)).join('&');
584 }
585 }
586});
587
588// trunk compatibility
589MochiKit.Sortable.Sortable = MochiKit.Sortable;
diff --git a/frontend/beta/js/MochiKit/Style.js b/frontend/beta/js/MochiKit/Style.js
new file mode 100644
index 0000000..6fdfbfb
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Style.js
@@ -0,0 +1,444 @@
1/***
2
3MochiKit.Style 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Style');
13 dojo.require('MochiKit.Base');
14 dojo.require('MochiKit.DOM');
15}
16if (typeof(JSAN) != 'undefined') {
17 JSAN.use('MochiKit.Base', []);
18}
19
20try {
21 if (typeof(MochiKit.Base) == 'undefined') {
22 throw '';
23 }
24} catch (e) {
25 throw 'MochiKit.Style depends on MochiKit.Base!';
26}
27
28try {
29 if (typeof(MochiKit.DOM) == 'undefined') {
30 throw '';
31 }
32} catch (e) {
33 throw 'MochiKit.Style depends on MochiKit.DOM!';
34}
35
36
37if (typeof(MochiKit.Style) == 'undefined') {
38 MochiKit.Style = {};
39}
40
41MochiKit.Style.NAME = 'MochiKit.Style';
42MochiKit.Style.VERSION = '1.4';
43MochiKit.Style.__repr__ = function () {
44 return '[' + this.NAME + ' ' + this.VERSION + ']';
45};
46MochiKit.Style.toString = function () {
47 return this.__repr__();
48};
49
50MochiKit.Style.EXPORT_OK = [];
51
52MochiKit.Style.EXPORT = [
53 'setStyle',
54 'setOpacity',
55 'getStyle',
56 'getElementDimensions',
57 'elementDimensions', // deprecated
58 'setElementDimensions',
59 'getElementPosition',
60 'elementPosition', // deprecated
61 'setElementPosition',
62 'setDisplayForElement',
63 'hideElement',
64 'showElement',
65 'getViewportDimensions',
66 'getViewportPosition',
67 'Dimensions',
68 'Coordinates'
69];
70
71
72/*
73
74 Dimensions
75
76*/
77/** @id MochiKit.Style.Dimensions */
78MochiKit.Style.Dimensions = function (w, h) {
79 this.w = w;
80 this.h = h;
81};
82
83MochiKit.Style.Dimensions.prototype.__repr__ = function () {
84 var repr = MochiKit.Base.repr;
85 return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}';
86};
87
88MochiKit.Style.Dimensions.prototype.toString = function () {
89 return this.__repr__();
90};
91
92
93/*
94
95 Coordinates
96
97*/
98/** @id MochiKit.Style.Coordinates */
99MochiKit.Style.Coordinates = function (x, y) {
100 this.x = x;
101 this.y = y;
102};
103
104MochiKit.Style.Coordinates.prototype.__repr__ = function () {
105 var repr = MochiKit.Base.repr;
106 return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}';
107};
108
109MochiKit.Style.Coordinates.prototype.toString = function () {
110 return this.__repr__();
111};
112
113
114MochiKit.Base.update(MochiKit.Style, {
115
116 /** @id MochiKit.Style.getStyle */
117 getStyle: function (elem, cssProperty) {
118 var dom = MochiKit.DOM;
119 var d = dom._document;
120
121 elem = dom.getElement(elem);
122 cssProperty = MochiKit.Base.camelize(cssProperty);
123
124 if (!elem || elem == d) {
125 return undefined;
126 }
127 if (cssProperty == 'opacity' && elem.filters) {
128 var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/);
129 if (opacity && opacity[1]) {
130 return parseFloat(opacity[1]) / 100;
131 }
132 return 1.0;
133 }
134 var value = elem.style ? elem.style[cssProperty] : null;
135 if (!value) {
136 if (d.defaultView && d.defaultView.getComputedStyle) {
137 var css = d.defaultView.getComputedStyle(elem, null);
138 cssProperty = cssProperty.replace(/([A-Z])/g, '-$1'
139 ).toLowerCase(); // from dojo.style.toSelectorCase
140 value = css ? css.getPropertyValue(cssProperty) : null;
141 } else if (elem.currentStyle) {
142 value = elem.currentStyle[cssProperty];
143 }
144 }
145 if (cssProperty == 'opacity') {
146 value = parseFloat(value);
147 }
148
149 if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
150 if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
151 value = 'auto';
152 }
153 }
154
155 return value == 'auto' ? null : value;
156 },
157
158 /** @id MochiKit.Style.setStyle */
159 setStyle: function (elem, style) {
160 elem = MochiKit.DOM.getElement(elem);
161 for (name in style) {
162 if (name == 'opacity') {
163 MochiKit.Style.setOpacity(elem, style[name]);
164 } else {
165 elem.style[MochiKit.Base.camelize(name)] = style[name];
166 }
167 }
168 },
169
170 /** @id MochiKit.Style.setOpacity */
171 setOpacity: function (elem, o) {
172 elem = MochiKit.DOM.getElement(elem);
173 var self = MochiKit.Style;
174 if (o == 1) {
175 var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
176 elem.style["opacity"] = toSet ? 0.999999 : 1.0;
177 if (/MSIE/.test(navigator.userAgent)) {
178 elem.style['filter'] =
179 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '');
180 }
181 } else {
182 if (o < 0.00001) {
183 o = 0;
184 }
185 elem.style["opacity"] = o;
186 if (/MSIE/.test(navigator.userAgent)) {
187 elem.style['filter'] =
188 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')';
189 }
190 }
191 },
192
193 /*
194
195 getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
196 Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
197 License: BSD, http://developer.yahoo.net/yui/license.txt
198
199 */
200
201 /** @id MochiKit.Style.getElementPosition */
202 getElementPosition: function (elem, /* optional */relativeTo) {
203 var self = MochiKit.Style;
204 var dom = MochiKit.DOM;
205 elem = dom.getElement(elem);
206
207 if (!elem ||
208 (!(elem.x && elem.y) &&
209 (!elem.parentNode === null ||
210 self.getStyle(elem, 'display') == 'none'))) {
211 return undefined;
212 }
213
214 var c = new self.Coordinates(0, 0);
215 var box = null;
216 var parent = null;
217
218 var d = MochiKit.DOM._document;
219 var de = d.documentElement;
220 var b = d.body;
221
222 if (!elem.parentNode && elem.x && elem.y) {
223 /* it's just a MochiKit.Style.Coordinates object */
224 c.x += elem.x || 0;
225 c.y += elem.y || 0;
226 } else if (elem.getBoundingClientRect) { // IE shortcut
227 /*
228
229 The IE shortcut can be off by two. We fix it. See:
230 http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
231
232 This is similar to the method used in
233 MochiKit.Signal.Event.mouse().
234
235 */
236 box = elem.getBoundingClientRect();
237
238 c.x += box.left +
239 (de.scrollLeft || b.scrollLeft) -
240 (de.clientLeft || 0);
241
242 c.y += box.top +
243 (de.scrollTop || b.scrollTop) -
244 (de.clientTop || 0);
245
246 } else if (elem.offsetParent) {
247 c.x += elem.offsetLeft;
248 c.y += elem.offsetTop;
249 parent = elem.offsetParent;
250
251 if (parent != elem) {
252 while (parent) {
253 c.x += parent.offsetLeft;
254 c.y += parent.offsetTop;
255 parent = parent.offsetParent;
256 }
257 }
258
259 /*
260
261 Opera < 9 and old Safari (absolute) incorrectly account for
262 body offsetTop and offsetLeft.
263
264 */
265 var ua = navigator.userAgent.toLowerCase();
266 if ((typeof(opera) != 'undefined' &&
267 parseFloat(opera.version()) < 9) ||
268 (ua.indexOf('AppleWebKit') != -1 &&
269 self.getStyle(elem, 'position') == 'absolute')) {
270
271 c.x -= b.offsetLeft;
272 c.y -= b.offsetTop;
273
274 }
275 }
276
277 if (typeof(relativeTo) != 'undefined') {
278 relativeTo = arguments.callee(relativeTo);
279 if (relativeTo) {
280 c.x -= (relativeTo.x || 0);
281 c.y -= (relativeTo.y || 0);
282 }
283 }
284
285 if (elem.parentNode) {
286 parent = elem.parentNode;
287 } else {
288 parent = null;
289 }
290
291 while (parent) {
292 var tagName = parent.tagName.toUpperCase();
293 if (tagName === 'BODY' || tagName === 'HTML') {
294 break;
295 }
296 var disp = self.getStyle(parent, 'display');
297 // Handle strange Opera bug for some display
298 if (disp != 'inline' && disp != 'table-row') {
299 c.x -= parent.scrollLeft;
300 c.y -= parent.scrollTop;
301 }
302 if (parent.parentNode) {
303 parent = parent.parentNode;
304 } else {
305 parent = null;
306 }
307 }
308
309 return c;
310 },
311
312 /** @id MochiKit.Style.setElementPosition */
313 setElementPosition: function (elem, newPos/* optional */, units) {
314 elem = MochiKit.DOM.getElement(elem);
315 if (typeof(units) == 'undefined') {
316 units = 'px';
317 }
318 var newStyle = {};
319 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
320 if (!isUndefNull(newPos.x)) {
321 newStyle['left'] = newPos.x + units;
322 }
323 if (!isUndefNull(newPos.y)) {
324 newStyle['top'] = newPos.y + units;
325 }
326 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
327 },
328
329 /** @id MochiKit.Style.getElementDimensions */
330 getElementDimensions: function (elem) {
331 var self = MochiKit.Style;
332 var dom = MochiKit.DOM;
333 if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
334 return new self.Dimensions(elem.w || 0, elem.h || 0);
335 }
336 elem = dom.getElement(elem);
337 if (!elem) {
338 return undefined;
339 }
340 var disp = self.getStyle(elem, 'display');
341 // display can be empty/undefined on WebKit/KHTML
342 if (disp != 'none' && disp !== '' && typeof(disp) != 'undefined') {
343 return new self.Dimensions(elem.offsetWidth || 0,
344 elem.offsetHeight || 0);
345 }
346 var s = elem.style;
347 var originalVisibility = s.visibility;
348 var originalPosition = s.position;
349 s.visibility = 'hidden';
350 s.position = 'absolute';
351 s.display = '';
352 var originalWidth = elem.offsetWidth;
353 var originalHeight = elem.offsetHeight;
354 s.display = 'none';
355 s.position = originalPosition;
356 s.visibility = originalVisibility;
357 return new self.Dimensions(originalWidth, originalHeight);
358 },
359
360 /** @id MochiKit.Style.setElementDimensions */
361 setElementDimensions: function (elem, newSize/* optional */, units) {
362 elem = MochiKit.DOM.getElement(elem);
363 if (typeof(units) == 'undefined') {
364 units = 'px';
365 }
366 var newStyle = {};
367 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
368 if (!isUndefNull(newSize.w)) {
369 newStyle['width'] = newSize.w + units;
370 }
371 if (!isUndefNull(newSize.h)) {
372 newStyle['height'] = newSize.h + units;
373 }
374 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
375 },
376
377 /** @id MochiKit.Style.setDisplayForElement */
378 setDisplayForElement: function (display, element/*, ...*/) {
379 var elements = MochiKit.Base.extend(null, arguments, 1);
380 var getElement = MochiKit.DOM.getElement;
381 for (var i = 0; i < elements.length; i++) {
382 element = getElement(elements[i]);
383 if (element) {
384 element.style.display = display;
385 }
386 }
387 },
388
389 /** @id MochiKit.Style.getViewportDimensions */
390 getViewportDimensions: function () {
391 var d = new MochiKit.Style.Dimensions();
392
393 var w = MochiKit.DOM._window;
394 var b = MochiKit.DOM._document.body;
395
396 if (w.innerWidth) {
397 d.w = w.innerWidth;
398 d.h = w.innerHeight;
399 } else if (b.parentElement.clientWidth) {
400 d.w = b.parentElement.clientWidth;
401 d.h = b.parentElement.clientHeight;
402 } else if (b && b.clientWidth) {
403 d.w = b.clientWidth;
404 d.h = b.clientHeight;
405 }
406 return d;
407 },
408
409 /** @id MochiKit.Style.getViewportPosition */
410 getViewportPosition: function () {
411 var c = new MochiKit.Style.Coordinates(0, 0);
412 var d = MochiKit.DOM._document;
413 var de = d.documentElement;
414 var db = d.body;
415 if (de && (de.scrollTop || de.scrollLeft)) {
416 c.x = de.scrollLeft;
417 c.y = de.scrollTop;
418 } else if (db) {
419 c.x = db.scrollLeft;
420 c.y = db.scrollTop;
421 }
422 return c;
423 },
424
425 __new__: function () {
426 var m = MochiKit.Base;
427
428 this.elementPosition = this.getElementPosition;
429 this.elementDimensions = this.getElementDimensions;
430
431 this.hideElement = m.partial(this.setDisplayForElement, 'none');
432 this.showElement = m.partial(this.setDisplayForElement, 'block');
433
434 this.EXPORT_TAGS = {
435 ':common': this.EXPORT,
436 ':all': m.concat(this.EXPORT, this.EXPORT_OK)
437 };
438
439 m.nameFunctions(this);
440 }
441});
442
443MochiKit.Style.__new__();
444MochiKit.Base._exportSymbols(this, MochiKit.Style);
diff --git a/frontend/beta/js/MochiKit/Test.js b/frontend/beta/js/MochiKit/Test.js
new file mode 100644
index 0000000..494a5b4
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Test.js
@@ -0,0 +1,181 @@
1/***
2
3MochiKit.Test 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Test');
13 dojo.require('MochiKit.Base');
14}
15
16if (typeof(JSAN) != 'undefined') {
17 JSAN.use("MochiKit.Base", []);
18}
19
20try {
21 if (typeof(MochiKit.Base) == 'undefined') {
22 throw "";
23 }
24} catch (e) {
25 throw "MochiKit.Test depends on MochiKit.Base!";
26}
27
28if (typeof(MochiKit.Test) == 'undefined') {
29 MochiKit.Test = {};
30}
31
32MochiKit.Test.NAME = "MochiKit.Test";
33MochiKit.Test.VERSION = "1.4";
34MochiKit.Test.__repr__ = function () {
35 return "[" + this.NAME + " " + this.VERSION + "]";
36};
37
38MochiKit.Test.toString = function () {
39 return this.__repr__();
40};
41
42
43MochiKit.Test.EXPORT = ["runTests"];
44MochiKit.Test.EXPORT_OK = [];
45
46MochiKit.Test.runTests = function (obj) {
47 if (typeof(obj) == "string") {
48 obj = JSAN.use(obj);
49 }
50 var suite = new MochiKit.Test.Suite();
51 suite.run(obj);
52};
53
54MochiKit.Test.Suite = function () {
55 this.testIndex = 0;
56 MochiKit.Base.bindMethods(this);
57};
58
59MochiKit.Test.Suite.prototype = {
60 run: function (obj) {
61 try {
62 obj(this);
63 } catch (e) {
64 this.traceback(e);
65 }
66 },
67 traceback: function (e) {
68 var items = MochiKit.Iter.sorted(MochiKit.Base.items(e));
69 print("not ok " + this.testIndex + " - Error thrown");
70 for (var i = 0; i < items.length; i++) {
71 var kv = items[i];
72 if (kv[0] == "stack") {
73 kv[1] = kv[1].split(/\n/)[0];
74 }
75 this.print("# " + kv.join(": "));
76 }
77 },
78 print: function (s) {
79 print(s);
80 },
81 is: function (got, expected, /* optional */message) {
82 var res = 1;
83 var msg = null;
84 try {
85 res = MochiKit.Base.compare(got, expected);
86 } catch (e) {
87 msg = "Can not compare " + typeof(got) + ":" + typeof(expected);
88 }
89 if (res) {
90 msg = "Expected value did not compare equal";
91 }
92 if (!res) {
93 return this.testResult(true, message);
94 }
95 return this.testResult(false, message,
96 [[msg], ["got:", got], ["expected:", expected]]);
97 },
98
99 testResult: function (pass, msg, failures) {
100 this.testIndex += 1;
101 if (pass) {
102 this.print("ok " + this.testIndex + " - " + msg);
103 return;
104 }
105 this.print("not ok " + this.testIndex + " - " + msg);
106 if (failures) {
107 for (var i = 0; i < failures.length; i++) {
108 this.print("# " + failures[i].join(" "));
109 }
110 }
111 },
112
113 isDeeply: function (got, expected, /* optional */message) {
114 var m = MochiKit.Base;
115 var res = 1;
116 try {
117 res = m.compare(got, expected);
118 } catch (e) {
119 // pass
120 }
121 if (res === 0) {
122 return this.ok(true, message);
123 }
124 var gk = m.keys(got);
125 var ek = m.keys(expected);
126 gk.sort();
127 ek.sort();
128 if (m.compare(gk, ek)) {
129 // differing keys
130 var cmp = {};
131 var i;
132 for (i = 0; i < gk.length; i++) {
133 cmp[gk[i]] = "got";
134 }
135 for (i = 0; i < ek.length; i++) {
136 if (ek[i] in cmp) {
137 delete cmp[ek[i]];
138 } else {
139 cmp[ek[i]] = "expected";
140 }
141 }
142 var diffkeys = m.keys(cmp);
143 diffkeys.sort();
144 var gotkeys = [];
145 var expkeys = [];
146 while (diffkeys.length) {
147 var k = diffkeys.shift();
148 if (k in Object.prototype) {
149 continue;
150 }
151 (cmp[k] == "got" ? gotkeys : expkeys).push(k);
152 }
153
154
155 }
156
157 return this.testResult((!res), msg,
158 (msg ? [["got:", got], ["expected:", expected]] : undefined)
159 );
160 },
161
162 ok: function (res, message) {
163 return this.testResult(res, message);
164 }
165};
166
167MochiKit.Test.__new__ = function () {
168 var m = MochiKit.Base;
169
170 this.EXPORT_TAGS = {
171 ":common": this.EXPORT,
172 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
173 };
174
175 m.nameFunctions(this);
176
177};
178
179MochiKit.Test.__new__();
180
181MochiKit.Base._exportSymbols(this, MochiKit.Test);
diff --git a/frontend/beta/js/MochiKit/Visual.js b/frontend/beta/js/MochiKit/Visual.js
new file mode 100644
index 0000000..914b3b4
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/Visual.js
@@ -0,0 +1,1976 @@
1/***
2
3MochiKit.Visual 1.4
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito and others. All rights Reserved.
8
9***/
10
11if (typeof(dojo) != 'undefined') {
12 dojo.provide('MochiKit.Visual');
13 dojo.require('MochiKit.Base');
14 dojo.require('MochiKit.DOM');
15 dojo.require('MochiKit.Style');
16 dojo.require('MochiKit.Color');
17 dojo.require('MochiKit.Position');
18}
19
20if (typeof(JSAN) != 'undefined') {
21 JSAN.use("MochiKit.Base", []);
22 JSAN.use("MochiKit.DOM", []);
23 JSAN.use("MochiKit.Style", []);
24 JSAN.use("MochiKit.Color", []);
25 JSAN.use("MochiKit.Position", []);
26}
27
28try {
29 if (typeof(MochiKit.Base) === 'undefined' ||
30 typeof(MochiKit.DOM) === 'undefined' ||
31 typeof(MochiKit.Style) === 'undefined' ||
32 typeof(MochiKit.Position) === 'undefined' ||
33 typeof(MochiKit.Color) === 'undefined') {
34 throw "";
35 }
36} catch (e) {
37 throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM, MochiKit.Style, MochiKit.Position and MochiKit.Color!";
38}
39
40if (typeof(MochiKit.Visual) == "undefined") {
41 MochiKit.Visual = {};
42}
43
44MochiKit.Visual.NAME = "MochiKit.Visual";
45MochiKit.Visual.VERSION = "1.4";
46
47MochiKit.Visual.__repr__ = function () {
48 return "[" + this.NAME + " " + this.VERSION + "]";
49};
50
51MochiKit.Visual.toString = function () {
52 return this.__repr__();
53};
54
55MochiKit.Visual._RoundCorners = function (e, options) {
56 e = MochiKit.DOM.getElement(e);
57 this._setOptions(options);
58 if (this.options.__unstable__wrapElement) {
59 e = this._doWrap(e);
60 }
61
62 var color = this.options.color;
63 var C = MochiKit.Color.Color;
64 if (this.options.color === "fromElement") {
65 color = C.fromBackground(e);
66 } else if (!(color instanceof C)) {
67 color = C.fromString(color);
68 }
69 this.isTransparent = (color.asRGB().a <= 0);
70
71 var bgColor = this.options.bgColor;
72 if (this.options.bgColor === "fromParent") {
73 bgColor = C.fromBackground(e.offsetParent);
74 } else if (!(bgColor instanceof C)) {
75 bgColor = C.fromString(bgColor);
76 }
77
78 this._roundCornersImpl(e, color, bgColor);
79};
80
81MochiKit.Visual._RoundCorners.prototype = {
82 _doWrap: function (e) {
83 var parent = e.parentNode;
84 var doc = MochiKit.DOM.currentDocument();
85 if (typeof(doc.defaultView) === "undefined"
86 || doc.defaultView === null) {
87 return e;
88 }
89 var style = doc.defaultView.getComputedStyle(e, null);
90 if (typeof(style) === "undefined" || style === null) {
91 return e;
92 }
93 var wrapper = MochiKit.DOM.DIV({"style": {
94 display: "block",
95 // convert padding to margin
96 marginTop: style.getPropertyValue("padding-top"),
97 marginRight: style.getPropertyValue("padding-right"),
98 marginBottom: style.getPropertyValue("padding-bottom"),
99 marginLeft: style.getPropertyValue("padding-left"),
100 // remove padding so the rounding looks right
101 padding: "0px"
102 /*
103 paddingRight: "0px",
104 paddingLeft: "0px"
105 */
106 }});
107 wrapper.innerHTML = e.innerHTML;
108 e.innerHTML = "";
109 e.appendChild(wrapper);
110 return e;
111 },
112
113 _roundCornersImpl: function (e, color, bgColor) {
114 if (this.options.border) {
115 this._renderBorder(e, bgColor);
116 }
117 if (this._isTopRounded()) {
118 this._roundTopCorners(e, color, bgColor);
119 }
120 if (this._isBottomRounded()) {
121 this._roundBottomCorners(e, color, bgColor);
122 }
123 },
124
125 _renderBorder: function (el, bgColor) {
126 var borderValue = "1px solid " + this._borderColor(bgColor);
127 var borderL = "border-left: " + borderValue;
128 var borderR = "border-right: " + borderValue;
129 var style = "style='" + borderL + ";" + borderR + "'";
130 el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>";
131 },
132
133 _roundTopCorners: function (el, color, bgColor) {
134 var corner = this._createCorner(bgColor);
135 for (var i = 0; i < this.options.numSlices; i++) {
136 corner.appendChild(
137 this._createCornerSlice(color, bgColor, i, "top")
138 );
139 }
140 el.style.paddingTop = 0;
141 el.insertBefore(corner, el.firstChild);
142 },
143
144 _roundBottomCorners: function (el, color, bgColor) {
145 var corner = this._createCorner(bgColor);
146 for (var i = (this.options.numSlices - 1); i >= 0; i--) {
147 corner.appendChild(
148 this._createCornerSlice(color, bgColor, i, "bottom")
149 );
150 }
151 el.style.paddingBottom = 0;
152 el.appendChild(corner);
153 },
154
155 _createCorner: function (bgColor) {
156 var dom = MochiKit.DOM;
157 return dom.DIV({style: {backgroundColor: bgColor.toString()}});
158 },
159
160 _createCornerSlice: function (color, bgColor, n, position) {
161 var slice = MochiKit.DOM.SPAN();
162
163 var inStyle = slice.style;
164 inStyle.backgroundColor = color.toString();
165 inStyle.display = "block";
166 inStyle.height = "1px";
167 inStyle.overflow = "hidden";
168 inStyle.fontSize = "1px";
169
170 var borderColor = this._borderColor(color, bgColor);
171 if (this.options.border && n === 0) {
172 inStyle.borderTopStyle = "solid";
173 inStyle.borderTopWidth = "1px";
174 inStyle.borderLeftWidth = "0px";
175 inStyle.borderRightWidth = "0px";
176 inStyle.borderBottomWidth = "0px";
177 // assumes css compliant box model
178 inStyle.height = "0px";
179 inStyle.borderColor = borderColor.toString();
180 } else if (borderColor) {
181 inStyle.borderColor = borderColor.toString();
182 inStyle.borderStyle = "solid";
183 inStyle.borderWidth = "0px 1px";
184 }
185
186 if (!this.options.compact && (n == (this.options.numSlices - 1))) {
187 inStyle.height = "2px";
188 }
189
190 this._setMargin(slice, n, position);
191 this._setBorder(slice, n, position);
192
193 return slice;
194 },
195
196 _setOptions: function (options) {
197 this.options = {
198 corners: "all",
199 color: "fromElement",
200 bgColor: "fromParent",
201 blend: true,
202 border: false,
203 compact: false,
204 __unstable__wrapElement: false
205 };
206 MochiKit.Base.update(this.options, options);
207
208 this.options.numSlices = (this.options.compact ? 2 : 4);
209 },
210
211 _whichSideTop: function () {
212 var corners = this.options.corners;
213 if (this._hasString(corners, "all", "top")) {
214 return "";
215 }
216
217 var has_tl = (corners.indexOf("tl") != -1);
218 var has_tr = (corners.indexOf("tr") != -1);
219 if (has_tl && has_tr) {
220 return "";
221 }
222 if (has_tl) {
223 return "left";
224 }
225 if (has_tr) {
226 return "right";
227 }
228 return "";
229 },
230
231 _whichSideBottom: function () {
232 var corners = this.options.corners;
233 if (this._hasString(corners, "all", "bottom")) {
234 return "";
235 }
236
237 var has_bl = (corners.indexOf('bl') != -1);
238 var has_br = (corners.indexOf('br') != -1);
239 if (has_bl && has_br) {
240 return "";
241 }
242 if (has_bl) {
243 return "left";
244 }
245 if (has_br) {
246 return "right";
247 }
248 return "";
249 },
250
251 _borderColor: function (color, bgColor) {
252 if (color == "transparent") {
253 return bgColor;
254 } else if (this.options.border) {
255 return this.options.border;
256 } else if (this.options.blend) {
257 return bgColor.blendedColor(color);
258 }
259 return "";
260 },
261
262
263 _setMargin: function (el, n, corners) {
264 var marginSize = this._marginSize(n) + "px";
265 var whichSide = (
266 corners == "top" ? this._whichSideTop() : this._whichSideBottom()
267 );
268 var style = el.style;
269
270 if (whichSide == "left") {
271 style.marginLeft = marginSize;
272 style.marginRight = "0px";
273 } else if (whichSide == "right") {
274 style.marginRight = marginSize;
275 style.marginLeft = "0px";
276 } else {
277 style.marginLeft = marginSize;
278 style.marginRight = marginSize;
279 }
280 },
281
282 _setBorder: function (el, n, corners) {
283 var borderSize = this._borderSize(n) + "px";
284 var whichSide = (
285 corners == "top" ? this._whichSideTop() : this._whichSideBottom()
286 );
287
288 var style = el.style;
289 if (whichSide == "left") {
290 style.borderLeftWidth = borderSize;
291 style.borderRightWidth = "0px";
292 } else if (whichSide == "right") {
293 style.borderRightWidth = borderSize;
294 style.borderLeftWidth = "0px";
295 } else {
296 style.borderLeftWidth = borderSize;
297 style.borderRightWidth = borderSize;
298 }
299 },
300
301 _marginSize: function (n) {
302 if (this.isTransparent) {
303 return 0;
304 }
305
306 var o = this.options;
307 if (o.compact && o.blend) {
308 var smBlendedMarginSizes = [1, 0];
309 return smBlendedMarginSizes[n];
310 } else if (o.compact) {
311 var compactMarginSizes = [2, 1];
312 return compactMarginSizes[n];
313 } else if (o.blend) {
314 var blendedMarginSizes = [3, 2, 1, 0];
315 return blendedMarginSizes[n];
316 } else {
317 var marginSizes = [5, 3, 2, 1];
318 return marginSizes[n];
319 }
320 },
321
322 _borderSize: function (n) {
323 var o = this.options;
324 var borderSizes;
325 if (o.compact && (o.blend || this.isTransparent)) {
326 return 1;
327 } else if (o.compact) {
328 borderSizes = [1, 0];
329 } else if (o.blend) {
330 borderSizes = [2, 1, 1, 1];
331 } else if (o.border) {
332 borderSizes = [0, 2, 0, 0];
333 } else if (this.isTransparent) {
334 borderSizes = [5, 3, 2, 1];
335 } else {
336 return 0;
337 }
338 return borderSizes[n];
339 },
340
341 _hasString: function (str) {
342 for (var i = 1; i< arguments.length; i++) {
343 if (str.indexOf(arguments[i]) != -1) {
344 return true;
345 }
346 }
347 return false;
348 },
349
350 _isTopRounded: function () {
351 return this._hasString(this.options.corners,
352 "all", "top", "tl", "tr"
353 );
354 },
355
356 _isBottomRounded: function () {
357 return this._hasString(this.options.corners,
358 "all", "bottom", "bl", "br"
359 );
360 },
361
362 _hasSingleTextChild: function (el) {
363 return (el.childNodes.length == 1 && el.childNodes[0].nodeType == 3);
364 }
365};
366
367/** @id MochiKit.Visual.roundElement */
368MochiKit.Visual.roundElement = function (e, options) {
369 new MochiKit.Visual._RoundCorners(e, options);
370};
371
372/** @id MochiKit.Visual.roundClass */
373MochiKit.Visual.roundClass = function (tagName, className, options) {
374 var elements = MochiKit.DOM.getElementsByTagAndClassName(
375 tagName, className
376 );
377 for (var i = 0; i < elements.length; i++) {
378 MochiKit.Visual.roundElement(elements[i], options);
379 }
380};
381
382/** @id MochiKit.Visual.tagifyText */
383MochiKit.Visual.tagifyText = function (element, /* optional */tagifyStyle) {
384 /***
385
386 Change a node text to character in tags.
387
388 @param tagifyStyle: the style to apply to character nodes, default to
389 'position: relative'.
390
391 ***/
392 tagifyStyle = tagifyStyle || 'position:relative';
393 if (/MSIE/.test(navigator.userAgent)) {
394 tagifyStyle += ';zoom:1';
395 }
396 element = MochiKit.DOM.getElement(element);
397 var ma = MochiKit.Base.map;
398 ma(function (child) {
399 if (child.nodeType == 3) {
400 ma(function (character) {
401 element.insertBefore(
402 MochiKit.DOM.SPAN({style: tagifyStyle},
403 character == ' ' ? String.fromCharCode(160) : character), child);
404 }, child.nodeValue.split(''));
405 MochiKit.DOM.removeElement(child);
406 }
407 }, element.childNodes);
408};
409
410/** @id MochiKit.Visual.forceRerendering */
411MochiKit.Visual.forceRerendering = function (element) {
412 try {
413 element = MochiKit.DOM.getElement(element);
414 var n = document.createTextNode(' ');
415 element.appendChild(n);
416 element.removeChild(n);
417 } catch(e) {
418 }
419};
420
421/** @id MochiKit.Visual.multiple */
422MochiKit.Visual.multiple = function (elements, effect, /* optional */options) {
423 /***
424
425 Launch the same effect subsequently on given elements.
426
427 ***/
428 options = MochiKit.Base.update({
429 speed: 0.1, delay: 0.0
430 }, options || {});
431 var masterDelay = options.delay;
432 var index = 0;
433 MochiKit.Base.map(function (innerelement) {
434 options.delay = index * options.speed + masterDelay;
435 new effect(innerelement, options);
436 index += 1;
437 }, elements);
438};
439
440MochiKit.Visual.PAIRS = {
441 'slide': ['slideDown', 'slideUp'],
442 'blind': ['blindDown', 'blindUp'],
443 'appear': ['appear', 'fade'],
444 'size': ['grow', 'shrink']
445};
446
447/** @id MochiKit.Visual.toggle */
448MochiKit.Visual.toggle = function (element, /* optional */effect, /* optional */options) {
449 /***
450
451 Toggle an item between two state depending of its visibility, making
452 a effect between these states. Default effect is 'appear', can be
453 'slide' or 'blind'.
454
455 ***/
456 element = MochiKit.DOM.getElement(element);
457 effect = (effect || 'appear').toLowerCase();
458 options = MochiKit.Base.update({
459 queue: {position: 'end', scope: (element.id || 'global'), limit: 1}
460 }, options || {});
461 var v = MochiKit.Visual;
462 v[element.style.display != 'none' ?
463 v.PAIRS[effect][1] : v.PAIRS[effect][0]](element, options);
464};
465
466/***
467
468Transitions: define functions calculating variations depending of a position.
469
470***/
471
472MochiKit.Visual.Transitions = {};
473
474/** @id MochiKit.Visual.Transitions.linear */
475MochiKit.Visual.Transitions.linear = function (pos) {
476 return pos;
477};
478
479/** @id MochiKit.Visual.Transitions.sinoidal */
480MochiKit.Visual.Transitions.sinoidal = function (pos) {
481 return (-Math.cos(pos*Math.PI)/2) + 0.5;
482};
483
484/** @id MochiKit.Visual.Transitions.reverse */
485MochiKit.Visual.Transitions.reverse = function (pos) {
486 return 1 - pos;
487};
488
489/** @id MochiKit.Visual.Transitions.flicker */
490MochiKit.Visual.Transitions.flicker = function (pos) {
491 return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
492};
493
494/** @id MochiKit.Visual.Transitions.wobble */
495MochiKit.Visual.Transitions.wobble = function (pos) {
496 return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
497};
498
499/** @id MochiKit.Visual.Transitions.pulse */
500MochiKit.Visual.Transitions.pulse = function (pos) {
501 return (Math.floor(pos*10) % 2 === 0 ?
502 (pos*10 - Math.floor(pos*10)) : 1 - (pos*10 - Math.floor(pos*10)));
503};
504
505/** @id MochiKit.Visual.Transitions.none */
506MochiKit.Visual.Transitions.none = function (pos) {
507 return 0;
508};
509
510/** @id MochiKit.Visual.Transitions.full */
511MochiKit.Visual.Transitions.full = function (pos) {
512 return 1;
513};
514
515/***
516
517Core effects
518
519***/
520
521MochiKit.Visual.ScopedQueue = function () {
522 var cls = arguments.callee;
523 if (!(this instanceof cls)) {
524 return new cls();
525 }
526 this.__init__();
527};
528
529MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype, {
530 __init__: function () {
531 this.effects = [];
532 this.interval = null;
533 },
534
535 /** @id MochiKit.Visual.ScopedQueue.prototype.add */
536 add: function (effect) {
537 var timestamp = new Date().getTime();
538
539 var position = (typeof(effect.options.queue) == 'string') ?
540 effect.options.queue : effect.options.queue.position;
541
542 var ma = MochiKit.Base.map;
543 switch (position) {
544 case 'front':
545 // move unstarted effects after this effect
546 ma(function (e) {
547 if (e.state == 'idle') {
548 e.startOn += effect.finishOn;
549 e.finishOn += effect.finishOn;
550 }
551 }, this.effects);
552 break;
553 case 'end':
554 var finish;
555 // start effect after last queued effect has finished
556 ma(function (e) {
557 var i = e.finishOn;
558 if (i >= (finish || i)) {
559 finish = i;
560 }
561 }, this.effects);
562 timestamp = finish || timestamp;
563 break;
564 case 'break':
565 ma(function (e) {
566 e.finalize();
567 }, this.effects);
568 break;
569 }
570
571 effect.startOn += timestamp;
572 effect.finishOn += timestamp;
573 if (!effect.options.queue.limit ||
574 this.effects.length < effect.options.queue.limit) {
575 this.effects.push(effect);
576 }
577
578 if (!this.interval) {
579 this.interval = this.startLoop(MochiKit.Base.bind(this.loop, this),
580 40);
581 }
582 },
583
584 /** @id MochiKit.Visual.ScopedQueue.prototype.startLoop */
585 startLoop: function (func, interval) {
586 return setInterval(func, interval);
587 },
588
589 /** @id MochiKit.Visual.ScopedQueue.prototype.remove */
590 remove: function (effect) {
591 this.effects = MochiKit.Base.filter(function (e) {
592 return e != effect;
593 }, this.effects);
594 if (!this.effects.length) {
595 this.stopLoop(this.interval);
596 this.interval = null;
597 }
598 },
599
600 /** @id MochiKit.Visual.ScopedQueue.prototype.stopLoop */
601 stopLoop: function (interval) {
602 clearInterval(interval);
603 },
604
605 /** @id MochiKit.Visual.ScopedQueue.prototype.loop */
606 loop: function () {
607 var timePos = new Date().getTime();
608 MochiKit.Base.map(function (effect) {
609 effect.loop(timePos);
610 }, this.effects);
611 }
612});
613
614MochiKit.Visual.Queues = {
615 instances: {},
616
617 get: function (queueName) {
618 if (typeof(queueName) != 'string') {
619 return queueName;
620 }
621
622 if (!this.instances[queueName]) {
623 this.instances[queueName] = new MochiKit.Visual.ScopedQueue();
624 }
625 return this.instances[queueName];
626 }
627};
628
629MochiKit.Visual.Queue = MochiKit.Visual.Queues.get('global');
630
631MochiKit.Visual.DefaultOptions = {
632 transition: MochiKit.Visual.Transitions.sinoidal,
633 duration: 1.0, // seconds
634 fps: 25.0, // max. 25fps due to MochiKit.Visual.Queue implementation
635 sync: false, // true for combining
636 from: 0.0,
637 to: 1.0,
638 delay: 0.0,
639 queue: 'parallel'
640};
641
642MochiKit.Visual.Base = function () {};
643
644MochiKit.Visual.Base.prototype = {
645 /***
646
647 Basic class for all Effects. Define a looping mechanism called for each step
648 of an effect. Don't instantiate it, only subclass it.
649
650 ***/
651
652 __class__ : MochiKit.Visual.Base,
653
654 /** @id MochiKit.Visual.Base.prototype.start */
655 start: function (options) {
656 var v = MochiKit.Visual;
657 this.options = MochiKit.Base.setdefault(options || {},
658 v.DefaultOptions);
659 this.currentFrame = 0;
660 this.state = 'idle';
661 this.startOn = this.options.delay*1000;
662 this.finishOn = this.startOn + (this.options.duration*1000);
663 this.event('beforeStart');
664 if (!this.options.sync) {
665 v.Queues.get(typeof(this.options.queue) == 'string' ?
666 'global' : this.options.queue.scope).add(this);
667 }
668 },
669
670 /** @id MochiKit.Visual.Base.prototype.loop */
671 loop: function (timePos) {
672 if (timePos >= this.startOn) {
673 if (timePos >= this.finishOn) {
674 return this.finalize();
675 }
676 var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
677 var frame =
678 Math.round(pos * this.options.fps * this.options.duration);
679 if (frame > this.currentFrame) {
680 this.render(pos);
681 this.currentFrame = frame;
682 }
683 }
684 },
685
686 /** @id MochiKit.Visual.Base.prototype.render */
687 render: function (pos) {
688 if (this.state == 'idle') {
689 this.state = 'running';
690 this.event('beforeSetup');
691 this.setup();
692 this.event('afterSetup');
693 }
694 if (this.state == 'running') {
695 if (this.options.transition) {
696 pos = this.options.transition(pos);
697 }
698 pos *= (this.options.to - this.options.from);
699 pos += this.options.from;
700 this.event('beforeUpdate');
701 this.update(pos);
702 this.event('afterUpdate');
703 }
704 },
705
706 /** @id MochiKit.Visual.Base.prototype.cancel */
707 cancel: function () {
708 if (!this.options.sync) {
709 MochiKit.Visual.Queues.get(typeof(this.options.queue) == 'string' ?
710 'global' : this.options.queue.scope).remove(this);
711 }
712 this.state = 'finished';
713 },
714
715 /** @id MochiKit.Visual.Base.prototype.finalize */
716 finalize: function () {
717 this.render(1.0);
718 this.cancel();
719 this.event('beforeFinish');
720 this.finish();
721 this.event('afterFinish');
722 },
723
724 setup: function () {
725 },
726
727 finish: function () {
728 },
729
730 update: function (position) {
731 },
732
733 /** @id MochiKit.Visual.Base.prototype.event */
734 event: function (eventName) {
735 if (this.options[eventName + 'Internal']) {
736 this.options[eventName + 'Internal'](this);
737 }
738 if (this.options[eventName]) {
739 this.options[eventName](this);
740 }
741 },
742
743 /** @id MochiKit.Visual.Base.prototype.repr */
744 repr: function () {
745 return '[' + this.__class__.NAME + ', options:' +
746 MochiKit.Base.repr(this.options) + ']';
747 }
748};
749
750 /** @id MochiKit.Visual.Parallel */
751MochiKit.Visual.Parallel = function (effects, options) {
752 var cls = arguments.callee;
753 if (!(this instanceof cls)) {
754 return new cls(effects, options);
755 }
756
757 this.__init__(effects, options);
758};
759
760MochiKit.Visual.Parallel.prototype = new MochiKit.Visual.Base();
761
762MochiKit.Base.update(MochiKit.Visual.Parallel.prototype, {
763 /***
764
765 Run multiple effects at the same time.
766
767 ***/
768
769 __class__ : MochiKit.Visual.Parallel,
770
771 __init__: function (effects, options) {
772 this.effects = effects || [];
773 this.start(options);
774 },
775
776 /** @id MochiKit.Visual.Parallel.prototype.update */
777 update: function (position) {
778 MochiKit.Base.map(function (effect) {
779 effect.render(position);
780 }, this.effects);
781 },
782
783 /** @id MochiKit.Visual.Parallel.prototype.finish */
784 finish: function () {
785 MochiKit.Base.map(function (effect) {
786 effect.finalize();
787 }, this.effects);
788 }
789});
790
791/** @id MochiKit.Visual.Opacity */
792MochiKit.Visual.Opacity = function (element, options) {
793 var cls = arguments.callee;
794 if (!(this instanceof cls)) {
795 return new cls(element, options);
796 }
797 this.__init__(element, options);
798};
799
800MochiKit.Visual.Opacity.prototype = new MochiKit.Visual.Base();
801
802MochiKit.Base.update(MochiKit.Visual.Opacity.prototype, {
803 /***
804
805 Change the opacity of an element.
806
807 @param options: 'from' and 'to' change the starting and ending opacities.
808 Must be between 0.0 and 1.0. Default to current opacity and 1.0.
809
810 ***/
811
812 __class__ : MochiKit.Visual.Opacity,
813
814 __init__: function (element, /* optional */options) {
815 var b = MochiKit.Base;
816 var s = MochiKit.Style;
817 this.element = MochiKit.DOM.getElement(element);
818 // make this work on IE on elements without 'layout'
819 if (this.element.currentStyle &&
820 (!this.element.currentStyle.hasLayout)) {
821 s.setStyle(this.element, {zoom: 1});
822 }
823 options = b.update({
824 from: s.getStyle(this.element, 'opacity') || 0.0,
825 to: 1.0
826 }, options || {});
827 this.start(options);
828 },
829
830 /** @id MochiKit.Visual.Opacity.prototype.update */
831 update: function (position) {
832 MochiKit.Style.setStyle(this.element, {'opacity': position});
833 }
834});
835
836/** @id MochiKit.Visual.Move.prototype */
837MochiKit.Visual.Move = function (element, options) {
838 var cls = arguments.callee;
839 if (!(this instanceof cls)) {
840 return new cls(element, options);
841 }
842 this.__init__(element, options);
843};
844
845MochiKit.Visual.Move.prototype = new MochiKit.Visual.Base();
846
847MochiKit.Base.update(MochiKit.Visual.Move.prototype, {
848 /***
849
850 Move an element between its current position to a defined position
851
852 @param options: 'x' and 'y' for final positions, default to 0, 0.
853
854 ***/
855
856 __class__ : MochiKit.Visual.Move,
857
858 __init__: function (element, /* optional */options) {
859 this.element = MochiKit.DOM.getElement(element);
860 options = MochiKit.Base.update({
861 x: 0,
862 y: 0,
863 mode: 'relative'
864 }, options || {});
865 this.start(options);
866 },
867
868 /** @id MochiKit.Visual.Move.prototype.setup */
869 setup: function () {
870 // Bug in Opera: Opera returns the 'real' position of a static element
871 // or relative element that does not have top/left explicitly set.
872 // ==> Always set top and left for position relative elements in your
873 // stylesheets (to 0 if you do not need them)
874 MochiKit.DOM.makePositioned(this.element);
875
876 var s = this.element.style;
877 var originalVisibility = s.visibility;
878 var originalDisplay = s.display;
879 if (originalDisplay == 'none') {
880 s.visibility = 'hidden';
881 s.display = '';
882 }
883
884 this.originalLeft = parseFloat(MochiKit.Style.getStyle(this.element, 'left') || '0');
885 this.originalTop = parseFloat(MochiKit.Style.getStyle(this.element, 'top') || '0');
886
887 if (this.options.mode == 'absolute') {
888 // absolute movement, so we need to calc deltaX and deltaY
889 this.options.x -= this.originalLeft;
890 this.options.y -= this.originalTop;
891 }
892 if (originalDisplay == 'none') {
893 s.visibility = originalVisibility;
894 s.display = originalDisplay;
895 }
896 },
897
898 /** @id MochiKit.Visual.Move.prototype.update */
899 update: function (position) {
900 MochiKit.Style.setStyle(this.element, {
901 left: Math.round(this.options.x * position + this.originalLeft) + 'px',
902 top: Math.round(this.options.y * position + this.originalTop) + 'px'
903 });
904 }
905});
906
907/** @id MochiKit.Visual.Scale */
908MochiKit.Visual.Scale = function (element, percent, options) {
909 var cls = arguments.callee;
910 if (!(this instanceof cls)) {
911 return new cls(element, percent, options);
912 }
913 this.__init__(element, percent, options);
914};
915
916MochiKit.Visual.Scale.prototype = new MochiKit.Visual.Base();
917
918MochiKit.Base.update(MochiKit.Visual.Scale.prototype, {
919 /***
920
921 Change the size of an element.
922
923 @param percent: final_size = percent*original_size
924
925 @param options: several options changing scale behaviour
926
927 ***/
928
929 __class__ : MochiKit.Visual.Scale,
930
931 __init__: function (element, percent, /* optional */options) {
932 this.element = MochiKit.DOM.getElement(element);
933 options = MochiKit.Base.update({
934 scaleX: true,
935 scaleY: true,
936 scaleContent: true,
937 scaleFromCenter: false,
938 scaleMode: 'box', // 'box' or 'contents' or {} with provided values
939 scaleFrom: 100.0,
940 scaleTo: percent
941 }, options || {});
942 this.start(options);
943 },
944
945 /** @id MochiKit.Visual.Scale.prototype.setup */
946 setup: function () {
947 this.restoreAfterFinish = this.options.restoreAfterFinish || false;
948 this.elementPositioning = MochiKit.Style.getStyle(this.element,
949 'position');
950
951 var ma = MochiKit.Base.map;
952 var b = MochiKit.Base.bind;
953 this.originalStyle = {};
954 ma(b(function (k) {
955 this.originalStyle[k] = this.element.style[k];
956 }, this), ['top', 'left', 'width', 'height', 'fontSize']);
957
958 this.originalTop = this.element.offsetTop;
959 this.originalLeft = this.element.offsetLeft;
960
961 var fontSize = MochiKit.Style.getStyle(this.element,
962 'font-size') || '100%';
963 ma(b(function (fontSizeType) {
964 if (fontSize.indexOf(fontSizeType) > 0) {
965 this.fontSize = parseFloat(fontSize);
966 this.fontSizeType = fontSizeType;
967 }
968 }, this), ['em', 'px', '%']);
969
970 this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
971
972 if (/^content/.test(this.options.scaleMode)) {
973 this.dims = [this.element.scrollHeight, this.element.scrollWidth];
974 } else if (this.options.scaleMode == 'box') {
975 this.dims = [this.element.offsetHeight, this.element.offsetWidth];
976 } else {
977 this.dims = [this.options.scaleMode.originalHeight,
978 this.options.scaleMode.originalWidth];
979 }
980 },
981
982 /** @id MochiKit.Visual.Scale.prototype.update */
983 update: function (position) {
984 var currentScale = (this.options.scaleFrom/100.0) +
985 (this.factor * position);
986 if (this.options.scaleContent && this.fontSize) {
987 MochiKit.Style.setStyle(this.element, {
988 fontSize: this.fontSize * currentScale + this.fontSizeType
989 });
990 }
991 this.setDimensions(this.dims[0] * currentScale,
992 this.dims[1] * currentScale);
993 },
994
995 /** @id MochiKit.Visual.Scale.prototype.finish */
996 finish: function () {
997 if (this.restoreAfterFinish) {
998 MochiKit.Style.setStyle(this.element, this.originalStyle);
999 }
1000 },
1001
1002 /** @id MochiKit.Visual.Scale.prototype.setDimensions */
1003 setDimensions: function (height, width) {
1004 var d = {};
1005 var r = Math.round;
1006 if (/MSIE/.test(navigator.userAgent)) {
1007 r = Math.ceil;
1008 }
1009 if (this.options.scaleX) {
1010 d.width = r(width) + 'px';
1011 }
1012 if (this.options.scaleY) {
1013 d.height = r(height) + 'px';
1014 }
1015 if (this.options.scaleFromCenter) {
1016 var topd = (height - this.dims[0])/2;
1017 var leftd = (width - this.dims[1])/2;
1018 if (this.elementPositioning == 'absolute') {
1019 if (this.options.scaleY) {
1020 d.top = this.originalTop - topd + 'px';
1021 }
1022 if (this.options.scaleX) {
1023 d.left = this.originalLeft - leftd + 'px';
1024 }
1025 } else {
1026 if (this.options.scaleY) {
1027 d.top = -topd + 'px';
1028 }
1029 if (this.options.scaleX) {
1030 d.left = -leftd + 'px';
1031 }
1032 }
1033 }
1034 MochiKit.Style.setStyle(this.element, d);
1035 }
1036});
1037
1038/** @id MochiKit.Visual.Highlight */
1039MochiKit.Visual.Highlight = function (element, options) {
1040 var cls = arguments.callee;
1041 if (!(this instanceof cls)) {
1042 return new cls(element, options);
1043 }
1044 this.__init__(element, options);
1045};
1046
1047MochiKit.Visual.Highlight.prototype = new MochiKit.Visual.Base();
1048
1049MochiKit.Base.update(MochiKit.Visual.Highlight.prototype, {
1050 /***
1051
1052 Highlight an item of the page.
1053
1054 @param options: 'startcolor' for choosing highlighting color, default
1055 to '#ffff99'.
1056
1057 ***/
1058
1059 __class__ : MochiKit.Visual.Highlight,
1060
1061 __init__: function (element, /* optional */options) {
1062 this.element = MochiKit.DOM.getElement(element);
1063 options = MochiKit.Base.update({
1064 startcolor: '#ffff99'
1065 }, options || {});
1066 this.start(options);
1067 },
1068
1069 /** @id MochiKit.Visual.Highlight.prototype.setup */
1070 setup: function () {
1071 var b = MochiKit.Base;
1072 var s = MochiKit.Style;
1073 // Prevent executing on elements not in the layout flow
1074 if (s.getStyle(this.element, 'display') == 'none') {
1075 this.cancel();
1076 return;
1077 }
1078 // Disable background image during the effect
1079 this.oldStyle = {
1080 backgroundImage: s.getStyle(this.element, 'background-image')
1081 };
1082 s.setStyle(this.element, {
1083 backgroundImage: 'none'
1084 });
1085
1086 if (!this.options.endcolor) {
1087 this.options.endcolor =
1088 MochiKit.Color.Color.fromBackground(this.element).toHexString();
1089 }
1090 if (b.isUndefinedOrNull(this.options.restorecolor)) {
1091 this.options.restorecolor = s.getStyle(this.element,
1092 'background-color');
1093 }
1094 // init color calculations
1095 this._base = b.map(b.bind(function (i) {
1096 return parseInt(
1097 this.options.startcolor.slice(i*2 + 1, i*2 + 3), 16);
1098 }, this), [0, 1, 2]);
1099 this._delta = b.map(b.bind(function (i) {
1100 return parseInt(this.options.endcolor.slice(i*2 + 1, i*2 + 3), 16)
1101 - this._base[i];
1102 }, this), [0, 1, 2]);
1103 },
1104
1105 /** @id MochiKit.Visual.Highlight.prototype.update */
1106 update: function (position) {
1107 var m = '#';
1108 MochiKit.Base.map(MochiKit.Base.bind(function (i) {
1109 m += MochiKit.Color.toColorPart(Math.round(this._base[i] +
1110 this._delta[i]*position));
1111 }, this), [0, 1, 2]);
1112 MochiKit.Style.setStyle(this.element, {
1113 backgroundColor: m
1114 });
1115 },
1116
1117 /** @id MochiKit.Visual.Highlight.prototype.finish */
1118 finish: function () {
1119 MochiKit.Style.setStyle(this.element,
1120 MochiKit.Base.update(this.oldStyle, {
1121 backgroundColor: this.options.restorecolor
1122 }));
1123 }
1124});
1125
1126/** @id MochiKit.Visual.ScrollTo */
1127MochiKit.Visual.ScrollTo = function (element, options) {
1128 var cls = arguments.callee;
1129 if (!(this instanceof cls)) {
1130 return new cls(element, options);
1131 }
1132 this.__init__(element, options);
1133};
1134
1135MochiKit.Visual.ScrollTo.prototype = new MochiKit.Visual.Base();
1136
1137MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype, {
1138 /***
1139
1140 Scroll to an element in the page.
1141
1142 ***/
1143
1144 __class__ : MochiKit.Visual.ScrollTo,
1145
1146 __init__: function (element, /* optional */options) {
1147 this.element = MochiKit.DOM.getElement(element);
1148 this.start(options || {});
1149 },
1150
1151 /** @id MochiKit.Visual.ScrollTo.prototype.setup */
1152 setup: function () {
1153 var p = MochiKit.Position;
1154 p.prepare();
1155 var offsets = p.cumulativeOffset(this.element);
1156 if (this.options.offset) {
1157 offsets.y += this.options.offset;
1158 }
1159 var max;
1160 if (window.innerHeight) {
1161 max = window.innerHeight - window.height;
1162 } else if (document.documentElement &&
1163 document.documentElement.clientHeight) {
1164 max = document.documentElement.clientHeight -
1165 document.body.scrollHeight;
1166 } else if (document.body) {
1167 max = document.body.clientHeight - document.body.scrollHeight;
1168 }
1169 this.scrollStart = p.windowOffset.y;
1170 this.delta = (offsets.y > max ? max : offsets.y) - this.scrollStart;
1171 },
1172
1173 /** @id MochiKit.Visual.ScrollTo.prototype.update */
1174 update: function (position) {
1175 var p = MochiKit.Position;
1176 p.prepare();
1177 window.scrollTo(p.windowOffset.x, this.scrollStart + (position * this.delta));
1178 }
1179});
1180
1181MochiKit.Visual.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1182
1183MochiKit.Visual.Morph = function (element, options) {
1184 var cls = arguments.callee;
1185 if (!(this instanceof cls)) {
1186 return new cls(element, options);
1187 }
1188 this.__init__(element, options);
1189};
1190
1191MochiKit.Visual.Morph.prototype = new MochiKit.Visual.Base();
1192
1193MochiKit.Base.update(MochiKit.Visual.Morph.prototype, {
1194 /***
1195
1196 Morph effect: make a transformation from current style to the given style,
1197 automatically making a transition between the two.
1198
1199 ***/
1200
1201 __class__ : MochiKit.Visual.Morph,
1202
1203 __init__: function (element, /* optional */options) {
1204 this.element = MochiKit.DOM.getElement(element);
1205 this.start(options || {});
1206 },
1207
1208 /** @id MochiKit.Visual.Morph.prototype.setup */
1209 setup: function () {
1210 var b = MochiKit.Base;
1211 var style = this.options.style;
1212 this.styleStart = {};
1213 this.styleEnd = {};
1214 this.units = {};
1215 var value, unit;
1216 for (var s in style) {
1217 value = style[s];
1218 s = b.camelize(s);
1219 if (MochiKit.Visual.CSS_LENGTH.test(value)) {
1220 var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
1221 value = parseFloat(components[1]);
1222 unit = (components.length == 3) ? components[2] : null;
1223 this.styleEnd[s] = value;
1224 this.units[s] = unit;
1225 value = MochiKit.Style.getStyle(this.element, s);
1226 components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
1227 value = parseFloat(components[1]);
1228 this.styleStart[s] = value;
1229 } else {
1230 var c = MochiKit.Color.Color;
1231 value = c.fromString(value);
1232 if (value) {
1233 this.units[s] = "color";
1234 this.styleEnd[s] = value.toHexString();
1235 value = MochiKit.Style.getStyle(this.element, s);
1236 this.styleStart[s] = c.fromString(value).toHexString();
1237
1238 this.styleStart[s] = b.map(b.bind(function (i) {
1239 return parseInt(
1240 this.styleStart[s].slice(i*2 + 1, i*2 + 3), 16);
1241 }, this), [0, 1, 2]);
1242 this.styleEnd[s] = b.map(b.bind(function (i) {
1243 return parseInt(
1244 this.styleEnd[s].slice(i*2 + 1, i*2 + 3), 16);
1245 }, this), [0, 1, 2]);
1246 }
1247 }
1248 }
1249 },
1250
1251 /** @id MochiKit.Visual.Morph.prototype.update */
1252 update: function (position) {
1253 var value;
1254 for (var s in this.styleStart) {
1255 if (this.units[s] == "color") {
1256 var m = '#';
1257 var start = this.styleStart[s];
1258 var end = this.styleEnd[s];
1259 MochiKit.Base.map(MochiKit.Base.bind(function (i) {
1260 m += MochiKit.Color.toColorPart(Math.round(start[i] +
1261 (end[i] - start[i])*position));
1262 }, this), [0, 1, 2]);
1263 this.element.style[s] = m;
1264 } else {
1265 value = this.styleStart[s] + Math.round((this.styleEnd[s] - this.styleStart[s]) * position * 1000) / 1000 + this.units[s];
1266 this.element.style[s] = value;
1267 }
1268 }
1269 }
1270});
1271
1272/***
1273
1274Combination effects.
1275
1276***/
1277
1278/** @id MochiKit.Visual.fade */
1279MochiKit.Visual.fade = function (element, /* optional */ options) {
1280 /***
1281
1282 Fade a given element: change its opacity and hide it in the end.
1283
1284 @param options: 'to' and 'from' to change opacity.
1285
1286 ***/
1287 var s = MochiKit.Style;
1288 var oldOpacity = s.getStyle(element, 'opacity');
1289 options = MochiKit.Base.update({
1290 from: s.getStyle(element, 'opacity') || 1.0,
1291 to: 0.0,
1292 afterFinishInternal: function (effect) {
1293 if (effect.options.to !== 0) {
1294 return;
1295 }
1296 s.hideElement(effect.element);
1297 s.setStyle(effect.element, {'opacity': oldOpacity});
1298 }
1299 }, options || {});
1300 return new MochiKit.Visual.Opacity(element, options);
1301};
1302
1303/** @id MochiKit.Visual.appear */
1304MochiKit.Visual.appear = function (element, /* optional */ options) {
1305 /***
1306
1307 Make an element appear.
1308
1309 @param options: 'to' and 'from' to change opacity.
1310
1311 ***/
1312 var s = MochiKit.Style;
1313 var v = MochiKit.Visual;
1314 options = MochiKit.Base.update({
1315 from: (s.getStyle(element, 'display') == 'none' ? 0.0 :
1316 s.getStyle(element, 'opacity') || 0.0),
1317 to: 1.0,
1318 // force Safari to render floated elements properly
1319 afterFinishInternal: function (effect) {
1320 v.forceRerendering(effect.element);
1321 },
1322 beforeSetupInternal: function (effect) {
1323 s.setStyle(effect.element, {'opacity': effect.options.from});
1324 s.showElement(effect.element);
1325 }
1326 }, options || {});
1327 return new v.Opacity(element, options);
1328};
1329
1330/** @id MochiKit.Visual.puff */
1331MochiKit.Visual.puff = function (element, /* optional */ options) {
1332 /***
1333
1334 'Puff' an element: grow it to double size, fading it and make it hidden.
1335
1336 ***/
1337 var s = MochiKit.Style;
1338 var v = MochiKit.Visual;
1339 element = MochiKit.DOM.getElement(element);
1340 var oldStyle = {
1341 position: s.getStyle(element, 'position'),
1342 top: element.style.top,
1343 left: element.style.left,
1344 width: element.style.width,
1345 height: element.style.height,
1346 opacity: s.getStyle(element, 'opacity')
1347 };
1348 options = MochiKit.Base.update({
1349 beforeSetupInternal: function (effect) {
1350 MochiKit.Position.absolutize(effect.effects[0].element);
1351 },
1352 afterFinishInternal: function (effect) {
1353 s.hideElement(effect.effects[0].element);
1354 s.setStyle(effect.effects[0].element, oldStyle);
1355 },
1356 scaleContent: true,
1357 scaleFromCenter: true
1358 }, options || {});
1359 return new v.Parallel(
1360 [new v.Scale(element, 200,
1361 {sync: true, scaleFromCenter: options.scaleFromCenter,
1362 scaleContent: options.scaleContent, restoreAfterFinish: true}),
1363 new v.Opacity(element, {sync: true, to: 0.0 })],
1364 options);
1365};
1366
1367/** @id MochiKit.Visual.blindUp */
1368MochiKit.Visual.blindUp = function (element, /* optional */ options) {
1369 /***
1370
1371 Blind an element up: change its vertical size to 0.
1372
1373 ***/
1374 var d = MochiKit.DOM;
1375 element = d.getElement(element);
1376 var elemClip = d.makeClipping(element);
1377 options = MochiKit.Base.update({
1378 scaleContent: false,
1379 scaleX: false,
1380 restoreAfterFinish: true,
1381 afterFinishInternal: function (effect) {
1382 MochiKit.Style.hideElement(effect.element);
1383 d.undoClipping(effect.element, elemClip);
1384 }
1385 }, options || {});
1386
1387 return new MochiKit.Visual.Scale(element, 0, options);
1388};
1389
1390/** @id MochiKit.Visual.blindDown */
1391MochiKit.Visual.blindDown = function (element, /* optional */ options) {
1392 /***
1393
1394 Blind an element down: restore its vertical size.
1395
1396 ***/
1397 var d = MochiKit.DOM;
1398 var s = MochiKit.Style;
1399 element = d.getElement(element);
1400 var elementDimensions = s.getElementDimensions(element);
1401 var elemClip;
1402 options = MochiKit.Base.update({
1403 scaleContent: false,
1404 scaleX: false,
1405 scaleFrom: 0,
1406 scaleMode: {originalHeight: elementDimensions.h,
1407 originalWidth: elementDimensions.w},
1408 restoreAfterFinish: true,
1409 afterSetupInternal: function (effect) {
1410 elemClip = d.makeClipping(effect.element);
1411 s.setStyle(effect.element, {height: '0px'});
1412 s.showElement(effect.element);
1413 },
1414 afterFinishInternal: function (effect) {
1415 d.undoClipping(effect.element, elemClip);
1416 }
1417 }, options || {});
1418 return new MochiKit.Visual.Scale(element, 100, options);
1419};
1420
1421/** @id MochiKit.Visual.switchOff */
1422MochiKit.Visual.switchOff = function (element, /* optional */ options) {
1423 /***
1424
1425 Apply a switch-off-like effect.
1426
1427 ***/
1428 var d = MochiKit.DOM;
1429 element = d.getElement(element);
1430 var oldOpacity = MochiKit.Style.getStyle(element, 'opacity');
1431 var elemClip;
1432 options = MochiKit.Base.update({
1433 duration: 0.3,
1434 scaleFromCenter: true,
1435 scaleX: false,
1436 scaleContent: false,
1437 restoreAfterFinish: true,
1438 beforeSetupInternal: function (effect) {
1439 d.makePositioned(effect.element);
1440 elemClip = d.makeClipping(effect.element);
1441 },
1442 afterFinishInternal: function (effect) {
1443 MochiKit.Style.hideElement(effect.element);
1444 d.undoClipping(effect.element, elemClip);
1445 d.undoPositioned(effect.element);
1446 MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity});
1447 }
1448 }, options || {});
1449 var v = MochiKit.Visual;
1450 return new v.appear(element, {
1451 duration: 0.4,
1452 from: 0,
1453 transition: v.Transitions.flicker,
1454 afterFinishInternal: function (effect) {
1455 new v.Scale(effect.element, 1, options);
1456 }
1457 });
1458};
1459
1460/** @id MochiKit.Visual.dropOut */
1461MochiKit.Visual.dropOut = function (element, /* optional */ options) {
1462 /***
1463
1464 Make an element fall and disappear.
1465
1466 ***/
1467 var d = MochiKit.DOM;
1468 var s = MochiKit.Style;
1469 element = d.getElement(element);
1470 var oldStyle = {
1471 top: s.getStyle(element, 'top'),
1472 left: s.getStyle(element, 'left'),
1473 opacity: s.getStyle(element, 'opacity')
1474 };
1475
1476 options = MochiKit.Base.update({
1477 duration: 0.5,
1478 distance: 100,
1479 beforeSetupInternal: function (effect) {
1480 d.makePositioned(effect.effects[0].element);
1481 },
1482 afterFinishInternal: function (effect) {
1483 s.hideElement(effect.effects[0].element);
1484 d.undoPositioned(effect.effects[0].element);
1485 s.setStyle(effect.effects[0].element, oldStyle);
1486 }
1487 }, options || {});
1488 var v = MochiKit.Visual;
1489 return new v.Parallel(
1490 [new v.Move(element, {x: 0, y: options.distance, sync: true}),
1491 new v.Opacity(element, {sync: true, to: 0.0})],
1492 options);
1493};
1494
1495/** @id MochiKit.Visual.shake */
1496MochiKit.Visual.shake = function (element, /* optional */ options) {
1497 /***
1498
1499 Move an element from left to right several times.
1500
1501 ***/
1502 var d = MochiKit.DOM;
1503 var v = MochiKit.Visual;
1504 var s = MochiKit.Style;
1505 element = d.getElement(element);
1506 options = MochiKit.Base.update({
1507 x: -20,
1508 y: 0,
1509 duration: 0.05,
1510 afterFinishInternal: function (effect) {
1511 d.undoPositioned(effect.element);
1512 s.setStyle(effect.element, oldStyle);
1513 }
1514 }, options || {});
1515 var oldStyle = {
1516 top: s.getStyle(element, 'top'),
1517 left: s.getStyle(element, 'left') };
1518 return new v.Move(element,
1519 {x: 20, y: 0, duration: 0.05, afterFinishInternal: function (effect) {
1520 new v.Move(effect.element,
1521 {x: -40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
1522 new v.Move(effect.element,
1523 {x: 40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
1524 new v.Move(effect.element,
1525 {x: -40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
1526 new v.Move(effect.element,
1527 {x: 40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
1528 new v.Move(effect.element, options
1529 ) }}) }}) }}) }}) }});
1530};
1531
1532/** @id MochiKit.Visual.slideDown */
1533MochiKit.Visual.slideDown = function (element, /* optional */ options) {
1534 /***
1535
1536 Slide an element down.
1537 It needs to have the content of the element wrapped in a container
1538 element with fixed height.
1539
1540 ***/
1541 var d = MochiKit.DOM;
1542 var b = MochiKit.Base;
1543 var s = MochiKit.Style;
1544 element = d.getElement(element);
1545 if (!element.firstChild) {
1546 throw "MochiKit.Visual.slideDown must be used on a element with a child";
1547 }
1548 d.removeEmptyTextNodes(element);
1549 var oldInnerBottom = s.getStyle(element.firstChild, 'bottom') || 0;
1550 var elementDimensions = s.getElementDimensions(element);
1551 var elemClip;
1552 options = b.update({
1553 scaleContent: false,
1554 scaleX: false,
1555 scaleFrom: 0,
1556 scaleMode: {originalHeight: elementDimensions.h,
1557 originalWidth: elementDimensions.w},
1558 restoreAfterFinish: true,
1559 afterSetupInternal: function (effect) {
1560 d.makePositioned(effect.element);
1561 d.makePositioned(effect.element.firstChild);
1562 if (/Opera/.test(navigator.userAgent)) {
1563 s.setStyle(effect.element, {top: ''});
1564 }
1565 elemClip = d.makeClipping(effect.element);
1566 s.setStyle(effect.element, {height: '0px'});
1567 s.showElement(effect.element);
1568 },
1569 afterUpdateInternal: function (effect) {
1570 s.setStyle(effect.element.firstChild,
1571 {bottom: (effect.dims[0] - effect.element.clientHeight) + 'px'});
1572 },
1573 afterFinishInternal: function (effect) {
1574 d.undoClipping(effect.element, elemClip);
1575 // IE will crash if child is undoPositioned first
1576 if (/MSIE/.test(navigator.userAgent)) {
1577 d.undoPositioned(effect.element);
1578 d.undoPositioned(effect.element.firstChild);
1579 } else {
1580 d.undoPositioned(effect.element.firstChild);
1581 d.undoPositioned(effect.element);
1582 }
1583 s.setStyle(effect.element.firstChild,
1584 {bottom: oldInnerBottom});
1585 }
1586 }, options || {});
1587
1588 return new MochiKit.Visual.Scale(element, 100, options);
1589};
1590
1591/** @id MochiKit.Visual.slideUp */
1592MochiKit.Visual.slideUp = function (element, /* optional */ options) {
1593 /***
1594
1595 Slide an element up.
1596 It needs to have the content of the element wrapped in a container
1597 element with fixed height.
1598
1599 ***/
1600 var d = MochiKit.DOM;
1601 var b = MochiKit.Base;
1602 var s = MochiKit.Style;
1603 element = d.getElement(element);
1604 if (!element.firstChild) {
1605 throw "MochiKit.Visual.slideUp must be used on a element with a child";
1606 }
1607 d.removeEmptyTextNodes(element);
1608 var oldInnerBottom = s.getStyle(element.firstChild, 'bottom');
1609 var elemClip;
1610 options = b.update({
1611 scaleContent: false,
1612 scaleX: false,
1613 scaleMode: 'box',
1614 scaleFrom: 100,
1615 restoreAfterFinish: true,
1616 beforeStartInternal: function (effect) {
1617 d.makePositioned(effect.element);
1618 d.makePositioned(effect.element.firstChild);
1619 if (/Opera/.test(navigator.userAgent)) {
1620 s.setStyle(effect.element, {top: ''});
1621 }
1622 elemClip = d.makeClipping(effect.element);
1623 s.showElement(effect.element);
1624 },
1625 afterUpdateInternal: function (effect) {
1626 s.setStyle(effect.element.firstChild,
1627 {bottom: (effect.dims[0] - effect.element.clientHeight) + 'px'});
1628 },
1629 afterFinishInternal: function (effect) {
1630 s.hideElement(effect.element);
1631 d.undoClipping(effect.element, elemClip);
1632 d.undoPositioned(effect.element.firstChild);
1633 d.undoPositioned(effect.element);
1634 s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom});
1635 }
1636 }, options || {});
1637 return new MochiKit.Visual.Scale(element, 0, options);
1638};
1639
1640// Bug in opera makes the TD containing this element expand for a instance
1641// after finish
1642/** @id MochiKit.Visual.squish */
1643MochiKit.Visual.squish = function (element, /* optional */ options) {
1644 /***
1645
1646 Reduce an element and make it disappear.
1647
1648 ***/
1649 var d = MochiKit.DOM;
1650 var b = MochiKit.Base;
1651 var elemClip;
1652 options = b.update({
1653 restoreAfterFinish: true,
1654 beforeSetupInternal: function (effect) {
1655 elemClip = d.makeClipping(effect.element);
1656 },
1657 afterFinishInternal: function (effect) {
1658 MochiKit.Style.hideElement(effect.element);
1659 d.undoClipping(effect.element, elemClip);
1660 }
1661 }, options || {});
1662
1663 return new MochiKit.Visual.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, options);
1664};
1665
1666/** @id MochiKit.Visual.grow */
1667MochiKit.Visual.grow = function (element, /* optional */ options) {
1668 /***
1669
1670 Grow an element to its original size. Make it zero-sized before
1671 if necessary.
1672
1673 ***/
1674 var d = MochiKit.DOM;
1675 var v = MochiKit.Visual;
1676 var s = MochiKit.Style;
1677 element = d.getElement(element);
1678 options = MochiKit.Base.update({
1679 direction: 'center',
1680 moveTransition: v.Transitions.sinoidal,
1681 scaleTransition: v.Transitions.sinoidal,
1682 opacityTransition: v.Transitions.full,
1683 scaleContent: true,
1684 scaleFromCenter: false
1685 }, options || {});
1686 var oldStyle = {
1687 top: element.style.top,
1688 left: element.style.left,
1689 height: element.style.height,
1690 width: element.style.width,
1691 opacity: s.getStyle(element, 'opacity')
1692 };
1693
1694 var dims = s.getElementDimensions(element);
1695 var initialMoveX, initialMoveY;
1696 var moveX, moveY;
1697
1698 switch (options.direction) {
1699 case 'top-left':
1700 initialMoveX = initialMoveY = moveX = moveY = 0;
1701 break;
1702 case 'top-right':
1703 initialMoveX = dims.w;
1704 initialMoveY = moveY = 0;
1705 moveX = -dims.w;
1706 break;
1707 case 'bottom-left':
1708 initialMoveX = moveX = 0;
1709 initialMoveY = dims.h;
1710 moveY = -dims.h;
1711 break;
1712 case 'bottom-right':
1713 initialMoveX = dims.w;
1714 initialMoveY = dims.h;
1715 moveX = -dims.w;
1716 moveY = -dims.h;
1717 break;
1718 case 'center':
1719 initialMoveX = dims.w / 2;
1720 initialMoveY = dims.h / 2;
1721 moveX = -dims.w / 2;
1722 moveY = -dims.h / 2;
1723 break;
1724 }
1725
1726 var optionsParallel = MochiKit.Base.update({
1727 beforeSetupInternal: function (effect) {
1728 s.setStyle(effect.effects[0].element, {height: '0px'});
1729 s.showElement(effect.effects[0].element);
1730 },
1731 afterFinishInternal: function (effect) {
1732 d.undoClipping(effect.effects[0].element);
1733 d.undoPositioned(effect.effects[0].element);
1734 s.setStyle(effect.effects[0].element, oldStyle);
1735 }
1736 }, options || {});
1737
1738 return new v.Move(element, {
1739 x: initialMoveX,
1740 y: initialMoveY,
1741 duration: 0.01,
1742 beforeSetupInternal: function (effect) {
1743 s.hideElement(effect.element);
1744 d.makeClipping(effect.element);
1745 d.makePositioned(effect.element);
1746 },
1747 afterFinishInternal: function (effect) {
1748 new v.Parallel(
1749 [new v.Opacity(effect.element, {
1750 sync: true, to: 1.0, from: 0.0,
1751 transition: options.opacityTransition
1752 }),
1753 new v.Move(effect.element, {
1754 x: moveX, y: moveY, sync: true,
1755 transition: options.moveTransition
1756 }),
1757 new v.Scale(effect.element, 100, {
1758 scaleMode: {originalHeight: dims.h,
1759 originalWidth: dims.w},
1760 sync: true,
1761 scaleFrom: /Opera/.test(navigator.userAgent) ? 1 : 0,
1762 transition: options.scaleTransition,
1763 scaleContent: options.scaleContent,
1764 scaleFromCenter: options.scaleFromCenter,
1765 restoreAfterFinish: true
1766 })
1767 ], optionsParallel
1768 );
1769 }
1770 });
1771};
1772
1773/** @id MochiKit.Visual.shrink */
1774MochiKit.Visual.shrink = function (element, /* optional */ options) {
1775 /***
1776
1777 Shrink an element and make it disappear.
1778
1779 ***/
1780 var d = MochiKit.DOM;
1781 var v = MochiKit.Visual;
1782 var s = MochiKit.Style;
1783 element = d.getElement(element);
1784 options = MochiKit.Base.update({
1785 direction: 'center',
1786 moveTransition: v.Transitions.sinoidal,
1787 scaleTransition: v.Transitions.sinoidal,
1788 opacityTransition: v.Transitions.none,
1789 scaleContent: true,
1790 scaleFromCenter: false
1791 }, options || {});
1792 var oldStyle = {
1793 top: element.style.top,
1794 left: element.style.left,
1795 height: element.style.height,
1796 width: element.style.width,
1797 opacity: s.getStyle(element, 'opacity')
1798 };
1799
1800 var dims = s.getElementDimensions(element);
1801 var moveX, moveY;
1802
1803 switch (options.direction) {
1804 case 'top-left':
1805 moveX = moveY = 0;
1806 break;
1807 case 'top-right':
1808 moveX = dims.w;
1809 moveY = 0;
1810 break;
1811 case 'bottom-left':
1812 moveX = 0;
1813 moveY = dims.h;
1814 break;
1815 case 'bottom-right':
1816 moveX = dims.w;
1817 moveY = dims.h;
1818 break;
1819 case 'center':
1820 moveX = dims.w / 2;
1821 moveY = dims.h / 2;
1822 break;
1823 }
1824 var elemClip;
1825
1826 var optionsParallel = MochiKit.Base.update({
1827 beforeStartInternal: function (effect) {
1828 elemClip = d.makePositioned(effect.effects[0].element);
1829 d.makeClipping(effect.effects[0].element);
1830 },
1831 afterFinishInternal: function (effect) {
1832 s.hideElement(effect.effects[0].element);
1833 d.undoClipping(effect.effects[0].element, elemClip);
1834 d.undoPositioned(effect.effects[0].element);
1835 s.setStyle(effect.effects[0].element, oldStyle);
1836 }
1837 }, options || {});
1838
1839 return new v.Parallel(
1840 [new v.Opacity(element, {
1841 sync: true, to: 0.0, from: 1.0,
1842 transition: options.opacityTransition
1843 }),
1844 new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
1845 sync: true, transition: options.scaleTransition,
1846 scaleContent: options.scaleContent,
1847 scaleFromCenter: options.scaleFromCenter,
1848 restoreAfterFinish: true
1849 }),
1850 new v.Move(element, {
1851 x: moveX, y: moveY, sync: true, transition: options.moveTransition
1852 })
1853 ], optionsParallel
1854 );
1855};
1856
1857/** @id MochiKit.Visual.pulsate */
1858MochiKit.Visual.pulsate = function (element, /* optional */ options) {
1859 /***
1860
1861 Pulse an element between appear/fade.
1862
1863 ***/
1864 var d = MochiKit.DOM;
1865 var v = MochiKit.Visual;
1866 var b = MochiKit.Base;
1867 var oldOpacity = MochiKit.Style.getStyle(element, 'opacity');
1868 options = b.update({
1869 duration: 3.0,
1870 from: 0,
1871 afterFinishInternal: function (effect) {
1872 MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity});
1873 }
1874 }, options || {});
1875 var transition = options.transition || v.Transitions.sinoidal;
1876 var reverser = b.bind(function (pos) {
1877 return transition(1 - v.Transitions.pulse(pos));
1878 }, transition);
1879 b.bind(reverser, transition);
1880 return new v.Opacity(element, b.update({
1881 transition: reverser}, options));
1882};
1883
1884/** @id MochiKit.Visual.fold */
1885MochiKit.Visual.fold = function (element, /* optional */ options) {
1886 /***
1887
1888 Fold an element, first vertically, then horizontally.
1889
1890 ***/
1891 var d = MochiKit.DOM;
1892 var v = MochiKit.Visual;
1893 var s = MochiKit.Style;
1894 element = d.getElement(element);
1895 var oldStyle = {
1896 top: element.style.top,
1897 left: element.style.left,
1898 width: element.style.width,
1899 height: element.style.height
1900 };
1901 var elemClip = d.makeClipping(element);
1902 options = MochiKit.Base.update({
1903 scaleContent: false,
1904 scaleX: false,
1905 afterFinishInternal: function (effect) {
1906 new v.Scale(element, 1, {
1907 scaleContent: false,
1908 scaleY: false,
1909 afterFinishInternal: function (effect) {
1910 s.hideElement(effect.element);
1911 d.undoClipping(effect.element, elemClip);
1912 s.setStyle(effect.element, oldStyle);
1913 }
1914 });
1915 }
1916 }, options || {});
1917 return new v.Scale(element, 5, options);
1918};
1919
1920
1921// Compatibility with MochiKit 1.0
1922MochiKit.Visual.Color = MochiKit.Color.Color;
1923MochiKit.Visual.getElementsComputedStyle = MochiKit.DOM.computedStyle;
1924
1925/* end of Rico adaptation */
1926
1927MochiKit.Visual.__new__ = function () {
1928 var m = MochiKit.Base;
1929
1930 m.nameFunctions(this);
1931
1932 this.EXPORT_TAGS = {
1933 ":common": this.EXPORT,
1934 ":all": m.concat(this.EXPORT, this.EXPORT_OK)
1935 };
1936
1937};
1938
1939MochiKit.Visual.EXPORT = [
1940 "roundElement",
1941 "roundClass",
1942 "tagifyText",
1943 "multiple",
1944 "toggle",
1945 "Parallel",
1946 "Opacity",
1947 "Move",
1948 "Scale",
1949 "Highlight",
1950 "ScrollTo",
1951 "Morph",
1952 "fade",
1953 "appear",
1954 "puff",
1955 "blindUp",
1956 "blindDown",
1957 "switchOff",
1958 "dropOut",
1959 "shake",
1960 "slideDown",
1961 "slideUp",
1962 "squish",
1963 "grow",
1964 "shrink",
1965 "pulsate",
1966 "fold"
1967];
1968
1969MochiKit.Visual.EXPORT_OK = [
1970 "Base",
1971 "PAIRS"
1972];
1973
1974MochiKit.Visual.__new__();
1975
1976MochiKit.Base._exportSymbols(this, MochiKit.Visual);
diff --git a/frontend/beta/js/MochiKit/__package__.js b/frontend/beta/js/MochiKit/__package__.js
new file mode 100644
index 0000000..8d644b1
--- a/dev/null
+++ b/frontend/beta/js/MochiKit/__package__.js
@@ -0,0 +1,18 @@
1dojo.kwCompoundRequire({
2 "common": [
3 "MochiKit.Base",
4 "MochiKit.Iter",
5 "MochiKit.Logging",
6 "MochiKit.DateTime",
7 "MochiKit.Format",
8 "MochiKit.Async",
9 "MochiKit.DOM",
10 "MochiKit.Style",
11 "MochiKit.LoggingPane",
12 "MochiKit.Color",
13 "MochiKit.Signal",
14 "MochiKit.Position",
15 "MochiKit.Visual"
16 ]
17});
18dojo.provide("MochiKit.*");