summaryrefslogtreecommitdiff
path: root/frontend/gamma/js/MochiKit
authorGiulio Cesare Solaroli <giulio.cesare@clipperz.com>2011-10-02 23:56:18 (UTC)
committer Giulio Cesare Solaroli <giulio.cesare@clipperz.com>2011-10-02 23:56:18 (UTC)
commitef68436ac04da078ffdcacd7e1f785473a303d45 (patch) (unidiff)
treec403752d66a2c4775f00affd4fa8431b29c5b68c /frontend/gamma/js/MochiKit
parent597ecfbc0249d83e1b856cbd558340c01237a360 (diff)
downloadclipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.zip
clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.gz
clipperz-ef68436ac04da078ffdcacd7e1f785473a303d45.tar.bz2
First version of the newly restructured repository
Diffstat (limited to 'frontend/gamma/js/MochiKit') (more/less context) (show whitespace changes)
-rw-r--r--frontend/gamma/js/MochiKit/Async.js640
-rw-r--r--frontend/gamma/js/MochiKit/Base.js1452
-rw-r--r--frontend/gamma/js/MochiKit/Color.js832
-rw-r--r--frontend/gamma/js/MochiKit/DOM.js1144
-rw-r--r--frontend/gamma/js/MochiKit/DateTime.js173
-rw-r--r--frontend/gamma/js/MochiKit/DragAndDrop.js766
-rw-r--r--frontend/gamma/js/MochiKit/Format.js309
-rw-r--r--frontend/gamma/js/MochiKit/Iter.js790
-rw-r--r--frontend/gamma/js/MochiKit/Logging.js262
-rw-r--r--frontend/gamma/js/MochiKit/LoggingPane.js327
-rw-r--r--frontend/gamma/js/MochiKit/MochiKit.js136
-rw-r--r--frontend/gamma/js/MochiKit/MockDOM.js115
-rw-r--r--frontend/gamma/js/MochiKit/Position.js218
-rw-r--r--frontend/gamma/js/MochiKit/Selector.js387
-rw-r--r--frontend/gamma/js/MochiKit/Signal.js888
-rw-r--r--frontend/gamma/js/MochiKit/Sortable.js569
-rw-r--r--frontend/gamma/js/MochiKit/Style.js558
-rw-r--r--frontend/gamma/js/MochiKit/Test.js144
-rw-r--r--frontend/gamma/js/MochiKit/Text.js577
-rw-r--r--frontend/gamma/js/MochiKit/Visual.js1975
-rw-r--r--frontend/gamma/js/MochiKit/__package__.js18
21 files changed, 12280 insertions, 0 deletions
diff --git a/frontend/gamma/js/MochiKit/Async.js b/frontend/gamma/js/MochiKit/Async.js
new file mode 100644
index 0000000..c7408e7
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Async.js
@@ -0,0 +1,640 @@
1/***
2
3MochiKit.Async 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('Async', '1.5', ['Base']);
12
13/** @id MochiKit.Async.Deferred */
14MochiKit.Async.Deferred = function (/* optional */ canceller) {
15 this.chain = [];
16 this.id = this._nextId();
17 this.fired = -1;
18 this.paused = 0;
19 this.results = [null, null];
20 this.canceller = canceller;
21 this.silentlyCancelled = false;
22 this.chained = false;
23};
24
25MochiKit.Async.Deferred.prototype = {
26 /** @id MochiKit.Async.Deferred.prototype.repr */
27 repr: function () {
28 var state;
29 if (this.fired == -1) {
30 state = 'unfired';
31 } else if (this.fired === 0) {
32 state = 'success';
33 } else {
34 state = 'error';
35 }
36 return 'Deferred(' + this.id + ', ' + state + ')';
37 },
38
39 toString: MochiKit.Base.forwardCall("repr"),
40
41 _nextId: MochiKit.Base.counter(),
42
43 /** @id MochiKit.Async.Deferred.prototype.cancel */
44 cancel: function () {
45 var self = MochiKit.Async;
46 if (this.fired == -1) {
47 if (this.canceller) {
48 this.canceller(this);
49 } else {
50 this.silentlyCancelled = true;
51 }
52 if (this.fired == -1) {
53 this.errback(new self.CancelledError(this));
54 }
55 } else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) {
56 this.results[0].cancel();
57 }
58 },
59
60 _resback: function (res) {
61 /***
62
63 The primitive that means either callback or errback
64
65 ***/
66 this.fired = ((res instanceof Error) ? 1 : 0);
67 this.results[this.fired] = res;
68 this._fire();
69 },
70
71 _check: function () {
72 if (this.fired != -1) {
73 if (!this.silentlyCancelled) {
74 throw new MochiKit.Async.AlreadyCalledError(this);
75 }
76 this.silentlyCancelled = false;
77 return;
78 }
79 },
80
81 /** @id MochiKit.Async.Deferred.prototype.callback */
82 callback: function (res) {
83 this._check();
84 if (res instanceof MochiKit.Async.Deferred) {
85 throw new Error("Deferred instances can only be chained if they are the result of a callback");
86 }
87 this._resback(res);
88 },
89
90 /** @id MochiKit.Async.Deferred.prototype.errback */
91 errback: function (res) {
92 this._check();
93 var self = MochiKit.Async;
94 if (res instanceof self.Deferred) {
95 throw new Error("Deferred instances can only be chained if they are the result of a callback");
96 }
97 if (!(res instanceof Error)) {
98 res = new self.GenericError(res);
99 }
100 this._resback(res);
101 },
102
103 /** @id MochiKit.Async.Deferred.prototype.addBoth */
104 addBoth: function (fn) {
105 if (arguments.length > 1) {
106 fn = MochiKit.Base.partial.apply(null, arguments);
107 }
108 return this.addCallbacks(fn, fn);
109 },
110
111 /** @id MochiKit.Async.Deferred.prototype.addCallback */
112 addCallback: function (fn) {
113 if (arguments.length > 1) {
114 fn = MochiKit.Base.partial.apply(null, arguments);
115 }
116 return this.addCallbacks(fn, null);
117 },
118
119 /** @id MochiKit.Async.Deferred.prototype.addErrback */
120 addErrback: function (fn) {
121 if (arguments.length > 1) {
122 fn = MochiKit.Base.partial.apply(null, arguments);
123 }
124 return this.addCallbacks(null, fn);
125 },
126
127 /** @id MochiKit.Async.Deferred.prototype.addCallbacks */
128 addCallbacks: function (cb, eb) {
129 if (this.chained) {
130 throw new Error("Chained Deferreds can not be re-used");
131 }
132 this.chain.push([cb, eb]);
133 if (this.fired >= 0) {
134 this._fire();
135 }
136 return this;
137 },
138
139 _fire: function () {
140 /***
141
142 Used internally to exhaust the callback sequence when a result
143 is available.
144
145 ***/
146 var chain = this.chain;
147 var fired = this.fired;
148 var res = this.results[fired];
149 var self = this;
150 var cb = null;
151 while (chain.length > 0 && this.paused === 0) {
152 // Array
153 var pair = chain.shift();
154 var f = pair[fired];
155 if (f === null) {
156 continue;
157 }
158 try {
159 res = f(res);
160 fired = ((res instanceof Error) ? 1 : 0);
161 if (res instanceof MochiKit.Async.Deferred) {
162 cb = function (res) {
163 self._resback(res);
164 self.paused--;
165 if ((self.paused === 0) && (self.fired >= 0)) {
166 self._fire();
167 }
168 };
169 this.paused++;
170 }
171 } catch (err) {
172 fired = 1;
173 if (!(err instanceof Error)) {
174 err = new MochiKit.Async.GenericError(err);
175 }
176 res = err;
177 }
178 }
179 this.fired = fired;
180 this.results[fired] = res;
181 if (cb && this.paused) {
182 // this is for "tail recursion" in case the dependent deferred
183 // is already fired
184 res.addBoth(cb);
185 res.chained = true;
186 }
187 }
188};
189
190MochiKit.Base.update(MochiKit.Async, {
191 /** @id MochiKit.Async.evalJSONRequest */
192 evalJSONRequest: function (req) {
193 return MochiKit.Base.evalJSON(req.responseText);
194 },
195
196 /** @id MochiKit.Async.succeed */
197 succeed: function (/* optional */result) {
198 var d = new MochiKit.Async.Deferred();
199 d.callback.apply(d, arguments);
200 return d;
201 },
202
203 /** @id MochiKit.Async.fail */
204 fail: function (/* optional */result) {
205 var d = new MochiKit.Async.Deferred();
206 d.errback.apply(d, arguments);
207 return d;
208 },
209
210 /** @id MochiKit.Async.getXMLHttpRequest */
211 getXMLHttpRequest: function () {
212 var self = arguments.callee;
213 if (!self.XMLHttpRequest) {
214 var tryThese = [
215 function () { return new XMLHttpRequest(); },
216 function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
217 function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
218 function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
219 function () {
220 throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
221 }
222 ];
223 for (var i = 0; i < tryThese.length; i++) {
224 var func = tryThese[i];
225 try {
226 self.XMLHttpRequest = func;
227 return func();
228 } catch (e) {
229 // pass
230 }
231 }
232 }
233 return self.XMLHttpRequest();
234 },
235
236 _xhr_onreadystatechange: function (d) {
237 // MochiKit.Logging.logDebug('this.readyState', this.readyState);
238 var m = MochiKit.Base;
239 if (this.readyState == 4) {
240 // IE SUCKS
241 try {
242 this.onreadystatechange = null;
243 } catch (e) {
244 try {
245 this.onreadystatechange = m.noop;
246 } catch (e) {
247 }
248 }
249 var status = null;
250 try {
251 status = this.status;
252 if (!status && m.isNotEmpty(this.responseText)) {
253 // 0 or undefined seems to mean cached or local
254 status = 304;
255 }
256 } catch (e) {
257 // pass
258 // MochiKit.Logging.logDebug('error getting status?', repr(items(e)));
259 }
260 // 200 is OK, 201 is CREATED, 204 is NO CONTENT
261 // 304 is NOT MODIFIED, 1223 is apparently a bug in IE
262 if (status == 200 || status == 201 || status == 204 ||
263 status == 304 || status == 1223) {
264 d.callback(this);
265 } else {
266 var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed");
267 if (err.number) {
268 // XXX: This seems to happen on page change
269 d.errback(err);
270 } else {
271 // XXX: this seems to happen when the server is unreachable
272 d.errback(err);
273 }
274 }
275 }
276 },
277
278 _xhr_canceller: function (req) {
279 // IE SUCKS
280 try {
281 req.onreadystatechange = null;
282 } catch (e) {
283 try {
284 req.onreadystatechange = MochiKit.Base.noop;
285 } catch (e) {
286 }
287 }
288 req.abort();
289 },
290
291
292 /** @id MochiKit.Async.sendXMLHttpRequest */
293 sendXMLHttpRequest: function (req, /* optional */ sendContent) {
294 if (typeof(sendContent) == "undefined" || sendContent === null) {
295 sendContent = "";
296 }
297
298 var m = MochiKit.Base;
299 var self = MochiKit.Async;
300 var d = new self.Deferred(m.partial(self._xhr_canceller, req));
301
302 try {
303 req.onreadystatechange = m.bind(self._xhr_onreadystatechange,
304 req, d);
305 req.send(sendContent);
306 } catch (e) {
307 try {
308 req.onreadystatechange = null;
309 } catch (ignore) {
310 // pass
311 }
312 d.errback(e);
313 }
314
315 return d;
316
317 },
318
319 /** @id MochiKit.Async.doXHR */
320 doXHR: function (url, opts) {
321 /*
322 Work around a Firefox bug by dealing with XHR during
323 the next event loop iteration. Maybe it's this one:
324 https://bugzilla.mozilla.org/show_bug.cgi?id=249843
325 */
326 var self = MochiKit.Async;
327 return self.callLater(0, self._doXHR, url, opts);
328 },
329
330 _doXHR: function (url, opts) {
331 var m = MochiKit.Base;
332 opts = m.update({
333 method: 'GET',
334 sendContent: ''
335 /*
336 queryString: undefined,
337 username: undefined,
338 password: undefined,
339 headers: undefined,
340 mimeType: undefined
341 */
342 }, opts);
343 var self = MochiKit.Async;
344 var req = self.getXMLHttpRequest();
345 if (opts.queryString) {
346 var qs = m.queryString(opts.queryString);
347 if (qs) {
348 url += "?" + qs;
349 }
350 }
351 // Safari will send undefined:undefined, so we have to check.
352 // We can't use apply, since the function is native.
353 if ('username' in opts) {
354 req.open(opts.method, url, true, opts.username, opts.password);
355 } else {
356 req.open(opts.method, url, true);
357 }
358 if (req.overrideMimeType && opts.mimeType) {
359 req.overrideMimeType(opts.mimeType);
360 }
361 req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
362 if (opts.headers) {
363 var headers = opts.headers;
364 if (!m.isArrayLike(headers)) {
365 headers = m.items(headers);
366 }
367 for (var i = 0; i < headers.length; i++) {
368 var header = headers[i];
369 var name = header[0];
370 var value = header[1];
371 req.setRequestHeader(name, value);
372 }
373 }
374 return self.sendXMLHttpRequest(req, opts.sendContent);
375 },
376
377 _buildURL: function (url/*, ...*/) {
378 if (arguments.length > 1) {
379 var m = MochiKit.Base;
380 var qs = m.queryString.apply(null, m.extend(null, arguments, 1));
381 if (qs) {
382 return url + "?" + qs;
383 }
384 }
385 return url;
386 },
387
388 /** @id MochiKit.Async.doSimpleXMLHttpRequest */
389 doSimpleXMLHttpRequest: function (url/*, ...*/) {
390 var self = MochiKit.Async;
391 url = self._buildURL.apply(self, arguments);
392 return self.doXHR(url);
393 },
394
395 /** @id MochiKit.Async.loadJSONDoc */
396 loadJSONDoc: function (url/*, ...*/) {
397 var self = MochiKit.Async;
398 url = self._buildURL.apply(self, arguments);
399 var d = self.doXHR(url, {
400 'mimeType': 'text/plain',
401 'headers': [['Accept', 'application/json']]
402 });
403 d = d.addCallback(self.evalJSONRequest);
404 return d;
405 },
406
407 /** @id MochiKit.Async.wait */
408 wait: function (seconds, /* optional */value) {
409 var d = new MochiKit.Async.Deferred();
410 var m = MochiKit.Base;
411 if (typeof(value) != 'undefined') {
412 d.addCallback(function () { return value; });
413 }
414 var timeout = setTimeout(
415 m.bind("callback", d),
416 Math.floor(seconds * 1000));
417 d.canceller = function () {
418 try {
419 clearTimeout(timeout);
420 } catch (e) {
421 // pass
422 }
423 };
424 return d;
425 },
426
427 /** @id MochiKit.Async.callLater */
428 callLater: function (seconds, func) {
429 var m = MochiKit.Base;
430 var pfunc = m.partial.apply(m, m.extend(null, arguments, 1));
431 return MochiKit.Async.wait(seconds).addCallback(
432 function (res) { return pfunc(); }
433 );
434 }
435});
436
437
438/** @id MochiKit.Async.DeferredLock */
439MochiKit.Async.DeferredLock = function () {
440 this.waiting = [];
441 this.locked = false;
442 this.id = this._nextId();
443};
444
445MochiKit.Async.DeferredLock.prototype = {
446 __class__: MochiKit.Async.DeferredLock,
447 /** @id MochiKit.Async.DeferredLock.prototype.acquire */
448 acquire: function () {
449 var d = new MochiKit.Async.Deferred();
450 if (this.locked) {
451 this.waiting.push(d);
452 } else {
453 this.locked = true;
454 d.callback(this);
455 }
456 return d;
457 },
458 /** @id MochiKit.Async.DeferredLock.prototype.release */
459 release: function () {
460 if (!this.locked) {
461 throw TypeError("Tried to release an unlocked DeferredLock");
462 }
463 this.locked = false;
464 if (this.waiting.length > 0) {
465 this.locked = true;
466 this.waiting.shift().callback(this);
467 }
468 },
469 _nextId: MochiKit.Base.counter(),
470 repr: function () {
471 var state;
472 if (this.locked) {
473 state = 'locked, ' + this.waiting.length + ' waiting';
474 } else {
475 state = 'unlocked';
476 }
477 return 'DeferredLock(' + this.id + ', ' + state + ')';
478 },
479 toString: MochiKit.Base.forwardCall("repr")
480
481};
482
483/** @id MochiKit.Async.DeferredList */
484MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {
485
486 // call parent constructor
487 MochiKit.Async.Deferred.apply(this, [canceller]);
488
489 this.list = list;
490 var resultList = [];
491 this.resultList = resultList;
492
493 this.finishedCount = 0;
494 this.fireOnOneCallback = fireOnOneCallback;
495 this.fireOnOneErrback = fireOnOneErrback;
496 this.consumeErrors = consumeErrors;
497
498 var cb = MochiKit.Base.bind(this._cbDeferred, this);
499 for (var i = 0; i < list.length; i++) {
500 var d = list[i];
501 resultList.push(undefined);
502 d.addCallback(cb, i, true);
503 d.addErrback(cb, i, false);
504 }
505
506 if (list.length === 0 && !fireOnOneCallback) {
507 this.callback(this.resultList);
508 }
509
510};
511
512MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred();
513
514MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) {
515 this.resultList[index] = [succeeded, result];
516 this.finishedCount += 1;
517 if (this.fired == -1) {
518 if (succeeded && this.fireOnOneCallback) {
519 this.callback([index, result]);
520 } else if (!succeeded && this.fireOnOneErrback) {
521 this.errback(result);
522 } else if (this.finishedCount == this.list.length) {
523 this.callback(this.resultList);
524 }
525 }
526 if (!succeeded && this.consumeErrors) {
527 result = null;
528 }
529 return result;
530};
531
532/** @id MochiKit.Async.gatherResults */
533MochiKit.Async.gatherResults = function (deferredList) {
534 var d = new MochiKit.Async.DeferredList(deferredList, false, true, false);
535 d.addCallback(function (results) {
536 var ret = [];
537 for (var i = 0; i < results.length; i++) {
538 ret.push(results[i][1]);
539 }
540 return ret;
541 });
542 return d;
543};
544
545/** @id MochiKit.Async.maybeDeferred */
546MochiKit.Async.maybeDeferred = function (func) {
547 var self = MochiKit.Async;
548 var result;
549 try {
550 var r = func.apply(null, MochiKit.Base.extend([], arguments, 1));
551 if (r instanceof self.Deferred) {
552 result = r;
553 } else if (r instanceof Error) {
554 result = self.fail(r);
555 } else {
556 result = self.succeed(r);
557 }
558 } catch (e) {
559 result = self.fail(e);
560 }
561 return result;
562};
563
564
565MochiKit.Async.__new__ = function () {
566 var m = MochiKit.Base;
567 var ne = m.partial(m._newNamedError, this);
568
569 ne("AlreadyCalledError",
570 /** @id MochiKit.Async.AlreadyCalledError */
571 function (deferred) {
572 /***
573
574 Raised by the Deferred if callback or errback happens
575 after it was already fired.
576
577 ***/
578 this.deferred = deferred;
579 }
580 );
581
582 ne("CancelledError",
583 /** @id MochiKit.Async.CancelledError */
584 function (deferred) {
585 /***
586
587 Raised by the Deferred cancellation mechanism.
588
589 ***/
590 this.deferred = deferred;
591 }
592 );
593
594 ne("BrowserComplianceError",
595 /** @id MochiKit.Async.BrowserComplianceError */
596 function (msg) {
597 /***
598
599 Raised when the JavaScript runtime is not capable of performing
600 the given function. Technically, this should really never be
601 raised because a non-conforming JavaScript runtime probably
602 isn't going to support exceptions in the first place.
603
604 ***/
605 this.message = msg;
606 }
607 );
608
609 ne("GenericError",
610 /** @id MochiKit.Async.GenericError */
611 function (msg) {
612 this.message = msg;
613 }
614 );
615
616 ne("XMLHttpRequestError",
617 /** @id MochiKit.Async.XMLHttpRequestError */
618 function (req, msg) {
619 /***
620
621 Raised when an XMLHttpRequest does not complete for any reason.
622
623 ***/
624 this.req = req;
625 this.message = msg;
626 try {
627 // Strange but true that this can raise in some cases.
628 this.number = req.status;
629 } catch (e) {
630 // pass
631 }
632 }
633 );
634
635 m.nameFunctions(this);
636};
637
638MochiKit.Async.__new__();
639
640MochiKit.Base._exportSymbols(this, MochiKit.Async);
diff --git a/frontend/gamma/js/MochiKit/Base.js b/frontend/gamma/js/MochiKit/Base.js
new file mode 100644
index 0000000..d33c269
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Base.js
@@ -0,0 +1,1452 @@
1/***
2
3MochiKit.Base 1.5
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}
14if (typeof(MochiKit.__export__) == "undefined") {
15 MochiKit.__export__ = true;
16}
17if (typeof(MochiKit.Base) == 'undefined') {
18 MochiKit.Base = {};
19}
20
21/**
22 * Registers a new MochiKit module. This function will insert a new
23 * property into the "MochiKit" object, making sure that all
24 * dependency modules have already been inserted. It will also make
25 * sure that the appropriate properties and default module functions
26 * are defined.
27 *
28 * @param {String} name the module name, e.g. "Base"
29 * @param {String} version the module version, e.g. "1.5"
30 * @param {Array} deps the array of module dependencies (as strings)
31 */
32MochiKit.Base._module = function (name, version, deps) {
33 if (!(name in MochiKit)) {
34 MochiKit[name] = {};
35 }
36 var module = MochiKit[name];
37 module.NAME = "MochiKit." + name;
38 module.VERSION = version;
39 module.__repr__ = function () {
40 return "[" + this.NAME + " " + this.VERSION + "]";
41 };
42 module.toString = function () {
43 return this.__repr__();
44 };
45 for (var i = 0; i < deps.length; i++) {
46 if (!(deps[i] in MochiKit)) {
47 throw 'MochiKit.' + name + ' depends on MochiKit.' + deps[i] + '!';
48 }
49 }
50}
51
52MochiKit.Base._module("Base", "1.5", []);
53
54/** @id MochiKit.Base.update */
55MochiKit.Base.update = function (self, obj/*, ... */) {
56 if (self === null || self === undefined) {
57 self = {};
58 }
59 for (var i = 1; i < arguments.length; i++) {
60 var o = arguments[i];
61 if (typeof(o) != 'undefined' && o !== null) {
62 for (var k in o) {
63 self[k] = o[k];
64 }
65 }
66 }
67 return self;
68};
69
70MochiKit.Base.update(MochiKit.Base, {
71 /** @id MochiKit.Base.camelize */
72 camelize: function (selector) {
73 /* from dojo.style.toCamelCase */
74 var arr = selector.split('-');
75 var cc = arr[0];
76 for (var i = 1; i < arr.length; i++) {
77 cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
78 }
79 return cc;
80 },
81
82 /** @id MochiKit.Base.counter */
83 counter: function (n/* = 1 */) {
84 if (arguments.length === 0) {
85 n = 1;
86 }
87 return function () {
88 return n++;
89 };
90 },
91
92 /** @id MochiKit.Base.clone */
93 clone: function (obj) {
94 var me = arguments.callee;
95 if (arguments.length == 1) {
96 me.prototype = obj;
97 return new me();
98 }
99 },
100
101 _flattenArray: function (res, lst) {
102 for (var i = 0; i < lst.length; i++) {
103 var o = lst[i];
104 if (o instanceof Array) {
105 arguments.callee(res, o);
106 } else {
107 res.push(o);
108 }
109 }
110 return res;
111 },
112
113 /** @id MochiKit.Base.flattenArray */
114 flattenArray: function (lst) {
115 return MochiKit.Base._flattenArray([], lst);
116 },
117
118 /** @id MochiKit.Base.flattenArguments */
119 flattenArguments: function (lst/* ...*/) {
120 var res = [];
121 var m = MochiKit.Base;
122 var args = m.extend(null, arguments);
123 while (args.length) {
124 var o = args.shift();
125 if (o && typeof(o) == "object" && typeof(o.length) == "number") {
126 for (var i = o.length - 1; i >= 0; i--) {
127 args.unshift(o[i]);
128 }
129 } else {
130 res.push(o);
131 }
132 }
133 return res;
134 },
135
136 /** @id MochiKit.Base.extend */
137 extend: function (self, obj, /* optional */skip) {
138 // Extend an array with an array-like object starting
139 // from the skip index
140 if (!skip) {
141 skip = 0;
142 }
143 if (obj) {
144 // allow iterable fall-through, but skip the full isArrayLike
145 // check for speed, this is called often.
146 var l = obj.length;
147 if (typeof(l) != 'number' /* !isArrayLike(obj) */) {
148 if (typeof(MochiKit.Iter) != "undefined") {
149 obj = MochiKit.Iter.list(obj);
150 l = obj.length;
151 } else {
152 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
153 }
154 }
155 if (!self) {
156 self = [];
157 }
158 for (var i = skip; i < l; i++) {
159 self.push(obj[i]);
160 }
161 }
162 // This mutates, but it's convenient to return because
163 // it's often used like a constructor when turning some
164 // ghetto array-like to a real array
165 return self;
166 },
167
168
169 /** @id MochiKit.Base.updatetree */
170 updatetree: function (self, obj/*, ...*/) {
171 if (self === null || self === undefined) {
172 self = {};
173 }
174 for (var i = 1; i < arguments.length; i++) {
175 var o = arguments[i];
176 if (typeof(o) != 'undefined' && o !== null) {
177 for (var k in o) {
178 var v = o[k];
179 if (typeof(self[k]) == 'object' && typeof(v) == 'object') {
180 arguments.callee(self[k], v);
181 } else {
182 self[k] = v;
183 }
184 }
185 }
186 }
187 return self;
188 },
189
190 /** @id MochiKit.Base.setdefault */
191 setdefault: function (self, obj/*, ...*/) {
192 if (self === null || self === undefined) {
193 self = {};
194 }
195 for (var i = 1; i < arguments.length; i++) {
196 var o = arguments[i];
197 for (var k in o) {
198 if (!(k in self)) {
199 self[k] = o[k];
200 }
201 }
202 }
203 return self;
204 },
205
206 /** @id MochiKit.Base.keys */
207 keys: function (obj) {
208 var rval = [];
209 for (var prop in obj) {
210 rval.push(prop);
211 }
212 return rval;
213 },
214
215 /** @id MochiKit.Base.values */
216 values: function (obj) {
217 var rval = [];
218 for (var prop in obj) {
219 rval.push(obj[prop]);
220 }
221 return rval;
222 },
223
224 /** @id MochiKit.Base.items */
225 items: function (obj) {
226 var rval = [];
227 var e;
228 for (var prop in obj) {
229 var v;
230 try {
231 v = obj[prop];
232 } catch (e) {
233 continue;
234 }
235 rval.push([prop, v]);
236 }
237 return rval;
238 },
239
240
241 _newNamedError: function (module, name, func) {
242 func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name);
243 module[name] = func;
244 },
245
246
247 /** @id MochiKit.Base.operator */
248 operator: {
249 // unary logic operators
250 /** @id MochiKit.Base.truth */
251 truth: function (a) { return !!a; },
252 /** @id MochiKit.Base.lognot */
253 lognot: function (a) { return !a; },
254 /** @id MochiKit.Base.identity */
255 identity: function (a) { return a; },
256
257 // bitwise unary operators
258 /** @id MochiKit.Base.not */
259 not: function (a) { return ~a; },
260 /** @id MochiKit.Base.neg */
261 neg: function (a) { return -a; },
262
263 // binary operators
264 /** @id MochiKit.Base.add */
265 add: function (a, b) { return a + b; },
266 /** @id MochiKit.Base.sub */
267 sub: function (a, b) { return a - b; },
268 /** @id MochiKit.Base.div */
269 div: function (a, b) { return a / b; },
270 /** @id MochiKit.Base.mod */
271 mod: function (a, b) { return a % b; },
272 /** @id MochiKit.Base.mul */
273 mul: function (a, b) { return a * b; },
274
275 // bitwise binary operators
276 /** @id MochiKit.Base.and */
277 and: function (a, b) { return a & b; },
278 /** @id MochiKit.Base.or */
279 or: function (a, b) { return a | b; },
280 /** @id MochiKit.Base.xor */
281 xor: function (a, b) { return a ^ b; },
282 /** @id MochiKit.Base.lshift */
283 lshift: function (a, b) { return a << b; },
284 /** @id MochiKit.Base.rshift */
285 rshift: function (a, b) { return a >> b; },
286 /** @id MochiKit.Base.zrshift */
287 zrshift: function (a, b) { return a >>> b; },
288
289 // near-worthless built-in comparators
290 /** @id MochiKit.Base.eq */
291 eq: function (a, b) { return a == b; },
292 /** @id MochiKit.Base.ne */
293 ne: function (a, b) { return a != b; },
294 /** @id MochiKit.Base.gt */
295 gt: function (a, b) { return a > b; },
296 /** @id MochiKit.Base.ge */
297 ge: function (a, b) { return a >= b; },
298 /** @id MochiKit.Base.lt */
299 lt: function (a, b) { return a < b; },
300 /** @id MochiKit.Base.le */
301 le: function (a, b) { return a <= b; },
302
303 // strict built-in comparators
304 seq: function (a, b) { return a === b; },
305 sne: function (a, b) { return a !== b; },
306
307 // compare comparators
308 /** @id MochiKit.Base.ceq */
309 ceq: function (a, b) { return MochiKit.Base.compare(a, b) === 0; },
310 /** @id MochiKit.Base.cne */
311 cne: function (a, b) { return MochiKit.Base.compare(a, b) !== 0; },
312 /** @id MochiKit.Base.cgt */
313 cgt: function (a, b) { return MochiKit.Base.compare(a, b) == 1; },
314 /** @id MochiKit.Base.cge */
315 cge: function (a, b) { return MochiKit.Base.compare(a, b) != -1; },
316 /** @id MochiKit.Base.clt */
317 clt: function (a, b) { return MochiKit.Base.compare(a, b) == -1; },
318 /** @id MochiKit.Base.cle */
319 cle: function (a, b) { return MochiKit.Base.compare(a, b) != 1; },
320
321 // binary logical operators
322 /** @id MochiKit.Base.logand */
323 logand: function (a, b) { return a && b; },
324 /** @id MochiKit.Base.logor */
325 logor: function (a, b) { return a || b; },
326 /** @id MochiKit.Base.contains */
327 contains: function (a, b) { return b in a; }
328 },
329
330 /** @id MochiKit.Base.forwardCall */
331 forwardCall: function (func) {
332 return function () {
333 return this[func].apply(this, arguments);
334 };
335 },
336
337 /** @id MochiKit.Base.itemgetter */
338 itemgetter: function (func) {
339 return function (arg) {
340 return arg[func];
341 };
342 },
343
344 /** @id MochiKit.Base.bool */
345 bool: function (value) {
346 if (typeof(value) === "boolean" || value instanceof Boolean) {
347 return value.valueOf();
348 } else if (typeof(value) === "string" || value instanceof String) {
349 return value.length > 0 && value != "false" && value != "null" &&
350 value != "undefined" && value != "0";
351 } else if (typeof(value) === "number" || value instanceof Number) {
352 return !isNaN(value) && value != 0;
353 } else if (value != null && typeof(value.length) === "number") {
354 return value.length !== 0
355 } else {
356 return value != null;
357 }
358 },
359
360 /** @id MochiKit.Base.typeMatcher */
361 typeMatcher: function (/* typ */) {
362 var types = {};
363 for (var i = 0; i < arguments.length; i++) {
364 var typ = arguments[i];
365 types[typ] = typ;
366 }
367 return function () {
368 for (var i = 0; i < arguments.length; i++) {
369 if (!(typeof(arguments[i]) in types)) {
370 return false;
371 }
372 }
373 return true;
374 };
375 },
376
377 /** @id MochiKit.Base.isNull */
378 isNull: function (/* ... */) {
379 for (var i = 0; i < arguments.length; i++) {
380 if (arguments[i] !== null) {
381 return false;
382 }
383 }
384 return true;
385 },
386
387 /** @id MochiKit.Base.isUndefinedOrNull */
388 isUndefinedOrNull: function (/* ... */) {
389 for (var i = 0; i < arguments.length; i++) {
390 var o = arguments[i];
391 if (!(typeof(o) == 'undefined' || o === null)) {
392 return false;
393 }
394 }
395 return true;
396 },
397
398 /** @id MochiKit.Base.isEmpty */
399 isEmpty: function (obj) {
400 return !MochiKit.Base.isNotEmpty.apply(this, arguments);
401 },
402
403 /** @id MochiKit.Base.isNotEmpty */
404 isNotEmpty: function (obj) {
405 for (var i = 0; i < arguments.length; i++) {
406 var o = arguments[i];
407 if (!(o && o.length)) {
408 return false;
409 }
410 }
411 return true;
412 },
413
414 /** @id MochiKit.Base.isArrayLike */
415 isArrayLike: function () {
416 for (var i = 0; i < arguments.length; i++) {
417 var o = arguments[i];
418 var typ = typeof(o);
419 if (
420 (typ != 'object' && !(typ == 'function' && typeof(o.item) == 'function')) ||
421 o === null ||
422 typeof(o.length) != 'number' ||
423 o.nodeType === 3 ||
424 o.nodeType === 4
425 ) {
426 return false;
427 }
428 }
429 return true;
430 },
431
432 /** @id MochiKit.Base.isDateLike */
433 isDateLike: function () {
434 for (var i = 0; i < arguments.length; i++) {
435 var o = arguments[i];
436 if (typeof(o) != "object" || o === null
437 || typeof(o.getTime) != 'function') {
438 return false;
439 }
440 }
441 return true;
442 },
443
444
445 /** @id MochiKit.Base.xmap */
446 xmap: function (fn/*, obj... */) {
447 if (fn === null) {
448 return MochiKit.Base.extend(null, arguments, 1);
449 }
450 var rval = [];
451 for (var i = 1; i < arguments.length; i++) {
452 rval.push(fn(arguments[i]));
453 }
454 return rval;
455 },
456
457 /** @id MochiKit.Base.map */
458 map: function (fn, lst/*, lst... */) {
459 var m = MochiKit.Base;
460 var itr = MochiKit.Iter;
461 var isArrayLike = m.isArrayLike;
462 if (arguments.length <= 2) {
463 // allow an iterable to be passed
464 if (!isArrayLike(lst)) {
465 if (itr) {
466 // fast path for map(null, iterable)
467 lst = itr.list(lst);
468 if (fn === null) {
469 return lst;
470 }
471 } else {
472 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
473 }
474 }
475 // fast path for map(null, lst)
476 if (fn === null) {
477 return m.extend(null, lst);
478 }
479 // disabled fast path for map(fn, lst)
480 /*
481 if (false && typeof(Array.prototype.map) == 'function') {
482 // Mozilla fast-path
483 return Array.prototype.map.call(lst, fn);
484 }
485 */
486 var rval = [];
487 for (var i = 0; i < lst.length; i++) {
488 rval.push(fn(lst[i]));
489 }
490 return rval;
491 } else {
492 // default for map(null, ...) is zip(...)
493 if (fn === null) {
494 fn = Array;
495 }
496 var length = null;
497 for (var i = 1; i < arguments.length; i++) {
498 // allow iterables to be passed
499 if (!isArrayLike(arguments[i])) {
500 if (itr) {
501 return itr.list(itr.imap.apply(null, arguments));
502 } else {
503 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
504 }
505 }
506 // find the minimum length
507 var l = arguments[i].length;
508 if (length === null || length > l) {
509 length = l;
510 }
511 }
512 rval = [];
513 for (var i = 0; i < length; i++) {
514 var args = [];
515 for (var j = 1; j < arguments.length; j++) {
516 args.push(arguments[j][i]);
517 }
518 rval.push(fn.apply(this, args));
519 }
520 return rval;
521 }
522 },
523
524 /** @id MochiKit.Base.xfilter */
525 xfilter: function (fn/*, obj... */) {
526 var rval = [];
527 if (fn === null) {
528 fn = MochiKit.Base.operator.truth;
529 }
530 for (var i = 1; i < arguments.length; i++) {
531 var o = arguments[i];
532 if (fn(o)) {
533 rval.push(o);
534 }
535 }
536 return rval;
537 },
538
539 /** @id MochiKit.Base.filter */
540 filter: function (fn, lst, self) {
541 var rval = [];
542 // allow an iterable to be passed
543 var m = MochiKit.Base;
544 if (!m.isArrayLike(lst)) {
545 if (MochiKit.Iter) {
546 lst = MochiKit.Iter.list(lst);
547 } else {
548 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
549 }
550 }
551 if (fn === null) {
552 fn = m.operator.truth;
553 }
554 if (typeof(Array.prototype.filter) == 'function') {
555 // Mozilla fast-path
556 return Array.prototype.filter.call(lst, fn, self);
557 } else if (typeof(self) == 'undefined' || self === null) {
558 for (var i = 0; i < lst.length; i++) {
559 var o = lst[i];
560 if (fn(o)) {
561 rval.push(o);
562 }
563 }
564 } else {
565 for (var i = 0; i < lst.length; i++) {
566 o = lst[i];
567 if (fn.call(self, o)) {
568 rval.push(o);
569 }
570 }
571 }
572 return rval;
573 },
574
575
576 _wrapDumbFunction: function (func) {
577 return function () {
578 // fast path!
579 switch (arguments.length) {
580 case 0: return func();
581 case 1: return func(arguments[0]);
582 case 2: return func(arguments[0], arguments[1]);
583 case 3: return func(arguments[0], arguments[1], arguments[2]);
584 }
585 var args = [];
586 for (var i = 0; i < arguments.length; i++) {
587 args.push("arguments[" + i + "]");
588 }
589 return eval("(func(" + args.join(",") + "))");
590 };
591 },
592
593 /** @id MochiKit.Base.methodcaller */
594 methodcaller: function (func/*, args... */) {
595 var args = MochiKit.Base.extend(null, arguments, 1);
596 if (typeof(func) == "function") {
597 return function (obj) {
598 return func.apply(obj, args);
599 };
600 } else {
601 return function (obj) {
602 return obj[func].apply(obj, args);
603 };
604 }
605 },
606
607 /** @id MochiKit.Base.method */
608 method: function (self, func) {
609 var m = MochiKit.Base;
610 return m.bind.apply(this, m.extend([func, self], arguments, 2));
611 },
612
613 /** @id MochiKit.Base.compose */
614 compose: function (f1, f2/*, f3, ... fN */) {
615 var fnlist = [];
616 var m = MochiKit.Base;
617 if (arguments.length === 0) {
618 throw new TypeError("compose() requires at least one argument");
619 }
620 for (var i = 0; i < arguments.length; i++) {
621 var fn = arguments[i];
622 if (typeof(fn) != "function") {
623 throw new TypeError(m.repr(fn) + " is not a function");
624 }
625 fnlist.push(fn);
626 }
627 return function () {
628 var args = arguments;
629 for (var i = fnlist.length - 1; i >= 0; i--) {
630 args = [fnlist[i].apply(this, args)];
631 }
632 return args[0];
633 };
634 },
635
636 /** @id MochiKit.Base.bind */
637 bind: function (func, self/* args... */) {
638 if (typeof(func) == "string") {
639 func = self[func];
640 }
641 var im_func = func.im_func;
642 var im_preargs = func.im_preargs;
643 var im_self = func.im_self;
644 var m = MochiKit.Base;
645 if (typeof(func) == "function" && typeof(func.apply) == "undefined") {
646 // this is for cases where JavaScript sucks ass and gives you a
647 // really dumb built-in function like alert() that doesn't have
648 // an apply
649 func = m._wrapDumbFunction(func);
650 }
651 if (typeof(im_func) != 'function') {
652 im_func = func;
653 }
654 if (typeof(self) != 'undefined') {
655 im_self = self;
656 }
657 if (typeof(im_preargs) == 'undefined') {
658 im_preargs = [];
659 } else {
660 im_preargs = im_preargs.slice();
661 }
662 m.extend(im_preargs, arguments, 2);
663 var newfunc = function () {
664 var args = arguments;
665 var me = arguments.callee;
666 if (me.im_preargs.length > 0) {
667 args = m.concat(me.im_preargs, args);
668 }
669 var self = me.im_self;
670 if (!self) {
671 self = this;
672 }
673 return me.im_func.apply(self, args);
674 };
675 newfunc.im_self = im_self;
676 newfunc.im_func = im_func;
677 newfunc.im_preargs = im_preargs;
678 return newfunc;
679 },
680
681 /** @id MochiKit.Base.bindLate */
682 bindLate: function (func, self/* args... */) {
683 var m = MochiKit.Base;
684 var args = arguments;
685 if (typeof(func) === "string") {
686 args = m.extend([m.forwardCall(func)], arguments, 1);
687 return m.bind.apply(this, args);
688 }
689 return m.bind.apply(this, args);
690 },
691
692 /** @id MochiKit.Base.bindMethods */
693 bindMethods: function (self) {
694 var bind = MochiKit.Base.bind;
695 for (var k in self) {
696 var func = self[k];
697 if (typeof(func) == 'function') {
698 self[k] = bind(func, self);
699 }
700 }
701 },
702
703 /** @id MochiKit.Base.registerComparator */
704 registerComparator: function (name, check, comparator, /* optional */ override) {
705 MochiKit.Base.comparatorRegistry.register(name, check, comparator, override);
706 },
707
708 _primitives: {'boolean': true, 'string': true, 'number': true},
709
710 /** @id MochiKit.Base.compare */
711 compare: function (a, b) {
712 if (a == b) {
713 return 0;
714 }
715 var aIsNull = (typeof(a) == 'undefined' || a === null);
716 var bIsNull = (typeof(b) == 'undefined' || b === null);
717 if (aIsNull && bIsNull) {
718 return 0;
719 } else if (aIsNull) {
720 return -1;
721 } else if (bIsNull) {
722 return 1;
723 }
724 var m = MochiKit.Base;
725 // bool, number, string have meaningful comparisons
726 var prim = m._primitives;
727 if (!(typeof(a) in prim && typeof(b) in prim)) {
728 try {
729 return m.comparatorRegistry.match(a, b);
730 } catch (e) {
731 if (e != m.NotFound) {
732 throw e;
733 }
734 }
735 }
736 if (a < b) {
737 return -1;
738 } else if (a > b) {
739 return 1;
740 }
741 // These types can't be compared
742 var repr = m.repr;
743 throw new TypeError(repr(a) + " and " + repr(b) + " can not be compared");
744 },
745
746 /** @id MochiKit.Base.compareDateLike */
747 compareDateLike: function (a, b) {
748 return MochiKit.Base.compare(a.getTime(), b.getTime());
749 },
750
751 /** @id MochiKit.Base.compareArrayLike */
752 compareArrayLike: function (a, b) {
753 var compare = MochiKit.Base.compare;
754 var count = a.length;
755 var rval = 0;
756 if (count > b.length) {
757 rval = 1;
758 count = b.length;
759 } else if (count < b.length) {
760 rval = -1;
761 }
762 for (var i = 0; i < count; i++) {
763 var cmp = compare(a[i], b[i]);
764 if (cmp) {
765 return cmp;
766 }
767 }
768 return rval;
769 },
770
771 /** @id MochiKit.Base.registerRepr */
772 registerRepr: function (name, check, wrap, /* optional */override) {
773 MochiKit.Base.reprRegistry.register(name, check, wrap, override);
774 },
775
776 /** @id MochiKit.Base.repr */
777 repr: function (o) {
778 if (typeof(o) == "undefined") {
779 return "undefined";
780 } else if (o === null) {
781 return "null";
782 }
783 try {
784 if (typeof(o.__repr__) == 'function') {
785 return o.__repr__();
786 } else if (typeof(o.repr) == 'function' && o.repr != arguments.callee) {
787 return o.repr();
788 }
789 return MochiKit.Base.reprRegistry.match(o);
790 } catch (e) {
791 if (typeof(o.NAME) == 'string' && (
792 o.toString == Function.prototype.toString ||
793 o.toString == Object.prototype.toString
794 )) {
795 return o.NAME;
796 }
797 }
798 try {
799 var ostring = (o + "");
800 } catch (e) {
801 return "[" + typeof(o) + "]";
802 }
803 if (typeof(o) == "function") {
804 ostring = ostring.replace(/^\s+/, "").replace(/\s+/g, " ");
805 ostring = ostring.replace(/,(\S)/, ", $1");
806 var idx = ostring.indexOf("{");
807 if (idx != -1) {
808 ostring = ostring.substr(0, idx) + "{...}";
809 }
810 }
811 return ostring;
812 },
813
814 /** @id MochiKit.Base.reprArrayLike */
815 reprArrayLike: function (o) {
816 var m = MochiKit.Base;
817 return "[" + m.map(m.repr, o).join(", ") + "]";
818 },
819
820 /** @id MochiKit.Base.reprString */
821 reprString: function (o) {
822 return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
823 ).replace(/[\f]/g, "\\f"
824 ).replace(/[\b]/g, "\\b"
825 ).replace(/[\n]/g, "\\n"
826 ).replace(/[\t]/g, "\\t"
827 ).replace(/[\v]/g, "\\v"
828 ).replace(/[\r]/g, "\\r");
829 },
830
831 /** @id MochiKit.Base.reprNumber */
832 reprNumber: function (o) {
833 return o + "";
834 },
835
836 /** @id MochiKit.Base.registerJSON */
837 registerJSON: function (name, check, wrap, /* optional */override) {
838 MochiKit.Base.jsonRegistry.register(name, check, wrap, override);
839 },
840
841
842 /** @id MochiKit.Base.evalJSON */
843 evalJSON: function () {
844 return eval("(" + MochiKit.Base._filterJSON(arguments[0]) + ")");
845 },
846
847 _filterJSON: function (s) {
848 var m = s.match(/^\s*\/\*(.*)\*\/\s*$/);
849 if (m) {
850 return m[1];
851 }
852 return s;
853 },
854
855 /** @id MochiKit.Base.serializeJSON */
856 serializeJSON: function (o) {
857 var objtype = typeof(o);
858 if (objtype == "number" || objtype == "boolean") {
859 return o + "";
860 } else if (o === null) {
861 return "null";
862 } else if (objtype == "string") {
863 var res = "";
864 for (var i = 0; i < o.length; i++) {
865 var c = o.charAt(i);
866 if (c == '\"') {
867 res += '\\"';
868 } else if (c == '\\') {
869 res += '\\\\';
870 } else if (c == '\b') {
871 res += '\\b';
872 } else if (c == '\f') {
873 res += '\\f';
874 } else if (c == '\n') {
875 res += '\\n';
876 } else if (c == '\r') {
877 res += '\\r';
878 } else if (c == '\t') {
879 res += '\\t';
880 } else if (o.charCodeAt(i) <= 0x1F) {
881 var hex = o.charCodeAt(i).toString(16);
882 if (hex.length < 2) {
883 hex = '0' + hex;
884 }
885 res += '\\u00' + hex.toUpperCase();
886 } else {
887 res += c;
888 }
889 }
890 return '"' + res + '"';
891 }
892 // recurse
893 var me = arguments.callee;
894 // short-circuit for objects that support "json" serialization
895 // if they return "self" then just pass-through...
896 var newObj;
897 if (typeof(o.__json__) == "function") {
898 newObj = o.__json__();
899 if (o !== newObj) {
900 return me(newObj);
901 }
902 }
903 if (typeof(o.json) == "function") {
904 newObj = o.json();
905 if (o !== newObj) {
906 return me(newObj);
907 }
908 }
909 // array
910 if (objtype != "function" && typeof(o.length) == "number") {
911 var res = [];
912 for (var i = 0; i < o.length; i++) {
913 var val = me(o[i]);
914 if (typeof(val) != "string") {
915 // skip non-serializable values
916 continue;
917 }
918 res.push(val);
919 }
920 return "[" + res.join(", ") + "]";
921 }
922 // look in the registry
923 var m = MochiKit.Base;
924 try {
925 newObj = m.jsonRegistry.match(o);
926 if (o !== newObj) {
927 return me(newObj);
928 }
929 } catch (e) {
930 if (e != m.NotFound) {
931 // something really bad happened
932 throw e;
933 }
934 }
935 // undefined is outside of the spec
936 if (objtype == "undefined") {
937 throw new TypeError("undefined can not be serialized as JSON");
938 }
939 // it's a function with no adapter, bad
940 if (objtype == "function") {
941 return null;
942 }
943 // generic object code path
944 res = [];
945 for (var k in o) {
946 var useKey;
947 if (typeof(k) == "number") {
948 useKey = '"' + k + '"';
949 } else if (typeof(k) == "string") {
950 useKey = me(k);
951 } else {
952 // skip non-string or number keys
953 continue;
954 }
955 val = me(o[k]);
956 if (typeof(val) != "string") {
957 // skip non-serializable values
958 continue;
959 }
960 res.push(useKey + ":" + val);
961 }
962 return "{" + res.join(", ") + "}";
963 },
964
965
966 /** @id MochiKit.Base.objEqual */
967 objEqual: function (a, b) {
968 return (MochiKit.Base.compare(a, b) === 0);
969 },
970
971 /** @id MochiKit.Base.arrayEqual */
972 arrayEqual: function (self, arr) {
973 if (self.length != arr.length) {
974 return false;
975 }
976 return (MochiKit.Base.compare(self, arr) === 0);
977 },
978
979 /** @id MochiKit.Base.concat */
980 concat: function (/* lst... */) {
981 var rval = [];
982 var extend = MochiKit.Base.extend;
983 for (var i = 0; i < arguments.length; i++) {
984 extend(rval, arguments[i]);
985 }
986 return rval;
987 },
988
989 /** @id MochiKit.Base.keyComparator */
990 keyComparator: function (key/* ... */) {
991 // fast-path for single key comparisons
992 var m = MochiKit.Base;
993 var compare = m.compare;
994 if (arguments.length == 1) {
995 return function (a, b) {
996 return compare(a[key], b[key]);
997 };
998 }
999 var compareKeys = m.extend(null, arguments);
1000 return function (a, b) {
1001 var rval = 0;
1002 // keep comparing until something is inequal or we run out of
1003 // keys to compare
1004 for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) {
1005 var key = compareKeys[i];
1006 rval = compare(a[key], b[key]);
1007 }
1008 return rval;
1009 };
1010 },
1011
1012 /** @id MochiKit.Base.reverseKeyComparator */
1013 reverseKeyComparator: function (key) {
1014 var comparator = MochiKit.Base.keyComparator.apply(this, arguments);
1015 return function (a, b) {
1016 return comparator(b, a);
1017 };
1018 },
1019
1020 /** @id MochiKit.Base.partial */
1021 partial: function (func) {
1022 var m = MochiKit.Base;
1023 return m.bind.apply(this, m.extend([func, undefined], arguments, 1));
1024 },
1025
1026 /** @id MochiKit.Base.listMinMax */
1027 listMinMax: function (which, lst) {
1028 if (lst.length === 0) {
1029 return null;
1030 }
1031 var cur = lst[0];
1032 var compare = MochiKit.Base.compare;
1033 for (var i = 1; i < lst.length; i++) {
1034 var o = lst[i];
1035 if (compare(o, cur) == which) {
1036 cur = o;
1037 }
1038 }
1039 return cur;
1040 },
1041
1042 /** @id MochiKit.Base.objMax */
1043 objMax: function (/* obj... */) {
1044 return MochiKit.Base.listMinMax(1, arguments);
1045 },
1046
1047 /** @id MochiKit.Base.objMin */
1048 objMin: function (/* obj... */) {
1049 return MochiKit.Base.listMinMax(-1, arguments);
1050 },
1051
1052 /** @id MochiKit.Base.findIdentical */
1053 findIdentical: function (lst, value, start/* = 0 */, /* optional */end) {
1054 if (typeof(end) == "undefined" || end === null) {
1055 end = lst.length;
1056 }
1057 if (typeof(start) == "undefined" || start === null) {
1058 start = 0;
1059 }
1060 for (var i = start; i < end; i++) {
1061 if (lst[i] === value) {
1062 return i;
1063 }
1064 }
1065 return -1;
1066 },
1067
1068 /** @id MochiKit.Base.mean */
1069 mean: function(/* lst... */) {
1070 /* http://www.nist.gov/dads/HTML/mean.html */
1071 var sum = 0;
1072
1073 var m = MochiKit.Base;
1074 var args = m.extend(null, arguments);
1075 var count = args.length;
1076
1077 while (args.length) {
1078 var o = args.shift();
1079 if (o && typeof(o) == "object" && typeof(o.length) == "number") {
1080 count += o.length - 1;
1081 for (var i = o.length - 1; i >= 0; i--) {
1082 sum += o[i];
1083 }
1084 } else {
1085 sum += o;
1086 }
1087 }
1088
1089 if (count <= 0) {
1090 throw new TypeError('mean() requires at least one argument');
1091 }
1092
1093 return sum/count;
1094 },
1095
1096 /** @id MochiKit.Base.median */
1097 median: function(/* lst... */) {
1098 /* http://www.nist.gov/dads/HTML/median.html */
1099 var data = MochiKit.Base.flattenArguments(arguments);
1100 if (data.length === 0) {
1101 throw new TypeError('median() requires at least one argument');
1102 }
1103 data.sort(compare);
1104 if (data.length % 2 == 0) {
1105 var upper = data.length / 2;
1106 return (data[upper] + data[upper - 1]) / 2;
1107 } else {
1108 return data[(data.length - 1) / 2];
1109 }
1110 },
1111
1112 /** @id MochiKit.Base.findValue */
1113 findValue: function (lst, value, start/* = 0 */, /* optional */end) {
1114 if (typeof(end) == "undefined" || end === null) {
1115 end = lst.length;
1116 }
1117 if (typeof(start) == "undefined" || start === null) {
1118 start = 0;
1119 }
1120 var cmp = MochiKit.Base.compare;
1121 for (var i = start; i < end; i++) {
1122 if (cmp(lst[i], value) === 0) {
1123 return i;
1124 }
1125 }
1126 return -1;
1127 },
1128
1129 /** @id MochiKit.Base.nodeWalk */
1130 nodeWalk: function (node, visitor) {
1131 var nodes = [node];
1132 var extend = MochiKit.Base.extend;
1133 while (nodes.length) {
1134 var res = visitor(nodes.shift());
1135 if (res) {
1136 extend(nodes, res);
1137 }
1138 }
1139 },
1140
1141
1142 /** @id MochiKit.Base.nameFunctions */
1143 nameFunctions: function (namespace) {
1144 var base = namespace.NAME;
1145 if (typeof(base) == 'undefined') {
1146 base = '';
1147 } else {
1148 base = base + '.';
1149 }
1150 for (var name in namespace) {
1151 var o = namespace[name];
1152 if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
1153 try {
1154 o.NAME = base + name;
1155 } catch (e) {
1156 // pass
1157 }
1158 }
1159 }
1160 },
1161
1162
1163 /** @id MochiKit.Base.queryString */
1164 queryString: function (names, values) {
1165 // check to see if names is a string or a DOM element, and if
1166 // MochiKit.DOM is available. If so, drop it like it's a form
1167 // Ugliest conditional in MochiKit? Probably!
1168 if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1
1169 && (typeof(names) == "string" || (
1170 typeof(names.nodeType) != "undefined" && names.nodeType > 0
1171 ))
1172 ) {
1173 var kv = MochiKit.DOM.formContents(names);
1174 names = kv[0];
1175 values = kv[1];
1176 } else if (arguments.length == 1) {
1177 // Allow the return value of formContents to be passed directly
1178 if (typeof(names.length) == "number" && names.length == 2) {
1179 return arguments.callee(names[0], names[1]);
1180 }
1181 var o = names;
1182 names = [];
1183 values = [];
1184 for (var k in o) {
1185 var v = o[k];
1186 if (typeof(v) == "function") {
1187 continue;
1188 } else if (MochiKit.Base.isArrayLike(v)){
1189 for (var i = 0; i < v.length; i++) {
1190 names.push(k);
1191 values.push(v[i]);
1192 }
1193 } else {
1194 names.push(k);
1195 values.push(v);
1196 }
1197 }
1198 }
1199 var rval = [];
1200 var len = Math.min(names.length, values.length);
1201 var urlEncode = MochiKit.Base.urlEncode;
1202 for (var i = 0; i < len; i++) {
1203 v = values[i];
1204 if (typeof(v) != 'undefined' && v !== null) {
1205 rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
1206 }
1207 }
1208 return rval.join("&");
1209 },
1210
1211
1212 /** @id MochiKit.Base.parseQueryString */
1213 parseQueryString: function (encodedString, useArrays) {
1214 // strip a leading '?' from the encoded string
1215 var qstr = (encodedString.charAt(0) == "?")
1216 ? encodedString.substring(1)
1217 : encodedString;
1218 var pairs = qstr.replace(/\+/g, "%20").split(/\&amp\;|\&\#38\;|\&#x26;|\&/);
1219 var o = {};
1220 var decode;
1221 if (typeof(decodeURIComponent) != "undefined") {
1222 decode = decodeURIComponent;
1223 } else {
1224 decode = unescape;
1225 }
1226 if (useArrays) {
1227 for (var i = 0; i < pairs.length; i++) {
1228 var pair = pairs[i].split("=");
1229 var name = decode(pair.shift());
1230 if (!name) {
1231 continue;
1232 }
1233 var arr = o[name];
1234 if (!(arr instanceof Array)) {
1235 arr = [];
1236 o[name] = arr;
1237 }
1238 arr.push(decode(pair.join("=")));
1239 }
1240 } else {
1241 for (var i = 0; i < pairs.length; i++) {
1242 pair = pairs[i].split("=");
1243 var name = pair.shift();
1244 if (!name) {
1245 continue;
1246 }
1247 o[decode(name)] = decode(pair.join("="));
1248 }
1249 }
1250 return o;
1251 }
1252});
1253
1254/** @id MochiKit.Base.AdapterRegistry */
1255MochiKit.Base.AdapterRegistry = function () {
1256 this.pairs = [];
1257};
1258
1259MochiKit.Base.AdapterRegistry.prototype = {
1260 /** @id MochiKit.Base.AdapterRegistry.prototype.register */
1261 register: function (name, check, wrap, /* optional */ override) {
1262 if (override) {
1263 this.pairs.unshift([name, check, wrap]);
1264 } else {
1265 this.pairs.push([name, check, wrap]);
1266 }
1267 },
1268
1269 /** @id MochiKit.Base.AdapterRegistry.prototype.match */
1270 match: function (/* ... */) {
1271 for (var i = 0; i < this.pairs.length; i++) {
1272 var pair = this.pairs[i];
1273 if (pair[1].apply(this, arguments)) {
1274 return pair[2].apply(this, arguments);
1275 }
1276 }
1277 throw MochiKit.Base.NotFound;
1278 },
1279
1280 /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
1281 unregister: function (name) {
1282 for (var i = 0; i < this.pairs.length; i++) {
1283 var pair = this.pairs[i];
1284 if (pair[0] == name) {
1285 this.pairs.splice(i, 1);
1286 return true;
1287 }
1288 }
1289 return false;
1290 }
1291};
1292
1293MochiKit.Base._exportSymbols = function (globals, module) {
1294 if (MochiKit.__export__ === false || module.__export__ === false) {
1295 return;
1296 }
1297 for (var k in module) {
1298 var v = module[k];
1299 if (v != null) {
1300 var okName = (k[0] !== "_" && k !== "toString");
1301 if (v.__export__ === true || (v.__export__ !== false && okName)) {
1302 globals[k] = module[k];
1303 }
1304 }
1305 }
1306};
1307
1308/**
1309 * Creates a deprecated function alias in the specified module. The
1310 * deprecated function will forward all calls and arguments to a
1311 * target function, while also logging a debug message on the first
1312 * call (if MochiKit.Logging is loaded). The destination function may
1313 * be located in another module, which must be loaded, or an
1314 * exception will be thrown.
1315 *
1316 * @param {Object/String} module the source module or module name
1317 * (e.g. 'DOM' or 'MochiKit.DOM')
1318 * @param {String} name the deprecated function name (e.g. 'getStyle')
1319 * @param {String} target the fully qualified name of the target
1320 * function (e.g. 'MochiKit.Style.getStyle')
1321 * @param {String} version the first version when the source function
1322 * was deprecated (e.g. '1.4')
1323 * @param {Boolean} [exportable] the exportable function flag,
1324 * defaults to true
1325 */
1326MochiKit.Base._deprecated = function (module, name, target, version, exportable) {
1327 if (typeof(module) === 'string') {
1328 if (module.indexOf('MochiKit.') === 0) {
1329 module = module.substring(9);
1330 }
1331 module = MochiKit[module];
1332 }
1333 var targetModule = target.split('.')[1];
1334 var targetName = target.split('.')[2];
1335 var func = function () {
1336 var self = arguments.callee;
1337 var msg = module.NAME + '.' + name + ' is deprecated since version ' +
1338 version + '. Use ' + target + ' instead.';
1339 if (self.logged !== true) {
1340 self.logged = true;
1341 if (MochiKit.Logging) {
1342 MochiKit.Logging.logDebug(msg);
1343 } else if (console && console.log) {
1344 console.log(msg);
1345 }
1346 }
1347 if (!MochiKit[targetModule]) {
1348 throw new Error(msg);
1349 }
1350 return MochiKit[targetModule][targetName].apply(this, arguments);
1351 };
1352 if (exportable === false) {
1353 func.__export__ = false;
1354 }
1355 module[name] = func;
1356}
1357
1358MochiKit.Base.__new__ = function () {
1359 var m = this;
1360
1361 /** @id MochiKit.Base.noop */
1362 m.noop = m.operator.identity;
1363
1364 // Backwards compat
1365 m._deprecated(m, 'forward', 'MochiKit.Base.forwardCall', '1.3', false);
1366 m._deprecated(m, 'find', 'MochiKit.Base.findValue', '1.3', false);
1367
1368 if (typeof(encodeURIComponent) != "undefined") {
1369 /** @id MochiKit.Base.urlEncode */
1370 m.urlEncode = function (unencoded) {
1371 return encodeURIComponent(unencoded).replace(/\'/g, '%27');
1372 };
1373 } else {
1374 m.urlEncode = function (unencoded) {
1375 return escape(unencoded
1376 ).replace(/\+/g, '%2B'
1377 ).replace(/\"/g,'%22'
1378 ).rval.replace(/\'/g, '%27');
1379 };
1380 }
1381
1382 /** @id MochiKit.Base.NamedError */
1383 m.NamedError = function (name) {
1384 this.message = name;
1385 this.name = name;
1386 };
1387 m.NamedError.prototype = new Error();
1388 m.update(m.NamedError.prototype, {
1389 repr: function () {
1390 if (this.message && this.message != this.name) {
1391 return this.name + "(" + m.repr(this.message) + ")";
1392 } else {
1393 return this.name + "()";
1394 }
1395 },
1396 toString: m.forwardCall("repr")
1397 });
1398
1399 /** @id MochiKit.Base.NotFound */
1400 m.NotFound = new m.NamedError("MochiKit.Base.NotFound");
1401
1402
1403 /** @id MochiKit.Base.listMax */
1404 m.listMax = m.partial(m.listMinMax, 1);
1405 /** @id MochiKit.Base.listMin */
1406 m.listMin = m.partial(m.listMinMax, -1);
1407
1408 /** @id MochiKit.Base.isCallable */
1409 m.isCallable = m.typeMatcher('function');
1410 /** @id MochiKit.Base.isUndefined */
1411 m.isUndefined = m.typeMatcher('undefined');
1412
1413 /** @id MochiKit.Base.merge */
1414 m.merge = m.partial(m.update, null);
1415 /** @id MochiKit.Base.zip */
1416 m.zip = m.partial(m.map, null);
1417
1418 /** @id MochiKit.Base.average */
1419 m.average = m.mean;
1420
1421 /** @id MochiKit.Base.comparatorRegistry */
1422 m.comparatorRegistry = new m.AdapterRegistry();
1423 m.registerComparator("dateLike", m.isDateLike, m.compareDateLike);
1424 m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike);
1425
1426 /** @id MochiKit.Base.reprRegistry */
1427 m.reprRegistry = new m.AdapterRegistry();
1428 m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
1429 m.registerRepr("string", m.typeMatcher("string"), m.reprString);
1430 m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);
1431
1432 /** @id MochiKit.Base.jsonRegistry */
1433 m.jsonRegistry = new m.AdapterRegistry();
1434
1435 m.nameFunctions(this);
1436
1437};
1438
1439MochiKit.Base.__new__();
1440
1441//
1442// XXX: Internet Explorer blows
1443//
1444if (MochiKit.__export__) {
1445 compare = MochiKit.Base.compare;
1446 compose = MochiKit.Base.compose;
1447 serializeJSON = MochiKit.Base.serializeJSON;
1448 mean = MochiKit.Base.mean;
1449 median = MochiKit.Base.median;
1450}
1451
1452MochiKit.Base._exportSymbols(this, MochiKit.Base);
diff --git a/frontend/gamma/js/MochiKit/Color.js b/frontend/gamma/js/MochiKit/Color.js
new file mode 100644
index 0000000..27dc2d0
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Color.js
@@ -0,0 +1,832 @@
1/***
2
3MochiKit.Color 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito and others. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('Color', '1.5', ['Base', 'DOM', 'Style']);
12
13/** @id MochiKit.Color.Color */
14MochiKit.Color.Color = function (red, green, blue, alpha) {
15 if (typeof(alpha) == 'undefined' || alpha === null) {
16 alpha = 1.0;
17 }
18 this.rgb = {
19 r: red,
20 g: green,
21 b: blue,
22 a: alpha
23 };
24};
25
26
27// Prototype methods
28
29MochiKit.Color.Color.prototype = {
30
31 __class__: MochiKit.Color.Color,
32
33 /** @id MochiKit.Color.Color.prototype.colorWithAlpha */
34 colorWithAlpha: function (alpha) {
35 var rgb = this.rgb;
36 var m = MochiKit.Color;
37 return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha);
38 },
39
40 /** @id MochiKit.Color.Color.prototype.colorWithHue */
41 colorWithHue: function (hue) {
42 // get an HSL model, and set the new hue...
43 var hsl = this.asHSL();
44 hsl.h = hue;
45 var m = MochiKit.Color;
46 // convert back to RGB...
47 return m.Color.fromHSL(hsl);
48 },
49
50 /** @id MochiKit.Color.Color.prototype.colorWithSaturation */
51 colorWithSaturation: function (saturation) {
52 // get an HSL model, and set the new hue...
53 var hsl = this.asHSL();
54 hsl.s = saturation;
55 var m = MochiKit.Color;
56 // convert back to RGB...
57 return m.Color.fromHSL(hsl);
58 },
59
60 /** @id MochiKit.Color.Color.prototype.colorWithLightness */
61 colorWithLightness: function (lightness) {
62 // get an HSL model, and set the new hue...
63 var hsl = this.asHSL();
64 hsl.l = lightness;
65 var m = MochiKit.Color;
66 // convert back to RGB...
67 return m.Color.fromHSL(hsl);
68 },
69
70 /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */
71 darkerColorWithLevel: function (level) {
72 var hsl = this.asHSL();
73 hsl.l = Math.max(hsl.l - level, 0);
74 var m = MochiKit.Color;
75 return m.Color.fromHSL(hsl);
76 },
77
78 /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
79 lighterColorWithLevel: function (level) {
80 var hsl = this.asHSL();
81 hsl.l = Math.min(hsl.l + level, 1);
82 var m = MochiKit.Color;
83 return m.Color.fromHSL(hsl);
84 },
85
86 /** @id MochiKit.Color.Color.prototype.blendedColor */
87 blendedColor: function (other, /* optional */ fraction) {
88 if (typeof(fraction) == 'undefined' || fraction === null) {
89 fraction = 0.5;
90 }
91 var sf = 1.0 - fraction;
92 var s = this.rgb;
93 var d = other.rgb;
94 var df = fraction;
95 return MochiKit.Color.Color.fromRGB(
96 (s.r * sf) + (d.r * df),
97 (s.g * sf) + (d.g * df),
98 (s.b * sf) + (d.b * df),
99 (s.a * sf) + (d.a * df)
100 );
101 },
102
103 /** @id MochiKit.Color.Color.prototype.compareRGB */
104 compareRGB: function (other) {
105 var a = this.asRGB();
106 var b = other.asRGB();
107 return MochiKit.Base.compare(
108 [a.r, a.g, a.b, a.a],
109 [b.r, b.g, b.b, b.a]
110 );
111 },
112
113 /** @id MochiKit.Color.Color.prototype.isLight */
114 isLight: function () {
115 return this.asHSL().b > 0.5;
116 },
117
118 /** @id MochiKit.Color.Color.prototype.isDark */
119 isDark: function () {
120 return (!this.isLight());
121 },
122
123 /** @id MochiKit.Color.Color.prototype.toHSLString */
124 toHSLString: function () {
125 var c = this.asHSL();
126 var ccc = MochiKit.Color.clampColorComponent;
127 var rval = this._hslString;
128 if (!rval) {
129 var mid = (
130 ccc(c.h, 360).toFixed(0)
131 + "," + ccc(c.s, 100).toPrecision(4) + "%"
132 + "," + ccc(c.l, 100).toPrecision(4) + "%"
133 );
134 var a = c.a;
135 if (a >= 1) {
136 a = 1;
137 rval = "hsl(" + mid + ")";
138 } else {
139 if (a <= 0) {
140 a = 0;
141 }
142 rval = "hsla(" + mid + "," + a + ")";
143 }
144 this._hslString = rval;
145 }
146 return rval;
147 },
148
149 /** @id MochiKit.Color.Color.prototype.toRGBString */
150 toRGBString: function () {
151 var c = this.rgb;
152 var ccc = MochiKit.Color.clampColorComponent;
153 var rval = this._rgbString;
154 if (!rval) {
155 var mid = (
156 ccc(c.r, 255).toFixed(0)
157 + "," + ccc(c.g, 255).toFixed(0)
158 + "," + ccc(c.b, 255).toFixed(0)
159 );
160 if (c.a != 1) {
161 rval = "rgba(" + mid + "," + c.a + ")";
162 } else {
163 rval = "rgb(" + mid + ")";
164 }
165 this._rgbString = rval;
166 }
167 return rval;
168 },
169
170 /** @id MochiKit.Color.Color.prototype.asRGB */
171 asRGB: function () {
172 return MochiKit.Base.clone(this.rgb);
173 },
174
175 /** @id MochiKit.Color.Color.prototype.toHexString */
176 toHexString: function () {
177 var m = MochiKit.Color;
178 var c = this.rgb;
179 var ccc = MochiKit.Color.clampColorComponent;
180 var rval = this._hexString;
181 if (!rval) {
182 rval = ("#" +
183 m.toColorPart(ccc(c.r, 255)) +
184 m.toColorPart(ccc(c.g, 255)) +
185 m.toColorPart(ccc(c.b, 255))
186 );
187 this._hexString = rval;
188 }
189 return rval;
190 },
191
192 /** @id MochiKit.Color.Color.prototype.asHSV */
193 asHSV: function () {
194 var hsv = this.hsv;
195 var c = this.rgb;
196 if (typeof(hsv) == 'undefined' || hsv === null) {
197 hsv = MochiKit.Color.rgbToHSV(this.rgb);
198 this.hsv = hsv;
199 }
200 return MochiKit.Base.clone(hsv);
201 },
202
203 /** @id MochiKit.Color.Color.prototype.asHSL */
204 asHSL: function () {
205 var hsl = this.hsl;
206 var c = this.rgb;
207 if (typeof(hsl) == 'undefined' || hsl === null) {
208 hsl = MochiKit.Color.rgbToHSL(this.rgb);
209 this.hsl = hsl;
210 }
211 return MochiKit.Base.clone(hsl);
212 },
213
214 /** @id MochiKit.Color.Color.prototype.toString */
215 toString: function () {
216 return this.toRGBString();
217 },
218
219 /** @id MochiKit.Color.Color.prototype.repr */
220 repr: function () {
221 var c = this.rgb;
222 var col = [c.r, c.g, c.b, c.a];
223 return this.__class__.NAME + "(" + col.join(", ") + ")";
224 }
225
226};
227
228// Constructor methods
229
230MochiKit.Base.update(MochiKit.Color.Color, {
231 /** @id MochiKit.Color.Color.fromRGB */
232 fromRGB: function (red, green, blue, alpha) {
233 // designated initializer
234 var Color = MochiKit.Color.Color;
235 if (arguments.length == 1) {
236 var rgb = red;
237 red = rgb.r;
238 green = rgb.g;
239 blue = rgb.b;
240 if (typeof(rgb.a) == 'undefined') {
241 alpha = undefined;
242 } else {
243 alpha = rgb.a;
244 }
245 }
246 return new Color(red, green, blue, alpha);
247 },
248
249 /** @id MochiKit.Color.Color.fromHSL */
250 fromHSL: function (hue, saturation, lightness, alpha) {
251 var m = MochiKit.Color;
252 return m.Color.fromRGB(m.hslToRGB.apply(m, arguments));
253 },
254
255 /** @id MochiKit.Color.Color.fromHSV */
256 fromHSV: function (hue, saturation, value, alpha) {
257 var m = MochiKit.Color;
258 return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments));
259 },
260
261 /** @id MochiKit.Color.Color.fromName */
262 fromName: function (name) {
263 var Color = MochiKit.Color.Color;
264 // Opera 9 seems to "quote" named colors(?!)
265 if (name.charAt(0) == '"') {
266 name = name.substr(1, name.length - 2);
267 }
268 var htmlColor = Color._namedColors[name.toLowerCase()];
269 if (typeof(htmlColor) == 'string') {
270 return Color.fromHexString(htmlColor);
271 } else if (name == "transparent") {
272 return Color.transparentColor();
273 }
274 return null;
275 },
276
277 /** @id MochiKit.Color.Color.fromString */
278 fromString: function (colorString) {
279 var self = MochiKit.Color.Color;
280 var three = colorString.substr(0, 3);
281 if (three == "rgb") {
282 return self.fromRGBString(colorString);
283 } else if (three == "hsl") {
284 return self.fromHSLString(colorString);
285 } else if (colorString.charAt(0) == "#") {
286 return self.fromHexString(colorString);
287 }
288 return self.fromName(colorString);
289 },
290
291
292 /** @id MochiKit.Color.Color.fromHexString */
293 fromHexString: function (hexCode) {
294 if (hexCode.charAt(0) == '#') {
295 hexCode = hexCode.substring(1);
296 }
297 var components = [];
298 var i, hex;
299 if (hexCode.length == 3) {
300 for (i = 0; i < 3; i++) {
301 hex = hexCode.substr(i, 1);
302 components.push(parseInt(hex + hex, 16) / 255.0);
303 }
304 } else {
305 for (i = 0; i < 6; i += 2) {
306 hex = hexCode.substr(i, 2);
307 components.push(parseInt(hex, 16) / 255.0);
308 }
309 }
310 var Color = MochiKit.Color.Color;
311 return Color.fromRGB.apply(Color, components);
312 },
313
314
315 _fromColorString: function (pre, method, scales, colorCode) {
316 // parses either HSL or RGB
317 if (colorCode.indexOf(pre) === 0) {
318 colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1);
319 }
320 var colorChunks = colorCode.split(/\s*,\s*/);
321 var colorFloats = [];
322 for (var i = 0; i < colorChunks.length; i++) {
323 var c = colorChunks[i];
324 var val;
325 var three = c.substring(c.length - 3);
326 if (c.charAt(c.length - 1) == '%') {
327 val = 0.01 * parseFloat(c.substring(0, c.length - 1));
328 } else if (three == "deg") {
329 val = parseFloat(c) / 360.0;
330 } else if (three == "rad") {
331 val = parseFloat(c) / (Math.PI * 2);
332 } else {
333 val = scales[i] * parseFloat(c);
334 }
335 colorFloats.push(val);
336 }
337 return this[method].apply(this, colorFloats);
338 },
339
340 /** @id MochiKit.Color.Color.fromComputedStyle */
341 fromComputedStyle: function (elem, style) {
342 var d = MochiKit.DOM;
343 var cls = MochiKit.Color.Color;
344 for (elem = d.getElement(elem); elem; elem = elem.parentNode) {
345 var actualColor = MochiKit.Style.getStyle.apply(d, arguments);
346 if (!actualColor) {
347 continue;
348 }
349 var color = cls.fromString(actualColor);
350 if (!color) {
351 break;
352 }
353 if (color.asRGB().a > 0) {
354 return color;
355 }
356 }
357 return null;
358 },
359
360 /** @id MochiKit.Color.Color.fromBackground */
361 fromBackground: function (elem) {
362 var cls = MochiKit.Color.Color;
363 return cls.fromComputedStyle(
364 elem, "backgroundColor", "background-color") || cls.whiteColor();
365 },
366
367 /** @id MochiKit.Color.Color.fromText */
368 fromText: function (elem) {
369 var cls = MochiKit.Color.Color;
370 return cls.fromComputedStyle(
371 elem, "color", "color") || cls.blackColor();
372 },
373
374 /** @id MochiKit.Color.Color.namedColors */
375 namedColors: function () {
376 return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
377 }
378});
379
380
381// Module level functions
382
383MochiKit.Base.update(MochiKit.Color, {
384 /** @id MochiKit.Color.clampColorComponent */
385 clampColorComponent: function (v, scale) {
386 v *= scale;
387 if (v < 0) {
388 return 0;
389 } else if (v > scale) {
390 return scale;
391 } else {
392 return v;
393 }
394 },
395
396 _hslValue: function (n1, n2, hue) {
397 if (hue > 6.0) {
398 hue -= 6.0;
399 } else if (hue < 0.0) {
400 hue += 6.0;
401 }
402 var val;
403 if (hue < 1.0) {
404 val = n1 + (n2 - n1) * hue;
405 } else if (hue < 3.0) {
406 val = n2;
407 } else if (hue < 4.0) {
408 val = n1 + (n2 - n1) * (4.0 - hue);
409 } else {
410 val = n1;
411 }
412 return val;
413 },
414
415 /** @id MochiKit.Color.hsvToRGB */
416 hsvToRGB: function (hue, saturation, value, alpha) {
417 if (arguments.length == 1) {
418 var hsv = hue;
419 hue = hsv.h;
420 saturation = hsv.s;
421 value = hsv.v;
422 alpha = hsv.a;
423 }
424 var red;
425 var green;
426 var blue;
427 if (saturation === 0) {
428 red = value;
429 green = value;
430 blue = value;
431 } else {
432 var i = Math.floor(hue * 6);
433 var f = (hue * 6) - i;
434 var p = value * (1 - saturation);
435 var q = value * (1 - (saturation * f));
436 var t = value * (1 - (saturation * (1 - f)));
437 switch (i) {
438 case 1: red = q; green = value; blue = p; break;
439 case 2: red = p; green = value; blue = t; break;
440 case 3: red = p; green = q; blue = value; break;
441 case 4: red = t; green = p; blue = value; break;
442 case 5: red = value; green = p; blue = q; break;
443 case 6: // fall through
444 case 0: red = value; green = t; blue = p; break;
445 }
446 }
447 return {
448 r: red,
449 g: green,
450 b: blue,
451 a: alpha
452 };
453 },
454
455 /** @id MochiKit.Color.hslToRGB */
456 hslToRGB: function (hue, saturation, lightness, alpha) {
457 if (arguments.length == 1) {
458 var hsl = hue;
459 hue = hsl.h;
460 saturation = hsl.s;
461 lightness = hsl.l;
462 alpha = hsl.a;
463 }
464 var red;
465 var green;
466 var blue;
467 if (saturation === 0) {
468 red = lightness;
469 green = lightness;
470 blue = lightness;
471 } else {
472 var m2;
473 if (lightness <= 0.5) {
474 m2 = lightness * (1.0 + saturation);
475 } else {
476 m2 = lightness + saturation - (lightness * saturation);
477 }
478 var m1 = (2.0 * lightness) - m2;
479 var f = MochiKit.Color._hslValue;
480 var h6 = hue * 6.0;
481 red = f(m1, m2, h6 + 2);
482 green = f(m1, m2, h6);
483 blue = f(m1, m2, h6 - 2);
484 }
485 return {
486 r: red,
487 g: green,
488 b: blue,
489 a: alpha
490 };
491 },
492
493 /** @id MochiKit.Color.rgbToHSV */
494 rgbToHSV: function (red, green, blue, alpha) {
495 if (arguments.length == 1) {
496 var rgb = red;
497 red = rgb.r;
498 green = rgb.g;
499 blue = rgb.b;
500 alpha = rgb.a;
501 }
502 var max = Math.max(Math.max(red, green), blue);
503 var min = Math.min(Math.min(red, green), blue);
504 var hue;
505 var saturation;
506 var value = max;
507 if (min == max) {
508 hue = 0;
509 saturation = 0;
510 } else {
511 var delta = (max - min);
512 saturation = delta / max;
513
514 if (red == max) {
515 hue = (green - blue) / delta;
516 } else if (green == max) {
517 hue = 2 + ((blue - red) / delta);
518 } else {
519 hue = 4 + ((red - green) / delta);
520 }
521 hue /= 6;
522 if (hue < 0) {
523 hue += 1;
524 }
525 if (hue > 1) {
526 hue -= 1;
527 }
528 }
529 return {
530 h: hue,
531 s: saturation,
532 v: value,
533 a: alpha
534 };
535 },
536
537 /** @id MochiKit.Color.rgbToHSL */
538 rgbToHSL: function (red, green, blue, alpha) {
539 if (arguments.length == 1) {
540 var rgb = red;
541 red = rgb.r;
542 green = rgb.g;
543 blue = rgb.b;
544 alpha = rgb.a;
545 }
546 var max = Math.max(red, Math.max(green, blue));
547 var min = Math.min(red, Math.min(green, blue));
548 var hue;
549 var saturation;
550 var lightness = (max + min) / 2.0;
551 var delta = max - min;
552 if (delta === 0) {
553 hue = 0;
554 saturation = 0;
555 } else {
556 if (lightness <= 0.5) {
557 saturation = delta / (max + min);
558 } else {
559 saturation = delta / (2 - max - min);
560 }
561 if (red == max) {
562 hue = (green - blue) / delta;
563 } else if (green == max) {
564 hue = 2 + ((blue - red) / delta);
565 } else {
566 hue = 4 + ((red - green) / delta);
567 }
568 hue /= 6;
569 if (hue < 0) {
570 hue += 1;
571 }
572 if (hue > 1) {
573 hue -= 1;
574 }
575
576 }
577 return {
578 h: hue,
579 s: saturation,
580 l: lightness,
581 a: alpha
582 };
583 },
584
585 /** @id MochiKit.Color.toColorPart */
586 toColorPart: function (num) {
587 num = Math.round(num);
588 var digits = num.toString(16);
589 if (num < 16) {
590 return '0' + digits;
591 }
592 return digits;
593 },
594
595 __new__: function () {
596 var m = MochiKit.Base;
597 /** @id MochiKit.Color.Color.fromRGBString */
598 this.Color.fromRGBString = m.bind(
599 this.Color._fromColorString, this.Color, "rgb", "fromRGB",
600 [1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
601 );
602 /** @id MochiKit.Color.Color.fromHSLString */
603 this.Color.fromHSLString = m.bind(
604 this.Color._fromColorString, this.Color, "hsl", "fromHSL",
605 [1.0/360.0, 0.01, 0.01, 1]
606 );
607
608 var third = 1.0 / 3.0;
609 /** @id MochiKit.Color.colors */
610 var colors = {
611 // NSColor colors plus transparent
612 /** @id MochiKit.Color.blackColor */
613 black: [0, 0, 0],
614 /** @id MochiKit.Color.blueColor */
615 blue: [0, 0, 1],
616 /** @id MochiKit.Color.brownColor */
617 brown: [0.6, 0.4, 0.2],
618 /** @id MochiKit.Color.cyanColor */
619 cyan: [0, 1, 1],
620 /** @id MochiKit.Color.darkGrayColor */
621 darkGray: [third, third, third],
622 /** @id MochiKit.Color.grayColor */
623 gray: [0.5, 0.5, 0.5],
624 /** @id MochiKit.Color.greenColor */
625 green: [0, 1, 0],
626 /** @id MochiKit.Color.lightGrayColor */
627 lightGray: [2 * third, 2 * third, 2 * third],
628 /** @id MochiKit.Color.magentaColor */
629 magenta: [1, 0, 1],
630 /** @id MochiKit.Color.orangeColor */
631 orange: [1, 0.5, 0],
632 /** @id MochiKit.Color.purpleColor */
633 purple: [0.5, 0, 0.5],
634 /** @id MochiKit.Color.redColor */
635 red: [1, 0, 0],
636 /** @id MochiKit.Color.transparentColor */
637 transparent: [0, 0, 0, 0],
638 /** @id MochiKit.Color.whiteColor */
639 white: [1, 1, 1],
640 /** @id MochiKit.Color.yellowColor */
641 yellow: [1, 1, 0]
642 };
643
644 var makeColor = function (name, r, g, b, a) {
645 var rval = this.fromRGB(r, g, b, a);
646 this[name] = function () { return rval; };
647 return rval;
648 };
649
650 for (var k in colors) {
651 var name = k + "Color";
652 var bindArgs = m.concat(
653 [makeColor, this.Color, name],
654 colors[k]
655 );
656 this.Color[name] = m.bind.apply(null, bindArgs);
657 }
658
659 var isColor = function () {
660 for (var i = 0; i < arguments.length; i++) {
661 if (!(arguments[i] instanceof MochiKit.Color.Color)) {
662 return false;
663 }
664 }
665 return true;
666 };
667
668 var compareColor = function (a, b) {
669 return a.compareRGB(b);
670 };
671
672 m.nameFunctions(this);
673
674 m.registerComparator(this.Color.NAME, isColor, compareColor);
675 }
676});
677
678MochiKit.Color.__new__();
679
680// Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
681
682MochiKit.Color.Color._namedColors = {
683 aliceblue: "#f0f8ff",
684 antiquewhite: "#faebd7",
685 aqua: "#00ffff",
686 aquamarine: "#7fffd4",
687 azure: "#f0ffff",
688 beige: "#f5f5dc",
689 bisque: "#ffe4c4",
690 black: "#000000",
691 blanchedalmond: "#ffebcd",
692 blue: "#0000ff",
693 blueviolet: "#8a2be2",
694 brown: "#a52a2a",
695 burlywood: "#deb887",
696 cadetblue: "#5f9ea0",
697 chartreuse: "#7fff00",
698 chocolate: "#d2691e",
699 coral: "#ff7f50",
700 cornflowerblue: "#6495ed",
701 cornsilk: "#fff8dc",
702 crimson: "#dc143c",
703 cyan: "#00ffff",
704 darkblue: "#00008b",
705 darkcyan: "#008b8b",
706 darkgoldenrod: "#b8860b",
707 darkgray: "#a9a9a9",
708 darkgreen: "#006400",
709 darkgrey: "#a9a9a9",
710 darkkhaki: "#bdb76b",
711 darkmagenta: "#8b008b",
712 darkolivegreen: "#556b2f",
713 darkorange: "#ff8c00",
714 darkorchid: "#9932cc",
715 darkred: "#8b0000",
716 darksalmon: "#e9967a",
717 darkseagreen: "#8fbc8f",
718 darkslateblue: "#483d8b",
719 darkslategray: "#2f4f4f",
720 darkslategrey: "#2f4f4f",
721 darkturquoise: "#00ced1",
722 darkviolet: "#9400d3",
723 deeppink: "#ff1493",
724 deepskyblue: "#00bfff",
725 dimgray: "#696969",
726 dimgrey: "#696969",
727 dodgerblue: "#1e90ff",
728 firebrick: "#b22222",
729 floralwhite: "#fffaf0",
730 forestgreen: "#228b22",
731 fuchsia: "#ff00ff",
732 gainsboro: "#dcdcdc",
733 ghostwhite: "#f8f8ff",
734 gold: "#ffd700",
735 goldenrod: "#daa520",
736 gray: "#808080",
737 green: "#008000",
738 greenyellow: "#adff2f",
739 grey: "#808080",
740 honeydew: "#f0fff0",
741 hotpink: "#ff69b4",
742 indianred: "#cd5c5c",
743 indigo: "#4b0082",
744 ivory: "#fffff0",
745 khaki: "#f0e68c",
746 lavender: "#e6e6fa",
747 lavenderblush: "#fff0f5",
748 lawngreen: "#7cfc00",
749 lemonchiffon: "#fffacd",
750 lightblue: "#add8e6",
751 lightcoral: "#f08080",
752 lightcyan: "#e0ffff",
753 lightgoldenrodyellow: "#fafad2",
754 lightgray: "#d3d3d3",
755 lightgreen: "#90ee90",
756 lightgrey: "#d3d3d3",
757 lightpink: "#ffb6c1",
758 lightsalmon: "#ffa07a",
759 lightseagreen: "#20b2aa",
760 lightskyblue: "#87cefa",
761 lightslategray: "#778899",
762 lightslategrey: "#778899",
763 lightsteelblue: "#b0c4de",
764 lightyellow: "#ffffe0",
765 lime: "#00ff00",
766 limegreen: "#32cd32",
767 linen: "#faf0e6",
768 magenta: "#ff00ff",
769 maroon: "#800000",
770 mediumaquamarine: "#66cdaa",
771 mediumblue: "#0000cd",
772 mediumorchid: "#ba55d3",
773 mediumpurple: "#9370db",
774 mediumseagreen: "#3cb371",
775 mediumslateblue: "#7b68ee",
776 mediumspringgreen: "#00fa9a",
777 mediumturquoise: "#48d1cc",
778 mediumvioletred: "#c71585",
779 midnightblue: "#191970",
780 mintcream: "#f5fffa",
781 mistyrose: "#ffe4e1",
782 moccasin: "#ffe4b5",
783 navajowhite: "#ffdead",
784 navy: "#000080",
785 oldlace: "#fdf5e6",
786 olive: "#808000",
787 olivedrab: "#6b8e23",
788 orange: "#ffa500",
789 orangered: "#ff4500",
790 orchid: "#da70d6",
791 palegoldenrod: "#eee8aa",
792 palegreen: "#98fb98",
793 paleturquoise: "#afeeee",
794 palevioletred: "#db7093",
795 papayawhip: "#ffefd5",
796 peachpuff: "#ffdab9",
797 peru: "#cd853f",
798 pink: "#ffc0cb",
799 plum: "#dda0dd",
800 powderblue: "#b0e0e6",
801 purple: "#800080",
802 red: "#ff0000",
803 rosybrown: "#bc8f8f",
804 royalblue: "#4169e1",
805 saddlebrown: "#8b4513",
806 salmon: "#fa8072",
807 sandybrown: "#f4a460",
808 seagreen: "#2e8b57",
809 seashell: "#fff5ee",
810 sienna: "#a0522d",
811 silver: "#c0c0c0",
812 skyblue: "#87ceeb",
813 slateblue: "#6a5acd",
814 slategray: "#708090",
815 slategrey: "#708090",
816 snow: "#fffafa",
817 springgreen: "#00ff7f",
818 steelblue: "#4682b4",
819 tan: "#d2b48c",
820 teal: "#008080",
821 thistle: "#d8bfd8",
822 tomato: "#ff6347",
823 turquoise: "#40e0d0",
824 violet: "#ee82ee",
825 wheat: "#f5deb3",
826 white: "#ffffff",
827 whitesmoke: "#f5f5f5",
828 yellow: "#ffff00",
829 yellowgreen: "#9acd32"
830};
831
832MochiKit.Base._exportSymbols(this, MochiKit.Color);
diff --git a/frontend/gamma/js/MochiKit/DOM.js b/frontend/gamma/js/MochiKit/DOM.js
new file mode 100644
index 0000000..af5d46f
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/DOM.js
@@ -0,0 +1,1144 @@
1/***
2
3MochiKit.DOM 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('DOM', '1.5', ['Base']);
12
13MochiKit.Base.update(MochiKit.DOM, {
14
15 /** @id MochiKit.DOM.currentWindow */
16 currentWindow: function () {
17 return MochiKit.DOM._window;
18 },
19
20 /** @id MochiKit.DOM.currentDocument */
21 currentDocument: function () {
22 return MochiKit.DOM._document;
23 },
24
25 /** @id MochiKit.DOM.withWindow */
26 withWindow: function (win, func) {
27 var self = MochiKit.DOM;
28 var oldDoc = self._document;
29 var oldWin = self._window;
30 var rval;
31 try {
32 self._window = win;
33 self._document = win.document;
34 rval = func();
35 } catch (e) {
36 self._window = oldWin;
37 self._document = oldDoc;
38 throw e;
39 }
40 self._window = oldWin;
41 self._document = oldDoc;
42 return rval;
43 },
44
45 /** @id MochiKit.DOM.formContents */
46 formContents: function (elem/* = document.body */) {
47 var names = [];
48 var values = [];
49 var m = MochiKit.Base;
50 var self = MochiKit.DOM;
51 if (typeof(elem) == "undefined" || elem === null) {
52 elem = self._document.body;
53 } else {
54 elem = self.getElement(elem);
55 }
56 m.nodeWalk(elem, function (elem) {
57 var name = elem.name;
58 if (m.isNotEmpty(name)) {
59 var tagName = elem.tagName.toUpperCase();
60 if (tagName === "INPUT"
61 && (elem.type == "radio" || elem.type == "checkbox")
62 && !elem.checked
63 ) {
64 return null;
65 }
66 if (tagName === "SELECT") {
67 if (elem.type == "select-one") {
68 if (elem.selectedIndex >= 0) {
69 var opt = elem.options[elem.selectedIndex];
70 var v = opt.value;
71 if (!v) {
72 var h = opt.outerHTML;
73 // internet explorer sure does suck.
74 if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
75 v = opt.text;
76 }
77 }
78 names.push(name);
79 values.push(v);
80 return null;
81 }
82 // no form elements?
83 names.push(name);
84 values.push("");
85 return null;
86 } else {
87 var opts = elem.options;
88 if (!opts.length) {
89 names.push(name);
90 values.push("");
91 return null;
92 }
93 for (var i = 0; i < opts.length; i++) {
94 var opt = opts[i];
95 if (!opt.selected) {
96 continue;
97 }
98 var v = opt.value;
99 if (!v) {
100 var h = opt.outerHTML;
101 // internet explorer sure does suck.
102 if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
103 v = opt.text;
104 }
105 }
106 names.push(name);
107 values.push(v);
108 }
109 return null;
110 }
111 }
112 if (tagName === "FORM" || tagName === "P" || tagName === "SPAN"
113 || tagName === "DIV"
114 ) {
115 return elem.childNodes;
116 }
117 names.push(name);
118 values.push(elem.value || '');
119 return null;
120 }
121 return elem.childNodes;
122 });
123 return [names, values];
124 },
125
126 /** @id MochiKit.DOM.withDocument */
127 withDocument: function (doc, func) {
128 var self = MochiKit.DOM;
129 var oldDoc = self._document;
130 var rval;
131 try {
132 self._document = doc;
133 rval = func();
134 } catch (e) {
135 self._document = oldDoc;
136 throw e;
137 }
138 self._document = oldDoc;
139 return rval;
140 },
141
142 /** @id MochiKit.DOM.registerDOMConverter */
143 registerDOMConverter: function (name, check, wrap, /* optional */override) {
144 MochiKit.DOM.domConverters.register(name, check, wrap, override);
145 },
146
147 /** @id MochiKit.DOM.coerceToDOM */
148 coerceToDOM: function (node, ctx) {
149 var m = MochiKit.Base;
150 var im = MochiKit.Iter;
151 var self = MochiKit.DOM;
152 if (im) {
153 var iter = im.iter;
154 var repeat = im.repeat;
155 }
156 var map = m.map;
157 var domConverters = self.domConverters;
158 var coerceToDOM = arguments.callee;
159 var NotFound = m.NotFound;
160 while (true) {
161 if (typeof(node) == 'undefined' || node === null) {
162 return null;
163 }
164 // this is a safari childNodes object, avoiding crashes w/ attr
165 // lookup
166 if (typeof(node) == "function" &&
167 typeof(node.length) == "number" &&
168 !(node instanceof Function)) {
169 node = im ? im.list(node) : m.extend(null, node);
170 }
171 if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) {
172 return node;
173 }
174 if (typeof(node) == 'number' || typeof(node) == 'boolean') {
175 node = node.toString();
176 // FALL THROUGH
177 }
178 if (typeof(node) == 'string') {
179 return self._document.createTextNode(node);
180 }
181 if (typeof(node.__dom__) == 'function') {
182 node = node.__dom__(ctx);
183 continue;
184 }
185 if (typeof(node.dom) == 'function') {
186 node = node.dom(ctx);
187 continue;
188 }
189 if (typeof(node) == 'function') {
190 node = node.apply(ctx, [ctx]);
191 continue;
192 }
193
194 if (im) {
195 // iterable
196 var iterNodes = null;
197 try {
198 iterNodes = iter(node);
199 } catch (e) {
200 // pass
201 }
202 if (iterNodes) {
203 return map(coerceToDOM, iterNodes, repeat(ctx));
204 }
205 } else if (m.isArrayLike(node)) {
206 var func = function (n) { return coerceToDOM(n, ctx); };
207 return map(func, node);
208 }
209
210 // adapter
211 try {
212 node = domConverters.match(node, ctx);
213 continue;
214 } catch (e) {
215 if (e != NotFound) {
216 throw e;
217 }
218 }
219
220 // fallback
221 return self._document.createTextNode(node.toString());
222 }
223 // mozilla warnings aren't too bright
224 return undefined;
225 },
226
227 /** @id MochiKit.DOM.isChildNode */
228 isChildNode: function (node, maybeparent) {
229 var self = MochiKit.DOM;
230 if (typeof(node) == "string") {
231 node = self.getElement(node);
232 }
233 if (typeof(maybeparent) == "string") {
234 maybeparent = self.getElement(maybeparent);
235 }
236 if (typeof(node) == 'undefined' || node === null) {
237 return false;
238 }
239 while (node != null && node !== self._document) {
240 if (node === maybeparent) {
241 return true;
242 }
243 node = node.parentNode;
244 }
245 return false;
246 },
247
248 /** @id MochiKit.DOM.setNodeAttribute */
249 setNodeAttribute: function (node, attr, value) {
250 var o = {};
251 o[attr] = value;
252 try {
253 return MochiKit.DOM.updateNodeAttributes(node, o);
254 } catch (e) {
255 // pass
256 }
257 return null;
258 },
259
260 /** @id MochiKit.DOM.getNodeAttribute */
261 getNodeAttribute: function (node, attr) {
262 var self = MochiKit.DOM;
263 var rename = self.attributeArray.renames[attr];
264 var ignoreValue = self.attributeArray.ignoreAttr[attr];
265 node = self.getElement(node);
266 try {
267 if (rename) {
268 return node[rename];
269 }
270 var value = node.getAttribute(attr);
271 if (value != ignoreValue) {
272 return value;
273 }
274 } catch (e) {
275 // pass
276 }
277 return null;
278 },
279
280 /** @id MochiKit.DOM.removeNodeAttribute */
281 removeNodeAttribute: function (node, attr) {
282 var self = MochiKit.DOM;
283 var rename = self.attributeArray.renames[attr];
284 node = self.getElement(node);
285 try {
286 if (rename) {
287 return node[rename];
288 }
289 return node.removeAttribute(attr);
290 } catch (e) {
291 // pass
292 }
293 return null;
294 },
295
296 /** @id MochiKit.DOM.updateNodeAttributes */
297 updateNodeAttributes: function (node, attrs) {
298 var elem = node;
299 var self = MochiKit.DOM;
300 if (typeof(node) == 'string') {
301 elem = self.getElement(node);
302 }
303 if (attrs) {
304 var updatetree = MochiKit.Base.updatetree;
305 if (self.attributeArray.compliant) {
306 // not IE, good.
307 for (var k in attrs) {
308 var v = attrs[k];
309 if (typeof(v) == 'object' && typeof(elem[k]) == 'object') {
310 if (k == "style" && MochiKit.Style) {
311 MochiKit.Style.setStyle(elem, v);
312 } else {
313 updatetree(elem[k], v);
314 }
315 } else if (k.substring(0, 2) == "on") {
316 if (typeof(v) == "string") {
317 v = new Function(v);
318 }
319 elem[k] = v;
320 } else {
321 elem.setAttribute(k, v);
322 }
323 if (typeof(elem[k]) == "string" && elem[k] != v) {
324 // Also set property for weird attributes (see #302)
325 elem[k] = v;
326 }
327 }
328 } else {
329 // IE is insane in the membrane
330 var renames = self.attributeArray.renames;
331 for (var k in attrs) {
332 v = attrs[k];
333 var renamed = renames[k];
334 if (k == "style" && typeof(v) == "string") {
335 elem.style.cssText = v;
336 } else if (typeof(renamed) == "string") {
337 elem[renamed] = v;
338 } else if (typeof(elem[k]) == 'object'
339 && typeof(v) == 'object') {
340 if (k == "style" && MochiKit.Style) {
341 MochiKit.Style.setStyle(elem, v);
342 } else {
343 updatetree(elem[k], v);
344 }
345 } else if (k.substring(0, 2) == "on") {
346 if (typeof(v) == "string") {
347 v = new Function(v);
348 }
349 elem[k] = v;
350 } else {
351 elem.setAttribute(k, v);
352 }
353 if (typeof(elem[k]) == "string" && elem[k] != v) {
354 // Also set property for weird attributes (see #302)
355 elem[k] = v;
356 }
357 }
358 }
359 }
360 return elem;
361 },
362
363 /** @id MochiKit.DOM.appendChildNodes */
364 appendChildNodes: function (node/*, nodes...*/) {
365 var elem = node;
366 var self = MochiKit.DOM;
367 if (typeof(node) == 'string') {
368 elem = self.getElement(node);
369 }
370 var nodeStack = [
371 self.coerceToDOM(
372 MochiKit.Base.extend(null, arguments, 1),
373 elem
374 )
375 ];
376 var concat = MochiKit.Base.concat;
377 while (nodeStack.length) {
378 var n = nodeStack.shift();
379 if (typeof(n) == 'undefined' || n === null) {
380 // pass
381 } else if (typeof(n.nodeType) == 'number') {
382 elem.appendChild(n);
383 } else {
384 nodeStack = concat(n, nodeStack);
385 }
386 }
387 return elem;
388 },
389
390
391 /** @id MochiKit.DOM.insertSiblingNodesBefore */
392 insertSiblingNodesBefore: function (node/*, nodes...*/) {
393 var elem = node;
394 var self = MochiKit.DOM;
395 if (typeof(node) == 'string') {
396 elem = self.getElement(node);
397 }
398 var nodeStack = [
399 self.coerceToDOM(
400 MochiKit.Base.extend(null, arguments, 1),
401 elem
402 )
403 ];
404 var parentnode = elem.parentNode;
405 var concat = MochiKit.Base.concat;
406 while (nodeStack.length) {
407 var n = nodeStack.shift();
408 if (typeof(n) == 'undefined' || n === null) {
409 // pass
410 } else if (typeof(n.nodeType) == 'number') {
411 parentnode.insertBefore(n, elem);
412 } else {
413 nodeStack = concat(n, nodeStack);
414 }
415 }
416 return parentnode;
417 },
418
419 /** @id MochiKit.DOM.insertSiblingNodesAfter */
420 insertSiblingNodesAfter: function (node/*, nodes...*/) {
421 var elem = node;
422 var self = MochiKit.DOM;
423
424 if (typeof(node) == 'string') {
425 elem = self.getElement(node);
426 }
427 var nodeStack = [
428 self.coerceToDOM(
429 MochiKit.Base.extend(null, arguments, 1),
430 elem
431 )
432 ];
433
434 if (elem.nextSibling) {
435 return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack);
436 }
437 else {
438 return self.appendChildNodes(elem.parentNode, nodeStack);
439 }
440 },
441
442 /** @id MochiKit.DOM.replaceChildNodes */
443 replaceChildNodes: function (node/*, nodes...*/) {
444 var elem = node;
445 var self = MochiKit.DOM;
446 if (typeof(node) == 'string') {
447 elem = self.getElement(node);
448 arguments[0] = elem;
449 }
450 var child;
451 while ((child = elem.firstChild)) {
452 elem.removeChild(child);
453 }
454 if (arguments.length < 2) {
455 return elem;
456 } else {
457 return self.appendChildNodes.apply(this, arguments);
458 }
459 },
460
461 /** @id MochiKit.DOM.createDOM */
462 createDOM: function (name, attrs/*, nodes... */) {
463 var elem;
464 var self = MochiKit.DOM;
465 var m = MochiKit.Base;
466 if (typeof(attrs) == "string" || typeof(attrs) == "number") {
467 var args = m.extend([name, null], arguments, 1);
468 return arguments.callee.apply(this, args);
469 }
470 if (typeof(name) == 'string') {
471 // Internet Explorer is dumb
472 var xhtml = self._xhtml;
473 if (attrs && !self.attributeArray.compliant) {
474 // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp
475 var contents = "";
476 if ('name' in attrs) {
477 contents += ' name="' + self.escapeHTML(attrs.name) + '"';
478 }
479 if (name == 'input' && 'type' in attrs) {
480 contents += ' type="' + self.escapeHTML(attrs.type) + '"';
481 }
482 if (contents) {
483 name = "<" + name + contents + ">";
484 xhtml = false;
485 }
486 }
487 var d = self._document;
488 if (xhtml && d === document) {
489 elem = d.createElementNS("http://www.w3.org/1999/xhtml", name);
490 } else {
491 elem = d.createElement(name);
492 }
493 } else {
494 elem = name;
495 }
496 if (attrs) {
497 self.updateNodeAttributes(elem, attrs);
498 }
499 if (arguments.length <= 2) {
500 return elem;
501 } else {
502 var args = m.extend([elem], arguments, 2);
503 return self.appendChildNodes.apply(this, args);
504 }
505 },
506
507 /** @id MochiKit.DOM.createDOMFunc */
508 createDOMFunc: function (/* tag, attrs, *nodes */) {
509 var m = MochiKit.Base;
510 return m.partial.apply(
511 this,
512 m.extend([MochiKit.DOM.createDOM], arguments)
513 );
514 },
515
516 /** @id MochiKit.DOM.removeElement */
517 removeElement: function (elem) {
518 var self = MochiKit.DOM;
519 if (typeof(elem) == "string") {
520 elem = self.getElement(elem);
521 }
522 var e = self.coerceToDOM(elem);
523 e.parentNode.removeChild(e);
524 return e;
525 },
526
527 /** @id MochiKit.DOM.swapDOM */
528 swapDOM: function (dest, src) {
529 var self = MochiKit.DOM;
530 dest = self.getElement(dest);
531 var parent = dest.parentNode;
532 if (src) {
533 if (typeof(src) == "string") {
534 src = self.getElement(src);
535 }
536 src = self.coerceToDOM(src, parent);
537 parent.replaceChild(src, dest);
538 } else {
539 parent.removeChild(dest);
540 }
541 return src;
542 },
543
544 /** @id MochiKit.DOM.getElement */
545 getElement: function (id) {
546 var self = MochiKit.DOM;
547 if (arguments.length == 1) {
548 return ((typeof(id) == "string") ?
549 self._document.getElementById(id) : id);
550 } else {
551 return MochiKit.Base.map(self.getElement, arguments);
552 }
553 },
554
555 /** @id MochiKit.DOM.getElementsByTagAndClassName */
556 getElementsByTagAndClassName: function (tagName, className,
557 /* optional */parent) {
558 var self = MochiKit.DOM;
559 if (typeof(tagName) == 'undefined' || tagName === null) {
560 tagName = '*';
561 }
562 if (typeof(parent) == 'undefined' || parent === null) {
563 parent = self._document;
564 }
565 parent = self.getElement(parent);
566 if (parent == null) {
567 return [];
568 }
569 var children = (parent.getElementsByTagName(tagName)
570 || self._document.all);
571 if (typeof(className) == 'undefined' || className === null) {
572 return MochiKit.Base.extend(null, children);
573 }
574
575 var elements = [];
576 for (var i = 0; i < children.length; i++) {
577 var child = children[i];
578 var cls = child.className;
579 if (typeof(cls) != "string") {
580 cls = child.getAttribute("class");
581 }
582 if (typeof(cls) == "string") {
583 var classNames = cls.split(' ');
584 for (var j = 0; j < classNames.length; j++) {
585 if (classNames[j] == className) {
586 elements.push(child);
587 break;
588 }
589 }
590 }
591 }
592
593 return elements;
594 },
595
596 _newCallStack: function (path, once) {
597 var rval = function () {
598 var callStack = arguments.callee.callStack;
599 for (var i = 0; i < callStack.length; i++) {
600 if (callStack[i].apply(this, arguments) === false) {
601 break;
602 }
603 }
604 if (once) {
605 try {
606 this[path] = null;
607 } catch (e) {
608 // pass
609 }
610 }
611 };
612 rval.callStack = [];
613 return rval;
614 },
615
616 /** @id MochiKit.DOM.addToCallStack */
617 addToCallStack: function (target, path, func, once) {
618 var self = MochiKit.DOM;
619 var existing = target[path];
620 var regfunc = existing;
621 if (!(typeof(existing) == 'function'
622 && typeof(existing.callStack) == "object"
623 && existing.callStack !== null)) {
624 regfunc = self._newCallStack(path, once);
625 if (typeof(existing) == 'function') {
626 regfunc.callStack.push(existing);
627 }
628 target[path] = regfunc;
629 }
630 regfunc.callStack.push(func);
631 },
632
633 /** @id MochiKit.DOM.addLoadEvent */
634 addLoadEvent: function (func) {
635 var self = MochiKit.DOM;
636 self.addToCallStack(self._window, "onload", func, true);
637
638 },
639
640 /** @id MochiKit.DOM.focusOnLoad */
641 focusOnLoad: function (element) {
642 var self = MochiKit.DOM;
643 self.addLoadEvent(function () {
644 element = self.getElement(element);
645 if (element) {
646 element.focus();
647 }
648 });
649 },
650
651 /** @id MochiKit.DOM.setElementClass */
652 setElementClass: function (element, className) {
653 var self = MochiKit.DOM;
654 var obj = self.getElement(element);
655 if (self.attributeArray.compliant) {
656 obj.setAttribute("class", className);
657 } else {
658 obj.setAttribute("className", className);
659 }
660 },
661
662 /** @id MochiKit.DOM.toggleElementClass */
663 toggleElementClass: function (className/*, element... */) {
664 var self = MochiKit.DOM;
665 for (var i = 1; i < arguments.length; i++) {
666 var obj = self.getElement(arguments[i]);
667 if (!self.addElementClass(obj, className)) {
668 self.removeElementClass(obj, className);
669 }
670 }
671 },
672
673 /** @id MochiKit.DOM.addElementClass */
674 addElementClass: function (element, className) {
675 var self = MochiKit.DOM;
676 var obj = self.getElement(element);
677 var cls = obj.className;
678 if (typeof(cls) != "string") {
679 cls = obj.getAttribute("class");
680 }
681 // trivial case, no className yet
682 if (typeof(cls) != "string" || cls.length === 0) {
683 self.setElementClass(obj, className);
684 return true;
685 }
686 // the other trivial case, already set as the only class
687 if (cls == className) {
688 return false;
689 }
690 var classes = cls.split(" ");
691 for (var i = 0; i < classes.length; i++) {
692 // already present
693 if (classes[i] == className) {
694 return false;
695 }
696 }
697 // append class
698 self.setElementClass(obj, cls + " " + className);
699 return true;
700 },
701
702 /** @id MochiKit.DOM.removeElementClass */
703 removeElementClass: function (element, className) {
704 var self = MochiKit.DOM;
705 var obj = self.getElement(element);
706 var cls = obj.className;
707 if (typeof(cls) != "string") {
708 cls = obj.getAttribute("class");
709 }
710 // trivial case, no className yet
711 if (typeof(cls) != "string" || cls.length === 0) {
712 return false;
713 }
714 // other trivial case, set only to className
715 if (cls == className) {
716 self.setElementClass(obj, "");
717 return true;
718 }
719 var classes = cls.split(" ");
720 for (var i = 0; i < classes.length; i++) {
721 // already present
722 if (classes[i] == className) {
723 // only check sane case where the class is used once
724 classes.splice(i, 1);
725 self.setElementClass(obj, classes.join(" "));
726 return true;
727 }
728 }
729 // not found
730 return false;
731 },
732
733 /** @id MochiKit.DOM.swapElementClass */
734 swapElementClass: function (element, fromClass, toClass) {
735 var obj = MochiKit.DOM.getElement(element);
736 var res = MochiKit.DOM.removeElementClass(obj, fromClass);
737 if (res) {
738 MochiKit.DOM.addElementClass(obj, toClass);
739 }
740 return res;
741 },
742
743 /** @id MochiKit.DOM.hasElementClass */
744 hasElementClass: function (element, className/*...*/) {
745 var obj = MochiKit.DOM.getElement(element);
746 if (obj == null) {
747 return false;
748 }
749 var cls = obj.className;
750 if (typeof(cls) != "string" && typeof(obj.getAttribute) == "function") {
751 cls = obj.getAttribute("class");
752 }
753 if (typeof(cls) != "string") {
754 return false;
755 }
756 var classes = cls.split(" ");
757 for (var i = 1; i < arguments.length; i++) {
758 var good = false;
759 for (var j = 0; j < classes.length; j++) {
760 if (classes[j] == arguments[i]) {
761 good = true;
762 break;
763 }
764 }
765 if (!good) {
766 return false;
767 }
768 }
769 return true;
770 },
771
772 /** @id MochiKit.DOM.escapeHTML */
773 escapeHTML: function (s) {
774 return s.replace(/&/g, "&amp;"
775 ).replace(/"/g, "&quot;"
776 ).replace(/</g, "&lt;"
777 ).replace(/>/g, "&gt;");
778 },
779
780 /** @id MochiKit.DOM.toHTML */
781 toHTML: function (dom) {
782 return MochiKit.DOM.emitHTML(dom).join("");
783 },
784
785 /** @id MochiKit.DOM.emitHTML */
786 emitHTML: function (dom, /* optional */lst) {
787 if (typeof(lst) == 'undefined' || lst === null) {
788 lst = [];
789 }
790 // queue is the call stack, we're doing this non-recursively
791 var queue = [dom];
792 var self = MochiKit.DOM;
793 var escapeHTML = self.escapeHTML;
794 var attributeArray = self.attributeArray;
795 while (queue.length) {
796 dom = queue.pop();
797 if (typeof(dom) == 'string') {
798 lst.push(dom);
799 } else if (dom.nodeType == 1) {
800 // we're not using higher order stuff here
801 // because safari has heisenbugs.. argh.
802 //
803 // I think it might have something to do with
804 // garbage collection and function calls.
805 lst.push('<' + dom.tagName.toLowerCase());
806 var attributes = [];
807 var domAttr = attributeArray(dom);
808 for (var i = 0; i < domAttr.length; i++) {
809 var a = domAttr[i];
810 attributes.push([
811 " ",
812 a.name,
813 '="',
814 escapeHTML(a.value),
815 '"'
816 ]);
817 }
818 attributes.sort();
819 for (i = 0; i < attributes.length; i++) {
820 var attrs = attributes[i];
821 for (var j = 0; j < attrs.length; j++) {
822 lst.push(attrs[j]);
823 }
824 }
825 if (dom.hasChildNodes()) {
826 lst.push(">");
827 // queue is the FILO call stack, so we put the close tag
828 // on first
829 queue.push("</" + dom.tagName.toLowerCase() + ">");
830 var cnodes = dom.childNodes;
831 for (i = cnodes.length - 1; i >= 0; i--) {
832 queue.push(cnodes[i]);
833 }
834 } else {
835 lst.push('/>');
836 }
837 } else if (dom.nodeType == 3) {
838 lst.push(escapeHTML(dom.nodeValue));
839 }
840 }
841 return lst;
842 },
843
844 /** @id MochiKit.DOM.scrapeText */
845 scrapeText: function (node, /* optional */asArray) {
846 var rval = [];
847 (function (node) {
848 var cn = node.childNodes;
849 if (cn) {
850 for (var i = 0; i < cn.length; i++) {
851 arguments.callee.call(this, cn[i]);
852 }
853 }
854 var nodeValue = node.nodeValue;
855 if (typeof(nodeValue) == 'string') {
856 rval.push(nodeValue);
857 }
858 })(MochiKit.DOM.getElement(node));
859 if (asArray) {
860 return rval;
861 } else {
862 return rval.join("");
863 }
864 },
865
866 /** @id MochiKit.DOM.removeEmptyTextNodes */
867 removeEmptyTextNodes: function (element) {
868 element = MochiKit.DOM.getElement(element);
869 for (var i = 0; i < element.childNodes.length; i++) {
870 var node = element.childNodes[i];
871 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
872 node.parentNode.removeChild(node);
873 }
874 }
875 },
876
877 /** @id MochiKit.DOM.getFirstElementByTagAndClassName */
878 getFirstElementByTagAndClassName: function (tagName, className,
879 /* optional */parent) {
880 var self = MochiKit.DOM;
881 if (typeof(tagName) == 'undefined' || tagName === null) {
882 tagName = '*';
883 }
884 if (typeof(parent) == 'undefined' || parent === null) {
885 parent = self._document;
886 }
887 parent = self.getElement(parent);
888 if (parent == null) {
889 return null;
890 }
891 var children = (parent.getElementsByTagName(tagName)
892 || self._document.all);
893 if (children.length <= 0) {
894 return null;
895 } else if (typeof(className) == 'undefined' || className === null) {
896 return children[0];
897 }
898
899 for (var i = 0; i < children.length; i++) {
900 var child = children[i];
901 var cls = child.className;
902 if (typeof(cls) != "string") {
903 cls = child.getAttribute("class");
904 }
905 if (typeof(cls) == "string") {
906 var classNames = cls.split(' ');
907 for (var j = 0; j < classNames.length; j++) {
908 if (classNames[j] == className) {
909 return child;
910 }
911 }
912 }
913 }
914 return null;
915 },
916
917 /** @id MochiKit.DOM.getFirstParentByTagAndClassName */
918 getFirstParentByTagAndClassName: function (elem, tagName, className) {
919 var self = MochiKit.DOM;
920 elem = self.getElement(elem);
921 if (typeof(tagName) == 'undefined' || tagName === null) {
922 tagName = '*';
923 } else {
924 tagName = tagName.toUpperCase();
925 }
926 if (typeof(className) == 'undefined' || className === null) {
927 className = null;
928 }
929 if (elem) {
930 elem = elem.parentNode;
931 }
932 while (elem && elem.tagName) {
933 var curTagName = elem.tagName.toUpperCase();
934 if ((tagName === '*' || tagName == curTagName) &&
935 (className === null || self.hasElementClass(elem, className))) {
936 return elem;
937 }
938 elem = elem.parentNode;
939 }
940 return null;
941 },
942
943 __new__: function (win) {
944
945 var m = MochiKit.Base;
946 if (typeof(document) != "undefined") {
947 this._document = document;
948 var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
949 this._xhtml = (document.documentElement &&
950 document.createElementNS &&
951 document.documentElement.namespaceURI === kXULNSURI);
952 } else if (MochiKit.MockDOM) {
953 this._document = MochiKit.MockDOM.document;
954 }
955 this._window = win;
956
957 this.domConverters = new m.AdapterRegistry();
958
959 var __tmpElement = this._document.createElement("span");
960 var attributeArray;
961 if (__tmpElement && __tmpElement.attributes &&
962 __tmpElement.attributes.length > 0) {
963 // for braindead browsers (IE) that insert extra junk
964 var filter = m.filter;
965 attributeArray = function (node) {
966 /***
967
968 Return an array of attributes for a given node,
969 filtering out attributes that don't belong for
970 that are inserted by "Certain Browsers".
971
972 ***/
973 return filter(attributeArray.ignoreAttrFilter, node.attributes);
974 };
975 attributeArray.ignoreAttr = {};
976 var attrs = __tmpElement.attributes;
977 var ignoreAttr = attributeArray.ignoreAttr;
978 for (var i = 0; i < attrs.length; i++) {
979 var a = attrs[i];
980 ignoreAttr[a.name] = a.value;
981 }
982 attributeArray.ignoreAttrFilter = function (a) {
983 return (attributeArray.ignoreAttr[a.name] != a.value);
984 };
985 attributeArray.compliant = false;
986 attributeArray.renames = {
987 "class": "className",
988 "checked": "defaultChecked",
989 "usemap": "useMap",
990 "for": "htmlFor",
991 "readonly": "readOnly",
992 "colspan": "colSpan",
993 "bgcolor": "bgColor",
994 "cellspacing": "cellSpacing",
995 "cellpadding": "cellPadding"
996 };
997 } else {
998 attributeArray = function (node) {
999 return node.attributes;
1000 };
1001 attributeArray.compliant = true;
1002 attributeArray.ignoreAttr = {};
1003 attributeArray.renames = {};
1004 }
1005 attributeArray.__export__ = false;
1006 this.attributeArray = attributeArray;
1007
1008 // Backwards compatibility aliases
1009 /** @id MochiKit.DOM.computedStyle */
1010 m._deprecated(this, 'computedStyle', 'MochiKit.Style.getStyle', '1.4');
1011 /** @id MochiKit.DOM.elementDimensions */
1012 m._deprecated(this, 'elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4');
1013 /** @id MochiKit.DOM.elementPosition */
1014 m._deprecated(this, 'elementPosition', 'MochiKit.Style.getElementPosition', '1.4');
1015 /** @id MochiKit.DOM.getViewportDimensions */
1016 m._deprecated(this, 'getViewportDimensions', 'MochiKit.Style.getViewportDimensions', '1.4');
1017 /** @id MochiKit.DOM.hideElement */
1018 m._deprecated(this, 'hideElement', 'MochiKit.Style.hideElement', '1.4');
1019 /** @id MochiKit.DOM.makeClipping */
1020 m._deprecated(this, 'makeClipping', 'MochiKit.Style.makeClipping', '1.4.1');
1021 /** @id MochiKit.DOM.makePositioned */
1022 m._deprecated(this, 'makePositioned', 'MochiKit.Style.makePositioned', '1.4.1');
1023 /** @id MochiKit.DOM.setElementDimensions */
1024 m._deprecated(this, 'setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4');
1025 /** @id MochiKit.DOM.setElementPosition */
1026 m._deprecated(this, 'setElementPosition', 'MochiKit.Style.setElementPosition', '1.4');
1027 /** @id MochiKit.DOM.setDisplayForElement */
1028 m._deprecated(this, 'setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4');
1029 /** @id MochiKit.DOM.setOpacity */
1030 m._deprecated(this, 'setOpacity', 'MochiKit.Style.setOpacity', '1.4');
1031 /** @id MochiKit.DOM.showElement */
1032 m._deprecated(this, 'showElement', 'MochiKit.Style.showElement', '1.4');
1033 /** @id MochiKit.DOM.undoClipping */
1034 m._deprecated(this, 'undoClipping', 'MochiKit.Style.undoClipping', '1.4.1');
1035 /** @id MochiKit.DOM.undoPositioned */
1036 m._deprecated(this, 'undoPositioned', 'MochiKit.Style.undoPositioned', '1.4.1');
1037 /** @id MochiKit.DOM.Coordinates */
1038 m._deprecated(this, 'Coordinates', 'MochiKit.Style.Coordinates', '1.4');
1039 /** @id MochiKit.DOM.Dimensions */
1040 m._deprecated(this, 'Dimensions', 'MochiKit.Style.Dimensions', '1.4');
1041
1042 // shorthand for createDOM syntax
1043 var createDOMFunc = this.createDOMFunc;
1044 /** @id MochiKit.DOM.UL */
1045 this.UL = createDOMFunc("ul");
1046 /** @id MochiKit.DOM.OL */
1047 this.OL = createDOMFunc("ol");
1048 /** @id MochiKit.DOM.LI */
1049 this.LI = createDOMFunc("li");
1050 /** @id MochiKit.DOM.DL */
1051 this.DL = createDOMFunc("dl");
1052 /** @id MochiKit.DOM.DT */
1053 this.DT = createDOMFunc("dt");
1054 /** @id MochiKit.DOM.DD */
1055 this.DD = createDOMFunc("dd");
1056 /** @id MochiKit.DOM.TD */
1057 this.TD = createDOMFunc("td");
1058 /** @id MochiKit.DOM.TR */
1059 this.TR = createDOMFunc("tr");
1060 /** @id MochiKit.DOM.TBODY */
1061 this.TBODY = createDOMFunc("tbody");
1062 /** @id MochiKit.DOM.THEAD */
1063 this.THEAD = createDOMFunc("thead");
1064 /** @id MochiKit.DOM.TFOOT */
1065 this.TFOOT = createDOMFunc("tfoot");
1066 /** @id MochiKit.DOM.TABLE */
1067 this.TABLE = createDOMFunc("table");
1068 /** @id MochiKit.DOM.TH */
1069 this.TH = createDOMFunc("th");
1070 /** @id MochiKit.DOM.INPUT */
1071 this.INPUT = createDOMFunc("input");
1072 /** @id MochiKit.DOM.SPAN */
1073 this.SPAN = createDOMFunc("span");
1074 /** @id MochiKit.DOM.A */
1075 this.A = createDOMFunc("a");
1076 /** @id MochiKit.DOM.DIV */
1077 this.DIV = createDOMFunc("div");
1078 /** @id MochiKit.DOM.IMG */
1079 this.IMG = createDOMFunc("img");
1080 /** @id MochiKit.DOM.BUTTON */
1081 this.BUTTON = createDOMFunc("button");
1082 /** @id MochiKit.DOM.TT */
1083 this.TT = createDOMFunc("tt");
1084 /** @id MochiKit.DOM.PRE */
1085 this.PRE = createDOMFunc("pre");
1086 /** @id MochiKit.DOM.H1 */
1087 this.H1 = createDOMFunc("h1");
1088 /** @id MochiKit.DOM.H2 */
1089 this.H2 = createDOMFunc("h2");
1090 /** @id MochiKit.DOM.H3 */
1091 this.H3 = createDOMFunc("h3");
1092 /** @id MochiKit.DOM.H4 */
1093 this.H4 = createDOMFunc("h4");
1094 /** @id MochiKit.DOM.H5 */
1095 this.H5 = createDOMFunc("h5");
1096 /** @id MochiKit.DOM.H6 */
1097 this.H6 = createDOMFunc("h6");
1098 /** @id MochiKit.DOM.BR */
1099 this.BR = createDOMFunc("br");
1100 /** @id MochiKit.DOM.HR */
1101 this.HR = createDOMFunc("hr");
1102 /** @id MochiKit.DOM.LABEL */
1103 this.LABEL = createDOMFunc("label");
1104 /** @id MochiKit.DOM.TEXTAREA */
1105 this.TEXTAREA = createDOMFunc("textarea");
1106 /** @id MochiKit.DOM.FORM */
1107 this.FORM = createDOMFunc("form");
1108 /** @id MochiKit.DOM.P */
1109 this.P = createDOMFunc("p");
1110 /** @id MochiKit.DOM.SELECT */
1111 this.SELECT = createDOMFunc("select");
1112 /** @id MochiKit.DOM.OPTION */
1113 this.OPTION = createDOMFunc("option");
1114 /** @id MochiKit.DOM.OPTGROUP */
1115 this.OPTGROUP = createDOMFunc("optgroup");
1116 /** @id MochiKit.DOM.LEGEND */
1117 this.LEGEND = createDOMFunc("legend");
1118 /** @id MochiKit.DOM.FIELDSET */
1119 this.FIELDSET = createDOMFunc("fieldset");
1120 /** @id MochiKit.DOM.STRONG */
1121 this.STRONG = createDOMFunc("strong");
1122 /** @id MochiKit.DOM.CANVAS */
1123 this.CANVAS = createDOMFunc("canvas");
1124
1125 /** @id MochiKit.DOM.$ */
1126 this.$ = this.getElement;
1127
1128 m.nameFunctions(this);
1129
1130 }
1131});
1132
1133
1134MochiKit.DOM.__new__(((typeof(window) == "undefined") ? this : window));
1135
1136//
1137// XXX: Internet Explorer blows
1138//
1139if (MochiKit.__export__) {
1140 withWindow = MochiKit.DOM.withWindow;
1141 withDocument = MochiKit.DOM.withDocument;
1142}
1143
1144MochiKit.Base._exportSymbols(this, MochiKit.DOM);
diff --git a/frontend/gamma/js/MochiKit/DateTime.js b/frontend/gamma/js/MochiKit/DateTime.js
new file mode 100644
index 0000000..c7b2d25
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/DateTime.js
@@ -0,0 +1,173 @@
1/***
2
3MochiKit.DateTime 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('DateTime', '1.5', ['Base']);
12
13/** @id MochiKit.DateTime.isoDate */
14MochiKit.DateTime.isoDate = function (str) {
15 str = str + "";
16 if (typeof(str) != "string" || str.length === 0) {
17 return null;
18 }
19 var iso = str.split('-');
20 if (iso.length === 0) {
21 return null;
22 }
23 var date = new Date(iso[0], iso[1] - 1, iso[2]);
24 date.setFullYear(iso[0]);
25 date.setMonth(iso[1] - 1);
26 date.setDate(iso[2]);
27 return date;
28};
29
30MochiKit.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}))?)?)?)?)?/;
31
32/** @id MochiKit.DateTime.isoTimestamp */
33MochiKit.DateTime.isoTimestamp = function (str) {
34 str = str + "";
35 if (typeof(str) != "string" || str.length === 0) {
36 return null;
37 }
38 var res = str.match(MochiKit.DateTime._isoRegexp);
39 if (typeof(res) == "undefined" || res === null) {
40 return null;
41 }
42 var year, month, day, hour, min, sec, msec;
43 year = parseInt(res[1], 10);
44 if (typeof(res[2]) == "undefined" || res[2] === '') {
45 return new Date(year);
46 }
47 month = parseInt(res[2], 10) - 1;
48 day = parseInt(res[3], 10);
49 if (typeof(res[4]) == "undefined" || res[4] === '') {
50 return new Date(year, month, day);
51 }
52 hour = parseInt(res[4], 10);
53 min = parseInt(res[5], 10);
54 sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0;
55 if (typeof(res[7]) != "undefined" && res[7] !== '') {
56 msec = Math.round(1000.0 * parseFloat("0." + res[7]));
57 } else {
58 msec = 0;
59 }
60 if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) {
61 return new Date(year, month, day, hour, min, sec, msec);
62 }
63 var ofs;
64 if (typeof(res[9]) != "undefined" && res[9] !== '') {
65 ofs = parseInt(res[10], 10) * 3600000;
66 if (typeof(res[11]) != "undefined" && res[11] !== '') {
67 ofs += parseInt(res[11], 10) * 60000;
68 }
69 if (res[9] == "-") {
70 ofs = -ofs;
71 }
72 } else {
73 ofs = 0;
74 }
75 return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs);
76};
77
78/** @id MochiKit.DateTime.toISOTime */
79MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) {
80 if (typeof(date) == "undefined" || date === null) {
81 return null;
82 }
83 var hh = date.getHours();
84 var mm = date.getMinutes();
85 var ss = date.getSeconds();
86 var lst = [
87 ((realISO && (hh < 10)) ? "0" + hh : hh),
88 ((mm < 10) ? "0" + mm : mm),
89 ((ss < 10) ? "0" + ss : ss)
90 ];
91 return lst.join(":");
92};
93
94/** @id MochiKit.DateTime.toISOTimeStamp */
95MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) {
96 if (typeof(date) == "undefined" || date === null) {
97 return null;
98 }
99 var sep = realISO ? "T" : " ";
100 var foot = realISO ? "Z" : "";
101 if (realISO) {
102 date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
103 }
104 return MochiKit.DateTime.toISODate(date) + sep + MochiKit.DateTime.toISOTime(date, realISO) + foot;
105};
106
107/** @id MochiKit.DateTime.toISODate */
108MochiKit.DateTime.toISODate = function (date) {
109 if (typeof(date) == "undefined" || date === null) {
110 return null;
111 }
112 var _padTwo = MochiKit.DateTime._padTwo;
113 var _padFour = MochiKit.DateTime._padFour;
114 return [
115 _padFour(date.getFullYear()),
116 _padTwo(date.getMonth() + 1),
117 _padTwo(date.getDate())
118 ].join("-");
119};
120
121/** @id MochiKit.DateTime.americanDate */
122MochiKit.DateTime.americanDate = function (d) {
123 d = d + "";
124 if (typeof(d) != "string" || d.length === 0) {
125 return null;
126 }
127 var a = d.split('/');
128 return new Date(a[2], a[0] - 1, a[1]);
129};
130
131MochiKit.DateTime._padTwo = function (n) {
132 return (n > 9) ? n : "0" + n;
133};
134
135MochiKit.DateTime._padFour = function(n) {
136 switch(n.toString().length) {
137 case 1: return "000" + n; break;
138 case 2: return "00" + n; break;
139 case 3: return "0" + n; break;
140 case 4:
141 default:
142 return n;
143 }
144};
145
146/** @id MochiKit.DateTime.toPaddedAmericanDate */
147MochiKit.DateTime.toPaddedAmericanDate = function (d) {
148 if (typeof(d) == "undefined" || d === null) {
149 return null;
150 }
151 var _padTwo = MochiKit.DateTime._padTwo;
152 return [
153 _padTwo(d.getMonth() + 1),
154 _padTwo(d.getDate()),
155 d.getFullYear()
156 ].join('/');
157};
158
159/** @id MochiKit.DateTime.toAmericanDate */
160MochiKit.DateTime.toAmericanDate = function (d) {
161 if (typeof(d) == "undefined" || d === null) {
162 return null;
163 }
164 return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/');
165};
166
167MochiKit.DateTime.__new__ = function () {
168 MochiKit.Base.nameFunctions(this);
169};
170
171MochiKit.DateTime.__new__();
172
173MochiKit.Base._exportSymbols(this, MochiKit.DateTime);
diff --git a/frontend/gamma/js/MochiKit/DragAndDrop.js b/frontend/gamma/js/MochiKit/DragAndDrop.js
new file mode 100644
index 0000000..62777c5
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/DragAndDrop.js
@@ -0,0 +1,766 @@
1/***
2MochiKit.DragAndDrop 1.5
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
11MochiKit.Base._module('DragAndDrop', '1.5', ['Base', 'Iter', 'DOM', 'Signal', 'Visual', 'Position']);
12
13MochiKit.DragAndDrop.Droppables = {
14 /***
15
16 Manage all droppables. Shouldn't be used, use the Droppable object instead.
17
18 ***/
19 drops: [],
20
21 remove: function (element) {
22 this.drops = MochiKit.Base.filter(function (d) {
23 return d.element != MochiKit.DOM.getElement(element);
24 }, this.drops);
25 },
26
27 register: function (drop) {
28 this.drops.push(drop);
29 },
30
31 unregister: function (drop) {
32 this.drops = MochiKit.Base.filter(function (d) {
33 return d != drop;
34 }, this.drops);
35 },
36
37 prepare: function (element) {
38 MochiKit.Base.map(function (drop) {
39 if (drop.isAccepted(element)) {
40 if (drop.options.activeclass) {
41 MochiKit.DOM.addElementClass(drop.element,
42 drop.options.activeclass);
43 }
44 drop.options.onactive(drop.element, element);
45 }
46 }, this.drops);
47 },
48
49 findDeepestChild: function (drops) {
50 var deepest = drops[0];
51
52 for (var i = 1; i < drops.length; ++i) {
53 if (MochiKit.DOM.isChildNode(drops[i].element, deepest.element)) {
54 deepest = drops[i];
55 }
56 }
57 return deepest;
58 },
59
60 show: function (point, element) {
61 if (!this.drops.length) {
62 return;
63 }
64 var affected = [];
65
66 if (this.last_active) {
67 this.last_active.deactivate();
68 }
69 MochiKit.Iter.forEach(this.drops, function (drop) {
70 if (drop.isAffected(point, element)) {
71 affected.push(drop);
72 }
73 });
74 if (affected.length > 0) {
75 var drop = this.findDeepestChild(affected);
76 MochiKit.Position.within(drop.element, point.page.x, point.page.y);
77 drop.options.onhover(element, drop.element,
78 MochiKit.Position.overlap(drop.options.overlap, drop.element));
79 drop.activate();
80 }
81 },
82
83 fire: function (event, element) {
84 if (!this.last_active) {
85 return;
86 }
87 MochiKit.Position.prepare();
88
89 if (this.last_active.isAffected(event.mouse(), element)) {
90 this.last_active.options.ondrop(element,
91 this.last_active.element, event);
92 }
93 },
94
95 reset: function (element) {
96 MochiKit.Base.map(function (drop) {
97 if (drop.options.activeclass) {
98 MochiKit.DOM.removeElementClass(drop.element,
99 drop.options.activeclass);
100 }
101 drop.options.ondesactive(drop.element, element);
102 }, this.drops);
103 if (this.last_active) {
104 this.last_active.deactivate();
105 }
106 }
107};
108
109/** @id MochiKit.DragAndDrop.Droppable */
110MochiKit.DragAndDrop.Droppable = function (element, options) {
111 var cls = arguments.callee;
112 if (!(this instanceof cls)) {
113 return new cls(element, options);
114 }
115 this.__init__(element, options);
116};
117
118MochiKit.DragAndDrop.Droppable.prototype = {
119 /***
120
121 A droppable object. Simple use is to create giving an element:
122
123 new MochiKit.DragAndDrop.Droppable('myelement');
124
125 Generally you'll want to define the 'ondrop' function and maybe the
126 'accept' option to filter draggables.
127
128 ***/
129 __class__: MochiKit.DragAndDrop.Droppable,
130
131 __init__: function (element, /* optional */options) {
132 var d = MochiKit.DOM;
133 var b = MochiKit.Base;
134 this.element = d.getElement(element);
135 this.options = b.update({
136
137 /** @id MochiKit.DragAndDrop.greedy */
138 greedy: true,
139
140 /** @id MochiKit.DragAndDrop.hoverclass */
141 hoverclass: null,
142
143 /** @id MochiKit.DragAndDrop.activeclass */
144 activeclass: null,
145
146 /** @id MochiKit.DragAndDrop.hoverfunc */
147 hoverfunc: b.noop,
148
149 /** @id MochiKit.DragAndDrop.accept */
150 accept: null,
151
152 /** @id MochiKit.DragAndDrop.onactive */
153 onactive: b.noop,
154
155 /** @id MochiKit.DragAndDrop.ondesactive */
156 ondesactive: b.noop,
157
158 /** @id MochiKit.DragAndDrop.onhover */
159 onhover: b.noop,
160
161 /** @id MochiKit.DragAndDrop.ondrop */
162 ondrop: b.noop,
163
164 /** @id MochiKit.DragAndDrop.containment */
165 containment: [],
166 tree: false
167 }, options);
168
169 // cache containers
170 this.options._containers = [];
171 b.map(MochiKit.Base.bind(function (c) {
172 this.options._containers.push(d.getElement(c));
173 }, this), this.options.containment);
174
175 MochiKit.Style.makePositioned(this.element); // fix IE
176
177 MochiKit.DragAndDrop.Droppables.register(this);
178 },
179
180 /** @id MochiKit.DragAndDrop.isContained */
181 isContained: function (element) {
182 if (this.options._containers.length) {
183 var containmentNode;
184 if (this.options.tree) {
185 containmentNode = element.treeNode;
186 } else {
187 containmentNode = element.parentNode;
188 }
189 return MochiKit.Iter.some(this.options._containers, function (c) {
190 return containmentNode == c;
191 });
192 } else {
193 return true;
194 }
195 },
196
197 /** @id MochiKit.DragAndDrop.isAccepted */
198 isAccepted: function (element) {
199 return ((!this.options.accept) || MochiKit.Iter.some(
200 this.options.accept, function (c) {
201 return MochiKit.DOM.hasElementClass(element, c);
202 }));
203 },
204
205 /** @id MochiKit.DragAndDrop.isAffected */
206 isAffected: function (point, element) {
207 return ((this.element != element) &&
208 this.isContained(element) &&
209 this.isAccepted(element) &&
210 MochiKit.Position.within(this.element, point.page.x,
211 point.page.y));
212 },
213
214 /** @id MochiKit.DragAndDrop.deactivate */
215 deactivate: function () {
216 /***
217
218 A droppable is deactivate when a draggable has been over it and left.
219
220 ***/
221 if (this.options.hoverclass) {
222 MochiKit.DOM.removeElementClass(this.element,
223 this.options.hoverclass);
224 }
225 this.options.hoverfunc(this.element, false);
226 MochiKit.DragAndDrop.Droppables.last_active = null;
227 },
228
229 /** @id MochiKit.DragAndDrop.activate */
230 activate: function () {
231 /***
232
233 A droppable is active when a draggable is over it.
234
235 ***/
236 if (this.options.hoverclass) {
237 MochiKit.DOM.addElementClass(this.element, this.options.hoverclass);
238 }
239 this.options.hoverfunc(this.element, true);
240 MochiKit.DragAndDrop.Droppables.last_active = this;
241 },
242
243 /** @id MochiKit.DragAndDrop.destroy */
244 destroy: function () {
245 /***
246
247 Delete this droppable.
248
249 ***/
250 MochiKit.DragAndDrop.Droppables.unregister(this);
251 },
252
253 /** @id MochiKit.DragAndDrop.repr */
254 repr: function () {
255 return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
256 }
257};
258
259MochiKit.DragAndDrop.Draggables = {
260 /***
261
262 Manage draggables elements. Not intended to direct use.
263
264 ***/
265 drags: [],
266
267 register: function (draggable) {
268 if (this.drags.length === 0) {
269 var conn = MochiKit.Signal.connect;
270 this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
271 this.eventMouseMove = conn(document, 'onmousemove', this,
272 this.updateDrag);
273 this.eventKeypress = conn(document, 'onkeypress', this,
274 this.keyPress);
275 }
276 this.drags.push(draggable);
277 },
278
279 unregister: function (draggable) {
280 this.drags = MochiKit.Base.filter(function (d) {
281 return d != draggable;
282 }, this.drags);
283 if (this.drags.length === 0) {
284 var disc = MochiKit.Signal.disconnect;
285 disc(this.eventMouseUp);
286 disc(this.eventMouseMove);
287 disc(this.eventKeypress);
288 }
289 },
290
291 activate: function (draggable) {
292 // allows keypress events if window is not currently focused
293 // fails for Safari
294 window.focus();
295 this.activeDraggable = draggable;
296 },
297
298 deactivate: function () {
299 this.activeDraggable = null;
300 },
301
302 updateDrag: function (event) {
303 if (!this.activeDraggable) {
304 return;
305 }
306 var pointer = event.mouse();
307 // Mozilla-based browsers fire successive mousemove events with
308 // the same coordinates, prevent needless redrawing (moz bug?)
309 if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) ==
310 MochiKit.Base.repr(pointer.page))) {
311 return;
312 }
313 this._lastPointer = pointer;
314 this.activeDraggable.updateDrag(event, pointer);
315 },
316
317 endDrag: function (event) {
318 if (!this.activeDraggable) {
319 return;
320 }
321 this._lastPointer = null;
322 this.activeDraggable.endDrag(event);
323 this.activeDraggable = null;
324 },
325
326 keyPress: function (event) {
327 if (this.activeDraggable) {
328 this.activeDraggable.keyPress(event);
329 }
330 },
331
332 notify: function (eventName, draggable, event) {
333 MochiKit.Signal.signal(this, eventName, draggable, event);
334 }
335};
336
337/** @id MochiKit.DragAndDrop.Draggable */
338MochiKit.DragAndDrop.Draggable = function (element, options) {
339 var cls = arguments.callee;
340 if (!(this instanceof cls)) {
341 return new cls(element, options);
342 }
343 this.__init__(element, options);
344};
345
346MochiKit.DragAndDrop.Draggable.prototype = {
347 /***
348
349 A draggable object. Simple instantiate :
350
351 new MochiKit.DragAndDrop.Draggable('myelement');
352
353 ***/
354 __class__ : MochiKit.DragAndDrop.Draggable,
355
356 __init__: function (element, /* optional */options) {
357 var v = MochiKit.Visual;
358 var b = MochiKit.Base;
359 options = b.update({
360
361 /** @id MochiKit.DragAndDrop.handle */
362 handle: false,
363
364 /** @id MochiKit.DragAndDrop.starteffect */
365 starteffect: function (innerelement) {
366 this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0;
367 new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7});
368 },
369 /** @id MochiKit.DragAndDrop.reverteffect */
370 reverteffect: function (innerelement, top_offset, left_offset) {
371 var dur = Math.sqrt(Math.abs(top_offset^2) +
372 Math.abs(left_offset^2))*0.02;
373 return new v.Move(innerelement,
374 {x: -left_offset, y: -top_offset, duration: dur});
375 },
376
377 /** @id MochiKit.DragAndDrop.endeffect */
378 endeffect: function (innerelement) {
379 new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
380 },
381
382 /** @id MochiKit.DragAndDrop.onchange */
383 onchange: b.noop,
384
385 /** @id MochiKit.DragAndDrop.zindex */
386 zindex: 1000,
387
388 /** @id MochiKit.DragAndDrop.revert */
389 revert: false,
390
391 /** @id MochiKit.DragAndDrop.scroll */
392 scroll: false,
393
394 /** @id MochiKit.DragAndDrop.scrollSensitivity */
395 scrollSensitivity: 20,
396
397 /** @id MochiKit.DragAndDrop.scrollSpeed */
398 scrollSpeed: 15,
399 // false, or xy or [x, y] or function (x, y){return [x, y];}
400
401 /** @id MochiKit.DragAndDrop.snap */
402 snap: false
403 }, options);
404
405 var d = MochiKit.DOM;
406 this.element = d.getElement(element);
407
408 if (options.handle && (typeof(options.handle) == 'string')) {
409 this.handle = d.getFirstElementByTagAndClassName(null,
410 options.handle, this.element);
411 }
412 if (!this.handle) {
413 this.handle = d.getElement(options.handle);
414 }
415 if (!this.handle) {
416 this.handle = this.element;
417 }
418
419 if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
420 options.scroll = d.getElement(options.scroll);
421 this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll);
422 }
423
424 MochiKit.Style.makePositioned(this.element); // fix IE
425
426 this.delta = this.currentDelta();
427 this.options = options;
428 this.dragging = false;
429
430 this.eventMouseDown = MochiKit.Signal.connect(this.handle,
431 'onmousedown', this, this.initDrag);
432 MochiKit.DragAndDrop.Draggables.register(this);
433 },
434
435 /** @id MochiKit.DragAndDrop.destroy */
436 destroy: function () {
437 MochiKit.Signal.disconnect(this.eventMouseDown);
438 MochiKit.DragAndDrop.Draggables.unregister(this);
439 },
440
441 /** @id MochiKit.DragAndDrop.currentDelta */
442 currentDelta: function () {
443 var s = MochiKit.Style.getStyle;
444 return [
445 parseInt(s(this.element, 'left') || '0'),
446 parseInt(s(this.element, 'top') || '0')];
447 },
448
449 /** @id MochiKit.DragAndDrop.initDrag */
450 initDrag: function (event) {
451 if (!event.mouse().button.left) {
452 return;
453 }
454 // abort on form elements, fixes a Firefox issue
455 var src = event.target();
456 var tagName = (src.tagName || '').toUpperCase();
457 if (tagName === 'INPUT' || tagName === 'SELECT' ||
458 tagName === 'OPTION' || tagName === 'BUTTON' ||
459 tagName === 'TEXTAREA') {
460 return;
461 }
462
463 if (this._revert) {
464 this._revert.cancel();
465 this._revert = null;
466 }
467
468 var pointer = event.mouse();
469 var pos = MochiKit.Position.cumulativeOffset(this.element);
470 this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y];
471
472 MochiKit.DragAndDrop.Draggables.activate(this);
473 event.stop();
474 },
475
476 /** @id MochiKit.DragAndDrop.startDrag */
477 startDrag: function (event) {
478 this.dragging = true;
479 if (this.options.selectclass) {
480 MochiKit.DOM.addElementClass(this.element,
481 this.options.selectclass);
482 }
483 if (this.options.zindex) {
484 this.originalZ = parseInt(MochiKit.Style.getStyle(this.element,
485 'z-index') || '0');
486 this.element.style.zIndex = this.options.zindex;
487 }
488
489 if (this.options.ghosting) {
490 this._clone = this.element.cloneNode(true);
491 this.ghostPosition = MochiKit.Position.absolutize(this.element);
492 this.element.parentNode.insertBefore(this._clone, this.element);
493 }
494
495 if (this.options.scroll) {
496 if (this.options.scroll == window) {
497 var where = this._getWindowScroll(this.options.scroll);
498 this.originalScrollLeft = where.left;
499 this.originalScrollTop = where.top;
500 } else {
501 this.originalScrollLeft = this.options.scroll.scrollLeft;
502 this.originalScrollTop = this.options.scroll.scrollTop;
503 }
504 }
505
506 MochiKit.DragAndDrop.Droppables.prepare(this.element);
507 MochiKit.DragAndDrop.Draggables.notify('start', this, event);
508 if (this.options.starteffect) {
509 this.options.starteffect(this.element);
510 }
511 },
512
513 /** @id MochiKit.DragAndDrop.updateDrag */
514 updateDrag: function (event, pointer) {
515 if (!this.dragging) {
516 this.startDrag(event);
517 }
518 MochiKit.Position.prepare();
519 MochiKit.DragAndDrop.Droppables.show(pointer, this.element);
520 MochiKit.DragAndDrop.Draggables.notify('drag', this, event);
521 this.draw(pointer);
522 this.options.onchange(this);
523
524 if (this.options.scroll) {
525 this.stopScrolling();
526 var p, q;
527 if (this.options.scroll == window) {
528 var s = this._getWindowScroll(this.options.scroll);
529 p = new MochiKit.Style.Coordinates(s.left, s.top);
530 q = new MochiKit.Style.Coordinates(s.left + s.width,
531 s.top + s.height);
532 } else {
533 p = MochiKit.Position.page(this.options.scroll);
534 p.x += this.options.scroll.scrollLeft;
535 p.y += this.options.scroll.scrollTop;
536 p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);
537 p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
538 q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth,
539 p.y + this.options.scroll.offsetHeight);
540 }
541 var speed = [0, 0];
542 if (pointer.page.x > (q.x - this.options.scrollSensitivity)) {
543 speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity);
544 } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) {
545 speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity);
546 }
547 if (pointer.page.y > (q.y - this.options.scrollSensitivity)) {
548 speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity);
549 } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) {
550 speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity);
551 }
552 this.startScrolling(speed);
553 }
554
555 // fix AppleWebKit rendering
556 if (/AppleWebKit/.test(navigator.appVersion)) {
557 window.scrollBy(0, 0);
558 }
559 event.stop();
560 },
561
562 /** @id MochiKit.DragAndDrop.finishDrag */
563 finishDrag: function (event, success) {
564 var dr = MochiKit.DragAndDrop;
565 this.dragging = false;
566 if (this.options.selectclass) {
567 MochiKit.DOM.removeElementClass(this.element,
568 this.options.selectclass);
569 }
570
571 if (this.options.ghosting) {
572 // XXX: from a user point of view, it would be better to remove
573 // the node only *after* the MochiKit.Visual.Move end when used
574 // with revert.
575 MochiKit.Position.relativize(this.element, this.ghostPosition);
576 MochiKit.DOM.removeElement(this._clone);
577 this._clone = null;
578 }
579
580 if (success) {
581 dr.Droppables.fire(event, this.element);
582 }
583 dr.Draggables.notify('end', this, event);
584
585 var revert = this.options.revert;
586 if (revert && typeof(revert) == 'function') {
587 revert = revert(this.element);
588 }
589
590 var d = this.currentDelta();
591 if (revert && this.options.reverteffect) {
592 this._revert = this.options.reverteffect(this.element,
593 d[1] - this.delta[1], d[0] - this.delta[0]);
594 } else {
595 this.delta = d;
596 }
597
598 if (this.options.zindex) {
599 this.element.style.zIndex = this.originalZ;
600 }
601
602 if (this.options.endeffect) {
603 this.options.endeffect(this.element);
604 }
605
606 dr.Draggables.deactivate();
607 dr.Droppables.reset(this.element);
608 },
609
610 /** @id MochiKit.DragAndDrop.keyPress */
611 keyPress: function (event) {
612 if (event.key().string != "KEY_ESCAPE") {
613 return;
614 }
615 this.finishDrag(event, false);
616 event.stop();
617 },
618
619 /** @id MochiKit.DragAndDrop.endDrag */
620 endDrag: function (event) {
621 if (!this.dragging) {
622 return;
623 }
624 this.stopScrolling();
625 this.finishDrag(event, true);
626 event.stop();
627 },
628
629 /** @id MochiKit.DragAndDrop.draw */
630 draw: function (point) {
631 var pos = MochiKit.Position.cumulativeOffset(this.element);
632 var d = this.currentDelta();
633 pos.x -= d[0];
634 pos.y -= d[1];
635
636 if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
637 pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft;
638 pos.y -= this.options.scroll.scrollTop - this.originalScrollTop;
639 }
640
641 var p = [point.page.x - pos.x - this.offset[0],
642 point.page.y - pos.y - this.offset[1]];
643
644 if (this.options.snap) {
645 if (typeof(this.options.snap) == 'function') {
646 p = this.options.snap(p[0], p[1]);
647 } else {
648 if (this.options.snap instanceof Array) {
649 var i = -1;
650 p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
651 i += 1;
652 return Math.round(v/this.options.snap[i]) *
653 this.options.snap[i];
654 }, this), p);
655 } else {
656 p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
657 return Math.round(v/this.options.snap) *
658 this.options.snap;
659 }, this), p);
660 }
661 }
662 }
663 var style = this.element.style;
664 if ((!this.options.constraint) ||
665 (this.options.constraint == 'horizontal')) {
666 style.left = p[0] + 'px';
667 }
668 if ((!this.options.constraint) ||
669 (this.options.constraint == 'vertical')) {
670 style.top = p[1] + 'px';
671 }
672 if (style.visibility == 'hidden') {
673 style.visibility = ''; // fix gecko rendering
674 }
675 },
676
677 /** @id MochiKit.DragAndDrop.stopScrolling */
678 stopScrolling: function () {
679 if (this.scrollInterval) {
680 clearInterval(this.scrollInterval);
681 this.scrollInterval = null;
682 MochiKit.DragAndDrop.Draggables._lastScrollPointer = null;
683 }
684 },
685
686 /** @id MochiKit.DragAndDrop.startScrolling */
687 startScrolling: function (speed) {
688 if (!speed[0] && !speed[1]) {
689 return;
690 }
691 this.scrollSpeed = [speed[0] * this.options.scrollSpeed,
692 speed[1] * this.options.scrollSpeed];
693 this.lastScrolled = new Date();
694 this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10);
695 },
696
697 /** @id MochiKit.DragAndDrop.scroll */
698 scroll: function () {
699 var current = new Date();
700 var delta = current - this.lastScrolled;
701 this.lastScrolled = current;
702
703 if (this.options.scroll == window) {
704 var s = this._getWindowScroll(this.options.scroll);
705 if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
706 var dm = delta / 1000;
707 this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0],
708 s.top + dm * this.scrollSpeed[1]);
709 }
710 } else {
711 this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
712 this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
713 }
714
715 var d = MochiKit.DragAndDrop;
716
717 MochiKit.Position.prepare();
718 d.Droppables.show(d.Draggables._lastPointer, this.element);
719 d.Draggables.notify('drag', this);
720 if (this._isScrollChild) {
721 d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer;
722 d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000;
723 d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000;
724 if (d.Draggables._lastScrollPointer.x < 0) {
725 d.Draggables._lastScrollPointer.x = 0;
726 }
727 if (d.Draggables._lastScrollPointer.y < 0) {
728 d.Draggables._lastScrollPointer.y = 0;
729 }
730 this.draw(d.Draggables._lastScrollPointer);
731 }
732
733 this.options.onchange(this);
734 },
735
736 _getWindowScroll: function (win) {
737 var vp, w, h;
738 MochiKit.DOM.withWindow(win, function () {
739 vp = MochiKit.Style.getViewportPosition(win.document);
740 });
741 if (win.innerWidth) {
742 w = win.innerWidth;
743 h = win.innerHeight;
744 } else if (win.document.documentElement && win.document.documentElement.clientWidth) {
745 w = win.document.documentElement.clientWidth;
746 h = win.document.documentElement.clientHeight;
747 } else {
748 w = win.document.body.offsetWidth;
749 h = win.document.body.offsetHeight;
750 }
751 return {top: vp.y, left: vp.x, width: w, height: h};
752 },
753
754 /** @id MochiKit.DragAndDrop.repr */
755 repr: function () {
756 return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
757 }
758};
759
760MochiKit.DragAndDrop.__new__ = function () {
761 MochiKit.Base.nameFunctions(this);
762};
763
764MochiKit.DragAndDrop.__new__();
765
766MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);
diff --git a/frontend/gamma/js/MochiKit/Format.js b/frontend/gamma/js/MochiKit/Format.js
new file mode 100644
index 0000000..122845e
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Format.js
@@ -0,0 +1,309 @@
1/***
2
3MochiKit.Format 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('Format', '1.5', ['Base']);
12
13MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) {
14 return function (num) {
15 num = parseFloat(num);
16 if (typeof(num) == "undefined" || num === null || isNaN(num)) {
17 return placeholder;
18 }
19 var curheader = header;
20 var curfooter = footer;
21 if (num < 0) {
22 num = -num;
23 } else {
24 curheader = curheader.replace(/-/, "");
25 }
26 var me = arguments.callee;
27 var fmt = MochiKit.Format.formatLocale(locale);
28 if (isPercent) {
29 num = num * 100.0;
30 curfooter = fmt.percent + curfooter;
31 }
32 num = MochiKit.Format.roundToFixed(num, precision);
33 var parts = num.split(/\./);
34 var whole = parts[0];
35 var frac = (parts.length == 1) ? "" : parts[1];
36 var res = "";
37 while (whole.length < leadingZeros) {
38 whole = "0" + whole;
39 }
40 if (separatorAt) {
41 while (whole.length > separatorAt) {
42 var i = whole.length - separatorAt;
43 //res = res + fmt.separator + whole.substring(i, whole.length);
44 res = fmt.separator + whole.substring(i, whole.length) + res;
45 whole = whole.substring(0, i);
46 }
47 }
48 res = whole + res;
49 if (precision > 0) {
50 while (frac.length < trailingZeros) {
51 frac = frac + "0";
52 }
53 res = res + fmt.decimal + frac;
54 }
55 return curheader + res + curfooter;
56 };
57};
58
59/** @id MochiKit.Format.numberFormatter */
60MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) {
61 // http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
62 // | 0 | leading or trailing zeros
63 // | # | just the number
64 // | , | separator
65 // | . | decimal separator
66 // | % | Multiply by 100 and format as percent
67 if (typeof(placeholder) == "undefined") {
68 placeholder = "";
69 }
70 var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
71 if (!match) {
72 throw TypeError("Invalid pattern");
73 }
74 var header = pattern.substr(0, match.index);
75 var footer = pattern.substr(match.index + match[0].length);
76 if (header.search(/-/) == -1) {
77 header = header + "-";
78 }
79 var whole = match[1];
80 var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : "";
81 var isPercent = (typeof(match[3]) == "string" && match[3] != "");
82 var tmp = whole.split(/,/);
83 var separatorAt;
84 if (typeof(locale) == "undefined") {
85 locale = "default";
86 }
87 if (tmp.length == 1) {
88 separatorAt = null;
89 } else {
90 separatorAt = tmp[1].length;
91 }
92 var leadingZeros = whole.length - whole.replace(/0/g, "").length;
93 var trailingZeros = frac.length - frac.replace(/0/g, "").length;
94 var precision = frac.length;
95 var rval = MochiKit.Format._numberFormatter(
96 placeholder, header, footer, locale, isPercent, precision,
97 leadingZeros, separatorAt, trailingZeros
98 );
99 var m = MochiKit.Base;
100 if (m) {
101 var fn = arguments.callee;
102 var args = m.concat(arguments);
103 rval.repr = function () {
104 return [
105 self.NAME,
106 "(",
107 map(m.repr, args).join(", "),
108 ")"
109 ].join("");
110 };
111 }
112 return rval;
113};
114
115/** @id MochiKit.Format.formatLocale */
116MochiKit.Format.formatLocale = function (locale) {
117 if (typeof(locale) == "undefined" || locale === null) {
118 locale = "default";
119 }
120 if (typeof(locale) == "string") {
121 var rval = MochiKit.Format.LOCALE[locale];
122 if (typeof(rval) == "string") {
123 rval = arguments.callee(rval);
124 MochiKit.Format.LOCALE[locale] = rval;
125 }
126 return rval;
127 } else {
128 return locale;
129 }
130};
131
132/** @id MochiKit.Format.twoDigitAverage */
133MochiKit.Format.twoDigitAverage = function (numerator, denominator) {
134 if (denominator) {
135 var res = numerator / denominator;
136 if (!isNaN(res)) {
137 return MochiKit.Format.twoDigitFloat(res);
138 }
139 }
140 return "0";
141};
142
143/** @id MochiKit.Format.twoDigitFloat */
144MochiKit.Format.twoDigitFloat = function (aNumber) {
145 var res = roundToFixed(aNumber, 2);
146 if (res.indexOf(".00") > 0) {
147 return res.substring(0, res.length - 3);
148 } else if (res.charAt(res.length - 1) == "0") {
149 return res.substring(0, res.length - 1);
150 } else {
151 return res;
152 }
153};
154
155/** @id MochiKit.Format.lstrip */
156MochiKit.Format.lstrip = function (str, /* optional */chars) {
157 str = str + "";
158 if (typeof(str) != "string") {
159 return null;
160 }
161 if (!chars) {
162 return str.replace(/^\s+/, "");
163 } else {
164 return str.replace(new RegExp("^[" + chars + "]+"), "");
165 }
166};
167
168/** @id MochiKit.Format.rstrip */
169MochiKit.Format.rstrip = function (str, /* optional */chars) {
170 str = str + "";
171 if (typeof(str) != "string") {
172 return null;
173 }
174 if (!chars) {
175 return str.replace(/\s+$/, "");
176 } else {
177 return str.replace(new RegExp("[" + chars + "]+$"), "");
178 }
179};
180
181/** @id MochiKit.Format.strip */
182MochiKit.Format.strip = function (str, /* optional */chars) {
183 var self = MochiKit.Format;
184 return self.rstrip(self.lstrip(str, chars), chars);
185};
186
187/** @id MochiKit.Format.truncToFixed */
188MochiKit.Format.truncToFixed = function (aNumber, precision) {
189 var fixed = MochiKit.Format._numberToFixed(aNumber, precision);
190 var fracPos = fixed.indexOf(".");
191 if (fracPos > 0 && fracPos + precision + 1 < fixed.length) {
192 fixed = fixed.substring(0, fracPos + precision + 1);
193 fixed = MochiKit.Format._shiftNumber(fixed, 0);
194 }
195 return fixed;
196}
197
198/** @id MochiKit.Format.roundToFixed */
199MochiKit.Format.roundToFixed = function (aNumber, precision) {
200 var fixed = MochiKit.Format._numberToFixed(aNumber, precision);
201 var fracPos = fixed.indexOf(".");
202 if (fracPos > 0 && fracPos + precision + 1 < fixed.length) {
203 var str = MochiKit.Format._shiftNumber(fixed, precision);
204 str = MochiKit.Format._numberToFixed(Math.round(parseFloat(str)), 0);
205 fixed = MochiKit.Format._shiftNumber(str, -precision);
206 }
207 return fixed;
208}
209
210/**
211 * Converts a number to a fixed format string. This function handles
212 * conversion of exponents by shifting the decimal point to the left
213 * or the right. It also guarantees a specified minimum number of
214 * fractional digits (but no maximum).
215 *
216 * @param {Number} aNumber the number to convert
217 * @param {Number} precision the minimum number of decimal digits
218 *
219 * @return {String} the fixed format number string
220 */
221MochiKit.Format._numberToFixed = function (aNumber, precision) {
222 var str = aNumber.toString();
223 var parts = str.split(/[eE]/);
224 var exp = (parts.length === 1) ? 0 : parseInt(parts[1]) || 0;
225 var fixed = MochiKit.Format._shiftNumber(parts[0], exp);
226 parts = fixed.split(/\./);
227 var whole = parts[0];
228 var frac = (parts.length === 1) ? "" : parts[1];
229 while (frac.length < precision) {
230 frac += "0";
231 }
232 if (frac.length > 0) {
233 return whole + "." + frac;
234 } else {
235 return whole;
236 }
237}
238
239/**
240 * Shifts the decimal dot location in a fixed format number string.
241 * This function handles negative values and will add and remove
242 * leading and trailing zeros as needed.
243 *
244 * @param {String} num the fixed format number string
245 * @param {Number} exp the base-10 exponent to apply
246 *
247 * @return {String} the new fixed format number string
248 */
249MochiKit.Format._shiftNumber = function (num, exp) {
250 var pos = num.indexOf(".");
251 if (pos < 0) {
252 pos = num.length;
253 } else {
254 num = num.substring(0, pos) + num.substring(pos + 1);
255 }
256 pos += exp;
257 while (pos <= 0 || (pos <= 1 && num.charAt(0) === "-")) {
258 if (num.charAt(0) === "-") {
259 num = "-0" + num.substring(1);
260 } else {
261 num = "0" + num;
262 }
263 pos++;
264 }
265 while (pos > num.length) {
266 num += "0";
267 }
268 if (pos < num.length) {
269 num = num.substring(0, pos) + "." + num.substring(pos);
270 }
271 while (/^0[^.]/.test(num)) {
272 num = num.substring(1);
273 }
274 while (/^-0[^.]/.test(num)) {
275 num = "-" + num.substring(2);
276 }
277 return num;
278}
279
280/** @id MochiKit.Format.percentFormat */
281MochiKit.Format.percentFormat = function (aNumber) {
282 return MochiKit.Format.twoDigitFloat(100 * aNumber) + '%';
283};
284
285MochiKit.Format.LOCALE = {
286 en_US: {separator: ",", decimal: ".", percent: "%"},
287 de_DE: {separator: ".", decimal: ",", percent: "%"},
288 pt_BR: {separator: ".", decimal: ",", percent: "%"},
289 fr_FR: {separator: " ", decimal: ",", percent: "%"},
290 "default": "en_US",
291 __export__: false
292};
293
294MochiKit.Format.__new__ = function () {
295 MochiKit.Base.nameFunctions(this);
296 var base = this.NAME + ".";
297 var k, v, o;
298 for (k in this.LOCALE) {
299 o = this.LOCALE[k];
300 if (typeof(o) == "object") {
301 o.repr = function () { return this.NAME; };
302 o.NAME = base + "LOCALE." + k;
303 }
304 }
305};
306
307MochiKit.Format.__new__();
308
309MochiKit.Base._exportSymbols(this, MochiKit.Format);
diff --git a/frontend/gamma/js/MochiKit/Iter.js b/frontend/gamma/js/MochiKit/Iter.js
new file mode 100644
index 0000000..524b2bc
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Iter.js
@@ -0,0 +1,790 @@
1/***
2
3MochiKit.Iter 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('Iter', '1.5', ['Base']);
12
13MochiKit.Base.update(MochiKit.Iter, {
14 /** @id MochiKit.Iter.registerIteratorFactory */
15 registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
16 MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
17 },
18
19 /** @id MochiKit.Iter.isIterable */
20 isIterable: function(o) {
21 return o != null &&
22 (typeof(o.next) == "function" || typeof(o.iter) == "function");
23 },
24
25 /** @id MochiKit.Iter.iter */
26 iter: function (iterable, /* optional */ sentinel) {
27 var self = MochiKit.Iter;
28 if (arguments.length == 2) {
29 return self.takewhile(
30 function (a) { return a != sentinel; },
31 iterable
32 );
33 }
34 if (typeof(iterable.next) == 'function') {
35 return iterable;
36 } else if (typeof(iterable.iter) == 'function') {
37 return iterable.iter();
38 /*
39 } else if (typeof(iterable.__iterator__) == 'function') {
40 //
41 // XXX: We can't support JavaScript 1.7 __iterator__ directly
42 // because of Object.prototype.__iterator__
43 //
44 return iterable.__iterator__();
45 */
46 }
47
48 try {
49 return self.iteratorRegistry.match(iterable);
50 } catch (e) {
51 var m = MochiKit.Base;
52 if (e == m.NotFound) {
53 e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
54 }
55 throw e;
56 }
57 },
58
59 /** @id MochiKit.Iter.count */
60 count: function (n) {
61 if (!n) {
62 n = 0;
63 }
64 var m = MochiKit.Base;
65 return {
66 repr: function () { return "count(" + n + ")"; },
67 toString: m.forwardCall("repr"),
68 next: m.counter(n)
69 };
70 },
71
72 /** @id MochiKit.Iter.cycle */
73 cycle: function (p) {
74 var self = MochiKit.Iter;
75 var m = MochiKit.Base;
76 var lst = [];
77 var iterator = self.iter(p);
78 return {
79 repr: function () { return "cycle(...)"; },
80 toString: m.forwardCall("repr"),
81 next: function () {
82 try {
83 var rval = iterator.next();
84 lst.push(rval);
85 return rval;
86 } catch (e) {
87 if (e != self.StopIteration) {
88 throw e;
89 }
90 if (lst.length === 0) {
91 this.next = function () {
92 throw self.StopIteration;
93 };
94 } else {
95 var i = -1;
96 this.next = function () {
97 i = (i + 1) % lst.length;
98 return lst[i];
99 };
100 }
101 return this.next();
102 }
103 }
104 };
105 },
106
107 /** @id MochiKit.Iter.repeat */
108 repeat: function (elem, /* optional */n) {
109 var m = MochiKit.Base;
110 if (typeof(n) == 'undefined') {
111 return {
112 repr: function () {
113 return "repeat(" + m.repr(elem) + ")";
114 },
115 toString: m.forwardCall("repr"),
116 next: function () {
117 return elem;
118 }
119 };
120 }
121 return {
122 repr: function () {
123 return "repeat(" + m.repr(elem) + ", " + n + ")";
124 },
125 toString: m.forwardCall("repr"),
126 next: function () {
127 if (n <= 0) {
128 throw MochiKit.Iter.StopIteration;
129 }
130 n -= 1;
131 return elem;
132 }
133 };
134 },
135
136 /** @id MochiKit.Iter.next */
137 next: function (iterator) {
138 return iterator.next();
139 },
140
141 /** @id MochiKit.Iter.izip */
142 izip: function (p, q/*, ...*/) {
143 var m = MochiKit.Base;
144 var self = MochiKit.Iter;
145 var next = self.next;
146 var iterables = m.map(self.iter, arguments);
147 return {
148 repr: function () { return "izip(...)"; },
149 toString: m.forwardCall("repr"),
150 next: function () { return m.map(next, iterables); }
151 };
152 },
153
154 /** @id MochiKit.Iter.ifilter */
155 ifilter: function (pred, seq) {
156 var m = MochiKit.Base;
157 seq = MochiKit.Iter.iter(seq);
158 if (pred === null) {
159 pred = m.operator.truth;
160 }
161 return {
162 repr: function () { return "ifilter(...)"; },
163 toString: m.forwardCall("repr"),
164 next: function () {
165 while (true) {
166 var rval = seq.next();
167 if (pred(rval)) {
168 return rval;
169 }
170 }
171 // mozilla warnings aren't too bright
172 return undefined;
173 }
174 };
175 },
176
177 /** @id MochiKit.Iter.ifilterfalse */
178 ifilterfalse: function (pred, seq) {
179 var m = MochiKit.Base;
180 seq = MochiKit.Iter.iter(seq);
181 if (pred === null) {
182 pred = m.operator.truth;
183 }
184 return {
185 repr: function () { return "ifilterfalse(...)"; },
186 toString: m.forwardCall("repr"),
187 next: function () {
188 while (true) {
189 var rval = seq.next();
190 if (!pred(rval)) {
191 return rval;
192 }
193 }
194 // mozilla warnings aren't too bright
195 return undefined;
196 }
197 };
198 },
199
200 /** @id MochiKit.Iter.islice */
201 islice: function (seq/*, [start,] stop[, step] */) {
202 var self = MochiKit.Iter;
203 var m = MochiKit.Base;
204 seq = self.iter(seq);
205 var start = 0;
206 var stop = 0;
207 var step = 1;
208 var i = -1;
209 if (arguments.length == 2) {
210 stop = arguments[1];
211 } else if (arguments.length == 3) {
212 start = arguments[1];
213 stop = arguments[2];
214 } else {
215 start = arguments[1];
216 stop = arguments[2];
217 step = arguments[3];
218 }
219 return {
220 repr: function () {
221 return "islice(" + ["...", start, stop, step].join(", ") + ")";
222 },
223 toString: m.forwardCall("repr"),
224 next: function () {
225 var rval;
226 while (i < start) {
227 rval = seq.next();
228 i++;
229 }
230 if (start >= stop) {
231 throw self.StopIteration;
232 }
233 start += step;
234 return rval;
235 }
236 };
237 },
238
239 /** @id MochiKit.Iter.imap */
240 imap: function (fun, p, q/*, ...*/) {
241 var m = MochiKit.Base;
242 var self = MochiKit.Iter;
243 var iterables = m.map(self.iter, m.extend(null, arguments, 1));
244 var map = m.map;
245 var next = self.next;
246 return {
247 repr: function () { return "imap(...)"; },
248 toString: m.forwardCall("repr"),
249 next: function () {
250 return fun.apply(this, map(next, iterables));
251 }
252 };
253 },
254
255 /** @id MochiKit.Iter.applymap */
256 applymap: function (fun, seq, self) {
257 seq = MochiKit.Iter.iter(seq);
258 var m = MochiKit.Base;
259 return {
260 repr: function () { return "applymap(...)"; },
261 toString: m.forwardCall("repr"),
262 next: function () {
263 return fun.apply(self, seq.next());
264 }
265 };
266 },
267
268 /** @id MochiKit.Iter.chain */
269 chain: function (p, q/*, ...*/) {
270 // dumb fast path
271 var self = MochiKit.Iter;
272 var m = MochiKit.Base;
273 if (arguments.length == 1) {
274 return self.iter(arguments[0]);
275 }
276 var argiter = m.map(self.iter, arguments);
277 return {
278 repr: function () { return "chain(...)"; },
279 toString: m.forwardCall("repr"),
280 next: function () {
281 while (argiter.length > 1) {
282 try {
283 var result = argiter[0].next();
284 return result;
285 } catch (e) {
286 if (e != self.StopIteration) {
287 throw e;
288 }
289 argiter.shift();
290 var result = argiter[0].next();
291 return result;
292 }
293 }
294 if (argiter.length == 1) {
295 // optimize last element
296 var arg = argiter.shift();
297 this.next = m.bind("next", arg);
298 return this.next();
299 }
300 throw self.StopIteration;
301 }
302 };
303 },
304
305 /** @id MochiKit.Iter.takewhile */
306 takewhile: function (pred, seq) {
307 var self = MochiKit.Iter;
308 seq = self.iter(seq);
309 return {
310 repr: function () { return "takewhile(...)"; },
311 toString: MochiKit.Base.forwardCall("repr"),
312 next: function () {
313 var rval = seq.next();
314 if (!pred(rval)) {
315 this.next = function () {
316 throw self.StopIteration;
317 };
318 this.next();
319 }
320 return rval;
321 }
322 };
323 },
324
325 /** @id MochiKit.Iter.dropwhile */
326 dropwhile: function (pred, seq) {
327 seq = MochiKit.Iter.iter(seq);
328 var m = MochiKit.Base;
329 var bind = m.bind;
330 return {
331 "repr": function () { return "dropwhile(...)"; },
332 "toString": m.forwardCall("repr"),
333 "next": function () {
334 while (true) {
335 var rval = seq.next();
336 if (!pred(rval)) {
337 break;
338 }
339 }
340 this.next = bind("next", seq);
341 return rval;
342 }
343 };
344 },
345
346 _tee: function (ident, sync, iterable) {
347 sync.pos[ident] = -1;
348 var m = MochiKit.Base;
349 var listMin = m.listMin;
350 return {
351 repr: function () { return "tee(" + ident + ", ...)"; },
352 toString: m.forwardCall("repr"),
353 next: function () {
354 var rval;
355 var i = sync.pos[ident];
356
357 if (i == sync.max) {
358 rval = iterable.next();
359 sync.deque.push(rval);
360 sync.max += 1;
361 sync.pos[ident] += 1;
362 } else {
363 rval = sync.deque[i - sync.min];
364 sync.pos[ident] += 1;
365 if (i == sync.min && listMin(sync.pos) != sync.min) {
366 sync.min += 1;
367 sync.deque.shift();
368 }
369 }
370 return rval;
371 }
372 };
373 },
374
375 /** @id MochiKit.Iter.tee */
376 tee: function (iterable, n/* = 2 */) {
377 var rval = [];
378 var sync = {
379 "pos": [],
380 "deque": [],
381 "max": -1,
382 "min": -1
383 };
384 if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
385 n = 2;
386 }
387 var self = MochiKit.Iter;
388 iterable = self.iter(iterable);
389 var _tee = self._tee;
390 for (var i = 0; i < n; i++) {
391 rval.push(_tee(i, sync, iterable));
392 }
393 return rval;
394 },
395
396 /** @id MochiKit.Iter.list */
397 list: function (iterable) {
398 // Fast-path for Array and Array-like
399 var rval;
400 if (iterable instanceof Array) {
401 return iterable.slice();
402 }
403 // this is necessary to avoid a Safari crash
404 if (typeof(iterable) == "function" &&
405 !(iterable instanceof Function) &&
406 typeof(iterable.length) == 'number') {
407 rval = [];
408 for (var i = 0; i < iterable.length; i++) {
409 rval.push(iterable[i]);
410 }
411 return rval;
412 }
413
414 var self = MochiKit.Iter;
415 iterable = self.iter(iterable);
416 var rval = [];
417 var a_val;
418 try {
419 while (true) {
420 a_val = iterable.next();
421 rval.push(a_val);
422 }
423 } catch (e) {
424 if (e != self.StopIteration) {
425 throw e;
426 }
427 return rval;
428 }
429 // mozilla warnings aren't too bright
430 return undefined;
431 },
432
433
434 /** @id MochiKit.Iter.reduce */
435 reduce: function (fn, iterable, /* optional */initial) {
436 var i = 0;
437 var x = initial;
438 var self = MochiKit.Iter;
439 iterable = self.iter(iterable);
440 if (arguments.length < 3) {
441 try {
442 x = iterable.next();
443 } catch (e) {
444 if (e == self.StopIteration) {
445 e = new TypeError("reduce() of empty sequence with no initial value");
446 }
447 throw e;
448 }
449 i++;
450 }
451 try {
452 while (true) {
453 x = fn(x, iterable.next());
454 }
455 } catch (e) {
456 if (e != self.StopIteration) {
457 throw e;
458 }
459 }
460 return x;
461 },
462
463 /** @id MochiKit.Iter.range */
464 range: function (/* [start,] stop[, step] */) {
465 var start = 0;
466 var stop = 0;
467 var step = 1;
468 if (arguments.length == 1) {
469 stop = arguments[0];
470 } else if (arguments.length == 2) {
471 start = arguments[0];
472 stop = arguments[1];
473 } else if (arguments.length == 3) {
474 start = arguments[0];
475 stop = arguments[1];
476 step = arguments[2];
477 } else {
478 throw new TypeError("range() takes 1, 2, or 3 arguments!");
479 }
480 if (step === 0) {
481 throw new TypeError("range() step must not be 0");
482 }
483 return {
484 next: function () {
485 if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
486 throw MochiKit.Iter.StopIteration;
487 }
488 var rval = start;
489 start += step;
490 return rval;
491 },
492 repr: function () {
493 return "range(" + [start, stop, step].join(", ") + ")";
494 },
495 toString: MochiKit.Base.forwardCall("repr")
496 };
497 },
498
499 /** @id MochiKit.Iter.sum */
500 sum: function (iterable, start/* = 0 */) {
501 if (typeof(start) == "undefined" || start === null) {
502 start = 0;
503 }
504 var x = start;
505 var self = MochiKit.Iter;
506 iterable = self.iter(iterable);
507 try {
508 while (true) {
509 x += iterable.next();
510 }
511 } catch (e) {
512 if (e != self.StopIteration) {
513 throw e;
514 }
515 }
516 return x;
517 },
518
519 /** @id MochiKit.Iter.exhaust */
520 exhaust: function (iterable) {
521 var self = MochiKit.Iter;
522 iterable = self.iter(iterable);
523 try {
524 while (true) {
525 iterable.next();
526 }
527 } catch (e) {
528 if (e != self.StopIteration) {
529 throw e;
530 }
531 }
532 },
533
534 /** @id MochiKit.Iter.forEach */
535 forEach: function (iterable, func, /* optional */obj) {
536 var m = MochiKit.Base;
537 var self = MochiKit.Iter;
538 if (arguments.length > 2) {
539 func = m.bind(func, obj);
540 }
541 // fast path for array
542 if (m.isArrayLike(iterable) && !self.isIterable(iterable)) {
543 try {
544 for (var i = 0; i < iterable.length; i++) {
545 func(iterable[i]);
546 }
547 } catch (e) {
548 if (e != self.StopIteration) {
549 throw e;
550 }
551 }
552 } else {
553 self.exhaust(self.imap(func, iterable));
554 }
555 },
556
557 /** @id MochiKit.Iter.every */
558 every: function (iterable, func) {
559 var self = MochiKit.Iter;
560 try {
561 self.ifilterfalse(func, iterable).next();
562 return false;
563 } catch (e) {
564 if (e != self.StopIteration) {
565 throw e;
566 }
567 return true;
568 }
569 },
570
571 /** @id MochiKit.Iter.sorted */
572 sorted: function (iterable, /* optional */cmp) {
573 var rval = MochiKit.Iter.list(iterable);
574 if (arguments.length == 1) {
575 cmp = MochiKit.Base.compare;
576 }
577 rval.sort(cmp);
578 return rval;
579 },
580
581 /** @id MochiKit.Iter.reversed */
582 reversed: function (iterable) {
583 var rval = MochiKit.Iter.list(iterable);
584 rval.reverse();
585 return rval;
586 },
587
588 /** @id MochiKit.Iter.some */
589 some: function (iterable, func) {
590 var self = MochiKit.Iter;
591 try {
592 self.ifilter(func, iterable).next();
593 return true;
594 } catch (e) {
595 if (e != self.StopIteration) {
596 throw e;
597 }
598 return false;
599 }
600 },
601
602 /** @id MochiKit.Iter.iextend */
603 iextend: function (lst, iterable) {
604 var m = MochiKit.Base;
605 var self = MochiKit.Iter;
606 if (m.isArrayLike(iterable) && !self.isIterable(iterable)) {
607 // fast-path for array-like
608 for (var i = 0; i < iterable.length; i++) {
609 lst.push(iterable[i]);
610 }
611 } else {
612 iterable = self.iter(iterable);
613 try {
614 while (true) {
615 lst.push(iterable.next());
616 }
617 } catch (e) {
618 if (e != self.StopIteration) {
619 throw e;
620 }
621 }
622 }
623 return lst;
624 },
625
626 /** @id MochiKit.Iter.groupby */
627 groupby: function(iterable, /* optional */ keyfunc) {
628 var m = MochiKit.Base;
629 var self = MochiKit.Iter;
630 if (arguments.length < 2) {
631 keyfunc = m.operator.identity;
632 }
633 iterable = self.iter(iterable);
634
635 // shared
636 var pk = undefined;
637 var k = undefined;
638 var v;
639
640 function fetch() {
641 v = iterable.next();
642 k = keyfunc(v);
643 };
644
645 function eat() {
646 var ret = v;
647 v = undefined;
648 return ret;
649 };
650
651 var first = true;
652 var compare = m.compare;
653 return {
654 repr: function () { return "groupby(...)"; },
655 next: function() {
656 // iterator-next
657
658 // iterate until meet next group
659 while (compare(k, pk) === 0) {
660 fetch();
661 if (first) {
662 first = false;
663 break;
664 }
665 }
666 pk = k;
667 return [k, {
668 next: function() {
669 // subiterator-next
670 if (v == undefined) { // Is there something to eat?
671 fetch();
672 }
673 if (compare(k, pk) !== 0) {
674 throw self.StopIteration;
675 }
676 return eat();
677 }
678 }];
679 }
680 };
681 },
682
683 /** @id MochiKit.Iter.groupby_as_array */
684 groupby_as_array: function (iterable, /* optional */ keyfunc) {
685 var m = MochiKit.Base;
686 var self = MochiKit.Iter;
687 if (arguments.length < 2) {
688 keyfunc = m.operator.identity;
689 }
690
691 iterable = self.iter(iterable);
692 var result = [];
693 var first = true;
694 var prev_key;
695 var compare = m.compare;
696 while (true) {
697 try {
698 var value = iterable.next();
699 var key = keyfunc(value);
700 } catch (e) {
701 if (e == self.StopIteration) {
702 break;
703 }
704 throw e;
705 }
706 if (first || compare(key, prev_key) !== 0) {
707 var values = [];
708 result.push([key, values]);
709 }
710 values.push(value);
711 first = false;
712 prev_key = key;
713 }
714 return result;
715 },
716
717 /** @id MochiKit.Iter.arrayLikeIter */
718 arrayLikeIter: function (iterable) {
719 var i = 0;
720 return {
721 repr: function () { return "arrayLikeIter(...)"; },
722 toString: MochiKit.Base.forwardCall("repr"),
723 next: function () {
724 if (i >= iterable.length) {
725 throw MochiKit.Iter.StopIteration;
726 }
727 return iterable[i++];
728 }
729 };
730 },
731
732 /** @id MochiKit.Iter.hasIterateNext */
733 hasIterateNext: function (iterable) {
734 return (iterable && typeof(iterable.iterateNext) == "function");
735 },
736
737 /** @id MochiKit.Iter.iterateNextIter */
738 iterateNextIter: function (iterable) {
739 return {
740 repr: function () { return "iterateNextIter(...)"; },
741 toString: MochiKit.Base.forwardCall("repr"),
742 next: function () {
743 var rval = iterable.iterateNext();
744 if (rval === null || rval === undefined) {
745 throw MochiKit.Iter.StopIteration;
746 }
747 return rval;
748 }
749 };
750 }
751});
752
753
754MochiKit.Iter.__new__ = function () {
755 var m = MochiKit.Base;
756 // Re-use StopIteration if exists (e.g. SpiderMonkey)
757 if (typeof(StopIteration) != "undefined") {
758 this.StopIteration = StopIteration;
759 } else {
760 /** @id MochiKit.Iter.StopIteration */
761 this.StopIteration = new m.NamedError("StopIteration");
762 }
763 this.iteratorRegistry = new m.AdapterRegistry();
764 // Register the iterator factory for arrays
765 this.registerIteratorFactory(
766 "arrayLike",
767 m.isArrayLike,
768 this.arrayLikeIter
769 );
770
771 this.registerIteratorFactory(
772 "iterateNext",
773 this.hasIterateNext,
774 this.iterateNextIter
775 );
776
777 m.nameFunctions(this);
778
779};
780
781MochiKit.Iter.__new__();
782
783//
784// XXX: Internet Explorer blows
785//
786if (MochiKit.__export__) {
787 reduce = MochiKit.Iter.reduce;
788}
789
790MochiKit.Base._exportSymbols(this, MochiKit.Iter);
diff --git a/frontend/gamma/js/MochiKit/Logging.js b/frontend/gamma/js/MochiKit/Logging.js
new file mode 100644
index 0000000..f00996b
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Logging.js
@@ -0,0 +1,262 @@
1/***
2
3MochiKit.Logging 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('Logging', '1.5', ['Base']);
12
13 /** @id MochiKit.Logging.LogMessage */
14MochiKit.Logging.LogMessage = function (num, level, info) {
15 this.num = num;
16 this.level = level;
17 this.info = info;
18 this.timestamp = new Date();
19};
20
21MochiKit.Logging.LogMessage.prototype = {
22 /** @id MochiKit.Logging.LogMessage.prototype.repr */
23 repr: function () {
24 var m = MochiKit.Base;
25 return 'LogMessage(' +
26 m.map(
27 m.repr,
28 [this.num, this.level, this.info]
29 ).join(', ') + ')';
30 },
31 /** @id MochiKit.Logging.LogMessage.prototype.toString */
32 toString: MochiKit.Base.forwardCall("repr")
33};
34
35MochiKit.Base.update(MochiKit.Logging, {
36 /** @id MochiKit.Logging.logLevelAtLeast */
37 logLevelAtLeast: function (minLevel) {
38 var self = MochiKit.Logging;
39 if (typeof(minLevel) == 'string') {
40 minLevel = self.LogLevel[minLevel];
41 }
42 return function (msg) {
43 var msgLevel = msg.level;
44 if (typeof(msgLevel) == 'string') {
45 msgLevel = self.LogLevel[msgLevel];
46 }
47 return msgLevel >= minLevel;
48 };
49 },
50
51 /** @id MochiKit.Logging.isLogMessage */
52 isLogMessage: function (/* ... */) {
53 var LogMessage = MochiKit.Logging.LogMessage;
54 for (var i = 0; i < arguments.length; i++) {
55 if (!(arguments[i] instanceof LogMessage)) {
56 return false;
57 }
58 }
59 return true;
60 },
61
62 /** @id MochiKit.Logging.compareLogMessage */
63 compareLogMessage: function (a, b) {
64 return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]);
65 },
66
67 /** @id MochiKit.Logging.alertListener */
68 alertListener: function (msg) {
69 alert(
70 "num: " + msg.num +
71 "\nlevel: " + msg.level +
72 "\ninfo: " + msg.info.join(" ")
73 );
74 }
75
76});
77
78/** @id MochiKit.Logging.Logger */
79MochiKit.Logging.Logger = function (/* optional */maxSize) {
80 this.counter = 0;
81 if (typeof(maxSize) == 'undefined' || maxSize === null) {
82 maxSize = -1;
83 }
84 this.maxSize = maxSize;
85 this._messages = [];
86 this.listeners = {};
87 this.useNativeConsole = false;
88};
89
90MochiKit.Logging.Logger.prototype = {
91 /** @id MochiKit.Logging.Logger.prototype.clear */
92 clear: function () {
93 this._messages.splice(0, this._messages.length);
94 },
95
96 /** @id MochiKit.Logging.Logger.prototype.logToConsole */
97 logToConsole: function (msg) {
98 if (typeof(window) != "undefined" && window.console
99 && window.console.log) {
100 // Safari and FireBug 0.4
101 // Percent replacement is a workaround for cute Safari crashing bug
102 window.console.log(msg.replace(/%/g, '\uFF05'));
103 } else if (typeof(opera) != "undefined" && opera.postError) {
104 // Opera
105 opera.postError(msg);
106 } else if (typeof(Debug) != "undefined" && Debug.writeln) {
107 // IE Web Development Helper (?)
108 // http://www.nikhilk.net/Entry.aspx?id=93
109 Debug.writeln(msg);
110 } else if (typeof(debug) != "undefined" && debug.trace) {
111 // Atlas framework (?)
112 // http://www.nikhilk.net/Entry.aspx?id=93
113 debug.trace(msg);
114 }
115 },
116
117 /** @id MochiKit.Logging.Logger.prototype.dispatchListeners */
118 dispatchListeners: function (msg) {
119 for (var k in this.listeners) {
120 var pair = this.listeners[k];
121 if (pair.ident != k || (pair[0] && !pair[0](msg))) {
122 continue;
123 }
124 pair[1](msg);
125 }
126 },
127
128 /** @id MochiKit.Logging.Logger.prototype.addListener */
129 addListener: function (ident, filter, listener) {
130 if (typeof(filter) == 'string') {
131 filter = MochiKit.Logging.logLevelAtLeast(filter);
132 }
133 var entry = [filter, listener];
134 entry.ident = ident;
135 this.listeners[ident] = entry;
136 },
137
138 /** @id MochiKit.Logging.Logger.prototype.removeListener */
139 removeListener: function (ident) {
140 delete this.listeners[ident];
141 },
142
143 /** @id MochiKit.Logging.Logger.prototype.baseLog */
144 baseLog: function (level, message/*, ...*/) {
145 if (typeof(level) == "number") {
146 if (level >= MochiKit.Logging.LogLevel.FATAL) {
147 level = 'FATAL';
148 } else if (level >= MochiKit.Logging.LogLevel.ERROR) {
149 level = 'ERROR';
150 } else if (level >= MochiKit.Logging.LogLevel.WARNING) {
151 level = 'WARNING';
152 } else if (level >= MochiKit.Logging.LogLevel.INFO) {
153 level = 'INFO';
154 } else {
155 level = 'DEBUG';
156 }
157 }
158 var msg = new MochiKit.Logging.LogMessage(
159 this.counter,
160 level,
161 MochiKit.Base.extend(null, arguments, 1)
162 );
163 this._messages.push(msg);
164 this.dispatchListeners(msg);
165 if (this.useNativeConsole) {
166 this.logToConsole(msg.level + ": " + msg.info.join(" "));
167 }
168 this.counter += 1;
169 while (this.maxSize >= 0 && this._messages.length > this.maxSize) {
170 this._messages.shift();
171 }
172 },
173
174 /** @id MochiKit.Logging.Logger.prototype.getMessages */
175 getMessages: function (howMany) {
176 var firstMsg = 0;
177 if (!(typeof(howMany) == 'undefined' || howMany === null)) {
178 firstMsg = Math.max(0, this._messages.length - howMany);
179 }
180 return this._messages.slice(firstMsg);
181 },
182
183 /** @id MochiKit.Logging.Logger.prototype.getMessageText */
184 getMessageText: function (howMany) {
185 if (typeof(howMany) == 'undefined' || howMany === null) {
186 howMany = 30;
187 }
188 var messages = this.getMessages(howMany);
189 if (messages.length) {
190 var lst = map(function (m) {
191 return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' ');
192 }, messages);
193 lst.unshift('LAST ' + messages.length + ' MESSAGES:');
194 return lst.join('');
195 }
196 return '';
197 },
198
199 /** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */
200 debuggingBookmarklet: function (inline) {
201 if (typeof(MochiKit.LoggingPane) == "undefined") {
202 alert(this.getMessageText());
203 } else {
204 MochiKit.LoggingPane.createLoggingPane(inline || false);
205 }
206 }
207};
208
209MochiKit.Logging.__new__ = function () {
210 this.LogLevel = {
211 ERROR: 40,
212 FATAL: 50,
213 WARNING: 30,
214 INFO: 20,
215 DEBUG: 10
216 };
217
218 var m = MochiKit.Base;
219 m.registerComparator("LogMessage",
220 this.isLogMessage,
221 this.compareLogMessage
222 );
223
224 var partial = m.partial;
225
226 var Logger = this.Logger;
227 var baseLog = Logger.prototype.baseLog;
228 m.update(this.Logger.prototype, {
229 debug: partial(baseLog, 'DEBUG'),
230 log: partial(baseLog, 'INFO'),
231 error: partial(baseLog, 'ERROR'),
232 fatal: partial(baseLog, 'FATAL'),
233 warning: partial(baseLog, 'WARNING')
234 });
235
236 // indirectly find logger so it can be replaced
237 var self = this;
238 var connectLog = function (name) {
239 return function () {
240 self.logger[name].apply(self.logger, arguments);
241 };
242 };
243
244 /** @id MochiKit.Logging.log */
245 this.log = connectLog('log');
246 /** @id MochiKit.Logging.logError */
247 this.logError = connectLog('error');
248 /** @id MochiKit.Logging.logDebug */
249 this.logDebug = connectLog('debug');
250 /** @id MochiKit.Logging.logFatal */
251 this.logFatal = connectLog('fatal');
252 /** @id MochiKit.Logging.logWarning */
253 this.logWarning = connectLog('warning');
254 this.logger = new Logger();
255 this.logger.useNativeConsole = true;
256
257 m.nameFunctions(this);
258};
259
260MochiKit.Logging.__new__();
261
262MochiKit.Base._exportSymbols(this, MochiKit.Logging);
diff --git a/frontend/gamma/js/MochiKit/LoggingPane.js b/frontend/gamma/js/MochiKit/LoggingPane.js
new file mode 100644
index 0000000..c960c21
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/LoggingPane.js
@@ -0,0 +1,327 @@
1/***
2
3MochiKit.LoggingPane 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('LoggingPane', '1.5', ['Base', 'Logging']);
12
13/** @id MochiKit.LoggingPane.createLoggingPane */
14MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) {
15 var m = MochiKit.LoggingPane;
16 inline = !(!inline);
17 if (m._loggingPane && m._loggingPane.inline != inline) {
18 m._loggingPane.closePane();
19 m._loggingPane = null;
20 }
21 if (!m._loggingPane || m._loggingPane.closed) {
22 m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger);
23 }
24 return m._loggingPane;
25};
26
27/** @id MochiKit.LoggingPane.LoggingPane */
28MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) {
29
30 /* Use a div if inline, pop up a window if not */
31 /* Create the elements */
32 if (typeof(logger) == "undefined" || logger === null) {
33 logger = MochiKit.Logging.logger;
34 }
35 this.logger = logger;
36 var update = MochiKit.Base.update;
37 var updatetree = MochiKit.Base.updatetree;
38 var bind = MochiKit.Base.bind;
39 var clone = MochiKit.Base.clone;
40 var win = window;
41 var uid = "_MochiKit_LoggingPane";
42 if (typeof(MochiKit.DOM) != "undefined") {
43 win = MochiKit.DOM.currentWindow();
44 }
45 if (!inline) {
46 // name the popup with the base URL for uniqueness
47 var url = win.location.href.split("?")[0].replace(/[#:\/.><&%-]/g, "_");
48 var name = uid + "_" + url;
49 var nwin = win.open("", name, "dependent,resizable,height=200");
50 if (!nwin) {
51 alert("Not able to open debugging window due to pop-up blocking.");
52 return undefined;
53 }
54 nwin.document.write(
55 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
56 + '"http://www.w3.org/TR/html4/loose.dtd">'
57 + '<html><head><title>[MochiKit.LoggingPane]</title></head>'
58 + '<body></body></html>'
59 );
60 nwin.document.close();
61 nwin.document.title += ' ' + win.document.title;
62 win = nwin;
63 }
64 var doc = win.document;
65 this.doc = doc;
66
67 // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
68 var debugPane = doc.getElementById(uid);
69 var existing_pane = !!debugPane;
70 if (debugPane && typeof(debugPane.loggingPane) != "undefined") {
71 debugPane.loggingPane.logger = this.logger;
72 debugPane.loggingPane.buildAndApplyFilter();
73 return debugPane.loggingPane;
74 }
75
76 if (existing_pane) {
77 // clear any existing contents
78 var child;
79 while ((child = debugPane.firstChild)) {
80 debugPane.removeChild(child);
81 }
82 } else {
83 debugPane = doc.createElement("div");
84 debugPane.id = uid;
85 }
86 debugPane.loggingPane = this;
87 var levelFilterField = doc.createElement("input");
88 var infoFilterField = doc.createElement("input");
89 var filterButton = doc.createElement("button");
90 var loadButton = doc.createElement("button");
91 var clearButton = doc.createElement("button");
92 var closeButton = doc.createElement("button");
93 var logPaneArea = doc.createElement("div");
94 var logPane = doc.createElement("div");
95
96 /* Set up the functions */
97 var listenerId = uid + "_Listener";
98 this.colorTable = clone(this.colorTable);
99 var messages = [];
100 var messageFilter = null;
101
102 /** @id MochiKit.LoggingPane.messageLevel */
103 var messageLevel = function (msg) {
104 var level = msg.level;
105 if (typeof(level) == "number") {
106 level = MochiKit.Logging.LogLevel[level];
107 }
108 return level;
109 };
110
111 /** @id MochiKit.LoggingPane.messageText */
112 var messageText = function (msg) {
113 return msg.info.join(" ");
114 };
115
116 /** @id MochiKit.LoggingPane.addMessageText */
117 var addMessageText = bind(function (msg) {
118 var level = messageLevel(msg);
119 var text = messageText(msg);
120 var c = this.colorTable[level];
121 var p = doc.createElement("span");
122 p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level;
123 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;
124 p.appendChild(doc.createTextNode(level + ": " + text));
125 logPane.appendChild(p);
126 logPane.appendChild(doc.createElement("br"));
127 if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) {
128 logPaneArea.scrollTop = 0;
129 } else {
130 logPaneArea.scrollTop = logPaneArea.scrollHeight;
131 }
132 }, this);
133
134 /** @id MochiKit.LoggingPane.addMessage */
135 var addMessage = function (msg) {
136 messages[messages.length] = msg;
137 addMessageText(msg);
138 };
139
140 /** @id MochiKit.LoggingPane.buildMessageFilter */
141 var buildMessageFilter = function () {
142 var levelre, infore;
143 try {
144 /* Catch any exceptions that might arise due to invalid regexes */
145 levelre = new RegExp(levelFilterField.value);
146 infore = new RegExp(infoFilterField.value);
147 } catch(e) {
148 /* If there was an error with the regexes, do no filtering */
149 logDebug("Error in filter regex: " + e.message);
150 return null;
151 }
152
153 return function (msg) {
154 return (
155 levelre.test(messageLevel(msg)) &&
156 infore.test(messageText(msg))
157 );
158 };
159 };
160
161 /** @id MochiKit.LoggingPane.clearMessagePane */
162 var clearMessagePane = function () {
163 while (logPane.firstChild) {
164 logPane.removeChild(logPane.firstChild);
165 }
166 };
167
168 /** @id MochiKit.LoggingPane.clearMessages */
169 var clearMessages = function () {
170 messages = [];
171 clearMessagePane();
172 };
173
174 /** @id MochiKit.LoggingPane.closePane */
175 var closePane = bind(function () {
176 if (this.closed) {
177 return;
178 }
179 this.closed = true;
180 if (MochiKit.LoggingPane._loggingPane == this) {
181 MochiKit.LoggingPane._loggingPane = null;
182 }
183 this.logger.removeListener(listenerId);
184 try {
185 try {
186 debugPane.loggingPane = null;
187 } catch(e) { logFatal("Bookmarklet was closed incorrectly."); }
188 if (inline) {
189 debugPane.parentNode.removeChild(debugPane);
190 } else {
191 this.win.close();
192 }
193 } catch(e) {}
194 }, this);
195
196 /** @id MochiKit.LoggingPane.filterMessages */
197 var filterMessages = function () {
198 clearMessagePane();
199
200 for (var i = 0; i < messages.length; i++) {
201 var msg = messages[i];
202 if (messageFilter === null || messageFilter(msg)) {
203 addMessageText(msg);
204 }
205 }
206 };
207
208 this.buildAndApplyFilter = function () {
209 messageFilter = buildMessageFilter();
210
211 filterMessages();
212
213 this.logger.removeListener(listenerId);
214 this.logger.addListener(listenerId, messageFilter, addMessage);
215 };
216
217
218 /** @id MochiKit.LoggingPane.loadMessages */
219 var loadMessages = bind(function () {
220 messages = this.logger.getMessages();
221 filterMessages();
222 }, this);
223
224 /** @id MochiKit.LoggingPane.filterOnEnter */
225 var filterOnEnter = bind(function (event) {
226 event = event || window.event;
227 key = event.which || event.keyCode;
228 if (key == 13) {
229 this.buildAndApplyFilter();
230 }
231 }, this);
232
233 /* Create the debug pane */
234 var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont;
235 if (inline) {
236 style += "; height: 10em; border-top: 2px solid black";
237 } else {
238 style += "; height: 100%;";
239 }
240 debugPane.style.cssText = style;
241
242 if (!existing_pane) {
243 doc.body.appendChild(debugPane);
244 }
245
246 /* Create the filter fields */
247 style = {"cssText": "width: 33%; display: inline; font: " + this.logFont};
248
249 updatetree(levelFilterField, {
250 "value": "FATAL|ERROR|WARNING|INFO|DEBUG",
251 "onkeypress": filterOnEnter,
252 "style": style
253 });
254 debugPane.appendChild(levelFilterField);
255
256 updatetree(infoFilterField, {
257 "value": ".*",
258 "onkeypress": filterOnEnter,
259 "style": style
260 });
261 debugPane.appendChild(infoFilterField);
262
263 /* Create the buttons */
264 style = "width: 8%; display:inline; font: " + this.logFont;
265
266 filterButton.appendChild(doc.createTextNode("Filter"));
267 filterButton.onclick = bind("buildAndApplyFilter", this);
268 filterButton.style.cssText = style;
269 debugPane.appendChild(filterButton);
270
271 loadButton.appendChild(doc.createTextNode("Load"));
272 loadButton.onclick = loadMessages;
273 loadButton.style.cssText = style;
274 debugPane.appendChild(loadButton);
275
276 clearButton.appendChild(doc.createTextNode("Clear"));
277 clearButton.onclick = clearMessages;
278 clearButton.style.cssText = style;
279 debugPane.appendChild(clearButton);
280
281 closeButton.appendChild(doc.createTextNode("Close"));
282 closeButton.onclick = closePane;
283 closeButton.style.cssText = style;
284 debugPane.appendChild(closeButton);
285
286 /* Create the logging pane */
287 logPaneArea.style.cssText = "overflow: auto; width: 100%";
288 logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%");
289
290 logPaneArea.appendChild(logPane);
291 debugPane.appendChild(logPaneArea);
292
293 this.buildAndApplyFilter();
294 loadMessages();
295
296 if (inline) {
297 this.win = undefined;
298 } else {
299 this.win = win;
300 }
301 this.inline = inline;
302 this.closePane = closePane;
303 this.closed = false;
304
305
306 return this;
307};
308
309MochiKit.LoggingPane.LoggingPane.prototype = {
310 "logFont": "8pt Verdana,sans-serif",
311 "colorTable": {
312 "ERROR": "red",
313 "FATAL": "darkred",
314 "WARNING": "blue",
315 "INFO": "black",
316 "DEBUG": "green"
317 }
318};
319
320MochiKit.LoggingPane.__new__ = function () {
321 MochiKit.Base.nameFunctions(this);
322 MochiKit.LoggingPane._loggingPane = null;
323};
324
325MochiKit.LoggingPane.__new__();
326
327MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane);
diff --git a/frontend/gamma/js/MochiKit/MochiKit.js b/frontend/gamma/js/MochiKit/MochiKit.js
new file mode 100644
index 0000000..8e5be68
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/MochiKit.js
@@ -0,0 +1,136 @@
1/***
2
3MochiKit.MochiKit 1.5
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.5";
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 "Text",
39 "Async",
40 "DOM",
41 "Selector",
42 "Style",
43 "LoggingPane",
44 "Color",
45 "Signal",
46 "Position",
47 "Visual",
48 "DragAndDrop",
49 "Sortable"
50];
51
52(function () {
53 if (typeof(document) == "undefined") {
54 return;
55 }
56 var scripts = document.getElementsByTagName("script");
57 var kXHTMLNSURI = "http://www.w3.org/1999/xhtml";
58 var kSVGNSURI = "http://www.w3.org/2000/svg";
59 var kXLINKNSURI = "http://www.w3.org/1999/xlink";
60 var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
61 var base = null;
62 var baseElem = null;
63 var allScripts = {};
64 var i;
65 var src;
66 for (i = 0; i < scripts.length; i++) {
67 src = null;
68 switch (scripts[i].namespaceURI) {
69 case kSVGNSURI:
70 src = scripts[i].getAttributeNS(kXLINKNSURI, "href");
71 break;
72 /*
73 case null: // HTML
74 case '': // HTML
75 case kXHTMLNSURI:
76 case kXULNSURI:
77 */
78 default:
79 src = scripts[i].getAttribute("src");
80 break;
81 }
82 if (!src) {
83 continue;
84 }
85 allScripts[src] = true;
86 if (src.match(/MochiKit.js(\?.*)?$/)) {
87 base = src.substring(0, src.lastIndexOf('MochiKit.js'));
88 baseElem = scripts[i];
89 }
90 }
91 if (base === null) {
92 return;
93 }
94 var modules = MochiKit.MochiKit.SUBMODULES;
95 for (var i = 0; i < modules.length; i++) {
96 if (MochiKit[modules[i]]) {
97 continue;
98 }
99 var uri = base + modules[i] + '.js';
100 if (uri in allScripts) {
101 continue;
102 }
103 if (baseElem.namespaceURI == kSVGNSURI ||
104 baseElem.namespaceURI == kXULNSURI) {
105 // SVG, XUL
106 /*
107 SVG does not support document.write, so if Safari wants to
108 support SVG tests it should fix its deferred loading bug
109 (see following below).
110 */
111 var s = document.createElementNS(baseElem.namespaceURI, 'script');
112 s.setAttribute("id", "MochiKit_" + base + modules[i]);
113 if (baseElem.namespaceURI == kSVGNSURI) {
114 s.setAttributeNS(kXLINKNSURI, 'href', uri);
115 } else {
116 s.setAttribute('src', uri);
117 }
118 s.setAttribute("type", "application/x-javascript");
119 baseElem.parentNode.appendChild(s);
120 } else {
121 // HTML, XHTML
122 /*
123 DOM can not be used here because Safari does
124 deferred loading of scripts unless they are
125 in the document or inserted with document.write
126
127 This is not XHTML compliant. If you want XHTML
128 compliance then you must use the packed version of MochiKit
129 or include each script individually (basically unroll
130 these document.write calls into your XHTML source)
131 */
132 document.write('<' + baseElem.nodeName + ' src="' + uri +
133 '" type="text/javascript"></script>');
134 }
135 };
136})();
diff --git a/frontend/gamma/js/MochiKit/MockDOM.js b/frontend/gamma/js/MochiKit/MockDOM.js
new file mode 100644
index 0000000..abdb54a
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/MockDOM.js
@@ -0,0 +1,115 @@
1/***
2
3MochiKit.MockDOM 1.5
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.5";
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/gamma/js/MochiKit/Position.js b/frontend/gamma/js/MochiKit/Position.js
new file mode 100644
index 0000000..6bc5b39
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Position.js
@@ -0,0 +1,218 @@
1/***
2
3MochiKit.Position 1.5
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
11MochiKit.Base._module('Position', '1.5', ['Base', 'DOM', 'Style']);
12
13MochiKit.Base.update(MochiKit.Position, {
14 // Don't export from this module
15 __export__: false,
16
17 // set to true if needed, warning: firefox performance problems
18 // NOT neeeded for page scrolling, only if draggable contained in
19 // scrollable elements
20 includeScrollOffsets: false,
21
22 /** @id MochiKit.Position.prepare */
23 prepare: function () {
24 var deltaX = window.pageXOffset
25 || document.documentElement.scrollLeft
26 || document.body.scrollLeft
27 || 0;
28 var deltaY = window.pageYOffset
29 || document.documentElement.scrollTop
30 || document.body.scrollTop
31 || 0;
32 this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY);
33 },
34
35 /** @id MochiKit.Position.cumulativeOffset */
36 cumulativeOffset: function (element) {
37 var valueT = 0;
38 var valueL = 0;
39 do {
40 valueT += element.offsetTop || 0;
41 valueL += element.offsetLeft || 0;
42 element = element.offsetParent;
43 } while (element);
44 return new MochiKit.Style.Coordinates(valueL, valueT);
45 },
46
47 /** @id MochiKit.Position.realOffset */
48 realOffset: function (element) {
49 var valueT = 0;
50 var valueL = 0;
51 do {
52 valueT += element.scrollTop || 0;
53 valueL += element.scrollLeft || 0;
54 element = element.parentNode;
55 } while (element);
56 return new MochiKit.Style.Coordinates(valueL, valueT);
57 },
58
59 /** @id MochiKit.Position.within */
60 within: function (element, x, y) {
61 if (this.includeScrollOffsets) {
62 return this.withinIncludingScrolloffsets(element, x, y);
63 }
64 this.xcomp = x;
65 this.ycomp = y;
66 this.offset = this.cumulativeOffset(element);
67 if (element.style.position == "fixed") {
68 this.offset.x += this.windowOffset.x;
69 this.offset.y += this.windowOffset.y;
70 }
71
72 return (y >= this.offset.y &&
73 y < this.offset.y + element.offsetHeight &&
74 x >= this.offset.x &&
75 x < this.offset.x + element.offsetWidth);
76 },
77
78 /** @id MochiKit.Position.withinIncludingScrolloffsets */
79 withinIncludingScrolloffsets: function (element, x, y) {
80 var offsetcache = this.realOffset(element);
81
82 this.xcomp = x + offsetcache.x - this.windowOffset.x;
83 this.ycomp = y + offsetcache.y - this.windowOffset.y;
84 this.offset = this.cumulativeOffset(element);
85
86 return (this.ycomp >= this.offset.y &&
87 this.ycomp < this.offset.y + element.offsetHeight &&
88 this.xcomp >= this.offset.x &&
89 this.xcomp < this.offset.x + element.offsetWidth);
90 },
91
92 // within must be called directly before
93 /** @id MochiKit.Position.overlap */
94 overlap: function (mode, element) {
95 if (!mode) {
96 return 0;
97 }
98 if (mode == 'vertical') {
99 return ((this.offset.y + element.offsetHeight) - this.ycomp) /
100 element.offsetHeight;
101 }
102 if (mode == 'horizontal') {
103 return ((this.offset.x + element.offsetWidth) - this.xcomp) /
104 element.offsetWidth;
105 }
106 },
107
108 /** @id MochiKit.Position.absolutize */
109 absolutize: function (element) {
110 element = MochiKit.DOM.getElement(element);
111 if (element.style.position == 'absolute') {
112 return;
113 }
114 MochiKit.Position.prepare();
115
116 var offsets = MochiKit.Position.positionedOffset(element);
117 var width = element.clientWidth;
118 var height = element.clientHeight;
119
120 var oldStyle = {
121 'position': element.style.position,
122 'left': offsets.x - parseFloat(element.style.left || 0),
123 'top': offsets.y - parseFloat(element.style.top || 0),
124 'width': element.style.width,
125 'height': element.style.height
126 };
127
128 element.style.position = 'absolute';
129 element.style.top = offsets.y + 'px';
130 element.style.left = offsets.x + 'px';
131 element.style.width = width + 'px';
132 element.style.height = height + 'px';
133
134 return oldStyle;
135 },
136
137 /** @id MochiKit.Position.positionedOffset */
138 positionedOffset: function (element) {
139 var valueT = 0, valueL = 0;
140 do {
141 valueT += element.offsetTop || 0;
142 valueL += element.offsetLeft || 0;
143 element = element.offsetParent;
144 if (element) {
145 var p = MochiKit.Style.getStyle(element, 'position');
146 if (p == 'relative' || p == 'absolute') {
147 break;
148 }
149 }
150 } while (element);
151 return new MochiKit.Style.Coordinates(valueL, valueT);
152 },
153
154 /** @id MochiKit.Position.relativize */
155 relativize: function (element, oldPos) {
156 element = MochiKit.DOM.getElement(element);
157 if (element.style.position == 'relative') {
158 return;
159 }
160 MochiKit.Position.prepare();
161
162 var top = parseFloat(element.style.top || 0) -
163 (oldPos['top'] || 0);
164 var left = parseFloat(element.style.left || 0) -
165 (oldPos['left'] || 0);
166
167 element.style.position = oldPos['position'];
168 element.style.top = top + 'px';
169 element.style.left = left + 'px';
170 element.style.width = oldPos['width'];
171 element.style.height = oldPos['height'];
172 },
173
174 /** @id MochiKit.Position.clone */
175 clone: function (source, target) {
176 source = MochiKit.DOM.getElement(source);
177 target = MochiKit.DOM.getElement(target);
178 target.style.position = 'absolute';
179 var offsets = this.cumulativeOffset(source);
180 target.style.top = offsets.y + 'px';
181 target.style.left = offsets.x + 'px';
182 target.style.width = source.offsetWidth + 'px';
183 target.style.height = source.offsetHeight + 'px';
184 },
185
186 /** @id MochiKit.Position.page */
187 page: function (forElement) {
188 var valueT = 0;
189 var valueL = 0;
190
191 var element = forElement;
192 do {
193 valueT += element.offsetTop || 0;
194 valueL += element.offsetLeft || 0;
195
196 // Safari fix
197 if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') {
198 break;
199 }
200 } while (element = element.offsetParent);
201
202 element = forElement;
203 do {
204 valueT -= element.scrollTop || 0;
205 valueL -= element.scrollLeft || 0;
206 } while (element = element.parentNode);
207
208 return new MochiKit.Style.Coordinates(valueL, valueT);
209 }
210});
211
212MochiKit.Position.__new__ = function (win) {
213 MochiKit.Base.nameFunctions(this);
214};
215
216MochiKit.Position.__new__(this);
217
218MochiKit.Base._exportSymbols(this, MochiKit.Position);
diff --git a/frontend/gamma/js/MochiKit/Selector.js b/frontend/gamma/js/MochiKit/Selector.js
new file mode 100644
index 0000000..6aec892
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Selector.js
@@ -0,0 +1,387 @@
1/***
2
3MochiKit.Selector 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito and others. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('Selector', '1.5', ['Base', 'DOM', 'Iter']);
12
13MochiKit.Selector.Selector = function (expression) {
14 this.params = {classNames: [], pseudoClassNames: []};
15 this.expression = expression.toString().replace(/(^\s+|\s+$)/g, '');
16 this.parseExpression();
17 this.compileMatcher();
18};
19
20MochiKit.Selector.Selector.prototype = {
21 /***
22
23 Selector class: convenient object to make CSS selections.
24
25 ***/
26 __class__: MochiKit.Selector.Selector,
27
28 /** @id MochiKit.Selector.Selector.prototype.parseExpression */
29 parseExpression: function () {
30 function abort(message) {
31 throw 'Parse error in selector: ' + message;
32 }
33
34 if (this.expression == '') {
35 abort('empty expression');
36 }
37
38 var repr = MochiKit.Base.repr;
39 var params = this.params;
40 var expr = this.expression;
41 var match, modifier, clause, rest;
42 while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
43 params.attributes = params.attributes || [];
44 params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
45 expr = match[1];
46 }
47
48 if (expr == '*') {
49 return this.params.wildcard = true;
50 }
51
52 while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)) {
53 modifier = match[1];
54 clause = match[2];
55 rest = match[3];
56 switch (modifier) {
57 case '#':
58 params.id = clause;
59 break;
60 case '.':
61 params.classNames.push(clause);
62 break;
63 case ':':
64 params.pseudoClassNames.push(clause);
65 break;
66 case '':
67 case undefined:
68 params.tagName = clause.toUpperCase();
69 break;
70 default:
71 abort(repr(expr));
72 }
73 expr = rest;
74 }
75
76 if (expr.length > 0) {
77 abort(repr(expr));
78 }
79 },
80
81 /** @id MochiKit.Selector.Selector.prototype.buildMatchExpression */
82 buildMatchExpression: function () {
83 var repr = MochiKit.Base.repr;
84 var params = this.params;
85 var conditions = [];
86 var clause, i;
87
88 function childElements(element) {
89 return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, " + element + ".childNodes)";
90 }
91
92 if (params.wildcard) {
93 conditions.push('true');
94 }
95 if (clause = params.id) {
96 conditions.push('element.id == ' + repr(clause));
97 }
98 if (clause = params.tagName) {
99 conditions.push('element.tagName.toUpperCase() == ' + repr(clause));
100 }
101 if ((clause = params.classNames).length > 0) {
102 for (i = 0; i < clause.length; i++) {
103 conditions.push('MochiKit.DOM.hasElementClass(element, ' + repr(clause[i]) + ')');
104 }
105 }
106 if ((clause = params.pseudoClassNames).length > 0) {
107 for (i = 0; i < clause.length; i++) {
108 var match = clause[i].match(/^([^(]+)(?:\((.*)\))?$/);
109 var pseudoClass = match[1];
110 var pseudoClassArgument = match[2];
111 switch (pseudoClass) {
112 case 'root':
113 conditions.push('element.nodeType == 9 || element === element.ownerDocument.documentElement'); break;
114 case 'nth-child':
115 case 'nth-last-child':
116 case 'nth-of-type':
117 case 'nth-last-of-type':
118 match = pseudoClassArgument.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
119 if (!match) {
120 throw "Invalid argument to pseudo element nth-child: " + pseudoClassArgument;
121 }
122 var a, b;
123 if (match[0] == 'odd') {
124 a = 2;
125 b = 1;
126 } else if (match[0] == 'even') {
127 a = 2;
128 b = 0;
129 } else {
130 a = match[2] && parseInt(match) || null;
131 b = parseInt(match[3]);
132 }
133 conditions.push('this.nthChild(element,' + a + ',' + b
134 + ',' + !!pseudoClass.match('^nth-last') // Reverse
135 + ',' + !!pseudoClass.match('of-type$') // Restrict to same tagName
136 + ')');
137 break;
138 case 'first-child':
139 conditions.push('this.nthChild(element, null, 1)');
140 break;
141 case 'last-child':
142 conditions.push('this.nthChild(element, null, 1, true)');
143 break;
144 case 'first-of-type':
145 conditions.push('this.nthChild(element, null, 1, false, true)');
146 break;
147 case 'last-of-type':
148 conditions.push('this.nthChild(element, null, 1, true, true)');
149 break;
150 case 'only-child':
151 conditions.push(childElements('element.parentNode') + '.length == 1');
152 break;
153 case 'only-of-type':
154 conditions.push('MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, ' + childElements('element.parentNode') + ').length == 1');
155 break;
156 case 'empty':
157 conditions.push('element.childNodes.length == 0');
158 break;
159 case 'enabled':
160 conditions.push('(this.isUIElement(element) && element.disabled === false)');
161 break;
162 case 'disabled':
163 conditions.push('(this.isUIElement(element) && element.disabled === true)');
164 break;
165 case 'checked':
166 conditions.push('(this.isUIElement(element) && element.checked === true)');
167 break;
168 case 'not':
169 var subselector = new MochiKit.Selector.Selector(pseudoClassArgument);
170 conditions.push('!( ' + subselector.buildMatchExpression() + ')')
171 break;
172 }
173 }
174 }
175 if (clause = params.attributes) {
176 MochiKit.Base.map(function (attribute) {
177 var value = 'MochiKit.DOM.getNodeAttribute(element, ' + repr(attribute.name) + ')';
178 var splitValueBy = function (delimiter) {
179 return value + '.split(' + repr(delimiter) + ')';
180 }
181 conditions.push(value + ' != null');
182 switch (attribute.operator) {
183 case '=':
184 conditions.push(value + ' == ' + repr(attribute.value));
185 break;
186 case '~=':
187 conditions.push('MochiKit.Base.findValue(' + splitValueBy(' ') + ', ' + repr(attribute.value) + ') > -1');
188 break;
189 case '^=':
190 conditions.push(value + '.substring(0, ' + attribute.value.length + ') == ' + repr(attribute.value));
191 break;
192 case '$=':
193 conditions.push(value + '.substring(' + value + '.length - ' + attribute.value.length + ') == ' + repr(attribute.value));
194 break;
195 case '*=':
196 conditions.push(value + '.match(' + repr(attribute.value) + ')');
197 break;
198 case '|=':
199 conditions.push(splitValueBy('-') + '[0].toUpperCase() == ' + repr(attribute.value.toUpperCase()));
200 break;
201 case '!=':
202 conditions.push(value + ' != ' + repr(attribute.value));
203 break;
204 case '':
205 case undefined:
206 // Condition already added above
207 break;
208 default:
209 throw 'Unknown operator ' + attribute.operator + ' in selector';
210 }
211 }, clause);
212 }
213
214 return conditions.join(' && ');
215 },
216
217 /** @id MochiKit.Selector.Selector.prototype.compileMatcher */
218 compileMatcher: function () {
219 var code = 'return (!element.tagName) ? false : ' +
220 this.buildMatchExpression() + ';';
221 this.match = new Function('element', code);
222 },
223
224 /** @id MochiKit.Selector.Selector.prototype.nthChild */
225 nthChild: function (element, a, b, reverse, sametag){
226 var siblings = MochiKit.Base.filter(function (node) {
227 return node.nodeType == 1;
228 }, element.parentNode.childNodes);
229 if (sametag) {
230 siblings = MochiKit.Base.filter(function (node) {
231 return node.tagName == element.tagName;
232 }, siblings);
233 }
234 if (reverse) {
235 siblings = MochiKit.Iter.reversed(siblings);
236 }
237 if (a) {
238 var actualIndex = MochiKit.Base.findIdentical(siblings, element);
239 return ((actualIndex + 1 - b) / a) % 1 == 0;
240 } else {
241 return b == MochiKit.Base.findIdentical(siblings, element) + 1;
242 }
243 },
244
245 /** @id MochiKit.Selector.Selector.prototype.isUIElement */
246 isUIElement: function (element) {
247 return MochiKit.Base.findValue(['input', 'button', 'select', 'option', 'textarea', 'object'],
248 element.tagName.toLowerCase()) > -1;
249 },
250
251 /** @id MochiKit.Selector.Selector.prototype.findElements */
252 findElements: function (scope, axis) {
253 var element;
254
255 if (axis == undefined) {
256 axis = "";
257 }
258
259 function inScope(element, scope) {
260 if (axis == "") {
261 return MochiKit.DOM.isChildNode(element, scope);
262 } else if (axis == ">") {
263 return element.parentNode === scope;
264 } else if (axis == "+") {
265 return element === nextSiblingElement(scope);
266 } else if (axis == "~") {
267 var sibling = scope;
268 while (sibling = nextSiblingElement(sibling)) {
269 if (element === sibling) {
270 return true;
271 }
272 }
273 return false;
274 } else {
275 throw "Invalid axis: " + axis;
276 }
277 }
278
279 if (element = MochiKit.DOM.getElement(this.params.id)) {
280 if (this.match(element)) {
281 if (!scope || inScope(element, scope)) {
282 return [element];
283 }
284 }
285 }
286
287 function nextSiblingElement(node) {
288 node = node.nextSibling;
289 while (node && node.nodeType != 1) {
290 node = node.nextSibling;
291 }
292 return node;
293 }
294
295 if (axis == "") {
296 scope = (scope || MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName || '*');
297 } else if (axis == ">") {
298 if (!scope) {
299 throw "> combinator not allowed without preceeding expression";
300 }
301 scope = MochiKit.Base.filter(function (node) {
302 return node.nodeType == 1;
303 }, scope.childNodes);
304 } else if (axis == "+") {
305 if (!scope) {
306 throw "+ combinator not allowed without preceeding expression";
307 }
308 scope = nextSiblingElement(scope) && [nextSiblingElement(scope)];
309 } else if (axis == "~") {
310 if (!scope) {
311 throw "~ combinator not allowed without preceeding expression";
312 }
313 var newscope = [];
314 while (nextSiblingElement(scope)) {
315 scope = nextSiblingElement(scope);
316 newscope.push(scope);
317 }
318 scope = newscope;
319 }
320
321 if (!scope) {
322 return [];
323 }
324
325 var results = MochiKit.Base.filter(MochiKit.Base.bind(function (scopeElt) {
326 return this.match(scopeElt);
327 }, this), scope);
328
329 return results;
330 },
331
332 /** @id MochiKit.Selector.Selector.prototype.repr */
333 repr: function () {
334 return 'Selector(' + this.expression + ')';
335 },
336
337 toString: MochiKit.Base.forwardCall("repr")
338};
339
340MochiKit.Base.update(MochiKit.Selector, {
341
342 /** @id MochiKit.Selector.findChildElements */
343 findChildElements: function (element, expressions) {
344 element = MochiKit.DOM.getElement(element);
345 var uniq = function(arr) {
346 var res = [];
347 for (var i = 0; i < arr.length; i++) {
348 if (MochiKit.Base.findIdentical(res, arr[i]) < 0) {
349 res.push(arr[i]);
350 }
351 }
352 return res;
353 };
354 return MochiKit.Base.flattenArray(MochiKit.Base.map(function (expression) {
355 var nextScope = "";
356 var reducer = function (results, expr) {
357 var match = expr.match(/^[>+~]$/);
358 if (match) {
359 nextScope = match[0];
360 return results;
361 } else {
362 var selector = new MochiKit.Selector.Selector(expr);
363 var elements = MochiKit.Iter.reduce(function (elements, result) {
364 return MochiKit.Base.extend(elements, selector.findElements(result || element, nextScope));
365 }, results, []);
366 nextScope = "";
367 return elements;
368 }
369 };
370 var exprs = expression.replace(/(^\s+|\s+$)/g, '').split(/\s+/);
371 return uniq(MochiKit.Iter.reduce(reducer, exprs, [null]));
372 }, expressions));
373 },
374
375 findDocElements: function () {
376 return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(), arguments);
377 },
378
379 __new__: function () {
380 this.$$ = this.findDocElements;
381 MochiKit.Base.nameFunctions(this);
382 }
383});
384
385MochiKit.Selector.__new__();
386
387MochiKit.Base._exportSymbols(this, MochiKit.Selector);
diff --git a/frontend/gamma/js/MochiKit/Signal.js b/frontend/gamma/js/MochiKit/Signal.js
new file mode 100644
index 0000000..7df5619
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Signal.js
@@ -0,0 +1,888 @@
1/***
2
3MochiKit.Signal 1.5
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
11MochiKit.Base._module('Signal', '1.5', ['Base', 'DOM', 'Style']);
12
13MochiKit.Signal._observers = [];
14
15/** @id MochiKit.Signal.Event */
16MochiKit.Signal.Event = function (src, e) {
17 this._event = e || window.event;
18 this._src = src;
19};
20MochiKit.Signal.Event.__export__ = false;
21
22MochiKit.Base.update(MochiKit.Signal.Event.prototype, {
23
24 __repr__: function () {
25 var repr = MochiKit.Base.repr;
26 var str = '{event(): ' + repr(this.event()) +
27 ', src(): ' + repr(this.src()) +
28 ', type(): ' + repr(this.type()) +
29 ', target(): ' + repr(this.target());
30
31 if (this.type() &&
32 this.type().indexOf('key') === 0 ||
33 this.type().indexOf('mouse') === 0 ||
34 this.type().indexOf('click') != -1 ||
35 this.type() == 'contextmenu') {
36 str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) +
37 ', ctrl: ' + repr(this.modifier().ctrl) +
38 ', meta: ' + repr(this.modifier().meta) +
39 ', shift: ' + repr(this.modifier().shift) +
40 ', any: ' + repr(this.modifier().any) + '}';
41 }
42
43 if (this.type() && this.type().indexOf('key') === 0) {
44 str += ', key(): {code: ' + repr(this.key().code) +
45 ', string: ' + repr(this.key().string) + '}';
46 }
47
48 if (this.type() && (
49 this.type().indexOf('mouse') === 0 ||
50 this.type().indexOf('click') != -1 ||
51 this.type() == 'contextmenu')) {
52
53 str += ', mouse(): {page: ' + repr(this.mouse().page) +
54 ', client: ' + repr(this.mouse().client);
55
56 if (this.type() != 'mousemove' && this.type() != 'mousewheel') {
57 str += ', button: {left: ' + repr(this.mouse().button.left) +
58 ', middle: ' + repr(this.mouse().button.middle) +
59 ', right: ' + repr(this.mouse().button.right) + '}';
60 }
61 if (this.type() == 'mousewheel') {
62 str += ', wheel: ' + repr(this.mouse().wheel);
63 }
64 str += '}';
65 }
66 if (this.type() == 'mouseover' || this.type() == 'mouseout' ||
67 this.type() == 'mouseenter' || this.type() == 'mouseleave') {
68 str += ', relatedTarget(): ' + repr(this.relatedTarget());
69 }
70 str += '}';
71 return str;
72 },
73
74 /** @id MochiKit.Signal.Event.prototype.toString */
75 toString: function () {
76 return this.__repr__();
77 },
78
79 /** @id MochiKit.Signal.Event.prototype.src */
80 src: function () {
81 return this._src;
82 },
83
84 /** @id MochiKit.Signal.Event.prototype.event */
85 event: function () {
86 return this._event;
87 },
88
89 /** @id MochiKit.Signal.Event.prototype.type */
90 type: function () {
91 if (this._event.type === "DOMMouseScroll") {
92 return "mousewheel";
93 } else {
94 return this._event.type || undefined;
95 }
96 },
97
98 /** @id MochiKit.Signal.Event.prototype.target */
99 target: function () {
100 return this._event.target || this._event.srcElement;
101 },
102
103 _relatedTarget: null,
104 /** @id MochiKit.Signal.Event.prototype.relatedTarget */
105 relatedTarget: function () {
106 if (this._relatedTarget !== null) {
107 return this._relatedTarget;
108 }
109
110 var elem = null;
111 if (this.type() == 'mouseover' || this.type() == 'mouseenter') {
112 elem = (this._event.relatedTarget ||
113 this._event.fromElement);
114 } else if (this.type() == 'mouseout' || this.type() == 'mouseleave') {
115 elem = (this._event.relatedTarget ||
116 this._event.toElement);
117 }
118 try {
119 if (elem !== null && elem.nodeType !== null) {
120 this._relatedTarget = elem;
121 return elem;
122 }
123 } catch (ignore) {
124 // Firefox 3 throws a permission denied error when accessing
125 // any property on XUL elements (e.g. scrollbars)...
126 }
127
128 return undefined;
129 },
130
131 _modifier: null,
132 /** @id MochiKit.Signal.Event.prototype.modifier */
133 modifier: function () {
134 if (this._modifier !== null) {
135 return this._modifier;
136 }
137 var m = {};
138 m.alt = this._event.altKey;
139 m.ctrl = this._event.ctrlKey;
140 m.meta = this._event.metaKey || false; // IE and Opera punt here
141 m.shift = this._event.shiftKey;
142 m.any = m.alt || m.ctrl || m.shift || m.meta;
143 this._modifier = m;
144 return m;
145 },
146
147 _key: null,
148 /** @id MochiKit.Signal.Event.prototype.key */
149 key: function () {
150 if (this._key !== null) {
151 return this._key;
152 }
153 var k = {};
154 if (this.type() && this.type().indexOf('key') === 0) {
155
156 /*
157
158 If you're looking for a special key, look for it in keydown or
159 keyup, but never keypress. If you're looking for a Unicode
160 chracter, look for it with keypress, but never keyup or
161 keydown.
162
163 Notes:
164
165 FF key event behavior:
166 key event charCode keyCode
167 DOWN ku,kd 0 40
168 DOWN kp 0 40
169 ESC ku,kd 0 27
170 ESC kp 0 27
171 a ku,kd 0 65
172 a kp 97 0
173 shift+a ku,kd 0 65
174 shift+a kp 65 0
175 1 ku,kd 0 49
176 1 kp 49 0
177 shift+1 ku,kd 0 0
178 shift+1 kp 33 0
179
180 IE key event behavior:
181 (IE doesn't fire keypress events for special keys.)
182 key event keyCode
183 DOWN ku,kd 40
184 DOWN kp undefined
185 ESC ku,kd 27
186 ESC kp 27
187 a ku,kd 65
188 a kp 97
189 shift+a ku,kd 65
190 shift+a kp 65
191 1 ku,kd 49
192 1 kp 49
193 shift+1 ku,kd 49
194 shift+1 kp 33
195
196 Safari key event behavior:
197 (Safari sets charCode and keyCode to something crazy for
198 special keys.)
199 key event charCode keyCode
200 DOWN ku,kd 63233 40
201 DOWN kp 63233 63233
202 ESC ku,kd 27 27
203 ESC kp 27 27
204 a ku,kd 97 65
205 a kp 97 97
206 shift+a ku,kd 65 65
207 shift+a kp 65 65
208 1 ku,kd 49 49
209 1 kp 49 49
210 shift+1 ku,kd 33 49
211 shift+1 kp 33 33
212
213 */
214
215 /* look for special keys here */
216 if (this.type() == 'keydown' || this.type() == 'keyup') {
217 k.code = this._event.keyCode;
218 k.string = (MochiKit.Signal._specialKeys[k.code] ||
219 'KEY_UNKNOWN');
220 this._key = k;
221 return k;
222
223 /* look for characters here */
224 } else if (this.type() == 'keypress') {
225
226 /*
227
228 Special key behavior:
229
230 IE: does not fire keypress events for special keys
231 FF: sets charCode to 0, and sets the correct keyCode
232 Safari: sets keyCode and charCode to something stupid
233
234 */
235
236 k.code = 0;
237 k.string = '';
238
239 if (typeof(this._event.charCode) != 'undefined' &&
240 this._event.charCode !== 0 &&
241 !MochiKit.Signal._specialMacKeys[this._event.charCode]) {
242 k.code = this._event.charCode;
243 k.string = String.fromCharCode(k.code);
244 } else if (this._event.keyCode &&
245 typeof(this._event.charCode) == 'undefined') { // IE
246 k.code = this._event.keyCode;
247 k.string = String.fromCharCode(k.code);
248 }
249
250 this._key = k;
251 return k;
252 }
253 }
254 return undefined;
255 },
256
257 _mouse: null,
258 /** @id MochiKit.Signal.Event.prototype.mouse */
259 mouse: function () {
260 if (this._mouse !== null) {
261 return this._mouse;
262 }
263
264 var m = {};
265 var e = this._event;
266
267 if (this.type() && (
268 this.type().indexOf('mouse') === 0 ||
269 this.type().indexOf('click') != -1 ||
270 this.type() == 'contextmenu')) {
271
272 m.client = new MochiKit.Style.Coordinates(0, 0);
273 if (e.clientX || e.clientY) {
274 m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX;
275 m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY;
276 }
277
278 m.page = new MochiKit.Style.Coordinates(0, 0);
279 if (e.pageX || e.pageY) {
280 m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX;
281 m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY;
282 } else {
283 /*
284
285 The IE shortcut can be off by two. We fix it. See:
286 http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
287
288 This is similar to the method used in
289 MochiKit.Style.getElementPosition().
290
291 */
292 var de = MochiKit.DOM._document.documentElement;
293 var b = MochiKit.DOM._document.body;
294
295 m.page.x = e.clientX +
296 (de.scrollLeft || b.scrollLeft) -
297 (de.clientLeft || 0);
298
299 m.page.y = e.clientY +
300 (de.scrollTop || b.scrollTop) -
301 (de.clientTop || 0);
302
303 }
304 if (this.type() != 'mousemove' && this.type() != 'mousewheel') {
305 m.button = {};
306 m.button.left = false;
307 m.button.right = false;
308 m.button.middle = false;
309
310 /* we could check e.button, but which is more consistent */
311 if (e.which) {
312 m.button.left = (e.which == 1);
313 m.button.middle = (e.which == 2);
314 m.button.right = (e.which == 3);
315
316 /*
317
318 Mac browsers and right click:
319
320 - Safari doesn't fire any click events on a right
321 click:
322 http://bugs.webkit.org/show_bug.cgi?id=6595
323
324 - Firefox fires the event, and sets ctrlKey = true
325
326 - Opera fires the event, and sets metaKey = true
327
328 oncontextmenu is fired on right clicks between
329 browsers and across platforms.
330
331 */
332
333 } else {
334 m.button.left = !!(e.button & 1);
335 m.button.right = !!(e.button & 2);
336 m.button.middle = !!(e.button & 4);
337 }
338 }
339 if (this.type() == 'mousewheel') {
340 m.wheel = new MochiKit.Style.Coordinates(0, 0);
341 if (e.wheelDeltaX || e.wheelDeltaY) {
342 m.wheel.x = e.wheelDeltaX / -40 || 0;
343 m.wheel.y = e.wheelDeltaY / -40 || 0;
344 } else if (e.wheelDelta) {
345 m.wheel.y = e.wheelDelta / -40;
346 } else {
347 m.wheel.y = e.detail || 0;
348 }
349 }
350 this._mouse = m;
351 return m;
352 }
353 return undefined;
354 },
355
356 /** @id MochiKit.Signal.Event.prototype.stop */
357 stop: function () {
358 this.stopPropagation();
359 this.preventDefault();
360 },
361
362 /** @id MochiKit.Signal.Event.prototype.stopPropagation */
363 stopPropagation: function () {
364 if (this._event.stopPropagation) {
365 this._event.stopPropagation();
366 } else {
367 this._event.cancelBubble = true;
368 }
369 },
370
371 /** @id MochiKit.Signal.Event.prototype.preventDefault */
372 preventDefault: function () {
373 if (this._event.preventDefault) {
374 this._event.preventDefault();
375 } else if (this._confirmUnload === null) {
376 this._event.returnValue = false;
377 }
378 },
379
380 _confirmUnload: null,
381
382 /** @id MochiKit.Signal.Event.prototype.confirmUnload */
383 confirmUnload: function (msg) {
384 if (this.type() == 'beforeunload') {
385 this._confirmUnload = msg;
386 this._event.returnValue = msg;
387 }
388 }
389});
390
391/* Safari sets keyCode to these special values onkeypress. */
392MochiKit.Signal._specialMacKeys = {
393 3: 'KEY_ENTER',
394 63289: 'KEY_NUM_PAD_CLEAR',
395 63276: 'KEY_PAGE_UP',
396 63277: 'KEY_PAGE_DOWN',
397 63275: 'KEY_END',
398 63273: 'KEY_HOME',
399 63234: 'KEY_ARROW_LEFT',
400 63232: 'KEY_ARROW_UP',
401 63235: 'KEY_ARROW_RIGHT',
402 63233: 'KEY_ARROW_DOWN',
403 63302: 'KEY_INSERT',
404 63272: 'KEY_DELETE'
405};
406
407/* for KEY_F1 - KEY_F12 */
408(function () {
409 var _specialMacKeys = MochiKit.Signal._specialMacKeys;
410 for (var i = 63236; i <= 63242; i++) {
411 // no F0
412 _specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1);
413 }
414})();
415
416/* Standard keyboard key codes. */
417MochiKit.Signal._specialKeys = {
418 8: 'KEY_BACKSPACE',
419 9: 'KEY_TAB',
420 12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only
421 13: 'KEY_ENTER',
422 16: 'KEY_SHIFT',
423 17: 'KEY_CTRL',
424 18: 'KEY_ALT',
425 19: 'KEY_PAUSE',
426 20: 'KEY_CAPS_LOCK',
427 27: 'KEY_ESCAPE',
428 32: 'KEY_SPACEBAR',
429 33: 'KEY_PAGE_UP',
430 34: 'KEY_PAGE_DOWN',
431 35: 'KEY_END',
432 36: 'KEY_HOME',
433 37: 'KEY_ARROW_LEFT',
434 38: 'KEY_ARROW_UP',
435 39: 'KEY_ARROW_RIGHT',
436 40: 'KEY_ARROW_DOWN',
437 44: 'KEY_PRINT_SCREEN',
438 45: 'KEY_INSERT',
439 46: 'KEY_DELETE',
440 59: 'KEY_SEMICOLON', // weird, for Safari and IE only
441 91: 'KEY_WINDOWS_LEFT',
442 92: 'KEY_WINDOWS_RIGHT',
443 93: 'KEY_SELECT',
444 106: 'KEY_NUM_PAD_ASTERISK',
445 107: 'KEY_NUM_PAD_PLUS_SIGN',
446 109: 'KEY_NUM_PAD_HYPHEN-MINUS',
447 110: 'KEY_NUM_PAD_FULL_STOP',
448 111: 'KEY_NUM_PAD_SOLIDUS',
449 144: 'KEY_NUM_LOCK',
450 145: 'KEY_SCROLL_LOCK',
451 186: 'KEY_SEMICOLON',
452 187: 'KEY_EQUALS_SIGN',
453 188: 'KEY_COMMA',
454 189: 'KEY_HYPHEN-MINUS',
455 190: 'KEY_FULL_STOP',
456 191: 'KEY_SOLIDUS',
457 192: 'KEY_GRAVE_ACCENT',
458 219: 'KEY_LEFT_SQUARE_BRACKET',
459 220: 'KEY_REVERSE_SOLIDUS',
460 221: 'KEY_RIGHT_SQUARE_BRACKET',
461 222: 'KEY_APOSTROPHE'
462 // undefined: 'KEY_UNKNOWN'
463};
464
465(function () {
466 /* for KEY_0 - KEY_9 */
467 var _specialKeys = MochiKit.Signal._specialKeys;
468 for (var i = 48; i <= 57; i++) {
469 _specialKeys[i] = 'KEY_' + (i - 48);
470 }
471
472 /* for KEY_A - KEY_Z */
473 for (i = 65; i <= 90; i++) {
474 _specialKeys[i] = 'KEY_' + String.fromCharCode(i);
475 }
476
477 /* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */
478 for (i = 96; i <= 105; i++) {
479 _specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96);
480 }
481
482 /* for KEY_F1 - KEY_F12 */
483 for (i = 112; i <= 123; i++) {
484 // no F0
485 _specialKeys[i] = 'KEY_F' + (i - 112 + 1);
486 }
487})();
488
489/* Internal object to keep track of created signals. */
490MochiKit.Signal.Ident = function (ident) {
491 this.source = ident.source;
492 this.signal = ident.signal;
493 this.listener = ident.listener;
494 this.isDOM = ident.isDOM;
495 this.objOrFunc = ident.objOrFunc;
496 this.funcOrStr = ident.funcOrStr;
497 this.connected = ident.connected;
498};
499MochiKit.Signal.Ident.__export__ = false;
500MochiKit.Signal.Ident.prototype = {};
501
502MochiKit.Base.update(MochiKit.Signal, {
503
504 _unloadCache: function () {
505 var self = MochiKit.Signal;
506 var observers = self._observers;
507
508 for (var i = 0; i < observers.length; i++) {
509 if (observers[i].signal !== 'onload' && observers[i].signal !== 'onunload') {
510 self._disconnect(observers[i]);
511 }
512 }
513 },
514
515 _listener: function (src, sig, func, obj, isDOM) {
516 var self = MochiKit.Signal;
517 var E = self.Event;
518 if (!isDOM) {
519 /* We don't want to re-bind already bound methods */
520 if (typeof(func.im_self) == 'undefined') {
521 return MochiKit.Base.bindLate(func, obj);
522 } else {
523 return func;
524 }
525 }
526 obj = obj || src;
527 if (typeof(func) == "string") {
528 if (sig === 'onload' || sig === 'onunload') {
529 return function (nativeEvent) {
530 obj[func].apply(obj, [new E(src, nativeEvent)]);
531
532 var ident = new MochiKit.Signal.Ident({
533 source: src, signal: sig, objOrFunc: obj, funcOrStr: func});
534
535 MochiKit.Signal._disconnect(ident);
536 };
537 } else {
538 return function (nativeEvent) {
539 obj[func].apply(obj, [new E(src, nativeEvent)]);
540 };
541 }
542 } else {
543 if (sig === 'onload' || sig === 'onunload') {
544 return function (nativeEvent) {
545 func.apply(obj, [new E(src, nativeEvent)]);
546
547 var ident = new MochiKit.Signal.Ident({
548 source: src, signal: sig, objOrFunc: func});
549
550 MochiKit.Signal._disconnect(ident);
551 };
552 } else {
553 return function (nativeEvent) {
554 func.apply(obj, [new E(src, nativeEvent)]);
555 };
556 }
557 }
558 },
559
560 _browserAlreadyHasMouseEnterAndLeave: function () {
561 return /MSIE/.test(navigator.userAgent);
562 },
563
564 _browserLacksMouseWheelEvent: function () {
565 return /Gecko\//.test(navigator.userAgent);
566 },
567
568 _mouseEnterListener: function (src, sig, func, obj) {
569 var E = MochiKit.Signal.Event;
570 return function (nativeEvent) {
571 var e = new E(src, nativeEvent);
572 try {
573 e.relatedTarget().nodeName;
574 } catch (err) {
575 /* probably hit a permission denied error; possibly one of
576 * firefox's screwy anonymous DIVs inside an input element.
577 * Allow this event to propogate up.
578 */
579 return;
580 }
581 e.stop();
582 if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) {
583 /* We've moved between our node and a child. Ignore. */
584 return;
585 }
586 e.type = function () { return sig; };
587 if (typeof(func) == "string") {
588 return obj[func].apply(obj, [e]);
589 } else {
590 return func.apply(obj, [e]);
591 }
592 };
593 },
594
595 _getDestPair: function (objOrFunc, funcOrStr) {
596 var obj = null;
597 var func = null;
598 if (typeof(funcOrStr) != 'undefined') {
599 obj = objOrFunc;
600 func = funcOrStr;
601 if (typeof(funcOrStr) == 'string') {
602 if (typeof(objOrFunc[funcOrStr]) != "function") {
603 throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
604 }
605 } else if (typeof(funcOrStr) != 'function') {
606 throw new Error("'funcOrStr' must be a function or string");
607 }
608 } else if (typeof(objOrFunc) != "function") {
609 throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
610 } else {
611 func = objOrFunc;
612 }
613 return [obj, func];
614 },
615
616 /** @id MochiKit.Signal.connect */
617 connect: function (src, sig, objOrFunc/* optional */, funcOrStr) {
618 if (typeof(src) == "string") {
619 src = MochiKit.DOM.getElement(src);
620 }
621 var self = MochiKit.Signal;
622
623 if (typeof(sig) != 'string') {
624 throw new Error("'sig' must be a string");
625 }
626
627 var destPair = self._getDestPair(objOrFunc, funcOrStr);
628 var obj = destPair[0];
629 var func = destPair[1];
630 if (typeof(obj) == 'undefined' || obj === null) {
631 obj = src;
632 }
633
634 var isDOM = !!(src.addEventListener || src.attachEvent);
635 if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave")
636 && !self._browserAlreadyHasMouseEnterAndLeave()) {
637 var listener = self._mouseEnterListener(src, sig.substr(2), func, obj);
638 if (sig === "onmouseenter") {
639 sig = "onmouseover";
640 } else {
641 sig = "onmouseout";
642 }
643 } else if (isDOM && sig == "onmousewheel" && self._browserLacksMouseWheelEvent()) {
644 var listener = self._listener(src, sig, func, obj, isDOM);
645 sig = "onDOMMouseScroll";
646 } else {
647 var listener = self._listener(src, sig, func, obj, isDOM);
648 }
649
650 if (src.addEventListener) {
651 src.addEventListener(sig.substr(2), listener, false);
652 } else if (src.attachEvent) {
653 src.attachEvent(sig, listener); // useCapture unsupported
654 }
655
656 var ident = new MochiKit.Signal.Ident({
657 source: src,
658 signal: sig,
659 listener: listener,
660 isDOM: isDOM,
661 objOrFunc: objOrFunc,
662 funcOrStr: funcOrStr,
663 connected: true
664 });
665 self._observers.push(ident);
666
667 if (!isDOM && typeof(src.__connect__) == 'function') {
668 var args = MochiKit.Base.extend([ident], arguments, 1);
669 src.__connect__.apply(src, args);
670 }
671
672 return ident;
673 },
674
675 _disconnect: function (ident) {
676 // already disconnected
677 if (!ident.connected) {
678 return;
679 }
680 ident.connected = false;
681 var src = ident.source;
682 var sig = ident.signal;
683 var listener = ident.listener;
684 // check isDOM
685 if (!ident.isDOM) {
686 if (typeof(src.__disconnect__) == 'function') {
687 src.__disconnect__(ident, sig, ident.objOrFunc, ident.funcOrStr);
688 }
689 return;
690 }
691 if (src.removeEventListener) {
692 src.removeEventListener(sig.substr(2), listener, false);
693 } else if (src.detachEvent) {
694 src.detachEvent(sig, listener); // useCapture unsupported
695 } else {
696 throw new Error("'src' must be a DOM element");
697 }
698 },
699
700 /** @id MochiKit.Signal.disconnect */
701 disconnect: function (ident) {
702 var self = MochiKit.Signal;
703 var observers = self._observers;
704 var m = MochiKit.Base;
705 if (arguments.length > 1) {
706 // compatibility API
707 var src = arguments[0];
708 if (typeof(src) == "string") {
709 src = MochiKit.DOM.getElement(src);
710 }
711 var sig = arguments[1];
712 var obj = arguments[2];
713 var func = arguments[3];
714 for (var i = observers.length - 1; i >= 0; i--) {
715 var o = observers[i];
716 if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) {
717 self._disconnect(o);
718 if (!self._lock) {
719 observers.splice(i, 1);
720 } else {
721 self._dirty = true;
722 }
723 return true;
724 }
725 }
726 } else {
727 var idx = m.findIdentical(observers, ident);
728 if (idx >= 0) {
729 self._disconnect(ident);
730 if (!self._lock) {
731 observers.splice(idx, 1);
732 } else {
733 self._dirty = true;
734 }
735 return true;
736 }
737 }
738 return false;
739 },
740
741 /** @id MochiKit.Signal.disconnectAllTo */
742 disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) {
743 var self = MochiKit.Signal;
744 var observers = self._observers;
745 var disconnect = self._disconnect;
746 var locked = self._lock;
747 var dirty = self._dirty;
748 if (typeof(funcOrStr) === 'undefined') {
749 funcOrStr = null;
750 }
751 for (var i = observers.length - 1; i >= 0; i--) {
752 var ident = observers[i];
753 if (ident.objOrFunc === objOrFunc &&
754 (funcOrStr === null || ident.funcOrStr === funcOrStr)) {
755 disconnect(ident);
756 if (locked) {
757 dirty = true;
758 } else {
759 observers.splice(i, 1);
760 }
761 }
762 }
763 self._dirty = dirty;
764 },
765
766 /** @id MochiKit.Signal.disconnectAll */
767 disconnectAll: function (src/* optional */, sig) {
768 if (typeof(src) == "string") {
769 src = MochiKit.DOM.getElement(src);
770 }
771 var m = MochiKit.Base;
772 var signals = m.flattenArguments(m.extend(null, arguments, 1));
773 var self = MochiKit.Signal;
774 var disconnect = self._disconnect;
775 var observers = self._observers;
776 var i, ident;
777 var locked = self._lock;
778 var dirty = self._dirty;
779 if (signals.length === 0) {
780 // disconnect all
781 for (i = observers.length - 1; i >= 0; i--) {
782 ident = observers[i];
783 if (ident.source === src) {
784 disconnect(ident);
785 if (!locked) {
786 observers.splice(i, 1);
787 } else {
788 dirty = true;
789 }
790 }
791 }
792 } else {
793 var sigs = {};
794 for (i = 0; i < signals.length; i++) {
795 sigs[signals[i]] = true;
796 }
797 for (i = observers.length - 1; i >= 0; i--) {
798 ident = observers[i];
799 if (ident.source === src && ident.signal in sigs) {
800 disconnect(ident);
801 if (!locked) {
802 observers.splice(i, 1);
803 } else {
804 dirty = true;
805 }
806 }
807 }
808 }
809 self._dirty = dirty;
810 },
811
812 /** @id MochiKit.Signal.signal */
813 signal: function (src, sig) {
814 var self = MochiKit.Signal;
815 var observers = self._observers;
816 if (typeof(src) == "string") {
817 src = MochiKit.DOM.getElement(src);
818 }
819 var args = MochiKit.Base.extend(null, arguments, 2);
820 var errors = [];
821 self._lock = true;
822 for (var i = 0; i < observers.length; i++) {
823 var ident = observers[i];
824 if (ident.source === src && ident.signal === sig &&
825 ident.connected) {
826 try {
827 if (ident.isDOM && ident.funcOrStr != null) {
828 var obj = ident.objOrFunc;
829 obj[ident.funcOrStr].apply(obj, args);
830 } else if (ident.isDOM) {
831 ident.objOrFunc.apply(src, args);
832 } else {
833 ident.listener.apply(src, args);
834 }
835 } catch (e) {
836 errors.push(e);
837 }
838 }
839 }
840 self._lock = false;
841 if (self._dirty) {
842 self._dirty = false;
843 for (var i = observers.length - 1; i >= 0; i--) {
844 if (!observers[i].connected) {
845 observers.splice(i, 1);
846 }
847 }
848 }
849 if (errors.length == 1) {
850 throw errors[0];
851 } else if (errors.length > 1) {
852 var e = new Error("Multiple errors thrown in handling 'sig', see errors property");
853 e.errors = errors;
854 throw e;
855 }
856 }
857
858});
859
860MochiKit.Signal.__new__ = function (win) {
861 var m = MochiKit.Base;
862 this._document = document;
863 this._window = win;
864 this._lock = false;
865 this._dirty = false;
866
867 try {
868 this.connect(window, 'onunload', this._unloadCache);
869 } catch (e) {
870 // pass: might not be a browser
871 }
872
873 m.nameFunctions(this);
874};
875
876MochiKit.Signal.__new__(this);
877
878//
879// XXX: Internet Explorer blows
880//
881if (MochiKit.__export__) {
882 connect = MochiKit.Signal.connect;
883 disconnect = MochiKit.Signal.disconnect;
884 disconnectAll = MochiKit.Signal.disconnectAll;
885 signal = MochiKit.Signal.signal;
886}
887
888MochiKit.Base._exportSymbols(this, MochiKit.Signal);
diff --git a/frontend/gamma/js/MochiKit/Sortable.js b/frontend/gamma/js/MochiKit/Sortable.js
new file mode 100644
index 0000000..863b506
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Sortable.js
@@ -0,0 +1,569 @@
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
9MochiKit.Base._module('Sortable', '1.5', ['Base', 'Iter', 'DOM', 'Position', 'DragAndDrop']);
10
11MochiKit.Base.update(MochiKit.Sortable, {
12 __export__: false,
13
14 /***
15
16 Manage sortables. Mainly use the create function to add a sortable.
17
18 ***/
19 sortables: {},
20
21 _findRootElement: function (element) {
22 while (element.tagName.toUpperCase() != "BODY") {
23 if (element.id && MochiKit.Sortable.sortables[element.id]) {
24 return element;
25 }
26 element = element.parentNode;
27 }
28 },
29
30 _createElementId: function(element) {
31 if (element.id == null || element.id == "") {
32 var d = MochiKit.DOM;
33 var id;
34 var count = 1;
35 while (d.getElement(id = "sortable" + count) != null) {
36 count += 1;
37 }
38 d.setNodeAttribute(element, "id", id);
39 }
40 },
41
42 /** @id MochiKit.Sortable.options */
43 options: function (element) {
44 element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element));
45 if (!element) {
46 return;
47 }
48 return MochiKit.Sortable.sortables[element.id];
49 },
50
51 /** @id MochiKit.Sortable.destroy */
52 destroy: function (element){
53 var s = MochiKit.Sortable.options(element);
54 var b = MochiKit.Base;
55 var d = MochiKit.DragAndDrop;
56
57 if (s) {
58 MochiKit.Signal.disconnect(s.startHandle);
59 MochiKit.Signal.disconnect(s.endHandle);
60 b.map(function (dr) {
61 d.Droppables.remove(dr);
62 }, s.droppables);
63 b.map(function (dr) {
64 dr.destroy();
65 }, s.draggables);
66
67 delete MochiKit.Sortable.sortables[s.element.id];
68 }
69 },
70
71 /** @id MochiKit.Sortable.create */
72 create: function (element, options) {
73 element = MochiKit.DOM.getElement(element);
74 var self = MochiKit.Sortable;
75 self._createElementId(element);
76
77 /** @id MochiKit.Sortable.options */
78 options = MochiKit.Base.update({
79
80 /** @id MochiKit.Sortable.element */
81 element: element,
82
83 /** @id MochiKit.Sortable.tag */
84 tag: 'li', // assumes li children, override with tag: 'tagname'
85
86 /** @id MochiKit.Sortable.dropOnEmpty */
87 dropOnEmpty: false,
88
89 /** @id MochiKit.Sortable.tree */
90 tree: false,
91
92 /** @id MochiKit.Sortable.treeTag */
93 treeTag: 'ul',
94
95 /** @id MochiKit.Sortable.overlap */
96 overlap: 'vertical', // one of 'vertical', 'horizontal'
97
98 /** @id MochiKit.Sortable.constraint */
99 constraint: 'vertical', // one of 'vertical', 'horizontal', false
100 // also takes array of elements (or ids); or false
101
102 /** @id MochiKit.Sortable.containment */
103 containment: [element],
104
105 /** @id MochiKit.Sortable.handle */
106 handle: false, // or a CSS class
107
108 /** @id MochiKit.Sortable.only */
109 only: false,
110
111 /** @id MochiKit.Sortable.hoverclass */
112 hoverclass: null,
113
114 /** @id MochiKit.Sortable.ghosting */
115 ghosting: false,
116
117 /** @id MochiKit.Sortable.scroll */
118 scroll: false,
119
120 /** @id MochiKit.Sortable.scrollSensitivity */
121 scrollSensitivity: 20,
122
123 /** @id MochiKit.Sortable.scrollSpeed */
124 scrollSpeed: 15,
125
126 /** @id MochiKit.Sortable.format */
127 format: /^[^_]*_(.*)$/,
128
129 /** @id MochiKit.Sortable.onChange */
130 onChange: MochiKit.Base.noop,
131
132 /** @id MochiKit.Sortable.onUpdate */
133 onUpdate: MochiKit.Base.noop,
134
135 /** @id MochiKit.Sortable.accept */
136 accept: null
137 }, options);
138
139 // clear any old sortable with same element
140 self.destroy(element);
141
142 // build options for the draggables
143 var options_for_draggable = {
144 revert: true,
145 ghosting: options.ghosting,
146 scroll: options.scroll,
147 scrollSensitivity: options.scrollSensitivity,
148 scrollSpeed: options.scrollSpeed,
149 constraint: options.constraint,
150 handle: options.handle
151 };
152
153 if (options.starteffect) {
154 options_for_draggable.starteffect = options.starteffect;
155 }
156
157 if (options.reverteffect) {
158 options_for_draggable.reverteffect = options.reverteffect;
159 } else if (options.ghosting) {
160 options_for_draggable.reverteffect = function (innerelement) {
161 innerelement.style.top = 0;
162 innerelement.style.left = 0;
163 };
164 }
165
166 if (options.endeffect) {
167 options_for_draggable.endeffect = options.endeffect;
168 }
169
170 if (options.zindex) {
171 options_for_draggable.zindex = options.zindex;
172 }
173
174 // build options for the droppables
175 var options_for_droppable = {
176 overlap: options.overlap,
177 containment: options.containment,
178 hoverclass: options.hoverclass,
179 onhover: self.onHover,
180 tree: options.tree,
181 accept: options.accept
182 }
183
184 var options_for_tree = {
185 onhover: self.onEmptyHover,
186 overlap: options.overlap,
187 containment: options.containment,
188 hoverclass: options.hoverclass,
189 accept: options.accept
190 }
191
192 // fix for gecko engine
193 MochiKit.DOM.removeEmptyTextNodes(element);
194
195 options.draggables = [];
196 options.droppables = [];
197
198 // drop on empty handling
199 if (options.dropOnEmpty || options.tree) {
200 new MochiKit.DragAndDrop.Droppable(element, options_for_tree);
201 options.droppables.push(element);
202 }
203 MochiKit.Base.map(function (e) {
204 // handles are per-draggable
205 var handle = options.handle ?
206 MochiKit.DOM.getFirstElementByTagAndClassName(null,
207 options.handle, e) : e;
208 options.draggables.push(
209 new MochiKit.DragAndDrop.Draggable(e,
210 MochiKit.Base.update(options_for_draggable,
211 {handle: handle})));
212 new MochiKit.DragAndDrop.Droppable(e, options_for_droppable);
213 if (options.tree) {
214 e.treeNode = element;
215 }
216 options.droppables.push(e);
217 }, (self.findElements(element, options) || []));
218
219 if (options.tree) {
220 MochiKit.Base.map(function (e) {
221 new MochiKit.DragAndDrop.Droppable(e, options_for_tree);
222 e.treeNode = element;
223 options.droppables.push(e);
224 }, (self.findTreeElements(element, options) || []));
225 }
226
227 // keep reference
228 self.sortables[element.id] = options;
229
230 options.lastValue = self.serialize(element);
231 options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start',
232 MochiKit.Base.partial(self.onStart, element));
233 options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
234 MochiKit.Base.partial(self.onEnd, element));
235 },
236
237 /** @id MochiKit.Sortable.onStart */
238 onStart: function (element, draggable) {
239 var self = MochiKit.Sortable;
240 var options = self.options(element);
241 options.lastValue = self.serialize(options.element);
242 },
243
244 /** @id MochiKit.Sortable.onEnd */
245 onEnd: function (element, draggable) {
246 var self = MochiKit.Sortable;
247 self.unmark();
248 var options = self.options(element);
249 if (options.lastValue != self.serialize(options.element)) {
250 options.onUpdate(options.element);
251 }
252 },
253
254 // return all suitable-for-sortable elements in a guaranteed order
255
256 /** @id MochiKit.Sortable.findElements */
257 findElements: function (element, options) {
258 return MochiKit.Sortable.findChildren(element, options.only, options.tree, options.tag);
259 },
260
261 /** @id MochiKit.Sortable.findTreeElements */
262 findTreeElements: function (element, options) {
263 return MochiKit.Sortable.findChildren(
264 element, options.only, options.tree ? true : false, options.treeTag);
265 },
266
267 /** @id MochiKit.Sortable.findChildren */
268 findChildren: function (element, only, recursive, tagName) {
269 if (!element.hasChildNodes()) {
270 return null;
271 }
272 tagName = tagName.toUpperCase();
273 if (only) {
274 only = MochiKit.Base.flattenArray([only]);
275 }
276 var elements = [];
277 MochiKit.Base.map(function (e) {
278 if (e.tagName &&
279 e.tagName.toUpperCase() == tagName &&
280 (!only ||
281 MochiKit.Iter.some(only, function (c) {
282 return MochiKit.DOM.hasElementClass(e, c);
283 }))) {
284 elements.push(e);
285 }
286 if (recursive) {
287 var grandchildren = MochiKit.Sortable.findChildren(e, only, recursive, tagName);
288 if (grandchildren && grandchildren.length > 0) {
289 elements = elements.concat(grandchildren);
290 }
291 }
292 }, element.childNodes);
293 return elements;
294 },
295
296 /** @id MochiKit.Sortable.onHover */
297 onHover: function (element, dropon, overlap) {
298 if (MochiKit.DOM.isChildNode(dropon, element)) {
299 return;
300 }
301 var self = MochiKit.Sortable;
302
303 if (overlap > .33 && overlap < .66 && self.options(dropon).tree) {
304 return;
305 } else if (overlap > 0.5) {
306 self.mark(dropon, 'before');
307 if (dropon.previousSibling != element) {
308 var oldParentNode = element.parentNode;
309 element.style.visibility = 'hidden'; // fix gecko rendering
310 dropon.parentNode.insertBefore(element, dropon);
311 if (dropon.parentNode != oldParentNode) {
312 self.options(oldParentNode).onChange(element);
313 }
314 self.options(dropon.parentNode).onChange(element);
315 }
316 } else {
317 self.mark(dropon, 'after');
318 var nextElement = dropon.nextSibling || null;
319 if (nextElement != element) {
320 var oldParentNode = element.parentNode;
321 element.style.visibility = 'hidden'; // fix gecko rendering
322 dropon.parentNode.insertBefore(element, nextElement);
323 if (dropon.parentNode != oldParentNode) {
324 self.options(oldParentNode).onChange(element);
325 }
326 self.options(dropon.parentNode).onChange(element);
327 }
328 }
329 },
330
331 _offsetSize: function (element, type) {
332 if (type == 'vertical' || type == 'height') {
333 return element.offsetHeight;
334 } else {
335 return element.offsetWidth;
336 }
337 },
338
339 /** @id MochiKit.Sortable.onEmptyHover */
340 onEmptyHover: function (element, dropon, overlap) {
341 var oldParentNode = element.parentNode;
342 var self = MochiKit.Sortable;
343 var droponOptions = self.options(dropon);
344
345 if (!MochiKit.DOM.isChildNode(dropon, element)) {
346 var index;
347
348 var children = self.findElements(dropon, {tag: droponOptions.tag,
349 only: droponOptions.only});
350 var child = null;
351
352 if (children) {
353 var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
354
355 for (index = 0; index < children.length; index += 1) {
356 if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) {
357 offset -= self._offsetSize(children[index], droponOptions.overlap);
358 } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
359 child = index + 1 < children.length ? children[index + 1] : null;
360 break;
361 } else {
362 child = children[index];
363 break;
364 }
365 }
366 }
367
368 dropon.insertBefore(element, child);
369
370 self.options(oldParentNode).onChange(element);
371 droponOptions.onChange(element);
372 }
373 },
374
375 /** @id MochiKit.Sortable.unmark */
376 unmark: function () {
377 var m = MochiKit.Sortable._marker;
378 if (m) {
379 MochiKit.Style.hideElement(m);
380 }
381 },
382
383 /** @id MochiKit.Sortable.mark */
384 mark: function (dropon, position) {
385 // mark on ghosting only
386 var d = MochiKit.DOM;
387 var self = MochiKit.Sortable;
388 var sortable = self.options(dropon.parentNode);
389 if (sortable && !sortable.ghosting) {
390 return;
391 }
392
393 if (!self._marker) {
394 self._marker = d.getElement('dropmarker') ||
395 document.createElement('DIV');
396 MochiKit.Style.hideElement(self._marker);
397 d.addElementClass(self._marker, 'dropmarker');
398 self._marker.style.position = 'absolute';
399 document.getElementsByTagName('body').item(0).appendChild(self._marker);
400 }
401 var offsets = MochiKit.Position.cumulativeOffset(dropon);
402 self._marker.style.left = offsets.x + 'px';
403 self._marker.style.top = offsets.y + 'px';
404
405 if (position == 'after') {
406 if (sortable.overlap == 'horizontal') {
407 self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px';
408 } else {
409 self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px';
410 }
411 }
412 MochiKit.Style.showElement(self._marker);
413 },
414
415 _tree: function (element, options, parent) {
416 var self = MochiKit.Sortable;
417 var children = self.findElements(element, options) || [];
418
419 for (var i = 0; i < children.length; ++i) {
420 var match = children[i].id.match(options.format);
421
422 if (!match) {
423 continue;
424 }
425
426 var child = {
427 id: encodeURIComponent(match ? match[1] : null),
428 element: element,
429 parent: parent,
430 children: [],
431 position: parent.children.length,
432 container: self._findChildrenElement(children[i], options.treeTag.toUpperCase())
433 }
434
435 /* Get the element containing the children and recurse over it */
436 if (child.container) {
437 self._tree(child.container, options, child)
438 }
439
440 parent.children.push (child);
441 }
442
443 return parent;
444 },
445
446 /* Finds the first element of the given tag type within a parent element.
447 Used for finding the first LI[ST] within a L[IST]I[TEM].*/
448 _findChildrenElement: function (element, containerTag) {
449 if (element && element.hasChildNodes) {
450 containerTag = containerTag.toUpperCase();
451 for (var i = 0; i < element.childNodes.length; ++i) {
452 if (element.childNodes[i].tagName.toUpperCase() == containerTag) {
453 return element.childNodes[i];
454 }
455 }
456 }
457 return null;
458 },
459
460 /** @id MochiKit.Sortable.tree */
461 tree: function (element, options) {
462 element = MochiKit.DOM.getElement(element);
463 var sortableOptions = MochiKit.Sortable.options(element);
464 options = MochiKit.Base.update({
465 tag: sortableOptions.tag,
466 treeTag: sortableOptions.treeTag,
467 only: sortableOptions.only,
468 name: element.id,
469 format: sortableOptions.format
470 }, options || {});
471
472 var root = {
473 id: null,
474 parent: null,
475 children: new Array,
476 container: element,
477 position: 0
478 }
479
480 return MochiKit.Sortable._tree(element, options, root);
481 },
482
483 /**
484 * Specifies the sequence for the Sortable.
485 * @param {Node} element Element to use as the Sortable.
486 * @param {Object} newSequence New sequence to use.
487 * @param {Object} options Options to use fro the Sortable.
488 */
489 setSequence: function (element, newSequence, options) {
490 var self = MochiKit.Sortable;
491 var b = MochiKit.Base;
492 element = MochiKit.DOM.getElement(element);
493 options = b.update(self.options(element), options || {});
494
495 var nodeMap = {};
496 b.map(function (n) {
497 var m = n.id.match(options.format);
498 if (m) {
499 nodeMap[m[1]] = [n, n.parentNode];
500 }
501 n.parentNode.removeChild(n);
502 }, self.findElements(element, options));
503
504 b.map(function (ident) {
505 var n = nodeMap[ident];
506 if (n) {
507 n[1].appendChild(n[0]);
508 delete nodeMap[ident];
509 }
510 }, newSequence);
511 },
512
513 /* Construct a [i] index for a particular node */
514 _constructIndex: function (node) {
515 var index = '';
516 do {
517 if (node.id) {
518 index = '[' + node.position + ']' + index;
519 }
520 } while ((node = node.parent) != null);
521 return index;
522 },
523
524 /** @id MochiKit.Sortable.sequence */
525 sequence: function (element, options) {
526 element = MochiKit.DOM.getElement(element);
527 var self = MochiKit.Sortable;
528 var options = MochiKit.Base.update(self.options(element), options || {});
529
530 return MochiKit.Base.map(function (item) {
531 return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
532 }, MochiKit.DOM.getElement(self.findElements(element, options) || []));
533 },
534
535 /**
536 * Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest.
537 * These options override the Sortable options for the serialization only.
538 * @param {Node} element Element to serialize.
539 * @param {Object} options Serialization options.
540 */
541 serialize: function (element, options) {
542 element = MochiKit.DOM.getElement(element);
543 var self = MochiKit.Sortable;
544 options = MochiKit.Base.update(self.options(element), options || {});
545 var name = encodeURIComponent(options.name || element.id);
546
547 if (options.tree) {
548 return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) {
549 return [name + self._constructIndex(item) + "[id]=" +
550 encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
551 }, self.tree(element, options).children)).join('&');
552 } else {
553 return MochiKit.Base.map(function (item) {
554 return name + "[]=" + encodeURIComponent(item);
555 }, self.sequence(element, options)).join('&');
556 }
557 }
558});
559
560// trunk compatibility
561MochiKit.Sortable.Sortable = MochiKit.Sortable;
562
563MochiKit.Sortable.__new__ = function () {
564 MochiKit.Base.nameFunctions(this);
565};
566
567MochiKit.Sortable.__new__();
568
569MochiKit.Base._exportSymbols(this, MochiKit.Sortable);
diff --git a/frontend/gamma/js/MochiKit/Style.js b/frontend/gamma/js/MochiKit/Style.js
new file mode 100644
index 0000000..7f10117
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Style.js
@@ -0,0 +1,558 @@
1/***
2
3MochiKit.Style 1.5
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
11MochiKit.Base._module('Style', '1.5', ['Base', 'DOM']);
12
13
14/** @id MochiKit.Style.Dimensions */
15MochiKit.Style.Dimensions = function (w, h) {
16 if (!(this instanceof MochiKit.Style.Dimensions)) {
17 return new MochiKit.Style.Dimensions(w, h);
18 }
19 this.w = w;
20 this.h = h;
21};
22
23MochiKit.Style.Dimensions.prototype.__repr__ = function () {
24 var repr = MochiKit.Base.repr;
25 return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}';
26};
27
28MochiKit.Style.Dimensions.prototype.toString = function () {
29 return this.__repr__();
30};
31
32
33/** @id MochiKit.Style.Coordinates */
34MochiKit.Style.Coordinates = function (x, y) {
35 if (!(this instanceof MochiKit.Style.Coordinates)) {
36 return new MochiKit.Style.Coordinates(x, y);
37 }
38 this.x = x;
39 this.y = y;
40};
41
42MochiKit.Style.Coordinates.prototype.__repr__ = function () {
43 var repr = MochiKit.Base.repr;
44 return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}';
45};
46
47MochiKit.Style.Coordinates.prototype.toString = function () {
48 return this.__repr__();
49};
50
51
52MochiKit.Base.update(MochiKit.Style, {
53
54 /** @id MochiKit.Style.getStyle */
55 getStyle: function (elem, cssProperty) {
56 var dom = MochiKit.DOM;
57 var d = dom._document;
58
59 elem = dom.getElement(elem);
60 cssProperty = MochiKit.Base.camelize(cssProperty);
61
62 if (!elem || elem == d) {
63 return undefined;
64 }
65 if (cssProperty == 'opacity' && typeof(elem.filters) != 'undefined') {
66 var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/);
67 if (opacity && opacity[1]) {
68 return parseFloat(opacity[1]) / 100;
69 }
70 return 1.0;
71 }
72 if (cssProperty == 'float' || cssProperty == 'cssFloat' || cssProperty == 'styleFloat') {
73 if (elem.style["float"]) {
74 return elem.style["float"];
75 } else if (elem.style.cssFloat) {
76 return elem.style.cssFloat;
77 } else if (elem.style.styleFloat) {
78 return elem.style.styleFloat;
79 } else {
80 return "none";
81 }
82 }
83 var value = elem.style ? elem.style[cssProperty] : null;
84 if (!value) {
85 if (d.defaultView && d.defaultView.getComputedStyle) {
86 var css = d.defaultView.getComputedStyle(elem, null);
87 cssProperty = cssProperty.replace(/([A-Z])/g, '-$1'
88 ).toLowerCase(); // from dojo.style.toSelectorCase
89 value = css ? css.getPropertyValue(cssProperty) : null;
90 } else if (elem.currentStyle) {
91 value = elem.currentStyle[cssProperty];
92 if (/^\d/.test(value) && !/px$/.test(value) && cssProperty != 'fontWeight') {
93 /* Convert to px using an hack from Dean Edwards */
94 var left = elem.style.left;
95 var rsLeft = elem.runtimeStyle.left;
96 elem.runtimeStyle.left = elem.currentStyle.left;
97 elem.style.left = value || 0;
98 value = elem.style.pixelLeft + "px";
99 elem.style.left = left;
100 elem.runtimeStyle.left = rsLeft;
101 }
102 }
103 }
104 if (cssProperty == 'opacity') {
105 value = parseFloat(value);
106 }
107
108 if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.findValue(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
109 if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
110 value = 'auto';
111 }
112 }
113
114 return value == 'auto' ? null : value;
115 },
116
117 /** @id MochiKit.Style.setStyle */
118 setStyle: function (elem, style) {
119 elem = MochiKit.DOM.getElement(elem);
120 for (var name in style) {
121 switch (name) {
122 case 'opacity':
123 MochiKit.Style.setOpacity(elem, style[name]);
124 break;
125 case 'float':
126 case 'cssFloat':
127 case 'styleFloat':
128 if (typeof(elem.style["float"]) != "undefined") {
129 elem.style["float"] = style[name];
130 } else if (typeof(elem.style.cssFloat) != "undefined") {
131 elem.style.cssFloat = style[name];
132 } else {
133 elem.style.styleFloat = style[name];
134 }
135 break;
136 default:
137 elem.style[MochiKit.Base.camelize(name)] = style[name];
138 }
139 }
140 },
141
142 /** @id MochiKit.Style.setOpacity */
143 setOpacity: function (elem, o) {
144 elem = MochiKit.DOM.getElement(elem);
145 var self = MochiKit.Style;
146 if (o == 1) {
147 var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
148 elem.style["opacity"] = toSet ? 0.999999 : 1.0;
149 if (/MSIE/.test(navigator.userAgent)) {
150 elem.style['filter'] =
151 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '');
152 }
153 } else {
154 if (o < 0.00001) {
155 o = 0;
156 }
157 elem.style["opacity"] = o;
158 if (/MSIE/.test(navigator.userAgent)) {
159 elem.style['filter'] =
160 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')';
161 }
162 }
163 },
164
165 /*
166
167 getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
168 Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
169 License: BSD, http://developer.yahoo.net/yui/license.txt
170
171 */
172
173 /** @id MochiKit.Style.getElementPosition */
174 getElementPosition: function (elem, /* optional */relativeTo) {
175 var self = MochiKit.Style;
176 var dom = MochiKit.DOM;
177 var isCoordinates = function (o) {
178 return o != null &&
179 o.nodeType == null &&
180 typeof(o.x) == "number" &&
181 typeof(o.y) == "number";
182 }
183
184 if (typeof(elem) == "string") {
185 elem = dom.getElement(elem);
186 }
187 if (elem == null ||
188 (!isCoordinates(elem) && self.getStyle(elem, 'display') == 'none')) {
189 return undefined;
190 }
191
192 var c = new self.Coordinates(0, 0);
193 var box = null;
194 var parent = null;
195
196 var d = MochiKit.DOM._document;
197 var de = d.documentElement;
198 var b = d.body;
199
200 if (!elem.parentNode && elem.x && elem.y) {
201 /* it's just a MochiKit.Style.Coordinates object */
202 c.x += elem.x || 0;
203 c.y += elem.y || 0;
204 } else if (elem.getBoundingClientRect) { // IE shortcut
205 /*
206
207 The IE shortcut can be off by two. We fix it. See:
208 http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
209
210 This is similar to the method used in
211 MochiKit.Signal.Event.mouse().
212
213 */
214 box = elem.getBoundingClientRect();
215
216 c.x += box.left +
217 (de.scrollLeft || b.scrollLeft) -
218 (de.clientLeft || 0);
219
220 c.y += box.top +
221 (de.scrollTop || b.scrollTop) -
222 (de.clientTop || 0);
223
224 } else if (elem.offsetParent) {
225 c.x += elem.offsetLeft;
226 c.y += elem.offsetTop;
227 parent = elem.offsetParent;
228
229 if (parent != elem) {
230 while (parent) {
231 c.x += parseInt(parent.style.borderLeftWidth) || 0;
232 c.y += parseInt(parent.style.borderTopWidth) || 0;
233 c.x += parent.offsetLeft;
234 c.y += parent.offsetTop;
235 parent = parent.offsetParent;
236 }
237 }
238
239 /*
240
241 Opera < 9 and old Safari (absolute) incorrectly account for
242 body offsetTop and offsetLeft.
243
244 */
245 var ua = navigator.userAgent.toLowerCase();
246 if ((typeof(opera) != 'undefined' &&
247 parseFloat(opera.version()) < 9) ||
248 (ua.indexOf('AppleWebKit') != -1 &&
249 self.getStyle(elem, 'position') == 'absolute')) {
250
251 c.x -= b.offsetLeft;
252 c.y -= b.offsetTop;
253
254 }
255
256 // Adjust position for strange Opera scroll bug
257 if (elem.parentNode) {
258 parent = elem.parentNode;
259 } else {
260 parent = null;
261 }
262 while (parent) {
263 var tagName = parent.tagName.toUpperCase();
264 if (tagName === 'BODY' || tagName === 'HTML') {
265 break;
266 }
267 var disp = self.getStyle(parent, 'display');
268 // Handle strange Opera bug for some display
269 if (disp.search(/^inline|table-row.*$/i)) {
270 c.x -= parent.scrollLeft;
271 c.y -= parent.scrollTop;
272 }
273 if (parent.parentNode) {
274 parent = parent.parentNode;
275 } else {
276 parent = null;
277 }
278 }
279 }
280
281 if (relativeTo) {
282 relativeTo = arguments.callee(relativeTo);
283 if (relativeTo) {
284 c.x -= (relativeTo.x || 0);
285 c.y -= (relativeTo.y || 0);
286 }
287 }
288
289 return c;
290 },
291
292 /** @id MochiKit.Style.setElementPosition */
293 setElementPosition: function (elem, newPos/* optional */, units) {
294 elem = MochiKit.DOM.getElement(elem);
295 if (typeof(units) == 'undefined') {
296 units = 'px';
297 }
298 var newStyle = {};
299 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
300 if (!isUndefNull(newPos.x)) {
301 newStyle['left'] = newPos.x + units;
302 }
303 if (!isUndefNull(newPos.y)) {
304 newStyle['top'] = newPos.y + units;
305 }
306 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
307 },
308
309 /** @id MochiKit.Style.makePositioned */
310 makePositioned: function (element) {
311 element = MochiKit.DOM.getElement(element);
312 var pos = MochiKit.Style.getStyle(element, 'position');
313 if (pos == 'static' || !pos) {
314 element.style.position = 'relative';
315 // Opera returns the offset relative to the positioning context,
316 // when an element is position relative but top and left have
317 // not been defined
318 if (/Opera/.test(navigator.userAgent)) {
319 element.style.top = 0;
320 element.style.left = 0;
321 }
322 }
323 },
324
325 /** @id MochiKit.Style.undoPositioned */
326 undoPositioned: function (element) {
327 element = MochiKit.DOM.getElement(element);
328 if (element.style.position == 'relative') {
329 element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
330 }
331 },
332
333 /** @id MochiKit.Style.makeClipping */
334 makeClipping: function (element) {
335 element = MochiKit.DOM.getElement(element);
336 var s = element.style;
337 var oldOverflow = { 'overflow': s.overflow,
338 'overflow-x': s.overflowX,
339 'overflow-y': s.overflowY };
340 if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
341 element.style.overflow = 'hidden';
342 element.style.overflowX = 'hidden';
343 element.style.overflowY = 'hidden';
344 }
345 return oldOverflow;
346 },
347
348 /** @id MochiKit.Style.undoClipping */
349 undoClipping: function (element, overflow) {
350 element = MochiKit.DOM.getElement(element);
351 if (typeof(overflow) == 'string') {
352 element.style.overflow = overflow;
353 } else if (overflow != null) {
354 element.style.overflow = overflow['overflow'];
355 element.style.overflowX = overflow['overflow-x'];
356 element.style.overflowY = overflow['overflow-y'];
357 }
358 },
359
360 /** @id MochiKit.Style.getElementDimensions */
361 getElementDimensions: function (elem, contentSize/*optional*/) {
362 var self = MochiKit.Style;
363 var dom = MochiKit.DOM;
364 if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
365 return new self.Dimensions(elem.w || 0, elem.h || 0);
366 }
367 elem = dom.getElement(elem);
368 if (!elem) {
369 return undefined;
370 }
371 var disp = self.getStyle(elem, 'display');
372 // display can be empty/undefined on WebKit/KHTML
373 if (disp == 'none' || disp == '' || typeof(disp) == 'undefined') {
374 var s = elem.style;
375 var originalVisibility = s.visibility;
376 var originalPosition = s.position;
377 var originalDisplay = s.display;
378 s.visibility = 'hidden';
379 s.position = 'absolute';
380 s.display = self._getDefaultDisplay(elem);
381 var originalWidth = elem.offsetWidth;
382 var originalHeight = elem.offsetHeight;
383 s.display = originalDisplay;
384 s.position = originalPosition;
385 s.visibility = originalVisibility;
386 } else {
387 originalWidth = elem.offsetWidth || 0;
388 originalHeight = elem.offsetHeight || 0;
389 }
390 if (contentSize) {
391 var tableCell = 'colSpan' in elem && 'rowSpan' in elem;
392 var collapse = (tableCell && elem.parentNode && self.getStyle(
393 elem.parentNode, 'borderCollapse') == 'collapse')
394 if (collapse) {
395 if (/MSIE/.test(navigator.userAgent)) {
396 var borderLeftQuota = elem.previousSibling? 0.5 : 1;
397 var borderRightQuota = elem.nextSibling? 0.5 : 1;
398 }
399 else {
400 var borderLeftQuota = 0.5;
401 var borderRightQuota = 0.5;
402 }
403 } else {
404 var borderLeftQuota = 1;
405 var borderRightQuota = 1;
406 }
407 originalWidth -= Math.round(
408 (parseFloat(self.getStyle(elem, 'paddingLeft')) || 0)
409 + (parseFloat(self.getStyle(elem, 'paddingRight')) || 0)
410 + borderLeftQuota *
411 (parseFloat(self.getStyle(elem, 'borderLeftWidth')) || 0)
412 + borderRightQuota *
413 (parseFloat(self.getStyle(elem, 'borderRightWidth')) || 0)
414 );
415 if (tableCell) {
416 if (/Gecko|Opera/.test(navigator.userAgent)
417 && !/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)) {
418 var borderHeightQuota = 0;
419 } else if (/MSIE/.test(navigator.userAgent)) {
420 var borderHeightQuota = 1;
421 } else {
422 var borderHeightQuota = collapse? 0.5 : 1;
423 }
424 } else {
425 var borderHeightQuota = 1;
426 }
427 originalHeight -= Math.round(
428 (parseFloat(self.getStyle(elem, 'paddingTop')) || 0)
429 + (parseFloat(self.getStyle(elem, 'paddingBottom')) || 0)
430 + borderHeightQuota * (
431 (parseFloat(self.getStyle(elem, 'borderTopWidth')) || 0)
432 + (parseFloat(self.getStyle(elem, 'borderBottomWidth')) || 0))
433 );
434 }
435 return new self.Dimensions(originalWidth, originalHeight);
436 },
437
438 /** @id MochiKit.Style.setElementDimensions */
439 setElementDimensions: function (elem, newSize/* optional */, units) {
440 elem = MochiKit.DOM.getElement(elem);
441 if (typeof(units) == 'undefined') {
442 units = 'px';
443 }
444 var newStyle = {};
445 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
446 if (!isUndefNull(newSize.w)) {
447 newStyle['width'] = newSize.w + units;
448 }
449 if (!isUndefNull(newSize.h)) {
450 newStyle['height'] = newSize.h + units;
451 }
452 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
453 },
454
455 _getDefaultDisplay: function (elem) {
456 var self = MochiKit.Style;
457 var dom = MochiKit.DOM;
458 elem = dom.getElement(elem);
459 if (!elem) {
460 return undefined;
461 }
462 var tagName = elem.tagName.toUpperCase();
463 return self._defaultDisplay[tagName] || 'block';
464 },
465
466 /** @id MochiKit.Style.setDisplayForElement */
467 setDisplayForElement: function (display, element/*, ...*/) {
468 var elements = MochiKit.Base.extend(null, arguments, 1);
469 var getElement = MochiKit.DOM.getElement;
470 for (var i = 0; i < elements.length; i++) {
471 element = getElement(elements[i]);
472 if (element) {
473 element.style.display = display;
474 }
475 }
476 },
477
478 /** @id MochiKit.Style.getViewportDimensions */
479 getViewportDimensions: function () {
480 var d = new MochiKit.Style.Dimensions();
481 var w = MochiKit.DOM._window;
482 var b = MochiKit.DOM._document.body;
483 if (w.innerWidth) {
484 d.w = w.innerWidth;
485 d.h = w.innerHeight;
486 } else if (b && b.parentElement && b.parentElement.clientWidth) {
487 d.w = b.parentElement.clientWidth;
488 d.h = b.parentElement.clientHeight;
489 } else if (b && b.clientWidth) {
490 d.w = b.clientWidth;
491 d.h = b.clientHeight;
492 }
493 return d;
494 },
495
496 /** @id MochiKit.Style.getViewportPosition */
497 getViewportPosition: function () {
498 var c = new MochiKit.Style.Coordinates(0, 0);
499 var d = MochiKit.DOM._document;
500 var de = d.documentElement;
501 var db = d.body;
502 if (de && (de.scrollTop || de.scrollLeft)) {
503 c.x = de.scrollLeft;
504 c.y = de.scrollTop;
505 } else if (db) {
506 c.x = db.scrollLeft;
507 c.y = db.scrollTop;
508 }
509 return c;
510 },
511
512 __new__: function () {
513 var m = MochiKit.Base;
514
515 var inlines = ['A','ABBR','ACRONYM','B','BASEFONT','BDO','BIG','BR',
516 'CITE','CODE','DFN','EM','FONT','I','IMG','KBD','LABEL',
517 'Q','S','SAMP','SMALL','SPAN','STRIKE','STRONG','SUB',
518 'SUP','TEXTAREA','TT','U','VAR'];
519 this._defaultDisplay = { 'TABLE': 'table',
520 'THEAD': 'table-header-group',
521 'TBODY': 'table-row-group',
522 'TFOOT': 'table-footer-group',
523 'COLGROUP': 'table-column-group',
524 'COL': 'table-column',
525 'TR': 'table-row',
526 'TD': 'table-cell',
527 'TH': 'table-cell',
528 'CAPTION': 'table-caption',
529 'LI': 'list-item',
530 'INPUT': 'inline-block',
531 'SELECT': 'inline-block' };
532 // CSS 'display' support in IE6/7 is just broken...
533 if (/MSIE/.test(navigator.userAgent)) {
534 for (var k in this._defaultDisplay) {
535 var v = this._defaultDisplay[k];
536 if (v.indexOf('table') == 0) {
537 this._defaultDisplay[k] = 'block';
538 }
539 }
540 }
541 for (var i = 0; i < inlines.length; i++) {
542 this._defaultDisplay[inlines[i]] = 'inline';
543 }
544
545 // Backwards compatibility aliases
546 m._deprecated(this, 'elementPosition', 'MochiKit.Style.getElementPosition', '1.3');
547 m._deprecated(this, 'elementDimensions', 'MochiKit.Style.getElementDimensions', '1.3');
548
549 this.hideElement = m.partial(this.setDisplayForElement, 'none');
550 // TODO: showElement could be improved by using getDefaultDisplay.
551 this.showElement = m.partial(this.setDisplayForElement, 'block');
552
553 m.nameFunctions(this);
554 }
555});
556
557MochiKit.Style.__new__();
558MochiKit.Base._exportSymbols(this, MochiKit.Style);
diff --git a/frontend/gamma/js/MochiKit/Test.js b/frontend/gamma/js/MochiKit/Test.js
new file mode 100644
index 0000000..9520ab2
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Test.js
@@ -0,0 +1,144 @@
1/***
2
3MochiKit.Test 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('Test', '1.5', ['Base']);
12
13MochiKit.Test.runTests = function (obj) {
14 if (typeof(obj) == "string") {
15 // TODO: Remove this temporary API change advertisement
16 throw new TypeError("Automatic module import not supported, call runTests() with proper object: " + obj);
17 }
18 var suite = new MochiKit.Test.Suite();
19 suite.run(obj);
20};
21
22MochiKit.Test.Suite = function () {
23 this.testIndex = 0;
24 MochiKit.Base.bindMethods(this);
25};
26
27MochiKit.Test.Suite.prototype = {
28 run: function (obj) {
29 try {
30 obj(this);
31 } catch (e) {
32 this.traceback(e);
33 }
34 },
35 traceback: function (e) {
36 var items = MochiKit.Iter.sorted(MochiKit.Base.items(e));
37 print("not ok " + this.testIndex + " - Error thrown");
38 for (var i = 0; i < items.length; i++) {
39 var kv = items[i];
40 if (kv[0] == "stack") {
41 kv[1] = kv[1].split(/\n/)[0];
42 }
43 this.print("# " + kv.join(": "));
44 }
45 },
46 print: function (s) {
47 print(s);
48 },
49 is: function (got, expected, /* optional */message) {
50 var res = 1;
51 var msg = null;
52 try {
53 res = MochiKit.Base.compare(got, expected);
54 } catch (e) {
55 msg = "Can not compare " + typeof(got) + ":" + typeof(expected);
56 }
57 if (res) {
58 msg = "Expected value did not compare equal";
59 }
60 if (!res) {
61 return this.testResult(true, message);
62 }
63 return this.testResult(false, message,
64 [[msg], ["got:", got], ["expected:", expected]]);
65 },
66
67 testResult: function (pass, msg, failures) {
68 this.testIndex += 1;
69 if (pass) {
70 this.print("ok " + this.testIndex + " - " + msg);
71 return;
72 }
73 this.print("not ok " + this.testIndex + " - " + msg);
74 if (failures) {
75 for (var i = 0; i < failures.length; i++) {
76 this.print("# " + failures[i].join(" "));
77 }
78 }
79 },
80
81 isDeeply: function (got, expected, /* optional */message) {
82 var m = MochiKit.Base;
83 var res = 1;
84 try {
85 res = m.compare(got, expected);
86 } catch (e) {
87 // pass
88 }
89 if (res === 0) {
90 return this.ok(true, message);
91 }
92 var gk = m.keys(got);
93 var ek = m.keys(expected);
94 gk.sort();
95 ek.sort();
96 if (m.compare(gk, ek)) {
97 // differing keys
98 var cmp = {};
99 var i;
100 for (i = 0; i < gk.length; i++) {
101 cmp[gk[i]] = "got";
102 }
103 for (i = 0; i < ek.length; i++) {
104 if (ek[i] in cmp) {
105 delete cmp[ek[i]];
106 } else {
107 cmp[ek[i]] = "expected";
108 }
109 }
110 var diffkeys = m.keys(cmp);
111 diffkeys.sort();
112 var gotkeys = [];
113 var expkeys = [];
114 while (diffkeys.length) {
115 var k = diffkeys.shift();
116 if (k in Object.prototype) {
117 continue;
118 }
119 (cmp[k] == "got" ? gotkeys : expkeys).push(k);
120 }
121
122
123 }
124
125 return this.testResult((!res), msg,
126 (msg ? [["got:", got], ["expected:", expected]] : undefined)
127 );
128 },
129
130 ok: function (res, message) {
131 return this.testResult(res, message);
132 }
133};
134
135MochiKit.Test.__new__ = function () {
136 var m = MochiKit.Base;
137 this.Suite.__export__ = false;
138 m.nameFunctions(this);
139
140};
141
142MochiKit.Test.__new__();
143
144MochiKit.Base._exportSymbols(this, MochiKit.Test);
diff --git a/frontend/gamma/js/MochiKit/Text.js b/frontend/gamma/js/MochiKit/Text.js
new file mode 100644
index 0000000..a44f7e4
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Text.js
@@ -0,0 +1,577 @@
1/***
2
3MochiKit.Text 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2008 Per Cederberg. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('Text', '1.5', ['Base', 'Format']);
12
13/**
14 * Checks if a text string starts with the specified substring. If
15 * either of the two strings is null, false will be returned.
16 *
17 * @param {String} substr the substring to search for
18 * @param {String} str the string to search in
19 *
20 * @return {Boolean} true if the string starts with the substring, or
21 * false otherwise
22 */
23MochiKit.Text.startsWith = function (substr, str) {
24 return str != null && substr != null && str.indexOf(substr) == 0;
25}
26
27/**
28 * Checks if a text string ends with the specified substring. If
29 * either of the two strings is null, false will be returned.
30 *
31 * @param {String} substr the substring to search for
32 * @param {String} str the string to search in
33 *
34 * @return {Boolean} true if the string ends with the substring, or
35 * false otherwise
36 */
37MochiKit.Text.endsWith = function (substr, str) {
38 return str != null && substr != null &&
39 str.lastIndexOf(substr) == Math.max(str.length - substr.length, 0);
40}
41
42/**
43 * Checks if a text string contains the specified substring. If
44 * either of the two strings is null, false will be returned.
45 *
46 * @param {String} substr the substring to search for
47 * @param {String} str the string to search in
48 *
49 * @return {Boolean} true if the string contains the substring, or
50 * false otherwise
51 */
52MochiKit.Text.contains = function (substr, str) {
53 return str != null && substr != null && str.indexOf(substr) >= 0;
54}
55
56/**
57 * Adds a character to the left-hand side of a string until it
58 * reaches the specified minimum length.
59 *
60 * @param {String} str the string to process
61 * @param {Number} minLength the requested minimum length
62 * @param {String} fillChar the padding character to add, defaults
63 * to a space
64 *
65 * @return {String} the padded string
66 */
67MochiKit.Text.padLeft = function (str, minLength, fillChar) {
68 str = str || "";
69 fillChar = fillChar || " ";
70 while (str.length < minLength) {
71 str = fillChar + str;
72 }
73 return str;
74}
75
76/**
77 * Adds a character to the right-hand side of a string until it
78 * reaches the specified minimum length.
79 *
80 * @param {String} str the string to process
81 * @param {Number} minLength the requested minimum length
82 * @param {String} fillChar the padding character to add, defaults
83 * to a space
84 *
85 * @return {String} the padded string
86 */
87MochiKit.Text.padRight = function (str, minLength, fillChar) {
88 str = str || "";
89 fillChar = fillChar || " ";
90 while (str.length < minLength) {
91 str += fillChar;
92 }
93 return str;
94}
95
96/**
97 * Returns a truncated copy of a string. If the string is shorter
98 * than the specified maximum length, the object will be returned
99 * unmodified. If an optional tail string is specified, additional
100 * elements will be removed in order to accomodate the tail (that
101 * will be appended). This function also works on arrays.
102 *
103 * @param {String} str the string to truncate
104 * @param {Number} maxLength the maximum length
105 * @param {String} [tail] the tail to append on truncation
106 *
107 * @return {String} the truncated string
108 */
109MochiKit.Text.truncate = function (str, maxLength, tail) {
110 if (str == null || str.length <= maxLength || maxLength < 0) {
111 return str;
112 } else if (tail != null) {
113 str = str.slice(0, Math.max(0, maxLength - tail.length));
114 if (typeof(str) == "string") {
115 return str + tail;
116 } else {
117 return MochiKit.Base.extend(str, tail);
118 }
119 } else {
120 return str.slice(0, maxLength);
121 }
122}
123
124/**
125 * Splits a text string, applies a function and joins the results
126 * back together again. This is a convenience function for calling
127 * split(), map() and join() separately. It can be used to easily
128 * trim each line in a text string (using the strip function), or to
129 * translate a text word-by-word.
130 *
131 * @param {Function} func the function to apply
132 * @param {String} str the string to split
133 * @param {String} [separator] the separator character to use,
134 * defaults to newline
135 *
136 * @return {String} a string with the joined up results
137 */
138MochiKit.Text.splitJoin = function (func, str, separator) {
139 if (str == null || str.length == 0) {
140 return str;
141 }
142 separator = separator || '\n'
143 return MochiKit.Base.map(func, str.split(separator)).join(separator);
144}
145
146/**
147 * Creates a formatter function for the specified formatter pattern
148 * and locale. The returned function takes as many arguments as the
149 * formatter pattern requires. See separate documentation for
150 * information about the formatter pattern syntax.
151 *
152 * @param {String} pattern the formatter pattern string
153 * @param {Object} [locale] the locale to use, defaults to
154 * LOCALE.en_US
155 *
156 * @return {Function} the formatter function created
157 *
158 * @throws FormatPatternError if the format pattern was invalid
159 */
160MochiKit.Text.formatter = function (pattern, locale) {
161 if (typeof(locale) == "undefined") {
162 locale = MochiKit.Format.formatLocale();
163 } else if (typeof(locale) == "string") {
164 locale = MochiKit.Format.formatLocale(locale);
165 }
166 var parts = MochiKit.Text._parsePattern(pattern);
167 return function() {
168 var values = MochiKit.Base.extend([], arguments);
169 var res = [];
170 for (var i = 0; i < parts.length; i++) {
171 if (typeof(parts[i]) == "string") {
172 res.push(parts[i]);
173 } else {
174 res.push(MochiKit.Text.formatValue(parts[i], values, locale));
175 }
176 }
177 return res.join("");
178 }
179}
180
181/**
182 * Formats the specified arguments according to a formatter pattern.
183 * See separate documentation for information about the formatter
184 * pattern syntax.
185 *
186 * @param {String} pattern the formatter pattern string
187 * @param {Object} [...] the optional values to format
188 *
189 * @return {String} the formatted output string
190 *
191 * @throws FormatPatternError if the format pattern was invalid
192 */
193MochiKit.Text.format = function (pattern/*, ...*/) {
194 var func = MochiKit.Text.formatter(pattern);
195 return func.apply(this, MochiKit.Base.extend([], arguments, 1));
196}
197
198/**
199 * Format a value with the specified format specifier.
200 *
201 * @param {String/Object} spec the format specifier string or parsed
202 * format specifier object
203 * @param {Object} value the value to format
204 * @param {Object} [locale] the locale to use, defaults to
205 * LOCALE.en_US
206 *
207 * @return {String} the formatted output string
208 */
209MochiKit.Text.formatValue = function (spec, value, locale) {
210 var self = MochiKit.Text;
211 if (typeof(spec) === "string") {
212 spec = self._parseFormatFlags(spec, 0, spec.length - 1);
213 }
214 for (var i = 0; spec.path != null && i < spec.path.length; i++) {
215 if (value != null) {
216 value = value[spec.path[i]];
217 }
218 }
219 if (typeof(locale) == "undefined") {
220 locale = MochiKit.Format.formatLocale();
221 } else if (typeof(locale) == "string") {
222 locale = MochiKit.Format.formatLocale(locale);
223 }
224 var str = "";
225 if (spec.numeric) {
226 if (typeof(value) != "number" || isNaN(value)) {
227 str = "";
228 } else if (value === Number.POSITIVE_INFINITY) {
229 str = "\u221e";
230 } else if (value === Number.NEGATIVE_INFINITY) {
231 str = "-\u221e";
232 } else {
233 var sign = (spec.sign === "-") ? "" : spec.sign;
234 sign = (value < 0) ? "-" : sign;
235 value = Math.abs(value);
236 if (spec.format === "%") {
237 str = self._truncToPercent(value, spec.precision);
238 } else if (spec.format === "d") {
239 str = MochiKit.Format.roundToFixed(value, 0);
240 } else if (spec.radix != 10) {
241 str = Math.floor(value).toString(spec.radix);
242 if (spec.format === "x") {
243 str = str.toLowerCase();
244 } else if (spec.format === "X") {
245 str = str.toUpperCase();
246 }
247 } else if (spec.precision >= 0) {
248 str = MochiKit.Format.roundToFixed(value, spec.precision);
249 } else {
250 str = value.toString();
251 }
252 if (spec.padding === "0" && spec.format === "%") {
253 str = self.padLeft(str, spec.width - sign.length - 1, "0");
254 } else if (spec.padding == "0") {
255 str = self.padLeft(str, spec.width - sign.length, "0");
256 }
257 str = self._localizeNumber(str, locale, spec.grouping);
258 str = sign + str;
259 }
260 if (str !== "" && spec.format === "%") {
261 str = str + locale.percent;
262 }
263 } else {
264 if (spec.format == "r") {
265 str = MochiKit.Base.repr(value);
266 } else {
267 str = (value == null) ? "null" : value.toString();
268 }
269 str = self.truncate(str, spec.precision);
270 }
271 if (spec.align == "<") {
272 str = self.padRight(str, spec.width);
273 } else {
274 str = self.padLeft(str, spec.width);
275 }
276 return str;
277}
278
279/**
280 * Adjust an already formatted numeric string for locale-specific
281 * grouping and decimal separators. The grouping is optional and
282 * will attempt to keep the number string length intact by removing
283 * padded zeros (if possible).
284 *
285 * @param {String} num the formatted number string
286 * @param {Object} locale the formatting locale to use
287 * @param {Boolean} grouping the grouping flag
288 *
289 * @return {String} the localized number string
290 */
291MochiKit.Text._localizeNumber = function (num, locale, grouping) {
292 var parts = num.split(/\./);
293 var whole = parts[0];
294 var frac = (parts.length == 1) ? "" : parts[1];
295 var res = (frac.length > 0) ? locale.decimal : "";
296 while (grouping && frac.length > 3) {
297 res = res + frac.substring(0, 3) + locale.separator;
298 frac = frac.substring(3);
299 if (whole.charAt(0) == "0") {
300 whole = whole.substring(1);
301 }
302 }
303 if (frac.length > 0) {
304 res += frac;
305 }
306 while (grouping && whole.length > 3) {
307 var pos = whole.length - 3;
308 res = locale.separator + whole.substring(pos) + res;
309 whole = whole.substring((whole.charAt(0) == "0") ? 1 : 0, pos);
310 }
311 return whole + res;
312}
313
314/**
315 * Parses a format pattern and returns an array of constant strings
316 * and format info objects.
317 *
318 * @param {String} pattern the format pattern to analyze
319 *
320 * @return {Array} an array of strings and format info objects
321 *
322 * @throws FormatPatternError if the format pattern was invalid
323 */
324MochiKit.Text._parsePattern = function (pattern) {
325 var self = MochiKit.Text;
326 var parts = [];
327 var start = 0;
328 var pos = 0;
329 for (pos = 0; pos < pattern.length; pos++) {
330 if (pattern.charAt(pos) == "{") {
331 if (pos + 1 >= pattern.length) {
332 var msg = "unescaped { char, should be escaped as {{";
333 throw new self.FormatPatternError(pattern, pos, msg);
334 } else if (pattern.charAt(pos + 1) == "{") {
335 parts.push(pattern.substring(start, pos + 1));
336 start = pos + 2;
337 pos++;
338 } else {
339 if (start < pos) {
340 parts.push(pattern.substring(start, pos));
341 }
342 start = pattern.indexOf("}", pos) + 1;
343 if (start <= 0) {
344 var msg = "unmatched { char, not followed by a } char";
345 throw new self.FormatPatternError(pattern, pos, msg);
346 }
347 parts.push(self._parseFormat(pattern, pos + 1, start - 1));
348 pos = start - 1;
349 }
350 } else if (pattern.charAt(pos) == "}") {
351 if (pos + 1 >= pattern.length || pattern.charAt(pos + 1) != "}") {
352 var msg = "unescaped } char, should be escaped as }}";
353 throw new self.FormatPatternError(pattern, pos, msg);
354 }
355 parts.push(pattern.substring(start, pos + 1));
356 start = pos + 2;
357 pos++;
358 }
359 }
360 if (start < pos) {
361 parts.push(pattern.substring(start, pos));
362 }
363 return parts;
364}
365
366/**
367 * Parses a format instruction and returns a format info object.
368 *
369 * @param {String} pattern the format pattern string
370 * @param {Number} startPos the first index of the format instruction
371 * @param {Number} endPos the last index of the format instruction
372 *
373 * @return {Object} the format info object
374 *
375 * @throws FormatPatternError if the format pattern was invalid
376 */
377MochiKit.Text._parseFormat = function (pattern, startPos, endPos) {
378 var self = MochiKit.Text;
379 var text = pattern.substring(startPos, endPos);
380 var info;
381 var pos = text.indexOf(":");
382 if (pos == 0) {
383 info = self._parseFormatFlags(pattern, startPos + 1, endPos);
384 info.path = [0];
385 } else if (pos > 0) {
386 info = self._parseFormatFlags(pattern, startPos + pos + 1, endPos);
387 info.path = text.substring(0, pos).split(".");
388 } else {
389 info = self._parseFormatFlags(pattern, endPos, endPos);
390 info.path = text.split(".");
391 }
392 var DIGITS = /^\d+$/;
393 for (var i = 0; i < info.path.length; i++) {
394 var e = info.path[i];
395 if (typeof(e) == "string") {
396 // TODO: replace with MochiKit.Format.strip?
397 e = e.replace(/^\s+/, "").replace(/\s+$/, "");
398 if (e == "" && info.path.length == 1) {
399 e = 0;
400 } else if (e == "") {
401 var msg = "format value path contains blanks";
402 throw new self.FormatPatternError(pattern, startPos, msg);
403 } else if (DIGITS.test(e)) {
404 e = parseInt(e);
405 }
406 }
407 info.path[i] = e;
408 }
409 if (info.path.length < 0 || typeof(info.path[0]) != "number") {
410 info.path.unshift(0);
411 }
412 return info;
413}
414
415/**
416 * Parses a string with format flags and returns a format info object.
417 *
418 * @param {String} pattern the format pattern string
419 * @param {Number} startPos the first index of the format instruction
420 * @param {Number} endPos the last index of the format instruction
421 *
422 * @return {Object} the format info object
423 *
424 * @throws FormatPatternError if the format pattern was invalid
425 */
426MochiKit.Text._parseFormatFlags = function (pattern, startPos, endPos) {
427 var self = MochiKit.Text;
428 var info = { numeric: false, format: "s", width: 0, precision: -1,
429 align: ">", sign: "-", padding: " ", grouping: false };
430 // TODO: replace with MochiKit.Format.rstrip?
431 var flags = pattern.substring(startPos, endPos).replace(/\s+$/, "");
432 while (flags.length > 0) {
433 switch (flags.charAt(0)) {
434 case ">":
435 case "<":
436 info.align = flags.charAt(0);
437 flags = flags.substring(1);
438 break;
439 case "+":
440 case "-":
441 case " ":
442 info.sign = flags.charAt(0);
443 flags = flags.substring(1);
444 break;
445 case ",":
446 info.grouping = true;
447 flags = flags.substring(1);
448 break;
449 case ".":
450 var chars = /^\d*/.exec(flags.substring(1))[0];
451 info.precision = parseInt(chars);
452 flags = flags.substring(1 + chars.length);
453 break;
454 case "0":
455 info.padding = flags.charAt(0);
456 flags = flags.substring(1);
457 break;
458 case "1":
459 case "2":
460 case "3":
461 case "4":
462 case "5":
463 case "6":
464 case "7":
465 case "8":
466 case "9":
467 var chars = /^\d*/.exec(flags)[0];
468 info.width = parseInt(chars);
469 flags = flags.substring(chars.length);
470 break;
471 case "s":
472 case "r":
473 info.format = flags.charAt(0);
474 flags = flags.substring(1);
475 break;
476 case "b":
477 case "d":
478 case "o":
479 case "x":
480 case "X":
481 case "f":
482 case "%":
483 info.numeric = true;
484 info.format = flags.charAt(0);
485 info.radix = 10;
486 if (info.format === "b") {
487 info.radix = 2;
488 } else if (info.format === "o") {
489 info.radix = 8;
490 } else if (info.format === "x" || info.format === "X") {
491 info.radix = 16;
492 }
493 flags = flags.substring(1);
494 break;
495 default:
496 var msg = "unsupported format flag: " + flags.charAt(0);
497 throw new self.FormatPatternError(pattern, startPos, msg);
498 }
499 }
500 return info;
501}
502
503/**
504 * Formats a value as a percentage. This method avoids multiplication
505 * by 100 since it leads to weird numeric rounding errors. Instead it
506 * just move the decimal separator in the text string. It is ugly,
507 * but works...
508 *
509 * @param {Number} value the value to format
510 * @param {Number} precision the number of precision digits
511 */
512MochiKit.Text._truncToPercent = function (value, precision) {
513 // TODO: This can be simplified by using the same helper function
514 // as roundToFixed now does.
515 var str;
516 if (precision >= 0) {
517 str = MochiKit.Format.roundToFixed(value, precision + 2);
518 } else {
519 str = (value == null) ? "0" : value.toString();
520 }
521 var fracPos = str.indexOf(".");
522 if (fracPos < 0) {
523 str = str + "00";
524 } else if (fracPos + 3 >= str.length) {
525 var fraction = str.substring(fracPos + 1);
526 while (fraction.length < 2) {
527 fraction = fraction + "0";
528 }
529 str = str.substring(0, fracPos) + fraction;
530 } else {
531 var fraction = str.substring(fracPos + 1);
532 str = str.substring(0, fracPos) + fraction.substring(0, 2) +
533 "." + fraction.substring(2);
534 }
535 while (str.length > 1 && str.charAt(0) == "0" && str.charAt(1) != ".") {
536 str = str.substring(1);
537 }
538 return str;
539}
540
541/**
542 * Creates a new format pattern error.
543 *
544 * @param {String} pattern the format pattern string
545 * @param {Number} pos the position of the error
546 * @param {String} message the error message text
547 *
548 * @return {Error} the format pattern error
549 *
550 * @class The format pattern error class. This error is thrown when
551 * a syntax error is encountered inside a format string.
552 * @property {String} pattern The format pattern string.
553 * @property {Number} pos The position of the error.
554 * @property {String} message The error message text.
555 * @extends MochiKit.Base.NamedError
556 */
557MochiKit.Text.FormatPatternError = function (pattern, pos, message) {
558 this.pattern = pattern;
559 this.pos = pos;
560 this.message = message;
561}
562MochiKit.Text.FormatPatternError.prototype =
563 new MochiKit.Base.NamedError("MochiKit.Text.FormatPatternError");
564
565
566//
567//XXX: Internet Explorer exception handling blows
568//
569if (MochiKit.__export__) {
570 formatter = MochiKit.Text.formatter;
571 format = MochiKit.Text.format;
572 formatValue = MochiKit.Text.formatValue;
573}
574
575
576MochiKit.Base.nameFunctions(MochiKit.Text);
577MochiKit.Base._exportSymbols(this, MochiKit.Text);
diff --git a/frontend/gamma/js/MochiKit/Visual.js b/frontend/gamma/js/MochiKit/Visual.js
new file mode 100644
index 0000000..648d82a
--- a/dev/null
+++ b/frontend/gamma/js/MochiKit/Visual.js
@@ -0,0 +1,1975 @@
1/***
2
3MochiKit.Visual 1.5
4
5See <http://mochikit.com/> for documentation, downloads, license, etc.
6
7(c) 2005 Bob Ippolito and others. All rights Reserved.
8
9***/
10
11MochiKit.Base._module('Visual', '1.5', ['Base', 'DOM', 'Style', 'Color', 'Position']);
12
13MochiKit.Visual._RoundCorners = function (e, options) {
14 e = MochiKit.DOM.getElement(e);
15 this._setOptions(options);
16 if (this.options.__unstable__wrapElement) {
17 e = this._doWrap(e);
18 }
19
20 var color = this.options.color;
21 var C = MochiKit.Color.Color;
22 if (this.options.color === "fromElement") {
23 color = C.fromBackground(e);
24 } else if (!(color instanceof C)) {
25 color = C.fromString(color);
26 }
27 this.isTransparent = (color.asRGB().a <= 0);
28
29 var bgColor = this.options.bgColor;
30 if (this.options.bgColor === "fromParent") {
31 bgColor = C.fromBackground(e.offsetParent);
32 } else if (!(bgColor instanceof C)) {
33 bgColor = C.fromString(bgColor);
34 }
35
36 this._roundCornersImpl(e, color, bgColor);
37};
38
39MochiKit.Visual._RoundCorners.prototype = {
40 _doWrap: function (e) {
41 var parent = e.parentNode;
42 var doc = MochiKit.DOM.currentDocument();
43 if (typeof(doc.defaultView) === "undefined"
44 || doc.defaultView === null) {
45 return e;
46 }
47 var style = doc.defaultView.getComputedStyle(e, null);
48 if (typeof(style) === "undefined" || style === null) {
49 return e;
50 }
51 var wrapper = MochiKit.DOM.DIV({"style": {
52 display: "block",
53 // convert padding to margin
54 marginTop: style.getPropertyValue("padding-top"),
55 marginRight: style.getPropertyValue("padding-right"),
56 marginBottom: style.getPropertyValue("padding-bottom"),
57 marginLeft: style.getPropertyValue("padding-left"),
58 // remove padding so the rounding looks right
59 padding: "0px"
60 /*
61 paddingRight: "0px",
62 paddingLeft: "0px"
63 */
64 }});
65 wrapper.innerHTML = e.innerHTML;
66 e.innerHTML = "";
67 e.appendChild(wrapper);
68 return e;
69 },
70
71 _roundCornersImpl: function (e, color, bgColor) {
72 if (this.options.border) {
73 this._renderBorder(e, bgColor);
74 }
75 if (this._isTopRounded()) {
76 this._roundTopCorners(e, color, bgColor);
77 }
78 if (this._isBottomRounded()) {
79 this._roundBottomCorners(e, color, bgColor);
80 }
81 },
82
83 _renderBorder: function (el, bgColor) {
84 var borderValue = "1px solid " + this._borderColor(bgColor);
85 var borderL = "border-left: " + borderValue;
86 var borderR = "border-right: " + borderValue;
87 var style = "style='" + borderL + ";" + borderR + "'";
88 el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>";
89 },
90
91 _roundTopCorners: function (el, color, bgColor) {
92 var corner = this._createCorner(bgColor);
93 for (var i = 0; i < this.options.numSlices; i++) {
94 corner.appendChild(
95 this._createCornerSlice(color, bgColor, i, "top")
96 );
97 }
98 el.style.paddingTop = 0;
99 el.insertBefore(corner, el.firstChild);
100 },
101
102 _roundBottomCorners: function (el, color, bgColor) {
103 var corner = this._createCorner(bgColor);
104 for (var i = (this.options.numSlices - 1); i >= 0; i--) {
105 corner.appendChild(
106 this._createCornerSlice(color, bgColor, i, "bottom")
107 );
108 }
109 el.style.paddingBottom = 0;
110 el.appendChild(corner);
111 },
112
113 _createCorner: function (bgColor) {
114 var dom = MochiKit.DOM;
115 return dom.DIV({style: {backgroundColor: bgColor.toString()}});
116 },
117
118 _createCornerSlice: function (color, bgColor, n, position) {
119 var slice = MochiKit.DOM.SPAN();
120
121 var inStyle = slice.style;
122 inStyle.backgroundColor = color.toString();
123 inStyle.display = "block";
124 inStyle.height = "1px";
125 inStyle.overflow = "hidden";
126 inStyle.fontSize = "1px";
127
128 var borderColor = this._borderColor(color, bgColor);
129 if (this.options.border && n === 0) {
130 inStyle.borderTopStyle = "solid";
131 inStyle.borderTopWidth = "1px";
132 inStyle.borderLeftWidth = "0px";
133 inStyle.borderRightWidth = "0px";
134 inStyle.borderBottomWidth = "0px";
135 // assumes css compliant box model
136 inStyle.height = "0px";
137 inStyle.borderColor = borderColor.toString();
138 } else if (borderColor) {
139 inStyle.borderColor = borderColor.toString();
140 inStyle.borderStyle = "solid";
141 inStyle.borderWidth = "0px 1px";
142 }
143
144 if (!this.options.compact && (n == (this.options.numSlices - 1))) {
145 inStyle.height = "2px";
146 }
147
148 this._setMargin(slice, n, position);
149 this._setBorder(slice, n, position);
150
151 return slice;
152 },
153
154 _setOptions: function (options) {
155 this.options = {
156 corners: "all",
157 color: "fromElement",
158 bgColor: "fromParent",
159 blend: true,
160 border: false,
161 compact: false,
162 __unstable__wrapElement: false
163 };
164 MochiKit.Base.update(this.options, options);
165
166 this.options.numSlices = (this.options.compact ? 2 : 4);
167 },
168
169 _whichSideTop: function () {
170 var corners = this.options.corners;
171 if (this._hasString(corners, "all", "top")) {
172 return "";
173 }
174
175 var has_tl = (corners.indexOf("tl") != -1);
176 var has_tr = (corners.indexOf("tr") != -1);
177 if (has_tl && has_tr) {
178 return "";
179 }
180 if (has_tl) {
181 return "left";
182 }
183 if (has_tr) {
184 return "right";
185 }
186 return "";
187 },
188
189 _whichSideBottom: function () {
190 var corners = this.options.corners;
191 if (this._hasString(corners, "all", "bottom")) {
192 return "";
193 }
194
195 var has_bl = (corners.indexOf('bl') != -1);
196 var has_br = (corners.indexOf('br') != -1);
197 if (has_bl && has_br) {
198 return "";
199 }
200 if (has_bl) {
201 return "left";
202 }
203 if (has_br) {
204 return "right";
205 }
206 return "";
207 },
208
209 _borderColor: function (color, bgColor) {
210 if (color == "transparent") {
211 return bgColor;
212 } else if (this.options.border) {
213 return this.options.border;
214 } else if (this.options.blend) {
215 return bgColor.blendedColor(color);
216 }
217 return "";
218 },
219
220
221 _setMargin: function (el, n, corners) {
222 var marginSize = this._marginSize(n) + "px";
223 var whichSide = (
224 corners == "top" ? this._whichSideTop() : this._whichSideBottom()
225 );
226 var style = el.style;
227
228 if (whichSide == "left") {
229 style.marginLeft = marginSize;
230 style.marginRight = "0px";
231 } else if (whichSide == "right") {
232 style.marginRight = marginSize;
233 style.marginLeft = "0px";
234 } else {
235 style.marginLeft = marginSize;
236 style.marginRight = marginSize;
237 }
238 },
239
240 _setBorder: function (el, n, corners) {
241 var borderSize = this._borderSize(n) + "px";
242 var whichSide = (
243 corners == "top" ? this._whichSideTop() : this._whichSideBottom()
244 );
245
246 var style = el.style;
247 if (whichSide == "left") {
248 style.borderLeftWidth = borderSize;
249 style.borderRightWidth = "0px";
250 } else if (whichSide == "right") {
251 style.borderRightWidth = borderSize;
252 style.borderLeftWidth = "0px";
253 } else {
254 style.borderLeftWidth = borderSize;
255 style.borderRightWidth = borderSize;
256 }
257 },
258
259 _marginSize: function (n) {
260 if (this.isTransparent) {
261 return 0;
262 }
263
264 var o = this.options;
265 if (o.compact && o.blend) {
266 var smBlendedMarginSizes = [1, 0];
267 return smBlendedMarginSizes[n];
268 } else if (o.compact) {
269 var compactMarginSizes = [2, 1];
270 return compactMarginSizes[n];
271 } else if (o.blend) {
272 var blendedMarginSizes = [3, 2, 1, 0];
273 return blendedMarginSizes[n];
274 } else {
275 var marginSizes = [5, 3, 2, 1];
276 return marginSizes[n];
277 }
278 },
279
280 _borderSize: function (n) {
281 var o = this.options;
282 var borderSizes;
283 if (o.compact && (o.blend || this.isTransparent)) {
284 return 1;
285 } else if (o.compact) {
286 borderSizes = [1, 0];
287 } else if (o.blend) {
288 borderSizes = [2, 1, 1, 1];
289 } else if (o.border) {
290 borderSizes = [0, 2, 0, 0];
291 } else if (this.isTransparent) {
292 borderSizes = [5, 3, 2, 1];
293 } else {
294 return 0;
295 }
296 return borderSizes[n];
297 },
298
299 _hasString: function (str) {
300 for (var i = 1; i< arguments.length; i++) {
301 if (str.indexOf(arguments[i]) != -1) {
302 return true;
303 }
304 }
305 return false;
306 },
307
308 _isTopRounded: function () {
309 return this._hasString(this.options.corners,
310 "all", "top", "tl", "tr"
311 );
312 },
313
314 _isBottomRounded: function () {
315 return this._hasString(this.options.corners,
316 "all", "bottom", "bl", "br"
317 );
318 },
319
320 _hasSingleTextChild: function (el) {
321 return (el.childNodes.length == 1 && el.childNodes[0].nodeType == 3);
322 }
323};
324
325/** @id MochiKit.Visual.roundElement */
326MochiKit.Visual.roundElement = function (e, options) {
327 new MochiKit.Visual._RoundCorners(e, options);
328};
329
330/** @id MochiKit.Visual.roundClass */
331MochiKit.Visual.roundClass = function (tagName, className, options) {
332 var elements = MochiKit.DOM.getElementsByTagAndClassName(
333 tagName, className
334 );
335 for (var i = 0; i < elements.length; i++) {
336 MochiKit.Visual.roundElement(elements[i], options);
337 }
338};
339
340/** @id MochiKit.Visual.tagifyText */
341MochiKit.Visual.tagifyText = function (element, /* optional */tagifyStyle) {
342 /***
343
344 Change a node text to character in tags.
345
346 @param tagifyStyle: the style to apply to character nodes, default to
347 'position: relative'.
348
349 ***/
350 tagifyStyle = tagifyStyle || 'position:relative';
351 if (/MSIE/.test(navigator.userAgent)) {
352 tagifyStyle += ';zoom:1';
353 }
354 element = MochiKit.DOM.getElement(element);
355 var ma = MochiKit.Base.map;
356 ma(function (child) {
357 if (child.nodeType == 3) {
358 ma(function (character) {
359 element.insertBefore(
360 MochiKit.DOM.SPAN({style: tagifyStyle},
361 character == ' ' ? String.fromCharCode(160) : character), child);
362 }, child.nodeValue.split(''));
363 MochiKit.DOM.removeElement(child);
364 }
365 }, element.childNodes);
366};
367
368MochiKit.Visual._forceRerendering = function (element) {
369 try {
370 element = MochiKit.DOM.getElement(element);
371 var n = document.createTextNode(' ');
372 element.appendChild(n);
373 element.removeChild(n);
374 } catch(e) {
375 }
376};
377
378/** @id MochiKit.Visual.multiple */
379MochiKit.Visual.multiple = function (elements, effect, /* optional */options) {
380 /***
381
382 Launch the same effect subsequently on given elements.
383
384 ***/
385 options = MochiKit.Base.update({
386 speed: 0.1, delay: 0.0
387 }, options);
388 var masterDelay = options.delay;
389 var index = 0;
390 MochiKit.Base.map(function (innerelement) {
391 options.delay = index * options.speed + masterDelay;
392 new effect(innerelement, options);
393 index += 1;
394 }, elements);
395};
396
397MochiKit.Visual.PAIRS = {
398 'slide': ['slideDown', 'slideUp'],
399 'blind': ['blindDown', 'blindUp'],
400 'appear': ['appear', 'fade'],
401 'size': ['grow', 'shrink']
402};
403
404/** @id MochiKit.Visual.toggle */
405MochiKit.Visual.toggle = function (element, /* optional */effect, /* optional */options) {
406 /***
407
408 Toggle an item between two state depending of its visibility, making
409 a effect between these states. Default effect is 'appear', can be
410 'slide' or 'blind'.
411
412 ***/
413 element = MochiKit.DOM.getElement(element);
414 effect = (effect || 'appear').toLowerCase();
415 options = MochiKit.Base.update({
416 queue: {position: 'end', scope: (element.id || 'global'), limit: 1}
417 }, options);
418 var v = MochiKit.Visual;
419 v[MochiKit.Style.getStyle(element, 'display') != 'none' ?
420 v.PAIRS[effect][1] : v.PAIRS[effect][0]](element, options);
421};
422
423/***
424
425Transitions: define functions calculating variations depending of a position.
426
427***/
428
429MochiKit.Visual.Transitions = { __export__: false };
430
431/** @id MochiKit.Visual.Transitions.linear */
432MochiKit.Visual.Transitions.linear = function (pos) {
433 return pos;
434};
435
436/** @id MochiKit.Visual.Transitions.sinoidal */
437MochiKit.Visual.Transitions.sinoidal = function (pos) {
438 return 0.5 - Math.cos(pos*Math.PI)/2;
439};
440
441/** @id MochiKit.Visual.Transitions.reverse */
442MochiKit.Visual.Transitions.reverse = function (pos) {
443 return 1 - pos;
444};
445
446/** @id MochiKit.Visual.Transitions.flicker */
447MochiKit.Visual.Transitions.flicker = function (pos) {
448 return 0.25 - Math.cos(pos*Math.PI)/4 + Math.random()/2;
449};
450
451/** @id MochiKit.Visual.Transitions.wobble */
452MochiKit.Visual.Transitions.wobble = function (pos) {
453 return 0.5 - Math.cos(9*pos*Math.PI)/2;
454};
455
456/** @id MochiKit.Visual.Transitions.pulse */
457MochiKit.Visual.Transitions.pulse = function (pos, pulses) {
458 if (pulses) {
459 pos *= 2 * pulses;
460 } else {
461 pos *= 10;
462 }
463 var decimals = pos - Math.floor(pos);
464 return (Math.floor(pos) % 2 == 0) ? decimals : 1 - decimals;
465};
466
467/** @id MochiKit.Visual.Transitions.parabolic */
468MochiKit.Visual.Transitions.parabolic = function (pos) {
469 return pos * pos;
470};
471
472/** @id MochiKit.Visual.Transitions.none */
473MochiKit.Visual.Transitions.none = function (pos) {
474 return 0;
475};
476
477/** @id MochiKit.Visual.Transitions.full */
478MochiKit.Visual.Transitions.full = function (pos) {
479 return 1;
480};
481
482/***
483
484Core effects
485
486***/
487
488MochiKit.Visual.ScopedQueue = function () {
489 var cls = arguments.callee;
490 if (!(this instanceof cls)) {
491 return new cls();
492 }
493 this.__init__();
494};
495MochiKit.Visual.ScopedQueue.__export__ = false;
496
497MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype, {
498 __init__: function () {
499 this.effects = [];
500 this.interval = null;
501 },
502
503 /** @id MochiKit.Visual.ScopedQueue.prototype.add */
504 add: function (effect) {
505 var timestamp = new Date().getTime();
506
507 var position = (typeof(effect.options.queue) == 'string') ?
508 effect.options.queue : effect.options.queue.position;
509
510 var ma = MochiKit.Base.map;
511 switch (position) {
512 case 'front':
513 // move unstarted effects after this effect
514 ma(function (e) {
515 if (e.state == 'idle') {
516 e.startOn += effect.finishOn;
517 e.finishOn += effect.finishOn;
518 }
519 }, this.effects);
520 break;
521 case 'end':
522 var finish;
523 // start effect after last queued effect has finished
524 ma(function (e) {
525 var i = e.finishOn;
526 if (i >= (finish || i)) {
527 finish = i;
528 }
529 }, this.effects);
530 timestamp = finish || timestamp;
531 break;
532 case 'break':
533 ma(function (e) {
534 e.finalize();
535 }, this.effects);
536 break;
537 }
538
539 effect.startOn += timestamp;
540 effect.finishOn += timestamp;
541 if (!effect.options.queue.limit ||
542 this.effects.length < effect.options.queue.limit) {
543 this.effects.push(effect);
544 }
545
546 if (!this.interval) {
547 this.interval = this.startLoop(MochiKit.Base.bind(this.loop, this),
548 40);
549 }
550 },
551
552 /** @id MochiKit.Visual.ScopedQueue.prototype.startLoop */
553 startLoop: function (func, interval) {
554 return setInterval(func, interval);
555 },
556
557 /** @id MochiKit.Visual.ScopedQueue.prototype.remove */
558 remove: function (effect) {
559 this.effects = MochiKit.Base.filter(function (e) {
560 return e != effect;
561 }, this.effects);
562 if (!this.effects.length) {
563 this.stopLoop(this.interval);
564 this.interval = null;
565 }
566 },
567
568 /** @id MochiKit.Visual.ScopedQueue.prototype.stopLoop */
569 stopLoop: function (interval) {
570 clearInterval(interval);
571 },
572
573 /** @id MochiKit.Visual.ScopedQueue.prototype.loop */
574 loop: function () {
575 var timePos = new Date().getTime();
576 MochiKit.Base.map(function (effect) {
577 effect.loop(timePos);
578 }, this.effects);
579 }
580});
581
582MochiKit.Visual.Queues = {
583 __export__: false,
584 instances: {},
585 get: function (queueName) {
586 if (typeof(queueName) != 'string') {
587 return queueName;
588 }
589
590 if (!this.instances[queueName]) {
591 this.instances[queueName] = new MochiKit.Visual.ScopedQueue();
592 }
593 return this.instances[queueName];
594 }
595};
596
597MochiKit.Visual.Queue = MochiKit.Visual.Queues.get('global');
598MochiKit.Visual.Queue.__export__ = false;
599
600MochiKit.Visual.DefaultOptions = {
601 __export__: false,
602 transition: MochiKit.Visual.Transitions.sinoidal,
603 duration: 1.0, // seconds
604 fps: 25.0, // max. 25fps due to MochiKit.Visual.Queue implementation
605 sync: false, // true for combining
606 from: 0.0,
607 to: 1.0,
608 delay: 0.0,
609 queue: 'parallel'
610};
611
612MochiKit.Visual.Base = function () {};
613
614MochiKit.Visual.Base.prototype = {
615 /***
616
617 Basic class for all Effects. Define a looping mechanism called for each step
618 of an effect. Don't instantiate it, only subclass it.
619
620 ***/
621
622 __class__ : MochiKit.Visual.Base,
623
624 /** @id MochiKit.Visual.Base.prototype.start */
625 start: function (options) {
626 var v = MochiKit.Visual;
627 this.options = MochiKit.Base.setdefault(options,
628 v.DefaultOptions);
629 this.currentFrame = 0;
630 this.state = 'idle';
631 this.startOn = this.options.delay*1000;
632 this.finishOn = this.startOn + (this.options.duration*1000);
633 this.event('beforeStart');
634 if (!this.options.sync) {
635 v.Queues.get(typeof(this.options.queue) == 'string' ?
636 'global' : this.options.queue.scope).add(this);
637 }
638 },
639
640 /** @id MochiKit.Visual.Base.prototype.loop */
641 loop: function (timePos) {
642 if (timePos >= this.startOn) {
643 if (timePos >= this.finishOn) {
644 return this.finalize();
645 }
646 var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
647 var frame =
648 Math.round(pos * this.options.fps * this.options.duration);
649 if (frame > this.currentFrame) {
650 this.render(pos);
651 this.currentFrame = frame;
652 }
653 }
654 },
655
656 /** @id MochiKit.Visual.Base.prototype.render */
657 render: function (pos) {
658 if (this.state == 'idle') {
659 this.state = 'running';
660 this.event('beforeSetup');
661 this.setup();
662 this.event('afterSetup');
663 }
664 if (this.state == 'running') {
665 if (this.options.transition) {
666 pos = this.options.transition(pos);
667 }
668 pos *= (this.options.to - this.options.from);
669 pos += this.options.from;
670 this.event('beforeUpdate');
671 this.update(pos);
672 this.event('afterUpdate');
673 }
674 },
675
676 /** @id MochiKit.Visual.Base.prototype.cancel */
677 cancel: function () {
678 if (!this.options.sync) {
679 MochiKit.Visual.Queues.get(typeof(this.options.queue) == 'string' ?
680 'global' : this.options.queue.scope).remove(this);
681 }
682 this.state = 'finished';
683 },
684
685 /** @id MochiKit.Visual.Base.prototype.finalize */
686 finalize: function () {
687 this.render(1.0);
688 this.cancel();
689 this.event('beforeFinish');
690 this.finish();
691 this.event('afterFinish');
692 },
693
694 setup: function () {
695 },
696
697 finish: function () {
698 },
699
700 update: function (position) {
701 },
702
703 /** @id MochiKit.Visual.Base.prototype.event */
704 event: function (eventName) {
705 if (this.options[eventName + 'Internal']) {
706 this.options[eventName + 'Internal'](this);
707 }
708 if (this.options[eventName]) {
709 this.options[eventName](this);
710 }
711 },
712
713 /** @id MochiKit.Visual.Base.prototype.repr */
714 repr: function () {
715 return '[' + this.__class__.NAME + ', options:' +
716 MochiKit.Base.repr(this.options) + ']';
717 }
718};
719
720/** @id MochiKit.Visual.Parallel */
721MochiKit.Visual.Parallel = function (effects, options) {
722 var cls = arguments.callee;
723 if (!(this instanceof cls)) {
724 return new cls(effects, options);
725 }
726
727 this.__init__(effects, options);
728};
729
730MochiKit.Visual.Parallel.prototype = new MochiKit.Visual.Base();
731
732MochiKit.Base.update(MochiKit.Visual.Parallel.prototype, {
733 /***
734
735 Run multiple effects at the same time.
736
737 ***/
738
739 __class__ : MochiKit.Visual.Parallel,
740
741 __init__: function (effects, options) {
742 this.effects = effects || [];
743 this.start(options);
744 },
745
746 /** @id MochiKit.Visual.Parallel.prototype.update */
747 update: function (position) {
748 MochiKit.Base.map(function (effect) {
749 effect.render(position);
750 }, this.effects);
751 },
752
753 /** @id MochiKit.Visual.Parallel.prototype.finish */
754 finish: function () {
755 MochiKit.Base.map(function (effect) {
756 effect.finalize();
757 }, this.effects);
758 }
759});
760
761/** @id MochiKit.Visual.Sequence */
762MochiKit.Visual.Sequence = function (effects, options) {
763 var cls = arguments.callee;
764 if (!(this instanceof cls)) {
765 return new cls(effects, options);
766 }
767 this.__init__(effects, options);
768};
769
770MochiKit.Visual.Sequence.prototype = new MochiKit.Visual.Base();
771
772MochiKit.Base.update(MochiKit.Visual.Sequence.prototype, {
773
774 __class__ : MochiKit.Visual.Sequence,
775
776 __init__: function (effects, options) {
777 var defs = { transition: MochiKit.Visual.Transitions.linear,
778 duration: 0 };
779 this.effects = effects || [];
780 MochiKit.Base.map(function (effect) {
781 defs.duration += effect.options.duration;
782 }, this.effects);
783 MochiKit.Base.setdefault(options, defs);
784 this.start(options);
785 },
786
787 /** @id MochiKit.Visual.Sequence.prototype.update */
788 update: function (position) {
789 var time = position * this.options.duration;
790 for (var i = 0; i < this.effects.length; i++) {
791 var effect = this.effects[i];
792 if (time <= effect.options.duration) {
793 effect.render(time / effect.options.duration);
794 break;
795 } else {
796 time -= effect.options.duration;
797 }
798 }
799 },
800
801 /** @id MochiKit.Visual.Sequence.prototype.finish */
802 finish: function () {
803 MochiKit.Base.map(function (effect) {
804 effect.finalize();
805 }, this.effects);
806 }
807});
808
809/** @id MochiKit.Visual.Opacity */
810MochiKit.Visual.Opacity = function (element, options) {
811 var cls = arguments.callee;
812 if (!(this instanceof cls)) {
813 return new cls(element, options);
814 }
815 this.__init__(element, options);
816};
817
818MochiKit.Visual.Opacity.prototype = new MochiKit.Visual.Base();
819
820MochiKit.Base.update(MochiKit.Visual.Opacity.prototype, {
821 /***
822
823 Change the opacity of an element.
824
825 @param options: 'from' and 'to' change the starting and ending opacities.
826 Must be between 0.0 and 1.0. Default to current opacity and 1.0.
827
828 ***/
829
830 __class__ : MochiKit.Visual.Opacity,
831
832 __init__: function (element, /* optional */options) {
833 var b = MochiKit.Base;
834 var s = MochiKit.Style;
835 this.element = MochiKit.DOM.getElement(element);
836 // make this work on IE on elements without 'layout'
837 if (this.element.currentStyle &&
838 (!this.element.currentStyle.hasLayout)) {
839 s.setStyle(this.element, {zoom: 1});
840 }
841 options = b.update({
842 from: s.getStyle(this.element, 'opacity') || 0.0,
843 to: 1.0
844 }, options);
845 this.start(options);
846 },
847
848 /** @id MochiKit.Visual.Opacity.prototype.update */
849 update: function (position) {
850 MochiKit.Style.setStyle(this.element, {'opacity': position});
851 }
852});
853
854/** @id MochiKit.Visual.Move.prototype */
855MochiKit.Visual.Move = function (element, options) {
856 var cls = arguments.callee;
857 if (!(this instanceof cls)) {
858 return new cls(element, options);
859 }
860 this.__init__(element, options);
861};
862
863MochiKit.Visual.Move.prototype = new MochiKit.Visual.Base();
864
865MochiKit.Base.update(MochiKit.Visual.Move.prototype, {
866 /***
867
868 Move an element between its current position to a defined position
869
870 @param options: 'x' and 'y' for final positions, default to 0, 0.
871
872 ***/
873
874 __class__ : MochiKit.Visual.Move,
875
876 __init__: function (element, /* optional */options) {
877 this.element = MochiKit.DOM.getElement(element);
878 options = MochiKit.Base.update({
879 x: 0,
880 y: 0,
881 mode: 'relative'
882 }, options);
883 this.start(options);
884 },
885
886 /** @id MochiKit.Visual.Move.prototype.setup */
887 setup: function () {
888 // Bug in Opera: Opera returns the 'real' position of a static element
889 // or relative element that does not have top/left explicitly set.
890 // ==> Always set top and left for position relative elements in your
891 // stylesheets (to 0 if you do not need them)
892 MochiKit.Style.makePositioned(this.element);
893
894 var s = this.element.style;
895 var originalVisibility = s.visibility;
896 var originalDisplay = s.display;
897 if (originalDisplay == 'none') {
898 s.visibility = 'hidden';
899 s.display = '';
900 }
901
902 this.originalLeft = parseFloat(MochiKit.Style.getStyle(this.element, 'left') || '0');
903 this.originalTop = parseFloat(MochiKit.Style.getStyle(this.element, 'top') || '0');
904
905 if (this.options.mode == 'absolute') {
906 // absolute movement, so we need to calc deltaX and deltaY
907 this.options.x -= this.originalLeft;
908 this.options.y -= this.originalTop;
909 }
910 if (originalDisplay == 'none') {
911 s.visibility = originalVisibility;
912 s.display = originalDisplay;
913 }
914 },
915
916 /** @id MochiKit.Visual.Move.prototype.update */
917 update: function (position) {
918 MochiKit.Style.setStyle(this.element, {
919 left: Math.round(this.options.x * position + this.originalLeft) + 'px',
920 top: Math.round(this.options.y * position + this.originalTop) + 'px'
921 });
922 }
923});
924
925/** @id MochiKit.Visual.Scale */
926MochiKit.Visual.Scale = function (element, percent, options) {
927 var cls = arguments.callee;
928 if (!(this instanceof cls)) {
929 return new cls(element, percent, options);
930 }
931 this.__init__(element, percent, options);
932};
933
934MochiKit.Visual.Scale.prototype = new MochiKit.Visual.Base();
935
936MochiKit.Base.update(MochiKit.Visual.Scale.prototype, {
937 /***
938
939 Change the size of an element.
940
941 @param percent: final_size = percent*original_size
942
943 @param options: several options changing scale behaviour
944
945 ***/
946
947 __class__ : MochiKit.Visual.Scale,
948
949 __init__: function (element, percent, /* optional */options) {
950 this.element = MochiKit.DOM.getElement(element);
951 options = MochiKit.Base.update({
952 scaleX: true,
953 scaleY: true,
954 scaleContent: true,
955 scaleFromCenter: false,
956 scaleMode: 'box', // 'box' or 'contents' or {} with provided values
957 scaleFrom: 100.0,
958 scaleTo: percent
959 }, options);
960 this.start(options);
961 },
962
963 /** @id MochiKit.Visual.Scale.prototype.setup */
964 setup: function () {
965 this.restoreAfterFinish = this.options.restoreAfterFinish || false;
966 this.elementPositioning = MochiKit.Style.getStyle(this.element,
967 'position');
968
969 var ma = MochiKit.Base.map;
970 var b = MochiKit.Base.bind;
971 this.originalStyle = {};
972 ma(b(function (k) {
973 this.originalStyle[k] = this.element.style[k];
974 }, this), ['top', 'left', 'width', 'height', 'fontSize']);
975
976 this.originalTop = this.element.offsetTop;
977 this.originalLeft = this.element.offsetLeft;
978
979 var fontSize = MochiKit.Style.getStyle(this.element,
980 'font-size') || '100%';
981 ma(b(function (fontSizeType) {
982 if (fontSize.indexOf(fontSizeType) > 0) {
983 this.fontSize = parseFloat(fontSize);
984 this.fontSizeType = fontSizeType;
985 }
986 }, this), ['em', 'px', '%']);
987
988 this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
989
990 if (/^content/.test(this.options.scaleMode)) {
991 this.dims = [this.element.scrollHeight, this.element.scrollWidth];
992 } else if (this.options.scaleMode == 'box') {
993 this.dims = [this.element.offsetHeight, this.element.offsetWidth];
994 } else {
995 this.dims = [this.options.scaleMode.originalHeight,
996 this.options.scaleMode.originalWidth];
997 }
998 },
999
1000 /** @id MochiKit.Visual.Scale.prototype.update */
1001 update: function (position) {
1002 var currentScale = (this.options.scaleFrom/100.0) +
1003 (this.factor * position);
1004 if (this.options.scaleContent && this.fontSize) {
1005 MochiKit.Style.setStyle(this.element, {
1006 fontSize: this.fontSize * currentScale + this.fontSizeType
1007 });
1008 }
1009 this.setDimensions(this.dims[0] * currentScale,
1010 this.dims[1] * currentScale);
1011 },
1012
1013 /** @id MochiKit.Visual.Scale.prototype.finish */
1014 finish: function () {
1015 if (this.restoreAfterFinish) {
1016 MochiKit.Style.setStyle(this.element, this.originalStyle);
1017 }
1018 },
1019
1020 /** @id MochiKit.Visual.Scale.prototype.setDimensions */
1021 setDimensions: function (height, width) {
1022 var d = {};
1023 var r = Math.round;
1024 if (/MSIE/.test(navigator.userAgent)) {
1025 r = Math.ceil;
1026 }
1027 if (this.options.scaleX) {
1028 d.width = r(width) + 'px';
1029 }
1030 if (this.options.scaleY) {
1031 d.height = r(height) + 'px';
1032 }
1033 if (this.options.scaleFromCenter) {
1034 var topd = (height - this.dims[0])/2;
1035 var leftd = (width - this.dims[1])/2;
1036 if (this.elementPositioning == 'absolute') {
1037 if (this.options.scaleY) {
1038 d.top = this.originalTop - topd + 'px';
1039 }
1040 if (this.options.scaleX) {
1041 d.left = this.originalLeft - leftd + 'px';
1042 }
1043 } else {
1044 if (this.options.scaleY) {
1045 d.top = -topd + 'px';
1046 }
1047 if (this.options.scaleX) {
1048 d.left = -leftd + 'px';
1049 }
1050 }
1051 }
1052 MochiKit.Style.setStyle(this.element, d);
1053 }
1054});
1055
1056/** @id MochiKit.Visual.Highlight */
1057MochiKit.Visual.Highlight = function (element, options) {
1058 var cls = arguments.callee;
1059 if (!(this instanceof cls)) {
1060 return new cls(element, options);
1061 }
1062 this.__init__(element, options);
1063};
1064
1065MochiKit.Visual.Highlight.prototype = new MochiKit.Visual.Base();
1066
1067MochiKit.Base.update(MochiKit.Visual.Highlight.prototype, {
1068 /***
1069
1070 Highlight an item of the page.
1071
1072 @param options: 'startcolor' for choosing highlighting color, default
1073 to '#ffff99'.
1074
1075 ***/
1076
1077 __class__ : MochiKit.Visual.Highlight,
1078
1079 __init__: function (element, /* optional */options) {
1080 this.element = MochiKit.DOM.getElement(element);
1081 options = MochiKit.Base.update({
1082 startcolor: '#ffff99'
1083 }, options);
1084 this.start(options);
1085 },
1086
1087 /** @id MochiKit.Visual.Highlight.prototype.setup */
1088 setup: function () {
1089 var b = MochiKit.Base;
1090 var s = MochiKit.Style;
1091 // Prevent executing on elements not in the layout flow
1092 if (s.getStyle(this.element, 'display') == 'none') {
1093 this.cancel();
1094 return;
1095 }
1096 // Disable background image during the effect
1097 this.oldStyle = {
1098 backgroundImage: s.getStyle(this.element, 'background-image')
1099 };
1100 s.setStyle(this.element, {
1101 backgroundImage: 'none'
1102 });
1103
1104 if (!this.options.endcolor) {
1105 this.options.endcolor =
1106 MochiKit.Color.Color.fromBackground(this.element).toHexString();
1107 }
1108 if (b.isUndefinedOrNull(this.options.restorecolor)) {
1109 this.options.restorecolor = s.getStyle(this.element,
1110 'background-color');
1111 }
1112 // init color calculations
1113 this._base = b.map(b.bind(function (i) {
1114 return parseInt(
1115 this.options.startcolor.slice(i*2 + 1, i*2 + 3), 16);
1116 }, this), [0, 1, 2]);
1117 this._delta = b.map(b.bind(function (i) {
1118 return parseInt(this.options.endcolor.slice(i*2 + 1, i*2 + 3), 16)
1119 - this._base[i];
1120 }, this), [0, 1, 2]);
1121 },
1122
1123 /** @id MochiKit.Visual.Highlight.prototype.update */
1124 update: function (position) {
1125 var m = '#';
1126 MochiKit.Base.map(MochiKit.Base.bind(function (i) {
1127 m += MochiKit.Color.toColorPart(Math.round(this._base[i] +
1128 this._delta[i]*position));
1129 }, this), [0, 1, 2]);
1130 MochiKit.Style.setStyle(this.element, {
1131 backgroundColor: m
1132 });
1133 },
1134
1135 /** @id MochiKit.Visual.Highlight.prototype.finish */
1136 finish: function () {
1137 MochiKit.Style.setStyle(this.element,
1138 MochiKit.Base.update(this.oldStyle, {
1139 backgroundColor: this.options.restorecolor
1140 }));
1141 }
1142});
1143
1144/** @id MochiKit.Visual.ScrollTo */
1145MochiKit.Visual.ScrollTo = function (element, options) {
1146 var cls = arguments.callee;
1147 if (!(this instanceof cls)) {
1148 return new cls(element, options);
1149 }
1150 this.__init__(element, options);
1151};
1152
1153MochiKit.Visual.ScrollTo.prototype = new MochiKit.Visual.Base();
1154
1155MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype, {
1156 /***
1157
1158 Scroll to an element in the page.
1159
1160 ***/
1161
1162 __class__ : MochiKit.Visual.ScrollTo,
1163
1164 __init__: function (element, /* optional */options) {
1165 this.element = MochiKit.DOM.getElement(element);
1166 this.start(options);
1167 },
1168
1169 /** @id MochiKit.Visual.ScrollTo.prototype.setup */
1170 setup: function () {
1171 var p = MochiKit.Position;
1172 p.prepare();
1173 var offsets = p.cumulativeOffset(this.element);
1174 if (this.options.offset) {
1175 offsets.y += this.options.offset;
1176 }
1177 var max;
1178 if (window.innerHeight) {
1179 max = window.innerHeight - window.height;
1180 } else if (document.documentElement &&
1181 document.documentElement.clientHeight) {
1182 max = document.documentElement.clientHeight -
1183 document.body.scrollHeight;
1184 } else if (document.body) {
1185 max = document.body.clientHeight - document.body.scrollHeight;
1186 }
1187 this.scrollStart = p.windowOffset.y;
1188 this.delta = (offsets.y > max ? max : offsets.y) - this.scrollStart;
1189 },
1190
1191 /** @id MochiKit.Visual.ScrollTo.prototype.update */
1192 update: function (position) {
1193 var p = MochiKit.Position;
1194 p.prepare();
1195 window.scrollTo(p.windowOffset.x, this.scrollStart + (position * this.delta));
1196 }
1197});
1198
1199MochiKit.Visual._CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1200
1201MochiKit.Visual.Morph = function (element, options) {
1202 var cls = arguments.callee;
1203 if (!(this instanceof cls)) {
1204 return new cls(element, options);
1205 }
1206 this.__init__(element, options);
1207};
1208
1209MochiKit.Visual.Morph.prototype = new MochiKit.Visual.Base();
1210
1211MochiKit.Base.update(MochiKit.Visual.Morph.prototype, {
1212 /***
1213
1214 Morph effect: make a transformation from current style to the given style,
1215 automatically making a transition between the two.
1216
1217 ***/
1218
1219 __class__ : MochiKit.Visual.Morph,
1220
1221 __init__: function (element, /* optional */options) {
1222 this.element = MochiKit.DOM.getElement(element);
1223 this.start(options);
1224 },
1225
1226 /** @id MochiKit.Visual.Morph.prototype.setup */
1227 setup: function () {
1228 var b = MochiKit.Base;
1229 var style = this.options.style;
1230 this.styleStart = {};
1231 this.styleEnd = {};
1232 this.units = {};
1233 var value, unit;
1234 for (var s in style) {
1235 value = style[s];
1236 s = b.camelize(s);
1237 if (MochiKit.Visual._CSS_LENGTH.test(value)) {
1238 var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
1239 value = parseFloat(components[1]);
1240 unit = (components.length == 3) ? components[2] : null;
1241 this.styleEnd[s] = value;
1242 this.units[s] = unit;
1243 value = MochiKit.Style.getStyle(this.element, s);
1244 components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
1245 value = parseFloat(components[1]);
1246 this.styleStart[s] = value;
1247 } else if (/[Cc]olor$/.test(s)) {
1248 var c = MochiKit.Color.Color;
1249 value = c.fromString(value);
1250 if (value) {
1251 this.units[s] = "color";
1252 this.styleEnd[s] = value.toHexString();
1253 value = MochiKit.Style.getStyle(this.element, s);
1254 this.styleStart[s] = c.fromString(value).toHexString();
1255
1256 this.styleStart[s] = b.map(b.bind(function (i) {
1257 return parseInt(
1258 this.styleStart[s].slice(i*2 + 1, i*2 + 3), 16);
1259 }, this), [0, 1, 2]);
1260 this.styleEnd[s] = b.map(b.bind(function (i) {
1261 return parseInt(
1262 this.styleEnd[s].slice(i*2 + 1, i*2 + 3), 16);
1263 }, this), [0, 1, 2]);
1264 }
1265 } else {
1266 // For non-length & non-color properties, we just set the value
1267 this.element.style[s] = value;
1268 }
1269 }
1270 },
1271
1272 /** @id MochiKit.Visual.Morph.prototype.update */
1273 update: function (position) {
1274 var value;
1275 for (var s in this.styleStart) {
1276 if (this.units[s] == "color") {
1277 var m = '#';
1278 var start = this.styleStart[s];
1279 var end = this.styleEnd[s];
1280 MochiKit.Base.map(MochiKit.Base.bind(function (i) {
1281 m += MochiKit.Color.toColorPart(Math.round(start[i] +
1282 (end[i] - start[i])*position));
1283 }, this), [0, 1, 2]);
1284 this.element.style[s] = m;
1285 } else {
1286 value = this.styleStart[s] + Math.round((this.styleEnd[s] - this.styleStart[s]) * position * 1000) / 1000 + this.units[s];
1287 this.element.style[s] = value;
1288 }
1289 }
1290 }
1291});
1292
1293/***
1294
1295Combination effects.
1296
1297***/
1298
1299/** @id MochiKit.Visual.fade */
1300MochiKit.Visual.fade = function (element, /* optional */ options) {
1301 /***
1302
1303 Fade a given element: change its opacity and hide it in the end.
1304
1305 @param options: 'to' and 'from' to change opacity.
1306
1307 ***/
1308 var s = MochiKit.Style;
1309 var oldOpacity = s.getStyle(element, 'opacity');
1310 options = MochiKit.Base.update({
1311 from: s.getStyle(element, 'opacity') || 1.0,
1312 to: 0.0,
1313 afterFinishInternal: function (effect) {
1314 if (effect.options.to !== 0) {
1315 return;
1316 }
1317 s.hideElement(effect.element);
1318 s.setStyle(effect.element, {'opacity': oldOpacity});
1319 }
1320 }, options);
1321 return new MochiKit.Visual.Opacity(element, options);
1322};
1323
1324/** @id MochiKit.Visual.appear */
1325MochiKit.Visual.appear = function (element, /* optional */ options) {
1326 /***
1327
1328 Make an element appear.
1329
1330 @param options: 'to' and 'from' to change opacity.
1331
1332 ***/
1333 var s = MochiKit.Style;
1334 var v = MochiKit.Visual;
1335 options = MochiKit.Base.update({
1336 from: (s.getStyle(element, 'display') == 'none' ? 0.0 :
1337 s.getStyle(element, 'opacity') || 0.0),
1338 to: 1.0,
1339 // force Safari to render floated elements properly
1340 afterFinishInternal: function (effect) {
1341 v._forceRerendering(effect.element);
1342 },
1343 beforeSetupInternal: function (effect) {
1344 s.setStyle(effect.element, {'opacity': effect.options.from});
1345 s.showElement(effect.element);
1346 }
1347 }, options);
1348 return new v.Opacity(element, options);
1349};
1350
1351/** @id MochiKit.Visual.puff */
1352MochiKit.Visual.puff = function (element, /* optional */ options) {
1353 /***
1354
1355 'Puff' an element: grow it to double size, fading it and make it hidden.
1356
1357 ***/
1358 var s = MochiKit.Style;
1359 var v = MochiKit.Visual;
1360 element = MochiKit.DOM.getElement(element);
1361 var elementDimensions = MochiKit.Style.getElementDimensions(element, true);
1362 var oldStyle = {
1363 position: s.getStyle(element, 'position'),
1364 top: element.style.top,
1365 left: element.style.left,
1366 width: element.style.width,
1367 height: element.style.height,
1368 opacity: s.getStyle(element, 'opacity')
1369 };
1370 options = MochiKit.Base.update({
1371 beforeSetupInternal: function (effect) {
1372 MochiKit.Position.absolutize(effect.effects[0].element);
1373 },
1374 afterFinishInternal: function (effect) {
1375 s.hideElement(effect.effects[0].element);
1376 s.setStyle(effect.effects[0].element, oldStyle);
1377 },
1378 scaleContent: true,
1379 scaleFromCenter: true
1380 }, options);
1381 return new v.Parallel(
1382 [new v.Scale(element, 200,
1383 {sync: true, scaleFromCenter: options.scaleFromCenter,
1384 scaleMode: {originalHeight: elementDimensions.h,
1385 originalWidth: elementDimensions.w},
1386 scaleContent: options.scaleContent, restoreAfterFinish: true}),
1387 new v.Opacity(element, {sync: true, to: 0.0 })],
1388 options);
1389};
1390
1391/** @id MochiKit.Visual.blindUp */
1392MochiKit.Visual.blindUp = function (element, /* optional */ options) {
1393 /***
1394
1395 Blind an element up: change its vertical size to 0.
1396
1397 ***/
1398 var d = MochiKit.DOM;
1399 var s = MochiKit.Style;
1400 element = d.getElement(element);
1401 var elementDimensions = s.getElementDimensions(element, true);
1402 var elemClip = s.makeClipping(element);
1403 options = MochiKit.Base.update({
1404 scaleContent: false,
1405 scaleX: false,
1406 scaleMode: {originalHeight: elementDimensions.h,
1407 originalWidth: elementDimensions.w},
1408 restoreAfterFinish: true,
1409 afterFinishInternal: function (effect) {
1410 s.hideElement(effect.element);
1411 s.undoClipping(effect.element, elemClip);
1412 }
1413 }, options);
1414 return new MochiKit.Visual.Scale(element, 0, options);
1415};
1416
1417/** @id MochiKit.Visual.blindDown */
1418MochiKit.Visual.blindDown = function (element, /* optional */ options) {
1419 /***
1420
1421 Blind an element down: restore its vertical size.
1422
1423 ***/
1424 var d = MochiKit.DOM;
1425 var s = MochiKit.Style;
1426 element = d.getElement(element);
1427 var elementDimensions = s.getElementDimensions(element, true);
1428 var elemClip;
1429 options = MochiKit.Base.update({
1430 scaleContent: false,
1431 scaleX: false,
1432 scaleFrom: 0,
1433 scaleMode: {originalHeight: elementDimensions.h,
1434 originalWidth: elementDimensions.w},
1435 restoreAfterFinish: true,
1436 afterSetupInternal: function (effect) {
1437 elemClip = s.makeClipping(effect.element);
1438 s.setStyle(effect.element, {height: '0px'});
1439 s.showElement(effect.element);
1440 },
1441 afterFinishInternal: function (effect) {
1442 s.undoClipping(effect.element, elemClip);
1443 }
1444 }, options);
1445 return new MochiKit.Visual.Scale(element, 100, options);
1446};
1447
1448/** @id MochiKit.Visual.switchOff */
1449MochiKit.Visual.switchOff = function (element, /* optional */ options) {
1450 /***
1451
1452 Apply a switch-off-like effect.
1453
1454 ***/
1455 var d = MochiKit.DOM;
1456 var s = MochiKit.Style;
1457 element = d.getElement(element);
1458 var elementDimensions = s.getElementDimensions(element, true);
1459 var oldOpacity = s.getStyle(element, 'opacity');
1460 var elemClip;
1461 options = MochiKit.Base.update({
1462 duration: 0.7,
1463 restoreAfterFinish: true,
1464 beforeSetupInternal: function (effect) {
1465 s.makePositioned(element);
1466 elemClip = s.makeClipping(element);
1467 },
1468 afterFinishInternal: function (effect) {
1469 s.hideElement(element);
1470 s.undoClipping(element, elemClip);
1471 s.undoPositioned(element);
1472 s.setStyle(element, {'opacity': oldOpacity});
1473 }
1474 }, options);
1475 var v = MochiKit.Visual;
1476 return new v.Sequence(
1477 [new v.appear(element,
1478 { sync: true, duration: 0.57 * options.duration,
1479 from: 0, transition: v.Transitions.flicker }),
1480 new v.Scale(element, 1,
1481 { sync: true, duration: 0.43 * options.duration,
1482 scaleFromCenter: true, scaleX: false,
1483 scaleMode: {originalHeight: elementDimensions.h,
1484 originalWidth: elementDimensions.w},
1485 scaleContent: false, restoreAfterFinish: true })],
1486 options);
1487};
1488
1489/** @id MochiKit.Visual.dropOut */
1490MochiKit.Visual.dropOut = function (element, /* optional */ options) {
1491 /***
1492
1493 Make an element fall and disappear.
1494
1495 ***/
1496 var d = MochiKit.DOM;
1497 var s = MochiKit.Style;
1498 element = d.getElement(element);
1499 var oldStyle = {
1500 top: s.getStyle(element, 'top'),
1501 left: s.getStyle(element, 'left'),
1502 opacity: s.getStyle(element, 'opacity')
1503 };
1504
1505 options = MochiKit.Base.update({
1506 duration: 0.5,
1507 distance: 100,
1508 beforeSetupInternal: function (effect) {
1509 s.makePositioned(effect.effects[0].element);
1510 },
1511 afterFinishInternal: function (effect) {
1512 s.hideElement(effect.effects[0].element);
1513 s.undoPositioned(effect.effects[0].element);
1514 s.setStyle(effect.effects[0].element, oldStyle);
1515 }
1516 }, options);
1517 var v = MochiKit.Visual;
1518 return new v.Parallel(
1519 [new v.Move(element, {x: 0, y: options.distance, sync: true}),
1520 new v.Opacity(element, {sync: true, to: 0.0})],
1521 options);
1522};
1523
1524/** @id MochiKit.Visual.shake */
1525MochiKit.Visual.shake = function (element, /* optional */ options) {
1526 /***
1527
1528 Move an element from left to right several times.
1529
1530 ***/
1531 var d = MochiKit.DOM;
1532 var v = MochiKit.Visual;
1533 var s = MochiKit.Style;
1534 element = d.getElement(element);
1535 var oldStyle = {
1536 top: s.getStyle(element, 'top'),
1537 left: s.getStyle(element, 'left')
1538 };
1539 options = MochiKit.Base.update({
1540 duration: 0.5,
1541 afterFinishInternal: function (effect) {
1542 s.undoPositioned(element);
1543 s.setStyle(element, oldStyle);
1544 }
1545 }, options);
1546 return new v.Sequence(
1547 [new v.Move(element, { sync: true, duration: 0.1 * options.duration,
1548 x: 20, y: 0 }),
1549 new v.Move(element, { sync: true, duration: 0.2 * options.duration,
1550 x: -40, y: 0 }),
1551 new v.Move(element, { sync: true, duration: 0.2 * options.duration,
1552 x: 40, y: 0 }),
1553 new v.Move(element, { sync: true, duration: 0.2 * options.duration,
1554 x: -40, y: 0 }),
1555 new v.Move(element, { sync: true, duration: 0.2 * options.duration,
1556 x: 40, y: 0 }),
1557 new v.Move(element, { sync: true, duration: 0.1 * options.duration,
1558 x: -20, y: 0 })],
1559 options);
1560};
1561
1562/** @id MochiKit.Visual.slideDown */
1563MochiKit.Visual.slideDown = function (element, /* optional */ options) {
1564 /***
1565
1566 Slide an element down.
1567 It needs to have the content of the element wrapped in a container
1568 element with fixed height.
1569
1570 ***/
1571 var d = MochiKit.DOM;
1572 var b = MochiKit.Base;
1573 var s = MochiKit.Style;
1574 element = d.getElement(element);
1575 if (!element.firstChild) {
1576 throw new Error("MochiKit.Visual.slideDown must be used on a element with a child");
1577 }
1578 d.removeEmptyTextNodes(element);
1579 var oldInnerBottom = s.getStyle(element.firstChild, 'bottom') || 0;
1580 var elementDimensions = s.getElementDimensions(element, true);
1581 var elemClip;
1582 options = b.update({
1583 scaleContent: false,
1584 scaleX: false,
1585 scaleFrom: 0,
1586 scaleMode: {originalHeight: elementDimensions.h,
1587 originalWidth: elementDimensions.w},
1588 restoreAfterFinish: true,
1589 afterSetupInternal: function (effect) {
1590 s.makePositioned(effect.element);
1591 s.makePositioned(effect.element.firstChild);
1592 if (/Opera/.test(navigator.userAgent)) {
1593 s.setStyle(effect.element, {top: ''});
1594 }
1595 elemClip = s.makeClipping(effect.element);
1596 s.setStyle(effect.element, {height: '0px'});
1597 s.showElement(effect.element);
1598 },
1599 afterUpdateInternal: function (effect) {
1600 var elementDimensions = s.getElementDimensions(effect.element, true);
1601 s.setStyle(effect.element.firstChild,
1602 {bottom: (effect.dims[0] - elementDimensions.h) + 'px'});
1603 },
1604 afterFinishInternal: function (effect) {
1605 s.undoClipping(effect.element, elemClip);
1606 // IE will crash if child is undoPositioned first
1607 if (/MSIE/.test(navigator.userAgent)) {
1608 s.undoPositioned(effect.element);
1609 s.undoPositioned(effect.element.firstChild);
1610 } else {
1611 s.undoPositioned(effect.element.firstChild);
1612 s.undoPositioned(effect.element);
1613 }
1614 s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom});
1615 }
1616 }, options);
1617
1618 return new MochiKit.Visual.Scale(element, 100, options);
1619};
1620
1621/** @id MochiKit.Visual.slideUp */
1622MochiKit.Visual.slideUp = function (element, /* optional */ options) {
1623 /***
1624
1625 Slide an element up.
1626 It needs to have the content of the element wrapped in a container
1627 element with fixed height.
1628
1629 ***/
1630 var d = MochiKit.DOM;
1631 var b = MochiKit.Base;
1632 var s = MochiKit.Style;
1633 element = d.getElement(element);
1634 if (!element.firstChild) {
1635 throw new Error("MochiKit.Visual.slideUp must be used on a element with a child");
1636 }
1637 d.removeEmptyTextNodes(element);
1638 var oldInnerBottom = s.getStyle(element.firstChild, 'bottom');
1639 var elementDimensions = s.getElementDimensions(element, true);
1640 var elemClip;
1641 options = b.update({
1642 scaleContent: false,
1643 scaleX: false,
1644 scaleMode: {originalHeight: elementDimensions.h,
1645 originalWidth: elementDimensions.w},
1646 scaleFrom: 100,
1647 restoreAfterFinish: true,
1648 beforeStartInternal: function (effect) {
1649 s.makePositioned(effect.element);
1650 s.makePositioned(effect.element.firstChild);
1651 if (/Opera/.test(navigator.userAgent)) {
1652 s.setStyle(effect.element, {top: ''});
1653 }
1654 elemClip = s.makeClipping(effect.element);
1655 s.showElement(effect.element);
1656 },
1657 afterUpdateInternal: function (effect) {
1658 var elementDimensions = s.getElementDimensions(effect.element, true);
1659 s.setStyle(effect.element.firstChild,
1660 {bottom: (effect.dims[0] - elementDimensions.h) + 'px'});
1661 },
1662 afterFinishInternal: function (effect) {
1663 s.hideElement(effect.element);
1664 s.undoClipping(effect.element, elemClip);
1665 s.undoPositioned(effect.element.firstChild);
1666 s.undoPositioned(effect.element);
1667 s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom});
1668 }
1669 }, options);
1670 return new MochiKit.Visual.Scale(element, 0, options);
1671};
1672
1673// Bug in opera makes the TD containing this element expand for a instance
1674// after finish
1675/** @id MochiKit.Visual.squish */
1676MochiKit.Visual.squish = function (element, /* optional */ options) {
1677 /***
1678
1679 Reduce an element and make it disappear.
1680
1681 ***/
1682 var d = MochiKit.DOM;
1683 var b = MochiKit.Base;
1684 var s = MochiKit.Style;
1685 var elementDimensions = s.getElementDimensions(element, true);
1686 var elemClip;
1687 options = b.update({
1688 restoreAfterFinish: true,
1689 scaleMode: {originalHeight: elementDimensions.w,
1690 originalWidth: elementDimensions.h},
1691 beforeSetupInternal: function (effect) {
1692 elemClip = s.makeClipping(effect.element);
1693 },
1694 afterFinishInternal: function (effect) {
1695 s.hideElement(effect.element);
1696 s.undoClipping(effect.element, elemClip);
1697 }
1698 }, options);
1699
1700 return new MochiKit.Visual.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, options);
1701};
1702
1703/** @id MochiKit.Visual.grow */
1704MochiKit.Visual.grow = function (element, /* optional */ options) {
1705 /***
1706
1707 Grow an element to its original size. Make it zero-sized before
1708 if necessary.
1709
1710 ***/
1711 var d = MochiKit.DOM;
1712 var v = MochiKit.Visual;
1713 var s = MochiKit.Style;
1714 element = d.getElement(element);
1715 options = MochiKit.Base.update({
1716 direction: 'center',
1717 moveTransition: v.Transitions.sinoidal,
1718 scaleTransition: v.Transitions.sinoidal,
1719 opacityTransition: v.Transitions.full,
1720 scaleContent: true,
1721 scaleFromCenter: false
1722 }, options);
1723 var oldStyle = {
1724 top: element.style.top,
1725 left: element.style.left,
1726 height: element.style.height,
1727 width: element.style.width,
1728 opacity: s.getStyle(element, 'opacity')
1729 };
1730 var dims = s.getElementDimensions(element, true);
1731 var initialMoveX, initialMoveY;
1732 var moveX, moveY;
1733
1734 switch (options.direction) {
1735 case 'top-left':
1736 initialMoveX = initialMoveY = moveX = moveY = 0;
1737 break;
1738 case 'top-right':
1739 initialMoveX = dims.w;
1740 initialMoveY = moveY = 0;
1741 moveX = -dims.w;
1742 break;
1743 case 'bottom-left':
1744 initialMoveX = moveX = 0;
1745 initialMoveY = dims.h;
1746 moveY = -dims.h;
1747 break;
1748 case 'bottom-right':
1749 initialMoveX = dims.w;
1750 initialMoveY = dims.h;
1751 moveX = -dims.w;
1752 moveY = -dims.h;
1753 break;
1754 case 'center':
1755 initialMoveX = dims.w / 2;
1756 initialMoveY = dims.h / 2;
1757 moveX = -dims.w / 2;
1758 moveY = -dims.h / 2;
1759 break;
1760 }
1761
1762 var optionsParallel = MochiKit.Base.update({
1763 beforeSetupInternal: function (effect) {
1764 s.setStyle(effect.effects[0].element, {height: '0px'});
1765 s.showElement(effect.effects[0].element);
1766 },
1767 afterFinishInternal: function (effect) {
1768 s.undoClipping(effect.effects[0].element);
1769 s.undoPositioned(effect.effects[0].element);
1770 s.setStyle(effect.effects[0].element, oldStyle);
1771 }
1772 }, options);
1773
1774 return new v.Move(element, {
1775 x: initialMoveX,
1776 y: initialMoveY,
1777 duration: 0.01,
1778 beforeSetupInternal: function (effect) {
1779 s.hideElement(effect.element);
1780 s.makeClipping(effect.element);
1781 s.makePositioned(effect.element);
1782 },
1783 afterFinishInternal: function (effect) {
1784 new v.Parallel(
1785 [new v.Opacity(effect.element, {
1786 sync: true, to: 1.0, from: 0.0,
1787 transition: options.opacityTransition
1788 }),
1789 new v.Move(effect.element, {
1790 x: moveX, y: moveY, sync: true,
1791 transition: options.moveTransition
1792 }),
1793 new v.Scale(effect.element, 100, {
1794 scaleMode: {originalHeight: dims.h,
1795 originalWidth: dims.w},
1796 sync: true,
1797 scaleFrom: /Opera/.test(navigator.userAgent) ? 1 : 0,
1798 transition: options.scaleTransition,
1799 scaleContent: options.scaleContent,
1800 scaleFromCenter: options.scaleFromCenter,
1801 restoreAfterFinish: true
1802 })
1803 ], optionsParallel
1804 );
1805 }
1806 });
1807};
1808
1809/** @id MochiKit.Visual.shrink */
1810MochiKit.Visual.shrink = function (element, /* optional */ options) {
1811 /***
1812
1813 Shrink an element and make it disappear.
1814
1815 ***/
1816 var d = MochiKit.DOM;
1817 var v = MochiKit.Visual;
1818 var s = MochiKit.Style;
1819 element = d.getElement(element);
1820 options = MochiKit.Base.update({
1821 direction: 'center',
1822 moveTransition: v.Transitions.sinoidal,
1823 scaleTransition: v.Transitions.sinoidal,
1824 opacityTransition: v.Transitions.none,
1825 scaleContent: true,
1826 scaleFromCenter: false
1827 }, options);
1828 var oldStyle = {
1829 top: element.style.top,
1830 left: element.style.left,
1831 height: element.style.height,
1832 width: element.style.width,
1833 opacity: s.getStyle(element, 'opacity')
1834 };
1835
1836 var dims = s.getElementDimensions(element, true);
1837 var moveX, moveY;
1838
1839 switch (options.direction) {
1840 case 'top-left':
1841 moveX = moveY = 0;
1842 break;
1843 case 'top-right':
1844 moveX = dims.w;
1845 moveY = 0;
1846 break;
1847 case 'bottom-left':
1848 moveX = 0;
1849 moveY = dims.h;
1850 break;
1851 case 'bottom-right':
1852 moveX = dims.w;
1853 moveY = dims.h;
1854 break;
1855 case 'center':
1856 moveX = dims.w / 2;
1857 moveY = dims.h / 2;
1858 break;
1859 }
1860 var elemClip;
1861
1862 var optionsParallel = MochiKit.Base.update({
1863 beforeStartInternal: function (effect) {
1864 s.makePositioned(effect.effects[0].element);
1865 elemClip = s.makeClipping(effect.effects[0].element);
1866 },
1867 afterFinishInternal: function (effect) {
1868 s.hideElement(effect.effects[0].element);
1869 s.undoClipping(effect.effects[0].element, elemClip);
1870 s.undoPositioned(effect.effects[0].element);
1871 s.setStyle(effect.effects[0].element, oldStyle);
1872 }
1873 }, options);
1874
1875 return new v.Parallel(
1876 [new v.Opacity(element, {
1877 sync: true, to: 0.0, from: 1.0,
1878 transition: options.opacityTransition
1879 }),
1880 new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
1881 scaleMode: {originalHeight: dims.h, originalWidth: dims.w},
1882 sync: true, transition: options.scaleTransition,
1883 scaleContent: options.scaleContent,
1884 scaleFromCenter: options.scaleFromCenter,
1885 restoreAfterFinish: true
1886 }),
1887 new v.Move(element, {
1888 x: moveX, y: moveY, sync: true, transition: options.moveTransition
1889 })
1890 ], optionsParallel
1891 );
1892};
1893
1894/** @id MochiKit.Visual.pulsate */
1895MochiKit.Visual.pulsate = function (element, /* optional */ options) {
1896 /***
1897
1898 Pulse an element between appear/fade.
1899
1900 ***/
1901 var d = MochiKit.DOM;
1902 var v = MochiKit.Visual;
1903 var b = MochiKit.Base;
1904 var oldOpacity = MochiKit.Style.getStyle(element, 'opacity');
1905 options = b.update({
1906 duration: 3.0,
1907 from: 0,
1908 afterFinishInternal: function (effect) {
1909 MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity});
1910 }
1911 }, options);
1912 var transition = options.transition || v.Transitions.sinoidal;
1913 options.transition = function (pos) {
1914 return transition(1 - v.Transitions.pulse(pos, options.pulses));
1915 };
1916 return new v.Opacity(element, options);
1917};
1918
1919/** @id MochiKit.Visual.fold */
1920MochiKit.Visual.fold = function (element, /* optional */ options) {
1921 /***
1922
1923 Fold an element, first vertically, then horizontally.
1924
1925 ***/
1926 var d = MochiKit.DOM;
1927 var v = MochiKit.Visual;
1928 var s = MochiKit.Style;
1929 element = d.getElement(element);
1930 var elementDimensions = s.getElementDimensions(element, true);
1931 var oldStyle = {
1932 top: element.style.top,
1933 left: element.style.left,
1934 width: element.style.width,
1935 height: element.style.height
1936 };
1937 var elemClip = s.makeClipping(element);
1938 options = MochiKit.Base.update({
1939 scaleContent: false,
1940 scaleX: false,
1941 scaleMode: {originalHeight: elementDimensions.h,
1942 originalWidth: elementDimensions.w},
1943 afterFinishInternal: function (effect) {
1944 new v.Scale(element, 1, {
1945 scaleContent: false,
1946 scaleY: false,
1947 scaleMode: {originalHeight: elementDimensions.h,
1948 originalWidth: elementDimensions.w},
1949 afterFinishInternal: function (effect) {
1950 s.hideElement(effect.element);
1951 s.undoClipping(effect.element, elemClip);
1952 s.setStyle(effect.element, oldStyle);
1953 }
1954 });
1955 }
1956 }, options);
1957 return new v.Scale(element, 5, options);
1958};
1959
1960
1961/* end of Rico adaptation */
1962
1963MochiKit.Visual.__new__ = function () {
1964 var m = MochiKit.Base;
1965
1966 // Backwards compatibility aliases
1967 m._deprecated(this, 'Color', 'MochiKit.Color.Color', '1.1');
1968 m._deprecated(this, 'getElementsComputedStyle', 'MochiKit.Style.getStyle', '1.1');
1969
1970 m.nameFunctions(this);
1971};
1972
1973MochiKit.Visual.__new__();
1974
1975MochiKit.Base._exportSymbols(this, MochiKit.Visual);
diff --git a/frontend/gamma/js/MochiKit/__package__.js b/frontend/gamma/js/MochiKit/__package__.js
new file mode 100644
index 0000000..8d644b1
--- a/dev/null
+++ b/frontend/gamma/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.*");