summaryrefslogtreecommitdiff
path: root/frontend/delta/js/MochiKit
Unidiff
Diffstat (limited to 'frontend/delta/js/MochiKit') (more/less context) (ignore whitespace changes)
-rw-r--r--frontend/delta/js/MochiKit/Async.js733
-rw-r--r--frontend/delta/js/MochiKit/Base.js1523
-rw-r--r--frontend/delta/js/MochiKit/Color.js846
-rw-r--r--frontend/delta/js/MochiKit/DOM.js1202
-rw-r--r--frontend/delta/js/MochiKit/DateTime.js199
-rw-r--r--frontend/delta/js/MochiKit/DragAndDrop.js789
-rw-r--r--frontend/delta/js/MochiKit/Format.js332
-rw-r--r--frontend/delta/js/MochiKit/Iter.js811
-rw-r--r--frontend/delta/js/MochiKit/Logging.js285
-rw-r--r--frontend/delta/js/MochiKit/LoggingPane.js353
-rw-r--r--frontend/delta/js/MochiKit/MochiKit.js156
-rw-r--r--frontend/delta/js/MochiKit/MockDOM.js135
-rw-r--r--frontend/delta/js/MochiKit/Position.js241
-rw-r--r--frontend/delta/js/MochiKit/Selector.js416
-rw-r--r--frontend/delta/js/MochiKit/Signal.js924
-rw-r--r--frontend/delta/js/MochiKit/Sortable.js592
-rw-r--r--frontend/delta/js/MochiKit/Style.js584
-rw-r--r--frontend/delta/js/MochiKit/Test.js167
-rw-r--r--frontend/delta/js/MochiKit/Text.js569
-rw-r--r--frontend/delta/js/MochiKit/Visual.js1999
20 files changed, 12856 insertions, 0 deletions
diff --git a/frontend/delta/js/MochiKit/Async.js b/frontend/delta/js/MochiKit/Async.js
new file mode 100644
index 0000000..a76aaa2
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Async.js
@@ -0,0 +1,733 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Async 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Async', '1.5', ['Base']);
35
36/** @id MochiKit.Async.Deferred */
37MochiKit.Async.Deferred = function (/* optional */ canceller) {
38 this.chain = [];
39 this.id = this._nextId();
40 this.fired = -1;
41 this.paused = 0;
42 this.results = [null, null];
43 this.canceller = canceller;
44 this.silentlyCancelled = false;
45 this.chained = false;
46 this.finalized = false;
47};
48
49MochiKit.Async.Deferred.prototype = {
50 /** @id MochiKit.Async.Deferred.prototype.repr */
51 repr: function () {
52 return 'Deferred(' + this.id + ', ' + this.state() + ')';
53 },
54
55 toString: MochiKit.Base.forwardCall("repr"),
56
57 _nextId: MochiKit.Base.counter(),
58
59 /** @id MochiKit.Async.Deferred.prototype.state */
60 state: function () {
61 if (this.fired == -1) {
62 return 'unfired';
63 } else if (this.fired === 0) {
64 return 'success';
65 } else {
66 return 'error';
67 }
68 },
69
70 /** @id MochiKit.Async.Deferred.prototype.cancel */
71 cancel: function (e) {
72 var self = MochiKit.Async;
73 if (this.fired == -1) {
74 if (this.canceller) {
75 this.canceller(this);
76 } else {
77 this.silentlyCancelled = true;
78 }
79 if (this.fired == -1) {
80 if (typeof(e) === 'string') {
81 e = new self.GenericError(e);
82 } else if (!(e instanceof Error)) {
83 e = new self.CancelledError(this);
84 }
85 this.errback(e);
86 }
87 } else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) {
88 this.results[0].cancel(e);
89 }
90 },
91
92 _resback: function (res) {
93 /***
94
95 The primitive that means either callback or errback
96
97 ***/
98 this.fired = ((res instanceof Error) ? 1 : 0);
99 this.results[this.fired] = res;
100 if (this.paused === 0) {
101 this._fire();
102 }
103 },
104
105 _check: function () {
106 if (this.fired != -1) {
107 if (!this.silentlyCancelled) {
108 throw new MochiKit.Async.AlreadyCalledError(this);
109 }
110 this.silentlyCancelled = false;
111 return;
112 }
113 },
114
115 /** @id MochiKit.Async.Deferred.prototype.callback */
116 callback: function (res) {
117 this._check();
118 if (res instanceof MochiKit.Async.Deferred) {
119 throw new Error("Deferred instances can only be chained if they are the result of a callback");
120 }
121 this._resback(res);
122 },
123
124 /** @id MochiKit.Async.Deferred.prototype.errback */
125 errback: function (res) {
126 this._check();
127 var self = MochiKit.Async;
128 if (res instanceof self.Deferred) {
129 throw new Error("Deferred instances can only be chained if they are the result of a callback");
130 }
131 if (!(res instanceof Error)) {
132 res = new self.GenericError(res);
133 }
134 this._resback(res);
135 },
136
137 /** @id MochiKit.Async.Deferred.prototype.addBoth */
138 addBoth: function (fn) {
139 if (arguments.length > 1) {
140 fn = MochiKit.Base.partial.apply(null, arguments);
141 }
142 return this.addCallbacks(fn, fn);
143 },
144
145 /** @id MochiKit.Async.Deferred.prototype.addCallback */
146 addCallback: function (fn) {
147 if (arguments.length > 1) {
148 fn = MochiKit.Base.partial.apply(null, arguments);
149 }
150 return this.addCallbacks(fn, null);
151 },
152
153 /** @id MochiKit.Async.Deferred.prototype.addErrback */
154 addErrback: function (fn) {
155 if (arguments.length > 1) {
156 fn = MochiKit.Base.partial.apply(null, arguments);
157 }
158 return this.addCallbacks(null, fn);
159 },
160
161 /** @id MochiKit.Async.Deferred.prototype.addCallbacks */
162 addCallbacks: function (cb, eb) {
163 if (this.chained) {
164 throw new Error("Chained Deferreds can not be re-used");
165 }
166 if (this.finalized) {
167 throw new Error("Finalized Deferreds can not be re-used");
168 }
169 this.chain.push([cb, eb]);
170 if (this.fired >= 0) {
171 this._fire();
172 }
173 return this;
174 },
175
176 /** @id MochiKit.Async.Deferred.prototype.setFinalizer */
177 setFinalizer: function (fn) {
178 if (this.chained) {
179 throw new Error("Chained Deferreds can not be re-used");
180 }
181 if (this.finalized) {
182 throw new Error("Finalized Deferreds can not be re-used");
183 }
184 if (arguments.length > 1) {
185 fn = MochiKit.Base.partial.apply(null, arguments);
186 }
187 this._finalizer = fn;
188 if (this.fired >= 0) {
189 this._fire();
190 }
191 return this;
192 },
193
194 _fire: function () {
195 /***
196
197 Used internally to exhaust the callback sequence when a result
198 is available.
199
200 ***/
201 var chain = this.chain;
202 var fired = this.fired;
203 var res = this.results[fired];
204 var self = this;
205 var cb = null;
206 while (chain.length > 0 && this.paused === 0) {
207 // Array
208 var pair = chain.shift();
209 var f = pair[fired];
210 if (f === null) {
211 continue;
212 }
213 try {
214 res = f(res);
215 fired = ((res instanceof Error) ? 1 : 0);
216 if (res instanceof MochiKit.Async.Deferred) {
217 cb = function (res) {
218 self.paused--;
219 self._resback(res);
220 };
221 this.paused++;
222 }
223 } catch (err) {
224 fired = 1;
225 if (!(err instanceof Error)) {
226 err = new MochiKit.Async.GenericError(err);
227 }
228 res = err;
229 }
230 }
231 this.fired = fired;
232 this.results[fired] = res;
233 if (this.chain.length == 0 && this.paused === 0 && this._finalizer) {
234 this.finalized = true;
235 this._finalizer(res);
236 }
237 if (cb && this.paused) {
238 // this is for "tail recursion" in case the dependent deferred
239 // is already fired
240 res.addBoth(cb);
241 res.chained = true;
242 }
243 }
244};
245
246MochiKit.Base.update(MochiKit.Async, {
247 /** @id MochiKit.Async.evalJSONRequest */
248 evalJSONRequest: function (req) {
249 return MochiKit.Base.evalJSON(req.responseText);
250 },
251
252 /** @id MochiKit.Async.succeed */
253 succeed: function (/* optional */result) {
254 var d = new MochiKit.Async.Deferred();
255 d.callback.apply(d, arguments);
256 return d;
257 },
258
259 /** @id MochiKit.Async.fail */
260 fail: function (/* optional */result) {
261 var d = new MochiKit.Async.Deferred();
262 d.errback.apply(d, arguments);
263 return d;
264 },
265
266 /** @id MochiKit.Async.getXMLHttpRequest */
267 getXMLHttpRequest: function () {
268 var self = arguments.callee;
269 if (!self.XMLHttpRequest) {
270 var tryThese = [
271 function () { return new XMLHttpRequest(); },
272 function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
273 function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
274 function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
275 function () {
276 throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
277 }
278 ];
279 for (var i = 0; i < tryThese.length; i++) {
280 var func = tryThese[i];
281 try {
282 self.XMLHttpRequest = func;
283 return func();
284 } catch (e) {
285 // pass
286 }
287 }
288 }
289 return self.XMLHttpRequest();
290 },
291
292 _xhr_onreadystatechange: function (d) {
293 // MochiKit.Logging.logDebug('this.readyState', this.readyState);
294 var m = MochiKit.Base;
295 if (this.readyState == 4) {
296 // IE SUCKS
297 try {
298 this.onreadystatechange = null;
299 } catch (e) {
300 try {
301 this.onreadystatechange = m.noop;
302 } catch (e) {
303 }
304 }
305 var status = null;
306 try {
307 status = this.status;
308 if (!status && (this.response || m.isNotEmpty(this.responseText))) {
309 // 0 or undefined seems to mean cached or local
310 status = 304;
311 }
312 } catch (e) {
313 // pass
314 // MochiKit.Logging.logDebug('error getting status?', repr(items(e)));
315 }
316 // 200 is OK, 201 is CREATED, 204 is NO CONTENT
317 // 304 is NOT MODIFIED, 1223 is apparently a bug in IE
318 if (status == 200 || status == 201 || status == 204 ||
319 status == 304 || status == 1223) {
320 d.callback(this);
321 } else {
322 var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed");
323 if (err.number) {
324 // XXX: This seems to happen on page change
325 d.errback(err);
326 } else {
327 // XXX: this seems to happen when the server is unreachable
328 d.errback(err);
329 }
330 }
331 }
332 },
333
334 _xhr_canceller: function (req) {
335 // IE SUCKS
336 try {
337 req.onreadystatechange = null;
338 } catch (e) {
339 try {
340 req.onreadystatechange = MochiKit.Base.noop;
341 } catch (e) {
342 }
343 }
344 req.abort();
345 },
346
347
348 /** @id MochiKit.Async.sendXMLHttpRequest */
349 sendXMLHttpRequest: function (req, /* optional */ sendContent) {
350 if (typeof(sendContent) == "undefined" || sendContent === null) {
351 sendContent = "";
352 }
353
354 var m = MochiKit.Base;
355 var self = MochiKit.Async;
356 var d = new self.Deferred(m.partial(self._xhr_canceller, req));
357
358 try {
359 req.onreadystatechange = m.bind(self._xhr_onreadystatechange,
360 req, d);
361 req.send(sendContent);
362 } catch (e) {
363 try {
364 req.onreadystatechange = null;
365 } catch (ignore) {
366 // pass
367 }
368 d.errback(e);
369 }
370
371 return d;
372
373 },
374
375 /** @id MochiKit.Async.doXHR */
376 doXHR: function (url, opts) {
377 /*
378 Work around a Firefox bug by dealing with XHR during
379 the next event loop iteration. Maybe it's this one:
380 https://bugzilla.mozilla.org/show_bug.cgi?id=249843
381 */
382 var self = MochiKit.Async;
383 return self.callLater(0, self._doXHR, url, opts);
384 },
385
386 _doXHR: function (url, opts) {
387 var m = MochiKit.Base;
388 opts = m.update({
389 method: 'GET',
390 sendContent: ''
391 /*
392 queryString: undefined,
393 username: undefined,
394 password: undefined,
395 headers: undefined,
396 mimeType: undefined,
397 responseType: undefined,
398 withCredentials: undefined
399 */
400 }, opts);
401 var self = MochiKit.Async;
402 var req = self.getXMLHttpRequest();
403 if (opts.queryString) {
404 var qs = m.queryString(opts.queryString);
405 if (qs) {
406 url += "?" + qs;
407 }
408 }
409 // Safari will send undefined:undefined, so we have to check.
410 // We can't use apply, since the function is native.
411 if ('username' in opts) {
412 req.open(opts.method, url, true, opts.username, opts.password);
413 } else {
414 req.open(opts.method, url, true);
415 }
416 if (req.overrideMimeType && opts.mimeType) {
417 req.overrideMimeType(opts.mimeType);
418 }
419 req.setRequestHeader("X-Requested-With", "XMLHttpRequest");
420 if (opts.headers) {
421 var headers = opts.headers;
422 if (!m.isArrayLike(headers)) {
423 headers = m.items(headers);
424 }
425 for (var i = 0; i < headers.length; i++) {
426 var header = headers[i];
427 var name = header[0];
428 var value = header[1];
429 req.setRequestHeader(name, value);
430 }
431 }
432 if ("responseType" in opts && "responseType" in req) {
433 req.responseType = opts.responseType;
434 }
435 if (opts.withCredentials) {
436 req.withCredentials = 'true';
437 }
438 return self.sendXMLHttpRequest(req, opts.sendContent);
439 },
440
441 _buildURL: function (url/*, ...*/) {
442 if (arguments.length > 1) {
443 var m = MochiKit.Base;
444 var qs = m.queryString.apply(null, m.extend(null, arguments, 1));
445 if (qs) {
446 return url + "?" + qs;
447 }
448 }
449 return url;
450 },
451
452 /** @id MochiKit.Async.doSimpleXMLHttpRequest */
453 doSimpleXMLHttpRequest: function (url/*, ...*/) {
454 var self = MochiKit.Async;
455 url = self._buildURL.apply(self, arguments);
456 return self.doXHR(url);
457 },
458
459 /** @id MochiKit.Async.loadJSONDoc */
460 loadJSONDoc: function (url/*, ...*/) {
461 var self = MochiKit.Async;
462 url = self._buildURL.apply(self, arguments);
463 var d = self.doXHR(url, {
464 'mimeType': 'text/plain',
465 'headers': [['Accept', 'application/json']]
466 });
467 d = d.addCallback(self.evalJSONRequest);
468 return d;
469 },
470
471 /** @id MochiKit.Async.loadScript */
472 loadScript: function (url) {
473 var d = new MochiKit.Async.Deferred();
474 var script = document.createElement("script");
475 script.type = "text/javascript";
476 script.src = url;
477 script.onload = function () {
478 script.onload = null;
479 script.onerror = null;
480 script.onreadystatechange = null;
481 script = null;
482 d.callback();
483 };
484 script.onerror = function (msg) {
485 script.onload = null;
486 script.onerror = null;
487 script.onreadystatechange = null;
488 script = null;
489 msg = "Failed to load script at " + url + ": " + msg;
490 d.errback(new URIError(msg, url));
491 }
492 script.onreadystatechange = function () {
493 if (script.readyState == "loaded" || script.readyState == "complete") {
494 script.onload();
495 } else {
496 // IE doesn't bother to report errors...
497 MochiKit.Async.callLater(10, script.onerror, "Script loading timed out")
498 }
499 };
500 document.getElementsByTagName("head")[0].appendChild(script);
501 return d;
502 },
503
504 /** @id MochiKit.Async.wait */
505 wait: function (seconds, /* optional */value) {
506 var d = new MochiKit.Async.Deferred();
507 var cb = MochiKit.Base.bind("callback", d, value);
508 var timeout = setTimeout(cb, Math.floor(seconds * 1000));
509 d.canceller = function () {
510 try {
511 clearTimeout(timeout);
512 } catch (e) {
513 // pass
514 }
515 };
516 return d;
517 },
518
519 /** @id MochiKit.Async.callLater */
520 callLater: function (seconds, func) {
521 var m = MochiKit.Base;
522 var pfunc = m.partial.apply(m, m.extend(null, arguments, 1));
523 return MochiKit.Async.wait(seconds).addCallback(
524 function (res) { return pfunc(); }
525 );
526 }
527});
528
529
530/** @id MochiKit.Async.DeferredLock */
531MochiKit.Async.DeferredLock = function () {
532 this.waiting = [];
533 this.locked = false;
534 this.id = this._nextId();
535};
536
537MochiKit.Async.DeferredLock.prototype = {
538 __class__: MochiKit.Async.DeferredLock,
539 /** @id MochiKit.Async.DeferredLock.prototype.acquire */
540 acquire: function () {
541 var d = new MochiKit.Async.Deferred();
542 if (this.locked) {
543 this.waiting.push(d);
544 } else {
545 this.locked = true;
546 d.callback(this);
547 }
548 return d;
549 },
550 /** @id MochiKit.Async.DeferredLock.prototype.release */
551 release: function () {
552 if (!this.locked) {
553 throw TypeError("Tried to release an unlocked DeferredLock");
554 }
555 this.locked = false;
556 if (this.waiting.length > 0) {
557 this.locked = true;
558 this.waiting.shift().callback(this);
559 }
560 },
561 _nextId: MochiKit.Base.counter(),
562 repr: function () {
563 var state;
564 if (this.locked) {
565 state = 'locked, ' + this.waiting.length + ' waiting';
566 } else {
567 state = 'unlocked';
568 }
569 return 'DeferredLock(' + this.id + ', ' + state + ')';
570 },
571 toString: MochiKit.Base.forwardCall("repr")
572
573};
574
575/** @id MochiKit.Async.DeferredList */
576MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {
577
578 // call parent constructor
579 MochiKit.Async.Deferred.apply(this, [canceller]);
580
581 this.list = list;
582 var resultList = [];
583 this.resultList = resultList;
584
585 this.finishedCount = 0;
586 this.fireOnOneCallback = fireOnOneCallback;
587 this.fireOnOneErrback = fireOnOneErrback;
588 this.consumeErrors = consumeErrors;
589
590 var cb = MochiKit.Base.bind(this._cbDeferred, this);
591 for (var i = 0; i < list.length; i++) {
592 var d = list[i];
593 resultList.push(undefined);
594 d.addCallback(cb, i, true);
595 d.addErrback(cb, i, false);
596 }
597
598 if (list.length === 0 && !fireOnOneCallback) {
599 this.callback(this.resultList);
600 }
601
602};
603
604MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred();
605MochiKit.Async.DeferredList.prototype.constructor = MochiKit.Async.DeferredList;
606
607MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) {
608 this.resultList[index] = [succeeded, result];
609 this.finishedCount += 1;
610 if (this.fired == -1) {
611 if (succeeded && this.fireOnOneCallback) {
612 this.callback([index, result]);
613 } else if (!succeeded && this.fireOnOneErrback) {
614 this.errback(result);
615 } else if (this.finishedCount == this.list.length) {
616 this.callback(this.resultList);
617 }
618 }
619 if (!succeeded && this.consumeErrors) {
620 result = null;
621 }
622 return result;
623};
624
625/** @id MochiKit.Async.gatherResults */
626MochiKit.Async.gatherResults = function (deferredList) {
627 var d = new MochiKit.Async.DeferredList(deferredList, false, true, false);
628 d.addCallback(function (results) {
629 var ret = [];
630 for (var i = 0; i < results.length; i++) {
631 ret.push(results[i][1]);
632 }
633 return ret;
634 });
635 return d;
636};
637
638/** @id MochiKit.Async.maybeDeferred */
639MochiKit.Async.maybeDeferred = function (func) {
640 var self = MochiKit.Async;
641 var result;
642 try {
643 var r = func.apply(null, MochiKit.Base.extend([], arguments, 1));
644 if (r instanceof self.Deferred) {
645 result = r;
646 } else if (r instanceof Error) {
647 result = self.fail(r);
648 } else {
649 result = self.succeed(r);
650 }
651 } catch (e) {
652 result = self.fail(e);
653 }
654 return result;
655};
656
657
658MochiKit.Async.__new__ = function () {
659 var m = MochiKit.Base;
660 var ne = m.partial(m._newNamedError, this);
661
662 ne("AlreadyCalledError",
663 /** @id MochiKit.Async.AlreadyCalledError */
664 function (deferred) {
665 /***
666
667 Raised by the Deferred if callback or errback happens
668 after it was already fired.
669
670 ***/
671 this.deferred = deferred;
672 }
673 );
674
675 ne("CancelledError",
676 /** @id MochiKit.Async.CancelledError */
677 function (deferred) {
678 /***
679
680 Raised by the Deferred cancellation mechanism.
681
682 ***/
683 this.deferred = deferred;
684 }
685 );
686
687 ne("BrowserComplianceError",
688 /** @id MochiKit.Async.BrowserComplianceError */
689 function (msg) {
690 /***
691
692 Raised when the JavaScript runtime is not capable of performing
693 the given function. Technically, this should really never be
694 raised because a non-conforming JavaScript runtime probably
695 isn't going to support exceptions in the first place.
696
697 ***/
698 this.message = msg;
699 }
700 );
701
702 ne("GenericError",
703 /** @id MochiKit.Async.GenericError */
704 function (msg) {
705 this.message = msg;
706 }
707 );
708
709 ne("XMLHttpRequestError",
710 /** @id MochiKit.Async.XMLHttpRequestError */
711 function (req, msg) {
712 /***
713
714 Raised when an XMLHttpRequest does not complete for any reason.
715
716 ***/
717 this.req = req;
718 this.message = msg;
719 try {
720 // Strange but true that this can raise in some cases.
721 this.number = req.status;
722 } catch (e) {
723 // pass
724 }
725 }
726 );
727
728 m.nameFunctions(this);
729};
730
731MochiKit.Async.__new__();
732
733MochiKit.Base._exportSymbols(this, MochiKit.Async);
diff --git a/frontend/delta/js/MochiKit/Base.js b/frontend/delta/js/MochiKit/Base.js
new file mode 100644
index 0000000..c55f5c3
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Base.js
@@ -0,0 +1,1523 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Base 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34
35// MochiKit module (namespace)
36var MochiKit = MochiKit || {};
37if (typeof(MochiKit.__export__) == "undefined") {
38 MochiKit.__export__ = true;
39}
40MochiKit.NAME = "MochiKit";
41MochiKit.VERSION = "1.5";
42MochiKit.__repr__ = function () {
43 return "[" + this.NAME + " " + this.VERSION + "]";
44};
45MochiKit.toString = function () {
46 return this.__repr__();
47};
48
49
50// MochiKit.Base module
51MochiKit.Base = MochiKit.Base || {};
52
53/**
54 * Creates a new module in a parent namespace. This function will
55 * create a new empty module object with "NAME", "VERSION",
56 * "toString" and "__repr__" properties. This object will be inserted into the parent object
57 * using the specified name (i.e. parent[name] = module). It will
58 * also verify that all the dependency modules are defined in the
59 * parent, or an error will be thrown.
60 *
61 * @param {Object} parent the parent module (use "this" or "window" for
62 * a global module)
63 * @param {String} name the module name, e.g. "Base"
64 * @param {String} version the module version, e.g. "1.5"
65 * @param {Array} [deps] the array of module dependencies (as strings)
66 */
67MochiKit.Base.module = function (parent, name, version, deps) {
68 var module = parent[name] = parent[name] || {};
69 var prefix = (parent.NAME ? parent.NAME + "." : "");
70 module.NAME = prefix + name;
71 module.VERSION = version;
72 module.__repr__ = function () {
73 return "[" + this.NAME + " " + this.VERSION + "]";
74 };
75 module.toString = function () {
76 return this.__repr__();
77 };
78 for (var i = 0; deps != null && i < deps.length; i++) {
79 if (!(deps[i] in parent)) {
80 throw module.NAME + ' depends on ' + prefix + deps[i] + '!';
81 }
82 }
83 return module;
84};
85
86MochiKit.Base.module(MochiKit, "Base", "1.5", []);
87
88/** @id MochiKit.Base.update */
89MochiKit.Base.update = function (self, obj/*, ... */) {
90 if (self === null || self === undefined) {
91 self = {};
92 }
93 for (var i = 1; i < arguments.length; i++) {
94 var o = arguments[i];
95 if (typeof(o) != 'undefined' && o !== null) {
96 for (var k in o) {
97 self[k] = o[k];
98 }
99 }
100 }
101 return self;
102};
103
104MochiKit.Base.update(MochiKit.Base, {
105 /** @id MochiKit.Base.camelize */
106 camelize: function (selector) {
107 /* from dojo.style.toCamelCase */
108 var arr = selector.split('-');
109 var cc = arr[0];
110 for (var i = 1; i < arr.length; i++) {
111 cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
112 }
113 return cc;
114 },
115
116 /** @id MochiKit.Base.counter */
117 counter: function (n/* = 1 */) {
118 if (arguments.length === 0) {
119 n = 1;
120 }
121 return function () {
122 return n++;
123 };
124 },
125
126 /** @id MochiKit.Base.clone */
127 clone: function (obj) {
128 var me = arguments.callee;
129 if (arguments.length == 1) {
130 me.prototype = obj;
131 return new me();
132 }
133 },
134
135 _flattenArray: function (res, lst) {
136 for (var i = 0; i < lst.length; i++) {
137 var o = lst[i];
138 if (o instanceof Array) {
139 arguments.callee(res, o);
140 } else {
141 res.push(o);
142 }
143 }
144 return res;
145 },
146
147 /** @id MochiKit.Base.flattenArray */
148 flattenArray: function (lst) {
149 return MochiKit.Base._flattenArray([], lst);
150 },
151
152 /** @id MochiKit.Base.flattenArguments */
153 flattenArguments: function (lst/* ...*/) {
154 var res = [];
155 var m = MochiKit.Base;
156 var args = m.extend(null, arguments);
157 while (args.length) {
158 var o = args.shift();
159 if (o && typeof(o) == "object" && typeof(o.length) == "number") {
160 for (var i = o.length - 1; i >= 0; i--) {
161 args.unshift(o[i]);
162 }
163 } else {
164 res.push(o);
165 }
166 }
167 return res;
168 },
169
170 /** @id MochiKit.Base.extend */
171 extend: function (self, obj, /* optional */skip) {
172 // Extend an array with an array-like object starting
173 // from the skip index
174 if (!skip) {
175 skip = 0;
176 }
177 if (obj) {
178 // allow iterable fall-through, but skip the full isArrayLike
179 // check for speed, this is called often.
180 var l = obj.length;
181 if (typeof(l) != 'number' /* !isArrayLike(obj) */) {
182 if (typeof(MochiKit.Iter) != "undefined") {
183 obj = MochiKit.Iter.list(obj);
184 l = obj.length;
185 } else {
186 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
187 }
188 }
189 if (!self) {
190 self = [];
191 }
192 for (var i = skip; i < l; i++) {
193 self.push(obj[i]);
194 }
195 }
196 // This mutates, but it's convenient to return because
197 // it's often used like a constructor when turning some
198 // ghetto array-like to a real array
199 return self;
200 },
201
202
203 /** @id MochiKit.Base.updatetree */
204 updatetree: function (self, obj/*, ...*/) {
205 if (self === null || self === undefined) {
206 self = {};
207 }
208 for (var i = 1; i < arguments.length; i++) {
209 var o = arguments[i];
210 if (typeof(o) != 'undefined' && o !== null) {
211 for (var k in o) {
212 var v = o[k];
213 if (typeof(self[k]) == 'object' && typeof(v) == 'object') {
214 arguments.callee(self[k], v);
215 } else {
216 self[k] = v;
217 }
218 }
219 }
220 }
221 return self;
222 },
223
224 /** @id MochiKit.Base.setdefault */
225 setdefault: function (self, obj/*, ...*/) {
226 if (self === null || self === undefined) {
227 self = {};
228 }
229 for (var i = 1; i < arguments.length; i++) {
230 var o = arguments[i];
231 for (var k in o) {
232 if (!(k in self)) {
233 self[k] = o[k];
234 }
235 }
236 }
237 return self;
238 },
239
240 /** @id MochiKit.Base.keys */
241 keys: function (obj) {
242 var rval = [];
243 for (var prop in obj) {
244 rval.push(prop);
245 }
246 return rval;
247 },
248
249 /** @id MochiKit.Base.values */
250 values: function (obj) {
251 var rval = [];
252 for (var prop in obj) {
253 rval.push(obj[prop]);
254 }
255 return rval;
256 },
257
258 /** @id MochiKit.Base.items */
259 items: function (obj) {
260 var rval = [];
261 var e;
262 for (var prop in obj) {
263 var v;
264 try {
265 v = obj[prop];
266 } catch (e) {
267 continue;
268 }
269 rval.push([prop, v]);
270 }
271 return rval;
272 },
273
274
275 _newNamedError: function (module, name, func) {
276 func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name);
277 func.prototype.constructor = func;
278 module[name] = func;
279 },
280
281
282 /** @id MochiKit.Base.operator */
283 operator: {
284 // unary logic operators
285 /** @id MochiKit.Base.truth */
286 truth: function (a) { return !!a; },
287 /** @id MochiKit.Base.lognot */
288 lognot: function (a) { return !a; },
289 /** @id MochiKit.Base.identity */
290 identity: function (a) { return a; },
291
292 // bitwise unary operators
293 /** @id MochiKit.Base.not */
294 not: function (a) { return ~a; },
295 /** @id MochiKit.Base.neg */
296 neg: function (a) { return -a; },
297
298 // binary operators
299 /** @id MochiKit.Base.add */
300 add: function (a, b) { return a + b; },
301 /** @id MochiKit.Base.sub */
302 sub: function (a, b) { return a - b; },
303 /** @id MochiKit.Base.div */
304 div: function (a, b) { return a / b; },
305 /** @id MochiKit.Base.mod */
306 mod: function (a, b) { return a % b; },
307 /** @id MochiKit.Base.mul */
308 mul: function (a, b) { return a * b; },
309
310 // bitwise binary operators
311 /** @id MochiKit.Base.and */
312 and: function (a, b) { return a & b; },
313 /** @id MochiKit.Base.or */
314 or: function (a, b) { return a | b; },
315 /** @id MochiKit.Base.xor */
316 xor: function (a, b) { return a ^ b; },
317 /** @id MochiKit.Base.lshift */
318 lshift: function (a, b) { return a << b; },
319 /** @id MochiKit.Base.rshift */
320 rshift: function (a, b) { return a >> b; },
321 /** @id MochiKit.Base.zrshift */
322 zrshift: function (a, b) { return a >>> b; },
323
324 // near-worthless built-in comparators
325 /** @id MochiKit.Base.eq */
326 eq: function (a, b) { return a == b; },
327 /** @id MochiKit.Base.ne */
328 ne: function (a, b) { return a != b; },
329 /** @id MochiKit.Base.gt */
330 gt: function (a, b) { return a > b; },
331 /** @id MochiKit.Base.ge */
332 ge: function (a, b) { return a >= b; },
333 /** @id MochiKit.Base.lt */
334 lt: function (a, b) { return a < b; },
335 /** @id MochiKit.Base.le */
336 le: function (a, b) { return a <= b; },
337
338 // strict built-in comparators
339 seq: function (a, b) { return a === b; },
340 sne: function (a, b) { return a !== b; },
341
342 // compare comparators
343 /** @id MochiKit.Base.ceq */
344 ceq: function (a, b) { return MochiKit.Base.compare(a, b) === 0; },
345 /** @id MochiKit.Base.cne */
346 cne: function (a, b) { return MochiKit.Base.compare(a, b) !== 0; },
347 /** @id MochiKit.Base.cgt */
348 cgt: function (a, b) { return MochiKit.Base.compare(a, b) == 1; },
349 /** @id MochiKit.Base.cge */
350 cge: function (a, b) { return MochiKit.Base.compare(a, b) != -1; },
351 /** @id MochiKit.Base.clt */
352 clt: function (a, b) { return MochiKit.Base.compare(a, b) == -1; },
353 /** @id MochiKit.Base.cle */
354 cle: function (a, b) { return MochiKit.Base.compare(a, b) != 1; },
355
356 // binary logical operators
357 /** @id MochiKit.Base.logand */
358 logand: function (a, b) { return a && b; },
359 /** @id MochiKit.Base.logor */
360 logor: function (a, b) { return a || b; },
361 /** @id MochiKit.Base.contains */
362 contains: function (a, b) { return b in a; }
363 },
364
365 /** @id MochiKit.Base.forwardCall */
366 forwardCall: function (func) {
367 return function () {
368 return this[func].apply(this, arguments);
369 };
370 },
371
372 /** @id MochiKit.Base.itemgetter */
373 itemgetter: function (func) {
374 return function (arg) {
375 return arg[func];
376 };
377 },
378
379 /** @id MochiKit.Base.bool */
380 bool: function (value) {
381 if (typeof(value) === "boolean" || value instanceof Boolean) {
382 return value.valueOf();
383 } else if (typeof(value) === "string" || value instanceof String) {
384 return value.length > 0 && value != "false" && value != "null" &&
385 value != "undefined" && value != "0";
386 } else if (typeof(value) === "number" || value instanceof Number) {
387 return !isNaN(value) && value != 0;
388 } else if (value != null && typeof(value.length) === "number") {
389 return value.length !== 0;
390 } else {
391 return value != null;
392 }
393 },
394
395 /** @id MochiKit.Base.typeMatcher */
396 typeMatcher: function (/* typ */) {
397 var types = {};
398 for (var i = 0; i < arguments.length; i++) {
399 var typ = arguments[i];
400 types[typ] = typ;
401 }
402 return function () {
403 for (var i = 0; i < arguments.length; i++) {
404 if (!(typeof(arguments[i]) in types)) {
405 return false;
406 }
407 }
408 return true;
409 };
410 },
411
412 /** @id MochiKit.Base.isNull */
413 isNull: function (/* ... */) {
414 for (var i = 0; i < arguments.length; i++) {
415 if (arguments[i] !== null) {
416 return false;
417 }
418 }
419 return true;
420 },
421
422 /** @id MochiKit.Base.isUndefinedOrNull */
423 isUndefinedOrNull: function (/* ... */) {
424 for (var i = 0; i < arguments.length; i++) {
425 var o = arguments[i];
426 if (!(typeof(o) == 'undefined' || o === null)) {
427 return false;
428 }
429 }
430 return true;
431 },
432
433 /** @id MochiKit.Base.isEmpty */
434 isEmpty: function (obj) {
435 return !MochiKit.Base.isNotEmpty.apply(this, arguments);
436 },
437
438 /** @id MochiKit.Base.isNotEmpty */
439 isNotEmpty: function (obj) {
440 for (var i = 0; i < arguments.length; i++) {
441 var o = arguments[i];
442 if (!(o && o.length)) {
443 return false;
444 }
445 }
446 return true;
447 },
448
449 /** @id MochiKit.Base.isArrayLike */
450 isArrayLike: function () {
451 for (var i = 0; i < arguments.length; i++) {
452 var o = arguments[i];
453 var typ = typeof(o);
454 if (
455 (typ != 'object' && !(typ == 'function' && typeof(o.item) == 'function')) ||
456 o === null ||
457 typeof(o.length) != 'number' ||
458 o.nodeType === 3 ||
459 o.nodeType === 4
460 ) {
461 return false;
462 }
463 }
464 return true;
465 },
466
467 /** @id MochiKit.Base.isDateLike */
468 isDateLike: function () {
469 for (var i = 0; i < arguments.length; i++) {
470 var o = arguments[i];
471 if (typeof(o) != "object" || o === null
472 || typeof(o.getTime) != 'function') {
473 return false;
474 }
475 }
476 return true;
477 },
478
479
480 /** @id MochiKit.Base.xmap */
481 xmap: function (fn/*, obj... */) {
482 if (fn === null) {
483 return MochiKit.Base.extend(null, arguments, 1);
484 }
485 var rval = [];
486 for (var i = 1; i < arguments.length; i++) {
487 rval.push(fn(arguments[i]));
488 }
489 return rval;
490 },
491
492 /** @id MochiKit.Base.map */
493 map: function (fn, lst/*, lst... */) {
494 var m = MochiKit.Base;
495 var itr = MochiKit.Iter;
496 var isArrayLike = m.isArrayLike;
497 if (arguments.length <= 2) {
498 // allow an iterable to be passed
499 if (!isArrayLike(lst)) {
500 if (itr) {
501 // fast path for map(null, iterable)
502 lst = itr.list(lst);
503 if (fn === null) {
504 return lst;
505 }
506 } else {
507 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
508 }
509 }
510 // fast path for map(null, lst)
511 if (fn === null) {
512 return m.extend(null, lst);
513 }
514 // disabled fast path for map(fn, lst)
515 /*
516 if (false && typeof(Array.prototype.map) == 'function') {
517 // Mozilla fast-path
518 return Array.prototype.map.call(lst, fn);
519 }
520 */
521 var rval = [];
522 for (var i = 0; i < lst.length; i++) {
523 rval.push(fn(lst[i]));
524 }
525 return rval;
526 } else {
527 // default for map(null, ...) is zip(...)
528 if (fn === null) {
529 fn = Array;
530 }
531 var length = null;
532 for (var i = 1; i < arguments.length; i++) {
533 // allow iterables to be passed
534 if (!isArrayLike(arguments[i])) {
535 if (itr) {
536 return itr.list(itr.imap.apply(null, arguments));
537 } else {
538 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
539 }
540 }
541 // find the minimum length
542 var l = arguments[i].length;
543 if (length === null || length > l) {
544 length = l;
545 }
546 }
547 rval = [];
548 for (var i = 0; i < length; i++) {
549 var args = [];
550 for (var j = 1; j < arguments.length; j++) {
551 args.push(arguments[j][i]);
552 }
553 rval.push(fn.apply(this, args));
554 }
555 return rval;
556 }
557 },
558
559 /** @id MochiKit.Base.xfilter */
560 xfilter: function (fn/*, obj... */) {
561 var rval = [];
562 if (fn === null) {
563 fn = MochiKit.Base.operator.truth;
564 }
565 for (var i = 1; i < arguments.length; i++) {
566 var o = arguments[i];
567 if (fn(o)) {
568 rval.push(o);
569 }
570 }
571 return rval;
572 },
573
574 /** @id MochiKit.Base.filter */
575 filter: function (fn, lst, self) {
576 var rval = [];
577 // allow an iterable to be passed
578 var m = MochiKit.Base;
579 if (!m.isArrayLike(lst)) {
580 if (MochiKit.Iter) {
581 lst = MochiKit.Iter.list(lst);
582 } else {
583 throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
584 }
585 }
586 if (fn === null) {
587 fn = m.operator.truth;
588 }
589 if (typeof(Array.prototype.filter) == 'function') {
590 // Mozilla fast-path
591 return Array.prototype.filter.call(lst, fn, self);
592 } else if (typeof(self) == 'undefined' || self === null) {
593 for (var i = 0; i < lst.length; i++) {
594 var o = lst[i];
595 if (fn(o)) {
596 rval.push(o);
597 }
598 }
599 } else {
600 for (var i = 0; i < lst.length; i++) {
601 o = lst[i];
602 if (fn.call(self, o)) {
603 rval.push(o);
604 }
605 }
606 }
607 return rval;
608 },
609
610
611 _wrapDumbFunction: function (func) {
612 return function () {
613 // fast path!
614 switch (arguments.length) {
615 case 0: return func();
616 case 1: return func(arguments[0]);
617 case 2: return func(arguments[0], arguments[1]);
618 case 3: return func(arguments[0], arguments[1], arguments[2]);
619 }
620 var args = [];
621 for (var i = 0; i < arguments.length; i++) {
622 args.push("arguments[" + i + "]");
623 }
624 return eval("(func(" + args.join(",") + "))");
625 };
626 },
627
628 /** @id MochiKit.Base.methodcaller */
629 methodcaller: function (func/*, args... */) {
630 var args = MochiKit.Base.extend(null, arguments, 1);
631 if (typeof(func) == "function") {
632 return function (obj) {
633 return func.apply(obj, args);
634 };
635 } else {
636 return function (obj) {
637 return obj[func].apply(obj, args);
638 };
639 }
640 },
641
642 /** @id MochiKit.Base.method */
643 method: function (self, func) {
644 var m = MochiKit.Base;
645 return m.bind.apply(this, m.extend([func, self], arguments, 2));
646 },
647
648 /** @id MochiKit.Base.compose */
649 compose: function (f1, f2/*, f3, ... fN */) {
650 var fnlist = [];
651 var m = MochiKit.Base;
652 if (arguments.length === 0) {
653 throw new TypeError("compose() requires at least one argument");
654 }
655 for (var i = 0; i < arguments.length; i++) {
656 var fn = arguments[i];
657 if (typeof(fn) != "function") {
658 throw new TypeError(m.repr(fn) + " is not a function");
659 }
660 fnlist.push(fn);
661 }
662 return function () {
663 var args = arguments;
664 for (var i = fnlist.length - 1; i >= 0; i--) {
665 args = [fnlist[i].apply(this, args)];
666 }
667 return args[0];
668 };
669 },
670
671 /** @id MochiKit.Base.bind */
672 bind: function (func, self/* args... */) {
673 if (typeof(func) == "string") {
674 func = self[func];
675 }
676 var im_func = func.im_func;
677 var im_preargs = func.im_preargs;
678 var im_self = func.im_self;
679 var m = MochiKit.Base;
680 if (typeof(func) == "function" && typeof(func.apply) == "undefined") {
681 // this is for cases where JavaScript sucks ass and gives you a
682 // really dumb built-in function like alert() that doesn't have
683 // an apply
684 func = m._wrapDumbFunction(func);
685 }
686 if (typeof(im_func) != 'function') {
687 im_func = func;
688 }
689 if (typeof(self) != 'undefined') {
690 im_self = self;
691 }
692 if (typeof(im_preargs) == 'undefined') {
693 im_preargs = [];
694 } else {
695 im_preargs = im_preargs.slice();
696 }
697 m.extend(im_preargs, arguments, 2);
698 var newfunc = function () {
699 var args = arguments;
700 var me = arguments.callee;
701 if (me.im_preargs.length > 0) {
702 args = m.concat(me.im_preargs, args);
703 }
704 var self = me.im_self;
705 if (!self) {
706 self = this;
707 }
708 return me.im_func.apply(self, args);
709 };
710 newfunc.im_self = im_self;
711 newfunc.im_func = im_func;
712 newfunc.im_preargs = im_preargs;
713 if (typeof(im_func.NAME) == 'string') {
714 newfunc.NAME = "bind(" + im_func.NAME + ",...)";
715 }
716 return newfunc;
717 },
718
719 /** @id MochiKit.Base.bindLate */
720 bindLate: function (func, self/* args... */) {
721 var m = MochiKit.Base;
722 var args = arguments;
723 if (typeof(func) === "string") {
724 args = m.extend([m.forwardCall(func)], arguments, 1);
725 return m.bind.apply(this, args);
726 }
727 return m.bind.apply(this, args);
728 },
729
730 /** @id MochiKit.Base.bindMethods */
731 bindMethods: function (self) {
732 var bind = MochiKit.Base.bind;
733 for (var k in self) {
734 var func = self[k];
735 if (typeof(func) == 'function') {
736 self[k] = bind(func, self);
737 }
738 }
739 },
740
741 /** @id MochiKit.Base.registerComparator */
742 registerComparator: function (name, check, comparator, /* optional */ override) {
743 MochiKit.Base.comparatorRegistry.register(name, check, comparator, override);
744 },
745
746 _primitives: {'boolean': true, 'string': true, 'number': true},
747
748 /** @id MochiKit.Base.compare */
749 compare: function (a, b) {
750 if (a == b) {
751 return 0;
752 }
753 var aIsNull = (typeof(a) == 'undefined' || a === null);
754 var bIsNull = (typeof(b) == 'undefined' || b === null);
755 if (aIsNull && bIsNull) {
756 return 0;
757 } else if (aIsNull) {
758 return -1;
759 } else if (bIsNull) {
760 return 1;
761 }
762 var m = MochiKit.Base;
763 // bool, number, string have meaningful comparisons
764 var prim = m._primitives;
765 if (!(typeof(a) in prim && typeof(b) in prim)) {
766 try {
767 return m.comparatorRegistry.match(a, b);
768 } catch (e) {
769 if (e != m.NotFound) {
770 throw e;
771 }
772 }
773 }
774 if (a < b) {
775 return -1;
776 } else if (a > b) {
777 return 1;
778 }
779 // These types can't be compared
780 var repr = m.repr;
781 throw new TypeError(repr(a) + " and " + repr(b) + " can not be compared");
782 },
783
784 /** @id MochiKit.Base.compareDateLike */
785 compareDateLike: function (a, b) {
786 return MochiKit.Base.compare(a.getTime(), b.getTime());
787 },
788
789 /** @id MochiKit.Base.compareArrayLike */
790 compareArrayLike: function (a, b) {
791 var compare = MochiKit.Base.compare;
792 var count = a.length;
793 var rval = 0;
794 if (count > b.length) {
795 rval = 1;
796 count = b.length;
797 } else if (count < b.length) {
798 rval = -1;
799 }
800 for (var i = 0; i < count; i++) {
801 var cmp = compare(a[i], b[i]);
802 if (cmp) {
803 return cmp;
804 }
805 }
806 return rval;
807 },
808
809 /** @id MochiKit.Base.registerRepr */
810 registerRepr: function (name, check, wrap, /* optional */override) {
811 MochiKit.Base.reprRegistry.register(name, check, wrap, override);
812 },
813
814 /** @id MochiKit.Base.repr */
815 repr: function (o) {
816 if (typeof(o) == "undefined") {
817 return "undefined";
818 } else if (o === null) {
819 return "null";
820 }
821 try {
822 if (typeof(o.__repr__) == 'function') {
823 return o.__repr__();
824 } else if (typeof(o.repr) == 'function' && o.repr != arguments.callee) {
825 return o.repr();
826 }
827 return MochiKit.Base.reprRegistry.match(o);
828 } catch (e) {
829 try {
830 if (typeof(o.NAME) == 'string' && (
831 o.toString == Function.prototype.toString ||
832 o.toString == Object.prototype.toString
833 )) {
834 return o.NAME;
835 }
836 } catch (ignore) {
837 }
838 }
839 try {
840 var ostring = (o + "");
841 } catch (e) {
842 return "[" + typeof(o) + "]";
843 }
844 if (typeof(o) == "function") {
845 ostring = ostring.replace(/^\s+/, "").replace(/\s+/g, " ");
846 ostring = ostring.replace(/,(\S)/, ", $1");
847 var idx = ostring.indexOf("{");
848 if (idx != -1) {
849 ostring = ostring.substr(0, idx) + "{...}";
850 }
851 }
852 return ostring;
853 },
854
855 /** @id MochiKit.Base.reprArrayLike */
856 reprArrayLike: function (o) {
857 var m = MochiKit.Base;
858 return "[" + m.map(m.repr, o).join(", ") + "]";
859 },
860
861 /** @id MochiKit.Base.reprString */
862 reprString: function (o) {
863 return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
864 ).replace(/[\f]/g, "\\f"
865 ).replace(/[\b]/g, "\\b"
866 ).replace(/[\n]/g, "\\n"
867 ).replace(/[\t]/g, "\\t"
868 ).replace(/[\v]/g, "\\v"
869 ).replace(/[\r]/g, "\\r");
870 },
871
872 /** @id MochiKit.Base.reprNumber */
873 reprNumber: function (o) {
874 return o + "";
875 },
876
877 /** @id MochiKit.Base.registerJSON */
878 registerJSON: function (name, check, wrap, /* optional */override) {
879 MochiKit.Base.jsonRegistry.register(name, check, wrap, override);
880 },
881
882
883 /** @id MochiKit.Base.evalJSON */
884 evalJSON: function (jsonText) {
885 return eval("(" + MochiKit.Base._filterJSON(jsonText) + ")");
886 },
887
888 _filterJSON: function (s) {
889 var m = s.match(/^\s*\/\*(.*)\*\/\s*$/);
890 return (m) ? m[1] : s;
891 },
892
893 /** @id MochiKit.Base.serializeJSON */
894 serializeJSON: function (o) {
895 var objtype = typeof(o);
896 if (objtype == "number" || objtype == "boolean") {
897 return o + "";
898 } else if (o === null) {
899 return "null";
900 } else if (objtype == "string") {
901 var res = "";
902 for (var i = 0; i < o.length; i++) {
903 var c = o.charAt(i);
904 if (c == '\"') {
905 res += '\\"';
906 } else if (c == '\\') {
907 res += '\\\\';
908 } else if (c == '\b') {
909 res += '\\b';
910 } else if (c == '\f') {
911 res += '\\f';
912 } else if (c == '\n') {
913 res += '\\n';
914 } else if (c == '\r') {
915 res += '\\r';
916 } else if (c == '\t') {
917 res += '\\t';
918 } else if (o.charCodeAt(i) <= 0x1F) {
919 var hex = o.charCodeAt(i).toString(16);
920 if (hex.length < 2) {
921 hex = '0' + hex;
922 }
923 res += '\\u00' + hex.toUpperCase();
924 } else {
925 res += c;
926 }
927 }
928 return '"' + res + '"';
929 }
930 // recurse
931 var me = arguments.callee;
932 // short-circuit for objects that support "json" serialization
933 // if they return "self" then just pass-through...
934 var newObj;
935 if (typeof(o.toJSON) == "function") {
936 newObj = o.toJSON();
937 if (o !== newObj) {
938 return me(newObj);
939 }
940 }
941 if (typeof(o.__json__) == "function") {
942 newObj = o.__json__();
943 if (o !== newObj) {
944 return me(newObj);
945 }
946 }
947 if (typeof(o.json) == "function") {
948 newObj = o.json();
949 if (o !== newObj) {
950 return me(newObj);
951 }
952 }
953 // array
954 if (objtype != "function" && typeof(o.length) == "number") {
955 var res = [];
956 for (var i = 0; i < o.length; i++) {
957 var val = me(o[i]);
958 if (typeof(val) != "string") {
959 // skip non-serializable values
960 continue;
961 }
962 res.push(val);
963 }
964 return "[" + res.join(", ") + "]";
965 }
966 // look in the registry
967 var m = MochiKit.Base;
968 try {
969 newObj = m.jsonRegistry.match(o);
970 if (o !== newObj) {
971 return me(newObj);
972 }
973 } catch (e) {
974 if (e != m.NotFound) {
975 // something really bad happened
976 throw e;
977 }
978 }
979 // undefined is outside of the spec
980 if (objtype == "undefined") {
981 throw new TypeError("undefined can not be serialized as JSON");
982 }
983 // it's a function with no adapter, bad
984 if (objtype == "function") {
985 return null;
986 }
987 // generic object code path
988 res = [];
989 for (var k in o) {
990 var useKey;
991 if (typeof(k) == "number") {
992 useKey = '"' + k + '"';
993 } else if (typeof(k) == "string") {
994 useKey = me(k);
995 } else {
996 // skip non-string or number keys
997 continue;
998 }
999 val = me(o[k]);
1000 if (typeof(val) != "string") {
1001 // skip non-serializable values
1002 continue;
1003 }
1004 res.push(useKey + ":" + val);
1005 }
1006 return "{" + res.join(", ") + "}";
1007 },
1008
1009
1010 /** @id MochiKit.Base.objEqual */
1011 objEqual: function (a, b) {
1012 return (MochiKit.Base.compare(a, b) === 0);
1013 },
1014
1015 /** @id MochiKit.Base.arrayEqual */
1016 arrayEqual: function (self, arr) {
1017 if (self.length != arr.length) {
1018 return false;
1019 }
1020 return (MochiKit.Base.compare(self, arr) === 0);
1021 },
1022
1023 /** @id MochiKit.Base.concat */
1024 concat: function (/* lst... */) {
1025 var rval = [];
1026 var extend = MochiKit.Base.extend;
1027 for (var i = 0; i < arguments.length; i++) {
1028 extend(rval, arguments[i]);
1029 }
1030 return rval;
1031 },
1032
1033 /** @id MochiKit.Base.keyComparator */
1034 keyComparator: function (key/* ... */) {
1035 // fast-path for single key comparisons
1036 var m = MochiKit.Base;
1037 var compare = m.compare;
1038 if (arguments.length == 1) {
1039 return function (a, b) {
1040 return compare(a[key], b[key]);
1041 };
1042 }
1043 var compareKeys = m.extend(null, arguments);
1044 return function (a, b) {
1045 var rval = 0;
1046 // keep comparing until something is inequal or we run out of
1047 // keys to compare
1048 for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) {
1049 var key = compareKeys[i];
1050 rval = compare(a[key], b[key]);
1051 }
1052 return rval;
1053 };
1054 },
1055
1056 /** @id MochiKit.Base.reverseKeyComparator */
1057 reverseKeyComparator: function (key) {
1058 var comparator = MochiKit.Base.keyComparator.apply(this, arguments);
1059 return function (a, b) {
1060 return comparator(b, a);
1061 };
1062 },
1063
1064 /** @id MochiKit.Base.partial */
1065 partial: function (func) {
1066 var m = MochiKit.Base;
1067 return m.bind.apply(this, m.extend([func, undefined], arguments, 1));
1068 },
1069
1070 /** @id MochiKit.Base.listMinMax */
1071 listMinMax: function (which, lst) {
1072 if (lst.length === 0) {
1073 return null;
1074 }
1075 var cur = lst[0];
1076 var compare = MochiKit.Base.compare;
1077 for (var i = 1; i < lst.length; i++) {
1078 var o = lst[i];
1079 if (compare(o, cur) == which) {
1080 cur = o;
1081 }
1082 }
1083 return cur;
1084 },
1085
1086 /** @id MochiKit.Base.objMax */
1087 objMax: function (/* obj... */) {
1088 return MochiKit.Base.listMinMax(1, arguments);
1089 },
1090
1091 /** @id MochiKit.Base.objMin */
1092 objMin: function (/* obj... */) {
1093 return MochiKit.Base.listMinMax(-1, arguments);
1094 },
1095
1096 /** @id MochiKit.Base.findIdentical */
1097 findIdentical: function (lst, value, start/* = 0 */, /* optional */end) {
1098 if (typeof(end) == "undefined" || end === null) {
1099 end = lst.length;
1100 }
1101 if (typeof(start) == "undefined" || start === null) {
1102 start = 0;
1103 }
1104 for (var i = start; i < end; i++) {
1105 if (lst[i] === value) {
1106 return i;
1107 }
1108 }
1109 return -1;
1110 },
1111
1112 /** @id MochiKit.Base.mean */
1113 mean: function(/* lst... */) {
1114 /* http://www.nist.gov/dads/HTML/mean.html */
1115 var sum = 0;
1116
1117 var m = MochiKit.Base;
1118 var args = m.extend(null, arguments);
1119 var count = args.length;
1120
1121 while (args.length) {
1122 var o = args.shift();
1123 if (o && typeof(o) == "object" && typeof(o.length) == "number") {
1124 count += o.length - 1;
1125 for (var i = o.length - 1; i >= 0; i--) {
1126 sum += o[i];
1127 }
1128 } else {
1129 sum += o;
1130 }
1131 }
1132
1133 if (count <= 0) {
1134 throw new TypeError('mean() requires at least one argument');
1135 }
1136
1137 return sum/count;
1138 },
1139
1140 /** @id MochiKit.Base.median */
1141 median: function(/* lst... */) {
1142 /* http://www.nist.gov/dads/HTML/median.html */
1143 var data = MochiKit.Base.flattenArguments(arguments);
1144 if (data.length === 0) {
1145 throw new TypeError('median() requires at least one argument');
1146 }
1147 data.sort(MochiKit.Base.compare);
1148 if (data.length % 2 == 0) {
1149 var upper = data.length / 2;
1150 return (data[upper] + data[upper - 1]) / 2;
1151 } else {
1152 return data[(data.length - 1) / 2];
1153 }
1154 },
1155
1156 /** @id MochiKit.Base.findValue */
1157 findValue: function (lst, value, start/* = 0 */, /* optional */end) {
1158 if (typeof(end) == "undefined" || end === null) {
1159 end = lst.length;
1160 }
1161 if (typeof(start) == "undefined" || start === null) {
1162 start = 0;
1163 }
1164 var cmp = MochiKit.Base.compare;
1165 for (var i = start; i < end; i++) {
1166 if (cmp(lst[i], value) === 0) {
1167 return i;
1168 }
1169 }
1170 return -1;
1171 },
1172
1173 /** @id MochiKit.Base.nodeWalk */
1174 nodeWalk: function (node, visitor) {
1175 var nodes = [node];
1176 var extend = MochiKit.Base.extend;
1177 while (nodes.length) {
1178 var res = visitor(nodes.shift());
1179 if (res) {
1180 extend(nodes, res);
1181 }
1182 }
1183 },
1184
1185
1186 /** @id MochiKit.Base.nameFunctions */
1187 nameFunctions: function (namespace) {
1188 var base = namespace.NAME;
1189 if (typeof(base) == 'undefined') {
1190 base = '';
1191 } else {
1192 base = base + '.';
1193 }
1194 for (var name in namespace) {
1195 var o = namespace[name];
1196 if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
1197 try {
1198 o.NAME = base + name;
1199 } catch (e) {
1200 // pass
1201 }
1202 }
1203 }
1204 },
1205
1206
1207 /** @id MochiKit.Base.queryString */
1208 queryString: function (names, values) {
1209 // check to see if names is a string or a DOM element, and if
1210 // MochiKit.DOM is available. If so, drop it like it's a form
1211 // Ugliest conditional in MochiKit? Probably!
1212 if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1
1213 && (typeof(names) == "string" || (
1214 typeof(names.nodeType) != "undefined" && names.nodeType > 0
1215 ))
1216 ) {
1217 var kv = MochiKit.DOM.formContents(names);
1218 names = kv[0];
1219 values = kv[1];
1220 } else if (arguments.length == 1) {
1221 // Allow the return value of formContents to be passed directly
1222 if (typeof(names.length) == "number" && names.length == 2) {
1223 return arguments.callee(names[0], names[1]);
1224 }
1225 var o = names;
1226 names = [];
1227 values = [];
1228 for (var k in o) {
1229 var v = o[k];
1230 if (typeof(v) == "function") {
1231 continue;
1232 } else if (MochiKit.Base.isArrayLike(v)){
1233 for (var i = 0; i < v.length; i++) {
1234 names.push(k);
1235 values.push(v[i]);
1236 }
1237 } else {
1238 names.push(k);
1239 values.push(v);
1240 }
1241 }
1242 }
1243 var rval = [];
1244 var len = Math.min(names.length, values.length);
1245 var urlEncode = MochiKit.Base.urlEncode;
1246 for (var i = 0; i < len; i++) {
1247 v = values[i];
1248 if (typeof(v) != 'undefined' && v !== null) {
1249 rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
1250 }
1251 }
1252 return rval.join("&");
1253 },
1254
1255
1256 /** @id MochiKit.Base.parseQueryString */
1257 parseQueryString: function (encodedString, useArrays) {
1258 // strip a leading '?' from the encoded string
1259 var qstr = (encodedString.charAt(0) == "?")
1260 ? encodedString.substring(1)
1261 : encodedString;
1262 var pairs = qstr.replace(/\+/g, "%20").split(/\&amp\;|\&\#38\;|\&#x26;|\&/);
1263 var o = {};
1264 var decode;
1265 if (typeof(decodeURIComponent) != "undefined") {
1266 decode = decodeURIComponent;
1267 } else {
1268 decode = unescape;
1269 }
1270 if (useArrays) {
1271 for (var i = 0; i < pairs.length; i++) {
1272 var pair = pairs[i].split("=");
1273 var name = decode(pair.shift());
1274 if (!name) {
1275 continue;
1276 }
1277 var arr = o[name];
1278 if (!(arr instanceof Array)) {
1279 arr = [];
1280 o[name] = arr;
1281 }
1282 arr.push(decode(pair.join("=")));
1283 }
1284 } else {
1285 for (var i = 0; i < pairs.length; i++) {
1286 pair = pairs[i].split("=");
1287 var name = pair.shift();
1288 if (!name) {
1289 continue;
1290 }
1291 o[decode(name)] = decode(pair.join("="));
1292 }
1293 }
1294 return o;
1295 }
1296});
1297
1298/** @id MochiKit.Base.AdapterRegistry */
1299MochiKit.Base.AdapterRegistry = function () {
1300 this.pairs = [];
1301};
1302
1303MochiKit.Base.AdapterRegistry.prototype = {
1304 /** @id MochiKit.Base.AdapterRegistry.prototype.register */
1305 register: function (name, check, wrap, /* optional */ override) {
1306 if (override) {
1307 this.pairs.unshift([name, check, wrap]);
1308 } else {
1309 this.pairs.push([name, check, wrap]);
1310 }
1311 },
1312
1313 /** @id MochiKit.Base.AdapterRegistry.prototype.match */
1314 match: function (/* ... */) {
1315 for (var i = 0; i < this.pairs.length; i++) {
1316 var pair = this.pairs[i];
1317 if (pair[1].apply(this, arguments)) {
1318 return pair[2].apply(this, arguments);
1319 }
1320 }
1321 throw MochiKit.Base.NotFound;
1322 },
1323
1324 /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
1325 unregister: function (name) {
1326 for (var i = 0; i < this.pairs.length; i++) {
1327 var pair = this.pairs[i];
1328 if (pair[0] == name) {
1329 this.pairs.splice(i, 1);
1330 return true;
1331 }
1332 }
1333 return false;
1334 }
1335};
1336
1337/**
1338 * Exports all symbols from one or more modules into the specified
1339 * namespace (or scope). This is similar to MochiKit.Base.update(),
1340 * except for special handling of the "__export__" flag, contained
1341 * sub-modules (exported recursively), and names starting with "_".
1342 *
1343 * @param {Object} namespace the object or scope to modify
1344 * @param {Object} module the module to export
1345 */
1346MochiKit.Base.moduleExport = function (namespace, module/*, ...*/) {
1347 var SKIP = { toString: true, NAME: true, VERSION: true };
1348 var mods = MochiKit.Base.extend([], arguments, 1);
1349 while ((module = mods.shift()) != null) {
1350 for (var k in module) {
1351 var v = module[k];
1352 if (v != null) {
1353 var flagSet = (typeof(v.__export__) == 'boolean');
1354 var nameValid = (k[0] !== "_" && !SKIP[k]);
1355 if (flagSet ? v.__export__ : nameValid) {
1356 if (typeof(v) == 'object' && v.NAME && v.VERSION) {
1357 mods.push(v);
1358 } else {
1359 namespace[k] = module[k];
1360 }
1361 }
1362 }
1363 }
1364 }
1365 return namespace;
1366};
1367
1368/**
1369 * Identical to moduleExport, but also considers the global and
1370 * module-specific "__export__" flag.
1371 */
1372MochiKit.Base._exportSymbols = function (namespace, module) {
1373 if (MochiKit.__export__ !== false && module.__export__ !== false) {
1374 MochiKit.Base.moduleExport(namespace, module);
1375 }
1376};
1377
1378/**
1379 * Creates a deprecated function alias in the specified module. The
1380 * deprecated function will forward all calls and arguments to a
1381 * target function, while also logging a debug message on the first
1382 * call (if MochiKit.Logging is loaded). The destination function may
1383 * be located in another module, which must be loaded, or an
1384 * exception will be thrown.
1385 *
1386 * @param {Object/String} module the source module or module name
1387 * (e.g. 'DOM' or 'MochiKit.DOM')
1388 * @param {String} name the deprecated function name (e.g. 'getStyle')
1389 * @param {String} target the fully qualified name of the target
1390 * function (e.g. 'MochiKit.Style.getStyle')
1391 * @param {String} version the first version when the source function
1392 * was deprecated (e.g. '1.4')
1393 * @param {Boolean} [exportable] the exportable function flag,
1394 * defaults to false
1395 */
1396MochiKit.Base._deprecated = function (module, name, target, version, exportable) {
1397 if (typeof(module) === 'string') {
1398 if (module.indexOf('MochiKit.') === 0) {
1399 module = module.substring(9);
1400 }
1401 module = MochiKit[module];
1402 }
1403 var targetModule = target.split('.')[1];
1404 var targetName = target.split('.')[2];
1405 var func = function () {
1406 var self = arguments.callee;
1407 var msg = module.NAME + '.' + name + ' is deprecated since version ' +
1408 version + '. Use ' + target + ' instead.';
1409 if (self.logged !== true) {
1410 self.logged = true;
1411 if (MochiKit.Logging) {
1412 MochiKit.Logging.logDebug(msg);
1413 } else if (console && console.log) {
1414 console.log(msg);
1415 }
1416 }
1417 if (!MochiKit[targetModule]) {
1418 throw new Error(msg);
1419 }
1420 return MochiKit[targetModule][targetName].apply(this, arguments);
1421 };
1422 func.__export__ = (exportable === true);
1423 module[name] = func;
1424};
1425
1426MochiKit.Base.__new__ = function () {
1427 var m = this;
1428
1429 /** @id MochiKit.Base.noop */
1430 m.noop = m.operator.identity;
1431
1432 // Backwards compat
1433 m._deprecated(m, 'forward', 'MochiKit.Base.forwardCall', '1.3');
1434 m._deprecated(m, 'find', 'MochiKit.Base.findValue', '1.3');
1435
1436 if (typeof(encodeURIComponent) != "undefined") {
1437 /** @id MochiKit.Base.urlEncode */
1438 m.urlEncode = function (unencoded) {
1439 return encodeURIComponent(unencoded).replace(/\'/g, '%27');
1440 };
1441 } else {
1442 m.urlEncode = function (unencoded) {
1443 return escape(unencoded
1444 ).replace(/\+/g, '%2B'
1445 ).replace(/\"/g,'%22'
1446 ).replace(/\'/g, '%27');
1447 };
1448 }
1449
1450 /** @id MochiKit.Base.NamedError */
1451 m.NamedError = function (name) {
1452 this.message = name;
1453 this.name = name;
1454 };
1455 m.NamedError.prototype = new Error();
1456 m.NamedError.prototype.constructor = m.NamedError;
1457 m.update(m.NamedError.prototype, {
1458 repr: function () {
1459 if (this.message && this.message != this.name) {
1460 return this.name + "(" + m.repr(this.message) + ")";
1461 } else {
1462 return this.name + "()";
1463 }
1464 },
1465 toString: m.forwardCall("repr")
1466 });
1467
1468 /** @id MochiKit.Base.NotFound */
1469 m.NotFound = new m.NamedError("MochiKit.Base.NotFound");
1470
1471
1472 /** @id MochiKit.Base.listMax */
1473 m.listMax = m.partial(m.listMinMax, 1);
1474 /** @id MochiKit.Base.listMin */
1475 m.listMin = m.partial(m.listMinMax, -1);
1476
1477 /** @id MochiKit.Base.isCallable */
1478 m.isCallable = m.typeMatcher('function');
1479 /** @id MochiKit.Base.isUndefined */
1480 m.isUndefined = m.typeMatcher('undefined');
1481 /** @id MochiKit.Base.isValue */
1482 m.isValue = m.typeMatcher('boolean', 'number', 'string');
1483
1484 /** @id MochiKit.Base.merge */
1485 m.merge = m.partial(m.update, null);
1486 /** @id MochiKit.Base.zip */
1487 m.zip = m.partial(m.map, null);
1488
1489 /** @id MochiKit.Base.average */
1490 m.average = m.mean;
1491
1492 /** @id MochiKit.Base.comparatorRegistry */
1493 m.comparatorRegistry = new m.AdapterRegistry();
1494 m.registerComparator("dateLike", m.isDateLike, m.compareDateLike);
1495 m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike);
1496
1497 /** @id MochiKit.Base.reprRegistry */
1498 m.reprRegistry = new m.AdapterRegistry();
1499 m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
1500 m.registerRepr("string", m.typeMatcher("string"), m.reprString);
1501 m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);
1502
1503 /** @id MochiKit.Base.jsonRegistry */
1504 m.jsonRegistry = new m.AdapterRegistry();
1505
1506 m.nameFunctions(this);
1507
1508};
1509
1510MochiKit.Base.__new__();
1511
1512//
1513// XXX: Internet Explorer blows
1514//
1515if (MochiKit.__export__) {
1516 compare = MochiKit.Base.compare;
1517 compose = MochiKit.Base.compose;
1518 serializeJSON = MochiKit.Base.serializeJSON;
1519 mean = MochiKit.Base.mean;
1520 median = MochiKit.Base.median;
1521}
1522
1523MochiKit.Base._exportSymbols(this, MochiKit.Base);
diff --git a/frontend/delta/js/MochiKit/Color.js b/frontend/delta/js/MochiKit/Color.js
new file mode 100644
index 0000000..f421737
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Color.js
@@ -0,0 +1,846 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Color 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito and others. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Color', '1.5', ['Base', 'DOM', 'Style']);
35
36/** @id MochiKit.Color.Color */
37MochiKit.Color.Color = function (red, green, blue, alpha) {
38 if (typeof(alpha) == 'undefined' || alpha === null) {
39 alpha = 1.0;
40 }
41 this.rgb = {
42 r: red,
43 g: green,
44 b: blue,
45 a: alpha
46 };
47};
48
49
50// Prototype methods
51
52MochiKit.Color.Color.prototype = {
53
54 __class__: MochiKit.Color.Color,
55
56 /** @id MochiKit.Color.Color.prototype.colorWithAlpha */
57 colorWithAlpha: function (alpha) {
58 var rgb = this.rgb;
59 var m = MochiKit.Color;
60 return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha);
61 },
62
63 /** @id MochiKit.Color.Color.prototype.colorWithHue */
64 colorWithHue: function (hue) {
65 // get an HSL model, and set the new hue...
66 var hsl = this.asHSL();
67 hsl.h = hue;
68 var m = MochiKit.Color;
69 // convert back to RGB...
70 return m.Color.fromHSL(hsl);
71 },
72
73 /** @id MochiKit.Color.Color.prototype.colorWithSaturation */
74 colorWithSaturation: function (saturation) {
75 // get an HSL model, and set the new hue...
76 var hsl = this.asHSL();
77 hsl.s = saturation;
78 var m = MochiKit.Color;
79 // convert back to RGB...
80 return m.Color.fromHSL(hsl);
81 },
82
83 /** @id MochiKit.Color.Color.prototype.colorWithLightness */
84 colorWithLightness: function (lightness) {
85 // get an HSL model, and set the new hue...
86 var hsl = this.asHSL();
87 hsl.l = lightness;
88 var m = MochiKit.Color;
89 // convert back to RGB...
90 return m.Color.fromHSL(hsl);
91 },
92
93 /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */
94 darkerColorWithLevel: function (level) {
95 var hsl = this.asHSL();
96 hsl.l = Math.max(hsl.l - level, 0);
97 var m = MochiKit.Color;
98 return m.Color.fromHSL(hsl);
99 },
100
101 /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
102 lighterColorWithLevel: function (level) {
103 var hsl = this.asHSL();
104 hsl.l = Math.min(hsl.l + level, 1);
105 var m = MochiKit.Color;
106 return m.Color.fromHSL(hsl);
107 },
108
109 /** @id MochiKit.Color.Color.prototype.blendedColor */
110 blendedColor: function (other, /* optional */ fraction) {
111 if (typeof(fraction) == 'undefined' || fraction === null) {
112 fraction = 0.5;
113 }
114 var sf = 1.0 - fraction;
115 var s = this.rgb;
116 var d = other.rgb;
117 var df = fraction;
118 return MochiKit.Color.Color.fromRGB(
119 (s.r * sf) + (d.r * df),
120 (s.g * sf) + (d.g * df),
121 (s.b * sf) + (d.b * df),
122 (s.a * sf) + (d.a * df)
123 );
124 },
125
126 /** @id MochiKit.Color.Color.prototype.compareRGB */
127 compareRGB: function (other) {
128 var a = this.asRGB();
129 var b = other.asRGB();
130 return MochiKit.Base.compare(
131 [a.r, a.g, a.b, a.a],
132 [b.r, b.g, b.b, b.a]
133 );
134 },
135
136 /** @id MochiKit.Color.Color.prototype.isLight */
137 isLight: function () {
138 return this.asHSL().l > 0.5;
139 },
140
141 /** @id MochiKit.Color.Color.prototype.isDark */
142 isDark: function () {
143 return (!this.isLight());
144 },
145
146 /** @id MochiKit.Color.Color.prototype.toHSLString */
147 toHSLString: function () {
148 var c = this.asHSL();
149 var ccc = MochiKit.Color.clampColorComponent;
150 var rval = this._hslString;
151 if (!rval) {
152 var mid = (
153 ccc(c.h, 360).toFixed(0)
154 + "," + ccc(c.s, 100).toPrecision(4) + "%"
155 + "," + ccc(c.l, 100).toPrecision(4) + "%"
156 );
157 var a = c.a;
158 if (a >= 1) {
159 a = 1;
160 rval = "hsl(" + mid + ")";
161 } else {
162 if (a <= 0) {
163 a = 0;
164 }
165 rval = "hsla(" + mid + "," + a + ")";
166 }
167 this._hslString = rval;
168 }
169 return rval;
170 },
171
172 /** @id MochiKit.Color.Color.prototype.toRGBString */
173 toRGBString: function () {
174 var c = this.rgb;
175 var ccc = MochiKit.Color.clampColorComponent;
176 var rval = this._rgbString;
177 if (!rval) {
178 var mid = (
179 ccc(c.r, 255).toFixed(0)
180 + "," + ccc(c.g, 255).toFixed(0)
181 + "," + ccc(c.b, 255).toFixed(0)
182 );
183 if (c.a != 1) {
184 rval = "rgba(" + mid + "," + c.a + ")";
185 } else {
186 rval = "rgb(" + mid + ")";
187 }
188 this._rgbString = rval;
189 }
190 return rval;
191 },
192
193 /** @id MochiKit.Color.Color.prototype.asRGB */
194 asRGB: function () {
195 return MochiKit.Base.clone(this.rgb);
196 },
197
198 /** @id MochiKit.Color.Color.prototype.toHexString */
199 toHexString: function () {
200 var m = MochiKit.Color;
201 var c = this.rgb;
202 var ccc = MochiKit.Color.clampColorComponent;
203 var rval = this._hexString;
204 if (!rval) {
205 rval = ("#" +
206 m.toColorPart(ccc(c.r, 255)) +
207 m.toColorPart(ccc(c.g, 255)) +
208 m.toColorPart(ccc(c.b, 255))
209 );
210 this._hexString = rval;
211 }
212 return rval;
213 },
214
215 /** @id MochiKit.Color.Color.prototype.asHSV */
216 asHSV: function () {
217 var hsv = this.hsv;
218 var c = this.rgb;
219 if (typeof(hsv) == 'undefined' || hsv === null) {
220 hsv = MochiKit.Color.rgbToHSV(this.rgb);
221 this.hsv = hsv;
222 }
223 return MochiKit.Base.clone(hsv);
224 },
225
226 /** @id MochiKit.Color.Color.prototype.asHSL */
227 asHSL: function () {
228 var hsl = this.hsl;
229 var c = this.rgb;
230 if (typeof(hsl) == 'undefined' || hsl === null) {
231 hsl = MochiKit.Color.rgbToHSL(this.rgb);
232 this.hsl = hsl;
233 }
234 return MochiKit.Base.clone(hsl);
235 },
236
237 /** @id MochiKit.Color.Color.prototype.toString */
238 toString: function () {
239 return this.toRGBString();
240 },
241
242 /** @id MochiKit.Color.Color.prototype.repr */
243 repr: function () {
244 var c = this.rgb;
245 var col = [c.r, c.g, c.b, c.a];
246 return this.__class__.NAME + "(" + col.join(", ") + ")";
247 }
248
249};
250
251// Constructor methods
252
253MochiKit.Base.update(MochiKit.Color.Color, {
254 /** @id MochiKit.Color.Color.fromRGB */
255 fromRGB: function (red, green, blue, alpha) {
256 // designated initializer
257 var Color = MochiKit.Color.Color;
258 if (arguments.length == 1) {
259 var rgb = red;
260 red = rgb.r;
261 green = rgb.g;
262 blue = rgb.b;
263 if (typeof(rgb.a) == 'undefined') {
264 alpha = undefined;
265 } else {
266 alpha = rgb.a;
267 }
268 }
269 return new Color(red, green, blue, alpha);
270 },
271
272 /** @id MochiKit.Color.Color.fromHSL */
273 fromHSL: function (hue, saturation, lightness, alpha) {
274 var m = MochiKit.Color;
275 return m.Color.fromRGB(m.hslToRGB.apply(m, arguments));
276 },
277
278 /** @id MochiKit.Color.Color.fromHSV */
279 fromHSV: function (hue, saturation, value, alpha) {
280 var m = MochiKit.Color;
281 return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments));
282 },
283
284 /** @id MochiKit.Color.Color.fromName */
285 fromName: function (name) {
286 var Color = MochiKit.Color.Color;
287 // Opera 9 seems to "quote" named colors(?!)
288 if (name.charAt(0) == '"') {
289 name = name.substr(1, name.length - 2);
290 }
291 var htmlColor = Color._namedColors[name.toLowerCase()];
292 if (typeof(htmlColor) == 'string') {
293 return Color.fromHexString(htmlColor);
294 } else if (name == "transparent") {
295 return Color.transparentColor();
296 }
297 return null;
298 },
299
300 /** @id MochiKit.Color.Color.fromString */
301 fromString: function (colorString) {
302 var self = MochiKit.Color.Color;
303 var three = colorString.substr(0, 3);
304 if (three == "rgb") {
305 return self.fromRGBString(colorString);
306 } else if (three == "hsl") {
307 return self.fromHSLString(colorString);
308 } else if (colorString.charAt(0) == "#") {
309 return self.fromHexString(colorString);
310 }
311 return self.fromName(colorString);
312 },
313
314
315 /** @id MochiKit.Color.Color.fromHexString */
316 fromHexString: function (hexCode) {
317 if (hexCode.charAt(0) == '#') {
318 hexCode = hexCode.substring(1);
319 }
320 var components = [];
321 var i, hex;
322 if (hexCode.length == 3) {
323 for (i = 0; i < 3; i++) {
324 hex = hexCode.substr(i, 1);
325 components.push(parseInt(hex + hex, 16) / 255.0);
326 }
327 } else {
328 for (i = 0; i < 6; i += 2) {
329 hex = hexCode.substr(i, 2);
330 components.push(parseInt(hex, 16) / 255.0);
331 }
332 }
333 var Color = MochiKit.Color.Color;
334 return Color.fromRGB.apply(Color, components);
335 },
336
337
338 _fromColorString: function (pre, method, scales, colorCode) {
339 // parses either HSL or RGB
340 if (colorCode.indexOf(pre) === 0) {
341 colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1);
342 }
343 var colorChunks = colorCode.split(/\s*,\s*/);
344 var colorFloats = [];
345 for (var i = 0; i < colorChunks.length; i++) {
346 var c = colorChunks[i];
347 var val;
348 var three = c.substring(c.length - 3);
349 if (c.charAt(c.length - 1) == '%') {
350 val = 0.01 * parseFloat(c.substring(0, c.length - 1));
351 } else if (three == "deg") {
352 val = parseFloat(c) / 360.0;
353 } else if (three == "rad") {
354 val = parseFloat(c) / (Math.PI * 2);
355 } else {
356 val = scales[i] * parseFloat(c);
357 }
358 colorFloats.push(val);
359 }
360 return this[method].apply(this, colorFloats);
361 },
362
363 /** @id MochiKit.Color.Color.fromComputedStyle */
364 fromComputedStyle: function (elem, style) {
365 var d = MochiKit.DOM;
366 var cls = MochiKit.Color.Color;
367 for (elem = d.getElement(elem); elem; elem = elem.parentNode) {
368 var actualColor = MochiKit.Style.getStyle.apply(d, arguments);
369 if (!actualColor) {
370 continue;
371 }
372 var color = cls.fromString(actualColor);
373 if (!color) {
374 break;
375 }
376 if (color.asRGB().a > 0) {
377 return color;
378 }
379 }
380 return null;
381 },
382
383 /** @id MochiKit.Color.Color.fromBackground */
384 fromBackground: function (elem) {
385 var cls = MochiKit.Color.Color;
386 return cls.fromComputedStyle(
387 elem, "backgroundColor", "background-color") || cls.whiteColor();
388 },
389
390 /** @id MochiKit.Color.Color.fromText */
391 fromText: function (elem) {
392 var cls = MochiKit.Color.Color;
393 return cls.fromComputedStyle(
394 elem, "color", "color") || cls.blackColor();
395 },
396
397 /** @id MochiKit.Color.Color.namedColors */
398 namedColors: function () {
399 return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
400 }
401});
402
403
404// Module level functions
405
406MochiKit.Base.update(MochiKit.Color, {
407 /** @id MochiKit.Color.clampColorComponent */
408 clampColorComponent: function (v, scale) {
409 v *= scale;
410 if (v < 0) {
411 return 0;
412 } else if (v > scale) {
413 return scale;
414 } else {
415 return v;
416 }
417 },
418
419 _hslValue: function (n1, n2, hue) {
420 if (hue > 6.0) {
421 hue -= 6.0;
422 } else if (hue < 0.0) {
423 hue += 6.0;
424 }
425 var val;
426 if (hue < 1.0) {
427 val = n1 + (n2 - n1) * hue;
428 } else if (hue < 3.0) {
429 val = n2;
430 } else if (hue < 4.0) {
431 val = n1 + (n2 - n1) * (4.0 - hue);
432 } else {
433 val = n1;
434 }
435 return val;
436 },
437
438 /** @id MochiKit.Color.hsvToRGB */
439 hsvToRGB: function (hue, saturation, value, alpha) {
440 if (arguments.length == 1) {
441 var hsv = hue;
442 hue = hsv.h;
443 saturation = hsv.s;
444 value = hsv.v;
445 alpha = hsv.a;
446 }
447 var red;
448 var green;
449 var blue;
450 if (saturation === 0) {
451 red = value;
452 green = value;
453 blue = value;
454 } else {
455 var i = Math.floor(hue * 6);
456 var f = (hue * 6) - i;
457 var p = value * (1 - saturation);
458 var q = value * (1 - (saturation * f));
459 var t = value * (1 - (saturation * (1 - f)));
460 switch (i) {
461 case 1: red = q; green = value; blue = p; break;
462 case 2: red = p; green = value; blue = t; break;
463 case 3: red = p; green = q; blue = value; break;
464 case 4: red = t; green = p; blue = value; break;
465 case 5: red = value; green = p; blue = q; break;
466 case 6: // fall through
467 case 0: red = value; green = t; blue = p; break;
468 }
469 }
470 return {
471 r: red,
472 g: green,
473 b: blue,
474 a: alpha
475 };
476 },
477
478 /** @id MochiKit.Color.hslToRGB */
479 hslToRGB: function (hue, saturation, lightness, alpha) {
480 if (arguments.length == 1) {
481 var hsl = hue;
482 hue = hsl.h;
483 saturation = hsl.s;
484 lightness = hsl.l;
485 alpha = hsl.a;
486 }
487 var red;
488 var green;
489 var blue;
490 if (saturation === 0) {
491 red = lightness;
492 green = lightness;
493 blue = lightness;
494 } else {
495 var m2;
496 if (lightness <= 0.5) {
497 m2 = lightness * (1.0 + saturation);
498 } else {
499 m2 = lightness + saturation - (lightness * saturation);
500 }
501 var m1 = (2.0 * lightness) - m2;
502 var f = MochiKit.Color._hslValue;
503 var h6 = hue * 6.0;
504 red = f(m1, m2, h6 + 2);
505 green = f(m1, m2, h6);
506 blue = f(m1, m2, h6 - 2);
507 }
508 return {
509 r: red,
510 g: green,
511 b: blue,
512 a: alpha
513 };
514 },
515
516 /** @id MochiKit.Color.rgbToHSV */
517 rgbToHSV: function (red, green, blue, alpha) {
518 if (arguments.length == 1) {
519 var rgb = red;
520 red = rgb.r;
521 green = rgb.g;
522 blue = rgb.b;
523 alpha = rgb.a;
524 }
525 var max = Math.max(Math.max(red, green), blue);
526 var min = Math.min(Math.min(red, green), blue);
527 var hue;
528 var saturation;
529 var value = max;
530 if (min == max) {
531 hue = 0;
532 saturation = 0;
533 } else {
534 var delta = (max - min);
535 saturation = delta / max;
536
537 if (red == max) {
538 hue = (green - blue) / delta;
539 } else if (green == max) {
540 hue = 2 + ((blue - red) / delta);
541 } else {
542 hue = 4 + ((red - green) / delta);
543 }
544 hue /= 6;
545 if (hue < 0) {
546 hue += 1;
547 }
548 if (hue > 1) {
549 hue -= 1;
550 }
551 }
552 return {
553 h: hue,
554 s: saturation,
555 v: value,
556 a: alpha
557 };
558 },
559
560 /** @id MochiKit.Color.rgbToHSL */
561 rgbToHSL: function (red, green, blue, alpha) {
562 if (arguments.length == 1) {
563 var rgb = red;
564 red = rgb.r;
565 green = rgb.g;
566 blue = rgb.b;
567 alpha = rgb.a;
568 }
569 var max = Math.max(red, Math.max(green, blue));
570 var min = Math.min(red, Math.min(green, blue));
571 var hue;
572 var saturation;
573 var lightness = (max + min) / 2.0;
574 var delta = max - min;
575 if (delta === 0) {
576 hue = 0;
577 saturation = 0;
578 } else {
579 if (lightness <= 0.5) {
580 saturation = delta / (max + min);
581 } else {
582 saturation = delta / (2 - max - min);
583 }
584 if (red == max) {
585 hue = (green - blue) / delta;
586 } else if (green == max) {
587 hue = 2 + ((blue - red) / delta);
588 } else {
589 hue = 4 + ((red - green) / delta);
590 }
591 hue /= 6;
592 if (hue < 0) {
593 hue += 1;
594 }
595 if (hue > 1) {
596 hue -= 1;
597 }
598
599 }
600 return {
601 h: hue,
602 s: saturation,
603 l: lightness,
604 a: alpha
605 };
606 },
607
608 /** @id MochiKit.Color.toColorPart */
609 toColorPart: function (num) {
610 num = Math.round(num);
611 var digits = num.toString(16);
612 if (num < 16) {
613 return '0' + digits;
614 }
615 return digits;
616 },
617
618 __new__: function () {
619 var m = MochiKit.Base;
620 /** @id MochiKit.Color.Color.fromRGBString */
621 this.Color.fromRGBString = m.bind(
622 this.Color._fromColorString, this.Color, "rgb", "fromRGB",
623 [1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
624 );
625 /** @id MochiKit.Color.Color.fromHSLString */
626 this.Color.fromHSLString = m.bind(
627 this.Color._fromColorString, this.Color, "hsl", "fromHSL",
628 [1.0/360.0, 0.01, 0.01, 1]
629 );
630
631 var third = 1.0 / 3.0;
632 /** @id MochiKit.Color.colors */
633 var colors = {
634 // NSColor colors plus transparent
635 /** @id MochiKit.Color.blackColor */
636 black: [0, 0, 0],
637 /** @id MochiKit.Color.blueColor */
638 blue: [0, 0, 1],
639 /** @id MochiKit.Color.brownColor */
640 brown: [0.6, 0.4, 0.2],
641 /** @id MochiKit.Color.cyanColor */
642 cyan: [0, 1, 1],
643 /** @id MochiKit.Color.darkGrayColor */
644 darkGray: [third, third, third],
645 /** @id MochiKit.Color.grayColor */
646 gray: [0.5, 0.5, 0.5],
647 /** @id MochiKit.Color.greenColor */
648 green: [0, 1, 0],
649 /** @id MochiKit.Color.lightGrayColor */
650 lightGray: [2 * third, 2 * third, 2 * third],
651 /** @id MochiKit.Color.magentaColor */
652 magenta: [1, 0, 1],
653 /** @id MochiKit.Color.orangeColor */
654 orange: [1, 0.5, 0],
655 /** @id MochiKit.Color.purpleColor */
656 purple: [0.5, 0, 0.5],
657 /** @id MochiKit.Color.redColor */
658 red: [1, 0, 0],
659 /** @id MochiKit.Color.transparentColor */
660 transparent: [0, 0, 0, 0],
661 /** @id MochiKit.Color.whiteColor */
662 white: [1, 1, 1],
663 /** @id MochiKit.Color.yellowColor */
664 yellow: [1, 1, 0]
665 };
666
667 for (var k in colors) {
668 var name = k + "Color";
669 var value = this.Color.fromRGB.apply(this.Color, colors[k]);
670 this.Color[name] = m.partial(m.operator.identity, value);
671 }
672
673 var isColor = function () {
674 for (var i = 0; i < arguments.length; i++) {
675 if (!(arguments[i] instanceof MochiKit.Color.Color)) {
676 return false;
677 }
678 }
679 return true;
680 };
681
682 var compareColor = function (a, b) {
683 return a.compareRGB(b);
684 };
685
686 m.nameFunctions(this);
687
688 m.registerComparator(this.Color.NAME, isColor, compareColor);
689 }
690});
691
692MochiKit.Color.__new__();
693
694// Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
695
696MochiKit.Color.Color._namedColors = {
697 aliceblue: "#f0f8ff",
698 antiquewhite: "#faebd7",
699 aqua: "#00ffff",
700 aquamarine: "#7fffd4",
701 azure: "#f0ffff",
702 beige: "#f5f5dc",
703 bisque: "#ffe4c4",
704 black: "#000000",
705 blanchedalmond: "#ffebcd",
706 blue: "#0000ff",
707 blueviolet: "#8a2be2",
708 brown: "#a52a2a",
709 burlywood: "#deb887",
710 cadetblue: "#5f9ea0",
711 chartreuse: "#7fff00",
712 chocolate: "#d2691e",
713 coral: "#ff7f50",
714 cornflowerblue: "#6495ed",
715 cornsilk: "#fff8dc",
716 crimson: "#dc143c",
717 cyan: "#00ffff",
718 darkblue: "#00008b",
719 darkcyan: "#008b8b",
720 darkgoldenrod: "#b8860b",
721 darkgray: "#a9a9a9",
722 darkgreen: "#006400",
723 darkgrey: "#a9a9a9",
724 darkkhaki: "#bdb76b",
725 darkmagenta: "#8b008b",
726 darkolivegreen: "#556b2f",
727 darkorange: "#ff8c00",
728 darkorchid: "#9932cc",
729 darkred: "#8b0000",
730 darksalmon: "#e9967a",
731 darkseagreen: "#8fbc8f",
732 darkslateblue: "#483d8b",
733 darkslategray: "#2f4f4f",
734 darkslategrey: "#2f4f4f",
735 darkturquoise: "#00ced1",
736 darkviolet: "#9400d3",
737 deeppink: "#ff1493",
738 deepskyblue: "#00bfff",
739 dimgray: "#696969",
740 dimgrey: "#696969",
741 dodgerblue: "#1e90ff",
742 firebrick: "#b22222",
743 floralwhite: "#fffaf0",
744 forestgreen: "#228b22",
745 fuchsia: "#ff00ff",
746 gainsboro: "#dcdcdc",
747 ghostwhite: "#f8f8ff",
748 gold: "#ffd700",
749 goldenrod: "#daa520",
750 gray: "#808080",
751 green: "#008000",
752 greenyellow: "#adff2f",
753 grey: "#808080",
754 honeydew: "#f0fff0",
755 hotpink: "#ff69b4",
756 indianred: "#cd5c5c",
757 indigo: "#4b0082",
758 ivory: "#fffff0",
759 khaki: "#f0e68c",
760 lavender: "#e6e6fa",
761 lavenderblush: "#fff0f5",
762 lawngreen: "#7cfc00",
763 lemonchiffon: "#fffacd",
764 lightblue: "#add8e6",
765 lightcoral: "#f08080",
766 lightcyan: "#e0ffff",
767 lightgoldenrodyellow: "#fafad2",
768 lightgray: "#d3d3d3",
769 lightgreen: "#90ee90",
770 lightgrey: "#d3d3d3",
771 lightpink: "#ffb6c1",
772 lightsalmon: "#ffa07a",
773 lightseagreen: "#20b2aa",
774 lightskyblue: "#87cefa",
775 lightslategray: "#778899",
776 lightslategrey: "#778899",
777 lightsteelblue: "#b0c4de",
778 lightyellow: "#ffffe0",
779 lime: "#00ff00",
780 limegreen: "#32cd32",
781 linen: "#faf0e6",
782 magenta: "#ff00ff",
783 maroon: "#800000",
784 mediumaquamarine: "#66cdaa",
785 mediumblue: "#0000cd",
786 mediumorchid: "#ba55d3",
787 mediumpurple: "#9370db",
788 mediumseagreen: "#3cb371",
789 mediumslateblue: "#7b68ee",
790 mediumspringgreen: "#00fa9a",
791 mediumturquoise: "#48d1cc",
792 mediumvioletred: "#c71585",
793 midnightblue: "#191970",
794 mintcream: "#f5fffa",
795 mistyrose: "#ffe4e1",
796 moccasin: "#ffe4b5",
797 navajowhite: "#ffdead",
798 navy: "#000080",
799 oldlace: "#fdf5e6",
800 olive: "#808000",
801 olivedrab: "#6b8e23",
802 orange: "#ffa500",
803 orangered: "#ff4500",
804 orchid: "#da70d6",
805 palegoldenrod: "#eee8aa",
806 palegreen: "#98fb98",
807 paleturquoise: "#afeeee",
808 palevioletred: "#db7093",
809 papayawhip: "#ffefd5",
810 peachpuff: "#ffdab9",
811 peru: "#cd853f",
812 pink: "#ffc0cb",
813 plum: "#dda0dd",
814 powderblue: "#b0e0e6",
815 purple: "#800080",
816 red: "#ff0000",
817 rosybrown: "#bc8f8f",
818 royalblue: "#4169e1",
819 saddlebrown: "#8b4513",
820 salmon: "#fa8072",
821 sandybrown: "#f4a460",
822 seagreen: "#2e8b57",
823 seashell: "#fff5ee",
824 sienna: "#a0522d",
825 silver: "#c0c0c0",
826 skyblue: "#87ceeb",
827 slateblue: "#6a5acd",
828 slategray: "#708090",
829 slategrey: "#708090",
830 snow: "#fffafa",
831 springgreen: "#00ff7f",
832 steelblue: "#4682b4",
833 tan: "#d2b48c",
834 teal: "#008080",
835 thistle: "#d8bfd8",
836 tomato: "#ff6347",
837 turquoise: "#40e0d0",
838 violet: "#ee82ee",
839 wheat: "#f5deb3",
840 white: "#ffffff",
841 whitesmoke: "#f5f5f5",
842 yellow: "#ffff00",
843 yellowgreen: "#9acd32"
844};
845
846MochiKit.Base._exportSymbols(this, MochiKit.Color);
diff --git a/frontend/delta/js/MochiKit/DOM.js b/frontend/delta/js/MochiKit/DOM.js
new file mode 100644
index 0000000..23d996b
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/DOM.js
@@ -0,0 +1,1202 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.DOM 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'DOM', '1.5', ['Base']);
35
36MochiKit.Base.update(MochiKit.DOM, {
37
38 /** @id MochiKit.DOM.currentWindow */
39 currentWindow: function () {
40 return MochiKit.DOM._window;
41 },
42
43 /** @id MochiKit.DOM.currentDocument */
44 currentDocument: function () {
45 return MochiKit.DOM._document;
46 },
47
48 /** @id MochiKit.DOM.withWindow */
49 withWindow: function (win, func) {
50 var self = MochiKit.DOM;
51 var oldDoc = self._document;
52 var oldWin = self._window;
53 var rval;
54 try {
55 self._window = win;
56 self._document = win.document;
57 rval = func();
58 } catch (e) {
59 self._window = oldWin;
60 self._document = oldDoc;
61 throw e;
62 }
63 self._window = oldWin;
64 self._document = oldDoc;
65 return rval;
66 },
67
68 /** @id MochiKit.DOM.formContents */
69 formContents: function (elem/* = document.body */) {
70 var names = [];
71 var values = [];
72 var m = MochiKit.Base;
73 var self = MochiKit.DOM;
74 if (typeof(elem) == "undefined" || elem === null) {
75 elem = self._document.body;
76 } else {
77 elem = self.getElement(elem);
78 }
79 m.nodeWalk(elem, function (elem) {
80 var name = elem.name;
81 if (m.isNotEmpty(name)) {
82 var tagName = elem.tagName.toUpperCase();
83 if (tagName === "INPUT"
84 && (elem.type == "radio" || elem.type == "checkbox")
85 && !elem.checked
86 ) {
87 return null;
88 }
89 if (tagName === "SELECT") {
90 if (elem.type == "select-one") {
91 if (elem.selectedIndex >= 0) {
92 var opt = elem.options[elem.selectedIndex];
93 var v = opt.value;
94 if (!v) {
95 var h = opt.outerHTML;
96 // internet explorer sure does suck.
97 if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
98 v = opt.text;
99 }
100 }
101 names.push(name);
102 values.push(v);
103 return null;
104 }
105 // no form elements?
106 names.push(name);
107 values.push("");
108 return null;
109 } else {
110 var opts = elem.options;
111 if (!opts.length) {
112 names.push(name);
113 values.push("");
114 return null;
115 }
116 for (var i = 0; i < opts.length; i++) {
117 var opt = opts[i];
118 if (!opt.selected) {
119 continue;
120 }
121 var v = opt.value;
122 if (!v) {
123 var h = opt.outerHTML;
124 // internet explorer sure does suck.
125 if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
126 v = opt.text;
127 }
128 }
129 names.push(name);
130 values.push(v);
131 }
132 return null;
133 }
134 }
135 if (tagName === "FORM" || tagName === "P" || tagName === "SPAN"
136 || tagName === "DIV"
137 ) {
138 return elem.childNodes;
139 }
140 names.push(name);
141 values.push(elem.value || '');
142 return null;
143 }
144 return elem.childNodes;
145 });
146 return [names, values];
147 },
148
149 /** @id MochiKit.DOM.withDocument */
150 withDocument: function (doc, func) {
151 var self = MochiKit.DOM;
152 var oldDoc = self._document;
153 var rval;
154 try {
155 self._document = doc;
156 rval = func();
157 } catch (e) {
158 self._document = oldDoc;
159 throw e;
160 }
161 self._document = oldDoc;
162 return rval;
163 },
164
165 /** @id MochiKit.DOM.registerDOMConverter */
166 registerDOMConverter: function (name, check, wrap, /* optional */override) {
167 MochiKit.DOM.domConverters.register(name, check, wrap, override);
168 },
169
170 /** @id MochiKit.DOM.coerceToDOM */
171 coerceToDOM: function (node, ctx) {
172 var m = MochiKit.Base;
173 var im = MochiKit.Iter;
174 var self = MochiKit.DOM;
175 if (im) {
176 var iter = im.iter;
177 var repeat = im.repeat;
178 }
179 var map = m.map;
180 var domConverters = self.domConverters;
181 var coerceToDOM = arguments.callee;
182 var NotFound = m.NotFound;
183 while (true) {
184 if (typeof(node) == 'undefined' || node === null) {
185 return null;
186 }
187 // this is a safari childNodes object, avoiding crashes w/ attr
188 // lookup
189 if (typeof(node) == "function" &&
190 typeof(node.length) == "number" &&
191 !(node instanceof Function)) {
192 node = im ? im.list(node) : m.extend(null, node);
193 }
194 if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) {
195 return node;
196 }
197 if (typeof(node) == 'number' || typeof(node) == 'boolean') {
198 node = node.toString();
199 // FALL THROUGH
200 }
201 if (typeof(node) == 'string') {
202 return self._document.createTextNode(node);
203 }
204 if (typeof(node.__dom__) == 'function') {
205 node = node.__dom__(ctx);
206 continue;
207 }
208 if (typeof(node.dom) == 'function') {
209 node = node.dom(ctx);
210 continue;
211 }
212 if (typeof(node) == 'function') {
213 node = node.apply(ctx, [ctx]);
214 continue;
215 }
216
217 if (im) {
218 // iterable
219 var iterNodes = null;
220 try {
221 iterNodes = iter(node);
222 } catch (e) {
223 // pass
224 }
225 if (iterNodes) {
226 return map(coerceToDOM, iterNodes, repeat(ctx));
227 }
228 } else if (m.isArrayLike(node)) {
229 var func = function (n) { return coerceToDOM(n, ctx); };
230 return map(func, node);
231 }
232
233 // adapter
234 try {
235 node = domConverters.match(node, ctx);
236 continue;
237 } catch (e) {
238 if (e != NotFound) {
239 throw e;
240 }
241 }
242
243 // fallback
244 return self._document.createTextNode(node.toString());
245 }
246 // mozilla warnings aren't too bright
247 return undefined;
248 },
249
250 /** @id MochiKit.DOM.isChildNode */
251 isChildNode: function (node, maybeparent) {
252 var self = MochiKit.DOM;
253 if (typeof(node) == "string") {
254 node = self.getElement(node);
255 }
256 if (typeof(maybeparent) == "string") {
257 maybeparent = self.getElement(maybeparent);
258 }
259 if (typeof(node) == 'undefined' || node === null) {
260 return false;
261 }
262 while (node != null && node !== self._document) {
263 if (node === maybeparent) {
264 return true;
265 }
266 node = node.parentNode;
267 }
268 return false;
269 },
270
271 /** @id MochiKit.DOM.setNodeAttribute */
272 setNodeAttribute: function (node, attr, value) {
273 var o = {};
274 o[attr] = value;
275 try {
276 return MochiKit.DOM.updateNodeAttributes(node, o);
277 } catch (e) {
278 // pass
279 }
280 return null;
281 },
282
283 /** @id MochiKit.DOM.getNodeAttribute */
284 getNodeAttribute: function (node, attr) {
285 var self = MochiKit.DOM;
286 var rename = self.attributeArray.renames[attr];
287 var ignoreValue = self.attributeArray.ignoreAttr[attr];
288 node = self.getElement(node);
289 try {
290 if (rename) {
291 return node[rename];
292 }
293 var value = node.getAttribute(attr);
294 if (value != ignoreValue) {
295 return value;
296 }
297 } catch (e) {
298 // pass
299 }
300 return null;
301 },
302
303 /** @id MochiKit.DOM.removeNodeAttribute */
304 removeNodeAttribute: function (node, attr) {
305 var self = MochiKit.DOM;
306 var rename = self.attributeArray.renames[attr];
307 node = self.getElement(node);
308 try {
309 if (rename) {
310 return node[rename];
311 }
312 return node.removeAttribute(attr);
313 } catch (e) {
314 // pass
315 }
316 return null;
317 },
318
319 /** @id MochiKit.DOM.updateNodeAttributes */
320 updateNodeAttributes: function (node, attrs) {
321 var elem = node;
322 var self = MochiKit.DOM;
323 var base = MochiKit.Base;
324 if (typeof(node) == 'string') {
325 elem = self.getElement(node);
326 }
327 if (attrs) {
328 if (self.attributeArray.compliant) {
329 // not IE, good.
330 for (var k in attrs) {
331 var v = attrs[k];
332 if (typeof(v) == 'object' && typeof(elem[k]) == 'object') {
333 if (k == "style" && MochiKit.Style) {
334 MochiKit.Style.setStyle(elem, v);
335 } else {
336 base.updatetree(elem[k], v);
337 }
338 } else if (k.substring(0, 2) == "on") {
339 if (typeof(v) == "string") {
340 v = new Function(v);
341 }
342 elem[k] = v;
343 } else {
344 elem.setAttribute(k, v);
345 }
346 if (base.isValue(elem[k]) && elem[k] != v) {
347 // Also set property for weird attributes (see #302 & #335)
348 elem[k] = v;
349 }
350 }
351 } else {
352 // IE is insane in the membrane
353 var renames = self.attributeArray.renames;
354 for (var k in attrs) {
355 v = attrs[k];
356 var renamed = renames[k];
357 if (k == "style" && typeof(v) == "string") {
358 elem.style.cssText = v;
359 } else if (typeof(renamed) == "string") {
360 elem[renamed] = v;
361 } else if (typeof(elem[k]) == 'object'
362 && typeof(v) == 'object') {
363 if (k == "style" && MochiKit.Style) {
364 MochiKit.Style.setStyle(elem, v);
365 } else {
366 base.updatetree(elem[k], v);
367 }
368 } else if (k.substring(0, 2) == "on") {
369 if (typeof(v) == "string") {
370 v = new Function(v);
371 }
372 elem[k] = v;
373 } else {
374 elem.setAttribute(k, v);
375 }
376 if (base.isValue(elem[k]) && elem[k] != v) {
377 // Also set property for weird attributes (see #302 & #335)
378 elem[k] = v;
379 }
380 }
381 }
382 }
383 return elem;
384 },
385
386 /** @id MochiKit.DOM.appendChildNodes */
387 appendChildNodes: function (node/*, nodes...*/) {
388 var elem = node;
389 var self = MochiKit.DOM;
390 if (typeof(node) == 'string') {
391 elem = self.getElement(node);
392 }
393 var nodeStack = [
394 self.coerceToDOM(
395 MochiKit.Base.extend(null, arguments, 1),
396 elem
397 )
398 ];
399 var concat = MochiKit.Base.concat;
400 while (nodeStack.length) {
401 var n = nodeStack.shift();
402 if (typeof(n) == 'undefined' || n === null) {
403 // pass
404 } else if (typeof(n.nodeType) == 'number') {
405 elem.appendChild(n);
406 } else {
407 nodeStack = concat(n, nodeStack);
408 }
409 }
410 return elem;
411 },
412
413
414 /** @id MochiKit.DOM.insertSiblingNodesBefore */
415 insertSiblingNodesBefore: function (node/*, nodes...*/) {
416 var elem = node;
417 var self = MochiKit.DOM;
418 if (typeof(node) == 'string') {
419 elem = self.getElement(node);
420 }
421 var nodeStack = [
422 self.coerceToDOM(
423 MochiKit.Base.extend(null, arguments, 1),
424 elem
425 )
426 ];
427 var parentnode = elem.parentNode;
428 var concat = MochiKit.Base.concat;
429 while (nodeStack.length) {
430 var n = nodeStack.shift();
431 if (typeof(n) == 'undefined' || n === null) {
432 // pass
433 } else if (typeof(n.nodeType) == 'number') {
434 parentnode.insertBefore(n, elem);
435 } else {
436 nodeStack = concat(n, nodeStack);
437 }
438 }
439 return parentnode;
440 },
441
442 /** @id MochiKit.DOM.insertSiblingNodesAfter */
443 insertSiblingNodesAfter: function (node/*, nodes...*/) {
444 var elem = node;
445 var self = MochiKit.DOM;
446
447 if (typeof(node) == 'string') {
448 elem = self.getElement(node);
449 }
450 var nodeStack = [
451 self.coerceToDOM(
452 MochiKit.Base.extend(null, arguments, 1),
453 elem
454 )
455 ];
456
457 if (elem.nextSibling) {
458 return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack);
459 }
460 else {
461 return self.appendChildNodes(elem.parentNode, nodeStack);
462 }
463 },
464
465 /** @id MochiKit.DOM.replaceChildNodes */
466 replaceChildNodes: function (node/*, nodes...*/) {
467 var elem = node;
468 var self = MochiKit.DOM;
469 if (typeof(node) == 'string') {
470 elem = self.getElement(node);
471 arguments[0] = elem;
472 }
473 var child;
474 while ((child = elem.firstChild)) {
475 elem.removeChild(child);
476 }
477 if (arguments.length < 2) {
478 return elem;
479 } else {
480 return self.appendChildNodes.apply(this, arguments);
481 }
482 },
483
484 /** @id MochiKit.DOM.createDOM */
485 createDOM: function (name, attrs/*, nodes... */) {
486 var elem;
487 var self = MochiKit.DOM;
488 var m = MochiKit.Base;
489 if (typeof(attrs) == "string" || typeof(attrs) == "number") {
490 var args = m.extend([name, null], arguments, 1);
491 return arguments.callee.apply(this, args);
492 }
493 if (typeof(name) == 'string') {
494 // Internet Explorer is dumb
495 var xhtml = self._xhtml;
496 if (attrs && !self.attributeArray.compliant) {
497 // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp
498 var contents = "";
499 if ('name' in attrs) {
500 contents += ' name="' + self.escapeHTML(attrs.name) + '"';
501 }
502 if (name == 'input' && 'type' in attrs) {
503 contents += ' type="' + self.escapeHTML(attrs.type) + '"';
504 }
505 if (contents) {
506 name = "<" + name + contents + ">";
507 xhtml = false;
508 }
509 }
510 var d = self._document;
511 if (xhtml && d === document) {
512 elem = d.createElementNS("http://www.w3.org/1999/xhtml", name);
513 } else {
514 elem = d.createElement(name);
515 }
516 } else {
517 elem = name;
518 }
519 if (attrs) {
520 self.updateNodeAttributes(elem, attrs);
521 }
522 if (arguments.length <= 2) {
523 return elem;
524 } else {
525 var args = m.extend([elem], arguments, 2);
526 return self.appendChildNodes.apply(this, args);
527 }
528 },
529
530 /** @id MochiKit.DOM.createDOMFunc */
531 createDOMFunc: function (/* tag, attrs, *nodes */) {
532 var m = MochiKit.Base;
533 return m.partial.apply(
534 this,
535 m.extend([MochiKit.DOM.createDOM], arguments)
536 );
537 },
538
539 /** @id MochiKit.DOM.removeElement */
540 removeElement: function (elem) {
541 var self = MochiKit.DOM;
542 if (typeof(elem) == "string") {
543 elem = self.getElement(elem);
544 }
545 var e = self.coerceToDOM(elem);
546 e.parentNode.removeChild(e);
547 return e;
548 },
549
550 /** @id MochiKit.DOM.swapDOM */
551 swapDOM: function (dest, src) {
552 var self = MochiKit.DOM;
553 dest = self.getElement(dest);
554 var parent = dest.parentNode;
555 if (src) {
556 if (typeof(src) == "string") {
557 src = self.getElement(src);
558 }
559 src = self.coerceToDOM(src, parent);
560 parent.replaceChild(src, dest);
561 } else {
562 parent.removeChild(dest);
563 }
564 return src;
565 },
566
567 /** @id MochiKit.DOM.getElement */
568 getElement: function (id) {
569 var self = MochiKit.DOM;
570 if (arguments.length == 1) {
571 return ((typeof(id) == "string") ?
572 self._document.getElementById(id) : id);
573 } else {
574 return MochiKit.Base.map(self.getElement, arguments);
575 }
576 },
577
578 /** @id MochiKit.DOM.getElementsByTagAndClassName */
579 getElementsByTagAndClassName: function (tagName, className,
580 /* optional */parent) {
581 var self = MochiKit.DOM;
582 if (typeof(tagName) == 'undefined' || tagName === null) {
583 tagName = '*';
584 }
585 if (typeof(parent) == 'undefined' || parent === null) {
586 parent = self._document;
587 }
588 parent = self.getElement(parent);
589 if (parent == null) {
590 return [];
591 }
592 var children = (parent.getElementsByTagName(tagName)
593 || self._document.all);
594 if (typeof(className) == 'undefined' || className === null) {
595 return MochiKit.Base.extend(null, children);
596 }
597
598 var elements = [];
599 for (var i = 0; i < children.length; i++) {
600 var child = children[i];
601 var cls = child.className;
602 if (typeof(cls) != "string") {
603 cls = child.getAttribute("class");
604 }
605 if (typeof(cls) == "string") {
606 var classNames = cls.split(' ');
607 for (var j = 0; j < classNames.length; j++) {
608 if (classNames[j] == className) {
609 elements.push(child);
610 break;
611 }
612 }
613 }
614 }
615
616 return elements;
617 },
618
619 _newCallStack: function (path, once) {
620 var rval = function () {
621 var callStack = arguments.callee.callStack;
622 for (var i = 0; i < callStack.length; i++) {
623 if (callStack[i].apply(this, arguments) === false) {
624 break;
625 }
626 }
627 if (once) {
628 try {
629 this[path] = null;
630 } catch (e) {
631 // pass
632 }
633 }
634 };
635 rval.callStack = [];
636 return rval;
637 },
638
639 /** @id MochiKit.DOM.addToCallStack */
640 addToCallStack: function (target, path, func, once) {
641 var self = MochiKit.DOM;
642 var existing = target[path];
643 var regfunc = existing;
644 if (!(typeof(existing) == 'function'
645 && typeof(existing.callStack) == "object"
646 && existing.callStack !== null)) {
647 regfunc = self._newCallStack(path, once);
648 if (typeof(existing) == 'function') {
649 regfunc.callStack.push(existing);
650 }
651 target[path] = regfunc;
652 }
653 regfunc.callStack.push(func);
654 },
655
656 /** @id MochiKit.DOM.addLoadEvent */
657 addLoadEvent: function (func) {
658 var self = MochiKit.DOM;
659 self.addToCallStack(self._window, "onload", func, true);
660
661 },
662
663 /** @id MochiKit.DOM.focusOnLoad */
664 focusOnLoad: function (element) {
665 var self = MochiKit.DOM;
666 self.addLoadEvent(function () {
667 element = self.getElement(element);
668 if (element) {
669 element.focus();
670 }
671 });
672 },
673
674 /** @id MochiKit.DOM.setElementClass */
675 setElementClass: function (element, className) {
676 var self = MochiKit.DOM;
677 var obj = self.getElement(element);
678 if (self.attributeArray.compliant) {
679 obj.setAttribute("class", className);
680 } else {
681 obj.setAttribute("className", className);
682 }
683 },
684
685 /** @id MochiKit.DOM.toggleElementClass */
686 toggleElementClass: function (className/*, element... */) {
687 var self = MochiKit.DOM;
688 for (var i = 1; i < arguments.length; i++) {
689 var obj = self.getElement(arguments[i]);
690 if (!self.addElementClass(obj, className)) {
691 self.removeElementClass(obj, className);
692 }
693 }
694 },
695
696 /** @id MochiKit.DOM.addElementClass */
697 addElementClass: function (element, className) {
698 var self = MochiKit.DOM;
699 var obj = self.getElement(element);
700 var cls = obj.className;
701 if (typeof(cls) != "string") {
702 cls = obj.getAttribute("class");
703 }
704 // trivial case, no className yet
705 if (typeof(cls) != "string" || cls.length === 0) {
706 self.setElementClass(obj, className);
707 return true;
708 }
709 // the other trivial case, already set as the only class
710 if (cls == className) {
711 return false;
712 }
713 var classes = cls.split(" ");
714 for (var i = 0; i < classes.length; i++) {
715 // already present
716 if (classes[i] == className) {
717 return false;
718 }
719 }
720 // append class
721 self.setElementClass(obj, cls + " " + className);
722 return true;
723 },
724
725 /** @id MochiKit.DOM.removeElementClass */
726 removeElementClass: function (element, className) {
727 var self = MochiKit.DOM;
728 var obj = self.getElement(element);
729 var cls = obj.className;
730 if (typeof(cls) != "string") {
731 cls = obj.getAttribute("class");
732 }
733 // trivial case, no className yet
734 if (typeof(cls) != "string" || cls.length === 0) {
735 return false;
736 }
737 // other trivial case, set only to className
738 if (cls == className) {
739 self.setElementClass(obj, "");
740 return true;
741 }
742 var classes = cls.split(" ");
743 for (var i = 0; i < classes.length; i++) {
744 // already present
745 if (classes[i] == className) {
746 // only check sane case where the class is used once
747 classes.splice(i, 1);
748 self.setElementClass(obj, classes.join(" "));
749 return true;
750 }
751 }
752 // not found
753 return false;
754 },
755
756 /** @id MochiKit.DOM.swapElementClass */
757 swapElementClass: function (element, fromClass, toClass) {
758 var obj = MochiKit.DOM.getElement(element);
759 var res = MochiKit.DOM.removeElementClass(obj, fromClass);
760 if (res) {
761 MochiKit.DOM.addElementClass(obj, toClass);
762 }
763 return res;
764 },
765
766 /** @id MochiKit.DOM.hasElementClass */
767 hasElementClass: function (element, className/*...*/) {
768 var obj = MochiKit.DOM.getElement(element);
769 if (obj == null) {
770 return false;
771 }
772 var cls = obj.className;
773 if (typeof(cls) != "string" && typeof(obj.getAttribute) == "function") {
774 cls = obj.getAttribute("class");
775 }
776 if (typeof(cls) != "string") {
777 return false;
778 }
779 var classes = cls.split(" ");
780 for (var i = 1; i < arguments.length; i++) {
781 var good = false;
782 for (var j = 0; j < classes.length; j++) {
783 if (classes[j] == arguments[i]) {
784 good = true;
785 break;
786 }
787 }
788 if (!good) {
789 return false;
790 }
791 }
792 return true;
793 },
794
795 /** @id MochiKit.DOM.escapeHTML */
796 escapeHTML: function (s) {
797 return s.replace(/&/g, "&amp;"
798 ).replace(/"/g, "&quot;"
799 ).replace(/</g, "&lt;"
800 ).replace(/>/g, "&gt;");
801 },
802
803 /** @id MochiKit.DOM.toHTML */
804 toHTML: function (dom) {
805 return MochiKit.DOM.emitHTML(dom).join("");
806 },
807
808 /** @id MochiKit.DOM.emitHTML */
809 emitHTML: function (dom, /* optional */lst) {
810 if (typeof(lst) == 'undefined' || lst === null) {
811 lst = [];
812 }
813 // queue is the call stack, we're doing this non-recursively
814 var queue = [dom];
815 var self = MochiKit.DOM;
816 var escapeHTML = self.escapeHTML;
817 var attributeArray = self.attributeArray;
818 while (queue.length) {
819 dom = queue.pop();
820 if (typeof(dom) == 'string') {
821 lst.push(dom);
822 } else if (dom.nodeType == 1) {
823 // we're not using higher order stuff here
824 // because safari has heisenbugs.. argh.
825 //
826 // I think it might have something to do with
827 // garbage collection and function calls.
828 lst.push('<' + dom.tagName.toLowerCase());
829 var attributes = [];
830 var domAttr = attributeArray(dom);
831 for (var i = 0; i < domAttr.length; i++) {
832 var a = domAttr[i];
833 attributes.push([
834 " ",
835 a.name,
836 '="',
837 escapeHTML(a.value),
838 '"'
839 ]);
840 }
841 attributes.sort();
842 for (i = 0; i < attributes.length; i++) {
843 var attrs = attributes[i];
844 for (var j = 0; j < attrs.length; j++) {
845 lst.push(attrs[j]);
846 }
847 }
848 if (dom.hasChildNodes()) {
849 lst.push(">");
850 // queue is the FILO call stack, so we put the close tag
851 // on first
852 queue.push("</" + dom.tagName.toLowerCase() + ">");
853 var cnodes = dom.childNodes;
854 for (i = cnodes.length - 1; i >= 0; i--) {
855 queue.push(cnodes[i]);
856 }
857 } else {
858 lst.push('/>');
859 }
860 } else if (dom.nodeType == 3) {
861 lst.push(escapeHTML(dom.nodeValue));
862 }
863 }
864 return lst;
865 },
866
867 /** @id MochiKit.DOM.scrapeText */
868 scrapeText: function (node, /* optional */asArray) {
869 var rval = [];
870 (function (node) {
871 var cn = node.childNodes;
872 if (cn) {
873 for (var i = 0; i < cn.length; i++) {
874 arguments.callee.call(this, cn[i]);
875 }
876 }
877 var nodeValue = node.nodeValue;
878 if (typeof(nodeValue) == 'string') {
879 rval.push(nodeValue);
880 }
881 })(MochiKit.DOM.getElement(node));
882 if (asArray) {
883 return rval;
884 } else {
885 return rval.join("");
886 }
887 },
888
889 /** @id MochiKit.DOM.removeEmptyTextNodes */
890 removeEmptyTextNodes: function (element) {
891 element = MochiKit.DOM.getElement(element);
892 for (var i = 0; i < element.childNodes.length; i++) {
893 var node = element.childNodes[i];
894 if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
895 node.parentNode.removeChild(node);
896 }
897 }
898 },
899
900 /** @id MochiKit.DOM.getFirstElementByTagAndClassName */
901 getFirstElementByTagAndClassName: function (tagName, className,
902 /* optional */parent) {
903 var self = MochiKit.DOM;
904 if (typeof(tagName) == 'undefined' || tagName === null) {
905 tagName = '*';
906 }
907 if (typeof(parent) == 'undefined' || parent === null) {
908 parent = self._document;
909 }
910 parent = self.getElement(parent);
911 if (parent == null) {
912 return null;
913 }
914 var children = (parent.getElementsByTagName(tagName)
915 || self._document.all);
916 if (children.length <= 0) {
917 return null;
918 } else if (typeof(className) == 'undefined' || className === null) {
919 return children[0];
920 }
921
922 for (var i = 0; i < children.length; i++) {
923 var child = children[i];
924 var cls = child.className;
925 if (typeof(cls) != "string") {
926 cls = child.getAttribute("class");
927 }
928 if (typeof(cls) == "string") {
929 var classNames = cls.split(' ');
930 for (var j = 0; j < classNames.length; j++) {
931 if (classNames[j] == className) {
932 return child;
933 }
934 }
935 }
936 }
937 return null;
938 },
939
940 /** @id MochiKit.DOM.getFirstParentByTagAndClassName */
941 getFirstParentByTagAndClassName: function (elem, tagName, className) {
942 var self = MochiKit.DOM;
943 elem = self.getElement(elem);
944 if (typeof(tagName) == 'undefined' || tagName === null) {
945 tagName = '*';
946 } else {
947 tagName = tagName.toUpperCase();
948 }
949 if (typeof(className) == 'undefined' || className === null) {
950 className = null;
951 }
952 if (elem) {
953 elem = elem.parentNode;
954 }
955 while (elem && elem.tagName) {
956 var curTagName = elem.tagName.toUpperCase();
957 if ((tagName === '*' || tagName == curTagName) &&
958 (className === null || self.hasElementClass(elem, className))) {
959 return elem;
960 }
961 elem = elem.parentNode;
962 }
963 return null;
964 },
965
966 __new__: function (win) {
967
968 var m = MochiKit.Base;
969 if (typeof(document) != "undefined") {
970 this._document = document;
971 var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
972 this._xhtml = (document.documentElement &&
973 document.createElementNS &&
974 document.documentElement.namespaceURI === kXULNSURI);
975 } else if (MochiKit.MockDOM) {
976 this._document = MochiKit.MockDOM.document;
977 }
978 this._window = win;
979
980 this.domConverters = new m.AdapterRegistry();
981
982 var __tmpElement = this._document.createElement("span");
983 var attributeArray;
984 if (__tmpElement && __tmpElement.attributes &&
985 __tmpElement.attributes.length > 0) {
986 // for braindead browsers (IE) that insert extra junk
987 var filter = m.filter;
988 attributeArray = function (node) {
989 /***
990
991 Return an array of attributes for a given node,
992 filtering out attributes that don't belong for
993 that are inserted by "Certain Browsers".
994
995 ***/
996 return filter(attributeArray.ignoreAttrFilter, node.attributes);
997 };
998 attributeArray.ignoreAttr = {};
999 var attrs = __tmpElement.attributes;
1000 var ignoreAttr = attributeArray.ignoreAttr;
1001 for (var i = 0; i < attrs.length; i++) {
1002 var a = attrs[i];
1003 ignoreAttr[a.name] = a.value;
1004 }
1005 attributeArray.ignoreAttrFilter = function (a) {
1006 return (attributeArray.ignoreAttr[a.name] != a.value);
1007 };
1008 attributeArray.compliant = false;
1009 attributeArray.renames = {
1010 "class": "className",
1011 "checked": "defaultChecked",
1012 "usemap": "useMap",
1013 "for": "htmlFor",
1014 "readonly": "readOnly",
1015 "colspan": "colSpan",
1016 "rowspan": "rowSpan",
1017 "bgcolor": "bgColor",
1018 "cellspacing": "cellSpacing",
1019 "cellpadding": "cellPadding"
1020 };
1021 } else {
1022 attributeArray = function (node) {
1023 return node.attributes;
1024 };
1025 attributeArray.compliant = true;
1026 attributeArray.ignoreAttr = {};
1027 attributeArray.renames = {};
1028 }
1029 attributeArray.__export__ = false;
1030 this.attributeArray = attributeArray;
1031
1032 // Backwards compatibility aliases
1033 /** @id MochiKit.DOM.computedStyle */
1034 m._deprecated(this, 'computedStyle', 'MochiKit.Style.getStyle', '1.4', true);
1035 /** @id MochiKit.DOM.elementDimensions */
1036 m._deprecated(this, 'elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4');
1037 /** @id MochiKit.DOM.elementPosition */
1038 m._deprecated(this, 'elementPosition', 'MochiKit.Style.getElementPosition', '1.4');
1039 /** @id MochiKit.DOM.getViewportDimensions */
1040 m._deprecated(this, 'getViewportDimensions', 'MochiKit.Style.getViewportDimensions', '1.4');
1041 /** @id MochiKit.DOM.hideElement */
1042 m._deprecated(this, 'hideElement', 'MochiKit.Style.hideElement', '1.4');
1043 /** @id MochiKit.DOM.makeClipping */
1044 m._deprecated(this, 'makeClipping', 'MochiKit.Style.makeClipping', '1.4.1');
1045 /** @id MochiKit.DOM.makePositioned */
1046 m._deprecated(this, 'makePositioned', 'MochiKit.Style.makePositioned', '1.4.1');
1047 /** @id MochiKit.DOM.setElementDimensions */
1048 m._deprecated(this, 'setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4');
1049 /** @id MochiKit.DOM.setElementPosition */
1050 m._deprecated(this, 'setElementPosition', 'MochiKit.Style.setElementPosition', '1.4');
1051 /** @id MochiKit.DOM.setDisplayForElement */
1052 m._deprecated(this, 'setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4');
1053 /** @id MochiKit.DOM.setOpacity */
1054 m._deprecated(this, 'setOpacity', 'MochiKit.Style.setOpacity', '1.4');
1055 /** @id MochiKit.DOM.showElement */
1056 m._deprecated(this, 'showElement', 'MochiKit.Style.showElement', '1.4');
1057 /** @id MochiKit.DOM.undoClipping */
1058 m._deprecated(this, 'undoClipping', 'MochiKit.Style.undoClipping', '1.4.1');
1059 /** @id MochiKit.DOM.undoPositioned */
1060 m._deprecated(this, 'undoPositioned', 'MochiKit.Style.undoPositioned', '1.4.1');
1061 /** @id MochiKit.DOM.Coordinates */
1062 m._deprecated(this, 'Coordinates', 'MochiKit.Style.Coordinates', '1.4');
1063 /** @id MochiKit.DOM.Dimensions */
1064 m._deprecated(this, 'Dimensions', 'MochiKit.Style.Dimensions', '1.4');
1065
1066 // shorthand for createDOM syntax
1067 var createDOMFunc = this.createDOMFunc;
1068 /** @id MochiKit.DOM.A */
1069 this.A = createDOMFunc("a");
1070 /** @id MochiKit.DOM.ARTICLE */
1071 this.ARTICLE = createDOMFunc("article");
1072 /** @id MochiKit.DOM.ASIDE */
1073 this.ASIDE = createDOMFunc("aside");
1074 /** @id MochiKit.DOM.BR */
1075 this.BR = createDOMFunc("br");
1076 /** @id MochiKit.DOM.BUTTON */
1077 this.BUTTON = createDOMFunc("button");
1078 /** @id MochiKit.DOM.CANVAS */
1079 this.CANVAS = createDOMFunc("canvas");
1080 /** @id MochiKit.DOM.CAPTION */
1081 this.CAPTION = createDOMFunc("caption");
1082 /** @id MochiKit.DOM.DD */
1083 this.DD = createDOMFunc("dd");
1084 /** @id MochiKit.DOM.DIV */
1085 this.DIV = createDOMFunc("div");
1086 /** @id MochiKit.DOM.DL */
1087 this.DL = createDOMFunc("dl");
1088 /** @id MochiKit.DOM.DT */
1089 this.DT = createDOMFunc("dt");
1090 /** @id MochiKit.DOM.FIELDSET */
1091 this.FIELDSET = createDOMFunc("fieldset");
1092 /** @id MochiKit.DOM.FIGURE */
1093 this.FIGURE = createDOMFunc("figure");
1094 /** @id MochiKit.DOM.FIGCAPTION */
1095 this.FIGCAPTION = createDOMFunc("figcaption");
1096 /** @id MochiKit.DOM.FOOTER */
1097 this.FOOTER = createDOMFunc("footer");
1098 /** @id MochiKit.DOM.FORM */
1099 this.FORM = createDOMFunc("form");
1100 /** @id MochiKit.DOM.H1 */
1101 this.H1 = createDOMFunc("h1");
1102 /** @id MochiKit.DOM.H2 */
1103 this.H2 = createDOMFunc("h2");
1104 /** @id MochiKit.DOM.H3 */
1105 this.H3 = createDOMFunc("h3");
1106 /** @id MochiKit.DOM.H4 */
1107 this.H4 = createDOMFunc("h4");
1108 /** @id MochiKit.DOM.H5 */
1109 this.H5 = createDOMFunc("h5");
1110 /** @id MochiKit.DOM.H6 */
1111 this.H6 = createDOMFunc("h6");
1112 /** @id MochiKit.DOM.HEADER */
1113 this.HEADER = createDOMFunc("header");
1114 /** @id MochiKit.DOM.HGROUP */
1115 this.HGROUP = createDOMFunc("hgroup");
1116 /** @id MochiKit.DOM.HR */
1117 this.HR = createDOMFunc("hr");
1118 /** @id MochiKit.DOM.IFRAME */
1119 this.IFRAME = createDOMFunc("iframe");
1120 /** @id MochiKit.DOM.IMG */
1121 this.IMG = createDOMFunc("img");
1122 /** @id MochiKit.DOM.INPUT */
1123 this.INPUT = createDOMFunc("input");
1124 /** @id MochiKit.DOM.LABEL */
1125 this.LABEL = createDOMFunc("label");
1126 /** @id MochiKit.DOM.LEGEND */
1127 this.LEGEND = createDOMFunc("legend");
1128 /** @id MochiKit.DOM.LI */
1129 this.LI = createDOMFunc("li");
1130 /** @id MochiKit.DOM.LINK */
1131 this.LINK = createDOMFunc("link");
1132 /** @id MochiKit.DOM.MARK */
1133 this.MARK = createDOMFunc("mark");
1134 /** @id MochiKit.DOM.METER */
1135 this.METER = createDOMFunc("meter");
1136 /** @id MochiKit.DOM.NAV */
1137 this.NAV = createDOMFunc("nav");
1138 /** @id MochiKit.DOM.OL */
1139 this.OL = createDOMFunc("ol");
1140 /** @id MochiKit.DOM.OPTGROUP */
1141 this.OPTGROUP = createDOMFunc("optgroup");
1142 /** @id MochiKit.DOM.OPTION */
1143 this.OPTION = createDOMFunc("option");
1144 /** @id MochiKit.DOM.P */
1145 this.P = createDOMFunc("p");
1146 /** @id MochiKit.DOM.PRE */
1147 this.PRE = createDOMFunc("pre");
1148 /** @id MochiKit.DOM.PROGRESS */
1149 this.PROGRESS = createDOMFunc("progress");
1150 /** @id MochiKit.DOM.SCRIPT */
1151 this.SCRIPT = createDOMFunc("script");
1152 /** @id MochiKit.DOM.SECTION */
1153 this.SECTION = createDOMFunc("section");
1154 /** @id MochiKit.DOM.SELECT */
1155 this.SELECT = createDOMFunc("select");
1156 /** @id MochiKit.DOM.SPAN */
1157 this.SPAN = createDOMFunc("span");
1158 /** @id MochiKit.DOM.STRONG */
1159 this.STRONG = createDOMFunc("strong");
1160 /** @id MochiKit.DOM.STYLE */
1161 this.STYLE = createDOMFunc("style");
1162 /** @id MochiKit.DOM.TABLE */
1163 this.TABLE = createDOMFunc("table");
1164 /** @id MochiKit.DOM.TBODY */
1165 this.TBODY = createDOMFunc("tbody");
1166 /** @id MochiKit.DOM.TD */
1167 this.TD = createDOMFunc("td");
1168 /** @id MochiKit.DOM.TEXTAREA */
1169 this.TEXTAREA = createDOMFunc("textarea");
1170 /** @id MochiKit.DOM.TFOOT */
1171 this.TFOOT = createDOMFunc("tfoot");
1172 /** @id MochiKit.DOM.TH */
1173 this.TH = createDOMFunc("th");
1174 /** @id MochiKit.DOM.THEAD */
1175 this.THEAD = createDOMFunc("thead");
1176 /** @id MochiKit.DOM.TR */
1177 this.TR = createDOMFunc("tr");
1178 /** @id MochiKit.DOM.TT */
1179 this.TT = createDOMFunc("tt");
1180 /** @id MochiKit.DOM.UL */
1181 this.UL = createDOMFunc("ul");
1182 /** @id MochiKit.DOM.NBSP */
1183 this.NBSP = "\u00a0";
1184 /** @id MochiKit.DOM.$ */
1185 this.$ = this.getElement;
1186
1187 m.nameFunctions(this);
1188 }
1189});
1190
1191
1192MochiKit.DOM.__new__(((typeof(window) == "undefined") ? this : window));
1193
1194//
1195// XXX: Internet Explorer blows
1196//
1197if (MochiKit.__export__) {
1198 withWindow = MochiKit.DOM.withWindow;
1199 withDocument = MochiKit.DOM.withDocument;
1200}
1201
1202MochiKit.Base._exportSymbols(this, MochiKit.DOM);
diff --git a/frontend/delta/js/MochiKit/DateTime.js b/frontend/delta/js/MochiKit/DateTime.js
new file mode 100644
index 0000000..24ca087
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/DateTime.js
@@ -0,0 +1,199 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.DateTime 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'DateTime', '1.5', ['Base']);
35
36/** @id MochiKit.DateTime.isoDate */
37MochiKit.DateTime.isoDate = function (str) {
38 str = str + "";
39 if (typeof(str) != "string" || str.length === 0) {
40 return null;
41 }
42 var iso = str.split('-');
43 if (iso.length === 0) {
44 return null;
45 }
46 var date = new Date(parseInt(iso[0], 10), parseInt(iso[1], 10) - 1, parseInt(iso[2], 10));
47 date.setFullYear(iso[0]);
48 date.setMonth(iso[1] - 1);
49 date.setDate(iso[2]);
50 return date;
51};
52
53MochiKit.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}))?)?)?)?)?/;
54
55/** @id MochiKit.DateTime.isoTimestamp */
56MochiKit.DateTime.isoTimestamp = function (str) {
57 str = str + "";
58 if (typeof(str) != "string" || str.length === 0) {
59 return null;
60 }
61 var res = str.match(MochiKit.DateTime._isoRegexp);
62 if (typeof(res) == "undefined" || res === null) {
63 return null;
64 }
65 var year, month, day, hour, min, sec, msec;
66 year = parseInt(res[1], 10);
67 if (typeof(res[2]) == "undefined" || res[2] === '') {
68 return new Date(year);
69 }
70 month = parseInt(res[2], 10) - 1;
71 day = parseInt(res[3], 10);
72 if (typeof(res[4]) == "undefined" || res[4] === '') {
73 return new Date(year, month, day);
74 }
75 hour = parseInt(res[4], 10);
76 min = parseInt(res[5], 10);
77 sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0;
78 if (typeof(res[7]) != "undefined" && res[7] !== '') {
79 msec = Math.round(1000.0 * parseFloat("0." + res[7]));
80 } else {
81 msec = 0;
82 }
83 if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) {
84 return new Date(year, month, day, hour, min, sec, msec);
85 }
86 var ofs;
87 if (typeof(res[9]) != "undefined" && res[9] !== '') {
88 ofs = parseInt(res[10], 10) * 3600000;
89 if (typeof(res[11]) != "undefined" && res[11] !== '') {
90 ofs += parseInt(res[11], 10) * 60000;
91 }
92 if (res[9] == "-") {
93 ofs = -ofs;
94 }
95 } else {
96 ofs = 0;
97 }
98 return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs);
99};
100
101/** @id MochiKit.DateTime.toISOTime */
102MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) {
103 if (typeof(date) == "undefined" || date === null) {
104 return null;
105 }
106 var _padTwo = MochiKit.DateTime._padTwo;
107 if (realISO) {
108 // adjust date for UTC timezone
109 date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
110 }
111 var lst = [
112 (realISO ? _padTwo(date.getHours()) : date.getHours()),
113 _padTwo(date.getMinutes()),
114 _padTwo(date.getSeconds())
115 ];
116 return lst.join(":") + (realISO ? "Z" : "");
117};
118
119/** @id MochiKit.DateTime.toISOTimeStamp */
120MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) {
121 if (typeof(date) == "undefined" || date === null) {
122 return null;
123 }
124 var time = MochiKit.DateTime.toISOTime(date, realISO);
125 var sep = realISO ? "T" : " ";
126 if (realISO) {
127 // adjust date for UTC timezone
128 date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
129 }
130 return MochiKit.DateTime.toISODate(date) + sep + time;
131};
132
133/** @id MochiKit.DateTime.toISODate */
134MochiKit.DateTime.toISODate = function (date) {
135 if (typeof(date) == "undefined" || date === null) {
136 return null;
137 }
138 var _padTwo = MochiKit.DateTime._padTwo;
139 var _padFour = MochiKit.DateTime._padFour;
140 return [
141 _padFour(date.getFullYear()),
142 _padTwo(date.getMonth() + 1),
143 _padTwo(date.getDate())
144 ].join("-");
145};
146
147/** @id MochiKit.DateTime.americanDate */
148MochiKit.DateTime.americanDate = function (d) {
149 d = d + "";
150 if (typeof(d) != "string" || d.length === 0) {
151 return null;
152 }
153 var a = d.split('/');
154 return new Date(a[2], a[0] - 1, a[1]);
155};
156
157MochiKit.DateTime._padTwo = function (n) {
158 return (n > 9) ? n : "0" + n;
159};
160
161MochiKit.DateTime._padFour = function(n) {
162 switch(n.toString().length) {
163 case 1: return "000" + n; break;
164 case 2: return "00" + n; break;
165 case 3: return "0" + n; break;
166 case 4:
167 default:
168 return n;
169 }
170};
171
172/** @id MochiKit.DateTime.toPaddedAmericanDate */
173MochiKit.DateTime.toPaddedAmericanDate = function (d) {
174 if (typeof(d) == "undefined" || d === null) {
175 return null;
176 }
177 var _padTwo = MochiKit.DateTime._padTwo;
178 return [
179 _padTwo(d.getMonth() + 1),
180 _padTwo(d.getDate()),
181 d.getFullYear()
182 ].join('/');
183};
184
185/** @id MochiKit.DateTime.toAmericanDate */
186MochiKit.DateTime.toAmericanDate = function (d) {
187 if (typeof(d) == "undefined" || d === null) {
188 return null;
189 }
190 return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/');
191};
192
193MochiKit.DateTime.__new__ = function () {
194 MochiKit.Base.nameFunctions(this);
195};
196
197MochiKit.DateTime.__new__();
198
199MochiKit.Base._exportSymbols(this, MochiKit.DateTime);
diff --git a/frontend/delta/js/MochiKit/DragAndDrop.js b/frontend/delta/js/MochiKit/DragAndDrop.js
new file mode 100644
index 0000000..850e6bb
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/DragAndDrop.js
@@ -0,0 +1,789 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25MochiKit.DragAndDrop 1.5
26
27See <http://mochikit.com/> for documentation, downloads, license, etc.
28
29Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
30 Mochi-ized By Thomas Herve (_firstname_@nimail.org)
31
32***/
33
34MochiKit.Base.module(MochiKit, 'DragAndDrop', '1.5', ['Base', 'Iter', 'DOM', 'Signal', 'Visual', 'Position']);
35
36MochiKit.DragAndDrop.Droppables = {
37 /***
38
39 Manage all droppables. Shouldn't be used, use the Droppable object instead.
40
41 ***/
42 drops: [],
43
44 remove: function (element) {
45 this.drops = MochiKit.Base.filter(function (d) {
46 return d.element != MochiKit.DOM.getElement(element);
47 }, this.drops);
48 },
49
50 register: function (drop) {
51 this.drops.push(drop);
52 },
53
54 unregister: function (drop) {
55 this.drops = MochiKit.Base.filter(function (d) {
56 return d != drop;
57 }, this.drops);
58 },
59
60 prepare: function (element) {
61 MochiKit.Base.map(function (drop) {
62 if (drop.isAccepted(element)) {
63 if (drop.options.activeclass) {
64 MochiKit.DOM.addElementClass(drop.element,
65 drop.options.activeclass);
66 }
67 drop.options.onactive(drop.element, element);
68 }
69 }, this.drops);
70 },
71
72 findDeepestChild: function (drops) {
73 var deepest = drops[0];
74
75 for (var i = 1; i < drops.length; ++i) {
76 if (MochiKit.DOM.isChildNode(drops[i].element, deepest.element)) {
77 deepest = drops[i];
78 }
79 }
80 return deepest;
81 },
82
83 show: function (point, element) {
84 if (!this.drops.length) {
85 return;
86 }
87 var affected = [];
88
89 if (this.last_active) {
90 this.last_active.deactivate();
91 }
92 MochiKit.Iter.forEach(this.drops, function (drop) {
93 if (drop.isAffected(point, element)) {
94 affected.push(drop);
95 }
96 });
97 if (affected.length > 0) {
98 var drop = this.findDeepestChild(affected);
99 MochiKit.Position.within(drop.element, point.page.x, point.page.y);
100 drop.options.onhover(element, drop.element,
101 MochiKit.Position.overlap(drop.options.overlap, drop.element));
102 drop.activate();
103 }
104 },
105
106 fire: function (event, element) {
107 if (!this.last_active) {
108 return;
109 }
110 MochiKit.Position.prepare();
111
112 if (this.last_active.isAffected(event.mouse(), element)) {
113 this.last_active.options.ondrop(element,
114 this.last_active.element, event);
115 }
116 },
117
118 reset: function (element) {
119 MochiKit.Base.map(function (drop) {
120 if (drop.options.activeclass) {
121 MochiKit.DOM.removeElementClass(drop.element,
122 drop.options.activeclass);
123 }
124 drop.options.ondesactive(drop.element, element);
125 }, this.drops);
126 if (this.last_active) {
127 this.last_active.deactivate();
128 }
129 }
130};
131
132/** @id MochiKit.DragAndDrop.Droppable */
133MochiKit.DragAndDrop.Droppable = function (element, options) {
134 var cls = arguments.callee;
135 if (!(this instanceof cls)) {
136 return new cls(element, options);
137 }
138 this.__init__(element, options);
139};
140
141MochiKit.DragAndDrop.Droppable.prototype = {
142 /***
143
144 A droppable object. Simple use is to create giving an element:
145
146 new MochiKit.DragAndDrop.Droppable('myelement');
147
148 Generally you'll want to define the 'ondrop' function and maybe the
149 'accept' option to filter draggables.
150
151 ***/
152 __class__: MochiKit.DragAndDrop.Droppable,
153
154 __init__: function (element, /* optional */options) {
155 var d = MochiKit.DOM;
156 var b = MochiKit.Base;
157 this.element = d.getElement(element);
158 this.options = b.update({
159
160 /** @id MochiKit.DragAndDrop.greedy */
161 greedy: true,
162
163 /** @id MochiKit.DragAndDrop.hoverclass */
164 hoverclass: null,
165
166 /** @id MochiKit.DragAndDrop.activeclass */
167 activeclass: null,
168
169 /** @id MochiKit.DragAndDrop.hoverfunc */
170 hoverfunc: b.noop,
171
172 /** @id MochiKit.DragAndDrop.accept */
173 accept: null,
174
175 /** @id MochiKit.DragAndDrop.onactive */
176 onactive: b.noop,
177
178 /** @id MochiKit.DragAndDrop.ondesactive */
179 ondesactive: b.noop,
180
181 /** @id MochiKit.DragAndDrop.onhover */
182 onhover: b.noop,
183
184 /** @id MochiKit.DragAndDrop.ondrop */
185 ondrop: b.noop,
186
187 /** @id MochiKit.DragAndDrop.containment */
188 containment: [],
189 tree: false
190 }, options);
191
192 // cache containers
193 this.options._containers = [];
194 b.map(MochiKit.Base.bind(function (c) {
195 this.options._containers.push(d.getElement(c));
196 }, this), this.options.containment);
197
198 MochiKit.Style.makePositioned(this.element); // fix IE
199
200 MochiKit.DragAndDrop.Droppables.register(this);
201 },
202
203 /** @id MochiKit.DragAndDrop.isContained */
204 isContained: function (element) {
205 if (this.options._containers.length) {
206 var containmentNode;
207 if (this.options.tree) {
208 containmentNode = element.treeNode;
209 } else {
210 containmentNode = element.parentNode;
211 }
212 return MochiKit.Iter.some(this.options._containers, function (c) {
213 return containmentNode == c;
214 });
215 } else {
216 return true;
217 }
218 },
219
220 /** @id MochiKit.DragAndDrop.isAccepted */
221 isAccepted: function (element) {
222 return ((!this.options.accept) || MochiKit.Iter.some(
223 this.options.accept, function (c) {
224 return MochiKit.DOM.hasElementClass(element, c);
225 }));
226 },
227
228 /** @id MochiKit.DragAndDrop.isAffected */
229 isAffected: function (point, element) {
230 return ((this.element != element) &&
231 this.isContained(element) &&
232 this.isAccepted(element) &&
233 MochiKit.Position.within(this.element, point.page.x,
234 point.page.y));
235 },
236
237 /** @id MochiKit.DragAndDrop.deactivate */
238 deactivate: function () {
239 /***
240
241 A droppable is deactivate when a draggable has been over it and left.
242
243 ***/
244 if (this.options.hoverclass) {
245 MochiKit.DOM.removeElementClass(this.element,
246 this.options.hoverclass);
247 }
248 this.options.hoverfunc(this.element, false);
249 MochiKit.DragAndDrop.Droppables.last_active = null;
250 },
251
252 /** @id MochiKit.DragAndDrop.activate */
253 activate: function () {
254 /***
255
256 A droppable is active when a draggable is over it.
257
258 ***/
259 if (this.options.hoverclass) {
260 MochiKit.DOM.addElementClass(this.element, this.options.hoverclass);
261 }
262 this.options.hoverfunc(this.element, true);
263 MochiKit.DragAndDrop.Droppables.last_active = this;
264 },
265
266 /** @id MochiKit.DragAndDrop.destroy */
267 destroy: function () {
268 /***
269
270 Delete this droppable.
271
272 ***/
273 MochiKit.DragAndDrop.Droppables.unregister(this);
274 },
275
276 /** @id MochiKit.DragAndDrop.repr */
277 repr: function () {
278 return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
279 }
280};
281
282MochiKit.DragAndDrop.Draggables = {
283 /***
284
285 Manage draggables elements. Not intended to direct use.
286
287 ***/
288 drags: [],
289
290 register: function (draggable) {
291 if (this.drags.length === 0) {
292 var conn = MochiKit.Signal.connect;
293 this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
294 this.eventMouseMove = conn(document, 'onmousemove', this,
295 this.updateDrag);
296 this.eventKeypress = conn(document, 'onkeypress', this,
297 this.keyPress);
298 }
299 this.drags.push(draggable);
300 },
301
302 unregister: function (draggable) {
303 this.drags = MochiKit.Base.filter(function (d) {
304 return d != draggable;
305 }, this.drags);
306 if (this.drags.length === 0) {
307 var disc = MochiKit.Signal.disconnect;
308 disc(this.eventMouseUp);
309 disc(this.eventMouseMove);
310 disc(this.eventKeypress);
311 }
312 },
313
314 activate: function (draggable) {
315 // allows keypress events if window is not currently focused
316 // fails for Safari
317 window.focus();
318 this.activeDraggable = draggable;
319 },
320
321 deactivate: function () {
322 this.activeDraggable = null;
323 },
324
325 updateDrag: function (event) {
326 if (!this.activeDraggable) {
327 return;
328 }
329 var pointer = event.mouse();
330 // Mozilla-based browsers fire successive mousemove events with
331 // the same coordinates, prevent needless redrawing (moz bug?)
332 if (this._lastPointer &&
333 this._lastPointer.page.x == pointer.page.x &&
334 this._lastPointer.page.y == pointer.page.y) {
335 return;
336 }
337 this._lastPointer = pointer;
338 this.activeDraggable.updateDrag(event, pointer);
339 },
340
341 endDrag: function (event) {
342 if (!this.activeDraggable) {
343 return;
344 }
345 this._lastPointer = null;
346 this.activeDraggable.endDrag(event);
347 this.activeDraggable = null;
348 },
349
350 keyPress: function (event) {
351 if (this.activeDraggable) {
352 this.activeDraggable.keyPress(event);
353 }
354 },
355
356 notify: function (eventName, draggable, event) {
357 MochiKit.Signal.signal(this, eventName, draggable, event);
358 }
359};
360
361/** @id MochiKit.DragAndDrop.Draggable */
362MochiKit.DragAndDrop.Draggable = function (element, options) {
363 var cls = arguments.callee;
364 if (!(this instanceof cls)) {
365 return new cls(element, options);
366 }
367 this.__init__(element, options);
368};
369
370MochiKit.DragAndDrop.Draggable.prototype = {
371 /***
372
373 A draggable object. Simple instantiate :
374
375 new MochiKit.DragAndDrop.Draggable('myelement');
376
377 ***/
378 __class__ : MochiKit.DragAndDrop.Draggable,
379
380 __init__: function (element, /* optional */options) {
381 var v = MochiKit.Visual;
382 var b = MochiKit.Base;
383 options = b.update({
384
385 /** @id MochiKit.DragAndDrop.handle */
386 handle: false,
387
388 /** @id MochiKit.DragAndDrop.starteffect */
389 starteffect: function (innerelement) {
390 this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0;
391 new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7});
392 },
393 /** @id MochiKit.DragAndDrop.reverteffect */
394 reverteffect: function (innerelement, top_offset, left_offset) {
395 var dur = Math.sqrt(Math.abs(top_offset^2) +
396 Math.abs(left_offset^2))*0.02;
397 return new v.Move(innerelement,
398 {x: -left_offset, y: -top_offset, duration: dur});
399 },
400
401 /** @id MochiKit.DragAndDrop.endeffect */
402 endeffect: function (innerelement) {
403 new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
404 },
405
406 /** @id MochiKit.DragAndDrop.onchange */
407 onchange: b.noop,
408
409 /** @id MochiKit.DragAndDrop.zindex */
410 zindex: 1000,
411
412 /** @id MochiKit.DragAndDrop.revert */
413 revert: false,
414
415 /** @id MochiKit.DragAndDrop.scroll */
416 scroll: false,
417
418 /** @id MochiKit.DragAndDrop.scrollSensitivity */
419 scrollSensitivity: 20,
420
421 /** @id MochiKit.DragAndDrop.scrollSpeed */
422 scrollSpeed: 15,
423 // false, or xy or [x, y] or function (x, y){return [x, y];}
424
425 /** @id MochiKit.DragAndDrop.snap */
426 snap: false
427 }, options);
428
429 var d = MochiKit.DOM;
430 this.element = d.getElement(element);
431
432 if (options.handle && (typeof(options.handle) == 'string')) {
433 this.handle = d.getFirstElementByTagAndClassName(null,
434 options.handle, this.element);
435 }
436 if (!this.handle) {
437 this.handle = d.getElement(options.handle);
438 }
439 if (!this.handle) {
440 this.handle = this.element;
441 }
442
443 if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
444 options.scroll = d.getElement(options.scroll);
445 this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll);
446 }
447
448 MochiKit.Style.makePositioned(this.element); // fix IE
449
450 this.delta = this.currentDelta();
451 this.options = options;
452 this.dragging = false;
453
454 this.eventMouseDown = MochiKit.Signal.connect(this.handle,
455 'onmousedown', this, this.initDrag);
456 MochiKit.DragAndDrop.Draggables.register(this);
457 },
458
459 /** @id MochiKit.DragAndDrop.destroy */
460 destroy: function () {
461 MochiKit.Signal.disconnect(this.eventMouseDown);
462 MochiKit.DragAndDrop.Draggables.unregister(this);
463 },
464
465 /** @id MochiKit.DragAndDrop.currentDelta */
466 currentDelta: function () {
467 var s = MochiKit.Style.getStyle;
468 return [
469 parseInt(s(this.element, 'left') || '0', 10),
470 parseInt(s(this.element, 'top') || '0', 10)];
471 },
472
473 /** @id MochiKit.DragAndDrop.initDrag */
474 initDrag: function (event) {
475 if (!event.mouse().button.left) {
476 return;
477 }
478 // abort on form elements, fixes a Firefox issue
479 var src = event.target();
480 var tagName = (src.tagName || '').toUpperCase();
481 if (tagName === 'INPUT' || tagName === 'SELECT' ||
482 tagName === 'OPTION' || tagName === 'BUTTON' ||
483 tagName === 'TEXTAREA') {
484 return;
485 }
486
487 if (this._revert) {
488 this._revert.cancel();
489 this._revert = null;
490 }
491
492 var pointer = event.mouse();
493 var pos = MochiKit.Position.cumulativeOffset(this.element);
494 this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y];
495
496 MochiKit.DragAndDrop.Draggables.activate(this);
497 event.stop();
498 },
499
500 /** @id MochiKit.DragAndDrop.startDrag */
501 startDrag: function (event) {
502 this.dragging = true;
503 if (this.options.selectclass) {
504 MochiKit.DOM.addElementClass(this.element,
505 this.options.selectclass);
506 }
507 if (this.options.zindex) {
508 this.originalZ = MochiKit.Style.getStyle(this.element, 'z-index');
509 this.element.style.zIndex = this.options.zindex;
510 }
511
512 if (this.options.ghosting) {
513 this._clone = this.element.cloneNode(true);
514 this.ghostPosition = MochiKit.Position.absolutize(this.element);
515 this.element.parentNode.insertBefore(this._clone, this.element);
516 }
517
518 if (this.options.scroll) {
519 if (this.options.scroll == window) {
520 var where = this._getWindowScroll(this.options.scroll);
521 this.originalScrollLeft = where.left;
522 this.originalScrollTop = where.top;
523 } else {
524 this.originalScrollLeft = this.options.scroll.scrollLeft;
525 this.originalScrollTop = this.options.scroll.scrollTop;
526 }
527 }
528
529 MochiKit.DragAndDrop.Droppables.prepare(this.element);
530 MochiKit.DragAndDrop.Draggables.notify('start', this, event);
531 if (this.options.starteffect) {
532 this.options.starteffect(this.element);
533 }
534 },
535
536 /** @id MochiKit.DragAndDrop.updateDrag */
537 updateDrag: function (event, pointer) {
538 if (!this.dragging) {
539 this.startDrag(event);
540 }
541 MochiKit.Position.prepare();
542 MochiKit.DragAndDrop.Droppables.show(pointer, this.element);
543 MochiKit.DragAndDrop.Draggables.notify('drag', this, event);
544 this.draw(pointer);
545 this.options.onchange(this);
546
547 if (this.options.scroll) {
548 this.stopScrolling();
549 var p, q;
550 if (this.options.scroll == window) {
551 var s = this._getWindowScroll(this.options.scroll);
552 p = new MochiKit.Style.Coordinates(s.left, s.top);
553 q = new MochiKit.Style.Coordinates(s.left + s.width,
554 s.top + s.height);
555 } else {
556 p = MochiKit.Position.page(this.options.scroll);
557 p.x += this.options.scroll.scrollLeft;
558 p.y += this.options.scroll.scrollTop;
559 p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);
560 p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
561 q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth,
562 p.y + this.options.scroll.offsetHeight);
563 }
564 var speed = [0, 0];
565 if (pointer.page.x > (q.x - this.options.scrollSensitivity)) {
566 speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity);
567 } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) {
568 speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity);
569 }
570 if (pointer.page.y > (q.y - this.options.scrollSensitivity)) {
571 speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity);
572 } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) {
573 speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity);
574 }
575 this.startScrolling(speed);
576 }
577
578 // fix AppleWebKit rendering
579 if (/AppleWebKit/.test(navigator.appVersion)) {
580 window.scrollBy(0, 0);
581 }
582 event.stop();
583 },
584
585 /** @id MochiKit.DragAndDrop.finishDrag */
586 finishDrag: function (event, success) {
587 var dr = MochiKit.DragAndDrop;
588 this.dragging = false;
589 if (this.options.selectclass) {
590 MochiKit.DOM.removeElementClass(this.element,
591 this.options.selectclass);
592 }
593
594 if (this.options.ghosting) {
595 // XXX: from a user point of view, it would be better to remove
596 // the node only *after* the MochiKit.Visual.Move end when used
597 // with revert.
598 MochiKit.Position.relativize(this.element, this.ghostPosition);
599 MochiKit.DOM.removeElement(this._clone);
600 this._clone = null;
601 }
602
603 if (success) {
604 dr.Droppables.fire(event, this.element);
605 }
606 dr.Draggables.notify('end', this, event);
607
608 var revert = this.options.revert;
609 if (revert && typeof(revert) == 'function') {
610 revert = revert(this.element);
611 }
612
613 var d = this.currentDelta();
614 if (revert && this.options.reverteffect) {
615 this._revert = this.options.reverteffect(this.element,
616 d[1] - this.delta[1], d[0] - this.delta[0]);
617 } else {
618 this.delta = d;
619 }
620
621 if (this.options.zindex) {
622 this.element.style.zIndex = this.originalZ;
623 }
624
625 if (this.options.endeffect) {
626 this.options.endeffect(this.element);
627 }
628
629 dr.Draggables.deactivate();
630 dr.Droppables.reset(this.element);
631 },
632
633 /** @id MochiKit.DragAndDrop.keyPress */
634 keyPress: function (event) {
635 if (event.key().string != "KEY_ESCAPE") {
636 return;
637 }
638 this.finishDrag(event, false);
639 event.stop();
640 },
641
642 /** @id MochiKit.DragAndDrop.endDrag */
643 endDrag: function (event) {
644 if (!this.dragging) {
645 return;
646 }
647 this.stopScrolling();
648 this.finishDrag(event, true);
649 event.stop();
650 },
651
652 /** @id MochiKit.DragAndDrop.draw */
653 draw: function (point) {
654 var pos = MochiKit.Position.cumulativeOffset(this.element);
655 var d = this.currentDelta();
656 pos.x -= d[0];
657 pos.y -= d[1];
658
659 if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
660 pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft;
661 pos.y -= this.options.scroll.scrollTop - this.originalScrollTop;
662 }
663
664 var p = [point.page.x - pos.x - this.offset[0],
665 point.page.y - pos.y - this.offset[1]];
666
667 if (this.options.snap) {
668 if (typeof(this.options.snap) == 'function') {
669 p = this.options.snap(p[0], p[1]);
670 } else {
671 if (this.options.snap instanceof Array) {
672 var i = -1;
673 p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
674 i += 1;
675 return Math.round(v/this.options.snap[i]) *
676 this.options.snap[i];
677 }, this), p);
678 } else {
679 p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
680 return Math.round(v/this.options.snap) *
681 this.options.snap;
682 }, this), p);
683 }
684 }
685 }
686 var style = this.element.style;
687 if ((!this.options.constraint) ||
688 (this.options.constraint == 'horizontal')) {
689 style.left = p[0] + 'px';
690 }
691 if ((!this.options.constraint) ||
692 (this.options.constraint == 'vertical')) {
693 style.top = p[1] + 'px';
694 }
695 if (style.visibility == 'hidden') {
696 style.visibility = ''; // fix gecko rendering
697 }
698 },
699
700 /** @id MochiKit.DragAndDrop.stopScrolling */
701 stopScrolling: function () {
702 if (this.scrollInterval) {
703 clearInterval(this.scrollInterval);
704 this.scrollInterval = null;
705 MochiKit.DragAndDrop.Draggables._lastScrollPointer = null;
706 }
707 },
708
709 /** @id MochiKit.DragAndDrop.startScrolling */
710 startScrolling: function (speed) {
711 if (!speed[0] && !speed[1]) {
712 return;
713 }
714 this.scrollSpeed = [speed[0] * this.options.scrollSpeed,
715 speed[1] * this.options.scrollSpeed];
716 this.lastScrolled = new Date();
717 this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10);
718 },
719
720 /** @id MochiKit.DragAndDrop.scroll */
721 scroll: function () {
722 var current = new Date();
723 var delta = current - this.lastScrolled;
724 this.lastScrolled = current;
725
726 if (this.options.scroll == window) {
727 var s = this._getWindowScroll(this.options.scroll);
728 if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
729 var dm = delta / 1000;
730 this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0],
731 s.top + dm * this.scrollSpeed[1]);
732 }
733 } else {
734 this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
735 this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
736 }
737
738 var d = MochiKit.DragAndDrop;
739
740 MochiKit.Position.prepare();
741 d.Droppables.show(d.Draggables._lastPointer, this.element);
742 d.Draggables.notify('drag', this);
743 if (this._isScrollChild) {
744 d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer;
745 d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000;
746 d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000;
747 if (d.Draggables._lastScrollPointer.x < 0) {
748 d.Draggables._lastScrollPointer.x = 0;
749 }
750 if (d.Draggables._lastScrollPointer.y < 0) {
751 d.Draggables._lastScrollPointer.y = 0;
752 }
753 this.draw(d.Draggables._lastScrollPointer);
754 }
755
756 this.options.onchange(this);
757 },
758
759 _getWindowScroll: function (win) {
760 var vp, w, h;
761 MochiKit.DOM.withWindow(win, function () {
762 vp = MochiKit.Style.getViewportPosition(win.document);
763 });
764 if (win.innerWidth) {
765 w = win.innerWidth;
766 h = win.innerHeight;
767 } else if (win.document.documentElement && win.document.documentElement.clientWidth) {
768 w = win.document.documentElement.clientWidth;
769 h = win.document.documentElement.clientHeight;
770 } else {
771 w = win.document.body.offsetWidth;
772 h = win.document.body.offsetHeight;
773 }
774 return {top: vp.y, left: vp.x, width: w, height: h};
775 },
776
777 /** @id MochiKit.DragAndDrop.repr */
778 repr: function () {
779 return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
780 }
781};
782
783MochiKit.DragAndDrop.__new__ = function () {
784 MochiKit.Base.nameFunctions(this);
785};
786
787MochiKit.DragAndDrop.__new__();
788
789MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);
diff --git a/frontend/delta/js/MochiKit/Format.js b/frontend/delta/js/MochiKit/Format.js
new file mode 100644
index 0000000..0e7af50
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Format.js
@@ -0,0 +1,332 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Format 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Format', '1.5', ['Base']);
35
36MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) {
37 return function (num) {
38 num = parseFloat(num);
39 if (typeof(num) == "undefined" || num === null || isNaN(num)) {
40 return placeholder;
41 }
42 var curheader = header;
43 var curfooter = footer;
44 if (num < 0) {
45 num = -num;
46 } else {
47 curheader = curheader.replace(/-/, "");
48 }
49 var me = arguments.callee;
50 var fmt = MochiKit.Format.formatLocale(locale);
51 if (isPercent) {
52 num = num * 100.0;
53 curfooter = fmt.percent + curfooter;
54 }
55 num = MochiKit.Format.roundToFixed(num, precision);
56 var parts = num.split(/\./);
57 var whole = parts[0];
58 var frac = (parts.length == 1) ? "" : parts[1];
59 var res = "";
60 while (whole.length < leadingZeros) {
61 whole = "0" + whole;
62 }
63 if (separatorAt) {
64 while (whole.length > separatorAt) {
65 var i = whole.length - separatorAt;
66 //res = res + fmt.separator + whole.substring(i, whole.length);
67 res = fmt.separator + whole.substring(i, whole.length) + res;
68 whole = whole.substring(0, i);
69 }
70 }
71 res = whole + res;
72 if (precision > 0) {
73 while (frac.length < trailingZeros) {
74 frac = frac + "0";
75 }
76 res = res + fmt.decimal + frac;
77 }
78 return curheader + res + curfooter;
79 };
80};
81
82/** @id MochiKit.Format.numberFormatter */
83MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) {
84 // http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
85 // | 0 | leading or trailing zeros
86 // | # | just the number
87 // | , | separator
88 // | . | decimal separator
89 // | % | Multiply by 100 and format as percent
90 if (typeof(placeholder) == "undefined") {
91 placeholder = "";
92 }
93 var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
94 if (!match) {
95 throw TypeError("Invalid pattern");
96 }
97 var header = pattern.substr(0, match.index);
98 var footer = pattern.substr(match.index + match[0].length);
99 if (header.search(/-/) == -1) {
100 header = header + "-";
101 }
102 var whole = match[1];
103 var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : "";
104 var isPercent = (typeof(match[3]) == "string" && match[3] != "");
105 var tmp = whole.split(/,/);
106 var separatorAt;
107 if (typeof(locale) == "undefined") {
108 locale = "default";
109 }
110 if (tmp.length == 1) {
111 separatorAt = null;
112 } else {
113 separatorAt = tmp[1].length;
114 }
115 var leadingZeros = whole.length - whole.replace(/0/g, "").length;
116 var trailingZeros = frac.length - frac.replace(/0/g, "").length;
117 var precision = frac.length;
118 var rval = MochiKit.Format._numberFormatter(
119 placeholder, header, footer, locale, isPercent, precision,
120 leadingZeros, separatorAt, trailingZeros
121 );
122 var m = MochiKit.Base;
123 if (m) {
124 var fn = arguments.callee;
125 var args = m.concat(arguments);
126 rval.repr = function () {
127 return [
128 self.NAME,
129 "(",
130 m.map(m.repr, args).join(", "),
131 ")"
132 ].join("");
133 };
134 }
135 return rval;
136};
137
138/** @id MochiKit.Format.formatLocale */
139MochiKit.Format.formatLocale = function (locale) {
140 if (typeof(locale) == "undefined" || locale === null) {
141 locale = "default";
142 }
143 if (typeof(locale) == "string") {
144 var rval = MochiKit.Format.LOCALE[locale];
145 if (typeof(rval) == "string") {
146 rval = arguments.callee(rval);
147 MochiKit.Format.LOCALE[locale] = rval;
148 }
149 return rval;
150 } else {
151 return locale;
152 }
153};
154
155/** @id MochiKit.Format.twoDigitAverage */
156MochiKit.Format.twoDigitAverage = function (numerator, denominator) {
157 if (denominator) {
158 var res = numerator / denominator;
159 if (!isNaN(res)) {
160 return MochiKit.Format.twoDigitFloat(res);
161 }
162 }
163 return "0";
164};
165
166/** @id MochiKit.Format.twoDigitFloat */
167MochiKit.Format.twoDigitFloat = function (aNumber) {
168 var res = MochiKit.Format.roundToFixed(aNumber, 2);
169 if (res.indexOf(".00") > 0) {
170 return res.substring(0, res.length - 3);
171 } else if (res.charAt(res.length - 1) == "0") {
172 return res.substring(0, res.length - 1);
173 } else {
174 return res;
175 }
176};
177
178/** @id MochiKit.Format.lstrip */
179MochiKit.Format.lstrip = function (str, /* optional */chars) {
180 str = str + "";
181 if (typeof(str) != "string") {
182 return null;
183 }
184 if (!chars) {
185 return str.replace(/^\s+/, "");
186 } else {
187 return str.replace(new RegExp("^[" + chars + "]+"), "");
188 }
189};
190
191/** @id MochiKit.Format.rstrip */
192MochiKit.Format.rstrip = function (str, /* optional */chars) {
193 str = str + "";
194 if (typeof(str) != "string") {
195 return null;
196 }
197 if (!chars) {
198 return str.replace(/\s+$/, "");
199 } else {
200 return str.replace(new RegExp("[" + chars + "]+$"), "");
201 }
202};
203
204/** @id MochiKit.Format.strip */
205MochiKit.Format.strip = function (str, /* optional */chars) {
206 var self = MochiKit.Format;
207 return self.rstrip(self.lstrip(str, chars), chars);
208};
209
210/** @id MochiKit.Format.truncToFixed */
211MochiKit.Format.truncToFixed = function (aNumber, precision) {
212 var fixed = MochiKit.Format._numberToFixed(aNumber, precision);
213 var fracPos = fixed.indexOf(".");
214 if (fracPos > 0 && fracPos + precision + 1 < fixed.length) {
215 fixed = fixed.substring(0, fracPos + precision + 1);
216 fixed = MochiKit.Format._shiftNumber(fixed, 0);
217 }
218 return fixed;
219};
220
221/** @id MochiKit.Format.roundToFixed */
222MochiKit.Format.roundToFixed = function (aNumber, precision) {
223 var fixed = MochiKit.Format._numberToFixed(aNumber, precision);
224 var fracPos = fixed.indexOf(".");
225 if (fracPos > 0 && fracPos + precision + 1 < fixed.length) {
226 var str = MochiKit.Format._shiftNumber(fixed, precision);
227 str = MochiKit.Format._numberToFixed(Math.round(parseFloat(str)), 0);
228 fixed = MochiKit.Format._shiftNumber(str, -precision);
229 }
230 return fixed;
231};
232
233/**
234 * Converts a number to a fixed format string. This function handles
235 * conversion of exponents by shifting the decimal point to the left
236 * or the right. It also guarantees a specified minimum number of
237 * fractional digits (but no maximum).
238 *
239 * @param {Number} aNumber the number to convert
240 * @param {Number} precision the minimum number of decimal digits
241 *
242 * @return {String} the fixed format number string
243 */
244MochiKit.Format._numberToFixed = function (aNumber, precision) {
245 var str = aNumber.toString();
246 var parts = str.split(/[eE]/);
247 var exp = (parts.length === 1) ? 0 : parseInt(parts[1], 10) || 0;
248 var fixed = MochiKit.Format._shiftNumber(parts[0], exp);
249 parts = fixed.split(/\./);
250 var whole = parts[0];
251 var frac = (parts.length === 1) ? "" : parts[1];
252 while (frac.length < precision) {
253 frac += "0";
254 }
255 if (frac.length > 0) {
256 return whole + "." + frac;
257 } else {
258 return whole;
259 }
260};
261
262/**
263 * Shifts the decimal dot location in a fixed format number string.
264 * This function handles negative values and will add and remove
265 * leading and trailing zeros as needed.
266 *
267 * @param {String} num the fixed format number string
268 * @param {Number} exp the base-10 exponent to apply
269 *
270 * @return {String} the new fixed format number string
271 */
272MochiKit.Format._shiftNumber = function (num, exp) {
273 var pos = num.indexOf(".");
274 if (pos < 0) {
275 pos = num.length;
276 } else {
277 num = num.substring(0, pos) + num.substring(pos + 1);
278 }
279 pos += exp;
280 while (pos <= 0 || (pos <= 1 && num.charAt(0) === "-")) {
281 if (num.charAt(0) === "-") {
282 num = "-0" + num.substring(1);
283 } else {
284 num = "0" + num;
285 }
286 pos++;
287 }
288 while (pos > num.length) {
289 num += "0";
290 }
291 if (pos < num.length) {
292 num = num.substring(0, pos) + "." + num.substring(pos);
293 }
294 while (/^0[^.]/.test(num)) {
295 num = num.substring(1);
296 }
297 while (/^-0[^.]/.test(num)) {
298 num = "-" + num.substring(2);
299 }
300 return num;
301};
302
303/** @id MochiKit.Format.percentFormat */
304MochiKit.Format.percentFormat = function (aNumber) {
305 return MochiKit.Format.twoDigitFloat(100 * aNumber) + '%';
306};
307
308MochiKit.Format.LOCALE = {
309 en_US: {separator: ",", decimal: ".", percent: "%"},
310 de_DE: {separator: ".", decimal: ",", percent: "%"},
311 pt_BR: {separator: ".", decimal: ",", percent: "%"},
312 fr_FR: {separator: " ", decimal: ",", percent: "%"},
313 "default": "en_US",
314 __export__: false
315};
316
317MochiKit.Format.__new__ = function () {
318 MochiKit.Base.nameFunctions(this);
319 var base = this.NAME + ".";
320 var k, v, o;
321 for (k in this.LOCALE) {
322 o = this.LOCALE[k];
323 if (typeof(o) == "object") {
324 o.repr = function () { return this.NAME; };
325 o.NAME = base + "LOCALE." + k;
326 }
327 }
328};
329
330MochiKit.Format.__new__();
331
332MochiKit.Base._exportSymbols(this, MochiKit.Format);
diff --git a/frontend/delta/js/MochiKit/Iter.js b/frontend/delta/js/MochiKit/Iter.js
new file mode 100644
index 0000000..8f7ea3d
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Iter.js
@@ -0,0 +1,811 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Iter 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Iter', '1.5', ['Base']);
35
36MochiKit.Base.update(MochiKit.Iter, {
37 /** @id MochiKit.Iter.registerIteratorFactory */
38 registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
39 MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
40 },
41
42 /** @id MochiKit.Iter.isIterable */
43 isIterable: function(o) {
44 return o != null &&
45 (typeof(o.next) == "function" || typeof(o.iter) == "function");
46 },
47
48 /** @id MochiKit.Iter.iter */
49 iter: function (iterable, /* optional */ sentinel) {
50 var self = MochiKit.Iter;
51 if (arguments.length == 2) {
52 return self.takewhile(
53 function (a) { return a != sentinel; },
54 iterable
55 );
56 }
57 if (typeof(iterable.next) == 'function') {
58 return iterable;
59 } else if (typeof(iterable.iter) == 'function') {
60 return iterable.iter();
61 /*
62 } else if (typeof(iterable.__iterator__) == 'function') {
63 //
64 // XXX: We can't support JavaScript 1.7 __iterator__ directly
65 // because of Object.prototype.__iterator__
66 //
67 return iterable.__iterator__();
68 */
69 }
70
71 try {
72 return self.iteratorRegistry.match(iterable);
73 } catch (e) {
74 var m = MochiKit.Base;
75 if (e == m.NotFound) {
76 e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
77 }
78 throw e;
79 }
80 },
81
82 /** @id MochiKit.Iter.count */
83 count: function (n) {
84 if (!n) {
85 n = 0;
86 }
87 var m = MochiKit.Base;
88 return {
89 repr: function () { return "count(" + n + ")"; },
90 toString: m.forwardCall("repr"),
91 next: m.counter(n)
92 };
93 },
94
95 /** @id MochiKit.Iter.cycle */
96 cycle: function (p) {
97 var self = MochiKit.Iter;
98 var m = MochiKit.Base;
99 var lst = [];
100 var iterator = self.iter(p);
101 return {
102 repr: function () { return "cycle(...)"; },
103 toString: m.forwardCall("repr"),
104 next: function () {
105 try {
106 var rval = iterator.next();
107 lst.push(rval);
108 return rval;
109 } catch (e) {
110 if (e != self.StopIteration) {
111 throw e;
112 }
113 if (lst.length === 0) {
114 this.next = function () {
115 throw self.StopIteration;
116 };
117 } else {
118 var i = -1;
119 this.next = function () {
120 i = (i + 1) % lst.length;
121 return lst[i];
122 };
123 }
124 return this.next();
125 }
126 }
127 };
128 },
129
130 /** @id MochiKit.Iter.repeat */
131 repeat: function (elem, /* optional */n) {
132 var m = MochiKit.Base;
133 if (typeof(n) == 'undefined') {
134 return {
135 repr: function () {
136 return "repeat(" + m.repr(elem) + ")";
137 },
138 toString: m.forwardCall("repr"),
139 next: function () {
140 return elem;
141 }
142 };
143 }
144 return {
145 repr: function () {
146 return "repeat(" + m.repr(elem) + ", " + n + ")";
147 },
148 toString: m.forwardCall("repr"),
149 next: function () {
150 if (n <= 0) {
151 throw MochiKit.Iter.StopIteration;
152 }
153 n -= 1;
154 return elem;
155 }
156 };
157 },
158
159 /** @id MochiKit.Iter.next */
160 next: function (iterator) {
161 return iterator.next();
162 },
163
164 /** @id MochiKit.Iter.izip */
165 izip: function (p, q/*, ...*/) {
166 var m = MochiKit.Base;
167 var self = MochiKit.Iter;
168 var next = self.next;
169 var iterables = m.map(self.iter, arguments);
170 return {
171 repr: function () { return "izip(...)"; },
172 toString: m.forwardCall("repr"),
173 next: function () { return m.map(next, iterables); }
174 };
175 },
176
177 /** @id MochiKit.Iter.ifilter */
178 ifilter: 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 "ifilter(...)"; },
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.ifilterfalse */
201 ifilterfalse: function (pred, seq) {
202 var m = MochiKit.Base;
203 seq = MochiKit.Iter.iter(seq);
204 if (pred === null) {
205 pred = m.operator.truth;
206 }
207 return {
208 repr: function () { return "ifilterfalse(...)"; },
209 toString: m.forwardCall("repr"),
210 next: function () {
211 while (true) {
212 var rval = seq.next();
213 if (!pred(rval)) {
214 return rval;
215 }
216 }
217 // mozilla warnings aren't too bright
218 return undefined;
219 }
220 };
221 },
222
223 /** @id MochiKit.Iter.islice */
224 islice: function (seq/*, [start,] stop[, step] */) {
225 var self = MochiKit.Iter;
226 var m = MochiKit.Base;
227 seq = self.iter(seq);
228 var start = 0;
229 var stop = 0;
230 var step = 1;
231 var i = -1;
232 if (arguments.length == 2) {
233 stop = arguments[1];
234 } else if (arguments.length == 3) {
235 start = arguments[1];
236 stop = arguments[2];
237 } else {
238 start = arguments[1];
239 stop = arguments[2];
240 step = arguments[3];
241 }
242 return {
243 repr: function () {
244 return "islice(" + ["...", start, stop, step].join(", ") + ")";
245 },
246 toString: m.forwardCall("repr"),
247 next: function () {
248 if (start >= stop) {
249 throw self.StopIteration;
250 }
251
252 var rval;
253 while (i < start) {
254 rval = seq.next();
255 i++;
256 }
257 start += step;
258 return rval;
259 }
260 };
261 },
262
263 /** @id MochiKit.Iter.imap */
264 imap: function (fun, p, q/*, ...*/) {
265 var m = MochiKit.Base;
266 var self = MochiKit.Iter;
267 var iterables = m.map(self.iter, m.extend(null, arguments, 1));
268 var map = m.map;
269 var next = self.next;
270 return {
271 repr: function () { return "imap(...)"; },
272 toString: m.forwardCall("repr"),
273 next: function () {
274 return fun.apply(this, map(next, iterables));
275 }
276 };
277 },
278
279 /** @id MochiKit.Iter.applymap */
280 applymap: function (fun, seq, self) {
281 seq = MochiKit.Iter.iter(seq);
282 var m = MochiKit.Base;
283 return {
284 repr: function () { return "applymap(...)"; },
285 toString: m.forwardCall("repr"),
286 next: function () {
287 return fun.apply(self, seq.next());
288 }
289 };
290 },
291
292 /** @id MochiKit.Iter.chain */
293 chain: function (p, q/*, ...*/) {
294 // dumb fast path
295 var self = MochiKit.Iter;
296 var m = MochiKit.Base;
297 if (arguments.length == 1) {
298 return self.iter(arguments[0]);
299 }
300 var argiter = m.map(self.iter, arguments);
301 return {
302 repr: function () { return "chain(...)"; },
303 toString: m.forwardCall("repr"),
304 next: function () {
305 while (argiter.length > 1) {
306 try {
307 return argiter[0].next();
308 } catch (e) {
309 if (e != self.StopIteration) {
310 throw e;
311 }
312 argiter.shift();
313 }
314 }
315 if (argiter.length == 1) {
316 // optimize last element
317 var arg = argiter.shift();
318 this.next = m.bind("next", arg);
319 return this.next();
320 }
321 throw self.StopIteration;
322 }
323 };
324 },
325
326 /** @id MochiKit.Iter.takewhile */
327 takewhile: function (pred, seq) {
328 var self = MochiKit.Iter;
329 seq = self.iter(seq);
330 return {
331 repr: function () { return "takewhile(...)"; },
332 toString: MochiKit.Base.forwardCall("repr"),
333 next: function () {
334 var rval = seq.next();
335 if (!pred(rval)) {
336 this.next = function () {
337 throw self.StopIteration;
338 };
339 this.next();
340 }
341 return rval;
342 }
343 };
344 },
345
346 /** @id MochiKit.Iter.dropwhile */
347 dropwhile: function (pred, seq) {
348 seq = MochiKit.Iter.iter(seq);
349 var m = MochiKit.Base;
350 var bind = m.bind;
351 return {
352 "repr": function () { return "dropwhile(...)"; },
353 "toString": m.forwardCall("repr"),
354 "next": function () {
355 while (true) {
356 var rval = seq.next();
357 if (!pred(rval)) {
358 break;
359 }
360 }
361 this.next = bind("next", seq);
362 return rval;
363 }
364 };
365 },
366
367 _tee: function (ident, sync, iterable) {
368 sync.pos[ident] = -1;
369 var m = MochiKit.Base;
370 var listMin = m.listMin;
371 return {
372 repr: function () { return "tee(" + ident + ", ...)"; },
373 toString: m.forwardCall("repr"),
374 next: function () {
375 var rval;
376 var i = sync.pos[ident];
377
378 if (i == sync.max) {
379 rval = iterable.next();
380 sync.deque.push(rval);
381 sync.max += 1;
382 sync.pos[ident] += 1;
383 } else {
384 rval = sync.deque[i - sync.min];
385 sync.pos[ident] += 1;
386 if (i == sync.min && listMin(sync.pos) != sync.min) {
387 sync.min += 1;
388 sync.deque.shift();
389 }
390 }
391 return rval;
392 }
393 };
394 },
395
396 /** @id MochiKit.Iter.tee */
397 tee: function (iterable, n/* = 2 */) {
398 var rval = [];
399 var sync = {
400 "pos": [],
401 "deque": [],
402 "max": -1,
403 "min": -1
404 };
405 if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
406 n = 2;
407 }
408 var self = MochiKit.Iter;
409 iterable = self.iter(iterable);
410 var _tee = self._tee;
411 for (var i = 0; i < n; i++) {
412 rval.push(_tee(i, sync, iterable));
413 }
414 return rval;
415 },
416
417 /** @id MochiKit.Iter.list */
418 list: function (iterable) {
419 // Fast-path for Array and Array-like
420 var rval;
421 if (iterable instanceof Array) {
422 return iterable.slice();
423 }
424 // this is necessary to avoid a Safari crash
425 if (typeof(iterable) == "function" &&
426 !(iterable instanceof Function) &&
427 typeof(iterable.length) == 'number') {
428 rval = [];
429 for (var i = 0; i < iterable.length; i++) {
430 rval.push(iterable[i]);
431 }
432 return rval;
433 }
434
435 var self = MochiKit.Iter;
436 iterable = self.iter(iterable);
437 rval = [];
438 var a_val;
439 try {
440 while (true) {
441 a_val = iterable.next();
442 rval.push(a_val);
443 }
444 } catch (e) {
445 if (e != self.StopIteration) {
446 throw e;
447 }
448 return rval;
449 }
450 // mozilla warnings aren't too bright
451 return undefined;
452 },
453
454
455 /** @id MochiKit.Iter.reduce */
456 reduce: function (fn, iterable, /* optional */initial) {
457 var i = 0;
458 var x = initial;
459 var self = MochiKit.Iter;
460 iterable = self.iter(iterable);
461 if (arguments.length < 3) {
462 try {
463 x = iterable.next();
464 } catch (e) {
465 if (e == self.StopIteration) {
466 e = new TypeError("reduce() of empty sequence with no initial value");
467 }
468 throw e;
469 }
470 i++;
471 }
472 try {
473 while (true) {
474 x = fn(x, iterable.next());
475 }
476 } catch (e) {
477 if (e != self.StopIteration) {
478 throw e;
479 }
480 }
481 return x;
482 },
483
484 /** @id MochiKit.Iter.range */
485 range: function (/* [start,] stop[, step] */) {
486 var start = 0;
487 var stop = 0;
488 var step = 1;
489 if (arguments.length == 1) {
490 stop = arguments[0];
491 } else if (arguments.length == 2) {
492 start = arguments[0];
493 stop = arguments[1];
494 } else if (arguments.length == 3) {
495 start = arguments[0];
496 stop = arguments[1];
497 step = arguments[2];
498 } else {
499 throw new TypeError("range() takes 1, 2, or 3 arguments!");
500 }
501 if (step === 0) {
502 throw new TypeError("range() step must not be 0");
503 }
504 return {
505 next: function () {
506 if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
507 throw MochiKit.Iter.StopIteration;
508 }
509 var rval = start;
510 start += step;
511 return rval;
512 },
513 repr: function () {
514 return "range(" + [start, stop, step].join(", ") + ")";
515 },
516 toString: MochiKit.Base.forwardCall("repr")
517 };
518 },
519
520 /** @id MochiKit.Iter.sum */
521 sum: function (iterable, start/* = 0 */) {
522 if (typeof(start) == "undefined" || start === null) {
523 start = 0;
524 }
525 var x = start;
526 var self = MochiKit.Iter;
527 iterable = self.iter(iterable);
528 try {
529 while (true) {
530 x += iterable.next();
531 }
532 } catch (e) {
533 if (e != self.StopIteration) {
534 throw e;
535 }
536 }
537 return x;
538 },
539
540 /** @id MochiKit.Iter.exhaust */
541 exhaust: function (iterable) {
542 var self = MochiKit.Iter;
543 iterable = self.iter(iterable);
544 try {
545 while (true) {
546 iterable.next();
547 }
548 } catch (e) {
549 if (e != self.StopIteration) {
550 throw e;
551 }
552 }
553 },
554
555 /** @id MochiKit.Iter.forEach */
556 forEach: function (iterable, func, /* optional */obj) {
557 var m = MochiKit.Base;
558 var self = MochiKit.Iter;
559 if (arguments.length > 2) {
560 func = m.bind(func, obj);
561 }
562 // fast path for array
563 if (m.isArrayLike(iterable) && !self.isIterable(iterable)) {
564 try {
565 for (var i = 0; i < iterable.length; i++) {
566 func(iterable[i]);
567 }
568 } catch (e) {
569 if (e != self.StopIteration) {
570 throw e;
571 }
572 }
573 } else {
574 self.exhaust(self.imap(func, iterable));
575 }
576 },
577
578 /** @id MochiKit.Iter.every */
579 every: function (iterable, func) {
580 var self = MochiKit.Iter;
581 try {
582 self.ifilterfalse(func, iterable).next();
583 return false;
584 } catch (e) {
585 if (e != self.StopIteration) {
586 throw e;
587 }
588 return true;
589 }
590 },
591
592 /** @id MochiKit.Iter.sorted */
593 sorted: function (iterable, /* optional */cmp) {
594 var rval = MochiKit.Iter.list(iterable);
595 if (arguments.length == 1) {
596 cmp = MochiKit.Base.compare;
597 }
598 rval.sort(cmp);
599 return rval;
600 },
601
602 /** @id MochiKit.Iter.reversed */
603 reversed: function (iterable) {
604 var rval = MochiKit.Iter.list(iterable);
605 rval.reverse();
606 return rval;
607 },
608
609 /** @id MochiKit.Iter.some */
610 some: function (iterable, func) {
611 var self = MochiKit.Iter;
612 try {
613 self.ifilter(func, iterable).next();
614 return true;
615 } catch (e) {
616 if (e != self.StopIteration) {
617 throw e;
618 }
619 return false;
620 }
621 },
622
623 /** @id MochiKit.Iter.iextend */
624 iextend: function (lst, iterable) {
625 var m = MochiKit.Base;
626 var self = MochiKit.Iter;
627 if (m.isArrayLike(iterable) && !self.isIterable(iterable)) {
628 // fast-path for array-like
629 for (var i = 0; i < iterable.length; i++) {
630 lst.push(iterable[i]);
631 }
632 } else {
633 iterable = self.iter(iterable);
634 try {
635 while (true) {
636 lst.push(iterable.next());
637 }
638 } catch (e) {
639 if (e != self.StopIteration) {
640 throw e;
641 }
642 }
643 }
644 return lst;
645 },
646
647 /** @id MochiKit.Iter.groupby */
648 groupby: function(iterable, /* optional */ keyfunc) {
649 var m = MochiKit.Base;
650 var self = MochiKit.Iter;
651 if (arguments.length < 2) {
652 keyfunc = m.operator.identity;
653 }
654 iterable = self.iter(iterable);
655
656 // shared
657 var pk = undefined;
658 var k = undefined;
659 var v;
660
661 function fetch() {
662 v = iterable.next();
663 k = keyfunc(v);
664 };
665
666 function eat() {
667 var ret = v;
668 v = undefined;
669 return ret;
670 };
671
672 var first = true;
673 var compare = m.compare;
674 return {
675 repr: function () { return "groupby(...)"; },
676 next: function() {
677 // iterator-next
678
679 // iterate until meet next group
680 while (compare(k, pk) === 0) {
681 fetch();
682 if (first) {
683 first = false;
684 break;
685 }
686 }
687 pk = k;
688 return [k, {
689 next: function() {
690 // subiterator-next
691 if (v == undefined) { // Is there something to eat?
692 fetch();
693 }
694 if (compare(k, pk) !== 0) {
695 throw self.StopIteration;
696 }
697 return eat();
698 }
699 }];
700 }
701 };
702 },
703
704 /** @id MochiKit.Iter.groupby_as_array */
705 groupby_as_array: function (iterable, /* optional */ keyfunc) {
706 var m = MochiKit.Base;
707 var self = MochiKit.Iter;
708 if (arguments.length < 2) {
709 keyfunc = m.operator.identity;
710 }
711
712 iterable = self.iter(iterable);
713 var result = [];
714 var first = true;
715 var prev_key;
716 var compare = m.compare;
717 while (true) {
718 try {
719 var value = iterable.next();
720 var key = keyfunc(value);
721 } catch (e) {
722 if (e == self.StopIteration) {
723 break;
724 }
725 throw e;
726 }
727 if (first || compare(key, prev_key) !== 0) {
728 var values = [];
729 result.push([key, values]);
730 }
731 values.push(value);
732 first = false;
733 prev_key = key;
734 }
735 return result;
736 },
737
738 /** @id MochiKit.Iter.arrayLikeIter */
739 arrayLikeIter: function (iterable) {
740 var i = 0;
741 return {
742 repr: function () { return "arrayLikeIter(...)"; },
743 toString: MochiKit.Base.forwardCall("repr"),
744 next: function () {
745 if (i >= iterable.length) {
746 throw MochiKit.Iter.StopIteration;
747 }
748 return iterable[i++];
749 }
750 };
751 },
752
753 /** @id MochiKit.Iter.hasIterateNext */
754 hasIterateNext: function (iterable) {
755 return (iterable && typeof(iterable.iterateNext) == "function");
756 },
757
758 /** @id MochiKit.Iter.iterateNextIter */
759 iterateNextIter: function (iterable) {
760 return {
761 repr: function () { return "iterateNextIter(...)"; },
762 toString: MochiKit.Base.forwardCall("repr"),
763 next: function () {
764 var rval = iterable.iterateNext();
765 if (rval === null || rval === undefined) {
766 throw MochiKit.Iter.StopIteration;
767 }
768 return rval;
769 }
770 };
771 }
772});
773
774
775MochiKit.Iter.__new__ = function () {
776 var m = MochiKit.Base;
777 // Re-use StopIteration if exists (e.g. SpiderMonkey)
778 if (typeof(StopIteration) != "undefined") {
779 this.StopIteration = StopIteration;
780 } else {
781 /** @id MochiKit.Iter.StopIteration */
782 this.StopIteration = new m.NamedError("StopIteration");
783 }
784 this.iteratorRegistry = new m.AdapterRegistry();
785 // Register the iterator factory for arrays
786 this.registerIteratorFactory(
787 "arrayLike",
788 m.isArrayLike,
789 this.arrayLikeIter
790 );
791
792 this.registerIteratorFactory(
793 "iterateNext",
794 this.hasIterateNext,
795 this.iterateNextIter
796 );
797
798 m.nameFunctions(this);
799
800};
801
802MochiKit.Iter.__new__();
803
804//
805// XXX: Internet Explorer blows
806//
807if (MochiKit.__export__) {
808 reduce = MochiKit.Iter.reduce;
809}
810
811MochiKit.Base._exportSymbols(this, MochiKit.Iter);
diff --git a/frontend/delta/js/MochiKit/Logging.js b/frontend/delta/js/MochiKit/Logging.js
new file mode 100644
index 0000000..34070bc
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Logging.js
@@ -0,0 +1,285 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Logging 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Logging', '1.5', ['Base']);
35
36 /** @id MochiKit.Logging.LogMessage */
37MochiKit.Logging.LogMessage = function (num, level, info) {
38 this.num = num;
39 this.level = level;
40 this.info = info;
41 this.timestamp = new Date();
42};
43
44MochiKit.Logging.LogMessage.prototype = {
45 /** @id MochiKit.Logging.LogMessage.prototype.repr */
46 repr: function () {
47 var m = MochiKit.Base;
48 return 'LogMessage(' +
49 m.map(
50 m.repr,
51 [this.num, this.level, this.info]
52 ).join(', ') + ')';
53 },
54 /** @id MochiKit.Logging.LogMessage.prototype.toString */
55 toString: MochiKit.Base.forwardCall("repr")
56};
57
58MochiKit.Base.update(MochiKit.Logging, {
59 /** @id MochiKit.Logging.logLevelAtLeast */
60 logLevelAtLeast: function (minLevel) {
61 var self = MochiKit.Logging;
62 if (typeof(minLevel) == 'string') {
63 minLevel = self.LogLevel[minLevel];
64 }
65 return function (msg) {
66 var msgLevel = msg.level;
67 if (typeof(msgLevel) == 'string') {
68 msgLevel = self.LogLevel[msgLevel];
69 }
70 return msgLevel >= minLevel;
71 };
72 },
73
74 /** @id MochiKit.Logging.isLogMessage */
75 isLogMessage: function (/* ... */) {
76 var LogMessage = MochiKit.Logging.LogMessage;
77 for (var i = 0; i < arguments.length; i++) {
78 if (!(arguments[i] instanceof LogMessage)) {
79 return false;
80 }
81 }
82 return true;
83 },
84
85 /** @id MochiKit.Logging.compareLogMessage */
86 compareLogMessage: function (a, b) {
87 return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]);
88 },
89
90 /** @id MochiKit.Logging.alertListener */
91 alertListener: function (msg) {
92 alert(
93 "num: " + msg.num +
94 "\nlevel: " + msg.level +
95 "\ninfo: " + msg.info.join(" ")
96 );
97 }
98
99});
100
101/** @id MochiKit.Logging.Logger */
102MochiKit.Logging.Logger = function (/* optional */maxSize) {
103 this.counter = 0;
104 if (typeof(maxSize) == 'undefined' || maxSize === null) {
105 maxSize = -1;
106 }
107 this.maxSize = maxSize;
108 this._messages = [];
109 this.listeners = {};
110 this.useNativeConsole = false;
111};
112
113MochiKit.Logging.Logger.prototype = {
114 /** @id MochiKit.Logging.Logger.prototype.clear */
115 clear: function () {
116 this._messages.splice(0, this._messages.length);
117 },
118
119 /** @id MochiKit.Logging.Logger.prototype.logToConsole */
120 logToConsole: function (msg) {
121 if (typeof(window) != "undefined" && window.console
122 && window.console.log) {
123 // Safari and FireBug 0.4
124 // Percent replacement is a workaround for cute Safari crashing bug
125 window.console.log(msg.replace(/%/g, '\uFF05'));
126 } else if (typeof(opera) != "undefined" && opera.postError) {
127 // Opera
128 opera.postError(msg);
129 } else if (typeof(Debug) != "undefined" && Debug.writeln) {
130 // IE Web Development Helper (?)
131 // http://www.nikhilk.net/Entry.aspx?id=93
132 Debug.writeln(msg);
133 } else if (typeof(debug) != "undefined" && debug.trace) {
134 // Atlas framework (?)
135 // http://www.nikhilk.net/Entry.aspx?id=93
136 debug.trace(msg);
137 }
138 },
139
140 /** @id MochiKit.Logging.Logger.prototype.dispatchListeners */
141 dispatchListeners: function (msg) {
142 for (var k in this.listeners) {
143 var pair = this.listeners[k];
144 if (pair.ident != k || (pair[0] && !pair[0](msg))) {
145 continue;
146 }
147 pair[1](msg);
148 }
149 },
150
151 /** @id MochiKit.Logging.Logger.prototype.addListener */
152 addListener: function (ident, filter, listener) {
153 if (typeof(filter) == 'string') {
154 filter = MochiKit.Logging.logLevelAtLeast(filter);
155 }
156 var entry = [filter, listener];
157 entry.ident = ident;
158 this.listeners[ident] = entry;
159 },
160
161 /** @id MochiKit.Logging.Logger.prototype.removeListener */
162 removeListener: function (ident) {
163 delete this.listeners[ident];
164 },
165
166 /** @id MochiKit.Logging.Logger.prototype.baseLog */
167 baseLog: function (level, message/*, ...*/) {
168 if (typeof(level) == "number") {
169 if (level >= MochiKit.Logging.LogLevel.FATAL) {
170 level = 'FATAL';
171 } else if (level >= MochiKit.Logging.LogLevel.ERROR) {
172 level = 'ERROR';
173 } else if (level >= MochiKit.Logging.LogLevel.WARNING) {
174 level = 'WARNING';
175 } else if (level >= MochiKit.Logging.LogLevel.INFO) {
176 level = 'INFO';
177 } else {
178 level = 'DEBUG';
179 }
180 }
181 var msg = new MochiKit.Logging.LogMessage(
182 this.counter,
183 level,
184 MochiKit.Base.extend(null, arguments, 1)
185 );
186 this._messages.push(msg);
187 this.dispatchListeners(msg);
188 if (this.useNativeConsole) {
189 this.logToConsole(msg.level + ": " + msg.info.join(" "));
190 }
191 this.counter += 1;
192 while (this.maxSize >= 0 && this._messages.length > this.maxSize) {
193 this._messages.shift();
194 }
195 },
196
197 /** @id MochiKit.Logging.Logger.prototype.getMessages */
198 getMessages: function (howMany) {
199 var firstMsg = 0;
200 if (!(typeof(howMany) == 'undefined' || howMany === null)) {
201 firstMsg = Math.max(0, this._messages.length - howMany);
202 }
203 return this._messages.slice(firstMsg);
204 },
205
206 /** @id MochiKit.Logging.Logger.prototype.getMessageText */
207 getMessageText: function (howMany) {
208 if (typeof(howMany) == 'undefined' || howMany === null) {
209 howMany = 30;
210 }
211 var messages = this.getMessages(howMany);
212 if (messages.length) {
213 var lst = MochiKit.Base.map(function (m) {
214 return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' ');
215 }, messages);
216 lst.unshift('LAST ' + messages.length + ' MESSAGES:');
217 return lst.join('');
218 }
219 return '';
220 },
221
222 /** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */
223 debuggingBookmarklet: function (inline) {
224 if (typeof(MochiKit.LoggingPane) == "undefined") {
225 alert(this.getMessageText());
226 } else {
227 MochiKit.LoggingPane.createLoggingPane(inline || false);
228 }
229 }
230};
231
232MochiKit.Logging.__new__ = function () {
233 this.LogLevel = {
234 ERROR: 40,
235 FATAL: 50,
236 WARNING: 30,
237 INFO: 20,
238 DEBUG: 10
239 };
240
241 var m = MochiKit.Base;
242 m.registerComparator("LogMessage",
243 this.isLogMessage,
244 this.compareLogMessage
245 );
246
247 var partial = m.partial;
248
249 var Logger = this.Logger;
250 var baseLog = Logger.prototype.baseLog;
251 m.update(this.Logger.prototype, {
252 debug: partial(baseLog, 'DEBUG'),
253 log: partial(baseLog, 'INFO'),
254 error: partial(baseLog, 'ERROR'),
255 fatal: partial(baseLog, 'FATAL'),
256 warning: partial(baseLog, 'WARNING')
257 });
258
259 // indirectly find logger so it can be replaced
260 var self = this;
261 var connectLog = function (name) {
262 return function () {
263 self.logger[name].apply(self.logger, arguments);
264 };
265 };
266
267 /** @id MochiKit.Logging.log */
268 this.log = connectLog('log');
269 /** @id MochiKit.Logging.logError */
270 this.logError = connectLog('error');
271 /** @id MochiKit.Logging.logDebug */
272 this.logDebug = connectLog('debug');
273 /** @id MochiKit.Logging.logFatal */
274 this.logFatal = connectLog('fatal');
275 /** @id MochiKit.Logging.logWarning */
276 this.logWarning = connectLog('warning');
277 this.logger = new Logger();
278 this.logger.useNativeConsole = true;
279
280 m.nameFunctions(this);
281};
282
283MochiKit.Logging.__new__();
284
285MochiKit.Base._exportSymbols(this, MochiKit.Logging);
diff --git a/frontend/delta/js/MochiKit/LoggingPane.js b/frontend/delta/js/MochiKit/LoggingPane.js
new file mode 100644
index 0000000..e35aee8
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/LoggingPane.js
@@ -0,0 +1,353 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.LoggingPane 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'LoggingPane', '1.5', ['Base', 'Logging']);
35
36/** @id MochiKit.LoggingPane.createLoggingPane */
37MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) {
38 var m = MochiKit.LoggingPane;
39 inline = !(!inline);
40 if (m._loggingPane && m._loggingPane.inline != inline) {
41 m._loggingPane.closePane();
42 m._loggingPane = null;
43 }
44 if (!m._loggingPane || m._loggingPane.closed) {
45 m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger);
46 }
47 return m._loggingPane;
48};
49
50/**
51 * @id MochiKit.LoggingPane.LoggingPane
52 * @constructor
53 */
54MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) {
55
56 /* Use a div if inline, pop up a window if not */
57 /* Create the elements */
58 if (typeof(logger) == "undefined" || logger === null) {
59 logger = MochiKit.Logging.logger;
60 }
61 this.logger = logger;
62 var update = MochiKit.Base.update;
63 var updatetree = MochiKit.Base.updatetree;
64 var bind = MochiKit.Base.bind;
65 var clone = MochiKit.Base.clone;
66 var win = window;
67 var uid = "_MochiKit_LoggingPane";
68 if (typeof(MochiKit.DOM) != "undefined") {
69 win = MochiKit.DOM.currentWindow();
70 }
71 if (!inline) {
72 // name the popup with the base URL for uniqueness
73 var url = win.location.href.split("?")[0].replace(/[#:\/.><&%-]/g, "_");
74 var name = uid + "_" + url;
75 var nwin = win.open("", name, "dependent,resizable,height=200");
76 if (!nwin) {
77 alert("Not able to open debugging window due to pop-up blocking.");
78 return undefined;
79 }
80 nwin.document.write(
81 '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
82 + '"http://www.w3.org/TR/html4/loose.dtd">'
83 + '<html><head><title>[MochiKit.LoggingPane]</title></head>'
84 + '<body></body></html>'
85 );
86 nwin.document.close();
87 nwin.document.title += ' ' + win.document.title;
88 win = nwin;
89 }
90 var doc = win.document;
91 this.doc = doc;
92
93 // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
94 var debugPane = doc.getElementById(uid);
95 var existing_pane = !!debugPane;
96 if (debugPane && typeof(debugPane.loggingPane) != "undefined") {
97 debugPane.loggingPane.logger = this.logger;
98 debugPane.loggingPane.buildAndApplyFilter();
99 return debugPane.loggingPane;
100 }
101
102 if (existing_pane) {
103 // clear any existing contents
104 var child;
105 while ((child = debugPane.firstChild)) {
106 debugPane.removeChild(child);
107 }
108 } else {
109 debugPane = doc.createElement("div");
110 debugPane.id = uid;
111 }
112 debugPane.loggingPane = this;
113 var levelFilterField = doc.createElement("input");
114 var infoFilterField = doc.createElement("input");
115 var filterButton = doc.createElement("button");
116 var loadButton = doc.createElement("button");
117 var clearButton = doc.createElement("button");
118 var closeButton = doc.createElement("button");
119 var logPaneArea = doc.createElement("div");
120 var logPane = doc.createElement("div");
121
122 /* Set up the functions */
123 var listenerId = uid + "_Listener";
124 this.colorTable = clone(this.colorTable);
125 var messages = [];
126 var messageFilter = null;
127
128 /** @id MochiKit.LoggingPane.messageLevel */
129 var messageLevel = function (msg) {
130 var level = msg.level;
131 if (typeof(level) == "number") {
132 level = MochiKit.Logging.LogLevel[level];
133 }
134 return level;
135 };
136
137 /** @id MochiKit.LoggingPane.messageText */
138 var messageText = function (msg) {
139 return msg.info.join(" ");
140 };
141
142 /** @id MochiKit.LoggingPane.addMessageText */
143 var addMessageText = bind(function (msg) {
144 var level = messageLevel(msg);
145 var text = messageText(msg);
146 var c = this.colorTable[level];
147 var p = doc.createElement("span");
148 p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level;
149 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;
150 p.appendChild(doc.createTextNode(level + ": " + text));
151 logPane.appendChild(p);
152 logPane.appendChild(doc.createElement("br"));
153 if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) {
154 logPaneArea.scrollTop = 0;
155 } else {
156 logPaneArea.scrollTop = logPaneArea.scrollHeight;
157 }
158 }, this);
159
160 /** @id MochiKit.LoggingPane.addMessage */
161 var addMessage = function (msg) {
162 messages[messages.length] = msg;
163 addMessageText(msg);
164 };
165
166 /** @id MochiKit.LoggingPane.buildMessageFilter */
167 var buildMessageFilter = function () {
168 var levelre, infore;
169 try {
170 /* Catch any exceptions that might arise due to invalid regexes */
171 levelre = new RegExp(levelFilterField.value);
172 infore = new RegExp(infoFilterField.value);
173 } catch(e) {
174 /* If there was an error with the regexes, do no filtering */
175 MochiKit.Logging.logDebug("Error in filter regex: " + e.message);
176 return null;
177 }
178
179 return function (msg) {
180 return (
181 levelre.test(messageLevel(msg)) &&
182 infore.test(messageText(msg))
183 );
184 };
185 };
186
187 /** @id MochiKit.LoggingPane.clearMessagePane */
188 var clearMessagePane = function () {
189 while (logPane.firstChild) {
190 logPane.removeChild(logPane.firstChild);
191 }
192 };
193
194 /** @id MochiKit.LoggingPane.clearMessages */
195 var clearMessages = function () {
196 messages = [];
197 clearMessagePane();
198 };
199
200 /** @id MochiKit.LoggingPane.closePane */
201 var closePane = bind(function () {
202 if (this.closed) {
203 return;
204 }
205 this.closed = true;
206 if (MochiKit.LoggingPane._loggingPane == this) {
207 MochiKit.LoggingPane._loggingPane = null;
208 }
209 this.logger.removeListener(listenerId);
210 try {
211 try {
212 debugPane.loggingPane = null;
213 } catch(e) { MochiKit.Logging.logFatal("Bookmarklet was closed incorrectly."); }
214 if (inline) {
215 debugPane.parentNode.removeChild(debugPane);
216 } else {
217 this.win.close();
218 }
219 } catch(e) {}
220 }, this);
221
222 /** @id MochiKit.LoggingPane.filterMessages */
223 var filterMessages = function () {
224 clearMessagePane();
225
226 for (var i = 0; i < messages.length; i++) {
227 var msg = messages[i];
228 if (messageFilter === null || messageFilter(msg)) {
229 addMessageText(msg);
230 }
231 }
232 };
233
234 this.buildAndApplyFilter = function () {
235 messageFilter = buildMessageFilter();
236
237 filterMessages();
238
239 this.logger.removeListener(listenerId);
240 this.logger.addListener(listenerId, messageFilter, addMessage);
241 };
242
243
244 /** @id MochiKit.LoggingPane.loadMessages */
245 var loadMessages = bind(function () {
246 messages = this.logger.getMessages();
247 filterMessages();
248 }, this);
249
250 /** @id MochiKit.LoggingPane.filterOnEnter */
251 var filterOnEnter = bind(function (event) {
252 event = event || window.event;
253 var key = event.which || event.keyCode;
254 if (key == 13) {
255 this.buildAndApplyFilter();
256 }
257 }, this);
258
259 /* Create the debug pane */
260 var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont;
261 if (inline) {
262 style += "; height: 10em; border-top: 2px solid black";
263 } else {
264 style += "; height: 100%;";
265 }
266 debugPane.style.cssText = style;
267
268 if (!existing_pane) {
269 doc.body.appendChild(debugPane);
270 }
271
272 /* Create the filter fields */
273 style = {"cssText": "width: 33%; display: inline; font: " + this.logFont};
274
275 updatetree(levelFilterField, {
276 "value": "FATAL|ERROR|WARNING|INFO|DEBUG",
277 "onkeypress": filterOnEnter,
278 "style": style
279 });
280 debugPane.appendChild(levelFilterField);
281
282 updatetree(infoFilterField, {
283 "value": ".*",
284 "onkeypress": filterOnEnter,
285 "style": style
286 });
287 debugPane.appendChild(infoFilterField);
288
289 /* Create the buttons */
290 style = "width: 8%; display:inline; font: " + this.logFont;
291
292 filterButton.appendChild(doc.createTextNode("Filter"));
293 filterButton.onclick = bind("buildAndApplyFilter", this);
294 filterButton.style.cssText = style;
295 debugPane.appendChild(filterButton);
296
297 loadButton.appendChild(doc.createTextNode("Load"));
298 loadButton.onclick = loadMessages;
299 loadButton.style.cssText = style;
300 debugPane.appendChild(loadButton);
301
302 clearButton.appendChild(doc.createTextNode("Clear"));
303 clearButton.onclick = clearMessages;
304 clearButton.style.cssText = style;
305 debugPane.appendChild(clearButton);
306
307 closeButton.appendChild(doc.createTextNode("Close"));
308 closeButton.onclick = closePane;
309 closeButton.style.cssText = style;
310 debugPane.appendChild(closeButton);
311
312 /* Create the logging pane */
313 logPaneArea.style.cssText = "overflow: auto; width: 100%";
314 logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%");
315
316 logPaneArea.appendChild(logPane);
317 debugPane.appendChild(logPaneArea);
318
319 this.buildAndApplyFilter();
320 loadMessages();
321
322 if (inline) {
323 this.win = undefined;
324 } else {
325 this.win = win;
326 }
327 this.inline = inline;
328 this.closePane = closePane;
329 this.closed = false;
330
331
332 return this;
333};
334
335MochiKit.LoggingPane.LoggingPane.prototype = {
336 "logFont": "8pt Verdana,sans-serif",
337 "colorTable": {
338 "ERROR": "red",
339 "FATAL": "darkred",
340 "WARNING": "blue",
341 "INFO": "black",
342 "DEBUG": "green"
343 }
344};
345
346MochiKit.LoggingPane.__new__ = function () {
347 MochiKit.Base.nameFunctions(this);
348 MochiKit.LoggingPane._loggingPane = null;
349};
350
351MochiKit.LoggingPane.__new__();
352
353MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane);
diff --git a/frontend/delta/js/MochiKit/MochiKit.js b/frontend/delta/js/MochiKit/MochiKit.js
new file mode 100644
index 0000000..5fac077
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/MochiKit.js
@@ -0,0 +1,156 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.MochiKit 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34var MochiKit = MochiKit || {};
35
36/** @id MochiKit.MochiKit */
37MochiKit.MochiKit = MochiKit.MochiKit || {};
38
39MochiKit.MochiKit.NAME = "MochiKit.MochiKit";
40MochiKit.MochiKit.VERSION = "1.5";
41MochiKit.MochiKit.__export__ = false;
42MochiKit.MochiKit.__repr__ = function () {
43 return "[" + this.NAME + " " + this.VERSION + "]";
44};
45
46/** @id MochiKit.MochiKit.toString */
47MochiKit.MochiKit.toString = function () {
48 return this.__repr__();
49};
50
51/** @id MochiKit.MochiKit.SUBMODULES */
52MochiKit.MochiKit.SUBMODULES = [
53 "Base",
54 "Iter",
55 "Logging",
56 "DateTime",
57 "Format",
58 "Text",
59 "Async",
60 "DOM",
61 "Selector",
62 "Style",
63 "LoggingPane",
64 "Color",
65 "Signal",
66 "Position",
67 "Visual",
68 "DragAndDrop",
69 "Sortable"
70];
71
72(function () {
73 if (typeof(document) == "undefined") {
74 return;
75 }
76 var scripts = document.getElementsByTagName("script");
77 var kXHTMLNSURI = "http://www.w3.org/1999/xhtml";
78 var kSVGNSURI = "http://www.w3.org/2000/svg";
79 var kXLINKNSURI = "http://www.w3.org/1999/xlink";
80 var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
81 var base = null;
82 var baseElem = null;
83 var allScripts = {};
84 var i;
85 var src;
86 for (i = 0; i < scripts.length; i++) {
87 src = null;
88 switch (scripts[i].namespaceURI) {
89 case kSVGNSURI:
90 src = scripts[i].getAttributeNS(kXLINKNSURI, "href");
91 break;
92 /*
93 case null: // HTML
94 case '': // HTML
95 case kXHTMLNSURI:
96 case kXULNSURI:
97 */
98 default:
99 src = scripts[i].getAttribute("src");
100 break;
101 }
102 if (!src) {
103 continue;
104 }
105 allScripts[src] = true;
106 if (src.match(/MochiKit.js(\?.*)?$/)) {
107 base = src.substring(0, src.lastIndexOf('MochiKit.js'));
108 baseElem = scripts[i];
109 }
110 }
111 if (base === null) {
112 return;
113 }
114 var modules = MochiKit.MochiKit.SUBMODULES;
115 for (var i = 0; i < modules.length; i++) {
116 if (MochiKit[modules[i]]) {
117 continue;
118 }
119 var uri = base + modules[i] + '.js';
120 if (uri in allScripts) {
121 continue;
122 }
123 if (baseElem.namespaceURI == kSVGNSURI ||
124 baseElem.namespaceURI == kXULNSURI) {
125 // SVG, XUL
126 /*
127 SVG does not support document.write, so if Safari wants to
128 support SVG tests it should fix its deferred loading bug
129 (see following below).
130 */
131 var s = document.createElementNS(baseElem.namespaceURI, 'script');
132 s.setAttribute("id", "MochiKit_" + base + modules[i]);
133 if (baseElem.namespaceURI == kSVGNSURI) {
134 s.setAttributeNS(kXLINKNSURI, 'href', uri);
135 } else {
136 s.setAttribute('src', uri);
137 }
138 s.setAttribute("type", "application/x-javascript");
139 baseElem.parentNode.appendChild(s);
140 } else {
141 // HTML, XHTML
142 /*
143 DOM can not be used here because Safari does
144 deferred loading of scripts unless they are
145 in the document or inserted with document.write
146
147 This is not XHTML compliant. If you want XHTML
148 compliance then you must use the packed version of MochiKit
149 or include each script individually (basically unroll
150 these document.write calls into your XHTML source)
151 */
152 document.write('<' + baseElem.nodeName + ' src="' + uri +
153 '" type="text/javascript"></script>');
154 }
155 };
156})();
diff --git a/frontend/delta/js/MochiKit/MockDOM.js b/frontend/delta/js/MochiKit/MockDOM.js
new file mode 100644
index 0000000..6df7922
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/MockDOM.js
@@ -0,0 +1,135 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.MockDOM 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34var MochiKit = MochiKit || {};
35
36MochiKit.MockDOM = MochiKit.MockDOM || {};
37
38MochiKit.MockDOM.NAME = "MochiKit.MockDOM";
39MochiKit.MockDOM.VERSION = "1.5";
40MochiKit.MockDOM.__export__ = false;
41
42MochiKit.MockDOM.__repr__ = function () {
43 return "[" + this.NAME + " " + this.VERSION + "]";
44};
45
46/** @id MochiKit.MockDOM.toString */
47MochiKit.MockDOM.toString = function () {
48 return this.__repr__();
49};
50
51/** @id MochiKit.MockDOM.createDocument */
52MochiKit.MockDOM.createDocument = function () {
53 var doc = new MochiKit.MockDOM.MockElement("DOCUMENT");
54 doc.body = doc.createElement("BODY");
55 doc.appendChild(doc.body);
56 return doc;
57};
58
59/** @id MochiKit.MockDOM.MockElement */
60MochiKit.MockDOM.MockElement = function (name, data, ownerDocument) {
61 this.tagName = this.nodeName = name.toUpperCase();
62 this.ownerDocument = ownerDocument || null;
63 if (name == "DOCUMENT") {
64 this.nodeType = 9;
65 this.childNodes = [];
66 } else if (typeof(data) == "string") {
67 this.nodeValue = data;
68 this.nodeType = 3;
69 } else {
70 this.nodeType = 1;
71 this.childNodes = [];
72 }
73 if (name.substring(0, 1) == "<") {
74 var nameattr = name.substring(
75 name.indexOf('"') + 1, name.lastIndexOf('"'));
76 name = name.substring(1, name.indexOf(" "));
77 this.tagName = this.nodeName = name.toUpperCase();
78 this.setAttribute("name", nameattr);
79 }
80};
81
82MochiKit.MockDOM.MockElement.prototype = {
83 /** @id MochiKit.MockDOM.MockElement.prototype.createElement */
84 createElement: function (tagName) {
85 return new MochiKit.MockDOM.MockElement(tagName, null, this.nodeType == 9 ? this : this.ownerDocument);
86 },
87 /** @id MochiKit.MockDOM.MockElement.prototype.createTextNode */
88 createTextNode: function (text) {
89 return new MochiKit.MockDOM.MockElement("text", text, this.nodeType == 9 ? this : this.ownerDocument);
90 },
91 /** @id MochiKit.MockDOM.MockElement.prototype.setAttribute */
92 setAttribute: function (name, value) {
93 this[name] = value;
94 },
95 /** @id MochiKit.MockDOM.MockElement.prototype.getAttribute */
96 getAttribute: function (name) {
97 return this[name];
98 },
99 /** @id MochiKit.MockDOM.MockElement.prototype.appendChild */
100 appendChild: function (child) {
101 this.childNodes.push(child);
102 },
103 /** @id MochiKit.MockDOM.MockElement.prototype.toString */
104 toString: function () {
105 return "MockElement(" + this.tagName + ")";
106 },
107 /** @id MochiKit.MockDOM.MockElement.prototype.getElementsByTagName */
108 getElementsByTagName: function (tagName) {
109 var foundElements = [];
110 MochiKit.Base.nodeWalk(this, function(node){
111 if (tagName == '*' || tagName == node.tagName) {
112 foundElements.push(node);
113 return node.childNodes;
114 }
115 });
116 return foundElements;
117 }
118};
119
120 /** @id MochiKit.MockDOM.EXPORT_OK */
121MochiKit.MockDOM.EXPORT_OK = [
122 "mockElement",
123 "createDocument"
124];
125
126 /** @id MochiKit.MockDOM.EXPORT */
127MochiKit.MockDOM.EXPORT = [
128 "document"
129];
130
131MochiKit.MockDOM.__new__ = function () {
132 this.document = this.createDocument();
133};
134
135MochiKit.MockDOM.__new__();
diff --git a/frontend/delta/js/MochiKit/Position.js b/frontend/delta/js/MochiKit/Position.js
new file mode 100644
index 0000000..e5f4543
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Position.js
@@ -0,0 +1,241 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Position 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005-2006 Bob Ippolito and others. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Position', '1.5', ['Base', 'DOM', 'Style']);
35
36MochiKit.Base.update(MochiKit.Position, {
37 // Don't export from this module
38 __export__: false,
39
40 // set to true if needed, warning: firefox performance problems
41 // NOT neeeded for page scrolling, only if draggable contained in
42 // scrollable elements
43 includeScrollOffsets: false,
44
45 /** @id MochiKit.Position.prepare */
46 prepare: function () {
47 var deltaX = window.pageXOffset
48 || document.documentElement.scrollLeft
49 || document.body.scrollLeft
50 || 0;
51 var deltaY = window.pageYOffset
52 || document.documentElement.scrollTop
53 || document.body.scrollTop
54 || 0;
55 this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY);
56 },
57
58 /** @id MochiKit.Position.cumulativeOffset */
59 cumulativeOffset: function (element) {
60 var valueT = 0;
61 var valueL = 0;
62 do {
63 valueT += element.offsetTop || 0;
64 valueL += element.offsetLeft || 0;
65 element = element.offsetParent;
66 } while (element);
67 return new MochiKit.Style.Coordinates(valueL, valueT);
68 },
69
70 /** @id MochiKit.Position.realOffset */
71 realOffset: function (element) {
72 var valueT = 0;
73 var valueL = 0;
74 do {
75 valueT += element.scrollTop || 0;
76 valueL += element.scrollLeft || 0;
77 element = element.parentNode;
78 } while (element);
79 return new MochiKit.Style.Coordinates(valueL, valueT);
80 },
81
82 /** @id MochiKit.Position.within */
83 within: function (element, x, y) {
84 if (this.includeScrollOffsets) {
85 return this.withinIncludingScrolloffsets(element, x, y);
86 }
87 this.xcomp = x;
88 this.ycomp = y;
89 this.offset = this.cumulativeOffset(element);
90 if (element.style.position == "fixed") {
91 this.offset.x += this.windowOffset.x;
92 this.offset.y += this.windowOffset.y;
93 }
94
95 return (y >= this.offset.y &&
96 y < this.offset.y + element.offsetHeight &&
97 x >= this.offset.x &&
98 x < this.offset.x + element.offsetWidth);
99 },
100
101 /** @id MochiKit.Position.withinIncludingScrolloffsets */
102 withinIncludingScrolloffsets: function (element, x, y) {
103 var offsetcache = this.realOffset(element);
104
105 this.xcomp = x + offsetcache.x - this.windowOffset.x;
106 this.ycomp = y + offsetcache.y - this.windowOffset.y;
107 this.offset = this.cumulativeOffset(element);
108
109 return (this.ycomp >= this.offset.y &&
110 this.ycomp < this.offset.y + element.offsetHeight &&
111 this.xcomp >= this.offset.x &&
112 this.xcomp < this.offset.x + element.offsetWidth);
113 },
114
115 // within must be called directly before
116 /** @id MochiKit.Position.overlap */
117 overlap: function (mode, element) {
118 if (!mode) {
119 return 0;
120 }
121 if (mode == 'vertical') {
122 return ((this.offset.y + element.offsetHeight) - this.ycomp) /
123 element.offsetHeight;
124 }
125 if (mode == 'horizontal') {
126 return ((this.offset.x + element.offsetWidth) - this.xcomp) /
127 element.offsetWidth;
128 }
129 },
130
131 /** @id MochiKit.Position.absolutize */
132 absolutize: function (element) {
133 element = MochiKit.DOM.getElement(element);
134 if (element.style.position == 'absolute') {
135 return;
136 }
137 MochiKit.Position.prepare();
138
139 var offsets = MochiKit.Position.positionedOffset(element);
140 var width = element.clientWidth;
141 var height = element.clientHeight;
142
143 var oldStyle = {
144 'position': element.style.position,
145 'left': offsets.x - parseFloat(element.style.left || 0),
146 'top': offsets.y - parseFloat(element.style.top || 0),
147 'width': element.style.width,
148 'height': element.style.height
149 };
150
151 element.style.position = 'absolute';
152 element.style.top = offsets.y + 'px';
153 element.style.left = offsets.x + 'px';
154 element.style.width = width + 'px';
155 element.style.height = height + 'px';
156
157 return oldStyle;
158 },
159
160 /** @id MochiKit.Position.positionedOffset */
161 positionedOffset: function (element) {
162 var valueT = 0, valueL = 0;
163 do {
164 valueT += element.offsetTop || 0;
165 valueL += element.offsetLeft || 0;
166 element = element.offsetParent;
167 if (element) {
168 var p = MochiKit.Style.getStyle(element, 'position');
169 if (p == 'relative' || p == 'absolute') {
170 break;
171 }
172 }
173 } while (element);
174 return new MochiKit.Style.Coordinates(valueL, valueT);
175 },
176
177 /** @id MochiKit.Position.relativize */
178 relativize: function (element, oldPos) {
179 element = MochiKit.DOM.getElement(element);
180 if (element.style.position == 'relative') {
181 return;
182 }
183 MochiKit.Position.prepare();
184
185 var top = parseFloat(element.style.top || 0) -
186 (oldPos['top'] || 0);
187 var left = parseFloat(element.style.left || 0) -
188 (oldPos['left'] || 0);
189
190 element.style.position = oldPos['position'];
191 element.style.top = top + 'px';
192 element.style.left = left + 'px';
193 element.style.width = oldPos['width'];
194 element.style.height = oldPos['height'];
195 },
196
197 /** @id MochiKit.Position.clone */
198 clone: function (source, target) {
199 source = MochiKit.DOM.getElement(source);
200 target = MochiKit.DOM.getElement(target);
201 target.style.position = 'absolute';
202 var offsets = this.cumulativeOffset(source);
203 target.style.top = offsets.y + 'px';
204 target.style.left = offsets.x + 'px';
205 target.style.width = source.offsetWidth + 'px';
206 target.style.height = source.offsetHeight + 'px';
207 },
208
209 /** @id MochiKit.Position.page */
210 page: function (forElement) {
211 var valueT = 0;
212 var valueL = 0;
213
214 var element = forElement;
215 do {
216 valueT += element.offsetTop || 0;
217 valueL += element.offsetLeft || 0;
218
219 // Safari fix
220 if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') {
221 break;
222 }
223 } while (element = element.offsetParent);
224
225 element = forElement;
226 do {
227 valueT -= element.scrollTop || 0;
228 valueL -= element.scrollLeft || 0;
229 } while (element = element.parentNode);
230
231 return new MochiKit.Style.Coordinates(valueL, valueT);
232 }
233});
234
235MochiKit.Position.__new__ = function (win) {
236 MochiKit.Base.nameFunctions(this);
237};
238
239MochiKit.Position.__new__(this);
240
241MochiKit.Base._exportSymbols(this, MochiKit.Position);
diff --git a/frontend/delta/js/MochiKit/Selector.js b/frontend/delta/js/MochiKit/Selector.js
new file mode 100644
index 0000000..2719b13
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Selector.js
@@ -0,0 +1,416 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Selector 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito and others. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Selector', '1.5', ['Base', 'DOM', 'Iter']);
35
36MochiKit.Selector.Selector = function (expression) {
37 this.params = {classNames: [], pseudoClassNames: []};
38 this.expression = expression.toString().replace(/(^\s+|\s+$)/g, '');
39 this.parseExpression();
40 this.compileMatcher();
41};
42
43MochiKit.Selector.Selector.prototype = {
44 /***
45
46 Selector class: convenient object to make CSS selections.
47
48 ***/
49 __class__: MochiKit.Selector.Selector,
50
51 /** @id MochiKit.Selector.Selector.prototype.parseExpression */
52 parseExpression: function () {
53 function abort(message) {
54 throw 'Parse error in selector: ' + message;
55 }
56
57 if (this.expression == '') {
58 abort('empty expression');
59 }
60
61 var repr = MochiKit.Base.repr;
62 var params = this.params;
63 var expr = this.expression;
64 var match, modifier, clause, rest;
65 while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
66 params.attributes = params.attributes || [];
67 params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
68 expr = match[1];
69 }
70
71 if (expr == '*') {
72 return this.params.wildcard = true;
73 }
74
75 while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)) {
76 modifier = match[1];
77 clause = match[2];
78 rest = match[3];
79 switch (modifier) {
80 case '#':
81 params.id = clause;
82 break;
83 case '.':
84 params.classNames.push(clause);
85 break;
86 case ':':
87 params.pseudoClassNames.push(clause);
88 break;
89 case '':
90 case undefined:
91 params.tagName = clause.toUpperCase();
92 break;
93 default:
94 abort(repr(expr));
95 }
96 expr = rest;
97 }
98
99 if (expr.length > 0) {
100 abort(repr(expr));
101 }
102 },
103
104 /** @id MochiKit.Selector.Selector.prototype.buildMatchExpression */
105 buildMatchExpression: function () {
106 var repr = MochiKit.Base.repr;
107 var params = this.params;
108 var conditions = [];
109 var clause, i;
110
111 function childElements(element) {
112 return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, " + element + ".childNodes)";
113 }
114
115 if (params.wildcard) {
116 conditions.push('true');
117 }
118 if (clause = params.id) {
119 conditions.push('element.id == ' + repr(clause));
120 }
121 if (clause = params.tagName) {
122 conditions.push('element.tagName.toUpperCase() == ' + repr(clause));
123 }
124 if ((clause = params.classNames).length > 0) {
125 for (i = 0; i < clause.length; i++) {
126 conditions.push('MochiKit.DOM.hasElementClass(element, ' + repr(clause[i]) + ')');
127 }
128 }
129 if ((clause = params.pseudoClassNames).length > 0) {
130 for (i = 0; i < clause.length; i++) {
131 var match = clause[i].match(/^([^(]+)(?:\((.*)\))?$/);
132 var pseudoClass = match[1];
133 var pseudoClassArgument = match[2];
134 switch (pseudoClass) {
135 case 'root':
136 conditions.push('element.nodeType == 9 || element === element.ownerDocument.documentElement'); break;
137 case 'nth-child':
138 case 'nth-last-child':
139 case 'nth-of-type':
140 case 'nth-last-of-type':
141 match = pseudoClassArgument.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
142 if (!match) {
143 throw "Invalid argument to pseudo element nth-child: " + pseudoClassArgument;
144 }
145 var a, b;
146 if (match[0] == 'odd') {
147 a = 2;
148 b = 1;
149 } else if (match[0] == 'even') {
150 a = 2;
151 b = 0;
152 } else {
153 a = match[2] && parseInt(match, 10) || null;
154 b = parseInt(match[3], 10);
155 }
156 conditions.push('this.nthChild(element,' + a + ',' + b
157 + ',' + !!pseudoClass.match('^nth-last') // Reverse
158 + ',' + !!pseudoClass.match('of-type$') // Restrict to same tagName
159 + ')');
160 break;
161 case 'first-child':
162 conditions.push('this.nthChild(element, null, 1)');
163 break;
164 case 'last-child':
165 conditions.push('this.nthChild(element, null, 1, true)');
166 break;
167 case 'first-of-type':
168 conditions.push('this.nthChild(element, null, 1, false, true)');
169 break;
170 case 'last-of-type':
171 conditions.push('this.nthChild(element, null, 1, true, true)');
172 break;
173 case 'only-child':
174 conditions.push(childElements('element.parentNode') + '.length == 1');
175 break;
176 case 'only-of-type':
177 conditions.push('MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, ' + childElements('element.parentNode') + ').length == 1');
178 break;
179 case 'empty':
180 conditions.push('element.childNodes.length == 0');
181 break;
182 case 'enabled':
183 conditions.push('(this.isUIElement(element) && element.disabled === false)');
184 break;
185 case 'disabled':
186 conditions.push('(this.isUIElement(element) && element.disabled === true)');
187 break;
188 case 'checked':
189 conditions.push('(this.isUIElement(element) && element.checked === true)');
190 break;
191 case 'not':
192 var subselector = new MochiKit.Selector.Selector(pseudoClassArgument);
193 conditions.push('!( ' + subselector.buildMatchExpression() + ')');
194 break;
195 }
196 }
197 }
198 if (clause = params.attributes) {
199 MochiKit.Base.map(function (attribute) {
200 var value = 'MochiKit.DOM.getNodeAttribute(element, ' + repr(attribute.name) + ')';
201 var splitValueBy = function (delimiter) {
202 return value + '.split(' + repr(delimiter) + ')';
203 };
204 conditions.push(value + ' != null');
205 switch (attribute.operator) {
206 case '=':
207 conditions.push(value + ' == ' + repr(attribute.value));
208 break;
209 case '~=':
210 conditions.push('MochiKit.Base.findValue(' + splitValueBy(' ') + ', ' + repr(attribute.value) + ') > -1');
211 break;
212 case '^=':
213 conditions.push(value + '.substring(0, ' + attribute.value.length + ') == ' + repr(attribute.value));
214 break;
215 case '$=':
216 conditions.push(value + '.substring(' + value + '.length - ' + attribute.value.length + ') == ' + repr(attribute.value));
217 break;
218 case '*=':
219 conditions.push(value + '.match(' + repr(attribute.value) + ')');
220 break;
221 case '|=':
222 conditions.push(splitValueBy('-') + '[0].toUpperCase() == ' + repr(attribute.value.toUpperCase()));
223 break;
224 case '!=':
225 conditions.push(value + ' != ' + repr(attribute.value));
226 break;
227 case '':
228 case undefined:
229 // Condition already added above
230 break;
231 default:
232 throw 'Unknown operator ' + attribute.operator + ' in selector';
233 }
234 }, clause);
235 }
236
237 return conditions.join(' && ');
238 },
239
240 /** @id MochiKit.Selector.Selector.prototype.compileMatcher */
241 compileMatcher: function () {
242 var code = 'return (!element.tagName) ? false : ' +
243 this.buildMatchExpression() + ';';
244 this.match = new Function('element', code);
245 },
246
247 /** @id MochiKit.Selector.Selector.prototype.nthChild */
248 nthChild: function (element, a, b, reverse, sametag){
249 var siblings = MochiKit.Base.filter(function (node) {
250 return node.nodeType == 1;
251 }, element.parentNode.childNodes);
252 if (sametag) {
253 siblings = MochiKit.Base.filter(function (node) {
254 return node.tagName == element.tagName;
255 }, siblings);
256 }
257 if (reverse) {
258 siblings = MochiKit.Iter.reversed(siblings);
259 }
260 if (a) {
261 var actualIndex = MochiKit.Base.findIdentical(siblings, element);
262 return ((actualIndex + 1 - b) / a) % 1 == 0;
263 } else {
264 return b == MochiKit.Base.findIdentical(siblings, element) + 1;
265 }
266 },
267
268 /** @id MochiKit.Selector.Selector.prototype.isUIElement */
269 isUIElement: function (element) {
270 return MochiKit.Base.findValue(['input', 'button', 'select', 'option', 'textarea', 'object'],
271 element.tagName.toLowerCase()) > -1;
272 },
273
274 /** @id MochiKit.Selector.Selector.prototype.findElements */
275 findElements: function (scope, axis) {
276 var element;
277
278 if (axis == undefined) {
279 axis = "";
280 }
281
282 function inScope(element, scope) {
283 if (axis == "") {
284 return MochiKit.DOM.isChildNode(element, scope);
285 } else if (axis == ">") {
286 return element.parentNode === scope;
287 } else if (axis == "+") {
288 return element === nextSiblingElement(scope);
289 } else if (axis == "~") {
290 var sibling = scope;
291 while (sibling = nextSiblingElement(sibling)) {
292 if (element === sibling) {
293 return true;
294 }
295 }
296 return false;
297 } else {
298 throw "Invalid axis: " + axis;
299 }
300 }
301
302 if (element = MochiKit.DOM.getElement(this.params.id)) {
303 if (this.match(element)) {
304 if (!scope || inScope(element, scope)) {
305 return [element];
306 }
307 }
308 }
309
310 function nextSiblingElement(node) {
311 node = node.nextSibling;
312 while (node && node.nodeType != 1) {
313 node = node.nextSibling;
314 }
315 return node;
316 }
317
318 if (axis == "") {
319 scope = (scope || MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName || '*');
320 } else if (axis == ">") {
321 if (!scope) {
322 throw "> combinator not allowed without preceeding expression";
323 }
324 scope = MochiKit.Base.filter(function (node) {
325 return node.nodeType == 1;
326 }, scope.childNodes);
327 } else if (axis == "+") {
328 if (!scope) {
329 throw "+ combinator not allowed without preceeding expression";
330 }
331 scope = nextSiblingElement(scope) && [nextSiblingElement(scope)];
332 } else if (axis == "~") {
333 if (!scope) {
334 throw "~ combinator not allowed without preceeding expression";
335 }
336 var newscope = [];
337 while (nextSiblingElement(scope)) {
338 scope = nextSiblingElement(scope);
339 newscope.push(scope);
340 }
341 scope = newscope;
342 }
343
344 if (!scope) {
345 return [];
346 }
347
348 var results = MochiKit.Base.filter(MochiKit.Base.bind(function (scopeElt) {
349 return this.match(scopeElt);
350 }, this), scope);
351
352 return results;
353 },
354
355 /** @id MochiKit.Selector.Selector.prototype.repr */
356 repr: function () {
357 return 'Selector(' + this.expression + ')';
358 },
359
360 toString: MochiKit.Base.forwardCall("repr")
361};
362
363MochiKit.Base.update(MochiKit.Selector, {
364
365 /** @id MochiKit.Selector.findChildElements */
366 findChildElements: function (element, expressions) {
367 element = MochiKit.DOM.getElement(element);
368 var uniq = function(arr) {
369 var res = [];
370 for (var i = 0; i < arr.length; i++) {
371 if (MochiKit.Base.findIdentical(res, arr[i]) < 0) {
372 res.push(arr[i]);
373 }
374 }
375 return res;
376 };
377 return MochiKit.Base.flattenArray(MochiKit.Base.map(function (expression) {
378 try {
379 var res = element.querySelectorAll(expression);
380 return Array.prototype.slice.call(res, 0);
381 } catch (ignore) {
382 // No querySelectorAll or extended expression syntax used
383 }
384 var nextScope = "";
385 var reducer = function (results, expr) {
386 var match = expr.match(/^[>+~]$/);
387 if (match) {
388 nextScope = match[0];
389 return results;
390 } else {
391 var selector = new MochiKit.Selector.Selector(expr);
392 var elements = MochiKit.Iter.reduce(function (elements, result) {
393 return MochiKit.Base.extend(elements, selector.findElements(result || element, nextScope));
394 }, results, []);
395 nextScope = "";
396 return elements;
397 }
398 };
399 var exprs = expression.replace(/(^\s+|\s+$)/g, '').split(/\s+/);
400 return uniq(MochiKit.Iter.reduce(reducer, exprs, [null]));
401 }, expressions));
402 },
403
404 findDocElements: function () {
405 return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(), arguments);
406 },
407
408 __new__: function () {
409 this.$$ = this.findDocElements;
410 MochiKit.Base.nameFunctions(this);
411 }
412});
413
414MochiKit.Selector.__new__();
415
416MochiKit.Base._exportSymbols(this, MochiKit.Selector);
diff --git a/frontend/delta/js/MochiKit/Signal.js b/frontend/delta/js/MochiKit/Signal.js
new file mode 100644
index 0000000..58d0363
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Signal.js
@@ -0,0 +1,924 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Signal 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Signal', '1.5', ['Base', 'DOM']);
35
36MochiKit.Signal._observers = [];
37
38/** @id MochiKit.Signal.Event */
39MochiKit.Signal.Event = function (src, e) {
40 this._event = e || window.event;
41 this._src = src;
42};
43MochiKit.Signal.Event.__export__ = false;
44
45MochiKit.Base.update(MochiKit.Signal.Event.prototype, {
46
47 __repr__: function () {
48 var repr = MochiKit.Base.repr;
49 var str = '{event(): ' + repr(this.event()) +
50 ', src(): ' + repr(this.src()) +
51 ', type(): ' + repr(this.type()) +
52 ', target(): ' + repr(this.target());
53
54 if (this.type() &&
55 this.type().indexOf('key') === 0 ||
56 this.type().indexOf('mouse') === 0 ||
57 this.type().indexOf('click') != -1 ||
58 this.type() == 'contextmenu') {
59 str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) +
60 ', ctrl: ' + repr(this.modifier().ctrl) +
61 ', meta: ' + repr(this.modifier().meta) +
62 ', shift: ' + repr(this.modifier().shift) +
63 ', any: ' + repr(this.modifier().any) + '}';
64 }
65
66 if (this.type() && this.type().indexOf('key') === 0) {
67 str += ', key(): {code: ' + repr(this.key().code) +
68 ', string: ' + repr(this.key().string) + '}';
69 }
70
71 if (this.type() && (
72 this.type().indexOf('mouse') === 0 ||
73 this.type().indexOf('click') != -1 ||
74 this.type() == 'contextmenu')) {
75
76 str += ', mouse(): {page: ' + repr(this.mouse().page) +
77 ', client: ' + repr(this.mouse().client);
78
79 if (this.type() != 'mousemove' && this.type() != 'mousewheel') {
80 str += ', button: {left: ' + repr(this.mouse().button.left) +
81 ', middle: ' + repr(this.mouse().button.middle) +
82 ', right: ' + repr(this.mouse().button.right) + '}';
83 }
84 if (this.type() == 'mousewheel') {
85 str += ', wheel: ' + repr(this.mouse().wheel);
86 }
87 str += '}';
88 }
89 if (this.type() == 'mouseover' || this.type() == 'mouseout' ||
90 this.type() == 'mouseenter' || this.type() == 'mouseleave') {
91 str += ', relatedTarget(): ' + repr(this.relatedTarget());
92 }
93 str += '}';
94 return str;
95 },
96
97 /** @id MochiKit.Signal.Event.prototype.toString */
98 toString: function () {
99 return this.__repr__();
100 },
101
102 /** @id MochiKit.Signal.Event.prototype.src */
103 src: function () {
104 return this._src;
105 },
106
107 /** @id MochiKit.Signal.Event.prototype.event */
108 event: function () {
109 return this._event;
110 },
111
112 /** @id MochiKit.Signal.Event.prototype.type */
113 type: function () {
114 if (this._event.type === "DOMMouseScroll") {
115 return "mousewheel";
116 } else {
117 return this._event.type || undefined;
118 }
119 },
120
121 /** @id MochiKit.Signal.Event.prototype.target */
122 target: function () {
123 return this._event.target || this._event.srcElement;
124 },
125
126 _relatedTarget: null,
127 /** @id MochiKit.Signal.Event.prototype.relatedTarget */
128 relatedTarget: function () {
129 if (this._relatedTarget !== null) {
130 return this._relatedTarget;
131 }
132
133 var elem = null;
134 if (this.type() == 'mouseover' || this.type() == 'mouseenter') {
135 elem = (this._event.relatedTarget ||
136 this._event.fromElement);
137 } else if (this.type() == 'mouseout' || this.type() == 'mouseleave') {
138 elem = (this._event.relatedTarget ||
139 this._event.toElement);
140 }
141 try {
142 if (elem !== null && elem.nodeType !== null) {
143 this._relatedTarget = elem;
144 return elem;
145 }
146 } catch (ignore) {
147 // Firefox 3 throws a permission denied error when accessing
148 // any property on XUL elements (e.g. scrollbars)...
149 }
150
151 return undefined;
152 },
153
154 _modifier: null,
155 /** @id MochiKit.Signal.Event.prototype.modifier */
156 modifier: function () {
157 if (this._modifier !== null) {
158 return this._modifier;
159 }
160 var m = {};
161 m.alt = this._event.altKey;
162 m.ctrl = this._event.ctrlKey;
163 m.meta = this._event.metaKey || false; // IE and Opera punt here
164 m.shift = this._event.shiftKey;
165 m.any = m.alt || m.ctrl || m.shift || m.meta;
166 this._modifier = m;
167 return m;
168 },
169
170 _key: null,
171 /** @id MochiKit.Signal.Event.prototype.key */
172 key: function () {
173 if (this._key !== null) {
174 return this._key;
175 }
176 var k = {};
177 if (this.type() && this.type().indexOf('key') === 0) {
178
179 /*
180
181 If you're looking for a special key, look for it in keydown or
182 keyup, but never keypress. If you're looking for a Unicode
183 chracter, look for it with keypress, but never keyup or
184 keydown.
185
186 Notes:
187
188 FF key event behavior:
189 key event charCode keyCode
190 DOWN ku,kd 0 40
191 DOWN kp 0 40
192 ESC ku,kd 0 27
193 ESC kp 0 27
194 a ku,kd 0 65
195 a kp 97 0
196 shift+a ku,kd 0 65
197 shift+a kp 65 0
198 1 ku,kd 0 49
199 1 kp 49 0
200 shift+1 ku,kd 0 0
201 shift+1 kp 33 0
202
203 IE key event behavior:
204 (IE doesn't fire keypress events for special keys.)
205 key event keyCode
206 DOWN ku,kd 40
207 DOWN kp undefined
208 ESC ku,kd 27
209 ESC kp 27
210 a ku,kd 65
211 a kp 97
212 shift+a ku,kd 65
213 shift+a kp 65
214 1 ku,kd 49
215 1 kp 49
216 shift+1 ku,kd 49
217 shift+1 kp 33
218
219 Safari key event behavior:
220 (Safari sets charCode and keyCode to something crazy for
221 special keys.)
222 key event charCode keyCode
223 DOWN ku,kd 63233 40
224 DOWN kp 63233 63233
225 ESC ku,kd 27 27
226 ESC kp 27 27
227 a ku,kd 97 65
228 a kp 97 97
229 shift+a ku,kd 65 65
230 shift+a kp 65 65
231 1 ku,kd 49 49
232 1 kp 49 49
233 shift+1 ku,kd 33 49
234 shift+1 kp 33 33
235
236 */
237
238 /* look for special keys here */
239 if (this.type() == 'keydown' || this.type() == 'keyup') {
240 k.code = this._event.keyCode;
241 k.string = (MochiKit.Signal._specialKeys[k.code] ||
242 'KEY_UNKNOWN');
243 this._key = k;
244 return k;
245
246 /* look for characters here */
247 } else if (this.type() == 'keypress') {
248
249 /*
250
251 Special key behavior:
252
253 IE: does not fire keypress events for special keys
254 FF: sets charCode to 0, and sets the correct keyCode
255 Safari: sets keyCode and charCode to something stupid
256
257 */
258
259 k.code = 0;
260 k.string = '';
261
262 if (typeof(this._event.charCode) != 'undefined' &&
263 this._event.charCode !== 0 &&
264 !MochiKit.Signal._specialMacKeys[this._event.charCode]) {
265 k.code = this._event.charCode;
266 k.string = String.fromCharCode(k.code);
267 } else if (this._event.keyCode &&
268 typeof(this._event.charCode) == 'undefined') { // IE
269 k.code = this._event.keyCode;
270 k.string = String.fromCharCode(k.code);
271 }
272
273 this._key = k;
274 return k;
275 }
276 }
277 return undefined;
278 },
279
280 _mouse: null,
281 /** @id MochiKit.Signal.Event.prototype.mouse */
282 mouse: function () {
283 if (this._mouse !== null) {
284 return this._mouse;
285 }
286
287 var m = {};
288 var e = this._event;
289
290 if (this.type() && (
291 this.type().indexOf('mouse') === 0 ||
292 this.type().indexOf('drag') === 0 ||
293 this.type().indexOf('click') != -1 ||
294 this.type() == 'contextmenu')) {
295
296 m.client = { x: 0, y: 0 };
297 if (e.clientX || e.clientY) {
298 m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX;
299 m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY;
300 }
301
302 m.page = { x: 0, y: 0 };
303 if (e.pageX || e.pageY) {
304 m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX;
305 m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY;
306 } else {
307 /*
308
309 The IE shortcut can be off by two. We fix it. See:
310 http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
311
312 This is similar to the method used in
313 MochiKit.Style.getElementPosition().
314
315 */
316 var de = MochiKit.DOM._document.documentElement;
317 var b = MochiKit.DOM._document.body;
318
319 m.page.x = e.clientX +
320 (de.scrollLeft || b.scrollLeft) -
321 (de.clientLeft || 0);
322
323 m.page.y = e.clientY +
324 (de.scrollTop || b.scrollTop) -
325 (de.clientTop || 0);
326
327 }
328 if (this.type() != 'mousemove' && this.type() != 'mousewheel') {
329 m.button = {};
330 m.button.left = false;
331 m.button.right = false;
332 m.button.middle = false;
333
334 /* we could check e.button, but which is more consistent */
335 if (e.which) {
336 m.button.left = (e.which == 1);
337 m.button.middle = (e.which == 2);
338 m.button.right = (e.which == 3);
339
340 /*
341
342 Mac browsers and right click:
343
344 - Safari doesn't fire any click events on a right
345 click:
346 http://bugs.webkit.org/show_bug.cgi?id=6595
347
348 - Firefox fires the event, and sets ctrlKey = true
349
350 - Opera fires the event, and sets metaKey = true
351
352 oncontextmenu is fired on right clicks between
353 browsers and across platforms.
354
355 */
356
357 } else {
358 m.button.left = !!(e.button & 1);
359 m.button.right = !!(e.button & 2);
360 m.button.middle = !!(e.button & 4);
361 }
362 }
363 if (this.type() == 'mousewheel') {
364 m.wheel = { x: 0, y: 0 };
365 if (e.wheelDeltaX || e.wheelDeltaY) {
366 m.wheel.x = e.wheelDeltaX / -40 || 0;
367 m.wheel.y = e.wheelDeltaY / -40 || 0;
368 } else if (e.wheelDelta) {
369 m.wheel.y = e.wheelDelta / -40;
370 } else {
371 m.wheel.y = e.detail || 0;
372 }
373 }
374 this._mouse = m;
375 return m;
376 }
377 return undefined;
378 },
379
380 /** @id MochiKit.Signal.Event.prototype.stop */
381 stop: function () {
382 this.stopPropagation();
383 this.preventDefault();
384 },
385
386 /** @id MochiKit.Signal.Event.prototype.stopPropagation */
387 stopPropagation: function () {
388 if (this._event.stopPropagation) {
389 this._event.stopPropagation();
390 } else {
391 this._event.cancelBubble = true;
392 }
393 },
394
395 /** @id MochiKit.Signal.Event.prototype.preventDefault */
396 preventDefault: function () {
397 if (this._event.preventDefault) {
398 this._event.preventDefault();
399 } else if (this._confirmUnload === null) {
400 this._event.returnValue = false;
401 }
402 },
403
404 _confirmUnload: null,
405
406 /** @id MochiKit.Signal.Event.prototype.confirmUnload */
407 confirmUnload: function (msg) {
408 if (this.type() == 'beforeunload') {
409 this._confirmUnload = msg;
410 this._event.returnValue = msg;
411 }
412 }
413});
414
415/* Safari sets keyCode to these special values onkeypress. */
416MochiKit.Signal._specialMacKeys = {
417 3: 'KEY_ENTER',
418 63289: 'KEY_NUM_PAD_CLEAR',
419 63276: 'KEY_PAGE_UP',
420 63277: 'KEY_PAGE_DOWN',
421 63275: 'KEY_END',
422 63273: 'KEY_HOME',
423 63234: 'KEY_ARROW_LEFT',
424 63232: 'KEY_ARROW_UP',
425 63235: 'KEY_ARROW_RIGHT',
426 63233: 'KEY_ARROW_DOWN',
427 63302: 'KEY_INSERT',
428 63272: 'KEY_DELETE'
429};
430
431/* for KEY_F1 - KEY_F12 */
432(function () {
433 var _specialMacKeys = MochiKit.Signal._specialMacKeys;
434 for (var i = 63236; i <= 63242; i++) {
435 // no F0
436 _specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1);
437 }
438})();
439
440/* Standard keyboard key codes. */
441MochiKit.Signal._specialKeys = {
442 8: 'KEY_BACKSPACE',
443 9: 'KEY_TAB',
444 12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only
445 13: 'KEY_ENTER',
446 16: 'KEY_SHIFT',
447 17: 'KEY_CTRL',
448 18: 'KEY_ALT',
449 19: 'KEY_PAUSE',
450 20: 'KEY_CAPS_LOCK',
451 27: 'KEY_ESCAPE',
452 32: 'KEY_SPACEBAR',
453 33: 'KEY_PAGE_UP',
454 34: 'KEY_PAGE_DOWN',
455 35: 'KEY_END',
456 36: 'KEY_HOME',
457 37: 'KEY_ARROW_LEFT',
458 38: 'KEY_ARROW_UP',
459 39: 'KEY_ARROW_RIGHT',
460 40: 'KEY_ARROW_DOWN',
461 44: 'KEY_PRINT_SCREEN',
462 45: 'KEY_INSERT',
463 46: 'KEY_DELETE',
464 59: 'KEY_SEMICOLON', // weird, for Safari and IE only
465 91: 'KEY_WINDOWS_LEFT',
466 92: 'KEY_WINDOWS_RIGHT',
467 93: 'KEY_SELECT',
468 106: 'KEY_NUM_PAD_ASTERISK',
469 107: 'KEY_NUM_PAD_PLUS_SIGN',
470 109: 'KEY_NUM_PAD_HYPHEN-MINUS',
471 110: 'KEY_NUM_PAD_FULL_STOP',
472 111: 'KEY_NUM_PAD_SOLIDUS',
473 144: 'KEY_NUM_LOCK',
474 145: 'KEY_SCROLL_LOCK',
475 186: 'KEY_SEMICOLON',
476 187: 'KEY_EQUALS_SIGN',
477 188: 'KEY_COMMA',
478 189: 'KEY_HYPHEN-MINUS',
479 190: 'KEY_FULL_STOP',
480 191: 'KEY_SOLIDUS',
481 192: 'KEY_GRAVE_ACCENT',
482 219: 'KEY_LEFT_SQUARE_BRACKET',
483 220: 'KEY_REVERSE_SOLIDUS',
484 221: 'KEY_RIGHT_SQUARE_BRACKET',
485 222: 'KEY_APOSTROPHE'
486 // undefined: 'KEY_UNKNOWN'
487};
488
489(function () {
490 /* for KEY_0 - KEY_9 */
491 var _specialKeys = MochiKit.Signal._specialKeys;
492 for (var i = 48; i <= 57; i++) {
493 _specialKeys[i] = 'KEY_' + (i - 48);
494 }
495
496 /* for KEY_A - KEY_Z */
497 for (i = 65; i <= 90; i++) {
498 _specialKeys[i] = 'KEY_' + String.fromCharCode(i);
499 }
500
501 /* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */
502 for (i = 96; i <= 105; i++) {
503 _specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96);
504 }
505
506 /* for KEY_F1 - KEY_F12 */
507 for (i = 112; i <= 123; i++) {
508 // no F0
509 _specialKeys[i] = 'KEY_F' + (i - 112 + 1);
510 }
511})();
512
513/* Internal object to keep track of created signals. */
514MochiKit.Signal.Ident = function (ident) {
515 this.source = ident.source;
516 this.signal = ident.signal;
517 this.listener = ident.listener;
518 this.isDOM = ident.isDOM;
519 this.objOrFunc = ident.objOrFunc;
520 this.funcOrStr = ident.funcOrStr;
521 this.connected = ident.connected;
522};
523MochiKit.Signal.Ident.__export__ = false;
524MochiKit.Signal.Ident.prototype = {};
525
526MochiKit.Base.update(MochiKit.Signal, {
527
528 _unloadCache: function () {
529 var self = MochiKit.Signal;
530 var observers = self._observers;
531
532 for (var i = 0; i < observers.length; i++) {
533 if (observers[i].signal !== 'onload' && observers[i].signal !== 'onunload') {
534 self._disconnect(observers[i]);
535 }
536 }
537 },
538
539 _listener: function (src, sig, func, obj, isDOM) {
540 var self = MochiKit.Signal;
541 var E = self.Event;
542 if (!isDOM) {
543 /* We don't want to re-bind already bound methods */
544 if (typeof(func.im_self) == 'undefined') {
545 return MochiKit.Base.bindLate(func, obj);
546 } else {
547 return func;
548 }
549 }
550 obj = obj || src;
551 if (typeof(func) == "string") {
552 if (sig === 'onload' || sig === 'onunload') {
553 return function (nativeEvent) {
554 obj[func].apply(obj, [new E(src, nativeEvent)]);
555
556 var ident = new MochiKit.Signal.Ident({
557 source: src, signal: sig, objOrFunc: obj, funcOrStr: func});
558
559 MochiKit.Signal._disconnect(ident);
560 };
561 } else {
562 return function (nativeEvent) {
563 obj[func].apply(obj, [new E(src, nativeEvent)]);
564 };
565 }
566 } else {
567 if (sig === 'onload' || sig === 'onunload') {
568 return function (nativeEvent) {
569 func.apply(obj, [new E(src, nativeEvent)]);
570
571 var ident = new MochiKit.Signal.Ident({
572 source: src, signal: sig, objOrFunc: func});
573
574 MochiKit.Signal._disconnect(ident);
575 };
576 } else {
577 return function (nativeEvent) {
578 func.apply(obj, [new E(src, nativeEvent)]);
579 };
580 }
581 }
582 },
583
584 _browserAlreadyHasMouseEnterAndLeave: function () {
585 return /MSIE/.test(navigator.userAgent);
586 },
587
588 _browserLacksMouseWheelEvent: function () {
589 return /Gecko\//.test(navigator.userAgent);
590 },
591
592 _mouseEnterListener: function (src, sig, func, obj) {
593 var E = MochiKit.Signal.Event;
594 return function (nativeEvent) {
595 var e = new E(src, nativeEvent);
596 try {
597 e.relatedTarget().nodeName;
598 } catch (err) {
599 /* probably hit a permission denied error; possibly one of
600 * firefox's screwy anonymous DIVs inside an input element.
601 * Allow this event to propogate up.
602 */
603 return;
604 }
605 e.stop();
606 if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) {
607 /* We've moved between our node and a child. Ignore. */
608 return;
609 }
610 e.type = function () { return sig; };
611 if (typeof(func) == "string") {
612 return obj[func].apply(obj, [e]);
613 } else {
614 return func.apply(obj, [e]);
615 }
616 };
617 },
618
619 _getDestPair: function (objOrFunc, funcOrStr) {
620 var obj = null;
621 var func = null;
622 if (typeof(funcOrStr) != 'undefined') {
623 obj = objOrFunc;
624 func = funcOrStr;
625 if (typeof(funcOrStr) == 'string') {
626 if (typeof(objOrFunc[funcOrStr]) != "function") {
627 throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
628 }
629 } else if (typeof(funcOrStr) != 'function') {
630 throw new Error("'funcOrStr' must be a function or string");
631 }
632 } else if (typeof(objOrFunc) != "function") {
633 throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
634 } else {
635 func = objOrFunc;
636 }
637 return [obj, func];
638 },
639
640 /** @id MochiKit.Signal.connect */
641 connect: function (src, sig, objOrFunc/* optional */, funcOrStr) {
642 if (typeof(src) == "string") {
643 src = MochiKit.DOM.getElement(src);
644 }
645 var self = MochiKit.Signal;
646
647 if (typeof(sig) != 'string') {
648 throw new Error("'sig' must be a string");
649 }
650
651 var destPair = self._getDestPair(objOrFunc, funcOrStr);
652 var obj = destPair[0];
653 var func = destPair[1];
654 if (typeof(obj) == 'undefined' || obj === null) {
655 obj = src;
656 }
657
658 var isDOM = !!(src.addEventListener || src.attachEvent);
659 if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave")
660 && !self._browserAlreadyHasMouseEnterAndLeave()) {
661 var listener = self._mouseEnterListener(src, sig.substr(2), func, obj);
662 if (sig === "onmouseenter") {
663 sig = "onmouseover";
664 } else {
665 sig = "onmouseout";
666 }
667 } else if (isDOM && sig == "onmousewheel" && self._browserLacksMouseWheelEvent()) {
668 var listener = self._listener(src, sig, func, obj, isDOM);
669 sig = "onDOMMouseScroll";
670 } else {
671 var listener = self._listener(src, sig, func, obj, isDOM);
672 }
673
674 if (src.addEventListener) {
675 src.addEventListener(sig.substr(2), listener, false);
676 } else if (src.attachEvent) {
677 src.attachEvent(sig, listener); // useCapture unsupported
678 }
679
680 var ident = new MochiKit.Signal.Ident({
681 source: src,
682 signal: sig,
683 listener: listener,
684 isDOM: isDOM,
685 objOrFunc: objOrFunc,
686 funcOrStr: funcOrStr,
687 connected: true
688 });
689 self._observers.push(ident);
690
691 if (!isDOM && typeof(src.__connect__) == 'function') {
692 var args = MochiKit.Base.extend([ident], arguments, 1);
693 src.__connect__.apply(src, args);
694 }
695
696 return ident;
697 },
698
699 /** @id MochiKit.Signal.connectOnce */
700 connectOnce: function (src, sig, objOrFunc/* optional */, funcOrStr) {
701 var self = MochiKit.Signal;
702 var ident1 = self.connect(src, sig, objOrFunc, funcOrStr);
703 var ident2;
704 ident2 = self.connect(src, sig, function() {
705 self.disconnect(ident1);
706 self.disconnect(ident2);
707 });
708 return ident1;
709 },
710
711 _disconnect: function (ident) {
712 // already disconnected
713 if (!ident.connected) {
714 return;
715 }
716 ident.connected = false;
717 var src = ident.source;
718 var sig = ident.signal;
719 var listener = ident.listener;
720 // check isDOM
721 if (!ident.isDOM) {
722 if (typeof(src.__disconnect__) == 'function') {
723 src.__disconnect__(ident, sig, ident.objOrFunc, ident.funcOrStr);
724 }
725 return;
726 }
727 if (src.removeEventListener) {
728 src.removeEventListener(sig.substr(2), listener, false);
729 } else if (src.detachEvent) {
730 src.detachEvent(sig, listener); // useCapture unsupported
731 } else {
732 throw new Error("'src' must be a DOM element");
733 }
734 },
735
736 /** @id MochiKit.Signal.disconnect */
737 disconnect: function (ident) {
738 var self = MochiKit.Signal;
739 var observers = self._observers;
740 var m = MochiKit.Base;
741 if (arguments.length > 1) {
742 // compatibility API
743 var src = arguments[0];
744 if (typeof(src) == "string") {
745 src = MochiKit.DOM.getElement(src);
746 }
747 var sig = arguments[1];
748 var obj = arguments[2];
749 var func = arguments[3];
750 for (var i = observers.length - 1; i >= 0; i--) {
751 var o = observers[i];
752 if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) {
753 self._disconnect(o);
754 if (self._lock === 0) {
755 observers.splice(i, 1);
756 } else {
757 self._dirty = true;
758 }
759 return true;
760 }
761 }
762 } else {
763 var idx = m.findIdentical(observers, ident);
764 if (idx >= 0) {
765 self._disconnect(ident);
766 if (self._lock === 0) {
767 observers.splice(idx, 1);
768 } else {
769 self._dirty = true;
770 }
771 return true;
772 }
773 }
774 return false;
775 },
776
777 /** @id MochiKit.Signal.disconnectAllTo */
778 disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) {
779 var self = MochiKit.Signal;
780 var observers = self._observers;
781 var disconnect = self._disconnect;
782 var lock = self._lock;
783 var dirty = self._dirty;
784 if (typeof(funcOrStr) === 'undefined') {
785 funcOrStr = null;
786 }
787 for (var i = observers.length - 1; i >= 0; i--) {
788 var ident = observers[i];
789 if (ident.objOrFunc === objOrFunc &&
790 (funcOrStr === null || ident.funcOrStr === funcOrStr)) {
791 disconnect(ident);
792 if (lock === 0) {
793 observers.splice(i, 1);
794 } else {
795 dirty = true;
796 }
797 }
798 }
799 self._dirty = dirty;
800 },
801
802 /** @id MochiKit.Signal.disconnectAll */
803 disconnectAll: function (src/* optional */, sig) {
804 if (typeof(src) == "string") {
805 src = MochiKit.DOM.getElement(src);
806 }
807 var m = MochiKit.Base;
808 var signals = m.flattenArguments(m.extend(null, arguments, 1));
809 var self = MochiKit.Signal;
810 var disconnect = self._disconnect;
811 var observers = self._observers;
812 var i, ident;
813 var lock = self._lock;
814 var dirty = self._dirty;
815 if (signals.length === 0) {
816 // disconnect all
817 for (i = observers.length - 1; i >= 0; i--) {
818 ident = observers[i];
819 if (ident.source === src) {
820 disconnect(ident);
821 if (lock === 0) {
822 observers.splice(i, 1);
823 } else {
824 dirty = true;
825 }
826 }
827 }
828 } else {
829 var sigs = {};
830 for (i = 0; i < signals.length; i++) {
831 sigs[signals[i]] = true;
832 }
833 for (i = observers.length - 1; i >= 0; i--) {
834 ident = observers[i];
835 if (ident.source === src && ident.signal in sigs) {
836 disconnect(ident);
837 if (lock === 0) {
838 observers.splice(i, 1);
839 } else {
840 dirty = true;
841 }
842 }
843 }
844 }
845 self._dirty = dirty;
846 },
847
848 /** @id MochiKit.Signal.signal */
849 signal: function (src, sig) {
850 var self = MochiKit.Signal;
851 var observers = self._observers;
852 if (typeof(src) == "string") {
853 src = MochiKit.DOM.getElement(src);
854 }
855 var args = MochiKit.Base.extend(null, arguments, 2);
856 var errors = [];
857 self._lock++;
858 for (var i = 0; i < observers.length; i++) {
859 var ident = observers[i];
860 if (ident.source === src && ident.signal === sig &&
861 ident.connected) {
862 try {
863 if (ident.isDOM && ident.funcOrStr != null) {
864 var obj = ident.objOrFunc;
865 obj[ident.funcOrStr].apply(obj, args);
866 } else if (ident.isDOM) {
867 ident.objOrFunc.apply(src, args);
868 } else {
869 ident.listener.apply(src, args);
870 }
871 } catch (e) {
872 errors.push(e);
873 }
874 }
875 }
876 self._lock--;
877 if (self._lock === 0 && self._dirty) {
878 self._dirty = false;
879 for (var i = observers.length - 1; i >= 0; i--) {
880 if (!observers[i].connected) {
881 observers.splice(i, 1);
882 }
883 }
884 }
885 if (errors.length == 1) {
886 throw errors[0];
887 } else if (errors.length > 1) {
888 var e = new Error("Multiple errors thrown in handling 'sig', see errors property");
889 e.errors = errors;
890 throw e;
891 }
892 }
893
894});
895
896MochiKit.Signal.__new__ = function (win) {
897 var m = MochiKit.Base;
898 this._document = document;
899 this._window = win;
900 this._lock = 0;
901 this._dirty = false;
902
903 try {
904 this.connect(window, 'onunload', this._unloadCache);
905 } catch (e) {
906 // pass: might not be a browser
907 }
908
909 m.nameFunctions(this);
910};
911
912MochiKit.Signal.__new__(this);
913
914//
915// XXX: Internet Explorer blows
916//
917if (MochiKit.__export__) {
918 connect = MochiKit.Signal.connect;
919 disconnect = MochiKit.Signal.disconnect;
920 disconnectAll = MochiKit.Signal.disconnectAll;
921 signal = MochiKit.Signal.signal;
922}
923
924MochiKit.Base._exportSymbols(this, MochiKit.Signal);
diff --git a/frontend/delta/js/MochiKit/Sortable.js b/frontend/delta/js/MochiKit/Sortable.js
new file mode 100644
index 0000000..49ea390
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Sortable.js
@@ -0,0 +1,592 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
26 Mochi-ized By Thomas Herve (_firstname_@nimail.org)
27
28See scriptaculous.js for full license.
29
30***/
31
32MochiKit.Base.module(MochiKit, 'Sortable', '1.5', ['Base', 'Iter', 'DOM', 'Position', 'DragAndDrop']);
33
34MochiKit.Base.update(MochiKit.Sortable, {
35 __export__: false,
36
37 /***
38
39 Manage sortables. Mainly use the create function to add a sortable.
40
41 ***/
42 sortables: {},
43
44 _findRootElement: function (element) {
45 while (element.tagName.toUpperCase() != "BODY") {
46 if (element.id && MochiKit.Sortable.sortables[element.id]) {
47 return element;
48 }
49 element = element.parentNode;
50 }
51 },
52
53 _createElementId: function(element) {
54 if (element.id == null || element.id == "") {
55 var d = MochiKit.DOM;
56 var id;
57 var count = 1;
58 while (d.getElement(id = "sortable" + count) != null) {
59 count += 1;
60 }
61 d.setNodeAttribute(element, "id", id);
62 }
63 },
64
65 /** @id MochiKit.Sortable.options */
66 options: function (element) {
67 element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element));
68 if (!element) {
69 return;
70 }
71 return MochiKit.Sortable.sortables[element.id];
72 },
73
74 /** @id MochiKit.Sortable.destroy */
75 destroy: function (element){
76 var s = MochiKit.Sortable.options(element);
77 var b = MochiKit.Base;
78 var d = MochiKit.DragAndDrop;
79
80 if (s) {
81 MochiKit.Signal.disconnect(s.startHandle);
82 MochiKit.Signal.disconnect(s.endHandle);
83 b.map(function (dr) {
84 d.Droppables.remove(dr);
85 }, s.droppables);
86 b.map(function (dr) {
87 dr.destroy();
88 }, s.draggables);
89
90 delete MochiKit.Sortable.sortables[s.element.id];
91 }
92 },
93
94 /** @id MochiKit.Sortable.create */
95 create: function (element, options) {
96 element = MochiKit.DOM.getElement(element);
97 var self = MochiKit.Sortable;
98 self._createElementId(element);
99
100 /** @id MochiKit.Sortable.options */
101 options = MochiKit.Base.update({
102
103 /** @id MochiKit.Sortable.element */
104 element: element,
105
106 /** @id MochiKit.Sortable.tag */
107 tag: 'li', // assumes li children, override with tag: 'tagname'
108
109 /** @id MochiKit.Sortable.dropOnEmpty */
110 dropOnEmpty: false,
111
112 /** @id MochiKit.Sortable.tree */
113 tree: false,
114
115 /** @id MochiKit.Sortable.treeTag */
116 treeTag: 'ul',
117
118 /** @id MochiKit.Sortable.overlap */
119 overlap: 'vertical', // one of 'vertical', 'horizontal'
120
121 /** @id MochiKit.Sortable.constraint */
122 constraint: 'vertical', // one of 'vertical', 'horizontal', false
123 // also takes array of elements (or ids); or false
124
125 /** @id MochiKit.Sortable.containment */
126 containment: [element],
127
128 /** @id MochiKit.Sortable.handle */
129 handle: false, // or a CSS class
130
131 /** @id MochiKit.Sortable.only */
132 only: false,
133
134 /** @id MochiKit.Sortable.hoverclass */
135 hoverclass: null,
136
137 /** @id MochiKit.Sortable.ghosting */
138 ghosting: false,
139
140 /** @id MochiKit.Sortable.scroll */
141 scroll: false,
142
143 /** @id MochiKit.Sortable.scrollSensitivity */
144 scrollSensitivity: 20,
145
146 /** @id MochiKit.Sortable.scrollSpeed */
147 scrollSpeed: 15,
148
149 /** @id MochiKit.Sortable.format */
150 format: /^[^_]*_(.*)$/,
151
152 /** @id MochiKit.Sortable.onChange */
153 onChange: MochiKit.Base.noop,
154
155 /** @id MochiKit.Sortable.onUpdate */
156 onUpdate: MochiKit.Base.noop,
157
158 /** @id MochiKit.Sortable.accept */
159 accept: null
160 }, options);
161
162 // clear any old sortable with same element
163 self.destroy(element);
164
165 // build options for the draggables
166 var options_for_draggable = {
167 revert: true,
168 ghosting: options.ghosting,
169 scroll: options.scroll,
170 scrollSensitivity: options.scrollSensitivity,
171 scrollSpeed: options.scrollSpeed,
172 constraint: options.constraint,
173 handle: options.handle
174 };
175
176 if (options.starteffect) {
177 options_for_draggable.starteffect = options.starteffect;
178 }
179
180 if (options.reverteffect) {
181 options_for_draggable.reverteffect = options.reverteffect;
182 } else if (options.ghosting) {
183 options_for_draggable.reverteffect = function (innerelement) {
184 innerelement.style.top = 0;
185 innerelement.style.left = 0;
186 };
187 }
188
189 if (options.endeffect) {
190 options_for_draggable.endeffect = options.endeffect;
191 }
192
193 if (options.zindex) {
194 options_for_draggable.zindex = options.zindex;
195 }
196
197 // build options for the droppables
198 var options_for_droppable = {
199 overlap: options.overlap,
200 containment: options.containment,
201 hoverclass: options.hoverclass,
202 onhover: self.onHover,
203 tree: options.tree,
204 accept: options.accept
205 };
206
207 var options_for_tree = {
208 onhover: self.onEmptyHover,
209 overlap: options.overlap,
210 containment: options.containment,
211 hoverclass: options.hoverclass,
212 accept: options.accept
213 };
214
215 // fix for gecko engine
216 MochiKit.DOM.removeEmptyTextNodes(element);
217
218 options.draggables = [];
219 options.droppables = [];
220
221 // drop on empty handling
222 if (options.dropOnEmpty || options.tree) {
223 new MochiKit.DragAndDrop.Droppable(element, options_for_tree);
224 options.droppables.push(element);
225 }
226 MochiKit.Base.map(function (e) {
227 // handles are per-draggable
228 var handle = options.handle ?
229 MochiKit.DOM.getFirstElementByTagAndClassName(null,
230 options.handle, e) : e;
231 options.draggables.push(
232 new MochiKit.DragAndDrop.Draggable(e,
233 MochiKit.Base.update(options_for_draggable,
234 {handle: handle})));
235 new MochiKit.DragAndDrop.Droppable(e, options_for_droppable);
236 if (options.tree) {
237 e.treeNode = element;
238 }
239 options.droppables.push(e);
240 }, (self.findElements(element, options) || []));
241
242 if (options.tree) {
243 MochiKit.Base.map(function (e) {
244 new MochiKit.DragAndDrop.Droppable(e, options_for_tree);
245 e.treeNode = element;
246 options.droppables.push(e);
247 }, (self.findTreeElements(element, options) || []));
248 }
249
250 // keep reference
251 self.sortables[element.id] = options;
252
253 options.lastValue = self.serialize(element);
254 options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start',
255 MochiKit.Base.partial(self.onStart, element));
256 options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
257 MochiKit.Base.partial(self.onEnd, element));
258 },
259
260 /** @id MochiKit.Sortable.onStart */
261 onStart: function (element, draggable) {
262 var self = MochiKit.Sortable;
263 var options = self.options(element);
264 options.lastValue = self.serialize(options.element);
265 },
266
267 /** @id MochiKit.Sortable.onEnd */
268 onEnd: function (element, draggable) {
269 var self = MochiKit.Sortable;
270 self.unmark();
271 var options = self.options(element);
272 if (options.lastValue != self.serialize(options.element)) {
273 options.onUpdate(options.element);
274 }
275 },
276
277 // return all suitable-for-sortable elements in a guaranteed order
278
279 /** @id MochiKit.Sortable.findElements */
280 findElements: function (element, options) {
281 return MochiKit.Sortable.findChildren(element, options.only, options.tree, options.tag);
282 },
283
284 /** @id MochiKit.Sortable.findTreeElements */
285 findTreeElements: function (element, options) {
286 return MochiKit.Sortable.findChildren(
287 element, options.only, options.tree ? true : false, options.treeTag);
288 },
289
290 /** @id MochiKit.Sortable.findChildren */
291 findChildren: function (element, only, recursive, tagName) {
292 if (!element.hasChildNodes()) {
293 return null;
294 }
295 tagName = tagName.toUpperCase();
296 if (only) {
297 only = MochiKit.Base.flattenArray([only]);
298 }
299 var elements = [];
300 MochiKit.Base.map(function (e) {
301 if (e.tagName &&
302 e.tagName.toUpperCase() == tagName &&
303 (!only ||
304 MochiKit.Iter.some(only, function (c) {
305 return MochiKit.DOM.hasElementClass(e, c);
306 }))) {
307 elements.push(e);
308 }
309 if (recursive) {
310 var grandchildren = MochiKit.Sortable.findChildren(e, only, recursive, tagName);
311 if (grandchildren && grandchildren.length > 0) {
312 elements = elements.concat(grandchildren);
313 }
314 }
315 }, element.childNodes);
316 return elements;
317 },
318
319 /** @id MochiKit.Sortable.onHover */
320 onHover: function (element, dropon, overlap) {
321 if (MochiKit.DOM.isChildNode(dropon, element)) {
322 return;
323 }
324 var self = MochiKit.Sortable;
325
326 if (overlap > .33 && overlap < .66 && self.options(dropon).tree) {
327 return;
328 } else if (overlap > 0.5) {
329 self.mark(dropon, 'before');
330 if (dropon.previousSibling != element) {
331 var oldParentNode = element.parentNode;
332 element.style.visibility = 'hidden'; // fix gecko rendering
333 dropon.parentNode.insertBefore(element, dropon);
334 if (dropon.parentNode != oldParentNode) {
335 self.options(oldParentNode).onChange(element);
336 }
337 self.options(dropon.parentNode).onChange(element);
338 }
339 } else {
340 self.mark(dropon, 'after');
341 var nextElement = dropon.nextSibling || null;
342 if (nextElement != element) {
343 var oldParentNode = element.parentNode;
344 element.style.visibility = 'hidden'; // fix gecko rendering
345 dropon.parentNode.insertBefore(element, nextElement);
346 if (dropon.parentNode != oldParentNode) {
347 self.options(oldParentNode).onChange(element);
348 }
349 self.options(dropon.parentNode).onChange(element);
350 }
351 }
352 },
353
354 _offsetSize: function (element, type) {
355 if (type == 'vertical' || type == 'height') {
356 return element.offsetHeight;
357 } else {
358 return element.offsetWidth;
359 }
360 },
361
362 /** @id MochiKit.Sortable.onEmptyHover */
363 onEmptyHover: function (element, dropon, overlap) {
364 var oldParentNode = element.parentNode;
365 var self = MochiKit.Sortable;
366 var droponOptions = self.options(dropon);
367
368 if (!MochiKit.DOM.isChildNode(dropon, element)) {
369 var index;
370
371 var children = self.findElements(dropon, {tag: droponOptions.tag,
372 only: droponOptions.only});
373 var child = null;
374
375 if (children) {
376 var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
377
378 for (index = 0; index < children.length; index += 1) {
379 if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) {
380 offset -= self._offsetSize(children[index], droponOptions.overlap);
381 } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
382 child = index + 1 < children.length ? children[index + 1] : null;
383 break;
384 } else {
385 child = children[index];
386 break;
387 }
388 }
389 }
390
391 dropon.insertBefore(element, child);
392
393 self.options(oldParentNode).onChange(element);
394 droponOptions.onChange(element);
395 }
396 },
397
398 /** @id MochiKit.Sortable.unmark */
399 unmark: function () {
400 var m = MochiKit.Sortable._marker;
401 if (m) {
402 MochiKit.Style.hideElement(m);
403 }
404 },
405
406 /** @id MochiKit.Sortable.mark */
407 mark: function (dropon, position) {
408 // mark on ghosting only
409 var d = MochiKit.DOM;
410 var self = MochiKit.Sortable;
411 var sortable = self.options(dropon.parentNode);
412 if (sortable && !sortable.ghosting) {
413 return;
414 }
415
416 if (!self._marker) {
417 self._marker = d.getElement('dropmarker') ||
418 document.createElement('DIV');
419 MochiKit.Style.hideElement(self._marker);
420 d.addElementClass(self._marker, 'dropmarker');
421 self._marker.style.position = 'absolute';
422 document.getElementsByTagName('body').item(0).appendChild(self._marker);
423 }
424 var offsets = MochiKit.Position.cumulativeOffset(dropon);
425 self._marker.style.left = offsets.x + 'px';
426 self._marker.style.top = offsets.y + 'px';
427
428 if (position == 'after') {
429 if (sortable.overlap == 'horizontal') {
430 self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px';
431 } else {
432 self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px';
433 }
434 }
435 MochiKit.Style.showElement(self._marker);
436 },
437
438 _tree: function (element, options, parent) {
439 var self = MochiKit.Sortable;
440 var children = self.findElements(element, options) || [];
441
442 for (var i = 0; i < children.length; ++i) {
443 var match = children[i].id.match(options.format);
444
445 if (!match) {
446 continue;
447 }
448
449 var child = {
450 id: encodeURIComponent(match ? match[1] : null),
451 element: element,
452 parent: parent,
453 children: [],
454 position: parent.children.length,
455 container: self._findChildrenElement(children[i], options.treeTag.toUpperCase())
456 };
457
458 /* Get the element containing the children and recurse over it */
459 if (child.container) {
460 self._tree(child.container, options, child);
461 }
462
463 parent.children.push (child);
464 }
465
466 return parent;
467 },
468
469 /* Finds the first element of the given tag type within a parent element.
470 Used for finding the first LI[ST] within a L[IST]I[TEM].*/
471 _findChildrenElement: function (element, containerTag) {
472 if (element && element.hasChildNodes) {
473 containerTag = containerTag.toUpperCase();
474 for (var i = 0; i < element.childNodes.length; ++i) {
475 if (element.childNodes[i].tagName.toUpperCase() == containerTag) {
476 return element.childNodes[i];
477 }
478 }
479 }
480 return null;
481 },
482
483 /** @id MochiKit.Sortable.tree */
484 tree: function (element, options) {
485 element = MochiKit.DOM.getElement(element);
486 var sortableOptions = MochiKit.Sortable.options(element);
487 options = MochiKit.Base.update({
488 tag: sortableOptions.tag,
489 treeTag: sortableOptions.treeTag,
490 only: sortableOptions.only,
491 name: element.id,
492 format: sortableOptions.format
493 }, options || {});
494
495 var root = {
496 id: null,
497 parent: null,
498 children: new Array,
499 container: element,
500 position: 0
501 };
502
503 return MochiKit.Sortable._tree(element, options, root);
504 },
505
506 /**
507 * Specifies the sequence for the Sortable.
508 * @param {Node} element Element to use as the Sortable.
509 * @param {Object} newSequence New sequence to use.
510 * @param {Object} options Options to use fro the Sortable.
511 */
512 setSequence: function (element, newSequence, options) {
513 var self = MochiKit.Sortable;
514 var b = MochiKit.Base;
515 element = MochiKit.DOM.getElement(element);
516 options = b.update(self.options(element), options || {});
517
518 var nodeMap = {};
519 b.map(function (n) {
520 var m = n.id.match(options.format);
521 if (m) {
522 nodeMap[m[1]] = [n, n.parentNode];
523 }
524 n.parentNode.removeChild(n);
525 }, self.findElements(element, options));
526
527 b.map(function (ident) {
528 var n = nodeMap[ident];
529 if (n) {
530 n[1].appendChild(n[0]);
531 delete nodeMap[ident];
532 }
533 }, newSequence);
534 },
535
536 /* Construct a [i] index for a particular node */
537 _constructIndex: function (node) {
538 var index = '';
539 do {
540 if (node.id) {
541 index = '[' + node.position + ']' + index;
542 }
543 } while ((node = node.parent) != null);
544 return index;
545 },
546
547 /** @id MochiKit.Sortable.sequence */
548 sequence: function (element, options) {
549 element = MochiKit.DOM.getElement(element);
550 var self = MochiKit.Sortable;
551 var options = MochiKit.Base.update(self.options(element), options || {});
552
553 return MochiKit.Base.map(function (item) {
554 return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
555 }, MochiKit.DOM.getElement(self.findElements(element, options) || []));
556 },
557
558 /**
559 * Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest.
560 * These options override the Sortable options for the serialization only.
561 * @param {Node} element Element to serialize.
562 * @param {Object} options Serialization options.
563 */
564 serialize: function (element, options) {
565 element = MochiKit.DOM.getElement(element);
566 var self = MochiKit.Sortable;
567 options = MochiKit.Base.update(self.options(element), options || {});
568 var name = encodeURIComponent(options.name || element.id);
569
570 if (options.tree) {
571 return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) {
572 return [name + self._constructIndex(item) + "[id]=" +
573 encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
574 }, self.tree(element, options).children)).join('&');
575 } else {
576 return MochiKit.Base.map(function (item) {
577 return name + "[]=" + encodeURIComponent(item);
578 }, self.sequence(element, options)).join('&');
579 }
580 }
581});
582
583// trunk compatibility
584MochiKit.Sortable.Sortable = MochiKit.Sortable;
585
586MochiKit.Sortable.__new__ = function () {
587 MochiKit.Base.nameFunctions(this);
588};
589
590MochiKit.Sortable.__new__();
591
592MochiKit.Base._exportSymbols(this, MochiKit.Sortable);
diff --git a/frontend/delta/js/MochiKit/Style.js b/frontend/delta/js/MochiKit/Style.js
new file mode 100644
index 0000000..fa5edbf
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Style.js
@@ -0,0 +1,584 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Style 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved.
31
32The MochiKit.Style.getElementPosition function is adapted from
33YAHOO.util.Dom.getXY v0.9.0. which is copyrighted by Yahoo! Inc.
34
35***/
36
37MochiKit.Base.module(MochiKit, 'Style', '1.5', ['Base', 'DOM']);
38
39
40/** @id MochiKit.Style.Dimensions */
41MochiKit.Style.Dimensions = function (w, h) {
42 if (!(this instanceof MochiKit.Style.Dimensions)) {
43 return new MochiKit.Style.Dimensions(w, h);
44 }
45 this.w = w;
46 this.h = h;
47};
48
49MochiKit.Style.Dimensions.prototype.__repr__ = function () {
50 var repr = MochiKit.Base.repr;
51 return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}';
52};
53
54MochiKit.Style.Dimensions.prototype.toString = function () {
55 return this.__repr__();
56};
57
58
59/** @id MochiKit.Style.Coordinates */
60MochiKit.Style.Coordinates = function (x, y) {
61 if (!(this instanceof MochiKit.Style.Coordinates)) {
62 return new MochiKit.Style.Coordinates(x, y);
63 }
64 this.x = x;
65 this.y = y;
66};
67
68MochiKit.Style.Coordinates.prototype.__repr__ = function () {
69 var repr = MochiKit.Base.repr;
70 return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}';
71};
72
73MochiKit.Style.Coordinates.prototype.toString = function () {
74 return this.__repr__();
75};
76
77
78MochiKit.Base.update(MochiKit.Style, {
79
80 /** @id MochiKit.Style.getStyle */
81 getStyle: function (elem, cssProperty) {
82 var dom = MochiKit.DOM;
83 var d = dom._document;
84
85 elem = dom.getElement(elem);
86 cssProperty = MochiKit.Base.camelize(cssProperty);
87
88 if (!elem || elem == d) {
89 return undefined;
90 }
91 if (cssProperty == 'opacity' && typeof(elem.filters) != 'undefined') {
92 var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/);
93 if (opacity && opacity[1]) {
94 return parseFloat(opacity[1]) / 100;
95 }
96 return 1.0;
97 }
98 if (cssProperty == 'float' || cssProperty == 'cssFloat' || cssProperty == 'styleFloat') {
99 if (elem.style["float"]) {
100 return elem.style["float"];
101 } else if (elem.style.cssFloat) {
102 return elem.style.cssFloat;
103 } else if (elem.style.styleFloat) {
104 return elem.style.styleFloat;
105 } else {
106 return "none";
107 }
108 }
109 var value = elem.style ? elem.style[cssProperty] : null;
110 if (!value) {
111 if (d.defaultView && d.defaultView.getComputedStyle) {
112 var css = d.defaultView.getComputedStyle(elem, null);
113 cssProperty = cssProperty.replace(/([A-Z])/g, '-$1'
114 ).toLowerCase(); // from dojo.style.toSelectorCase
115 value = css ? css.getPropertyValue(cssProperty) : null;
116 } else if (elem.currentStyle) {
117 value = elem.currentStyle[cssProperty];
118 if (/^\d/.test(value) && !/px$/.test(value) && cssProperty != 'fontWeight') {
119 /* Convert to px using an hack from Dean Edwards */
120 var left = elem.style.left;
121 var rsLeft = elem.runtimeStyle.left;
122 elem.runtimeStyle.left = elem.currentStyle.left;
123 elem.style.left = value || 0;
124 value = elem.style.pixelLeft + "px";
125 elem.style.left = left;
126 elem.runtimeStyle.left = rsLeft;
127 }
128 }
129 }
130 if (cssProperty == 'opacity') {
131 value = parseFloat(value);
132 }
133
134 if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.findValue(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
135 if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
136 value = 'auto';
137 }
138 }
139
140 return value == 'auto' ? null : value;
141 },
142
143 /** @id MochiKit.Style.setStyle */
144 setStyle: function (elem, style) {
145 elem = MochiKit.DOM.getElement(elem);
146 for (var name in style) {
147 switch (name) {
148 case 'opacity':
149 MochiKit.Style.setOpacity(elem, style[name]);
150 break;
151 case 'float':
152 case 'cssFloat':
153 case 'styleFloat':
154 if (typeof(elem.style["float"]) != "undefined") {
155 elem.style["float"] = style[name];
156 } else if (typeof(elem.style.cssFloat) != "undefined") {
157 elem.style.cssFloat = style[name];
158 } else {
159 elem.style.styleFloat = style[name];
160 }
161 break;
162 default:
163 elem.style[MochiKit.Base.camelize(name)] = style[name];
164 }
165 }
166 },
167
168 /** @id MochiKit.Style.setOpacity */
169 setOpacity: function (elem, o) {
170 elem = MochiKit.DOM.getElement(elem);
171 var self = MochiKit.Style;
172 if (o == 1) {
173 var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
174 elem.style["opacity"] = toSet ? 0.999999 : 1.0;
175 if (/MSIE/.test(navigator.userAgent)) {
176 elem.style['filter'] =
177 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '');
178 }
179 } else {
180 if (o < 0.00001) {
181 o = 0;
182 }
183 elem.style["opacity"] = o;
184 if (/MSIE/.test(navigator.userAgent)) {
185 elem.style['filter'] =
186 self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')';
187 }
188 }
189 },
190
191 /*
192
193 getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
194 Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
195 License: BSD, http://developer.yahoo.net/yui/license.txt
196
197 */
198
199 /** @id MochiKit.Style.getElementPosition */
200 getElementPosition: function (elem, /* optional */relativeTo) {
201 var self = MochiKit.Style;
202 var dom = MochiKit.DOM;
203 var isCoordinates = function (o) {
204 return o != null &&
205 o.nodeType == null &&
206 typeof(o.x) == "number" &&
207 typeof(o.y) == "number";
208 };
209
210 if (typeof(elem) == "string") {
211 elem = dom.getElement(elem);
212 }
213 if (elem == null ||
214 (!isCoordinates(elem) && self.getStyle(elem, 'display') == 'none')) {
215 return undefined;
216 }
217
218 var c = new self.Coordinates(0, 0);
219 var box = null;
220 var parent = null;
221
222 var d = MochiKit.DOM._document;
223 var de = d.documentElement;
224 var b = d.body;
225
226 if (isCoordinates(elem)) {
227 /* it's just a MochiKit.Style.Coordinates object */
228 c.x += elem.x || 0;
229 c.y += elem.y || 0;
230 } else if (elem.getBoundingClientRect) { // IE shortcut
231 /*
232
233 The IE shortcut can be off by two. We fix it. See:
234 http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
235
236 This is similar to the method used in
237 MochiKit.Signal.Event.mouse().
238
239 */
240 box = elem.getBoundingClientRect();
241
242 c.x += box.left +
243 (de.scrollLeft || b.scrollLeft) -
244 (de.clientLeft || 0);
245
246 c.y += box.top +
247 (de.scrollTop || b.scrollTop) -
248 (de.clientTop || 0);
249
250 } else if (elem.offsetParent) {
251 c.x += elem.offsetLeft;
252 c.y += elem.offsetTop;
253 parent = elem.offsetParent;
254
255 if (parent != elem) {
256 while (parent) {
257 c.x += parseInt(parent.style.borderLeftWidth, 10) || 0;
258 c.y += parseInt(parent.style.borderTopWidth, 10) || 0;
259 c.x += parent.offsetLeft;
260 c.y += parent.offsetTop;
261 parent = parent.offsetParent;
262 }
263 }
264
265 /*
266
267 Opera < 9 and old Safari (absolute) incorrectly account for
268 body offsetTop and offsetLeft.
269
270 */
271 var ua = navigator.userAgent.toLowerCase();
272 if ((typeof(opera) != 'undefined' &&
273 parseFloat(opera.version()) < 9) ||
274 (ua.indexOf('AppleWebKit') != -1 &&
275 self.getStyle(elem, 'position') == 'absolute')) {
276
277 c.x -= b.offsetLeft;
278 c.y -= b.offsetTop;
279
280 }
281
282 // Adjust position for strange Opera scroll bug
283 if (elem.parentNode) {
284 parent = elem.parentNode;
285 } else {
286 parent = null;
287 }
288 while (parent) {
289 var tagName = parent.tagName.toUpperCase();
290 if (tagName === 'BODY' || tagName === 'HTML') {
291 break;
292 }
293 var disp = self.getStyle(parent, 'display');
294 // Handle strange Opera bug for some display
295 if (disp.search(/^inline|table-row.*$/i)) {
296 c.x -= parent.scrollLeft;
297 c.y -= parent.scrollTop;
298 }
299 if (parent.parentNode) {
300 parent = parent.parentNode;
301 } else {
302 parent = null;
303 }
304 }
305 }
306
307 if (relativeTo) {
308 relativeTo = arguments.callee(relativeTo);
309 if (relativeTo) {
310 c.x -= (relativeTo.x || 0);
311 c.y -= (relativeTo.y || 0);
312 }
313 }
314
315 return c;
316 },
317
318 /** @id MochiKit.Style.setElementPosition */
319 setElementPosition: function (elem, newPos/* optional */, units) {
320 elem = MochiKit.DOM.getElement(elem);
321 if (typeof(units) == 'undefined') {
322 units = 'px';
323 }
324 var newStyle = {};
325 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
326 if (!isUndefNull(newPos.x)) {
327 newStyle['left'] = newPos.x + units;
328 }
329 if (!isUndefNull(newPos.y)) {
330 newStyle['top'] = newPos.y + units;
331 }
332 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
333 },
334
335 /** @id MochiKit.Style.makePositioned */
336 makePositioned: function (element) {
337 element = MochiKit.DOM.getElement(element);
338 var pos = MochiKit.Style.getStyle(element, 'position');
339 if (pos == 'static' || !pos) {
340 element.style.position = 'relative';
341 // Opera returns the offset relative to the positioning context,
342 // when an element is position relative but top and left have
343 // not been defined
344 if (/Opera/.test(navigator.userAgent)) {
345 element.style.top = 0;
346 element.style.left = 0;
347 }
348 }
349 },
350
351 /** @id MochiKit.Style.undoPositioned */
352 undoPositioned: function (element) {
353 element = MochiKit.DOM.getElement(element);
354 if (element.style.position == 'relative') {
355 element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
356 }
357 },
358
359 /** @id MochiKit.Style.makeClipping */
360 makeClipping: function (element) {
361 element = MochiKit.DOM.getElement(element);
362 var s = element.style;
363 var oldOverflow = { 'overflow': s.overflow,
364 'overflow-x': s.overflowX,
365 'overflow-y': s.overflowY };
366 if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
367 element.style.overflow = 'hidden';
368 element.style.overflowX = 'hidden';
369 element.style.overflowY = 'hidden';
370 }
371 return oldOverflow;
372 },
373
374 /** @id MochiKit.Style.undoClipping */
375 undoClipping: function (element, overflow) {
376 element = MochiKit.DOM.getElement(element);
377 if (typeof(overflow) == 'string') {
378 element.style.overflow = overflow;
379 } else if (overflow != null) {
380 element.style.overflow = overflow['overflow'];
381 element.style.overflowX = overflow['overflow-x'];
382 element.style.overflowY = overflow['overflow-y'];
383 }
384 },
385
386 /** @id MochiKit.Style.getElementDimensions */
387 getElementDimensions: function (elem, contentSize/*optional*/) {
388 var self = MochiKit.Style;
389 var dom = MochiKit.DOM;
390 if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
391 return new self.Dimensions(elem.w || 0, elem.h || 0);
392 }
393 elem = dom.getElement(elem);
394 if (!elem) {
395 return undefined;
396 }
397 var disp = self.getStyle(elem, 'display');
398 // display can be empty/undefined on WebKit/KHTML
399 if (disp == 'none' || disp == '' || typeof(disp) == 'undefined') {
400 var s = elem.style;
401 var originalVisibility = s.visibility;
402 var originalPosition = s.position;
403 var originalDisplay = s.display;
404 s.visibility = 'hidden';
405 s.position = 'absolute';
406 s.display = self._getDefaultDisplay(elem);
407 var originalWidth = elem.offsetWidth;
408 var originalHeight = elem.offsetHeight;
409 s.display = originalDisplay;
410 s.position = originalPosition;
411 s.visibility = originalVisibility;
412 } else {
413 originalWidth = elem.offsetWidth || 0;
414 originalHeight = elem.offsetHeight || 0;
415 }
416 if (contentSize) {
417 var tableCell = 'colSpan' in elem && 'rowSpan' in elem;
418 var collapse = (tableCell && elem.parentNode && self.getStyle(
419 elem.parentNode, 'borderCollapse') == 'collapse');
420 if (collapse) {
421 if (/MSIE/.test(navigator.userAgent)) {
422 var borderLeftQuota = elem.previousSibling? 0.5 : 1;
423 var borderRightQuota = elem.nextSibling? 0.5 : 1;
424 }
425 else {
426 var borderLeftQuota = 0.5;
427 var borderRightQuota = 0.5;
428 }
429 } else {
430 var borderLeftQuota = 1;
431 var borderRightQuota = 1;
432 }
433 originalWidth -= Math.round(
434 (parseFloat(self.getStyle(elem, 'paddingLeft')) || 0)
435 + (parseFloat(self.getStyle(elem, 'paddingRight')) || 0)
436 + borderLeftQuota *
437 (parseFloat(self.getStyle(elem, 'borderLeftWidth')) || 0)
438 + borderRightQuota *
439 (parseFloat(self.getStyle(elem, 'borderRightWidth')) || 0)
440 );
441 if (tableCell) {
442 if (/Gecko|Opera/.test(navigator.userAgent)
443 && !/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent)) {
444 var borderHeightQuota = 0;
445 } else if (/MSIE/.test(navigator.userAgent)) {
446 var borderHeightQuota = 1;
447 } else {
448 var borderHeightQuota = collapse? 0.5 : 1;
449 }
450 } else {
451 var borderHeightQuota = 1;
452 }
453 originalHeight -= Math.round(
454 (parseFloat(self.getStyle(elem, 'paddingTop')) || 0)
455 + (parseFloat(self.getStyle(elem, 'paddingBottom')) || 0)
456 + borderHeightQuota * (
457 (parseFloat(self.getStyle(elem, 'borderTopWidth')) || 0)
458 + (parseFloat(self.getStyle(elem, 'borderBottomWidth')) || 0))
459 );
460 }
461 return new self.Dimensions(originalWidth, originalHeight);
462 },
463
464 /** @id MochiKit.Style.setElementDimensions */
465 setElementDimensions: function (elem, newSize/* optional */, units) {
466 elem = MochiKit.DOM.getElement(elem);
467 if (typeof(units) == 'undefined') {
468 units = 'px';
469 }
470 var newStyle = {};
471 var isUndefNull = MochiKit.Base.isUndefinedOrNull;
472 if (!isUndefNull(newSize.w)) {
473 newStyle['width'] = newSize.w + units;
474 }
475 if (!isUndefNull(newSize.h)) {
476 newStyle['height'] = newSize.h + units;
477 }
478 MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
479 },
480
481 _getDefaultDisplay: function (elem) {
482 var self = MochiKit.Style;
483 var dom = MochiKit.DOM;
484 elem = dom.getElement(elem);
485 if (!elem) {
486 return undefined;
487 }
488 var tagName = elem.tagName.toUpperCase();
489 return self._defaultDisplay[tagName] || 'block';
490 },
491
492 /** @id MochiKit.Style.setDisplayForElement */
493 setDisplayForElement: function (display, element/*, ...*/) {
494 var elements = MochiKit.Base.extend(null, arguments, 1);
495 var getElement = MochiKit.DOM.getElement;
496 for (var i = 0; i < elements.length; i++) {
497 element = getElement(elements[i]);
498 if (element) {
499 element.style.display = display;
500 }
501 }
502 },
503
504 /** @id MochiKit.Style.getViewportDimensions */
505 getViewportDimensions: function () {
506 var d = new MochiKit.Style.Dimensions();
507 var w = MochiKit.DOM._window;
508 var b = MochiKit.DOM._document.body;
509 if (w.innerWidth) {
510 d.w = w.innerWidth;
511 d.h = w.innerHeight;
512 } else if (b && b.parentElement && b.parentElement.clientWidth) {
513 d.w = b.parentElement.clientWidth;
514 d.h = b.parentElement.clientHeight;
515 } else if (b && b.clientWidth) {
516 d.w = b.clientWidth;
517 d.h = b.clientHeight;
518 }
519 return d;
520 },
521
522 /** @id MochiKit.Style.getViewportPosition */
523 getViewportPosition: function () {
524 var c = new MochiKit.Style.Coordinates(0, 0);
525 var d = MochiKit.DOM._document;
526 var de = d.documentElement;
527 var db = d.body;
528 if (de && (de.scrollTop || de.scrollLeft)) {
529 c.x = de.scrollLeft;
530 c.y = de.scrollTop;
531 } else if (db) {
532 c.x = db.scrollLeft;
533 c.y = db.scrollTop;
534 }
535 return c;
536 },
537
538 __new__: function () {
539 var m = MochiKit.Base;
540
541 var inlines = ['A','ABBR','ACRONYM','B','BASEFONT','BDO','BIG','BR',
542 'CITE','CODE','DFN','EM','FONT','I','IMG','KBD','LABEL',
543 'Q','S','SAMP','SMALL','SPAN','STRIKE','STRONG','SUB',
544 'SUP','TEXTAREA','TT','U','VAR'];
545 this._defaultDisplay = { 'TABLE': 'table',
546 'THEAD': 'table-header-group',
547 'TBODY': 'table-row-group',
548 'TFOOT': 'table-footer-group',
549 'COLGROUP': 'table-column-group',
550 'COL': 'table-column',
551 'TR': 'table-row',
552 'TD': 'table-cell',
553 'TH': 'table-cell',
554 'CAPTION': 'table-caption',
555 'LI': 'list-item',
556 'INPUT': 'inline-block',
557 'SELECT': 'inline-block' };
558 // CSS 'display' support in IE6/7 is just broken...
559 if (/MSIE/.test(navigator.userAgent)) {
560 for (var k in this._defaultDisplay) {
561 var v = this._defaultDisplay[k];
562 if (v.indexOf('table') == 0) {
563 this._defaultDisplay[k] = 'block';
564 }
565 }
566 }
567 for (var i = 0; i < inlines.length; i++) {
568 this._defaultDisplay[inlines[i]] = 'inline';
569 }
570
571 // Backwards compatibility aliases
572 m._deprecated(this, 'elementPosition', 'MochiKit.Style.getElementPosition', '1.3', true);
573 m._deprecated(this, 'elementDimensions', 'MochiKit.Style.getElementDimensions', '1.3', true);
574
575 this.hideElement = m.partial(this.setDisplayForElement, 'none');
576 // TODO: showElement could be improved by using getDefaultDisplay.
577 this.showElement = m.partial(this.setDisplayForElement, 'block');
578
579 m.nameFunctions(this);
580 }
581});
582
583MochiKit.Style.__new__();
584MochiKit.Base._exportSymbols(this, MochiKit.Style);
diff --git a/frontend/delta/js/MochiKit/Test.js b/frontend/delta/js/MochiKit/Test.js
new file mode 100644
index 0000000..55d226c
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Test.js
@@ -0,0 +1,167 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Test 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Test', '1.5', ['Base']);
35
36MochiKit.Test.runTests = function (obj) {
37 if (typeof(obj) == "string") {
38 // TODO: Remove this temporary API change advertisement
39 throw new TypeError("Automatic module import not supported, call runTests() with proper object: " + obj);
40 }
41 var suite = new MochiKit.Test.Suite();
42 suite.run(obj);
43};
44
45MochiKit.Test.Suite = function () {
46 this.testIndex = 0;
47 MochiKit.Base.bindMethods(this);
48};
49
50MochiKit.Test.Suite.prototype = {
51 run: function (obj) {
52 try {
53 obj(this);
54 } catch (e) {
55 this.traceback(e);
56 }
57 },
58 traceback: function (e) {
59 var items = MochiKit.Iter.sorted(MochiKit.Base.items(e));
60 print("not ok " + this.testIndex + " - Error thrown");
61 for (var i = 0; i < items.length; i++) {
62 var kv = items[i];
63 if (kv[0] == "stack") {
64 kv[1] = kv[1].split(/\n/)[0];
65 }
66 this.print("# " + kv.join(": "));
67 }
68 },
69 print: function (s) {
70 print(s);
71 },
72 is: function (got, expected, /* optional */message) {
73 var res = 1;
74 var msg = null;
75 try {
76 res = MochiKit.Base.compare(got, expected);
77 } catch (e) {
78 msg = "Can not compare " + typeof(got) + ":" + typeof(expected);
79 }
80 if (res) {
81 msg = "Expected value did not compare equal";
82 }
83 if (!res) {
84 return this.testResult(true, message);
85 }
86 return this.testResult(false, message,
87 [[msg], ["got:", got], ["expected:", expected]]);
88 },
89
90 testResult: function (pass, msg, failures) {
91 this.testIndex += 1;
92 if (pass) {
93 this.print("ok " + this.testIndex + " - " + msg);
94 return;
95 }
96 this.print("not ok " + this.testIndex + " - " + msg);
97 if (failures) {
98 for (var i = 0; i < failures.length; i++) {
99 this.print("# " + failures[i].join(" "));
100 }
101 }
102 },
103
104 isDeeply: function (got, expected, /* optional */message) {
105 var m = MochiKit.Base;
106 var res = 1;
107 try {
108 res = m.compare(got, expected);
109 } catch (e) {
110 // pass
111 }
112 if (res === 0) {
113 return this.ok(true, message);
114 }
115 var gk = m.keys(got);
116 var ek = m.keys(expected);
117 gk.sort();
118 ek.sort();
119 if (m.compare(gk, ek)) {
120 // differing keys
121 var cmp = {};
122 var i;
123 for (i = 0; i < gk.length; i++) {
124 cmp[gk[i]] = "got";
125 }
126 for (i = 0; i < ek.length; i++) {
127 if (ek[i] in cmp) {
128 delete cmp[ek[i]];
129 } else {
130 cmp[ek[i]] = "expected";
131 }
132 }
133 var diffkeys = m.keys(cmp);
134 diffkeys.sort();
135 var gotkeys = [];
136 var expkeys = [];
137 while (diffkeys.length) {
138 var k = diffkeys.shift();
139 if (k in Object.prototype) {
140 continue;
141 }
142 (cmp[k] == "got" ? gotkeys : expkeys).push(k);
143 }
144
145
146 }
147
148 return this.testResult((!res), msg,
149 (msg ? [["got:", got], ["expected:", expected]] : undefined)
150 );
151 },
152
153 ok: function (res, message) {
154 return this.testResult(res, message);
155 }
156};
157
158MochiKit.Test.__new__ = function () {
159 var m = MochiKit.Base;
160 this.Suite.__export__ = false;
161 m.nameFunctions(this);
162
163};
164
165MochiKit.Test.__new__();
166
167MochiKit.Base._exportSymbols(this, MochiKit.Test);
diff --git a/frontend/delta/js/MochiKit/Text.js b/frontend/delta/js/MochiKit/Text.js
new file mode 100644
index 0000000..0c230fa
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Text.js
@@ -0,0 +1,569 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Text 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2008 Per Cederberg. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Text', '1.5', ['Base', 'Format']);
35
36/**
37 * Checks if a text string starts with the specified substring. If
38 * either of the two strings is null, false will be returned.
39 *
40 * @param {String} substr the substring to search for
41 * @param {String} str the string to search in
42 *
43 * @return {Boolean} true if the string starts with the substring, or
44 * false otherwise
45 */
46MochiKit.Text.startsWith = function (substr, str) {
47 return str != null && substr != null && str.indexOf(substr) == 0;
48};
49
50/**
51 * Checks if a text string ends with the specified substring. If
52 * either of the two strings is null, false will be returned.
53 *
54 * @param {String} substr the substring to search for
55 * @param {String} str the string to search in
56 *
57 * @return {Boolean} true if the string ends with the substring, or
58 * false otherwise
59 */
60MochiKit.Text.endsWith = function (substr, str) {
61 return str != null && substr != null &&
62 str.lastIndexOf(substr) == Math.max(str.length - substr.length, 0);
63};
64
65/**
66 * Checks if a text string contains the specified substring. If
67 * either of the two strings is null, false will be returned.
68 *
69 * @param {String} substr the substring to search for
70 * @param {String} str the string to search in
71 *
72 * @return {Boolean} true if the string contains the substring, or
73 * false otherwise
74 */
75MochiKit.Text.contains = function (substr, str) {
76 return str != null && substr != null && str.indexOf(substr) >= 0;
77};
78
79/**
80 * Adds a character to the left-hand side of a string until it
81 * reaches the specified minimum length.
82 *
83 * @param {String} str the string to process
84 * @param {Number} minLength the requested minimum length
85 * @param {String} fillChar the padding character to add, defaults
86 * to a space
87 *
88 * @return {String} the padded string
89 */
90MochiKit.Text.padLeft = function (str, minLength, fillChar) {
91 str = str || "";
92 fillChar = fillChar || " ";
93 while (str.length < minLength) {
94 str = fillChar + str;
95 }
96 return str;
97};
98
99/**
100 * Adds a character to the right-hand side of a string until it
101 * reaches the specified minimum length.
102 *
103 * @param {String} str the string to process
104 * @param {Number} minLength the requested minimum length
105 * @param {String} fillChar the padding character to add, defaults
106 * to a space
107 *
108 * @return {String} the padded string
109 */
110MochiKit.Text.padRight = function (str, minLength, fillChar) {
111 str = str || "";
112 fillChar = fillChar || " ";
113 while (str.length < minLength) {
114 str += fillChar;
115 }
116 return str;
117};
118
119/**
120 * Returns a truncated copy of a string. If the string is shorter
121 * than the specified maximum length, the object will be returned
122 * unmodified. If an optional tail string is specified, additional
123 * elements will be removed in order to accomodate the tail (that
124 * will be appended). This function also works on arrays.
125 *
126 * @param {String} str the string to truncate
127 * @param {Number} maxLength the maximum length
128 * @param {String} [tail] the tail to append on truncation
129 *
130 * @return {String} the truncated string
131 */
132MochiKit.Text.truncate = function (str, maxLength, tail) {
133 if (str == null || str.length <= maxLength || maxLength < 0) {
134 return str;
135 } else if (tail != null) {
136 str = str.slice(0, Math.max(0, maxLength - tail.length));
137 if (typeof(str) == "string") {
138 return str + tail;
139 } else {
140 return MochiKit.Base.extend(str, tail);
141 }
142 } else {
143 return str.slice(0, maxLength);
144 }
145};
146
147/**
148 * Splits a text string using separator as the split point
149 * If max is given, at most max splits are done, giving at most
150 * max + 1 elements in the returned list.
151 *
152 * @param {String} str the string to split
153 * @param {String/RegExp} [separator] the separator char or regexp to use,
154 * defaults to newline
155 * @param {Number} [max] the maximum number of parts to return
156 * @return {Array} an array of parts of the string
157 */
158MochiKit.Text.split = function (str, separator, max) {
159 if (str == null) {
160 return str;
161 }
162 separator = separator || '\n';
163 var bits = str.split(separator);
164 if ((typeof(max) == "undefined") || max >= bits.length - 1) {
165 return bits;
166 }
167 bits.splice(max, bits.length, bits.slice(max, bits.length).join(separator));
168 return bits;
169};
170
171/**
172 * Splits a text string using separator as the split point
173 * If max is given, at most max splits are done,
174 * using splits from the right
175 *
176 * @param {String} str the string to split
177 * @param {String/RegExp} [separator] the separator char or regexp to use,
178 * defaults to newline
179 * @param {Number} [max] the maximum number of parts to return
180 * @return {Array} an array of parts of the string
181 */
182MochiKit.Text.rsplit = function (str, separator, max) {
183 if (str == null) {
184 return str;
185 }
186 separator = separator || '\n';
187 var bits = str.split(separator);
188 if ((typeof(max) == "undefined") || max >= bits.length - 1){
189 return bits;
190 }
191 bits.splice(0, bits.length-max, bits.slice(0, bits.length-max).join(separator));
192 return bits;
193};
194
195/**
196 * Creates a formatter function for the specified formatter pattern
197 * and locale. The returned function takes as many arguments as the
198 * formatter pattern requires. See separate documentation for
199 * information about the formatter pattern syntax.
200 *
201 * @param {String} pattern the formatter pattern string
202 * @param {Object} [locale] the locale to use, defaults to
203 * LOCALE.en_US
204 *
205 * @return {Function} the formatter function created
206 *
207 * @throws FormatPatternError if the format pattern was invalid
208 */
209MochiKit.Text.formatter = function (pattern, locale) {
210 if (locale == null) {
211 locale = MochiKit.Format.formatLocale();
212 } else if (typeof(locale) == "string") {
213 locale = MochiKit.Format.formatLocale(locale);
214 }
215 var parts = MochiKit.Text._parsePattern(pattern);
216 return function() {
217 var values = MochiKit.Base.extend([], arguments);
218 var res = [];
219 for (var i = 0; i < parts.length; i++) {
220 if (typeof(parts[i]) == "string") {
221 res.push(parts[i]);
222 } else {
223 res.push(MochiKit.Text.formatValue(parts[i], values, locale));
224 }
225 }
226 return res.join("");
227 };
228};
229
230/**
231 * Formats the specified arguments according to a formatter pattern.
232 * See separate documentation for information about the formatter
233 * pattern syntax.
234 *
235 * @param {String} pattern the formatter pattern string
236 * @param {Object} [...] the optional values to format
237 *
238 * @return {String} the formatted output string
239 *
240 * @throws FormatPatternError if the format pattern was invalid
241 */
242MochiKit.Text.format = function (pattern/*, ...*/) {
243 var func = MochiKit.Text.formatter(pattern);
244 return func.apply(this, MochiKit.Base.extend([], arguments, 1));
245};
246
247/**
248 * Format a value with the specified format specifier.
249 *
250 * @param {String/Object} spec the format specifier string or parsed
251 * format specifier object
252 * @param {Object} value the value to format
253 * @param {Object} [locale] the locale to use, defaults to
254 * LOCALE.en_US
255 *
256 * @return {String} the formatted output string
257 *
258 * @throws FormatPatternError if the format specifier was invalid
259 */
260MochiKit.Text.formatValue = function (spec, value, locale) {
261 var self = MochiKit.Text;
262 if (typeof(spec) === "string") {
263 spec = self._parseFormatFlags(spec, 0, spec.length);
264 }
265 for (var i = 0; spec.path != null && i < spec.path.length; i++) {
266 if (value != null) {
267 value = value[spec.path[i]];
268 }
269 }
270 if (locale == null) {
271 locale = MochiKit.Format.formatLocale();
272 } else if (typeof(locale) == "string") {
273 locale = MochiKit.Format.formatLocale(locale);
274 }
275 var str = "";
276 if (spec.type == "number") {
277 if (value instanceof Number) {
278 value = value.valueOf();
279 }
280 if (typeof(value) != "number" || isNaN(value)) {
281 str = "";
282 } else if (value === Number.POSITIVE_INFINITY) {
283 str = "\u221e";
284 } else if (value === Number.NEGATIVE_INFINITY) {
285 str = "-\u221e";
286 } else {
287 var sign = (value < 0) ? "-" : spec.sign;
288 value = Math.abs(value);
289 if (spec.format === "%") {
290 str = self._truncToPercent(value, spec.precision);
291 } else if (spec.format === "d") {
292 str = MochiKit.Format.roundToFixed(value, 0);
293 } else if (spec.radix != 10) {
294 str = Math.floor(value).toString(spec.radix);
295 if (spec.format === "x") {
296 str = str.toLowerCase();
297 } else if (spec.format === "X") {
298 str = str.toUpperCase();
299 }
300 } else if (spec.precision >= 0) {
301 str = MochiKit.Format.roundToFixed(value, spec.precision);
302 } else {
303 str = value.toString();
304 }
305 if (spec.padding === "0" && spec.format === "%") {
306 str = self.padLeft(str, spec.width - sign.length - 1, "0");
307 } else if (spec.padding == "0") {
308 str = self.padLeft(str, spec.width - sign.length, "0");
309 }
310 str = self._localizeNumber(str, locale, spec.group);
311 str = sign + str;
312 }
313 if (str !== "" && spec.format === "%") {
314 str = str + locale.percent;
315 }
316 } else {
317 if (spec.format == "r") {
318 str = MochiKit.Base.repr(value);
319 } else {
320 str = (value == null) ? "" : value.toString();
321 }
322 str = self.truncate(str, spec.precision);
323 }
324 if (spec.align == "<") {
325 str = self.padRight(str, spec.width);
326 } else {
327 str = self.padLeft(str, spec.width);
328 }
329 return str;
330};
331
332/**
333 * Adjust an already formatted numeric string for locale-specific
334 * grouping and decimal separators. The grouping is optional and
335 * will attempt to keep the number string length intact by removing
336 * padded zeros (if possible).
337 *
338 * @param {String} num the formatted number string
339 * @param {Object} locale the formatting locale to use
340 * @param {Boolean} group the grouping flag
341 *
342 * @return {String} the localized number string
343 */
344MochiKit.Text._localizeNumber = function (num, locale, group) {
345 var parts = num.split(/\./);
346 var whole = parts[0];
347 var frac = (parts.length == 1) ? "" : parts[1];
348 var res = (frac.length > 0) ? locale.decimal : "";
349 while (group && frac.length > 3) {
350 res = res + frac.substring(0, 3) + locale.separator;
351 frac = frac.substring(3);
352 if (whole.charAt(0) == "0") {
353 whole = whole.substring(1);
354 }
355 }
356 if (frac.length > 0) {
357 res = res + frac;
358 }
359 while (group && whole.length > 3) {
360 var pos = whole.length - 3;
361 res = locale.separator + whole.substring(pos) + res;
362 whole = whole.substring((whole.charAt(0) == "0") ? 1 : 0, pos);
363 }
364 return whole + res;
365};
366
367/**
368 * Parses a format pattern and returns an array of constant strings
369 * and format info objects.
370 *
371 * @param {String} pattern the format pattern to analyze
372 *
373 * @return {Array} an array of strings and format info objects
374 *
375 * @throws FormatPatternError if the format pattern was invalid
376 */
377MochiKit.Text._parsePattern = function (pattern) {
378 var self = MochiKit.Text;
379 var parts = [];
380 var re = /{[^{}]*}|{{?|}}?/g;
381 var lastPos = re.lastIndex = 0;
382 var m;
383 while ((m = re.exec(pattern)) != null) {
384 if (lastPos < m.index) {
385 parts.push(pattern.substring(lastPos, m.index))
386 }
387 var str = m[0];
388 lastPos = m.index + str.length;
389 if (self.startsWith("{", str) && self.endsWith("}", str)) {
390 parts.push(self._parseFormat(pattern, m.index + 1, lastPos - 1));
391 } else if (self.startsWith("{{", str) || self.startsWith("}}", str)) {
392 parts.push(str.substring(1));
393 } else if (self.startsWith("{", str)) {
394 var msg = "unescaped { char, should be escaped as {{";
395 throw new self.FormatPatternError(pattern, m.index, msg);
396 } else if (self.startsWith("}", str)) {
397 var msg = "unescaped } char, should be escaped as }}";
398 throw new self.FormatPatternError(pattern, m.index, msg);
399 }
400 }
401 if (lastPos < pattern.length) {
402 parts.push(pattern.substring(lastPos));
403 }
404 return parts;
405};
406
407/**
408 * Parses a format instruction and returns a format info object.
409 *
410 * @param {String} pattern the format pattern string
411 * @param {Number} startPos the first index of the format instruction
412 * @param {Number} endPos the last index of the format instruction
413 *
414 * @return {Object} the format info object
415 *
416 * @throws FormatPatternError if the format pattern was invalid
417 */
418MochiKit.Text._parseFormat = function (pattern, startPos, endPos) {
419 var self = MochiKit.Text;
420 var text = pattern.substring(startPos, endPos);
421 var parts = self.split(text, ":", 1);
422 var path = parts[0];
423 var flagsPos = startPos + path.length + ((parts.length == 1) ? 0 : 1);
424 var info = self._parseFormatFlags(pattern, flagsPos, endPos);
425 info.path = (path == "") ? [] : path.split(".");
426 for (var i = 0; i < info.path.length; i++) {
427 var v = info.path[i];
428 // TODO: replace with MochiKit.Format.strip?
429 v = v.replace(/^\s+/, "").replace(/\s+$/, "");
430 if (v == "" && info.path.length == 1) {
431 v = 0;
432 } else if (v == "") {
433 var msg = "format value path contains blanks";
434 throw new self.FormatPatternError(pattern, startPos, msg);
435 } else if (/^\d+$/.test(v)) {
436 v = parseInt(v, 10);
437 }
438 info.path[i] = v;
439 }
440 if (info.path.length <= 0 || typeof(info.path[0]) != "number") {
441 info.path.unshift(0);
442 }
443 return info;
444};
445
446/**
447 * Parses a string with format flags and returns a format info object.
448 *
449 * @param {String} pattern the format pattern string
450 * @param {Number} startPos the first index of the format instruction
451 * @param {Number} endPos the last index of the format instruction
452 *
453 * @return {Object} the format info object
454 *
455 * @throws FormatPatternError if the format pattern was invalid
456 */
457MochiKit.Text._parseFormatFlags = function (pattern, startPos, endPos) {
458 var update = MochiKit.Base.update;
459 var info = { type: "string", format: "s", width: 0, precision: -1,
460 align: ">", sign: "", padding: " ", group: false };
461 // TODO: replace with MochiKit.Format.rstrip?
462 var text = pattern.substring(startPos, endPos).replace(/\s+$/, "");
463 var m = /^([<>+ 0,-]+)?(\d+)?(\.\d*)?([srbdoxXf%])?(.*)$/.exec(text);
464 var flags = m[1];
465 var width = m[2];
466 var precision = m[3];
467 var type = m[4];
468 var unmatched = m[5];
469 for (var i = 0; flags && i < flags.length; i++) {
470 var chr = flags.charAt(i);
471 if (chr == "<" || chr == ">") {
472 info.align = chr;
473 } else if (chr == "+" || chr == "-" || chr == " ") {
474 info.sign = (chr == "-") ? "" : chr;
475 } else if (chr == "0") {
476 info.padding = chr;
477 } else if (chr == ",") {
478 info.group = true;
479 }
480 }
481 if (width) {
482 info.width = parseInt(width, 10);
483 }
484 if (precision && precision.length > 1) {
485 info.precision = parseInt(precision.substring(1), 10);
486 }
487 if (type == "s" || type == "r") {
488 info.format = type;
489 } else if (type == "b") {
490 update(info, { type: "number", format: type, radix: 2 });
491 } else if (type == "o") {
492 update(info, { type: "number", format: type, radix: 8 });
493 } else if (type == "x" || type == "X") {
494 update(info, { type: "number", format: type, radix: 16 });
495 } else if (type == "d" || type == "f" || type == "%") {
496 update(info, { type: "number", format: type, radix: 10 });
497 }
498 if (unmatched) {
499 var msg = "unsupported format flag: " + unmatched.charAt(0);
500 throw new MochiKit.Text.FormatPatternError(pattern, startPos, msg);
501 }
502 return info;
503};
504
505/**
506 * Formats a value as a percentage. This method avoids multiplication
507 * by 100 since it leads to weird numeric rounding errors. Instead it
508 * just move the decimal separator in the text string. It is ugly,
509 * but works...
510 *
511 * @param {Number} value the value to format
512 * @param {Number} precision the number of precision digits
513 */
514MochiKit.Text._truncToPercent = function (value, precision) {
515 // TODO: This can be simplified by using MochiKit.Format._shiftNumber
516 // as roundToFixed does.
517 var str;
518 if (precision >= 0) {
519 str = MochiKit.Format.roundToFixed(value, precision + 2);
520 } else {
521 str = (value == null) ? "0" : value.toString();
522 }
523 var arr = MochiKit.Text.split(str, ".", 2);
524 var frac = MochiKit.Text.padRight(arr[1], 2, "0");
525 var whole = arr[0] + frac.substring(0, 2);
526 frac = frac.substring(2);
527 while (/^0[0-9]/.test(whole)) {
528 whole = whole.substring(1);
529 }
530 return (frac.length <= 0) ? whole : whole + "." + frac;
531};
532
533/**
534 * Creates a new format pattern error.
535 *
536 * @param {String} pattern the format pattern string
537 * @param {Number} pos the position of the error
538 * @param {String} message the error message text
539 *
540 * @return {Error} the format pattern error
541 *
542 * @class The format pattern error class. This error is thrown when
543 * a syntax error is encountered inside a format string.
544 * @property {String} pattern The format pattern string.
545 * @property {Number} pos The position of the error.
546 * @property {String} message The error message text.
547 * @extends MochiKit.Base.NamedError
548 */
549MochiKit.Text.FormatPatternError = function (pattern, pos, message) {
550 this.pattern = pattern;
551 this.pos = pos;
552 this.message = message;
553};
554
555MochiKit.Text.FormatPatternError.prototype = new MochiKit.Base.NamedError("MochiKit.Text.FormatPatternError");
556MochiKit.Text.FormatPatternError.constructor = MochiKit.Text.FormatPatternError;
557
558//
559//XXX: Internet Explorer export fix
560//
561if (MochiKit.__export__) {
562 formatter = MochiKit.Text.formatter;
563 format = MochiKit.Text.format;
564 formatValue = MochiKit.Text.formatValue;
565}
566
567
568MochiKit.Base.nameFunctions(MochiKit.Text);
569MochiKit.Base._exportSymbols(this, MochiKit.Text);
diff --git a/frontend/delta/js/MochiKit/Visual.js b/frontend/delta/js/MochiKit/Visual.js
new file mode 100644
index 0000000..9bcd805
--- a/dev/null
+++ b/frontend/delta/js/MochiKit/Visual.js
@@ -0,0 +1,1999 @@
1/*
2
3Copyright 2008-2013 Clipperz Srl
4
5This file is part of Clipperz, the online password manager.
6For further information about its features and functionalities please
7refer to http://www.clipperz.com.
8
9* Clipperz is free software: you can redistribute it and/or modify it
10 under the terms of the GNU Affero General Public License as published
11 by the Free Software Foundation, either version 3 of the License, or
12 (at your option) any later version.
13
14* Clipperz is distributed in the hope that it will be useful, but
15 WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
17 See the GNU Affero General Public License for more details.
18
19* You should have received a copy of the GNU Affero General Public
20 License along with Clipperz. If not, see http://www.gnu.org/licenses/.
21
22*/
23
24/***
25
26MochiKit.Visual 1.5
27
28See <http://mochikit.com/> for documentation, downloads, license, etc.
29
30(c) 2005 Bob Ippolito and others. All rights Reserved.
31
32***/
33
34MochiKit.Base.module(MochiKit, 'Visual', '1.5', ['Base', 'DOM', 'Style', 'Color', 'Position']);
35
36MochiKit.Visual._RoundCorners = function (e, options) {
37 e = MochiKit.DOM.getElement(e);
38 this._setOptions(options);
39 if (this.options.__unstable__wrapElement) {
40 e = this._doWrap(e);
41 }
42
43 var color = this.options.color;
44 var C = MochiKit.Color.Color;
45 if (this.options.color === "fromElement") {
46 color = C.fromBackground(e);
47 } else if (!(color instanceof C)) {
48 color = C.fromString(color);
49 }
50 this.isTransparent = (color.asRGB().a <= 0);
51
52 var bgColor = this.options.bgColor;
53 if (this.options.bgColor === "fromParent") {
54 bgColor = C.fromBackground(e.offsetParent);
55 } else if (!(bgColor instanceof C)) {
56 bgColor = C.fromString(bgColor);
57 }
58
59 this._roundCornersImpl(e, color, bgColor);
60};
61
62MochiKit.Visual._RoundCorners.prototype = {
63 _doWrap: function (e) {
64 var parent = e.parentNode;
65 var doc = MochiKit.DOM.currentDocument();
66 if (typeof(doc.defaultView) === "undefined"
67 || doc.defaultView === null) {
68 return e;
69 }
70 var style = doc.defaultView.getComputedStyle(e, null);
71 if (typeof(style) === "undefined" || style === null) {
72 return e;
73 }
74 var wrapper = MochiKit.DOM.DIV({"style": {
75 display: "block",
76 // convert padding to margin
77 marginTop: style.getPropertyValue("padding-top"),
78 marginRight: style.getPropertyValue("padding-right"),
79 marginBottom: style.getPropertyValue("padding-bottom"),
80 marginLeft: style.getPropertyValue("padding-left"),
81 // remove padding so the rounding looks right
82 padding: "0px"
83 /*
84 paddingRight: "0px",
85 paddingLeft: "0px"
86 */
87 }});
88 wrapper.innerHTML = e.innerHTML;
89 e.innerHTML = "";
90 e.appendChild(wrapper);
91 return e;
92 },
93
94 _roundCornersImpl: function (e, color, bgColor) {
95 if (this.options.border) {
96 this._renderBorder(e, bgColor);
97 }
98 if (this._isTopRounded()) {
99 this._roundTopCorners(e, color, bgColor);
100 }
101 if (this._isBottomRounded()) {
102 this._roundBottomCorners(e, color, bgColor);
103 }
104 },
105
106 _renderBorder: function (el, bgColor) {
107 var borderValue = "1px solid " + this._borderColor(bgColor);
108 var borderL = "border-left: " + borderValue;
109 var borderR = "border-right: " + borderValue;
110 var style = "style='" + borderL + ";" + borderR + "'";
111 el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>";
112 },
113
114 _roundTopCorners: function (el, color, bgColor) {
115 var corner = this._createCorner(bgColor);
116 for (var i = 0; i < this.options.numSlices; i++) {
117 corner.appendChild(
118 this._createCornerSlice(color, bgColor, i, "top")
119 );
120 }
121 el.style.paddingTop = 0;
122 el.insertBefore(corner, el.firstChild);
123 },
124
125 _roundBottomCorners: function (el, color, bgColor) {
126 var corner = this._createCorner(bgColor);
127 for (var i = (this.options.numSlices - 1); i >= 0; i--) {
128 corner.appendChild(
129 this._createCornerSlice(color, bgColor, i, "bottom")
130 );
131 }
132 el.style.paddingBottom = 0;
133 el.appendChild(corner);
134 },
135
136 _createCorner: function (bgColor) {
137 var dom = MochiKit.DOM;
138 return dom.DIV({style: {backgroundColor: bgColor.toString()}});
139 },
140
141 _createCornerSlice: function (color, bgColor, n, position) {
142 var slice = MochiKit.DOM.SPAN();
143
144 var inStyle = slice.style;
145 inStyle.backgroundColor = color.toString();
146 inStyle.display = "block";
147 inStyle.height = "1px";
148 inStyle.overflow = "hidden";
149 inStyle.fontSize = "1px";
150
151 var borderColor = this._borderColor(color, bgColor);
152 if (this.options.border && n === 0) {
153 inStyle.borderTopStyle = "solid";
154 inStyle.borderTopWidth = "1px";
155 inStyle.borderLeftWidth = "0px";
156 inStyle.borderRightWidth = "0px";
157 inStyle.borderBottomWidth = "0px";
158 // assumes css compliant box model
159 inStyle.height = "0px";
160 inStyle.borderColor = borderColor.toString();
161 } else if (borderColor) {
162 inStyle.borderColor = borderColor.toString();
163 inStyle.borderStyle = "solid";
164 inStyle.borderWidth = "0px 1px";
165 }
166
167 if (!this.options.compact && (n == (this.options.numSlices - 1))) {
168 inStyle.height = "2px";
169 }
170
171 this._setMargin(slice, n, position);
172 this._setBorder(slice, n, position);
173
174 return slice;
175 },
176
177 _setOptions: function (options) {
178 this.options = {
179 corners: "all",
180 color: "fromElement",
181 bgColor: "fromParent",
182 blend: true,
183 border: false,
184 compact: false,
185 __unstable__wrapElement: false
186 };
187 MochiKit.Base.update(this.options, options);
188
189 this.options.numSlices = (this.options.compact ? 2 : 4);
190 },
191
192 _whichSideTop: function () {
193 var corners = this.options.corners;
194 if (this._hasString(corners, "all", "top")) {
195 return "";
196 }
197
198 var has_tl = (corners.indexOf("tl") != -1);
199 var has_tr = (corners.indexOf("tr") != -1);
200 if (has_tl && has_tr) {
201 return "";
202 }
203 if (has_tl) {
204 return "left";
205 }
206 if (has_tr) {
207 return "right";
208 }
209 return "";
210 },
211
212 _whichSideBottom: function () {
213 var corners = this.options.corners;
214 if (this._hasString(corners, "all", "bottom")) {
215 return "";
216 }
217
218 var has_bl = (corners.indexOf('bl') != -1);
219 var has_br = (corners.indexOf('br') != -1);
220 if (has_bl && has_br) {
221 return "";
222 }
223 if (has_bl) {
224 return "left";
225 }
226 if (has_br) {
227 return "right";
228 }
229 return "";
230 },
231
232 _borderColor: function (color, bgColor) {
233 if (color == "transparent") {
234 return bgColor;
235 } else if (this.options.border) {
236 return this.options.border;
237 } else if (this.options.blend) {
238 return bgColor.blendedColor(color);
239 }
240 return "";
241 },
242
243
244 _setMargin: function (el, n, corners) {
245 var marginSize = this._marginSize(n) + "px";
246 var whichSide = (
247 corners == "top" ? this._whichSideTop() : this._whichSideBottom()
248 );
249 var style = el.style;
250
251 if (whichSide == "left") {
252 style.marginLeft = marginSize;
253 style.marginRight = "0px";
254 } else if (whichSide == "right") {
255 style.marginRight = marginSize;
256 style.marginLeft = "0px";
257 } else {
258 style.marginLeft = marginSize;
259 style.marginRight = marginSize;
260 }
261 },
262
263 _setBorder: function (el, n, corners) {
264 var borderSize = this._borderSize(n) + "px";
265 var whichSide = (
266 corners == "top" ? this._whichSideTop() : this._whichSideBottom()
267 );
268
269 var style = el.style;
270 if (whichSide == "left") {
271 style.borderLeftWidth = borderSize;
272 style.borderRightWidth = "0px";
273 } else if (whichSide == "right") {
274 style.borderRightWidth = borderSize;
275 style.borderLeftWidth = "0px";
276 } else {
277 style.borderLeftWidth = borderSize;
278 style.borderRightWidth = borderSize;
279 }
280 },
281
282 _marginSize: function (n) {
283 if (this.isTransparent) {
284 return 0;
285 }
286
287 var o = this.options;
288 if (o.compact && o.blend) {
289 var smBlendedMarginSizes = [1, 0];
290 return smBlendedMarginSizes[n];
291 } else if (o.compact) {
292 var compactMarginSizes = [2, 1];
293 return compactMarginSizes[n];
294 } else if (o.blend) {
295 var blendedMarginSizes = [3, 2, 1, 0];
296 return blendedMarginSizes[n];
297 } else {
298 var marginSizes = [5, 3, 2, 1];
299 return marginSizes[n];
300 }
301 },
302
303 _borderSize: function (n) {
304 var o = this.options;
305 var borderSizes;
306 if (o.compact && (o.blend || this.isTransparent)) {
307 return 1;
308 } else if (o.compact) {
309 borderSizes = [1, 0];
310 } else if (o.blend) {
311 borderSizes = [2, 1, 1, 1];
312 } else if (o.border) {
313 borderSizes = [0, 2, 0, 0];
314 } else if (this.isTransparent) {
315 borderSizes = [5, 3, 2, 1];
316 } else {
317 return 0;
318 }
319 return borderSizes[n];
320 },
321
322 _hasString: function (str) {
323 for (var i = 1; i< arguments.length; i++) {
324 if (str.indexOf(arguments[i]) != -1) {
325 return true;
326 }
327 }
328 return false;
329 },
330
331 _isTopRounded: function () {
332 return this._hasString(this.options.corners,
333 "all", "top", "tl", "tr"
334 );
335 },
336
337 _isBottomRounded: function () {
338 return this._hasString(this.options.corners,
339 "all", "bottom", "bl", "br"
340 );
341 },
342
343 _hasSingleTextChild: function (el) {
344 return (el.childNodes.length == 1 && el.childNodes[0].nodeType == 3);
345 }
346};
347
348/** @id MochiKit.Visual.roundElement */
349MochiKit.Visual.roundElement = function (e, options) {
350 new MochiKit.Visual._RoundCorners(e, options);
351};
352
353/** @id MochiKit.Visual.roundClass */
354MochiKit.Visual.roundClass = function (tagName, className, options) {
355 var elements = MochiKit.DOM.getElementsByTagAndClassName(
356 tagName, className
357 );
358 for (var i = 0; i < elements.length; i++) {
359 MochiKit.Visual.roundElement(elements[i], options);
360 }
361};
362
363/** @id MochiKit.Visual.tagifyText */
364MochiKit.Visual.tagifyText = function (element, /* optional */tagifyStyle) {
365 /***
366
367 Change a node text to character in tags.
368
369 @param tagifyStyle: the style to apply to character nodes, default to
370 'position: relative'.
371
372 ***/
373 tagifyStyle = tagifyStyle || 'position:relative';
374 if (/MSIE/.test(navigator.userAgent)) {
375 tagifyStyle += ';zoom:1';
376 }
377 element = MochiKit.DOM.getElement(element);
378 var ma = MochiKit.Base.map;
379 ma(function (child) {
380 if (child.nodeType == 3) {
381 ma(function (character) {
382 element.insertBefore(
383 MochiKit.DOM.SPAN({style: tagifyStyle},
384 character == ' ' ? String.fromCharCode(160) : character), child);
385 }, child.nodeValue.split(''));
386 MochiKit.DOM.removeElement(child);
387 }
388 }, element.childNodes);
389};
390
391MochiKit.Visual._forceRerendering = function (element) {
392 try {
393 element = MochiKit.DOM.getElement(element);
394 var n = document.createTextNode(' ');
395 element.appendChild(n);
396 element.removeChild(n);
397 } catch(e) {
398 }
399};
400
401/** @id MochiKit.Visual.multiple */
402MochiKit.Visual.multiple = function (elements, effect, /* optional */options) {
403 /***
404
405 Launch the same effect subsequently on given elements.
406
407 ***/
408 options = MochiKit.Base.update({
409 speed: 0.1, delay: 0.0
410 }, options);
411 var masterDelay = options.delay;
412 var index = 0;
413 MochiKit.Base.map(function (innerelement) {
414 options.delay = index * options.speed + masterDelay;
415 new effect(innerelement, options);
416 index += 1;
417 }, elements);
418};
419
420MochiKit.Visual.PAIRS = {
421 'slide': ['slideDown', 'slideUp'],
422 'blind': ['blindDown', 'blindUp'],
423 'appear': ['appear', 'fade'],
424 'size': ['grow', 'shrink']
425};
426
427/** @id MochiKit.Visual.toggle */
428MochiKit.Visual.toggle = function (element, /* optional */effect, /* optional */options) {
429 /***
430
431 Toggle an item between two state depending of its visibility, making
432 a effect between these states. Default effect is 'appear', can be
433 'slide' or 'blind'.
434
435 ***/
436 element = MochiKit.DOM.getElement(element);
437 effect = (effect || 'appear').toLowerCase();
438 options = MochiKit.Base.update({
439 queue: {position: 'end', scope: (element.id || 'global'), limit: 1}
440 }, options);
441 var v = MochiKit.Visual;
442 v[MochiKit.Style.getStyle(element, 'display') != 'none' ?
443 v.PAIRS[effect][1] : v.PAIRS[effect][0]](element, options);
444};
445
446/***
447
448Transitions: define functions calculating variations depending of a position.
449
450***/
451
452MochiKit.Visual.Transitions = { __export__: false };
453
454/** @id MochiKit.Visual.Transitions.linear */
455MochiKit.Visual.Transitions.linear = function (pos) {
456 return pos;
457};
458
459/** @id MochiKit.Visual.Transitions.sinoidal */
460MochiKit.Visual.Transitions.sinoidal = function (pos) {
461 return 0.5 - Math.cos(pos*Math.PI)/2;
462};
463
464/** @id MochiKit.Visual.Transitions.reverse */
465MochiKit.Visual.Transitions.reverse = function (pos) {
466 return 1 - pos;
467};
468
469/** @id MochiKit.Visual.Transitions.flicker */
470MochiKit.Visual.Transitions.flicker = function (pos) {
471 return 0.25 - Math.cos(pos*Math.PI)/4 + Math.random()/2;
472};
473
474/** @id MochiKit.Visual.Transitions.wobble */
475MochiKit.Visual.Transitions.wobble = function (pos) {
476 return 0.5 - Math.cos(9*pos*Math.PI)/2;
477};
478
479/** @id MochiKit.Visual.Transitions.pulse */
480MochiKit.Visual.Transitions.pulse = function (pos, pulses) {
481 if (pulses) {
482 pos *= 2 * pulses;
483 } else {
484 pos *= 10;
485 }
486 var decimals = pos - Math.floor(pos);
487 return (Math.floor(pos) % 2 == 0) ? decimals : 1 - decimals;
488};
489
490/** @id MochiKit.Visual.Transitions.parabolic */
491MochiKit.Visual.Transitions.parabolic = function (pos) {
492 return pos * pos;
493};
494
495/** @id MochiKit.Visual.Transitions.spring */
496MochiKit.Visual.Transitions.spring = function (pos) {
497 return 1 - (Math.cos(pos * 2.5 * Math.PI) * Math.exp(-pos * 6));
498};
499
500/** @id MochiKit.Visual.Transitions.none */
501MochiKit.Visual.Transitions.none = function (pos) {
502 return 0;
503};
504
505/** @id MochiKit.Visual.Transitions.full */
506MochiKit.Visual.Transitions.full = function (pos) {
507 return 1;
508};
509
510/***
511
512Core effects
513
514***/
515
516MochiKit.Visual.ScopedQueue = function () {
517 var cls = arguments.callee;
518 if (!(this instanceof cls)) {
519 return new cls();
520 }
521 this.__init__();
522};
523MochiKit.Visual.ScopedQueue.__export__ = false;
524
525MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype, {
526 __init__: function () {
527 this.effects = [];
528 this.interval = null;
529 },
530
531 /** @id MochiKit.Visual.ScopedQueue.prototype.add */
532 add: function (effect) {
533 var timestamp = new Date().getTime();
534
535 var position = (typeof(effect.options.queue) == 'string') ?
536 effect.options.queue : effect.options.queue.position;
537
538 var ma = MochiKit.Base.map;
539 switch (position) {
540 case 'front':
541 // move unstarted effects after this effect
542 ma(function (e) {
543 if (e.state == 'idle') {
544 e.startOn += effect.finishOn;
545 e.finishOn += effect.finishOn;
546 }
547 }, this.effects);
548 break;
549 case 'end':
550 var finish;
551 // start effect after last queued effect has finished
552 ma(function (e) {
553 var i = e.finishOn;
554 if (i >= (finish || i)) {
555 finish = i;
556 }
557 }, this.effects);
558 timestamp = finish || timestamp;
559 break;
560 case 'break':
561 ma(function (e) {
562 e.finalize();
563 }, this.effects);
564 break;
565 case 'replace':
566 ma(function (e) {
567 e.cancel();
568 }, this.effects);
569 break;
570 }
571
572 effect.startOn += timestamp;
573 effect.finishOn += timestamp;
574 if (!effect.options.queue.limit ||
575 this.effects.length < effect.options.queue.limit) {
576 this.effects.push(effect);
577 }
578
579 if (!this.interval) {
580 this.interval = this.startLoop(MochiKit.Base.bind(this.loop, this),
581 40);
582 }
583 },
584
585 /** @id MochiKit.Visual.ScopedQueue.prototype.startLoop */
586 startLoop: function (func, interval) {
587 return setInterval(func, interval);
588 },
589
590 /** @id MochiKit.Visual.ScopedQueue.prototype.remove */
591 remove: function (effect) {
592 this.effects = MochiKit.Base.filter(function (e) {
593 return e != effect;
594 }, this.effects);
595 if (!this.effects.length) {
596 this.stopLoop(this.interval);
597 this.interval = null;
598 }
599 },
600
601 /** @id MochiKit.Visual.ScopedQueue.prototype.stopLoop */
602 stopLoop: function (interval) {
603 clearInterval(interval);
604 },
605
606 /** @id MochiKit.Visual.ScopedQueue.prototype.loop */
607 loop: function () {
608 var timePos = new Date().getTime();
609 MochiKit.Base.map(function (effect) {
610 effect.loop(timePos);
611 }, this.effects);
612 }
613});
614
615MochiKit.Visual.Queues = {
616 __export__: false,
617 instances: {},
618 get: function (queueName) {
619 if (typeof(queueName) != 'string') {
620 return queueName;
621 }
622
623 if (!this.instances[queueName]) {
624 this.instances[queueName] = new MochiKit.Visual.ScopedQueue();
625 }
626 return this.instances[queueName];
627 }
628};
629
630MochiKit.Visual.Queue = MochiKit.Visual.Queues.get('global');
631MochiKit.Visual.Queue.__export__ = false;
632
633MochiKit.Visual.DefaultOptions = {
634 __export__: false,
635 transition: MochiKit.Visual.Transitions.sinoidal,
636 duration: 1.0, // seconds
637 fps: 25.0, // max. 25fps due to MochiKit.Visual.Queue implementation
638 sync: false, // true for combining
639 from: 0.0,
640 to: 1.0,
641 delay: 0.0,
642 queue: 'parallel'
643};
644
645MochiKit.Visual.Base = function () {};
646
647MochiKit.Visual.Base.prototype = {
648 /***
649
650 Basic class for all Effects. Define a looping mechanism called for each step
651 of an effect. Don't instantiate it, only subclass it.
652
653 ***/
654
655 __class__ : MochiKit.Visual.Base,
656
657 /** @id MochiKit.Visual.Base.prototype.start */
658 start: function (options) {
659 var v = MochiKit.Visual;
660 this.options = MochiKit.Base.setdefault(options,
661 v.DefaultOptions);
662 this.currentFrame = 0;
663 this.state = 'idle';
664 this.startOn = this.options.delay*1000;
665 this.finishOn = this.startOn + (this.options.duration*1000);
666 this.event('beforeStart');
667 if (!this.options.sync) {
668 v.Queues.get(typeof(this.options.queue) == 'string' ?
669 'global' : this.options.queue.scope).add(this);
670 }
671 },
672
673 /** @id MochiKit.Visual.Base.prototype.loop */
674 loop: function (timePos) {
675 if (timePos >= this.startOn) {
676 if (timePos >= this.finishOn) {
677 return this.finalize();
678 }
679 var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
680 var frame =
681 Math.round(pos * this.options.fps * this.options.duration);
682 if (frame > this.currentFrame) {
683 this.render(pos);
684 this.currentFrame = frame;
685 }
686 }
687 },
688
689 /** @id MochiKit.Visual.Base.prototype.render */
690 render: function (pos) {
691 if (this.state == 'idle') {
692 this.state = 'running';
693 this.event('beforeSetup');
694 this.setup();
695 this.event('afterSetup');
696 }
697 if (this.state == 'running') {
698 var trans = this.options.transition;
699 if (typeof(trans) == "string") {
700 trans = MochiKit.Visual.Transitions[trans];
701 }
702 if (typeof(trans) == "function") {
703 pos = trans(pos);
704 }
705 pos *= (this.options.to - this.options.from);
706 pos += this.options.from;
707 this.event('beforeUpdate');
708 this.update(pos);
709 this.event('afterUpdate');
710 }
711 },
712
713 /** @id MochiKit.Visual.Base.prototype.cancel */
714 cancel: function () {
715 if (!this.options.sync) {
716 MochiKit.Visual.Queues.get(typeof(this.options.queue) == 'string' ?
717 'global' : this.options.queue.scope).remove(this);
718 }
719 this.state = 'finished';
720 },
721
722 /** @id MochiKit.Visual.Base.prototype.finalize */
723 finalize: function () {
724 this.render(1.0);
725 this.cancel();
726 this.event('beforeFinish');
727 this.finish();
728 this.event('afterFinish');
729 },
730
731 setup: function () {
732 },
733
734 finish: function () {
735 },
736
737 update: function (position) {
738 },
739
740 /** @id MochiKit.Visual.Base.prototype.event */
741 event: function (eventName) {
742 if (this.options[eventName + 'Internal']) {
743 this.options[eventName + 'Internal'](this);
744 }
745 if (this.options[eventName]) {
746 this.options[eventName](this);
747 }
748 },
749
750 /** @id MochiKit.Visual.Base.prototype.repr */
751 repr: function () {
752 return '[' + this.__class__.NAME + ', options:' +
753 MochiKit.Base.repr(this.options) + ']';
754 }
755};
756
757/** @id MochiKit.Visual.Parallel */
758MochiKit.Visual.Parallel = function (effects, options) {
759 var cls = arguments.callee;
760 if (!(this instanceof cls)) {
761 return new cls(effects, options);
762 }
763
764 this.__init__(effects, options);
765};
766
767MochiKit.Visual.Parallel.prototype = new MochiKit.Visual.Base();
768
769MochiKit.Base.update(MochiKit.Visual.Parallel.prototype, {
770 /***
771
772 Run multiple effects at the same time.
773
774 ***/
775
776 __class__ : MochiKit.Visual.Parallel,
777
778 __init__: function (effects, options) {
779 this.effects = effects || [];
780 this.start(options);
781 },
782
783 /** @id MochiKit.Visual.Parallel.prototype.update */
784 update: function (position) {
785 MochiKit.Base.map(function (effect) {
786 effect.render(position);
787 }, this.effects);
788 },
789
790 /** @id MochiKit.Visual.Parallel.prototype.finish */
791 finish: function () {
792 MochiKit.Base.map(function (effect) {
793 effect.finalize();
794 }, this.effects);
795 }
796});
797
798/** @id MochiKit.Visual.Sequence */
799MochiKit.Visual.Sequence = function (effects, options) {
800 var cls = arguments.callee;
801 if (!(this instanceof cls)) {
802 return new cls(effects, options);
803 }
804 this.__init__(effects, options);
805};
806
807MochiKit.Visual.Sequence.prototype = new MochiKit.Visual.Base();
808
809MochiKit.Base.update(MochiKit.Visual.Sequence.prototype, {
810
811 __class__ : MochiKit.Visual.Sequence,
812
813 __init__: function (effects, options) {
814 var defs = { transition: MochiKit.Visual.Transitions.linear,
815 duration: 0 };
816 this.effects = effects || [];
817 MochiKit.Base.map(function (effect) {
818 defs.duration += effect.options.duration;
819 }, this.effects);
820 MochiKit.Base.setdefault(options, defs);
821 this.start(options);
822 },
823
824 /** @id MochiKit.Visual.Sequence.prototype.update */
825 update: function (position) {
826 var time = position * this.options.duration;
827 for (var i = 0; i < this.effects.length; i++) {
828 var effect = this.effects[i];
829 if (time <= effect.options.duration) {
830 effect.render(time / effect.options.duration);
831 break;
832 } else {
833 time -= effect.options.duration;
834 }
835 }
836 },
837
838 /** @id MochiKit.Visual.Sequence.prototype.finish */
839 finish: function () {
840 MochiKit.Base.map(function (effect) {
841 effect.finalize();
842 }, this.effects);
843 }
844});
845
846/** @id MochiKit.Visual.Opacity */
847MochiKit.Visual.Opacity = function (element, options) {
848 var cls = arguments.callee;
849 if (!(this instanceof cls)) {
850 return new cls(element, options);
851 }
852 this.__init__(element, options);
853};
854
855MochiKit.Visual.Opacity.prototype = new MochiKit.Visual.Base();
856
857MochiKit.Base.update(MochiKit.Visual.Opacity.prototype, {
858 /***
859
860 Change the opacity of an element.
861
862 @param options: 'from' and 'to' change the starting and ending opacities.
863 Must be between 0.0 and 1.0. Default to current opacity and 1.0.
864
865 ***/
866
867 __class__ : MochiKit.Visual.Opacity,
868
869 __init__: function (element, /* optional */options) {
870 var b = MochiKit.Base;
871 var s = MochiKit.Style;
872 this.element = MochiKit.DOM.getElement(element);
873 // make this work on IE on elements without 'layout'
874 if (this.element.currentStyle &&
875 (!this.element.currentStyle.hasLayout)) {
876 s.setStyle(this.element, {zoom: 1});
877 }
878 options = b.update({
879 from: s.getStyle(this.element, 'opacity') || 0.0,
880 to: 1.0
881 }, options);
882 this.start(options);
883 },
884
885 /** @id MochiKit.Visual.Opacity.prototype.update */
886 update: function (position) {
887 MochiKit.Style.setStyle(this.element, {'opacity': position});
888 }
889});
890
891/** @id MochiKit.Visual.Move.prototype */
892MochiKit.Visual.Move = function (element, options) {
893 var cls = arguments.callee;
894 if (!(this instanceof cls)) {
895 return new cls(element, options);
896 }
897 this.__init__(element, options);
898};
899
900MochiKit.Visual.Move.prototype = new MochiKit.Visual.Base();
901
902MochiKit.Base.update(MochiKit.Visual.Move.prototype, {
903 /***
904
905 Move an element between its current position to a defined position
906
907 @param options: 'x' and 'y' for final positions, default to 0, 0.
908
909 ***/
910
911 __class__ : MochiKit.Visual.Move,
912
913 __init__: function (element, /* optional */options) {
914 this.element = MochiKit.DOM.getElement(element);
915 options = MochiKit.Base.update({
916 x: 0,
917 y: 0,
918 mode: 'relative'
919 }, options);
920 this.start(options);
921 },
922
923 /** @id MochiKit.Visual.Move.prototype.setup */
924 setup: function () {
925 // Bug in Opera: Opera returns the 'real' position of a static element
926 // or relative element that does not have top/left explicitly set.
927 // ==> Always set top and left for position relative elements in your
928 // stylesheets (to 0 if you do not need them)
929 MochiKit.Style.makePositioned(this.element);
930
931 var s = this.element.style;
932 var originalVisibility = s.visibility;
933 var originalDisplay = s.display;
934 if (originalDisplay == 'none') {
935 s.visibility = 'hidden';
936 s.display = '';
937 }
938
939 this.originalLeft = parseFloat(MochiKit.Style.getStyle(this.element, 'left') || '0');
940 this.originalTop = parseFloat(MochiKit.Style.getStyle(this.element, 'top') || '0');
941
942 if (this.options.mode == 'absolute') {
943 // absolute movement, so we need to calc deltaX and deltaY
944 this.options.x -= this.originalLeft;
945 this.options.y -= this.originalTop;
946 }
947 if (originalDisplay == 'none') {
948 s.visibility = originalVisibility;
949 s.display = originalDisplay;
950 }
951 },
952
953 /** @id MochiKit.Visual.Move.prototype.update */
954 update: function (position) {
955 MochiKit.Style.setStyle(this.element, {
956 left: Math.round(this.options.x * position + this.originalLeft) + 'px',
957 top: Math.round(this.options.y * position + this.originalTop) + 'px'
958 });
959 }
960});
961
962/** @id MochiKit.Visual.Scale */
963MochiKit.Visual.Scale = function (element, percent, options) {
964 var cls = arguments.callee;
965 if (!(this instanceof cls)) {
966 return new cls(element, percent, options);
967 }
968 this.__init__(element, percent, options);
969};
970
971MochiKit.Visual.Scale.prototype = new MochiKit.Visual.Base();
972
973MochiKit.Base.update(MochiKit.Visual.Scale.prototype, {
974 /***
975
976 Change the size of an element.
977
978 @param percent: final_size = percent*original_size
979
980 @param options: several options changing scale behaviour
981
982 ***/
983
984 __class__ : MochiKit.Visual.Scale,
985
986 __init__: function (element, percent, /* optional */options) {
987 this.element = MochiKit.DOM.getElement(element);
988 options = MochiKit.Base.update({
989 scaleX: true,
990 scaleY: true,
991 scaleContent: true,
992 scaleFromCenter: false,
993 scaleMode: 'box', // 'box' or 'contents' or {} with provided values
994 scaleFrom: 100.0,
995 scaleTo: percent
996 }, options);
997 this.start(options);
998 },
999
1000 /** @id MochiKit.Visual.Scale.prototype.setup */
1001 setup: function () {
1002 this.restoreAfterFinish = this.options.restoreAfterFinish || false;
1003 this.elementPositioning = MochiKit.Style.getStyle(this.element,
1004 'position');
1005
1006 var ma = MochiKit.Base.map;
1007 var b = MochiKit.Base.bind;
1008 this.originalStyle = {};
1009 ma(b(function (k) {
1010 this.originalStyle[k] = this.element.style[k];
1011 }, this), ['top', 'left', 'width', 'height', 'fontSize']);
1012
1013 this.originalTop = this.element.offsetTop;
1014 this.originalLeft = this.element.offsetLeft;
1015
1016 var fontSize = MochiKit.Style.getStyle(this.element,
1017 'font-size') || '100%';
1018 ma(b(function (fontSizeType) {
1019 if (fontSize.indexOf(fontSizeType) > 0) {
1020 this.fontSize = parseFloat(fontSize);
1021 this.fontSizeType = fontSizeType;
1022 }
1023 }, this), ['em', 'px', '%']);
1024
1025 this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
1026
1027 if (/^content/.test(this.options.scaleMode)) {
1028 this.dims = [this.element.scrollHeight, this.element.scrollWidth];
1029 } else if (this.options.scaleMode == 'box') {
1030 this.dims = [this.element.offsetHeight, this.element.offsetWidth];
1031 } else {
1032 this.dims = [this.options.scaleMode.originalHeight,
1033 this.options.scaleMode.originalWidth];
1034 }
1035 },
1036
1037 /** @id MochiKit.Visual.Scale.prototype.update */
1038 update: function (position) {
1039 var currentScale = (this.options.scaleFrom/100.0) +
1040 (this.factor * position);
1041 if (this.options.scaleContent && this.fontSize) {
1042 MochiKit.Style.setStyle(this.element, {
1043 fontSize: this.fontSize * currentScale + this.fontSizeType
1044 });
1045 }
1046 this.setDimensions(this.dims[0] * currentScale,
1047 this.dims[1] * currentScale);
1048 },
1049
1050 /** @id MochiKit.Visual.Scale.prototype.finish */
1051 finish: function () {
1052 if (this.restoreAfterFinish) {
1053 MochiKit.Style.setStyle(this.element, this.originalStyle);
1054 }
1055 },
1056
1057 /** @id MochiKit.Visual.Scale.prototype.setDimensions */
1058 setDimensions: function (height, width) {
1059 var d = {};
1060 var r = Math.round;
1061 if (/MSIE/.test(navigator.userAgent)) {
1062 r = Math.ceil;
1063 }
1064 if (this.options.scaleX) {
1065 d.width = r(width) + 'px';
1066 }
1067 if (this.options.scaleY) {
1068 d.height = r(height) + 'px';
1069 }
1070 if (this.options.scaleFromCenter) {
1071 var topd = (height - this.dims[0])/2;
1072 var leftd = (width - this.dims[1])/2;
1073 if (this.elementPositioning == 'absolute') {
1074 if (this.options.scaleY) {
1075 d.top = this.originalTop - topd + 'px';
1076 }
1077 if (this.options.scaleX) {
1078 d.left = this.originalLeft - leftd + 'px';
1079 }
1080 } else {
1081 if (this.options.scaleY) {
1082 d.top = -topd + 'px';
1083 }
1084 if (this.options.scaleX) {
1085 d.left = -leftd + 'px';
1086 }
1087 }
1088 }
1089 MochiKit.Style.setStyle(this.element, d);
1090 }
1091});
1092
1093/** @id MochiKit.Visual.Highlight */
1094MochiKit.Visual.Highlight = function (element, options) {
1095 var cls = arguments.callee;
1096 if (!(this instanceof cls)) {
1097 return new cls(element, options);
1098 }
1099 this.__init__(element, options);
1100};
1101
1102MochiKit.Visual.Highlight.prototype = new MochiKit.Visual.Base();
1103
1104MochiKit.Base.update(MochiKit.Visual.Highlight.prototype, {
1105 /***
1106
1107 Highlight an item of the page.
1108
1109 @param options: 'startcolor' for choosing highlighting color, default
1110 to '#ffff99'.
1111
1112 ***/
1113
1114 __class__ : MochiKit.Visual.Highlight,
1115
1116 __init__: function (element, /* optional */options) {
1117 this.element = MochiKit.DOM.getElement(element);
1118 options = MochiKit.Base.update({
1119 startcolor: '#ffff99'
1120 }, options);
1121 this.start(options);
1122 },
1123
1124 /** @id MochiKit.Visual.Highlight.prototype.setup */
1125 setup: function () {
1126 var b = MochiKit.Base;
1127 var s = MochiKit.Style;
1128 // Prevent executing on elements not in the layout flow
1129 if (s.getStyle(this.element, 'display') == 'none') {
1130 this.cancel();
1131 return;
1132 }
1133 // Disable background image during the effect
1134 this.oldStyle = {
1135 backgroundImage: s.getStyle(this.element, 'background-image')
1136 };
1137 s.setStyle(this.element, {
1138 backgroundImage: 'none'
1139 });
1140
1141 if (!this.options.endcolor) {
1142 this.options.endcolor =
1143 MochiKit.Color.Color.fromBackground(this.element).toHexString();
1144 }
1145 if (b.isUndefinedOrNull(this.options.restorecolor)) {
1146 this.options.restorecolor = s.getStyle(this.element,
1147 'background-color');
1148 }
1149 // init color calculations
1150 this._base = b.map(b.bind(function (i) {
1151 return parseInt(
1152 this.options.startcolor.slice(i*2 + 1, i*2 + 3), 16);
1153 }, this), [0, 1, 2]);
1154 this._delta = b.map(b.bind(function (i) {
1155 return parseInt(this.options.endcolor.slice(i*2 + 1, i*2 + 3), 16)
1156 - this._base[i];
1157 }, this), [0, 1, 2]);
1158 },
1159
1160 /** @id MochiKit.Visual.Highlight.prototype.update */
1161 update: function (position) {
1162 var m = '#';
1163 MochiKit.Base.map(MochiKit.Base.bind(function (i) {
1164 m += MochiKit.Color.toColorPart(Math.round(this._base[i] +
1165 this._delta[i]*position));
1166 }, this), [0, 1, 2]);
1167 MochiKit.Style.setStyle(this.element, {
1168 backgroundColor: m
1169 });
1170 },
1171
1172 /** @id MochiKit.Visual.Highlight.prototype.finish */
1173 finish: function () {
1174 MochiKit.Style.setStyle(this.element,
1175 MochiKit.Base.update(this.oldStyle, {
1176 backgroundColor: this.options.restorecolor
1177 }));
1178 }
1179});
1180
1181/** @id MochiKit.Visual.ScrollTo */
1182MochiKit.Visual.ScrollTo = function (element, options) {
1183 var cls = arguments.callee;
1184 if (!(this instanceof cls)) {
1185 return new cls(element, options);
1186 }
1187 this.__init__(element, options);
1188};
1189
1190MochiKit.Visual.ScrollTo.prototype = new MochiKit.Visual.Base();
1191
1192MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype, {
1193 /***
1194
1195 Scroll to an element in the page.
1196
1197 ***/
1198
1199 __class__ : MochiKit.Visual.ScrollTo,
1200
1201 __init__: function (element, /* optional */options) {
1202 this.element = MochiKit.DOM.getElement(element);
1203 this.start(options);
1204 },
1205
1206 /** @id MochiKit.Visual.ScrollTo.prototype.setup */
1207 setup: function () {
1208 var p = MochiKit.Position;
1209 p.prepare();
1210 var offsets = p.cumulativeOffset(this.element);
1211 if (this.options.offset) {
1212 offsets.y += this.options.offset;
1213 }
1214 var max;
1215 if (window.innerHeight) {
1216 max = window.innerHeight - window.height;
1217 } else if (document.documentElement &&
1218 document.documentElement.clientHeight) {
1219 max = document.documentElement.clientHeight -
1220 document.body.scrollHeight;
1221 } else if (document.body) {
1222 max = document.body.clientHeight - document.body.scrollHeight;
1223 }
1224 this.scrollStart = p.windowOffset.y;
1225 this.delta = (offsets.y > max ? max : offsets.y) - this.scrollStart;
1226 },
1227
1228 /** @id MochiKit.Visual.ScrollTo.prototype.update */
1229 update: function (position) {
1230 var p = MochiKit.Position;
1231 p.prepare();
1232 window.scrollTo(p.windowOffset.x, this.scrollStart + (position * this.delta));
1233 }
1234});
1235
1236MochiKit.Visual._CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
1237
1238MochiKit.Visual.Morph = function (element, options) {
1239 var cls = arguments.callee;
1240 if (!(this instanceof cls)) {
1241 return new cls(element, options);
1242 }
1243 this.__init__(element, options);
1244};
1245
1246MochiKit.Visual.Morph.prototype = new MochiKit.Visual.Base();
1247
1248MochiKit.Base.update(MochiKit.Visual.Morph.prototype, {
1249 /***
1250
1251 Morph effect: make a transformation from current style to the given style,
1252 automatically making a transition between the two.
1253
1254 ***/
1255
1256 __class__ : MochiKit.Visual.Morph,
1257
1258 __init__: function (element, /* optional */options) {
1259 this.element = MochiKit.DOM.getElement(element);
1260 this.start(options);
1261 },
1262
1263 /** @id MochiKit.Visual.Morph.prototype.setup */
1264 setup: function () {
1265 var b = MochiKit.Base;
1266 var style = this.options.style;
1267 this.styleStart = {};
1268 this.styleEnd = {};
1269 this.units = {};
1270 var value, unit;
1271 for (var s in style) {
1272 value = style[s];
1273 s = b.camelize(s);
1274 if (MochiKit.Visual._CSS_LENGTH.test(value)) {
1275 var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
1276 value = parseFloat(components[1]);
1277 unit = (components.length == 3) ? components[2] : null;
1278 this.styleEnd[s] = value;
1279 this.units[s] = unit;
1280 value = MochiKit.Style.getStyle(this.element, s);
1281 components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
1282 value = parseFloat(components[1]);
1283 this.styleStart[s] = value;
1284 } else if (/[Cc]olor$/.test(s)) {
1285 var c = MochiKit.Color.Color;
1286 value = c.fromString(value);
1287 if (value) {
1288 this.units[s] = "color";
1289 this.styleEnd[s] = value.toHexString();
1290 value = MochiKit.Style.getStyle(this.element, s);
1291 this.styleStart[s] = c.fromString(value).toHexString();
1292
1293 this.styleStart[s] = b.map(b.bind(function (i) {
1294 return parseInt(
1295 this.styleStart[s].slice(i*2 + 1, i*2 + 3), 16);
1296 }, this), [0, 1, 2]);
1297 this.styleEnd[s] = b.map(b.bind(function (i) {
1298 return parseInt(
1299 this.styleEnd[s].slice(i*2 + 1, i*2 + 3), 16);
1300 }, this), [0, 1, 2]);
1301 }
1302 } else {
1303 // For non-length & non-color properties, we just set the value
1304 this.element.style[s] = value;
1305 }
1306 }
1307 },
1308
1309 /** @id MochiKit.Visual.Morph.prototype.update */
1310 update: function (position) {
1311 var value;
1312 for (var s in this.styleStart) {
1313 if (this.units[s] == "color") {
1314 var m = '#';
1315 var start = this.styleStart[s];
1316 var end = this.styleEnd[s];
1317 MochiKit.Base.map(MochiKit.Base.bind(function (i) {
1318 m += MochiKit.Color.toColorPart(Math.round(start[i] +
1319 (end[i] - start[i])*position));
1320 }, this), [0, 1, 2]);
1321 this.element.style[s] = m;
1322 } else {
1323 value = this.styleStart[s] + Math.round((this.styleEnd[s] - this.styleStart[s]) * position * 1000) / 1000 + this.units[s];
1324 this.element.style[s] = value;
1325 }
1326 }
1327 }
1328});
1329
1330/***
1331
1332Combination effects.
1333
1334***/
1335
1336/** @id MochiKit.Visual.fade */
1337MochiKit.Visual.fade = function (element, /* optional */ options) {
1338 /***
1339
1340 Fade a given element: change its opacity and hide it in the end.
1341
1342 @param options: 'to' and 'from' to change opacity.
1343
1344 ***/
1345 var s = MochiKit.Style;
1346 var oldOpacity = s.getStyle(element, 'opacity');
1347 options = MochiKit.Base.update({
1348 from: s.getStyle(element, 'opacity') || 1.0,
1349 to: 0.0,
1350 afterFinishInternal: function (effect) {
1351 if (effect.options.to !== 0) {
1352 return;
1353 }
1354 s.hideElement(effect.element);
1355 s.setStyle(effect.element, {'opacity': oldOpacity});
1356 }
1357 }, options);
1358 return new MochiKit.Visual.Opacity(element, options);
1359};
1360
1361/** @id MochiKit.Visual.appear */
1362MochiKit.Visual.appear = function (element, /* optional */ options) {
1363 /***
1364
1365 Make an element appear.
1366
1367 @param options: 'to' and 'from' to change opacity.
1368
1369 ***/
1370 var s = MochiKit.Style;
1371 var v = MochiKit.Visual;
1372 options = MochiKit.Base.update({
1373 from: (s.getStyle(element, 'display') == 'none' ? 0.0 :
1374 s.getStyle(element, 'opacity') || 0.0),
1375 to: 1.0,
1376 // force Safari to render floated elements properly
1377 afterFinishInternal: function (effect) {
1378 v._forceRerendering(effect.element);
1379 },
1380 beforeSetupInternal: function (effect) {
1381 s.setStyle(effect.element, {'opacity': effect.options.from});
1382 s.showElement(effect.element);
1383 }
1384 }, options);
1385 return new v.Opacity(element, options);
1386};
1387
1388/** @id MochiKit.Visual.puff */
1389MochiKit.Visual.puff = function (element, /* optional */ options) {
1390 /***
1391
1392 'Puff' an element: grow it to double size, fading it and make it hidden.
1393
1394 ***/
1395 var s = MochiKit.Style;
1396 var v = MochiKit.Visual;
1397 element = MochiKit.DOM.getElement(element);
1398 var elementDimensions = MochiKit.Style.getElementDimensions(element, true);
1399 var oldStyle = {
1400 position: s.getStyle(element, 'position'),
1401 top: element.style.top,
1402 left: element.style.left,
1403 width: element.style.width,
1404 height: element.style.height,
1405 opacity: s.getStyle(element, 'opacity')
1406 };
1407 options = MochiKit.Base.update({
1408 beforeSetupInternal: function (effect) {
1409 MochiKit.Position.absolutize(effect.effects[0].element);
1410 },
1411 afterFinishInternal: function (effect) {
1412 s.hideElement(effect.effects[0].element);
1413 s.setStyle(effect.effects[0].element, oldStyle);
1414 },
1415 scaleContent: true,
1416 scaleFromCenter: true
1417 }, options);
1418 return new v.Parallel(
1419 [new v.Scale(element, 200,
1420 {sync: true, scaleFromCenter: options.scaleFromCenter,
1421 scaleMode: {originalHeight: elementDimensions.h,
1422 originalWidth: elementDimensions.w},
1423 scaleContent: options.scaleContent, restoreAfterFinish: true}),
1424 new v.Opacity(element, {sync: true, to: 0.0 })],
1425 options);
1426};
1427
1428/** @id MochiKit.Visual.blindUp */
1429MochiKit.Visual.blindUp = function (element, /* optional */ options) {
1430 /***
1431
1432 Blind an element up: change its vertical size to 0.
1433
1434 ***/
1435 var d = MochiKit.DOM;
1436 var s = MochiKit.Style;
1437 element = d.getElement(element);
1438 var elementDimensions = s.getElementDimensions(element, true);
1439 var elemClip = s.makeClipping(element);
1440 options = MochiKit.Base.update({
1441 scaleContent: false,
1442 scaleX: false,
1443 scaleMode: {originalHeight: elementDimensions.h,
1444 originalWidth: elementDimensions.w},
1445 restoreAfterFinish: true,
1446 afterFinishInternal: function (effect) {
1447 s.hideElement(effect.element);
1448 s.undoClipping(effect.element, elemClip);
1449 }
1450 }, options);
1451 return new MochiKit.Visual.Scale(element, 0, options);
1452};
1453
1454/** @id MochiKit.Visual.blindDown */
1455MochiKit.Visual.blindDown = function (element, /* optional */ options) {
1456 /***
1457
1458 Blind an element down: restore its vertical size.
1459
1460 ***/
1461 var d = MochiKit.DOM;
1462 var s = MochiKit.Style;
1463 element = d.getElement(element);
1464 var elementDimensions = s.getElementDimensions(element, true);
1465 var elemClip;
1466 options = MochiKit.Base.update({
1467 scaleContent: false,
1468 scaleX: false,
1469 scaleFrom: 0,
1470 scaleMode: {originalHeight: elementDimensions.h,
1471 originalWidth: elementDimensions.w},
1472 restoreAfterFinish: true,
1473 afterSetupInternal: function (effect) {
1474 elemClip = s.makeClipping(effect.element);
1475 s.setStyle(effect.element, {height: '0px'});
1476 s.showElement(effect.element);
1477 },
1478 afterFinishInternal: function (effect) {
1479 s.undoClipping(effect.element, elemClip);
1480 }
1481 }, options);
1482 return new MochiKit.Visual.Scale(element, 100, options);
1483};
1484
1485/** @id MochiKit.Visual.switchOff */
1486MochiKit.Visual.switchOff = function (element, /* optional */ options) {
1487 /***
1488
1489 Apply a switch-off-like effect.
1490
1491 ***/
1492 var d = MochiKit.DOM;
1493 var s = MochiKit.Style;
1494 element = d.getElement(element);
1495 var elementDimensions = s.getElementDimensions(element, true);
1496 var oldOpacity = s.getStyle(element, 'opacity');
1497 var elemClip;
1498 options = MochiKit.Base.update({
1499 duration: 0.7,
1500 restoreAfterFinish: true,
1501 beforeSetupInternal: function (effect) {
1502 s.makePositioned(element);
1503 elemClip = s.makeClipping(element);
1504 },
1505 afterFinishInternal: function (effect) {
1506 s.hideElement(element);
1507 s.undoClipping(element, elemClip);
1508 s.undoPositioned(element);
1509 s.setStyle(element, {'opacity': oldOpacity});
1510 }
1511 }, options);
1512 var v = MochiKit.Visual;
1513 return new v.Sequence(
1514 [new v.appear(element,
1515 { sync: true, duration: 0.57 * options.duration,
1516 from: 0, transition: v.Transitions.flicker }),
1517 new v.Scale(element, 1,
1518 { sync: true, duration: 0.43 * options.duration,
1519 scaleFromCenter: true, scaleX: false,
1520 scaleMode: {originalHeight: elementDimensions.h,
1521 originalWidth: elementDimensions.w},
1522 scaleContent: false, restoreAfterFinish: true })],
1523 options);
1524};
1525
1526/** @id MochiKit.Visual.dropOut */
1527MochiKit.Visual.dropOut = function (element, /* optional */ options) {
1528 /***
1529
1530 Make an element fall and disappear.
1531
1532 ***/
1533 var d = MochiKit.DOM;
1534 var s = MochiKit.Style;
1535 element = d.getElement(element);
1536 var oldStyle = {
1537 top: s.getStyle(element, 'top'),
1538 left: s.getStyle(element, 'left'),
1539 opacity: s.getStyle(element, 'opacity')
1540 };
1541
1542 options = MochiKit.Base.update({
1543 duration: 0.5,
1544 distance: 100,
1545 beforeSetupInternal: function (effect) {
1546 s.makePositioned(effect.effects[0].element);
1547 },
1548 afterFinishInternal: function (effect) {
1549 s.hideElement(effect.effects[0].element);
1550 s.undoPositioned(effect.effects[0].element);
1551 s.setStyle(effect.effects[0].element, oldStyle);
1552 }
1553 }, options);
1554 var v = MochiKit.Visual;
1555 return new v.Parallel(
1556 [new v.Move(element, {x: 0, y: options.distance, sync: true}),
1557 new v.Opacity(element, {sync: true, to: 0.0})],
1558 options);
1559};
1560
1561/** @id MochiKit.Visual.shake */
1562MochiKit.Visual.shake = function (element, /* optional */ options) {
1563 /***
1564
1565 Move an element from left to right several times.
1566
1567 ***/
1568 var d = MochiKit.DOM;
1569 var v = MochiKit.Visual;
1570 var s = MochiKit.Style;
1571 element = d.getElement(element);
1572 var oldStyle = {
1573 top: s.getStyle(element, 'top'),
1574 left: s.getStyle(element, 'left')
1575 };
1576 options = MochiKit.Base.update({
1577 duration: 0.5,
1578 afterFinishInternal: function (effect) {
1579 s.undoPositioned(element);
1580 s.setStyle(element, oldStyle);
1581 }
1582 }, options);
1583 return new v.Sequence(
1584 [new v.Move(element, { sync: true, duration: 0.1 * options.duration,
1585 x: 20, y: 0 }),
1586 new v.Move(element, { sync: true, duration: 0.2 * options.duration,
1587 x: -40, y: 0 }),
1588 new v.Move(element, { sync: true, duration: 0.2 * options.duration,
1589 x: 40, y: 0 }),
1590 new v.Move(element, { sync: true, duration: 0.2 * options.duration,
1591 x: -40, y: 0 }),
1592 new v.Move(element, { sync: true, duration: 0.2 * options.duration,
1593 x: 40, y: 0 }),
1594 new v.Move(element, { sync: true, duration: 0.1 * options.duration,
1595 x: -20, y: 0 })],
1596 options);
1597};
1598
1599/** @id MochiKit.Visual.slideDown */
1600MochiKit.Visual.slideDown = function (element, /* optional */ options) {
1601 /***
1602
1603 Slide an element down.
1604 It needs to have the content of the element wrapped in a container
1605 element with fixed height.
1606
1607 ***/
1608 var d = MochiKit.DOM;
1609 var b = MochiKit.Base;
1610 var s = MochiKit.Style;
1611 element = d.getElement(element);
1612 if (!element.firstChild) {
1613 throw new Error("MochiKit.Visual.slideDown must be used on a element with a child");
1614 }
1615 d.removeEmptyTextNodes(element);
1616 var oldInnerBottom = s.getStyle(element.firstChild, 'bottom') || 0;
1617 var elementDimensions = s.getElementDimensions(element, true);
1618 var elemClip;
1619 options = b.update({
1620 scaleContent: false,
1621 scaleX: false,
1622 scaleFrom: 0,
1623 scaleMode: {originalHeight: elementDimensions.h,
1624 originalWidth: elementDimensions.w},
1625 restoreAfterFinish: true,
1626 afterSetupInternal: function (effect) {
1627 s.makePositioned(effect.element);
1628 s.makePositioned(effect.element.firstChild);
1629 if (/Opera/.test(navigator.userAgent)) {
1630 s.setStyle(effect.element, {top: ''});
1631 }
1632 elemClip = s.makeClipping(effect.element);
1633 s.setStyle(effect.element, {height: '0px'});
1634 s.showElement(effect.element);
1635 },
1636 afterUpdateInternal: function (effect) {
1637 var elementDimensions = s.getElementDimensions(effect.element, true);
1638 s.setStyle(effect.element.firstChild,
1639 {bottom: (effect.dims[0] - elementDimensions.h) + 'px'});
1640 },
1641 afterFinishInternal: function (effect) {
1642 s.undoClipping(effect.element, elemClip);
1643 // IE will crash if child is undoPositioned first
1644 if (/MSIE/.test(navigator.userAgent)) {
1645 s.undoPositioned(effect.element);
1646 s.undoPositioned(effect.element.firstChild);
1647 } else {
1648 s.undoPositioned(effect.element.firstChild);
1649 s.undoPositioned(effect.element);
1650 }
1651 s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom});
1652 }
1653 }, options);
1654
1655 return new MochiKit.Visual.Scale(element, 100, options);
1656};
1657
1658/** @id MochiKit.Visual.slideUp */
1659MochiKit.Visual.slideUp = function (element, /* optional */ options) {
1660 /***
1661
1662 Slide an element up.
1663 It needs to have the content of the element wrapped in a container
1664 element with fixed height.
1665
1666 ***/
1667 var d = MochiKit.DOM;
1668 var b = MochiKit.Base;
1669 var s = MochiKit.Style;
1670 element = d.getElement(element);
1671 if (!element.firstChild) {
1672 throw new Error("MochiKit.Visual.slideUp must be used on a element with a child");
1673 }
1674 d.removeEmptyTextNodes(element);
1675 var oldInnerBottom = s.getStyle(element.firstChild, 'bottom');
1676 var elementDimensions = s.getElementDimensions(element, true);
1677 var elemClip;
1678 options = b.update({
1679 scaleContent: false,
1680 scaleX: false,
1681 scaleMode: {originalHeight: elementDimensions.h,
1682 originalWidth: elementDimensions.w},
1683 scaleFrom: 100,
1684 restoreAfterFinish: true,
1685 beforeStartInternal: function (effect) {
1686 s.makePositioned(effect.element);
1687 s.makePositioned(effect.element.firstChild);
1688 if (/Opera/.test(navigator.userAgent)) {
1689 s.setStyle(effect.element, {top: ''});
1690 }
1691 elemClip = s.makeClipping(effect.element);
1692 s.showElement(effect.element);
1693 },
1694 afterUpdateInternal: function (effect) {
1695 var elementDimensions = s.getElementDimensions(effect.element, true);
1696 s.setStyle(effect.element.firstChild,
1697 {bottom: (effect.dims[0] - elementDimensions.h) + 'px'});
1698 },
1699 afterFinishInternal: function (effect) {
1700 s.hideElement(effect.element);
1701 s.undoClipping(effect.element, elemClip);
1702 s.undoPositioned(effect.element.firstChild);
1703 s.undoPositioned(effect.element);
1704 s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom});
1705 }
1706 }, options);
1707 return new MochiKit.Visual.Scale(element, 0, options);
1708};
1709
1710// Bug in opera makes the TD containing this element expand for a instance
1711// after finish
1712/** @id MochiKit.Visual.squish */
1713MochiKit.Visual.squish = function (element, /* optional */ options) {
1714 /***
1715
1716 Reduce an element and make it disappear.
1717
1718 ***/
1719 var d = MochiKit.DOM;
1720 var b = MochiKit.Base;
1721 var s = MochiKit.Style;
1722 var elementDimensions = s.getElementDimensions(element, true);
1723 var elemClip;
1724 options = b.update({
1725 restoreAfterFinish: true,
1726 scaleMode: {originalHeight: elementDimensions.h,
1727 originalWidth: elementDimensions.w},
1728 beforeSetupInternal: function (effect) {
1729 elemClip = s.makeClipping(effect.element);
1730 },
1731 afterFinishInternal: function (effect) {
1732 s.hideElement(effect.element);
1733 s.undoClipping(effect.element, elemClip);
1734 }
1735 }, options);
1736
1737 return new MochiKit.Visual.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, options);
1738};
1739
1740/** @id MochiKit.Visual.grow */
1741MochiKit.Visual.grow = function (element, /* optional */ options) {
1742 /***
1743
1744 Grow an element to its original size. Make it zero-sized before
1745 if necessary.
1746
1747 ***/
1748 var d = MochiKit.DOM;
1749 var v = MochiKit.Visual;
1750 var s = MochiKit.Style;
1751 element = d.getElement(element);
1752 options = MochiKit.Base.update({
1753 direction: 'center',
1754 moveTransition: v.Transitions.sinoidal,
1755 scaleTransition: v.Transitions.sinoidal,
1756 opacityTransition: v.Transitions.full,
1757 scaleContent: true,
1758 scaleFromCenter: false
1759 }, options);
1760 var oldStyle = {
1761 top: element.style.top,
1762 left: element.style.left,
1763 height: element.style.height,
1764 width: element.style.width,
1765 opacity: s.getStyle(element, 'opacity')
1766 };
1767 var dims = s.getElementDimensions(element, true);
1768 var initialMoveX, initialMoveY;
1769 var moveX, moveY;
1770
1771 switch (options.direction) {
1772 case 'top-left':
1773 initialMoveX = initialMoveY = moveX = moveY = 0;
1774 break;
1775 case 'top-right':
1776 initialMoveX = dims.w;
1777 initialMoveY = moveY = 0;
1778 moveX = -dims.w;
1779 break;
1780 case 'bottom-left':
1781 initialMoveX = moveX = 0;
1782 initialMoveY = dims.h;
1783 moveY = -dims.h;
1784 break;
1785 case 'bottom-right':
1786 initialMoveX = dims.w;
1787 initialMoveY = dims.h;
1788 moveX = -dims.w;
1789 moveY = -dims.h;
1790 break;
1791 case 'center':
1792 initialMoveX = dims.w / 2;
1793 initialMoveY = dims.h / 2;
1794 moveX = -dims.w / 2;
1795 moveY = -dims.h / 2;
1796 break;
1797 }
1798
1799 var optionsParallel = MochiKit.Base.update({
1800 beforeSetupInternal: function (effect) {
1801 s.setStyle(effect.effects[0].element, {height: '0px'});
1802 s.showElement(effect.effects[0].element);
1803 },
1804 afterFinishInternal: function (effect) {
1805 s.undoClipping(effect.effects[0].element);
1806 s.undoPositioned(effect.effects[0].element);
1807 s.setStyle(effect.effects[0].element, oldStyle);
1808 }
1809 }, options);
1810
1811 return new v.Move(element, {
1812 x: initialMoveX,
1813 y: initialMoveY,
1814 duration: 0.01,
1815 beforeSetupInternal: function (effect) {
1816 s.hideElement(effect.element);
1817 s.makeClipping(effect.element);
1818 s.makePositioned(effect.element);
1819 },
1820 afterFinishInternal: function (effect) {
1821 new v.Parallel(
1822 [new v.Opacity(effect.element, {
1823 sync: true, to: 1.0, from: 0.0,
1824 transition: options.opacityTransition
1825 }),
1826 new v.Move(effect.element, {
1827 x: moveX, y: moveY, sync: true,
1828 transition: options.moveTransition
1829 }),
1830 new v.Scale(effect.element, 100, {
1831 scaleMode: {originalHeight: dims.h,
1832 originalWidth: dims.w},
1833 sync: true,
1834 scaleFrom: /Opera/.test(navigator.userAgent) ? 1 : 0,
1835 transition: options.scaleTransition,
1836 scaleContent: options.scaleContent,
1837 scaleFromCenter: options.scaleFromCenter,
1838 restoreAfterFinish: true
1839 })
1840 ], optionsParallel
1841 );
1842 }
1843 });
1844};
1845
1846/** @id MochiKit.Visual.shrink */
1847MochiKit.Visual.shrink = function (element, /* optional */ options) {
1848 /***
1849
1850 Shrink an element and make it disappear.
1851
1852 ***/
1853 var d = MochiKit.DOM;
1854 var v = MochiKit.Visual;
1855 var s = MochiKit.Style;
1856 element = d.getElement(element);
1857 options = MochiKit.Base.update({
1858 direction: 'center',
1859 moveTransition: v.Transitions.sinoidal,
1860 scaleTransition: v.Transitions.sinoidal,
1861 opacityTransition: v.Transitions.none,
1862 scaleContent: true,
1863 scaleFromCenter: false
1864 }, options);
1865 var oldStyle = {
1866 top: element.style.top,
1867 left: element.style.left,
1868 height: element.style.height,
1869 width: element.style.width,
1870 opacity: s.getStyle(element, 'opacity')
1871 };
1872
1873 var dims = s.getElementDimensions(element, true);
1874 var moveX, moveY;
1875
1876 switch (options.direction) {
1877 case 'top-left':
1878 moveX = moveY = 0;
1879 break;
1880 case 'top-right':
1881 moveX = dims.w;
1882 moveY = 0;
1883 break;
1884 case 'bottom-left':
1885 moveX = 0;
1886 moveY = dims.h;
1887 break;
1888 case 'bottom-right':
1889 moveX = dims.w;
1890 moveY = dims.h;
1891 break;
1892 case 'center':
1893 moveX = dims.w / 2;
1894 moveY = dims.h / 2;
1895 break;
1896 }
1897 var elemClip;
1898
1899 var optionsParallel = MochiKit.Base.update({
1900 beforeStartInternal: function (effect) {
1901 s.makePositioned(effect.effects[0].element);
1902 elemClip = s.makeClipping(effect.effects[0].element);
1903 },
1904 afterFinishInternal: function (effect) {
1905 s.hideElement(effect.effects[0].element);
1906 s.undoClipping(effect.effects[0].element, elemClip);
1907 s.undoPositioned(effect.effects[0].element);
1908 s.setStyle(effect.effects[0].element, oldStyle);
1909 }
1910 }, options);
1911
1912 return new v.Parallel(
1913 [new v.Opacity(element, {
1914 sync: true, to: 0.0, from: 1.0,
1915 transition: options.opacityTransition
1916 }),
1917 new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
1918 scaleMode: {originalHeight: dims.h, originalWidth: dims.w},
1919 sync: true, transition: options.scaleTransition,
1920 scaleContent: options.scaleContent,
1921 scaleFromCenter: options.scaleFromCenter,
1922 restoreAfterFinish: true
1923 }),
1924 new v.Move(element, {
1925 x: moveX, y: moveY, sync: true, transition: options.moveTransition
1926 })
1927 ], optionsParallel
1928 );
1929};
1930
1931/** @id MochiKit.Visual.pulsate */
1932MochiKit.Visual.pulsate = function (element, /* optional */ options) {
1933 /***
1934
1935 Pulse an element between appear/fade.
1936
1937 ***/
1938 var d = MochiKit.DOM;
1939 var v = MochiKit.Visual;
1940 var b = MochiKit.Base;
1941 var oldOpacity = MochiKit.Style.getStyle(element, 'opacity');
1942 options = b.update({
1943 duration: 3.0,
1944 from: 0,
1945 afterFinishInternal: function (effect) {
1946 MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity});
1947 }
1948 }, options);
1949 var transition = options.transition || v.Transitions.sinoidal;
1950 options.transition = function (pos) {
1951 return transition(1 - v.Transitions.pulse(pos, options.pulses));
1952 };
1953 return new v.Opacity(element, options);
1954};
1955
1956/** @id MochiKit.Visual.fold */
1957MochiKit.Visual.fold = function (element, /* optional */ options) {
1958 /***
1959
1960 Fold an element, first vertically, then horizontally.
1961
1962 ***/
1963 var d = MochiKit.DOM;
1964 var v = MochiKit.Visual;
1965 var s = MochiKit.Style;
1966 element = d.getElement(element);
1967 var elementDimensions = s.getElementDimensions(element, true);
1968 var oldStyle = {
1969 top: element.style.top,
1970 left: element.style.left,
1971 width: element.style.width,
1972 height: element.style.height
1973 };
1974 var elemClip = s.makeClipping(element);
1975 options = MochiKit.Base.update({
1976 scaleContent: false,
1977 scaleX: false,
1978 scaleMode: {originalHeight: elementDimensions.h,
1979 originalWidth: elementDimensions.w},
1980 afterFinishInternal: function (effect) {
1981 new v.Scale(element, 1, {
1982 scaleContent: false,
1983 scaleY: false,
1984 scaleMode: {originalHeight: elementDimensions.h,
1985 originalWidth: elementDimensions.w},
1986 afterFinishInternal: function (effect) {
1987 s.hideElement(effect.element);
1988 s.undoClipping(effect.element, elemClip);
1989 s.setStyle(effect.element, oldStyle);
1990 }
1991 });
1992 }
1993 }, options);
1994 return new v.Scale(element, 5, options);
1995};
1996
1997
1998MochiKit.Base.nameFunctions(MochiKit.Visual);
1999MochiKit.Base._exportSymbols(this, MochiKit.Visual);