summaryrefslogtreecommitdiffstats
path: root/dom/tests/mochitest/ajax/mochikit
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-04-28 14:29:10 +0000
commit2aa4a82499d4becd2284cdb482213d541b8804dd (patch)
treeb80bf8bf13c3766139fbacc530efd0dd9d54394c /dom/tests/mochitest/ajax/mochikit
parentInitial commit. (diff)
downloadfirefox-upstream.tar.xz
firefox-upstream.zip
Adding upstream version 86.0.1.upstream/86.0.1upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'dom/tests/mochitest/ajax/mochikit')
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Async.js699
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Base.js1412
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Color.js902
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Controls.js1388
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/DOM.js1276
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/DateTime.js216
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/DragAndDrop.js824
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Format.js304
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Iter.js851
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Logging.js321
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/LoggingPane.js374
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/MochiKit.js154
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/MockDOM.js115
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Position.js258
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Selector.js431
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Signal.js899
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Sortable.js589
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Style.js445
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Test.js181
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/Visual.js1981
-rw-r--r--dom/tests/mochitest/ajax/mochikit/MochiKit/__package__.js18
-rw-r--r--dom/tests/mochitest/ajax/mochikit/manifest.json1
-rw-r--r--dom/tests/mochitest/ajax/mochikit/mochitest.ini26
-rw-r--r--dom/tests/mochitest/ajax/mochikit/test_Mochikit.html15
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/FakeJSAN.js40
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Async.html408
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Base.html34
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Color.html84
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DOM.html316
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DateTime.html39
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DragAndDrop.html54
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Format.html39
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Iter.html38
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-JSAN.html32
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Logging.html40
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-MochiKit.html18
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Selector.html274
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Signal.html43
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Style.html141
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Visual.html190
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/SimpleTest.js473
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/TestRunner.js177
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/test.css28
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/cli.js6
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/index.html25
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/standalone.js16
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/test_Base.js509
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/test_Color.js137
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/test_DateTime.js45
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/test_DragAndDrop.js30
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/test_Format.js80
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/test_Iter.js176
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/test_Logging.js75
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/test_MochiKit-Async.json1
-rw-r--r--dom/tests/mochitest/ajax/mochikit/tests/test_Signal.js441
55 files changed, 17689 insertions, 0 deletions
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Async.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Async.js
new file mode 100644
index 0000000000..55f4857b97
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Async.js
@@ -0,0 +1,699 @@
+/***
+
+MochiKit.Async 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide("MochiKit.Async");
+ dojo.require("MochiKit.Base");
+}
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.Async depends on MochiKit.Base!";
+}
+
+if (typeof(MochiKit.Async) == 'undefined') {
+ MochiKit.Async = {};
+}
+
+MochiKit.Async.NAME = "MochiKit.Async";
+MochiKit.Async.VERSION = "1.4";
+MochiKit.Async.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+MochiKit.Async.toString = function () {
+ return this.__repr__();
+};
+
+/** @id MochiKit.Async.Deferred */
+MochiKit.Async.Deferred = function (/* optional */ canceller) {
+ this.chain = [];
+ this.id = this._nextId();
+ this.fired = -1;
+ this.paused = 0;
+ this.results = [null, null];
+ this.canceller = canceller;
+ this.silentlyCancelled = false;
+ this.chained = false;
+};
+
+MochiKit.Async.Deferred.prototype = {
+ /** @id MochiKit.Async.Deferred.prototype.repr */
+ repr: function () {
+ var state;
+ if (this.fired == -1) {
+ state = 'unfired';
+ } else if (this.fired === 0) {
+ state = 'success';
+ } else {
+ state = 'error';
+ }
+ return 'Deferred(' + this.id + ', ' + state + ')';
+ },
+
+ toString: MochiKit.Base.forwardCall("repr"),
+
+ _nextId: MochiKit.Base.counter(),
+
+ /** @id MochiKit.Async.Deferred.prototype.cancel */
+ cancel: function () {
+ var self = MochiKit.Async;
+ if (this.fired == -1) {
+ if (this.canceller) {
+ this.canceller(this);
+ } else {
+ this.silentlyCancelled = true;
+ }
+ if (this.fired == -1) {
+ this.errback(new self.CancelledError(this));
+ }
+ } else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) {
+ this.results[0].cancel();
+ }
+ },
+
+ _resback: function (res) {
+ /***
+
+ The primitive that means either callback or errback
+
+ ***/
+ this.fired = ((res instanceof Error) ? 1 : 0);
+ this.results[this.fired] = res;
+ this._fire();
+ },
+
+ _check: function () {
+ if (this.fired != -1) {
+ if (!this.silentlyCancelled) {
+ throw new MochiKit.Async.AlreadyCalledError(this);
+ }
+ this.silentlyCancelled = false;
+ return;
+ }
+ },
+
+ /** @id MochiKit.Async.Deferred.prototype.callback */
+ callback: function (res) {
+ this._check();
+ if (res instanceof MochiKit.Async.Deferred) {
+ throw new Error("Deferred instances can only be chained if they are the result of a callback");
+ }
+ this._resback(res);
+ },
+
+ /** @id MochiKit.Async.Deferred.prototype.errback */
+ errback: function (res) {
+ this._check();
+ var self = MochiKit.Async;
+ if (res instanceof self.Deferred) {
+ throw new Error("Deferred instances can only be chained if they are the result of a callback");
+ }
+ if (!(res instanceof Error)) {
+ res = new self.GenericError(res);
+ }
+ this._resback(res);
+ },
+
+ /** @id MochiKit.Async.Deferred.prototype.addBoth */
+ addBoth: function (fn) {
+ if (arguments.length > 1) {
+ fn = MochiKit.Base.partial.apply(null, arguments);
+ }
+ return this.addCallbacks(fn, fn);
+ },
+
+ /** @id MochiKit.Async.Deferred.prototype.addCallback */
+ addCallback: function (fn) {
+ if (arguments.length > 1) {
+ fn = MochiKit.Base.partial.apply(null, arguments);
+ }
+ return this.addCallbacks(fn, null);
+ },
+
+ /** @id MochiKit.Async.Deferred.prototype.addErrback */
+ addErrback: function (fn) {
+ if (arguments.length > 1) {
+ fn = MochiKit.Base.partial.apply(null, arguments);
+ }
+ return this.addCallbacks(null, fn);
+ },
+
+ /** @id MochiKit.Async.Deferred.prototype.addCallbacks */
+ addCallbacks: function (cb, eb) {
+ if (this.chained) {
+ throw new Error("Chained Deferreds can not be re-used");
+ }
+ this.chain.push([cb, eb]);
+ if (this.fired >= 0) {
+ this._fire();
+ }
+ return this;
+ },
+
+ _fire: function () {
+ /***
+
+ Used internally to exhaust the callback sequence when a result
+ is available.
+
+ ***/
+ var chain = this.chain;
+ var fired = this.fired;
+ var res = this.results[fired];
+ var self = this;
+ var cb = null;
+ while (chain.length > 0 && this.paused === 0) {
+ // Array
+ var pair = chain.shift();
+ var f = pair[fired];
+ if (f === null) {
+ continue;
+ }
+ try {
+ res = f(res);
+ fired = ((res instanceof Error) ? 1 : 0);
+ if (res instanceof MochiKit.Async.Deferred) {
+ cb = function (res) {
+ self._resback(res);
+ self.paused--;
+ if ((self.paused === 0) && (self.fired >= 0)) {
+ self._fire();
+ }
+ };
+ this.paused++;
+ }
+ } catch (err) {
+ fired = 1;
+ if (!(err instanceof Error)) {
+ err = new MochiKit.Async.GenericError(err);
+ }
+ res = err;
+ }
+ }
+ this.fired = fired;
+ this.results[fired] = res;
+ if (cb && this.paused) {
+ // this is for "tail recursion" in case the dependent deferred
+ // is already fired
+ res.addBoth(cb);
+ res.chained = true;
+ }
+ }
+};
+
+MochiKit.Base.update(MochiKit.Async, {
+ /** @id MochiKit.Async.evalJSONRequest */
+ evalJSONRequest: function (req) {
+ return MochiKit.Base.evalJSON(req.responseText);
+ },
+
+ /** @id MochiKit.Async.succeed */
+ succeed: function (/* optional */result) {
+ var d = new MochiKit.Async.Deferred();
+ d.callback.apply(d, arguments);
+ return d;
+ },
+
+ /** @id MochiKit.Async.fail */
+ fail: function (/* optional */result) {
+ var d = new MochiKit.Async.Deferred();
+ d.errback.apply(d, arguments);
+ return d;
+ },
+
+ /** @id MochiKit.Async.getXMLHttpRequest */
+ getXMLHttpRequest: function () {
+ var self = arguments.callee;
+ if (!self.XMLHttpRequest) {
+ var tryThese = [
+ function () { return new XMLHttpRequest(); },
+ function () { return new ActiveXObject('Msxml2.XMLHTTP'); },
+ function () { return new ActiveXObject('Microsoft.XMLHTTP'); },
+ function () { return new ActiveXObject('Msxml2.XMLHTTP.4.0'); },
+ function () {
+ throw new MochiKit.Async.BrowserComplianceError("Browser does not support XMLHttpRequest");
+ }
+ ];
+ for (var i = 0; i < tryThese.length; i++) {
+ var func = tryThese[i];
+ try {
+ self.XMLHttpRequest = func;
+ return func();
+ } catch (e) {
+ // pass
+ }
+ }
+ }
+ return self.XMLHttpRequest();
+ },
+
+ _xhr_onreadystatechange: function (d) {
+ // MochiKit.Logging.logDebug('this.readyState', this.readyState);
+ var m = MochiKit.Base;
+ if (this.readyState == 4) {
+ // IE SUCKS
+ try {
+ this.onreadystatechange = null;
+ } catch (e) {
+ try {
+ this.onreadystatechange = m.noop;
+ } catch (e) {
+ }
+ }
+ var status = null;
+ try {
+ status = this.status;
+ if (!status && m.isNotEmpty(this.responseText)) {
+ // 0 or undefined seems to mean cached or local
+ status = 304;
+ }
+ } catch (e) {
+ // pass
+ // MochiKit.Logging.logDebug('error getting status?', repr(items(e)));
+ }
+ // 200 is OK, 201 is CREATED, 204 is NO CONTENT
+ // 304 is NOT MODIFIED, 1223 is apparently a bug in IE
+ if (status == 200 || status == 201 || status == 204 ||
+ status == 304 || status == 1223) {
+ d.callback(this);
+ } else {
+ var err = new MochiKit.Async.XMLHttpRequestError(this, "Request failed");
+ if (err.number) {
+ // XXX: This seems to happen on page change
+ d.errback(err);
+ } else {
+ // XXX: this seems to happen when the server is unreachable
+ d.errback(err);
+ }
+ }
+ }
+ },
+
+ _xhr_canceller: function (req) {
+ // IE SUCKS
+ try {
+ req.onreadystatechange = null;
+ } catch (e) {
+ try {
+ req.onreadystatechange = MochiKit.Base.noop;
+ } catch (e) {
+ }
+ }
+ req.abort();
+ },
+
+
+ /** @id MochiKit.Async.sendXMLHttpRequest */
+ sendXMLHttpRequest: function (req, /* optional */ sendContent) {
+ if (typeof(sendContent) == "undefined" || sendContent === null) {
+ sendContent = "";
+ }
+
+ var m = MochiKit.Base;
+ var self = MochiKit.Async;
+ var d = new self.Deferred(m.partial(self._xhr_canceller, req));
+
+ try {
+ req.onreadystatechange = m.bind(self._xhr_onreadystatechange,
+ req, d);
+ req.send(sendContent);
+ } catch (e) {
+ try {
+ req.onreadystatechange = null;
+ } catch (ignore) {
+ // pass
+ }
+ d.errback(e);
+ }
+
+ return d;
+
+ },
+
+ /** @id MochiKit.Async.doXHR */
+ doXHR: function (url, opts) {
+ /*
+ Work around a Firefox bug by dealing with XHR during
+ the next event loop iteration. Maybe it's this one:
+ https://bugzilla.mozilla.org/show_bug.cgi?id=249843
+ */
+ var self = MochiKit.Async;
+ return self.callLater(0, self._doXHR, url, opts);
+ },
+
+ _doXHR: function (url, opts) {
+ var m = MochiKit.Base;
+ opts = m.update({
+ method: 'GET',
+ sendContent: ''
+ /*
+ queryString: undefined,
+ username: undefined,
+ password: undefined,
+ headers: undefined,
+ mimeType: undefined
+ */
+ }, opts);
+ var self = MochiKit.Async;
+ var req = self.getXMLHttpRequest();
+ if (opts.queryString) {
+ var qs = m.queryString(opts.queryString);
+ if (qs) {
+ url += "?" + qs;
+ }
+ }
+ // Safari will send undefined:undefined, so we have to check.
+ // We can't use apply, since the function is native.
+ if ('username' in opts) {
+ req.open(opts.method, url, true, opts.username, opts.password);
+ } else {
+ req.open(opts.method, url, true);
+ }
+ if (req.overrideMimeType && opts.mimeType) {
+ req.overrideMimeType(opts.mimeType);
+ }
+ if (opts.headers) {
+ var headers = opts.headers;
+ if (!m.isArrayLike(headers)) {
+ headers = m.items(headers);
+ }
+ for (var i = 0; i < headers.length; i++) {
+ var header = headers[i];
+ var name = header[0];
+ var value = header[1];
+ req.setRequestHeader(name, value);
+ }
+ }
+ return self.sendXMLHttpRequest(req, opts.sendContent);
+ },
+
+ _buildURL: function (url/*, ...*/) {
+ if (arguments.length > 1) {
+ var m = MochiKit.Base;
+ var qs = m.queryString.apply(null, m.extend(null, arguments, 1));
+ if (qs) {
+ return url + "?" + qs;
+ }
+ }
+ return url;
+ },
+
+ /** @id MochiKit.Async.doSimpleXMLHttpRequest */
+ doSimpleXMLHttpRequest: function (url/*, ...*/) {
+ var self = MochiKit.Async;
+ url = self._buildURL.apply(self, arguments);
+ return self.doXHR(url);
+ },
+
+ /** @id MochiKit.Async.loadJSONDoc */
+ loadJSONDoc: function (url/*, ...*/) {
+ var self = MochiKit.Async;
+ url = self._buildURL.apply(self, arguments);
+ var d = self.doXHR(url, {
+ 'mimeType': 'text/plain',
+ 'headers': [['Accept', 'application/json']]
+ });
+ d = d.addCallback(self.evalJSONRequest);
+ return d;
+ },
+
+ /** @id MochiKit.Async.wait */
+ wait: function (seconds, /* optional */value) {
+ var d = new MochiKit.Async.Deferred();
+ var m = MochiKit.Base;
+ if (typeof(value) != 'undefined') {
+ d.addCallback(function () { return value; });
+ }
+ var timeout = setTimeout(
+ m.bind("callback", d),
+ Math.floor(seconds * 1000));
+ d.canceller = function () {
+ try {
+ clearTimeout(timeout);
+ } catch (e) {
+ // pass
+ }
+ };
+ return d;
+ },
+
+ /** @id MochiKit.Async.callLater */
+ callLater: function (seconds, func) {
+ var m = MochiKit.Base;
+ var pfunc = m.partial.apply(m, m.extend(null, arguments, 1));
+ return MochiKit.Async.wait(seconds).addCallback(
+ function (res) { return pfunc(); }
+ );
+ }
+});
+
+
+/** @id MochiKit.Async.DeferredLock */
+MochiKit.Async.DeferredLock = function () {
+ this.waiting = [];
+ this.locked = false;
+ this.id = this._nextId();
+};
+
+MochiKit.Async.DeferredLock.prototype = {
+ __class__: MochiKit.Async.DeferredLock,
+ /** @id MochiKit.Async.DeferredLock.prototype.acquire */
+ acquire: function () {
+ var d = new MochiKit.Async.Deferred();
+ if (this.locked) {
+ this.waiting.push(d);
+ } else {
+ this.locked = true;
+ d.callback(this);
+ }
+ return d;
+ },
+ /** @id MochiKit.Async.DeferredLock.prototype.release */
+ release: function () {
+ if (!this.locked) {
+ throw TypeError("Tried to release an unlocked DeferredLock");
+ }
+ this.locked = false;
+ if (this.waiting.length > 0) {
+ this.locked = true;
+ this.waiting.shift().callback(this);
+ }
+ },
+ _nextId: MochiKit.Base.counter(),
+ repr: function () {
+ var state;
+ if (this.locked) {
+ state = 'locked, ' + this.waiting.length + ' waiting';
+ } else {
+ state = 'unlocked';
+ }
+ return 'DeferredLock(' + this.id + ', ' + state + ')';
+ },
+ toString: MochiKit.Base.forwardCall("repr")
+
+};
+
+/** @id MochiKit.Async.DeferredList */
+MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, fireOnOneErrback, consumeErrors, canceller) {
+
+ // call parent constructor
+ MochiKit.Async.Deferred.apply(this, [canceller]);
+
+ this.list = list;
+ var resultList = [];
+ this.resultList = resultList;
+
+ this.finishedCount = 0;
+ this.fireOnOneCallback = fireOnOneCallback;
+ this.fireOnOneErrback = fireOnOneErrback;
+ this.consumeErrors = consumeErrors;
+
+ var cb = MochiKit.Base.bind(this._cbDeferred, this);
+ for (var i = 0; i < list.length; i++) {
+ var d = list[i];
+ resultList.push(undefined);
+ d.addCallback(cb, i, true);
+ d.addErrback(cb, i, false);
+ }
+
+ if (list.length === 0 && !fireOnOneCallback) {
+ this.callback(this.resultList);
+ }
+
+};
+
+MochiKit.Async.DeferredList.prototype = new MochiKit.Async.Deferred();
+
+MochiKit.Async.DeferredList.prototype._cbDeferred = function (index, succeeded, result) {
+ this.resultList[index] = [succeeded, result];
+ this.finishedCount += 1;
+ if (this.fired == -1) {
+ if (succeeded && this.fireOnOneCallback) {
+ this.callback([index, result]);
+ } else if (!succeeded && this.fireOnOneErrback) {
+ this.errback(result);
+ } else if (this.finishedCount == this.list.length) {
+ this.callback(this.resultList);
+ }
+ }
+ if (!succeeded && this.consumeErrors) {
+ result = null;
+ }
+ return result;
+};
+
+/** @id MochiKit.Async.gatherResults */
+MochiKit.Async.gatherResults = function (deferredList) {
+ var d = new MochiKit.Async.DeferredList(deferredList, false, true, false);
+ d.addCallback(function (results) {
+ var ret = [];
+ for (var i = 0; i < results.length; i++) {
+ ret.push(results[i][1]);
+ }
+ return ret;
+ });
+ return d;
+};
+
+/** @id MochiKit.Async.maybeDeferred */
+MochiKit.Async.maybeDeferred = function (func) {
+ var self = MochiKit.Async;
+ var result;
+ try {
+ var r = func.apply(null, MochiKit.Base.extend([], arguments, 1));
+ if (r instanceof self.Deferred) {
+ result = r;
+ } else if (r instanceof Error) {
+ result = self.fail(r);
+ } else {
+ result = self.succeed(r);
+ }
+ } catch (e) {
+ result = self.fail(e);
+ }
+ return result;
+};
+
+
+MochiKit.Async.EXPORT = [
+ "AlreadyCalledError",
+ "CancelledError",
+ "BrowserComplianceError",
+ "GenericError",
+ "XMLHttpRequestError",
+ "Deferred",
+ "succeed",
+ "fail",
+ "getXMLHttpRequest",
+ "doSimpleXMLHttpRequest",
+ "loadJSONDoc",
+ "wait",
+ "callLater",
+ "sendXMLHttpRequest",
+ "DeferredLock",
+ "DeferredList",
+ "gatherResults",
+ "maybeDeferred",
+ "doXHR"
+];
+
+MochiKit.Async.EXPORT_OK = [
+ "evalJSONRequest"
+];
+
+MochiKit.Async.__new__ = function () {
+ var m = MochiKit.Base;
+ var ne = m.partial(m._newNamedError, this);
+
+ ne("AlreadyCalledError",
+ /** @id MochiKit.Async.AlreadyCalledError */
+ function (deferred) {
+ /***
+
+ Raised by the Deferred if callback or errback happens
+ after it was already fired.
+
+ ***/
+ this.deferred = deferred;
+ }
+ );
+
+ ne("CancelledError",
+ /** @id MochiKit.Async.CancelledError */
+ function (deferred) {
+ /***
+
+ Raised by the Deferred cancellation mechanism.
+
+ ***/
+ this.deferred = deferred;
+ }
+ );
+
+ ne("BrowserComplianceError",
+ /** @id MochiKit.Async.BrowserComplianceError */
+ function (msg) {
+ /***
+
+ Raised when the JavaScript runtime is not capable of performing
+ the given function. Technically, this should really never be
+ raised because a non-conforming JavaScript runtime probably
+ isn't going to support exceptions in the first place.
+
+ ***/
+ this.message = msg;
+ }
+ );
+
+ ne("GenericError",
+ /** @id MochiKit.Async.GenericError */
+ function (msg) {
+ this.message = msg;
+ }
+ );
+
+ ne("XMLHttpRequestError",
+ /** @id MochiKit.Async.XMLHttpRequestError */
+ function (req, msg) {
+ /***
+
+ Raised when an XMLHttpRequest does not complete for any reason.
+
+ ***/
+ this.req = req;
+ this.message = msg;
+ try {
+ // Strange but true that this can raise in some cases.
+ this.number = req.status;
+ } catch (e) {
+ // pass
+ }
+ }
+ );
+
+
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ m.nameFunctions(this);
+
+};
+
+MochiKit.Async.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.Async);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Base.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Base.js
new file mode 100644
index 0000000000..ec1350e60d
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Base.js
@@ -0,0 +1,1412 @@
+/***
+
+MochiKit.Base 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide("MochiKit.Base");
+}
+if (typeof(MochiKit) == 'undefined') {
+ MochiKit = {};
+}
+if (typeof(MochiKit.Base) == 'undefined') {
+ MochiKit.Base = {};
+}
+if (typeof(MochiKit.__export__) == "undefined") {
+ MochiKit.__export__ = (MochiKit.__compat__ ||
+ (typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
+ );
+}
+
+MochiKit.Base.VERSION = "1.4";
+MochiKit.Base.NAME = "MochiKit.Base";
+/** @id MochiKit.Base.update */
+MochiKit.Base.update = function (self, obj/*, ... */) {
+ if (self === null) {
+ self = {};
+ }
+ for (var i = 1; i < arguments.length; i++) {
+ var o = arguments[i];
+ if (typeof(o) != 'undefined' && o !== null) {
+ for (var k in o) {
+ self[k] = o[k];
+ }
+ }
+ }
+ return self;
+};
+
+MochiKit.Base.update(MochiKit.Base, {
+ __repr__: function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+ },
+
+ toString: function () {
+ return this.__repr__();
+ },
+
+ /** @id MochiKit.Base.camelize */
+ camelize: function (selector) {
+ /* from dojo.style.toCamelCase */
+ var arr = selector.split('-');
+ var cc = arr[0];
+ for (var i = 1; i < arr.length; i++) {
+ cc += arr[i].charAt(0).toUpperCase() + arr[i].substring(1);
+ }
+ return cc;
+ },
+
+ /** @id MochiKit.Base.counter */
+ counter: function (n/* = 1 */) {
+ if (arguments.length === 0) {
+ n = 1;
+ }
+ return function () {
+ return n++;
+ };
+ },
+
+ /** @id MochiKit.Base.clone */
+ clone: function (obj) {
+ var me = arguments.callee;
+ if (arguments.length == 1) {
+ me.prototype = obj;
+ return new me();
+ }
+ },
+
+ _flattenArray: function (res, lst) {
+ for (var i = 0; i < lst.length; i++) {
+ var o = lst[i];
+ if (o instanceof Array) {
+ arguments.callee(res, o);
+ } else {
+ res.push(o);
+ }
+ }
+ return res;
+ },
+
+ /** @id MochiKit.Base.flattenArray */
+ flattenArray: function (lst) {
+ return MochiKit.Base._flattenArray([], lst);
+ },
+
+ /** @id MochiKit.Base.flattenArguments */
+ flattenArguments: function (lst/* ...*/) {
+ var res = [];
+ var m = MochiKit.Base;
+ var args = m.extend(null, arguments);
+ while (args.length) {
+ var o = args.shift();
+ if (o && typeof(o) == "object" && typeof(o.length) == "number") {
+ for (var i = o.length - 1; i >= 0; i--) {
+ args.unshift(o[i]);
+ }
+ } else {
+ res.push(o);
+ }
+ }
+ return res;
+ },
+
+ /** @id MochiKit.Base.extend */
+ extend: function (self, obj, /* optional */skip) {
+ // Extend an array with an array-like object starting
+ // from the skip index
+ if (!skip) {
+ skip = 0;
+ }
+ if (obj) {
+ // allow iterable fall-through, but skip the full isArrayLike
+ // check for speed, this is called often.
+ var l = obj.length;
+ if (typeof(l) != 'number' /* !isArrayLike(obj) */) {
+ if (typeof(MochiKit.Iter) != "undefined") {
+ obj = MochiKit.Iter.list(obj);
+ l = obj.length;
+ } else {
+ throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+ }
+ }
+ if (!self) {
+ self = [];
+ }
+ for (var i = skip; i < l; i++) {
+ self.push(obj[i]);
+ }
+ }
+ // This mutates, but it's convenient to return because
+ // it's often used like a constructor when turning some
+ // ghetto array-like to a real array
+ return self;
+ },
+
+
+ /** @id MochiKit.Base.updatetree */
+ updatetree: function (self, obj/*, ...*/) {
+ if (self === null) {
+ self = {};
+ }
+ for (var i = 1; i < arguments.length; i++) {
+ var o = arguments[i];
+ if (typeof(o) != 'undefined' && o !== null) {
+ for (var k in o) {
+ var v = o[k];
+ if (typeof(self[k]) == 'object' && typeof(v) == 'object') {
+ arguments.callee(self[k], v);
+ } else {
+ self[k] = v;
+ }
+ }
+ }
+ }
+ return self;
+ },
+
+ /** @id MochiKit.Base.setdefault */
+ setdefault: function (self, obj/*, ...*/) {
+ if (self === null) {
+ self = {};
+ }
+ for (var i = 1; i < arguments.length; i++) {
+ var o = arguments[i];
+ for (var k in o) {
+ if (!(k in self)) {
+ self[k] = o[k];
+ }
+ }
+ }
+ return self;
+ },
+
+ /** @id MochiKit.Base.keys */
+ keys: function (obj) {
+ var rval = [];
+ for (var prop in obj) {
+ rval.push(prop);
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Base.values */
+ values: function (obj) {
+ var rval = [];
+ for (var prop in obj) {
+ rval.push(obj[prop]);
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Base.items */
+ items: function (obj) {
+ var rval = [];
+ var e;
+ for (var prop in obj) {
+ var v;
+ try {
+ v = obj[prop];
+ } catch (e) {
+ continue;
+ }
+ rval.push([prop, v]);
+ }
+ return rval;
+ },
+
+
+ _newNamedError: function (module, name, func) {
+ func.prototype = new MochiKit.Base.NamedError(module.NAME + "." + name);
+ module[name] = func;
+ },
+
+
+ /** @id MochiKit.Base.operator */
+ operator: {
+ // unary logic operators
+ /** @id MochiKit.Base.truth */
+ truth: function (a) { return !!a; },
+ /** @id MochiKit.Base.lognot */
+ lognot: function (a) { return !a; },
+ /** @id MochiKit.Base.identity */
+ identity: function (a) { return a; },
+
+ // bitwise unary operators
+ /** @id MochiKit.Base.not */
+ not: function (a) { return ~a; },
+ /** @id MochiKit.Base.neg */
+ neg: function (a) { return -a; },
+
+ // binary operators
+ /** @id MochiKit.Base.add */
+ add: function (a, b) { return a + b; },
+ /** @id MochiKit.Base.sub */
+ sub: function (a, b) { return a - b; },
+ /** @id MochiKit.Base.div */
+ div: function (a, b) { return a / b; },
+ /** @id MochiKit.Base.mod */
+ mod: function (a, b) { return a % b; },
+ /** @id MochiKit.Base.mul */
+ mul: function (a, b) { return a * b; },
+
+ // bitwise binary operators
+ /** @id MochiKit.Base.and */
+ and: function (a, b) { return a & b; },
+ /** @id MochiKit.Base.or */
+ or: function (a, b) { return a | b; },
+ /** @id MochiKit.Base.xor */
+ xor: function (a, b) { return a ^ b; },
+ /** @id MochiKit.Base.lshift */
+ lshift: function (a, b) { return a << b; },
+ /** @id MochiKit.Base.rshift */
+ rshift: function (a, b) { return a >> b; },
+ /** @id MochiKit.Base.zrshift */
+ zrshift: function (a, b) { return a >>> b; },
+
+ // near-worthless built-in comparators
+ /** @id MochiKit.Base.eq */
+ eq: function (a, b) { return a == b; },
+ /** @id MochiKit.Base.ne */
+ ne: function (a, b) { return a != b; },
+ /** @id MochiKit.Base.gt */
+ gt: function (a, b) { return a > b; },
+ /** @id MochiKit.Base.ge */
+ ge: function (a, b) { return a >= b; },
+ /** @id MochiKit.Base.lt */
+ lt: function (a, b) { return a < b; },
+ /** @id MochiKit.Base.le */
+ le: function (a, b) { return a <= b; },
+
+ // strict built-in comparators
+ seq: function (a, b) { return a === b; },
+ sne: function (a, b) { return a !== b; },
+
+ // compare comparators
+ /** @id MochiKit.Base.ceq */
+ ceq: function (a, b) { return MochiKit.Base.compare(a, b) === 0; },
+ /** @id MochiKit.Base.cne */
+ cne: function (a, b) { return MochiKit.Base.compare(a, b) !== 0; },
+ /** @id MochiKit.Base.cgt */
+ cgt: function (a, b) { return MochiKit.Base.compare(a, b) == 1; },
+ /** @id MochiKit.Base.cge */
+ cge: function (a, b) { return MochiKit.Base.compare(a, b) != -1; },
+ /** @id MochiKit.Base.clt */
+ clt: function (a, b) { return MochiKit.Base.compare(a, b) == -1; },
+ /** @id MochiKit.Base.cle */
+ cle: function (a, b) { return MochiKit.Base.compare(a, b) != 1; },
+
+ // binary logical operators
+ /** @id MochiKit.Base.logand */
+ logand: function (a, b) { return a && b; },
+ /** @id MochiKit.Base.logor */
+ logor: function (a, b) { return a || b; },
+ /** @id MochiKit.Base.contains */
+ contains: function (a, b) { return b in a; }
+ },
+
+ /** @id MochiKit.Base.forwardCall */
+ forwardCall: function (func) {
+ return function () {
+ return this[func].apply(this, arguments);
+ };
+ },
+
+ /** @id MochiKit.Base.itemgetter */
+ itemgetter: function (func) {
+ return function (arg) {
+ return arg[func];
+ };
+ },
+
+ /** @id MochiKit.Base.typeMatcher */
+ typeMatcher: function (/* typ */) {
+ var types = {};
+ for (var i = 0; i < arguments.length; i++) {
+ var typ = arguments[i];
+ types[typ] = typ;
+ }
+ return function () {
+ for (var i = 0; i < arguments.length; i++) {
+ if (!(typeof(arguments[i]) in types)) {
+ return false;
+ }
+ }
+ return true;
+ };
+ },
+
+ /** @id MochiKit.Base.isNull */
+ isNull: function (/* ... */) {
+ for (var i = 0; i < arguments.length; i++) {
+ if (arguments[i] !== null) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /** @id MochiKit.Base.isUndefinedOrNull */
+ isUndefinedOrNull: function (/* ... */) {
+ for (var i = 0; i < arguments.length; i++) {
+ var o = arguments[i];
+ if (!(typeof(o) == 'undefined' || o === null)) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /** @id MochiKit.Base.isEmpty */
+ isEmpty: function (obj) {
+ return !MochiKit.Base.isNotEmpty.apply(this, arguments);
+ },
+
+ /** @id MochiKit.Base.isNotEmpty */
+ isNotEmpty: function (obj) {
+ for (var i = 0; i < arguments.length; i++) {
+ var o = arguments[i];
+ if (!(o && o.length)) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /** @id MochiKit.Base.isArrayLike */
+ isArrayLike: function () {
+ for (var i = 0; i < arguments.length; i++) {
+ var o = arguments[i];
+ var typ = typeof(o);
+ if (
+ (typ != 'object' && !(typ == 'function' && typeof(o.item) == 'function')) ||
+ o === null ||
+ typeof(o.length) != 'number' ||
+ o.nodeType === 3
+ ) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /** @id MochiKit.Base.isDateLike */
+ isDateLike: function () {
+ for (var i = 0; i < arguments.length; i++) {
+ var o = arguments[i];
+ if (typeof(o) != "object" || o === null
+ || typeof(o.getTime) != 'function') {
+ return false;
+ }
+ }
+ return true;
+ },
+
+
+ /** @id MochiKit.Base.xmap */
+ xmap: function (fn/*, obj... */) {
+ if (fn === null) {
+ return MochiKit.Base.extend(null, arguments, 1);
+ }
+ var rval = [];
+ for (var i = 1; i < arguments.length; i++) {
+ rval.push(fn(arguments[i]));
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Base.map */
+ map: function (fn, lst/*, lst... */) {
+ var m = MochiKit.Base;
+ var itr = MochiKit.Iter;
+ var isArrayLike = m.isArrayLike;
+ if (arguments.length <= 2) {
+ // allow an iterable to be passed
+ if (!isArrayLike(lst)) {
+ if (itr) {
+ // fast path for map(null, iterable)
+ lst = itr.list(lst);
+ if (fn === null) {
+ return lst;
+ }
+ } else {
+ throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+ }
+ }
+ // fast path for map(null, lst)
+ if (fn === null) {
+ return m.extend(null, lst);
+ }
+ // disabled fast path for map(fn, lst)
+ /*
+ if (false && typeof(Array.prototype.map) == 'function') {
+ // Mozilla fast-path
+ return Array.prototype.map.call(lst, fn);
+ }
+ */
+ var rval = [];
+ for (var i = 0; i < lst.length; i++) {
+ rval.push(fn(lst[i]));
+ }
+ return rval;
+ } else {
+ // default for map(null, ...) is zip(...)
+ if (fn === null) {
+ fn = Array;
+ }
+ var length = null;
+ for (i = 1; i < arguments.length; i++) {
+ // allow iterables to be passed
+ if (!isArrayLike(arguments[i])) {
+ if (itr) {
+ return itr.list(itr.imap.apply(null, arguments));
+ } else {
+ throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+ }
+ }
+ // find the minimum length
+ var l = arguments[i].length;
+ if (length === null || length > l) {
+ length = l;
+ }
+ }
+ rval = [];
+ for (i = 0; i < length; i++) {
+ var args = [];
+ for (var j = 1; j < arguments.length; j++) {
+ args.push(arguments[j][i]);
+ }
+ rval.push(fn.apply(this, args));
+ }
+ return rval;
+ }
+ },
+
+ /** @id MochiKit.Base.xfilter */
+ xfilter: function (fn/*, obj... */) {
+ var rval = [];
+ if (fn === null) {
+ fn = MochiKit.Base.operator.truth;
+ }
+ for (var i = 1; i < arguments.length; i++) {
+ var o = arguments[i];
+ if (fn(o)) {
+ rval.push(o);
+ }
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Base.filter */
+ filter: function (fn, lst, self) {
+ var rval = [];
+ // allow an iterable to be passed
+ var m = MochiKit.Base;
+ if (!m.isArrayLike(lst)) {
+ if (MochiKit.Iter) {
+ lst = MochiKit.Iter.list(lst);
+ } else {
+ throw new TypeError("Argument not an array-like and MochiKit.Iter not present");
+ }
+ }
+ if (fn === null) {
+ fn = m.operator.truth;
+ }
+ if (typeof(Array.prototype.filter) == 'function') {
+ // Mozilla fast-path
+ return Array.prototype.filter.call(lst, fn, self);
+ } else if (typeof(self) == 'undefined' || self === null) {
+ for (var i = 0; i < lst.length; i++) {
+ var o = lst[i];
+ if (fn(o)) {
+ rval.push(o);
+ }
+ }
+ } else {
+ for (i = 0; i < lst.length; i++) {
+ o = lst[i];
+ if (fn.call(self, o)) {
+ rval.push(o);
+ }
+ }
+ }
+ return rval;
+ },
+
+
+ _wrapDumbFunction: function (func) {
+ return function () {
+ // fast path!
+ switch (arguments.length) {
+ case 0: return func();
+ case 1: return func(arguments[0]);
+ case 2: return func(arguments[0], arguments[1]);
+ case 3: return func(arguments[0], arguments[1], arguments[2]);
+ }
+ var args = [];
+ for (var i = 0; i < arguments.length; i++) {
+ args.push("arguments[" + i + "]");
+ }
+ return eval("(func(" + args.join(",") + "))");
+ };
+ },
+
+ /** @id MochiKit.Base.methodcaller */
+ methodcaller: function (func/*, args... */) {
+ var args = MochiKit.Base.extend(null, arguments, 1);
+ if (typeof(func) == "function") {
+ return function (obj) {
+ return func.apply(obj, args);
+ };
+ } else {
+ return function (obj) {
+ return obj[func].apply(obj, args);
+ };
+ }
+ },
+
+ /** @id MochiKit.Base.method */
+ method: function (self, func) {
+ var m = MochiKit.Base;
+ return m.bind.apply(this, m.extend([func, self], arguments, 2));
+ },
+
+ /** @id MochiKit.Base.compose */
+ compose: function (f1, f2/*, f3, ... fN */) {
+ var fnlist = [];
+ var m = MochiKit.Base;
+ if (arguments.length === 0) {
+ throw new TypeError("compose() requires at least one argument");
+ }
+ for (var i = 0; i < arguments.length; i++) {
+ var fn = arguments[i];
+ if (typeof(fn) != "function") {
+ throw new TypeError(m.repr(fn) + " is not a function");
+ }
+ fnlist.push(fn);
+ }
+ return function () {
+ var args = arguments;
+ for (var i = fnlist.length - 1; i >= 0; i--) {
+ args = [fnlist[i].apply(this, args)];
+ }
+ return args[0];
+ };
+ },
+
+ /** @id MochiKit.Base.bind */
+ bind: function (func, self/* args... */) {
+ if (typeof(func) == "string") {
+ func = self[func];
+ }
+ var im_func = func.im_func;
+ var im_preargs = func.im_preargs;
+ var im_self = func.im_self;
+ var m = MochiKit.Base;
+ if (typeof(func) == "function" && typeof(func.apply) == "undefined") {
+ // this is for cases where JavaScript sucks ass and gives you a
+ // really dumb built-in function like alert() that doesn't have
+ // an apply
+ func = m._wrapDumbFunction(func);
+ }
+ if (typeof(im_func) != 'function') {
+ im_func = func;
+ }
+ if (typeof(self) != 'undefined') {
+ im_self = self;
+ }
+ if (typeof(im_preargs) == 'undefined') {
+ im_preargs = [];
+ } else {
+ im_preargs = im_preargs.slice();
+ }
+ m.extend(im_preargs, arguments, 2);
+ var newfunc = function () {
+ var args = arguments;
+ var me = arguments.callee;
+ if (me.im_preargs.length > 0) {
+ args = m.concat(me.im_preargs, args);
+ }
+ var self = me.im_self;
+ if (!self) {
+ self = this;
+ }
+ return me.im_func.apply(self, args);
+ };
+ newfunc.im_self = im_self;
+ newfunc.im_func = im_func;
+ newfunc.im_preargs = im_preargs;
+ return newfunc;
+ },
+
+ /** @id MochiKit.Base.bindMethods */
+ bindMethods: function (self) {
+ var bind = MochiKit.Base.bind;
+ for (var k in self) {
+ var func = self[k];
+ if (typeof(func) == 'function') {
+ self[k] = bind(func, self);
+ }
+ }
+ },
+
+ /** @id MochiKit.Base.registerComparator */
+ registerComparator: function (name, check, comparator, /* optional */ override) {
+ MochiKit.Base.comparatorRegistry.register(name, check, comparator, override);
+ },
+
+ _primitives: {'boolean': true, 'string': true, 'number': true},
+
+ /** @id MochiKit.Base.compare */
+ compare: function (a, b) {
+ if (a == b) {
+ return 0;
+ }
+ var aIsNull = (typeof(a) == 'undefined' || a === null);
+ var bIsNull = (typeof(b) == 'undefined' || b === null);
+ if (aIsNull && bIsNull) {
+ return 0;
+ } else if (aIsNull) {
+ return -1;
+ } else if (bIsNull) {
+ return 1;
+ }
+ var m = MochiKit.Base;
+ // bool, number, string have meaningful comparisons
+ var prim = m._primitives;
+ if (!(typeof(a) in prim && typeof(b) in prim)) {
+ try {
+ return m.comparatorRegistry.match(a, b);
+ } catch (e) {
+ if (e != m.NotFound) {
+ throw e;
+ }
+ }
+ }
+ if (a < b) {
+ return -1;
+ } else if (a > b) {
+ return 1;
+ }
+ // These types can't be compared
+ var repr = m.repr;
+ throw new TypeError(repr(a) + " and " + repr(b) + " can not be compared");
+ },
+
+ /** @id MochiKit.Base.compareDateLike */
+ compareDateLike: function (a, b) {
+ return MochiKit.Base.compare(a.getTime(), b.getTime());
+ },
+
+ /** @id MochiKit.Base.compareArrayLike */
+ compareArrayLike: function (a, b) {
+ var compare = MochiKit.Base.compare;
+ var count = a.length;
+ var rval = 0;
+ if (count > b.length) {
+ rval = 1;
+ count = b.length;
+ } else if (count < b.length) {
+ rval = -1;
+ }
+ for (var i = 0; i < count; i++) {
+ var cmp = compare(a[i], b[i]);
+ if (cmp) {
+ return cmp;
+ }
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Base.registerRepr */
+ registerRepr: function (name, check, wrap, /* optional */override) {
+ MochiKit.Base.reprRegistry.register(name, check, wrap, override);
+ },
+
+ /** @id MochiKit.Base.repr */
+ repr: function (o) {
+ if (typeof(o) == "undefined") {
+ return "undefined";
+ } else if (o === null) {
+ return "null";
+ }
+ try {
+ if (typeof(o.__repr__) == 'function') {
+ return o.__repr__();
+ } else if (typeof(o.repr) == 'function' && o.repr != arguments.callee) {
+ return o.repr();
+ }
+ return MochiKit.Base.reprRegistry.match(o);
+ } catch (e) {
+ if (typeof(o.NAME) == 'string' && (
+ o.toString == Function.prototype.toString ||
+ o.toString == Object.prototype.toString
+ )) {
+ return o.NAME;
+ }
+ }
+ try {
+ var ostring = (o + "");
+ } catch (e) {
+ return "[" + typeof(o) + "]";
+ }
+ if (typeof(o) == "function") {
+ o = ostring.replace(/^\s+/, "");
+ var idx = o.indexOf("{");
+ if (idx != -1) {
+ o = o.substr(0, idx) + "{...}";
+ }
+ }
+ return ostring;
+ },
+
+ /** @id MochiKit.Base.reprArrayLike */
+ reprArrayLike: function (o) {
+ var m = MochiKit.Base;
+ return "[" + m.map(m.repr, o).join(", ") + "]";
+ },
+
+ /** @id MochiKit.Base.reprString */
+ reprString: function (o) {
+ return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
+ ).replace(/[\f]/g, "\\f"
+ ).replace(/[\b]/g, "\\b"
+ ).replace(/[\n]/g, "\\n"
+ ).replace(/[\t]/g, "\\t"
+ ).replace(/[\r]/g, "\\r");
+ },
+
+ /** @id MochiKit.Base.reprNumber */
+ reprNumber: function (o) {
+ return o + "";
+ },
+
+ /** @id MochiKit.Base.registerJSON */
+ registerJSON: function (name, check, wrap, /* optional */override) {
+ MochiKit.Base.jsonRegistry.register(name, check, wrap, override);
+ },
+
+
+ /** @id MochiKit.Base.evalJSON */
+ evalJSON: function () {
+ return eval("(" + MochiKit.Base._filterJSON(arguments[0]) + ")");
+ },
+
+ _filterJSON: function (s) {
+ var m = s.match(/^\s*\/\*(.*)\*\/\s*$/);
+ if (m) {
+ return m[1];
+ }
+ return s;
+ },
+
+ /** @id MochiKit.Base.serializeJSON */
+ serializeJSON: function (o) {
+ var objtype = typeof(o);
+ if (objtype == "number" || objtype == "boolean") {
+ return o + "";
+ } else if (o === null) {
+ return "null";
+ }
+ var m = MochiKit.Base;
+ var reprString = m.reprString;
+ if (objtype == "string") {
+ return reprString(o);
+ }
+ // recurse
+ var me = arguments.callee;
+ // short-circuit for objects that support "json" serialization
+ // if they return "self" then just pass-through...
+ var newObj;
+ if (typeof(o.__json__) == "function") {
+ newObj = o.__json__();
+ if (o !== newObj) {
+ return me(newObj);
+ }
+ }
+ if (typeof(o.json) == "function") {
+ newObj = o.json();
+ if (o !== newObj) {
+ return me(newObj);
+ }
+ }
+ // array
+ if (objtype != "function" && typeof(o.length) == "number") {
+ var res = [];
+ for (var i = 0; i < o.length; i++) {
+ var val = me(o[i]);
+ if (typeof(val) != "string") {
+ val = "undefined";
+ }
+ res.push(val);
+ }
+ return "[" + res.join(", ") + "]";
+ }
+ // look in the registry
+ try {
+ newObj = m.jsonRegistry.match(o);
+ if (o !== newObj) {
+ return me(newObj);
+ }
+ } catch (e) {
+ if (e != m.NotFound) {
+ // something really bad happened
+ throw e;
+ }
+ }
+ // undefined is outside of the spec
+ if (objtype == "undefined") {
+ throw new TypeError("undefined can not be serialized as JSON");
+ }
+ // it's a function with no adapter, bad
+ if (objtype == "function") {
+ return null;
+ }
+ // generic object code path
+ res = [];
+ for (var k in o) {
+ var useKey;
+ if (typeof(k) == "number") {
+ useKey = '"' + k + '"';
+ } else if (typeof(k) == "string") {
+ useKey = reprString(k);
+ } else {
+ // skip non-string or number keys
+ continue;
+ }
+ val = me(o[k]);
+ if (typeof(val) != "string") {
+ // skip non-serializable values
+ continue;
+ }
+ res.push(useKey + ":" + val);
+ }
+ return "{" + res.join(", ") + "}";
+ },
+
+
+ /** @id MochiKit.Base.objEqual */
+ objEqual: function (a, b) {
+ return (MochiKit.Base.compare(a, b) === 0);
+ },
+
+ /** @id MochiKit.Base.arrayEqual */
+ arrayEqual: function (self, arr) {
+ if (self.length != arr.length) {
+ return false;
+ }
+ return (MochiKit.Base.compare(self, arr) === 0);
+ },
+
+ /** @id MochiKit.Base.concat */
+ concat: function (/* lst... */) {
+ var rval = [];
+ var extend = MochiKit.Base.extend;
+ for (var i = 0; i < arguments.length; i++) {
+ extend(rval, arguments[i]);
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Base.keyComparator */
+ keyComparator: function (key/* ... */) {
+ // fast-path for single key comparisons
+ var m = MochiKit.Base;
+ var compare = m.compare;
+ if (arguments.length == 1) {
+ return function (a, b) {
+ return compare(a[key], b[key]);
+ };
+ }
+ var compareKeys = m.extend(null, arguments);
+ return function (a, b) {
+ var rval = 0;
+ // keep comparing until something is inequal or we run out of
+ // keys to compare
+ for (var i = 0; (rval === 0) && (i < compareKeys.length); i++) {
+ var key = compareKeys[i];
+ rval = compare(a[key], b[key]);
+ }
+ return rval;
+ };
+ },
+
+ /** @id MochiKit.Base.reverseKeyComparator */
+ reverseKeyComparator: function (key) {
+ var comparator = MochiKit.Base.keyComparator.apply(this, arguments);
+ return function (a, b) {
+ return comparator(b, a);
+ };
+ },
+
+ /** @id MochiKit.Base.partial */
+ partial: function (func) {
+ var m = MochiKit.Base;
+ return m.bind.apply(this, m.extend([func, undefined], arguments, 1));
+ },
+
+ /** @id MochiKit.Base.listMinMax */
+ listMinMax: function (which, lst) {
+ if (lst.length === 0) {
+ return null;
+ }
+ var cur = lst[0];
+ var compare = MochiKit.Base.compare;
+ for (var i = 1; i < lst.length; i++) {
+ var o = lst[i];
+ if (compare(o, cur) == which) {
+ cur = o;
+ }
+ }
+ return cur;
+ },
+
+ /** @id MochiKit.Base.objMax */
+ objMax: function (/* obj... */) {
+ return MochiKit.Base.listMinMax(1, arguments);
+ },
+
+ /** @id MochiKit.Base.objMin */
+ objMin: function (/* obj... */) {
+ return MochiKit.Base.listMinMax(-1, arguments);
+ },
+
+ /** @id MochiKit.Base.findIdentical */
+ findIdentical: function (lst, value, start/* = 0 */, /* optional */end) {
+ if (typeof(end) == "undefined" || end === null) {
+ end = lst.length;
+ }
+ if (typeof(start) == "undefined" || start === null) {
+ start = 0;
+ }
+ for (var i = start; i < end; i++) {
+ if (lst[i] === value) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ /** @id MochiKit.Base.mean */
+ mean: function(/* lst... */) {
+ /* http://www.nist.gov/dads/HTML/mean.html */
+ var sum = 0;
+
+ var m = MochiKit.Base;
+ var args = m.extend(null, arguments);
+ var count = args.length;
+
+ while (args.length) {
+ var o = args.shift();
+ if (o && typeof(o) == "object" && typeof(o.length) == "number") {
+ count += o.length - 1;
+ for (var i = o.length - 1; i >= 0; i--) {
+ sum += o[i];
+ }
+ } else {
+ sum += o;
+ }
+ }
+
+ if (count <= 0) {
+ throw new TypeError('mean() requires at least one argument');
+ }
+
+ return sum/count;
+ },
+
+ /** @id MochiKit.Base.median */
+ median: function(/* lst... */) {
+ /* http://www.nist.gov/dads/HTML/median.html */
+ var data = MochiKit.Base.flattenArguments(arguments);
+ if (data.length === 0) {
+ throw new TypeError('median() requires at least one argument');
+ }
+ data.sort(compare);
+ if (data.length % 2 == 0) {
+ var upper = data.length / 2;
+ return (data[upper] + data[upper - 1]) / 2;
+ } else {
+ return data[(data.length - 1) / 2];
+ }
+ },
+
+ /** @id MochiKit.Base.findValue */
+ findValue: function (lst, value, start/* = 0 */, /* optional */end) {
+ if (typeof(end) == "undefined" || end === null) {
+ end = lst.length;
+ }
+ if (typeof(start) == "undefined" || start === null) {
+ start = 0;
+ }
+ var cmp = MochiKit.Base.compare;
+ for (var i = start; i < end; i++) {
+ if (cmp(lst[i], value) === 0) {
+ return i;
+ }
+ }
+ return -1;
+ },
+
+ /** @id MochiKit.Base.nodeWalk */
+ nodeWalk: function (node, visitor) {
+ var nodes = [node];
+ var extend = MochiKit.Base.extend;
+ while (nodes.length) {
+ var res = visitor(nodes.shift());
+ if (res) {
+ extend(nodes, res);
+ }
+ }
+ },
+
+
+ /** @id MochiKit.Base.nameFunctions */
+ nameFunctions: function (namespace) {
+ var base = namespace.NAME;
+ if (typeof(base) == 'undefined') {
+ base = '';
+ } else {
+ base = base + '.';
+ }
+ for (var name in namespace) {
+ var o = namespace[name];
+ if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
+ try {
+ o.NAME = base + name;
+ } catch (e) {
+ // pass
+ }
+ }
+ }
+ },
+
+
+ /** @id MochiKit.Base.queryString */
+ queryString: function (names, values) {
+ // check to see if names is a string or a DOM element, and if
+ // MochiKit.DOM is available. If so, drop it like it's a form
+ // Ugliest conditional in MochiKit? Probably!
+ if (typeof(MochiKit.DOM) != "undefined" && arguments.length == 1
+ && (typeof(names) == "string" || (
+ typeof(names.nodeType) != "undefined" && names.nodeType > 0
+ ))
+ ) {
+ var kv = MochiKit.DOM.formContents(names);
+ names = kv[0];
+ values = kv[1];
+ } else if (arguments.length == 1) {
+ // Allow the return value of formContents to be passed directly
+ if (typeof(names.length) == "number" && names.length == 2) {
+ return arguments.callee(names[0], names[1]);
+ }
+ var o = names;
+ names = [];
+ values = [];
+ for (var k in o) {
+ var v = o[k];
+ if (typeof(v) == "function") {
+ continue;
+ } else if (typeof(v) != "string" &&
+ typeof(v.length) == "number") {
+ for (var i = 0; i < v.length; i++) {
+ names.push(k);
+ values.push(v[i]);
+ }
+ } else {
+ names.push(k);
+ values.push(v);
+ }
+ }
+ }
+ var rval = [];
+ var len = Math.min(names.length, values.length);
+ var urlEncode = MochiKit.Base.urlEncode;
+ for (var i = 0; i < len; i++) {
+ v = values[i];
+ if (typeof(v) != 'undefined' && v !== null) {
+ rval.push(urlEncode(names[i]) + "=" + urlEncode(v));
+ }
+ }
+ return rval.join("&");
+ },
+
+
+ /** @id MochiKit.Base.parseQueryString */
+ parseQueryString: function (encodedString, useArrays) {
+ // strip a leading '?' from the encoded string
+ var qstr = (encodedString.charAt(0) == "?")
+ ? encodedString.substring(1)
+ : encodedString;
+ var pairs = qstr.replace(/\+/g, "%20").split(/(\&amp\;|\&\#38\;|\&#x26;|\&)/);
+ var o = {};
+ var decode;
+ if (typeof(decodeURIComponent) != "undefined") {
+ decode = decodeURIComponent;
+ } else {
+ decode = unescape;
+ }
+ if (useArrays) {
+ for (var i = 0; i < pairs.length; i++) {
+ var pair = pairs[i].split("=");
+ var name = decode(pair.shift());
+ if (!name) {
+ continue;
+ }
+ var arr = o[name];
+ if (!(arr instanceof Array)) {
+ arr = [];
+ o[name] = arr;
+ }
+ arr.push(decode(pair.join("=")));
+ }
+ } else {
+ for (i = 0; i < pairs.length; i++) {
+ pair = pairs[i].split("=");
+ var name = pair.shift();
+ if (!name) {
+ continue;
+ }
+ o[decode(name)] = decode(pair.join("="));
+ }
+ }
+ return o;
+ }
+});
+
+/** @id MochiKit.Base.AdapterRegistry */
+MochiKit.Base.AdapterRegistry = function () {
+ this.pairs = [];
+};
+
+MochiKit.Base.AdapterRegistry.prototype = {
+ /** @id MochiKit.Base.AdapterRegistry.prototype.register */
+ register: function (name, check, wrap, /* optional */ override) {
+ if (override) {
+ this.pairs.unshift([name, check, wrap]);
+ } else {
+ this.pairs.push([name, check, wrap]);
+ }
+ },
+
+ /** @id MochiKit.Base.AdapterRegistry.prototype.match */
+ match: function (/* ... */) {
+ for (var i = 0; i < this.pairs.length; i++) {
+ var pair = this.pairs[i];
+ if (pair[1].apply(this, arguments)) {
+ return pair[2].apply(this, arguments);
+ }
+ }
+ throw MochiKit.Base.NotFound;
+ },
+
+ /** @id MochiKit.Base.AdapterRegistry.prototype.unregister */
+ unregister: function (name) {
+ for (var i = 0; i < this.pairs.length; i++) {
+ var pair = this.pairs[i];
+ if (pair[0] == name) {
+ this.pairs.splice(i, 1);
+ return true;
+ }
+ }
+ return false;
+ }
+};
+
+
+MochiKit.Base.EXPORT = [
+ "flattenArray",
+ "noop",
+ "camelize",
+ "counter",
+ "clone",
+ "extend",
+ "update",
+ "updatetree",
+ "setdefault",
+ "keys",
+ "values",
+ "items",
+ "NamedError",
+ "operator",
+ "forwardCall",
+ "itemgetter",
+ "typeMatcher",
+ "isCallable",
+ "isUndefined",
+ "isUndefinedOrNull",
+ "isNull",
+ "isEmpty",
+ "isNotEmpty",
+ "isArrayLike",
+ "isDateLike",
+ "xmap",
+ "map",
+ "xfilter",
+ "filter",
+ "methodcaller",
+ "compose",
+ "bind",
+ "bindMethods",
+ "NotFound",
+ "AdapterRegistry",
+ "registerComparator",
+ "compare",
+ "registerRepr",
+ "repr",
+ "objEqual",
+ "arrayEqual",
+ "concat",
+ "keyComparator",
+ "reverseKeyComparator",
+ "partial",
+ "merge",
+ "listMinMax",
+ "listMax",
+ "listMin",
+ "objMax",
+ "objMin",
+ "nodeWalk",
+ "zip",
+ "urlEncode",
+ "queryString",
+ "serializeJSON",
+ "registerJSON",
+ "evalJSON",
+ "parseQueryString",
+ "findValue",
+ "findIdentical",
+ "flattenArguments",
+ "method",
+ "average",
+ "mean",
+ "median"
+];
+
+MochiKit.Base.EXPORT_OK = [
+ "nameFunctions",
+ "comparatorRegistry",
+ "reprRegistry",
+ "jsonRegistry",
+ "compareDateLike",
+ "compareArrayLike",
+ "reprArrayLike",
+ "reprString",
+ "reprNumber"
+];
+
+MochiKit.Base._exportSymbols = function (globals, module) {
+ if (!MochiKit.__export__) {
+ return;
+ }
+ var all = module.EXPORT_TAGS[":all"];
+ for (var i = 0; i < all.length; i++) {
+ globals[all[i]] = module[all[i]];
+ }
+};
+
+MochiKit.Base.__new__ = function () {
+ // A singleton raised when no suitable adapter is found
+ var m = this;
+
+ // convenience
+ /** @id MochiKit.Base.noop */
+ m.noop = m.operator.identity;
+
+ // Backwards compat
+ m.forward = m.forwardCall;
+ m.find = m.findValue;
+
+ if (typeof(encodeURIComponent) != "undefined") {
+ /** @id MochiKit.Base.urlEncode */
+ m.urlEncode = function (unencoded) {
+ return encodeURIComponent(unencoded).replace(/\'/g, '%27');
+ };
+ } else {
+ m.urlEncode = function (unencoded) {
+ return escape(unencoded
+ ).replace(/\+/g, '%2B'
+ ).replace(/\"/g,'%22'
+ ).rval.replace(/\'/g, '%27');
+ };
+ }
+
+ /** @id MochiKit.Base.NamedError */
+ m.NamedError = function (name) {
+ this.message = name;
+ this.name = name;
+ };
+ m.NamedError.prototype = new Error();
+ m.update(m.NamedError.prototype, {
+ repr: function () {
+ if (this.message && this.message != this.name) {
+ return this.name + "(" + m.repr(this.message) + ")";
+ } else {
+ return this.name + "()";
+ }
+ },
+ toString: m.forwardCall("repr")
+ });
+
+ /** @id MochiKit.Base.NotFound */
+ m.NotFound = new m.NamedError("MochiKit.Base.NotFound");
+
+
+ /** @id MochiKit.Base.listMax */
+ m.listMax = m.partial(m.listMinMax, 1);
+ /** @id MochiKit.Base.listMin */
+ m.listMin = m.partial(m.listMinMax, -1);
+
+ /** @id MochiKit.Base.isCallable */
+ m.isCallable = m.typeMatcher('function');
+ /** @id MochiKit.Base.isUndefined */
+ m.isUndefined = m.typeMatcher('undefined');
+
+ /** @id MochiKit.Base.merge */
+ m.merge = m.partial(m.update, null);
+ /** @id MochiKit.Base.zip */
+ m.zip = m.partial(m.map, null);
+
+ /** @id MochiKit.Base.average */
+ m.average = m.mean;
+
+ /** @id MochiKit.Base.comparatorRegistry */
+ m.comparatorRegistry = new m.AdapterRegistry();
+ m.registerComparator("dateLike", m.isDateLike, m.compareDateLike);
+ m.registerComparator("arrayLike", m.isArrayLike, m.compareArrayLike);
+
+ /** @id MochiKit.Base.reprRegistry */
+ m.reprRegistry = new m.AdapterRegistry();
+ m.registerRepr("arrayLike", m.isArrayLike, m.reprArrayLike);
+ m.registerRepr("string", m.typeMatcher("string"), m.reprString);
+ m.registerRepr("numbers", m.typeMatcher("number", "boolean"), m.reprNumber);
+
+ /** @id MochiKit.Base.jsonRegistry */
+ m.jsonRegistry = new m.AdapterRegistry();
+
+ var all = m.concat(m.EXPORT, m.EXPORT_OK);
+ m.EXPORT_TAGS = {
+ ":common": m.concat(m.EXPORT_OK),
+ ":all": all
+ };
+
+ m.nameFunctions(this);
+
+};
+
+MochiKit.Base.__new__();
+
+//
+// XXX: Internet Explorer blows
+//
+if (MochiKit.__export__) {
+ compare = MochiKit.Base.compare;
+ compose = MochiKit.Base.compose;
+ serializeJSON = MochiKit.Base.serializeJSON;
+}
+
+MochiKit.Base._exportSymbols(this, MochiKit.Base);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Color.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Color.js
new file mode 100644
index 0000000000..708f49017f
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Color.js
@@ -0,0 +1,902 @@
+/***
+
+MochiKit.Color 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito and others. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Color');
+ dojo.require('MochiKit.Base');
+ dojo.require('MochiKit.DOM');
+ dojo.require('MochiKit.Style');
+}
+
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+ JSAN.use("MochiKit.DOM", []);
+ JSAN.use("MochiKit.Style", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.Color depends on MochiKit.Base";
+}
+
+try {
+ if (typeof(MochiKit.DOM) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.Color depends on MochiKit.DOM";
+}
+
+try {
+ if (typeof(MochiKit.Style) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.Color depends on MochiKit.Style";
+}
+
+if (typeof(MochiKit.Color) == "undefined") {
+ MochiKit.Color = {};
+}
+
+MochiKit.Color.NAME = "MochiKit.Color";
+MochiKit.Color.VERSION = "1.4";
+
+MochiKit.Color.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.Color.toString = function () {
+ return this.__repr__();
+};
+
+
+/** @id MochiKit.Color.Color */
+MochiKit.Color.Color = function (red, green, blue, alpha) {
+ if (typeof(alpha) == 'undefined' || alpha === null) {
+ alpha = 1.0;
+ }
+ this.rgb = {
+ r: red,
+ g: green,
+ b: blue,
+ a: alpha
+ };
+};
+
+
+// Prototype methods
+
+MochiKit.Color.Color.prototype = {
+
+ __class__: MochiKit.Color.Color,
+
+ /** @id MochiKit.Color.Color.prototype.colorWithAlpha */
+ colorWithAlpha: function (alpha) {
+ var rgb = this.rgb;
+ var m = MochiKit.Color;
+ return m.Color.fromRGB(rgb.r, rgb.g, rgb.b, alpha);
+ },
+
+ /** @id MochiKit.Color.Color.prototype.colorWithHue */
+ colorWithHue: function (hue) {
+ // get an HSL model, and set the new hue...
+ var hsl = this.asHSL();
+ hsl.h = hue;
+ var m = MochiKit.Color;
+ // convert back to RGB...
+ return m.Color.fromHSL(hsl);
+ },
+
+ /** @id MochiKit.Color.Color.prototype.colorWithSaturation */
+ colorWithSaturation: function (saturation) {
+ // get an HSL model, and set the new hue...
+ var hsl = this.asHSL();
+ hsl.s = saturation;
+ var m = MochiKit.Color;
+ // convert back to RGB...
+ return m.Color.fromHSL(hsl);
+ },
+
+ /** @id MochiKit.Color.Color.prototype.colorWithLightness */
+ colorWithLightness: function (lightness) {
+ // get an HSL model, and set the new hue...
+ var hsl = this.asHSL();
+ hsl.l = lightness;
+ var m = MochiKit.Color;
+ // convert back to RGB...
+ return m.Color.fromHSL(hsl);
+ },
+
+ /** @id MochiKit.Color.Color.prototype.darkerColorWithLevel */
+ darkerColorWithLevel: function (level) {
+ var hsl = this.asHSL();
+ hsl.l = Math.max(hsl.l - level, 0);
+ var m = MochiKit.Color;
+ return m.Color.fromHSL(hsl);
+ },
+
+ /** @id MochiKit.Color.Color.prototype.lighterColorWithLevel */
+ lighterColorWithLevel: function (level) {
+ var hsl = this.asHSL();
+ hsl.l = Math.min(hsl.l + level, 1);
+ var m = MochiKit.Color;
+ return m.Color.fromHSL(hsl);
+ },
+
+ /** @id MochiKit.Color.Color.prototype.blendedColor */
+ blendedColor: function (other, /* optional */ fraction) {
+ if (typeof(fraction) == 'undefined' || fraction === null) {
+ fraction = 0.5;
+ }
+ var sf = 1.0 - fraction;
+ var s = this.rgb;
+ var d = other.rgb;
+ var df = fraction;
+ return MochiKit.Color.Color.fromRGB(
+ (s.r * sf) + (d.r * df),
+ (s.g * sf) + (d.g * df),
+ (s.b * sf) + (d.b * df),
+ (s.a * sf) + (d.a * df)
+ );
+ },
+
+ /** @id MochiKit.Color.Color.prototype.compareRGB */
+ compareRGB: function (other) {
+ var a = this.asRGB();
+ var b = other.asRGB();
+ return MochiKit.Base.compare(
+ [a.r, a.g, a.b, a.a],
+ [b.r, b.g, b.b, b.a]
+ );
+ },
+
+ /** @id MochiKit.Color.Color.prototype.isLight */
+ isLight: function () {
+ return this.asHSL().b > 0.5;
+ },
+
+ /** @id MochiKit.Color.Color.prototype.isDark */
+ isDark: function () {
+ return (!this.isLight());
+ },
+
+ /** @id MochiKit.Color.Color.prototype.toHSLString */
+ toHSLString: function () {
+ var c = this.asHSL();
+ var ccc = MochiKit.Color.clampColorComponent;
+ var rval = this._hslString;
+ if (!rval) {
+ var mid = (
+ ccc(c.h, 360).toFixed(0)
+ + "," + ccc(c.s, 100).toPrecision(4) + "%"
+ + "," + ccc(c.l, 100).toPrecision(4) + "%"
+ );
+ var a = c.a;
+ if (a >= 1) {
+ a = 1;
+ rval = "hsl(" + mid + ")";
+ } else {
+ if (a <= 0) {
+ a = 0;
+ }
+ rval = "hsla(" + mid + "," + a + ")";
+ }
+ this._hslString = rval;
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Color.Color.prototype.toRGBString */
+ toRGBString: function () {
+ var c = this.rgb;
+ var ccc = MochiKit.Color.clampColorComponent;
+ var rval = this._rgbString;
+ if (!rval) {
+ var mid = (
+ ccc(c.r, 255).toFixed(0)
+ + "," + ccc(c.g, 255).toFixed(0)
+ + "," + ccc(c.b, 255).toFixed(0)
+ );
+ if (c.a != 1) {
+ rval = "rgba(" + mid + "," + c.a + ")";
+ } else {
+ rval = "rgb(" + mid + ")";
+ }
+ this._rgbString = rval;
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Color.Color.prototype.asRGB */
+ asRGB: function () {
+ return MochiKit.Base.clone(this.rgb);
+ },
+
+ /** @id MochiKit.Color.Color.prototype.toHexString */
+ toHexString: function () {
+ var m = MochiKit.Color;
+ var c = this.rgb;
+ var ccc = MochiKit.Color.clampColorComponent;
+ var rval = this._hexString;
+ if (!rval) {
+ rval = ("#" +
+ m.toColorPart(ccc(c.r, 255)) +
+ m.toColorPart(ccc(c.g, 255)) +
+ m.toColorPart(ccc(c.b, 255))
+ );
+ this._hexString = rval;
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Color.Color.prototype.asHSV */
+ asHSV: function () {
+ var hsv = this.hsv;
+ var c = this.rgb;
+ if (typeof(hsv) == 'undefined' || hsv === null) {
+ hsv = MochiKit.Color.rgbToHSV(this.rgb);
+ this.hsv = hsv;
+ }
+ return MochiKit.Base.clone(hsv);
+ },
+
+ /** @id MochiKit.Color.Color.prototype.asHSL */
+ asHSL: function () {
+ var hsl = this.hsl;
+ var c = this.rgb;
+ if (typeof(hsl) == 'undefined' || hsl === null) {
+ hsl = MochiKit.Color.rgbToHSL(this.rgb);
+ this.hsl = hsl;
+ }
+ return MochiKit.Base.clone(hsl);
+ },
+
+ /** @id MochiKit.Color.Color.prototype.toString */
+ toString: function () {
+ return this.toRGBString();
+ },
+
+ /** @id MochiKit.Color.Color.prototype.repr */
+ repr: function () {
+ var c = this.rgb;
+ var col = [c.r, c.g, c.b, c.a];
+ return this.__class__.NAME + "(" + col.join(", ") + ")";
+ }
+
+};
+
+// Constructor methods
+
+MochiKit.Base.update(MochiKit.Color.Color, {
+ /** @id MochiKit.Color.Color.fromRGB */
+ fromRGB: function (red, green, blue, alpha) {
+ // designated initializer
+ var Color = MochiKit.Color.Color;
+ if (arguments.length == 1) {
+ var rgb = red;
+ red = rgb.r;
+ green = rgb.g;
+ blue = rgb.b;
+ if (typeof(rgb.a) == 'undefined') {
+ alpha = undefined;
+ } else {
+ alpha = rgb.a;
+ }
+ }
+ return new Color(red, green, blue, alpha);
+ },
+
+ /** @id MochiKit.Color.Color.fromHSL */
+ fromHSL: function (hue, saturation, lightness, alpha) {
+ var m = MochiKit.Color;
+ return m.Color.fromRGB(m.hslToRGB.apply(m, arguments));
+ },
+
+ /** @id MochiKit.Color.Color.fromHSV */
+ fromHSV: function (hue, saturation, value, alpha) {
+ var m = MochiKit.Color;
+ return m.Color.fromRGB(m.hsvToRGB.apply(m, arguments));
+ },
+
+ /** @id MochiKit.Color.Color.fromName */
+ fromName: function (name) {
+ var Color = MochiKit.Color.Color;
+ // Opera 9 seems to "quote" named colors(?!)
+ if (name.charAt(0) == '"') {
+ name = name.substr(1, name.length - 2);
+ }
+ var htmlColor = Color._namedColors[name.toLowerCase()];
+ if (typeof(htmlColor) == 'string') {
+ return Color.fromHexString(htmlColor);
+ } else if (name == "transparent") {
+ return Color.transparentColor();
+ }
+ return null;
+ },
+
+ /** @id MochiKit.Color.Color.fromString */
+ fromString: function (colorString) {
+ var self = MochiKit.Color.Color;
+ var three = colorString.substr(0, 3);
+ if (three == "rgb") {
+ return self.fromRGBString(colorString);
+ } else if (three == "hsl") {
+ return self.fromHSLString(colorString);
+ } else if (colorString.charAt(0) == "#") {
+ return self.fromHexString(colorString);
+ }
+ return self.fromName(colorString);
+ },
+
+
+ /** @id MochiKit.Color.Color.fromHexString */
+ fromHexString: function (hexCode) {
+ if (hexCode.charAt(0) == '#') {
+ hexCode = hexCode.substring(1);
+ }
+ var components = [];
+ var i, hex;
+ if (hexCode.length == 3) {
+ for (i = 0; i < 3; i++) {
+ hex = hexCode.substr(i, 1);
+ components.push(parseInt(hex + hex, 16) / 255.0);
+ }
+ } else {
+ for (i = 0; i < 6; i += 2) {
+ hex = hexCode.substr(i, 2);
+ components.push(parseInt(hex, 16) / 255.0);
+ }
+ }
+ var Color = MochiKit.Color.Color;
+ return Color.fromRGB.apply(Color, components);
+ },
+
+
+ _fromColorString: function (pre, method, scales, colorCode) {
+ // parses either HSL or RGB
+ if (colorCode.indexOf(pre) === 0) {
+ colorCode = colorCode.substring(colorCode.indexOf("(", 3) + 1, colorCode.length - 1);
+ }
+ var colorChunks = colorCode.split(/\s*,\s*/);
+ var colorFloats = [];
+ for (var i = 0; i < colorChunks.length; i++) {
+ var c = colorChunks[i];
+ var val;
+ var three = c.substring(c.length - 3);
+ if (c.charAt(c.length - 1) == '%') {
+ val = 0.01 * parseFloat(c.substring(0, c.length - 1));
+ } else if (three == "deg") {
+ val = parseFloat(c) / 360.0;
+ } else if (three == "rad") {
+ val = parseFloat(c) / (Math.PI * 2);
+ } else {
+ val = scales[i] * parseFloat(c);
+ }
+ colorFloats.push(val);
+ }
+ return this[method].apply(this, colorFloats);
+ },
+
+ /** @id MochiKit.Color.Color.fromComputedStyle */
+ fromComputedStyle: function (elem, style) {
+ var d = MochiKit.DOM;
+ var cls = MochiKit.Color.Color;
+ for (elem = d.getElement(elem); elem; elem = elem.parentNode) {
+ var actualColor = MochiKit.Style.getStyle.apply(d, arguments);
+ if (!actualColor) {
+ continue;
+ }
+ var color = cls.fromString(actualColor);
+ if (!color) {
+ break;
+ }
+ if (color.asRGB().a > 0) {
+ return color;
+ }
+ }
+ return null;
+ },
+
+ /** @id MochiKit.Color.Color.fromBackground */
+ fromBackground: function (elem) {
+ var cls = MochiKit.Color.Color;
+ return cls.fromComputedStyle(
+ elem, "backgroundColor", "background-color") || cls.whiteColor();
+ },
+
+ /** @id MochiKit.Color.Color.fromText */
+ fromText: function (elem) {
+ var cls = MochiKit.Color.Color;
+ return cls.fromComputedStyle(
+ elem, "color", "color") || cls.blackColor();
+ },
+
+ /** @id MochiKit.Color.Color.namedColors */
+ namedColors: function () {
+ return MochiKit.Base.clone(MochiKit.Color.Color._namedColors);
+ }
+});
+
+
+// Module level functions
+
+MochiKit.Base.update(MochiKit.Color, {
+ /** @id MochiKit.Color.clampColorComponent */
+ clampColorComponent: function (v, scale) {
+ v *= scale;
+ if (v < 0) {
+ return 0;
+ } else if (v > scale) {
+ return scale;
+ } else {
+ return v;
+ }
+ },
+
+ _hslValue: function (n1, n2, hue) {
+ if (hue > 6.0) {
+ hue -= 6.0;
+ } else if (hue < 0.0) {
+ hue += 6.0;
+ }
+ var val;
+ if (hue < 1.0) {
+ val = n1 + (n2 - n1) * hue;
+ } else if (hue < 3.0) {
+ val = n2;
+ } else if (hue < 4.0) {
+ val = n1 + (n2 - n1) * (4.0 - hue);
+ } else {
+ val = n1;
+ }
+ return val;
+ },
+
+ /** @id MochiKit.Color.hsvToRGB */
+ hsvToRGB: function (hue, saturation, value, alpha) {
+ if (arguments.length == 1) {
+ var hsv = hue;
+ hue = hsv.h;
+ saturation = hsv.s;
+ value = hsv.v;
+ alpha = hsv.a;
+ }
+ var red;
+ var green;
+ var blue;
+ if (saturation === 0) {
+ red = value;
+ green = value;
+ blue = value;
+ } else {
+ var i = Math.floor(hue * 6);
+ var f = (hue * 6) - i;
+ var p = value * (1 - saturation);
+ var q = value * (1 - (saturation * f));
+ var t = value * (1 - (saturation * (1 - f)));
+ switch (i) {
+ case 1: red = q; green = value; blue = p; break;
+ case 2: red = p; green = value; blue = t; break;
+ case 3: red = p; green = q; blue = value; break;
+ case 4: red = t; green = p; blue = value; break;
+ case 5: red = value; green = p; blue = q; break;
+ case 6: // fall through
+ case 0: red = value; green = t; blue = p; break;
+ }
+ }
+ return {
+ r: red,
+ g: green,
+ b: blue,
+ a: alpha
+ };
+ },
+
+ /** @id MochiKit.Color.hslToRGB */
+ hslToRGB: function (hue, saturation, lightness, alpha) {
+ if (arguments.length == 1) {
+ var hsl = hue;
+ hue = hsl.h;
+ saturation = hsl.s;
+ lightness = hsl.l;
+ alpha = hsl.a;
+ }
+ var red;
+ var green;
+ var blue;
+ if (saturation === 0) {
+ red = lightness;
+ green = lightness;
+ blue = lightness;
+ } else {
+ var m2;
+ if (lightness <= 0.5) {
+ m2 = lightness * (1.0 + saturation);
+ } else {
+ m2 = lightness + saturation - (lightness * saturation);
+ }
+ var m1 = (2.0 * lightness) - m2;
+ var f = MochiKit.Color._hslValue;
+ var h6 = hue * 6.0;
+ red = f(m1, m2, h6 + 2);
+ green = f(m1, m2, h6);
+ blue = f(m1, m2, h6 - 2);
+ }
+ return {
+ r: red,
+ g: green,
+ b: blue,
+ a: alpha
+ };
+ },
+
+ /** @id MochiKit.Color.rgbToHSV */
+ rgbToHSV: function (red, green, blue, alpha) {
+ if (arguments.length == 1) {
+ var rgb = red;
+ red = rgb.r;
+ green = rgb.g;
+ blue = rgb.b;
+ alpha = rgb.a;
+ }
+ var max = Math.max(Math.max(red, green), blue);
+ var min = Math.min(Math.min(red, green), blue);
+ var hue;
+ var saturation;
+ var value = max;
+ if (min == max) {
+ hue = 0;
+ saturation = 0;
+ } else {
+ var delta = (max - min);
+ saturation = delta / max;
+
+ if (red == max) {
+ hue = (green - blue) / delta;
+ } else if (green == max) {
+ hue = 2 + ((blue - red) / delta);
+ } else {
+ hue = 4 + ((red - green) / delta);
+ }
+ hue /= 6;
+ if (hue < 0) {
+ hue += 1;
+ }
+ if (hue > 1) {
+ hue -= 1;
+ }
+ }
+ return {
+ h: hue,
+ s: saturation,
+ v: value,
+ a: alpha
+ };
+ },
+
+ /** @id MochiKit.Color.rgbToHSL */
+ rgbToHSL: function (red, green, blue, alpha) {
+ if (arguments.length == 1) {
+ var rgb = red;
+ red = rgb.r;
+ green = rgb.g;
+ blue = rgb.b;
+ alpha = rgb.a;
+ }
+ var max = Math.max(red, Math.max(green, blue));
+ var min = Math.min(red, Math.min(green, blue));
+ var hue;
+ var saturation;
+ var lightness = (max + min) / 2.0;
+ var delta = max - min;
+ if (delta === 0) {
+ hue = 0;
+ saturation = 0;
+ } else {
+ if (lightness <= 0.5) {
+ saturation = delta / (max + min);
+ } else {
+ saturation = delta / (2 - max - min);
+ }
+ if (red == max) {
+ hue = (green - blue) / delta;
+ } else if (green == max) {
+ hue = 2 + ((blue - red) / delta);
+ } else {
+ hue = 4 + ((red - green) / delta);
+ }
+ hue /= 6;
+ if (hue < 0) {
+ hue += 1;
+ }
+ if (hue > 1) {
+ hue -= 1;
+ }
+
+ }
+ return {
+ h: hue,
+ s: saturation,
+ l: lightness,
+ a: alpha
+ };
+ },
+
+ /** @id MochiKit.Color.toColorPart */
+ toColorPart: function (num) {
+ num = Math.round(num);
+ var digits = num.toString(16);
+ if (num < 16) {
+ return '0' + digits;
+ }
+ return digits;
+ },
+
+ __new__: function () {
+ var m = MochiKit.Base;
+ /** @id MochiKit.Color.fromRGBString */
+ this.Color.fromRGBString = m.bind(
+ this.Color._fromColorString, this.Color, "rgb", "fromRGB",
+ [1.0/255.0, 1.0/255.0, 1.0/255.0, 1]
+ );
+ /** @id MochiKit.Color.fromHSLString */
+ this.Color.fromHSLString = m.bind(
+ this.Color._fromColorString, this.Color, "hsl", "fromHSL",
+ [1.0/360.0, 0.01, 0.01, 1]
+ );
+
+ var third = 1.0 / 3.0;
+ /** @id MochiKit.Color.colors */
+ var colors = {
+ // NSColor colors plus transparent
+ /** @id MochiKit.Color.blackColor */
+ black: [0, 0, 0],
+ /** @id MochiKit.Color.blueColor */
+ blue: [0, 0, 1],
+ /** @id MochiKit.Color.brownColor */
+ brown: [0.6, 0.4, 0.2],
+ /** @id MochiKit.Color.cyanColor */
+ cyan: [0, 1, 1],
+ /** @id MochiKit.Color.darkGrayColor */
+ darkGray: [third, third, third],
+ /** @id MochiKit.Color.grayColor */
+ gray: [0.5, 0.5, 0.5],
+ /** @id MochiKit.Color.greenColor */
+ green: [0, 1, 0],
+ /** @id MochiKit.Color.lightGrayColor */
+ lightGray: [2 * third, 2 * third, 2 * third],
+ /** @id MochiKit.Color.magentaColor */
+ magenta: [1, 0, 1],
+ /** @id MochiKit.Color.orangeColor */
+ orange: [1, 0.5, 0],
+ /** @id MochiKit.Color.purpleColor */
+ purple: [0.5, 0, 0.5],
+ /** @id MochiKit.Color.redColor */
+ red: [1, 0, 0],
+ /** @id MochiKit.Color.transparentColor */
+ transparent: [0, 0, 0, 0],
+ /** @id MochiKit.Color.whiteColor */
+ white: [1, 1, 1],
+ /** @id MochiKit.Color.yellowColor */
+ yellow: [1, 1, 0]
+ };
+
+ var makeColor = function (name, r, g, b, a) {
+ var rval = this.fromRGB(r, g, b, a);
+ this[name] = function () { return rval; };
+ return rval;
+ };
+
+ for (var k in colors) {
+ var name = k + "Color";
+ var bindArgs = m.concat(
+ [makeColor, this.Color, name],
+ colors[k]
+ );
+ this.Color[name] = m.bind.apply(null, bindArgs);
+ }
+
+ var isColor = function () {
+ for (var i = 0; i < arguments.length; i++) {
+ if (!(arguments[i] instanceof Color)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ var compareColor = function (a, b) {
+ return a.compareRGB(b);
+ };
+
+ m.nameFunctions(this);
+
+ m.registerComparator(this.Color.NAME, isColor, compareColor);
+
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ }
+});
+
+MochiKit.Color.EXPORT = [
+ "Color"
+];
+
+MochiKit.Color.EXPORT_OK = [
+ "clampColorComponent",
+ "rgbToHSL",
+ "hslToRGB",
+ "rgbToHSV",
+ "hsvToRGB",
+ "toColorPart"
+];
+
+MochiKit.Color.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.Color);
+
+// Full table of css3 X11 colors <http://www.w3.org/TR/css3-color/#X11COLORS>
+
+MochiKit.Color.Color._namedColors = {
+ aliceblue: "#f0f8ff",
+ antiquewhite: "#faebd7",
+ aqua: "#00ffff",
+ aquamarine: "#7fffd4",
+ azure: "#f0ffff",
+ beige: "#f5f5dc",
+ bisque: "#ffe4c4",
+ black: "#000000",
+ blanchedalmond: "#ffebcd",
+ blue: "#0000ff",
+ blueviolet: "#8a2be2",
+ brown: "#a52a2a",
+ burlywood: "#deb887",
+ cadetblue: "#5f9ea0",
+ chartreuse: "#7fff00",
+ chocolate: "#d2691e",
+ coral: "#ff7f50",
+ cornflowerblue: "#6495ed",
+ cornsilk: "#fff8dc",
+ crimson: "#dc143c",
+ cyan: "#00ffff",
+ darkblue: "#00008b",
+ darkcyan: "#008b8b",
+ darkgoldenrod: "#b8860b",
+ darkgray: "#a9a9a9",
+ darkgreen: "#006400",
+ darkgrey: "#a9a9a9",
+ darkkhaki: "#bdb76b",
+ darkmagenta: "#8b008b",
+ darkolivegreen: "#556b2f",
+ darkorange: "#ff8c00",
+ darkorchid: "#9932cc",
+ darkred: "#8b0000",
+ darksalmon: "#e9967a",
+ darkseagreen: "#8fbc8f",
+ darkslateblue: "#483d8b",
+ darkslategray: "#2f4f4f",
+ darkslategrey: "#2f4f4f",
+ darkturquoise: "#00ced1",
+ darkviolet: "#9400d3",
+ deeppink: "#ff1493",
+ deepskyblue: "#00bfff",
+ dimgray: "#696969",
+ dimgrey: "#696969",
+ dodgerblue: "#1e90ff",
+ firebrick: "#b22222",
+ floralwhite: "#fffaf0",
+ forestgreen: "#228b22",
+ fuchsia: "#ff00ff",
+ gainsboro: "#dcdcdc",
+ ghostwhite: "#f8f8ff",
+ gold: "#ffd700",
+ goldenrod: "#daa520",
+ gray: "#808080",
+ green: "#008000",
+ greenyellow: "#adff2f",
+ grey: "#808080",
+ honeydew: "#f0fff0",
+ hotpink: "#ff69b4",
+ indianred: "#cd5c5c",
+ indigo: "#4b0082",
+ ivory: "#fffff0",
+ khaki: "#f0e68c",
+ lavender: "#e6e6fa",
+ lavenderblush: "#fff0f5",
+ lawngreen: "#7cfc00",
+ lemonchiffon: "#fffacd",
+ lightblue: "#add8e6",
+ lightcoral: "#f08080",
+ lightcyan: "#e0ffff",
+ lightgoldenrodyellow: "#fafad2",
+ lightgray: "#d3d3d3",
+ lightgreen: "#90ee90",
+ lightgrey: "#d3d3d3",
+ lightpink: "#ffb6c1",
+ lightsalmon: "#ffa07a",
+ lightseagreen: "#20b2aa",
+ lightskyblue: "#87cefa",
+ lightslategray: "#778899",
+ lightslategrey: "#778899",
+ lightsteelblue: "#b0c4de",
+ lightyellow: "#ffffe0",
+ lime: "#00ff00",
+ limegreen: "#32cd32",
+ linen: "#faf0e6",
+ magenta: "#ff00ff",
+ maroon: "#800000",
+ mediumaquamarine: "#66cdaa",
+ mediumblue: "#0000cd",
+ mediumorchid: "#ba55d3",
+ mediumpurple: "#9370db",
+ mediumseagreen: "#3cb371",
+ mediumslateblue: "#7b68ee",
+ mediumspringgreen: "#00fa9a",
+ mediumturquoise: "#48d1cc",
+ mediumvioletred: "#c71585",
+ midnightblue: "#191970",
+ mintcream: "#f5fffa",
+ mistyrose: "#ffe4e1",
+ moccasin: "#ffe4b5",
+ navajowhite: "#ffdead",
+ navy: "#000080",
+ oldlace: "#fdf5e6",
+ olive: "#808000",
+ olivedrab: "#6b8e23",
+ orange: "#ffa500",
+ orangered: "#ff4500",
+ orchid: "#da70d6",
+ palegoldenrod: "#eee8aa",
+ palegreen: "#98fb98",
+ paleturquoise: "#afeeee",
+ palevioletred: "#db7093",
+ papayawhip: "#ffefd5",
+ peachpuff: "#ffdab9",
+ peru: "#cd853f",
+ pink: "#ffc0cb",
+ plum: "#dda0dd",
+ powderblue: "#b0e0e6",
+ purple: "#800080",
+ red: "#ff0000",
+ rosybrown: "#bc8f8f",
+ royalblue: "#4169e1",
+ saddlebrown: "#8b4513",
+ salmon: "#fa8072",
+ sandybrown: "#f4a460",
+ seagreen: "#2e8b57",
+ seashell: "#fff5ee",
+ sienna: "#a0522d",
+ silver: "#c0c0c0",
+ skyblue: "#87ceeb",
+ slateblue: "#6a5acd",
+ slategray: "#708090",
+ slategrey: "#708090",
+ snow: "#fffafa",
+ springgreen: "#00ff7f",
+ steelblue: "#4682b4",
+ tan: "#d2b48c",
+ teal: "#008080",
+ thistle: "#d8bfd8",
+ tomato: "#ff6347",
+ turquoise: "#40e0d0",
+ violet: "#ee82ee",
+ wheat: "#f5deb3",
+ white: "#ffffff",
+ whitesmoke: "#f5f5f5",
+ yellow: "#ffff00",
+ yellowgreen: "#9acd32"
+};
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Controls.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Controls.js
new file mode 100644
index 0000000000..c044ef2abf
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Controls.js
@@ -0,0 +1,1388 @@
+/***
+Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+ (c) 2005 Ivan Krstic (http://blogs.law.harvard.edu/ivan)
+ (c) 2005 Jon Tirsen (http://www.tirsen.com)
+Contributors:
+ Richard Livsey
+ Rahul Bhargava
+ Rob Wills
+ Mochi-ized By Thomas Herve (_firstname_@nimail.org)
+
+See scriptaculous.js for full license.
+
+Autocompleter.Base handles all the autocompletion functionality
+that's independent of the data source for autocompletion. This
+includes drawing the autocompletion menu, observing keyboard
+and mouse events, and similar.
+
+Specific autocompleters need to provide, at the very least,
+a getUpdatedChoices function that will be invoked every time
+the text inside the monitored textbox changes. This method
+should get the text for which to provide autocompletion by
+invoking this.getToken(), NOT by directly accessing
+this.element.value. This is to allow incremental tokenized
+autocompletion. Specific auto-completion logic (AJAX, etc)
+belongs in getUpdatedChoices.
+
+Tokenized incremental autocompletion is enabled automatically
+when an autocompleter is instantiated with the 'tokens' option
+in the options parameter, e.g.:
+new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' });
+will incrementally autocomplete with a comma as the token.
+Additionally, ',' in the above example can be replaced with
+a token array, e.g. { tokens: [',', '\n'] } which
+enables autocompletion on multiple tokens. This is most
+useful when one of the tokens is \n (a newline), as it
+allows smart autocompletion after linebreaks.
+
+***/
+
+MochiKit.Base.update(MochiKit.Base, {
+ ScriptFragment: '(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)',
+
+/** @id MochiKit.Base.stripScripts */
+ stripScripts: function (str) {
+ return str.replace(new RegExp(MochiKit.Base.ScriptFragment, 'img'), '');
+ },
+
+/** @id MochiKit.Base.stripTags */
+ stripTags: function(str) {
+ return str.replace(/<\/?[^>]+>/gi, '');
+ },
+
+/** @id MochiKit.Base.extractScripts */
+ extractScripts: function (str) {
+ var matchAll = new RegExp(MochiKit.Base.ScriptFragment, 'img');
+ var matchOne = new RegExp(MochiKit.Base.ScriptFragment, 'im');
+ return MochiKit.Base.map(function (scriptTag) {
+ return (scriptTag.match(matchOne) || ['', ''])[1];
+ }, str.match(matchAll) || []);
+ },
+
+/** @id MochiKit.Base.evalScripts */
+ evalScripts: function (str) {
+ return MochiKit.Base.map(function (scr) {
+ eval(scr);
+ }, MochiKit.Base.extractScripts(str));
+ }
+});
+
+MochiKit.Form = {
+
+/** @id MochiKit.Form.serialize */
+ serialize: function (form) {
+ var elements = MochiKit.Form.getElements(form);
+ var queryComponents = [];
+
+ for (var i = 0; i < elements.length; i++) {
+ var queryComponent = MochiKit.Form.serializeElement(elements[i]);
+ if (queryComponent) {
+ queryComponents.push(queryComponent);
+ }
+ }
+
+ return queryComponents.join('&');
+ },
+
+/** @id MochiKit.Form.getElements */
+ getElements: function (form) {
+ form = MochiKit.DOM.getElement(form);
+ var elements = [];
+
+ for (var tagName in MochiKit.Form.Serializers) {
+ var tagElements = form.getElementsByTagName(tagName);
+ for (var j = 0; j < tagElements.length; j++) {
+ elements.push(tagElements[j]);
+ }
+ }
+ return elements;
+ },
+
+/** @id MochiKit.Form.serializeElement */
+ serializeElement: function (element) {
+ element = MochiKit.DOM.getElement(element);
+ var method = element.tagName.toLowerCase();
+ var parameter = MochiKit.Form.Serializers[method](element);
+
+ if (parameter) {
+ var key = encodeURIComponent(parameter[0]);
+ if (key.length === 0) {
+ return;
+ }
+
+ if (!(parameter[1] instanceof Array)) {
+ parameter[1] = [parameter[1]];
+ }
+
+ return parameter[1].map(function (value) {
+ return key + '=' + encodeURIComponent(value);
+ }).join('&');
+ }
+ }
+};
+
+MochiKit.Form.Serializers = {
+
+/** @id MochiKit.Form.Serializers.input */
+ input: function (element) {
+ switch (element.type.toLowerCase()) {
+ case 'submit':
+ case 'hidden':
+ case 'password':
+ case 'text':
+ return MochiKit.Form.Serializers.textarea(element);
+ case 'checkbox':
+ case 'radio':
+ return MochiKit.Form.Serializers.inputSelector(element);
+ }
+ return false;
+ },
+
+/** @id MochiKit.Form.Serializers.inputSelector */
+ inputSelector: function (element) {
+ if (element.checked) {
+ return [element.name, element.value];
+ }
+ },
+
+/** @id MochiKit.Form.Serializers.textarea */
+ textarea: function (element) {
+ return [element.name, element.value];
+ },
+
+/** @id MochiKit.Form.Serializers.select */
+ select: function (element) {
+ return MochiKit.Form.Serializers[element.type == 'select-one' ?
+ 'selectOne' : 'selectMany'](element);
+ },
+
+/** @id MochiKit.Form.Serializers.selectOne */
+ selectOne: function (element) {
+ var value = '', opt, index = element.selectedIndex;
+ if (index >= 0) {
+ opt = element.options[index];
+ value = opt.value;
+ if (!value && !('value' in opt)) {
+ value = opt.text;
+ }
+ }
+ return [element.name, value];
+ },
+
+/** @id MochiKit.Form.Serializers.selectMany */
+ selectMany: function (element) {
+ var value = [];
+ for (var i = 0; i < element.length; i++) {
+ var opt = element.options[i];
+ if (opt.selected) {
+ var optValue = opt.value;
+ if (!optValue && !('value' in opt)) {
+ optValue = opt.text;
+ }
+ value.push(optValue);
+ }
+ }
+ return [element.name, value];
+ }
+};
+
+/** @id Ajax */
+var Ajax = {
+ activeRequestCount: 0
+};
+
+Ajax.Responders = {
+ responders: [],
+
+/** @id Ajax.Responders.register */
+ register: function (responderToAdd) {
+ if (MochiKit.Base.find(this.responders, responderToAdd) == -1) {
+ this.responders.push(responderToAdd);
+ }
+ },
+
+/** @id Ajax.Responders.unregister */
+ unregister: function (responderToRemove) {
+ this.responders = this.responders.without(responderToRemove);
+ },
+
+/** @id Ajax.Responders.dispatch */
+ dispatch: function (callback, request, transport, json) {
+ MochiKit.Iter.forEach(this.responders, function (responder) {
+ if (responder[callback] &&
+ typeof(responder[callback]) == 'function') {
+ try {
+ responder[callback].apply(responder, [request, transport, json]);
+ } catch (e) {}
+ }
+ });
+ }
+};
+
+Ajax.Responders.register({
+
+/** @id Ajax.Responders.onCreate */
+ onCreate: function () {
+ Ajax.activeRequestCount++;
+ },
+
+/** @id Ajax.Responders.onComplete */
+ onComplete: function () {
+ Ajax.activeRequestCount--;
+ }
+});
+
+/** @id Ajax.Base */
+Ajax.Base = function () {};
+
+Ajax.Base.prototype = {
+
+/** @id Ajax.Base.prototype.setOptions */
+ setOptions: function (options) {
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ parameters: ''
+ }
+ MochiKit.Base.update(this.options, options || {});
+ },
+
+/** @id Ajax.Base.prototype.responseIsSuccess */
+ responseIsSuccess: function () {
+ return this.transport.status == undefined
+ || this.transport.status === 0
+ || (this.transport.status >= 200 && this.transport.status < 300);
+ },
+
+/** @id Ajax.Base.prototype.responseIsFailure */
+ responseIsFailure: function () {
+ return !this.responseIsSuccess();
+ }
+};
+
+/** @id Ajax.Request */
+Ajax.Request = function (url, options) {
+ this.__init__(url, options);
+};
+
+/** @id Ajax.Events */
+Ajax.Request.Events = ['Uninitialized', 'Loading', 'Loaded',
+ 'Interactive', 'Complete'];
+
+MochiKit.Base.update(Ajax.Request.prototype, Ajax.Base.prototype);
+
+MochiKit.Base.update(Ajax.Request.prototype, {
+ __init__: function (url, options) {
+ this.transport = MochiKit.Async.getXMLHttpRequest();
+ this.setOptions(options);
+ this.request(url);
+ },
+
+/** @id Ajax.Request.prototype.request */
+ request: function (url) {
+ var parameters = this.options.parameters || '';
+ if (parameters.length > 0){
+ parameters += '&_=';
+ }
+
+ try {
+ this.url = url;
+ if (this.options.method == 'get' && parameters.length > 0) {
+ this.url += (this.url.match(/\?/) ? '&' : '?') + parameters;
+ }
+ Ajax.Responders.dispatch('onCreate', this, this.transport);
+
+ this.transport.open(this.options.method, this.url,
+ this.options.asynchronous);
+
+ if (this.options.asynchronous) {
+ this.transport.onreadystatechange = MochiKit.Base.bind(this.onStateChange, this);
+ setTimeout(MochiKit.Base.bind(function () {
+ this.respondToReadyState(1);
+ }, this), 10);
+ }
+
+ this.setRequestHeaders();
+
+ var body = this.options.postBody ? this.options.postBody : parameters;
+ this.transport.send(this.options.method == 'post' ? body : null);
+
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+/** @id Ajax.Request.prototype.setRequestHeaders */
+ setRequestHeaders: function () {
+ var requestHeaders = ['X-Requested-With', 'XMLHttpRequest'];
+
+ if (this.options.method == 'post') {
+ requestHeaders.push('Content-type',
+ 'application/x-www-form-urlencoded');
+
+ /* Force 'Connection: close' for Mozilla browsers to work around
+ * a bug where XMLHttpRequest sends an incorrect Content-length
+ * header. See Mozilla Bugzilla #246651.
+ */
+ if (this.transport.overrideMimeType) {
+ requestHeaders.push('Connection', 'close');
+ }
+ }
+
+ if (this.options.requestHeaders) {
+ requestHeaders.push.apply(requestHeaders, this.options.requestHeaders);
+ }
+
+ for (var i = 0; i < requestHeaders.length; i += 2) {
+ this.transport.setRequestHeader(requestHeaders[i], requestHeaders[i+1]);
+ }
+ },
+
+/** @id Ajax.Request.prototype.onStateChange */
+ onStateChange: function () {
+ var readyState = this.transport.readyState;
+ if (readyState != 1) {
+ this.respondToReadyState(this.transport.readyState);
+ }
+ },
+
+/** @id Ajax.Request.prototype.header */
+ header: function (name) {
+ try {
+ return this.transport.getResponseHeader(name);
+ } catch (e) {}
+ },
+
+/** @id Ajax.Request.prototype.evalJSON */
+ evalJSON: function () {
+ try {
+ return eval(this.header('X-JSON'));
+ } catch (e) {}
+ },
+
+/** @id Ajax.Request.prototype.evalResponse */
+ evalResponse: function () {
+ try {
+ return eval(this.transport.responseText);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+ },
+
+/** @id Ajax.Request.prototype.respondToReadyState */
+ respondToReadyState: function (readyState) {
+ var event = Ajax.Request.Events[readyState];
+ var transport = this.transport, json = this.evalJSON();
+
+ if (event == 'Complete') {
+ try {
+ (this.options['on' + this.transport.status]
+ || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
+ || MochiKit.Base.noop)(transport, json);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ if ((this.header('Content-type') || '').match(/^text\/javascript/i)) {
+ this.evalResponse();
+ }
+ }
+
+ try {
+ (this.options['on' + event] || MochiKit.Base.noop)(transport, json);
+ Ajax.Responders.dispatch('on' + event, this, transport, json);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
+ if (event == 'Complete') {
+ this.transport.onreadystatechange = MochiKit.Base.noop;
+ }
+ },
+
+/** @id Ajax.Request.prototype.dispatchException */
+ dispatchException: function (exception) {
+ (this.options.onException || MochiKit.Base.noop)(this, exception);
+ Ajax.Responders.dispatch('onException', this, exception);
+ }
+});
+
+/** @id Ajax.Updater */
+Ajax.Updater = function (container, url, options) {
+ this.__init__(container, url, options);
+};
+
+MochiKit.Base.update(Ajax.Updater.prototype, Ajax.Request.prototype);
+
+MochiKit.Base.update(Ajax.Updater.prototype, {
+ __init__: function (container, url, options) {
+ this.containers = {
+ success: container.success ? MochiKit.DOM.getElement(container.success) : MochiKit.DOM.getElement(container),
+ failure: container.failure ? MochiKit.DOM.getElement(container.failure) :
+ (container.success ? null : MochiKit.DOM.getElement(container))
+ }
+ this.transport = MochiKit.Async.getXMLHttpRequest();
+ this.setOptions(options);
+
+ var onComplete = this.options.onComplete || MochiKit.Base.noop;
+ this.options.onComplete = MochiKit.Base.bind(function (transport, object) {
+ this.updateContent();
+ onComplete(transport, object);
+ }, this);
+
+ this.request(url);
+ },
+
+/** @id Ajax.Updater.prototype.updateContent */
+ updateContent: function () {
+ var receiver = this.responseIsSuccess() ?
+ this.containers.success : this.containers.failure;
+ var response = this.transport.responseText;
+
+ if (!this.options.evalScripts) {
+ response = MochiKit.Base.stripScripts(response);
+ }
+
+ if (receiver) {
+ if (this.options.insertion) {
+ new this.options.insertion(receiver, response);
+ } else {
+ MochiKit.DOM.getElement(receiver).innerHTML =
+ MochiKit.Base.stripScripts(response);
+ setTimeout(function () {
+ MochiKit.Base.evalScripts(response);
+ }, 10);
+ }
+ }
+
+ if (this.responseIsSuccess()) {
+ if (this.onComplete) {
+ setTimeout(MochiKit.Base.bind(this.onComplete, this), 10);
+ }
+ }
+ }
+});
+
+/** @id Field */
+var Field = {
+
+/** @id clear */
+ clear: function () {
+ for (var i = 0; i < arguments.length; i++) {
+ MochiKit.DOM.getElement(arguments[i]).value = '';
+ }
+ },
+
+/** @id focus */
+ focus: function (element) {
+ MochiKit.DOM.getElement(element).focus();
+ },
+
+/** @id present */
+ present: function () {
+ for (var i = 0; i < arguments.length; i++) {
+ if (MochiKit.DOM.getElement(arguments[i]).value == '') {
+ return false;
+ }
+ }
+ return true;
+ },
+
+/** @id select */
+ select: function (element) {
+ MochiKit.DOM.getElement(element).select();
+ },
+
+/** @id activate */
+ activate: function (element) {
+ element = MochiKit.DOM.getElement(element);
+ element.focus();
+ if (element.select) {
+ element.select();
+ }
+ },
+
+/** @id scrollFreeActivate */
+ scrollFreeActivate: function (field) {
+ setTimeout(function () {
+ Field.activate(field);
+ }, 1);
+ }
+};
+
+
+/** @id Autocompleter */
+var Autocompleter = {};
+
+/** @id Autocompleter.Base */
+Autocompleter.Base = function () {};
+
+Autocompleter.Base.prototype = {
+
+/** @id Autocompleter.Base.prototype.baseInitialize */
+ baseInitialize: function (element, update, options) {
+ this.element = MochiKit.DOM.getElement(element);
+ this.update = MochiKit.DOM.getElement(update);
+ this.hasFocus = false;
+ this.changed = false;
+ this.active = false;
+ this.index = 0;
+ this.entryCount = 0;
+
+ if (this.setOptions) {
+ this.setOptions(options);
+ }
+ else {
+ this.options = options || {};
+ }
+
+ this.options.paramName = this.options.paramName || this.element.name;
+ this.options.tokens = this.options.tokens || [];
+ this.options.frequency = this.options.frequency || 0.4;
+ this.options.minChars = this.options.minChars || 1;
+ this.options.onShow = this.options.onShow || function (element, update) {
+ if (!update.style.position || update.style.position == 'absolute') {
+ update.style.position = 'absolute';
+ MochiKit.Position.clone(element, update, {
+ setHeight: false,
+ offsetTop: element.offsetHeight
+ });
+ }
+ MochiKit.Visual.appear(update, {duration:0.15});
+ };
+ this.options.onHide = this.options.onHide || function (element, update) {
+ MochiKit.Visual.fade(update, {duration: 0.15});
+ };
+
+ if (typeof(this.options.tokens) == 'string') {
+ this.options.tokens = new Array(this.options.tokens);
+ }
+
+ this.observer = null;
+
+ this.element.setAttribute('autocomplete', 'off');
+
+ MochiKit.Style.hideElement(this.update);
+
+ MochiKit.Signal.connect(this.element, 'onblur', this, this.onBlur);
+ MochiKit.Signal.connect(this.element, 'onkeypress', this, this.onKeyPress, this);
+ },
+
+/** @id Autocompleter.Base.prototype.show */
+ show: function () {
+ if (MochiKit.Style.getStyle(this.update, 'display') == 'none') {
+ this.options.onShow(this.element, this.update);
+ }
+ if (!this.iefix && /MSIE/.test(navigator.userAgent &&
+ (MochiKit.Style.getStyle(this.update, 'position') == 'absolute'))) {
+ new Insertion.After(this.update,
+ '<iframe id="' + this.update.id + '_iefix" '+
+ 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' +
+ 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');
+ this.iefix = MochiKit.DOM.getElement(this.update.id + '_iefix');
+ }
+ if (this.iefix) {
+ setTimeout(MochiKit.Base.bind(this.fixIEOverlapping, this), 50);
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.fixIEOverlapping */
+ fixIEOverlapping: function () {
+ MochiKit.Position.clone(this.update, this.iefix);
+ this.iefix.style.zIndex = 1;
+ this.update.style.zIndex = 2;
+ MochiKit.Style.showElement(this.iefix);
+ },
+
+/** @id Autocompleter.Base.prototype.hide */
+ hide: function () {
+ this.stopIndicator();
+ if (MochiKit.Style.getStyle(this.update, 'display') != 'none') {
+ this.options.onHide(this.element, this.update);
+ }
+ if (this.iefix) {
+ MochiKit.Style.hideElement(this.iefix);
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.startIndicator */
+ startIndicator: function () {
+ if (this.options.indicator) {
+ MochiKit.Style.showElement(this.options.indicator);
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.stopIndicator */
+ stopIndicator: function () {
+ if (this.options.indicator) {
+ MochiKit.Style.hideElement(this.options.indicator);
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.onKeyPress */
+ onKeyPress: function (event) {
+ if (this.active) {
+ if (event.key().string == "KEY_TAB" || event.key().string == "KEY_RETURN") {
+ this.selectEntry();
+ MochiKit.Event.stop(event);
+ } else if (event.key().string == "KEY_ESCAPE") {
+ this.hide();
+ this.active = false;
+ MochiKit.Event.stop(event);
+ return;
+ } else if (event.key().string == "KEY_LEFT" || event.key().string == "KEY_RIGHT") {
+ return;
+ } else if (event.key().string == "KEY_UP") {
+ this.markPrevious();
+ this.render();
+ if (/AppleWebKit'/.test(navigator.appVersion)) {
+ event.stop();
+ }
+ return;
+ } else if (event.key().string == "KEY_DOWN") {
+ this.markNext();
+ this.render();
+ if (/AppleWebKit'/.test(navigator.appVersion)) {
+ event.stop();
+ }
+ return;
+ }
+ } else {
+ if (event.key().string == "KEY_TAB" || event.key().string == "KEY_RETURN") {
+ return;
+ }
+ }
+
+ this.changed = true;
+ this.hasFocus = true;
+
+ if (this.observer) {
+ clearTimeout(this.observer);
+ }
+ this.observer = setTimeout(MochiKit.Base.bind(this.onObserverEvent, this),
+ this.options.frequency*1000);
+ },
+
+/** @id Autocompleter.Base.prototype.findElement */
+ findElement: function (event, tagName) {
+ var element = event.target;
+ while (element.parentNode && (!element.tagName ||
+ (element.tagName.toUpperCase() != tagName.toUpperCase()))) {
+ element = element.parentNode;
+ }
+ return element;
+ },
+
+/** @id Autocompleter.Base.prototype.hover */
+ onHover: function (event) {
+ var element = this.findElement(event, 'LI');
+ if (this.index != element.autocompleteIndex) {
+ this.index = element.autocompleteIndex;
+ this.render();
+ }
+ event.stop();
+ },
+
+/** @id Autocompleter.Base.prototype.onClick */
+ onClick: function (event) {
+ var element = this.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ },
+
+/** @id Autocompleter.Base.prototype.onBlur */
+ onBlur: function (event) {
+ // needed to make click events working
+ setTimeout(MochiKit.Base.bind(this.hide, this), 250);
+ this.hasFocus = false;
+ this.active = false;
+ },
+
+/** @id Autocompleter.Base.prototype.render */
+ render: function () {
+ if (this.entryCount > 0) {
+ for (var i = 0; i < this.entryCount; i++) {
+ this.index == i ?
+ MochiKit.DOM.addElementClass(this.getEntry(i), 'selected') :
+ MochiKit.DOM.removeElementClass(this.getEntry(i), 'selected');
+ }
+ if (this.hasFocus) {
+ this.show();
+ this.active = true;
+ }
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.markPrevious */
+ markPrevious: function () {
+ if (this.index > 0) {
+ this.index--
+ } else {
+ this.index = this.entryCount-1;
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.markNext */
+ markNext: function () {
+ if (this.index < this.entryCount-1) {
+ this.index++
+ } else {
+ this.index = 0;
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.getEntry */
+ getEntry: function (index) {
+ return this.update.firstChild.childNodes[index];
+ },
+
+/** @id Autocompleter.Base.prototype.getCurrentEntry */
+ getCurrentEntry: function () {
+ return this.getEntry(this.index);
+ },
+
+/** @id Autocompleter.Base.prototype.selectEntry */
+ selectEntry: function () {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ },
+
+/** @id Autocompleter.Base.prototype.collectTextNodesIgnoreClass */
+ collectTextNodesIgnoreClass: function (element, className) {
+ return MochiKit.Base.flattenArray(MochiKit.Base.map(function (node) {
+ if (node.nodeType == 3) {
+ return node.nodeValue;
+ } else if (node.hasChildNodes() && !MochiKit.DOM.hasElementClass(node, className)) {
+ return this.collectTextNodesIgnoreClass(node, className);
+ }
+ return '';
+ }, MochiKit.DOM.getElement(element).childNodes)).join('');
+ },
+
+/** @id Autocompleter.Base.prototype.updateElement */
+ updateElement: function (selectedElement) {
+ if (this.options.updateElement) {
+ this.options.updateElement(selectedElement);
+ return;
+ }
+ var value = '';
+ if (this.options.select) {
+ var nodes = document.getElementsByClassName(this.options.select, selectedElement) || [];
+ if (nodes.length > 0) {
+ value = MochiKit.DOM.scrapeText(nodes[0]);
+ }
+ } else {
+ value = this.collectTextNodesIgnoreClass(selectedElement, 'informal');
+ }
+ var lastTokenPos = this.findLastToken();
+ if (lastTokenPos != -1) {
+ var newValue = this.element.value.substr(0, lastTokenPos + 1);
+ var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/);
+ if (whitespace) {
+ newValue += whitespace[0];
+ }
+ this.element.value = newValue + value;
+ } else {
+ this.element.value = value;
+ }
+ this.element.focus();
+
+ if (this.options.afterUpdateElement) {
+ this.options.afterUpdateElement(this.element, selectedElement);
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.updateChoices */
+ updateChoices: function (choices) {
+ if (!this.changed && this.hasFocus) {
+ this.update.innerHTML = choices;
+ var d = MochiKit.DOM;
+ d.removeEmptyTextNodes(this.update);
+ d.removeEmptyTextNodes(this.update.firstChild);
+
+ if (this.update.firstChild && this.update.firstChild.childNodes) {
+ this.entryCount = this.update.firstChild.childNodes.length;
+ for (var i = 0; i < this.entryCount; i++) {
+ var entry = this.getEntry(i);
+ entry.autocompleteIndex = i;
+ this.addObservers(entry);
+ }
+ } else {
+ this.entryCount = 0;
+ }
+
+ this.stopIndicator();
+
+ this.index = 0;
+ this.render();
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.addObservers */
+ addObservers: function (element) {
+ MochiKit.Signal.connect(element, 'onmouseover', this, this.onHover);
+ MochiKit.Signal.connect(element, 'onclick', this, this.onClick);
+ },
+
+/** @id Autocompleter.Base.prototype.onObserverEvent */
+ onObserverEvent: function () {
+ this.changed = false;
+ if (this.getToken().length >= this.options.minChars) {
+ this.startIndicator();
+ this.getUpdatedChoices();
+ } else {
+ this.active = false;
+ this.hide();
+ }
+ },
+
+/** @id Autocompleter.Base.prototype.getToken */
+ getToken: function () {
+ var tokenPos = this.findLastToken();
+ if (tokenPos != -1) {
+ var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,'');
+ } else {
+ var ret = this.element.value;
+ }
+ return /\n/.test(ret) ? '' : ret;
+ },
+
+/** @id Autocompleter.Base.prototype.findLastToken */
+ findLastToken: function () {
+ var lastTokenPos = -1;
+
+ for (var i = 0; i < this.options.tokens.length; i++) {
+ var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]);
+ if (thisTokenPos > lastTokenPos) {
+ lastTokenPos = thisTokenPos;
+ }
+ }
+ return lastTokenPos;
+ }
+}
+
+/** @id Ajax.Autocompleter */
+Ajax.Autocompleter = function (element, update, url, options) {
+ this.__init__(element, update, url, options);
+};
+
+MochiKit.Base.update(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype);
+
+MochiKit.Base.update(Ajax.Autocompleter.prototype, {
+ __init__: function (element, update, url, options) {
+ this.baseInitialize(element, update, options);
+ this.options.asynchronous = true;
+ this.options.onComplete = MochiKit.Base.bind(this.onComplete, this);
+ this.options.defaultParams = this.options.parameters || null;
+ this.url = url;
+ },
+
+/** @id Ajax.Autocompleter.prototype.getUpdatedChoices */
+ getUpdatedChoices: function () {
+ var entry = encodeURIComponent(this.options.paramName) + '=' +
+ encodeURIComponent(this.getToken());
+
+ this.options.parameters = this.options.callback ?
+ this.options.callback(this.element, entry) : entry;
+
+ if (this.options.defaultParams) {
+ this.options.parameters += '&' + this.options.defaultParams;
+ }
+ new Ajax.Request(this.url, this.options);
+ },
+
+/** @id Ajax.Autocompleter.prototype.onComplete */
+ onComplete: function (request) {
+ this.updateChoices(request.responseText);
+ }
+});
+
+/***
+
+The local array autocompleter. Used when you'd prefer to
+inject an array of autocompletion options into the page, rather
+than sending out Ajax queries, which can be quite slow sometimes.
+
+The constructor takes four parameters. The first two are, as usual,
+the id of the monitored textbox, and id of the autocompletion menu.
+The third is the array you want to autocomplete from, and the fourth
+is the options block.
+
+Extra local autocompletion options:
+- choices - How many autocompletion choices to offer
+
+- partialSearch - If false, the autocompleter will match entered
+ text only at the beginning of strings in the
+ autocomplete array. Defaults to true, which will
+ match text at the beginning of any *word* in the
+ strings in the autocomplete array. If you want to
+ search anywhere in the string, additionally set
+ the option fullSearch to true (default: off).
+
+- fullSsearch - Search anywhere in autocomplete array strings.
+
+- partialChars - How many characters to enter before triggering
+ a partial match (unlike minChars, which defines
+ how many characters are required to do any match
+ at all). Defaults to 2.
+
+- ignoreCase - Whether to ignore case when autocompleting.
+ Defaults to true.
+
+It's possible to pass in a custom function as the 'selector'
+option, if you prefer to write your own autocompletion logic.
+In that case, the other options above will not apply unless
+you support them.
+
+***/
+
+/** @id Autocompleter.Local */
+Autocompleter.Local = function (element, update, array, options) {
+ this.__init__(element, update, array, options);
+};
+
+MochiKit.Base.update(Autocompleter.Local.prototype, Autocompleter.Base.prototype);
+
+MochiKit.Base.update(Autocompleter.Local.prototype, {
+ __init__: function (element, update, array, options) {
+ this.baseInitialize(element, update, options);
+ this.options.array = array;
+ },
+
+/** @id Autocompleter.Local.prototype.getUpdatedChoices */
+ getUpdatedChoices: function () {
+ this.updateChoices(this.options.selector(this));
+ },
+
+/** @id Autocompleter.Local.prototype.setOptions */
+ setOptions: function (options) {
+ this.options = MochiKit.Base.update({
+ choices: 10,
+ partialSearch: true,
+ partialChars: 2,
+ ignoreCase: true,
+ fullSearch: false,
+ selector: function (instance) {
+ var ret = []; // Beginning matches
+ var partial = []; // Inside matches
+ var entry = instance.getToken();
+ var count = 0;
+
+ for (var i = 0; i < instance.options.array.length &&
+ ret.length < instance.options.choices ; i++) {
+
+ var elem = instance.options.array[i];
+ var foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase()) :
+ elem.indexOf(entry);
+
+ while (foundPos != -1) {
+ if (foundPos === 0 && elem.length != entry.length) {
+ ret.push('<li><strong>' + elem.substr(0, entry.length) + '</strong>' +
+ elem.substr(entry.length) + '</li>');
+ break;
+ } else if (entry.length >= instance.options.partialChars &&
+ instance.options.partialSearch && foundPos != -1) {
+ if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos - 1, 1))) {
+ partial.push('<li>' + elem.substr(0, foundPos) + '<strong>' +
+ elem.substr(foundPos, entry.length) + '</strong>' + elem.substr(
+ foundPos + entry.length) + '</li>');
+ break;
+ }
+ }
+
+ foundPos = instance.options.ignoreCase ?
+ elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) :
+ elem.indexOf(entry, foundPos + 1);
+
+ }
+ }
+ if (partial.length) {
+ ret = ret.concat(partial.slice(0, instance.options.choices - ret.length))
+ }
+ return '<ul>' + ret.join('') + '</ul>';
+ }
+ }, options || {});
+ }
+});
+
+/***
+
+AJAX in-place editor
+
+see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor
+
+Use this if you notice weird scrolling problems on some browsers,
+the DOM might be a bit confused when this gets called so do this
+waits 1 ms (with setTimeout) until it does the activation
+
+***/
+
+/** @id Ajax.InPlaceEditor */
+Ajax.InPlaceEditor = function (element, url, options) {
+ this.__init__(element, url, options);
+};
+
+/** @id Ajax.InPlaceEditor.defaultHighlightColor */
+Ajax.InPlaceEditor.defaultHighlightColor = '#FFFF99';
+
+Ajax.InPlaceEditor.prototype = {
+ __init__: function (element, url, options) {
+ this.url = url;
+ this.element = MochiKit.DOM.getElement(element);
+
+ this.options = MochiKit.Base.update({
+ okButton: true,
+ okText: 'ok',
+ cancelLink: true,
+ cancelText: 'cancel',
+ savingText: 'Saving...',
+ clickToEditText: 'Click to edit',
+ okText: 'ok',
+ rows: 1,
+ onComplete: function (transport, element) {
+ new MochiKit.Visual.Highlight(element, {startcolor: this.options.highlightcolor});
+ },
+ onFailure: function (transport) {
+ alert('Error communicating with the server: ' + MochiKit.Base.stripTags(transport.responseText));
+ },
+ callback: function (form) {
+ return MochiKit.DOM.formContents(form);
+ },
+ handleLineBreaks: true,
+ loadingText: 'Loading...',
+ savingClassName: 'inplaceeditor-saving',
+ loadingClassName: 'inplaceeditor-loading',
+ formClassName: 'inplaceeditor-form',
+ highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor,
+ highlightendcolor: '#FFFFFF',
+ externalControl: null,
+ submitOnBlur: false,
+ ajaxOptions: {}
+ }, options || {});
+
+ if (!this.options.formId && this.element.id) {
+ this.options.formId = this.element.id + '-inplaceeditor';
+ if (MochiKit.DOM.getElement(this.options.formId)) {
+ // there's already a form with that name, don't specify an id
+ this.options.formId = null;
+ }
+ }
+
+ if (this.options.externalControl) {
+ this.options.externalControl = MochiKit.DOM.getElement(this.options.externalControl);
+ }
+
+ this.originalBackground = MochiKit.Style.getStyle(this.element, 'background-color');
+ if (!this.originalBackground) {
+ this.originalBackground = 'transparent';
+ }
+
+ this.element.title = this.options.clickToEditText;
+
+ this.onclickListener = MochiKit.Signal.connect(this.element, 'onclick', this, this.enterEditMode);
+ this.mouseoverListener = MochiKit.Signal.connect(this.element, 'onmouseover', this, this.enterHover);
+ this.mouseoutListener = MochiKit.Signal.connect(this.element, 'onmouseout', this, this.leaveHover);
+ if (this.options.externalControl) {
+ this.onclickListenerExternal = MochiKit.Signal.connect(this.options.externalControl,
+ 'onclick', this, this.enterEditMode);
+ this.mouseoverListenerExternal = MochiKit.Signal.connect(this.options.externalControl,
+ 'onmouseover', this, this.enterHover);
+ this.mouseoutListenerExternal = MochiKit.Signal.connect(this.options.externalControl,
+ 'onmouseout', this, this.leaveHover);
+ }
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.enterEditMode */
+ enterEditMode: function (evt) {
+ if (this.saving) {
+ return;
+ }
+ if (this.editing) {
+ return;
+ }
+ this.editing = true;
+ this.onEnterEditMode();
+ if (this.options.externalControl) {
+ MochiKit.Style.hideElement(this.options.externalControl);
+ }
+ MochiKit.Style.hideElement(this.element);
+ this.createForm();
+ this.element.parentNode.insertBefore(this.form, this.element);
+ Field.scrollFreeActivate(this.editField);
+ // stop the event to avoid a page refresh in Safari
+ if (evt) {
+ evt.stop();
+ }
+ return false;
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.createForm */
+ createForm: function () {
+ this.form = document.createElement('form');
+ this.form.id = this.options.formId;
+ MochiKit.DOM.addElementClass(this.form, this.options.formClassName)
+ this.form.onsubmit = MochiKit.Base.bind(this.onSubmit, this);
+
+ this.createEditField();
+
+ if (this.options.textarea) {
+ var br = document.createElement('br');
+ this.form.appendChild(br);
+ }
+
+ if (this.options.okButton) {
+ okButton = document.createElement('input');
+ okButton.type = 'submit';
+ okButton.value = this.options.okText;
+ this.form.appendChild(okButton);
+ }
+
+ if (this.options.cancelLink) {
+ cancelLink = document.createElement('a');
+ cancelLink.href = '#';
+ cancelLink.appendChild(document.createTextNode(this.options.cancelText));
+ cancelLink.onclick = MochiKit.Base.bind(this.onclickCancel, this);
+ this.form.appendChild(cancelLink);
+ }
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.hasHTMLLineBreaks */
+ hasHTMLLineBreaks: function (string) {
+ if (!this.options.handleLineBreaks) {
+ return false;
+ }
+ return string.match(/<br/i) || string.match(/<p>/i);
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.convertHTMLLineBreaks */
+ convertHTMLLineBreaks: function (string) {
+ return string.replace(/<br>/gi, '\n').replace(/<br\/>/gi, '\n').replace(/<\/p>/gi, '\n').replace(/<p>/gi, '');
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.createEditField */
+ createEditField: function () {
+ var text;
+ if (this.options.loadTextURL) {
+ text = this.options.loadingText;
+ } else {
+ text = this.getText();
+ }
+
+ var obj = this;
+
+ if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) {
+ this.options.textarea = false;
+ var textField = document.createElement('input');
+ textField.obj = this;
+ textField.type = 'text';
+ textField.name = 'value';
+ textField.value = text;
+ textField.style.backgroundColor = this.options.highlightcolor;
+ var size = this.options.size || this.options.cols || 0;
+ if (size !== 0) {
+ textField.size = size;
+ }
+ if (this.options.submitOnBlur) {
+ textField.onblur = MochiKit.Base.bind(this.onSubmit, this);
+ }
+ this.editField = textField;
+ } else {
+ this.options.textarea = true;
+ var textArea = document.createElement('textarea');
+ textArea.obj = this;
+ textArea.name = 'value';
+ textArea.value = this.convertHTMLLineBreaks(text);
+ textArea.rows = this.options.rows;
+ textArea.cols = this.options.cols || 40;
+ if (this.options.submitOnBlur) {
+ textArea.onblur = MochiKit.Base.bind(this.onSubmit, this);
+ }
+ this.editField = textArea;
+ }
+
+ if (this.options.loadTextURL) {
+ this.loadExternalText();
+ }
+ this.form.appendChild(this.editField);
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.getText */
+ getText: function () {
+ return this.element.innerHTML;
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.loadExternalText */
+ loadExternalText: function () {
+ MochiKit.DOM.addElementClass(this.form, this.options.loadingClassName);
+ this.editField.disabled = true;
+ new Ajax.Request(
+ this.options.loadTextURL,
+ MochiKit.Base.update({
+ asynchronous: true,
+ onComplete: MochiKit.Base.bind(this.onLoadedExternalText, this)
+ }, this.options.ajaxOptions)
+ );
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.onLoadedExternalText */
+ onLoadedExternalText: function (transport) {
+ MochiKit.DOM.removeElementClass(this.form, this.options.loadingClassName);
+ this.editField.disabled = false;
+ this.editField.value = MochiKit.Base.stripTags(transport);
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.onclickCancel */
+ onclickCancel: function () {
+ this.onComplete();
+ this.leaveEditMode();
+ return false;
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.onFailure */
+ onFailure: function (transport) {
+ this.options.onFailure(transport);
+ if (this.oldInnerHTML) {
+ this.element.innerHTML = this.oldInnerHTML;
+ this.oldInnerHTML = null;
+ }
+ return false;
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.onSubmit */
+ onSubmit: function () {
+ // onLoading resets these so we need to save them away for the Ajax call
+ var form = this.form;
+ var value = this.editField.value;
+
+ // do this first, sometimes the ajax call returns before we get a
+ // chance to switch on Saving which means this will actually switch on
+ // Saving *after* we have left edit mode causing Saving to be
+ // displayed indefinitely
+ this.onLoading();
+
+ new Ajax.Updater(
+ {
+ success: this.element,
+ // dont update on failure (this could be an option)
+ failure: null
+ },
+ this.url,
+ MochiKit.Base.update({
+ parameters: this.options.callback(form, value),
+ onComplete: MochiKit.Base.bind(this.onComplete, this),
+ onFailure: MochiKit.Base.bind(this.onFailure, this)
+ }, this.options.ajaxOptions)
+ );
+ // stop the event to avoid a page refresh in Safari
+ if (arguments.length > 1) {
+ arguments[0].stop();
+ }
+ return false;
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.onLoading */
+ onLoading: function () {
+ this.saving = true;
+ this.removeForm();
+ this.leaveHover();
+ this.showSaving();
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.onSaving */
+ showSaving: function () {
+ this.oldInnerHTML = this.element.innerHTML;
+ this.element.innerHTML = this.options.savingText;
+ MochiKit.DOM.addElementClass(this.element, this.options.savingClassName);
+ this.element.style.backgroundColor = this.originalBackground;
+ MochiKit.Style.showElement(this.element);
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.removeForm */
+ removeForm: function () {
+ if (this.form) {
+ if (this.form.parentNode) {
+ MochiKit.DOM.removeElement(this.form);
+ }
+ this.form = null;
+ }
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.enterHover */
+ enterHover: function () {
+ if (this.saving) {
+ return;
+ }
+ this.element.style.backgroundColor = this.options.highlightcolor;
+ if (this.effect) {
+ this.effect.cancel();
+ }
+ MochiKit.DOM.addElementClass(this.element, this.options.hoverClassName)
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.leaveHover */
+ leaveHover: function () {
+ if (this.options.backgroundColor) {
+ this.element.style.backgroundColor = this.oldBackground;
+ }
+ MochiKit.DOM.removeElementClass(this.element, this.options.hoverClassName)
+ if (this.saving) {
+ return;
+ }
+ this.effect = new MochiKit.Visual.Highlight(this.element, {
+ startcolor: this.options.highlightcolor,
+ endcolor: this.options.highlightendcolor,
+ restorecolor: this.originalBackground
+ });
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.leaveEditMode */
+ leaveEditMode: function () {
+ MochiKit.DOM.removeElementClass(this.element, this.options.savingClassName);
+ this.removeForm();
+ this.leaveHover();
+ this.element.style.backgroundColor = this.originalBackground;
+ MochiKit.Style.showElement(this.element);
+ if (this.options.externalControl) {
+ MochiKit.Style.showElement(this.options.externalControl);
+ }
+ this.editing = false;
+ this.saving = false;
+ this.oldInnerHTML = null;
+ this.onLeaveEditMode();
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.onComplete */
+ onComplete: function (transport) {
+ this.leaveEditMode();
+ MochiKit.Base.bind(this.options.onComplete, this)(transport, this.element);
+ },
+
+/** @id Ajax.InPlaceEditor.prototype.onEnterEditMode */
+ onEnterEditMode: function () {},
+
+/** @id Ajax.InPlaceEditor.prototype.onLeaveEditMode */
+ onLeaveEditMode: function () {},
+
+ /** @id Ajax.InPlaceEditor.prototype.dispose */
+ dispose: function () {
+ if (this.oldInnerHTML) {
+ this.element.innerHTML = this.oldInnerHTML;
+ }
+ this.leaveEditMode();
+ MochiKit.Signal.disconnect(this.onclickListener);
+ MochiKit.Signal.disconnect(this.mouseoverListener);
+ MochiKit.Signal.disconnect(this.mouseoutListener);
+ if (this.options.externalControl) {
+ MochiKit.Signal.disconnect(this.onclickListenerExternal);
+ MochiKit.Signal.disconnect(this.mouseoverListenerExternal);
+ MochiKit.Signal.disconnect(this.mouseoutListenerExternal);
+ }
+ }
+};
+
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/DOM.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/DOM.js
new file mode 100644
index 0000000000..02fe5bfb9c
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/DOM.js
@@ -0,0 +1,1276 @@
+/***
+
+MochiKit.DOM 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide("MochiKit.DOM");
+ dojo.require("MochiKit.Base");
+}
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.DOM depends on MochiKit.Base!";
+}
+
+if (typeof(MochiKit.DOM) == 'undefined') {
+ MochiKit.DOM = {};
+}
+
+MochiKit.DOM.NAME = "MochiKit.DOM";
+MochiKit.DOM.VERSION = "1.4";
+MochiKit.DOM.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+MochiKit.DOM.toString = function () {
+ return this.__repr__();
+};
+
+MochiKit.DOM.EXPORT = [
+ "removeEmptyTextNodes",
+ "formContents",
+ "currentWindow",
+ "currentDocument",
+ "withWindow",
+ "withDocument",
+ "registerDOMConverter",
+ "coerceToDOM",
+ "createDOM",
+ "createDOMFunc",
+ "isChildNode",
+ "getNodeAttribute",
+ "removeNodeAttribute",
+ "setNodeAttribute",
+ "updateNodeAttributes",
+ "appendChildNodes",
+ "insertSiblingNodesAfter",
+ "insertSiblingNodesBefore",
+ "replaceChildNodes",
+ "removeElement",
+ "swapDOM",
+ "BUTTON",
+ "TT",
+ "PRE",
+ "H1",
+ "H2",
+ "H3",
+ "BR",
+ "CANVAS",
+ "HR",
+ "LABEL",
+ "TEXTAREA",
+ "FORM",
+ "STRONG",
+ "SELECT",
+ "OPTION",
+ "OPTGROUP",
+ "LEGEND",
+ "FIELDSET",
+ "P",
+ "UL",
+ "OL",
+ "LI",
+ "TD",
+ "TR",
+ "THEAD",
+ "TBODY",
+ "TFOOT",
+ "TABLE",
+ "TH",
+ "INPUT",
+ "SPAN",
+ "A",
+ "DIV",
+ "IMG",
+ "getElement",
+ "$",
+ "getElementsByTagAndClassName",
+ "addToCallStack",
+ "addLoadEvent",
+ "focusOnLoad",
+ "setElementClass",
+ "toggleElementClass",
+ "addElementClass",
+ "removeElementClass",
+ "swapElementClass",
+ "hasElementClass",
+ "escapeHTML",
+ "toHTML",
+ "emitHTML",
+ "scrapeText",
+ "isParent",
+ "getFirstParentByTagAndClassName",
+ "makeClipping",
+ "undoClipping",
+ "makePositioned",
+ "undoPositioned",
+ "getFirstElementByTagAndClassName"
+];
+
+MochiKit.DOM.EXPORT_OK = [
+ "domConverters"
+];
+
+MochiKit.DOM.DEPRECATED = [
+ ['computedStyle', 'MochiKit.Style.getStyle', '1.4'],
+ /** @id MochiKit.DOM.elementDimensions */
+ ['elementDimensions', 'MochiKit.Style.getElementDimensions', '1.4'],
+ /** @id MochiKit.DOM.elementPosition */
+ ['elementPosition', 'MochiKit.Style.getElementPosition', '1.4'],
+ ['hideElement', 'MochiKit.Style.hideElement', '1.4'],
+ /** @id MochiKit.DOM.setElementDimensions */
+ ['setElementDimensions', 'MochiKit.Style.setElementDimensions', '1.4'],
+ /** @id MochiKit.DOM.setElementPosition */
+ ['setElementPosition', 'MochiKit.Style.setElementPosition', '1.4'],
+ ['setDisplayForElement', 'MochiKit.Style.setDisplayForElement', '1.4'],
+ /** @id MochiKit.DOM.setOpacity */
+ ['setOpacity', 'MochiKit.Style.setOpacity', '1.4'],
+ ['showElement', 'MochiKit.Style.showElement', '1.4'],
+ /** @id MochiKit.DOM.Coordinates */
+ ['Coordinates', 'MochiKit.Style.Coordinates', '1.4'], // FIXME: broken
+ /** @id MochiKit.DOM.Dimensions */
+ ['Dimensions', 'MochiKit.Style.Dimensions', '1.4'] // FIXME: broken
+];
+
+/** @id MochiKit.DOM.getViewportDimensions */
+MochiKit.DOM.getViewportDimensions = new Function('' +
+ 'if (!MochiKit["Style"]) {' +
+ ' throw new Error("This function has been deprecated and depends on MochiKit.Style.");' +
+ '}' +
+ 'return MochiKit.Style.getViewportDimensions.apply(this, arguments);');
+
+MochiKit.Base.update(MochiKit.DOM, {
+
+ /** @id MochiKit.DOM.currentWindow */
+ currentWindow: function () {
+ return MochiKit.DOM._window;
+ },
+
+ /** @id MochiKit.DOM.currentDocument */
+ currentDocument: function () {
+ return MochiKit.DOM._document;
+ },
+
+ /** @id MochiKit.DOM.withWindow */
+ withWindow: function (win, func) {
+ var self = MochiKit.DOM;
+ var oldDoc = self._document;
+ var oldWin = self._window;
+ var rval;
+ try {
+ self._window = win;
+ self._document = win.document;
+ rval = func();
+ } catch (e) {
+ self._window = oldWin;
+ self._document = oldDoc;
+ throw e;
+ }
+ self._window = oldWin;
+ self._document = oldDoc;
+ return rval;
+ },
+
+ /** @id MochiKit.DOM.formContents */
+ formContents: function (elem/* = document.body */) {
+ var names = [];
+ var values = [];
+ var m = MochiKit.Base;
+ var self = MochiKit.DOM;
+ if (typeof(elem) == "undefined" || elem === null) {
+ elem = self._document.body;
+ } else {
+ elem = self.getElement(elem);
+ }
+ m.nodeWalk(elem, function (elem) {
+ var name = elem.name;
+ if (m.isNotEmpty(name)) {
+ var tagName = elem.tagName.toUpperCase();
+ if (tagName === "INPUT"
+ && (elem.type == "radio" || elem.type == "checkbox")
+ && !elem.checked
+ ) {
+ return null;
+ }
+ if (tagName === "SELECT") {
+ if (elem.type == "select-one") {
+ if (elem.selectedIndex >= 0) {
+ var opt = elem.options[elem.selectedIndex];
+ var v = opt.value;
+ if (!v) {
+ var h = opt.outerHTML;
+ // internet explorer sure does suck.
+ if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
+ v = opt.text;
+ }
+ }
+ names.push(name);
+ values.push(v);
+ return null;
+ }
+ // no form elements?
+ names.push(name);
+ values.push("");
+ return null;
+ } else {
+ var opts = elem.options;
+ if (!opts.length) {
+ names.push(name);
+ values.push("");
+ return null;
+ }
+ for (var i = 0; i < opts.length; i++) {
+ var opt = opts[i];
+ if (!opt.selected) {
+ continue;
+ }
+ var v = opt.value;
+ if (!v) {
+ var h = opt.outerHTML;
+ // internet explorer sure does suck.
+ if (h && !h.match(/^[^>]+\svalue\s*=/i)) {
+ v = opt.text;
+ }
+ }
+ names.push(name);
+ values.push(v);
+ }
+ return null;
+ }
+ }
+ if (tagName === "FORM" || tagName === "P" || tagName === "SPAN"
+ || tagName === "DIV"
+ ) {
+ return elem.childNodes;
+ }
+ names.push(name);
+ values.push(elem.value || '');
+ return null;
+ }
+ return elem.childNodes;
+ });
+ return [names, values];
+ },
+
+ /** @id MochiKit.DOM.withDocument */
+ withDocument: function (doc, func) {
+ var self = MochiKit.DOM;
+ var oldDoc = self._document;
+ var rval;
+ try {
+ self._document = doc;
+ rval = func();
+ } catch (e) {
+ self._document = oldDoc;
+ throw e;
+ }
+ self._document = oldDoc;
+ return rval;
+ },
+
+ /** @id MochiKit.DOM.registerDOMConverter */
+ registerDOMConverter: function (name, check, wrap, /* optional */override) {
+ MochiKit.DOM.domConverters.register(name, check, wrap, override);
+ },
+
+ /** @id MochiKit.DOM.coerceToDOM */
+ coerceToDOM: function (node, ctx) {
+ var m = MochiKit.Base;
+ var im = MochiKit.Iter;
+ var self = MochiKit.DOM;
+ if (im) {
+ var iter = im.iter;
+ var repeat = im.repeat;
+ var map = m.map;
+ }
+ var domConverters = self.domConverters;
+ var coerceToDOM = arguments.callee;
+ var NotFound = m.NotFound;
+ while (true) {
+ if (typeof(node) == 'undefined' || node === null) {
+ return null;
+ }
+ // this is a safari childNodes object, avoiding crashes w/ attr
+ // lookup
+ if (typeof(node) == "function" &&
+ typeof(node.length) == "number" &&
+ !(node instanceof Function)) {
+ node = im.list(node);
+ }
+ if (typeof(node.nodeType) != 'undefined' && node.nodeType > 0) {
+ return node;
+ }
+ if (typeof(node) == 'number' || typeof(node) == 'boolean') {
+ node = node.toString();
+ // FALL THROUGH
+ }
+ if (typeof(node) == 'string') {
+ return self._document.createTextNode(node);
+ }
+ if (typeof(node.__dom__) == 'function') {
+ node = node.__dom__(ctx);
+ continue;
+ }
+ if (typeof(node.dom) == 'function') {
+ node = node.dom(ctx);
+ continue;
+ }
+ if (typeof(node) == 'function') {
+ node = node.apply(ctx, [ctx]);
+ continue;
+ }
+
+ if (im) {
+ // iterable
+ var iterNodes = null;
+ try {
+ iterNodes = iter(node);
+ } catch (e) {
+ // pass
+ }
+ if (iterNodes) {
+ return map(coerceToDOM, iterNodes, repeat(ctx));
+ }
+ }
+
+ // adapter
+ try {
+ node = domConverters.match(node, ctx);
+ continue;
+ } catch (e) {
+ if (e != NotFound) {
+ throw e;
+ }
+ }
+
+ // fallback
+ return self._document.createTextNode(node.toString());
+ }
+ // mozilla warnings aren't too bright
+ return undefined;
+ },
+
+ /** @id MochiKit.DOM.isChildNode */
+ isChildNode: function (node, maybeparent) {
+ var self = MochiKit.DOM;
+ if (typeof(node) == "string") {
+ node = self.getElement(node);
+ }
+ if (typeof(maybeparent) == "string") {
+ maybeparent = self.getElement(maybeparent);
+ }
+ if (node === maybeparent) {
+ return true;
+ }
+ while (node && node.tagName.toUpperCase() != "BODY") {
+ node = node.parentNode;
+ if (node === maybeparent) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /** @id MochiKit.DOM.setNodeAttribute */
+ setNodeAttribute: function (node, attr, value) {
+ var o = {};
+ o[attr] = value;
+ try {
+ return MochiKit.DOM.updateNodeAttributes(node, o);
+ } catch (e) {
+ // pass
+ }
+ return null;
+ },
+
+ /** @id MochiKit.DOM.getNodeAttribute */
+ getNodeAttribute: function (node, attr) {
+ var self = MochiKit.DOM;
+ var rename = self.attributeArray.renames[attr];
+ node = self.getElement(node);
+ try {
+ if (rename) {
+ return node[rename];
+ }
+ return node.getAttribute(attr);
+ } catch (e) {
+ // pass
+ }
+ return null;
+ },
+
+ /** @id MochiKit.DOM.removeNodeAttribute */
+ removeNodeAttribute: function (node, attr) {
+ var self = MochiKit.DOM;
+ var rename = self.attributeArray.renames[attr];
+ node = self.getElement(node);
+ try {
+ if (rename) {
+ return node[rename];
+ }
+ return node.removeAttribute(attr);
+ } catch (e) {
+ // pass
+ }
+ return null;
+ },
+
+ /** @id MochiKit.DOM.updateNodeAttributes */
+ updateNodeAttributes: function (node, attrs) {
+ var elem = node;
+ var self = MochiKit.DOM;
+ if (typeof(node) == 'string') {
+ elem = self.getElement(node);
+ }
+ if (attrs) {
+ var updatetree = MochiKit.Base.updatetree;
+ if (self.attributeArray.compliant) {
+ // not IE, good.
+ for (var k in attrs) {
+ var v = attrs[k];
+ if (typeof(v) == 'object' && typeof(elem[k]) == 'object') {
+ if (k == "style" && MochiKit.Style) {
+ MochiKit.Style.setStyle(elem, v);
+ } else {
+ updatetree(elem[k], v);
+ }
+ } else if (k.substring(0, 2) == "on") {
+ if (typeof(v) == "string") {
+ v = new Function(v);
+ }
+ elem[k] = v;
+ } else {
+ elem.setAttribute(k, v);
+ }
+ }
+ } else {
+ // IE is insane in the membrane
+ var renames = self.attributeArray.renames;
+ for (var k in attrs) {
+ v = attrs[k];
+ var renamed = renames[k];
+ if (k == "style" && typeof(v) == "string") {
+ elem.style.cssText = v;
+ } else if (typeof(renamed) == "string") {
+ elem[renamed] = v;
+ } else if (typeof(elem[k]) == 'object'
+ && typeof(v) == 'object') {
+ if (k == "style" && MochiKit.Style) {
+ MochiKit.Style.setStyle(elem, v);
+ } else {
+ updatetree(elem[k], v);
+ }
+ } else if (k.substring(0, 2) == "on") {
+ if (typeof(v) == "string") {
+ v = new Function(v);
+ }
+ elem[k] = v;
+ } else {
+ elem.setAttribute(k, v);
+ }
+ }
+ }
+ }
+ return elem;
+ },
+
+ /** @id MochiKit.DOM.appendChildNodes */
+ appendChildNodes: function (node/*, nodes...*/) {
+ var elem = node;
+ var self = MochiKit.DOM;
+ if (typeof(node) == 'string') {
+ elem = self.getElement(node);
+ }
+ var nodeStack = [
+ self.coerceToDOM(
+ MochiKit.Base.extend(null, arguments, 1),
+ elem
+ )
+ ];
+ var concat = MochiKit.Base.concat;
+ while (nodeStack.length) {
+ var n = nodeStack.shift();
+ if (typeof(n) == 'undefined' || n === null) {
+ // pass
+ } else if (typeof(n.nodeType) == 'number') {
+ elem.appendChild(n);
+ } else {
+ nodeStack = concat(n, nodeStack);
+ }
+ }
+ return elem;
+ },
+
+
+ /** @id MochiKit.DOM.insertSiblingNodesBefore */
+ insertSiblingNodesBefore: function (node/*, nodes...*/) {
+ var elem = node;
+ var self = MochiKit.DOM;
+ if (typeof(node) == 'string') {
+ elem = self.getElement(node);
+ }
+ var nodeStack = [
+ self.coerceToDOM(
+ MochiKit.Base.extend(null, arguments, 1),
+ elem
+ )
+ ];
+ var parentnode = elem.parentNode;
+ var concat = MochiKit.Base.concat;
+ while (nodeStack.length) {
+ var n = nodeStack.shift();
+ if (typeof(n) == 'undefined' || n === null) {
+ // pass
+ } else if (typeof(n.nodeType) == 'number') {
+ parentnode.insertBefore(n, elem);
+ } else {
+ nodeStack = concat(n, nodeStack);
+ }
+ }
+ return parentnode;
+ },
+
+ /** @id MochiKit.DOM.insertSiblingNodesAfter */
+ insertSiblingNodesAfter: function (node/*, nodes...*/) {
+ var elem = node;
+ var self = MochiKit.DOM;
+
+ if (typeof(node) == 'string') {
+ elem = self.getElement(node);
+ }
+ var nodeStack = [
+ self.coerceToDOM(
+ MochiKit.Base.extend(null, arguments, 1),
+ elem
+ )
+ ];
+
+ if (elem.nextSibling) {
+ return self.insertSiblingNodesBefore(elem.nextSibling, nodeStack);
+ }
+ else {
+ return self.appendChildNodes(elem.parentNode, nodeStack);
+ }
+ },
+
+ /** @id MochiKit.DOM.replaceChildNodes */
+ replaceChildNodes: function (node/*, nodes...*/) {
+ var elem = node;
+ var self = MochiKit.DOM;
+ if (typeof(node) == 'string') {
+ elem = self.getElement(node);
+ arguments[0] = elem;
+ }
+ var child;
+ while ((child = elem.firstChild)) {
+ elem.removeChild(child);
+ }
+ if (arguments.length < 2) {
+ return elem;
+ } else {
+ return self.appendChildNodes.apply(this, arguments);
+ }
+ },
+
+ /** @id MochiKit.DOM.createDOM */
+ createDOM: function (name, attrs/*, nodes... */) {
+ var elem;
+ var self = MochiKit.DOM;
+ var m = MochiKit.Base;
+ if (typeof(attrs) == "string" || typeof(attrs) == "number") {
+ var args = m.extend([name, null], arguments, 1);
+ return arguments.callee.apply(this, args);
+ }
+ if (typeof(name) == 'string') {
+ // Internet Explorer is dumb
+ var xhtml = self._xhtml;
+ if (attrs && !self.attributeArray.compliant) {
+ // http://msdn.microsoft.com/workshop/author/dhtml/reference/properties/name_2.asp
+ var contents = "";
+ if ('name' in attrs) {
+ contents += ' name="' + self.escapeHTML(attrs.name) + '"';
+ }
+ if (name == 'input' && 'type' in attrs) {
+ contents += ' type="' + self.escapeHTML(attrs.type) + '"';
+ }
+ if (contents) {
+ name = "<" + name + contents + ">";
+ xhtml = false;
+ }
+ }
+ var d = self._document;
+ if (xhtml && d === document) {
+ elem = d.createElementNS("http://www.w3.org/1999/xhtml", name);
+ } else {
+ elem = d.createElement(name);
+ }
+ } else {
+ elem = name;
+ }
+ if (attrs) {
+ self.updateNodeAttributes(elem, attrs);
+ }
+ if (arguments.length <= 2) {
+ return elem;
+ } else {
+ var args = m.extend([elem], arguments, 2);
+ return self.appendChildNodes.apply(this, args);
+ }
+ },
+
+ /** @id MochiKit.DOM.createDOMFunc */
+ createDOMFunc: function (/* tag, attrs, *nodes */) {
+ var m = MochiKit.Base;
+ return m.partial.apply(
+ this,
+ m.extend([MochiKit.DOM.createDOM], arguments)
+ );
+ },
+
+ /** @id MochiKit.DOM.removeElement */
+ removeElement: function (elem) {
+ var e = MochiKit.DOM.getElement(elem);
+ e.parentNode.removeChild(e);
+ return e;
+ },
+
+ /** @id MochiKit.DOM.swapDOM */
+ swapDOM: function (dest, src) {
+ var self = MochiKit.DOM;
+ dest = self.getElement(dest);
+ var parent = dest.parentNode;
+ if (src) {
+ src = self.getElement(src);
+ parent.replaceChild(src, dest);
+ } else {
+ parent.removeChild(dest);
+ }
+ return src;
+ },
+
+ /** @id MochiKit.DOM.getElement */
+ getElement: function (id) {
+ var self = MochiKit.DOM;
+ if (arguments.length == 1) {
+ return ((typeof(id) == "string") ?
+ self._document.getElementById(id) : id);
+ } else {
+ return MochiKit.Base.map(self.getElement, arguments);
+ }
+ },
+
+ /** @id MochiKit.DOM.getElementsByTagAndClassName */
+ getElementsByTagAndClassName: function (tagName, className,
+ /* optional */parent) {
+ var self = MochiKit.DOM;
+ if (typeof(tagName) == 'undefined' || tagName === null) {
+ tagName = '*';
+ }
+ if (typeof(parent) == 'undefined' || parent === null) {
+ parent = self._document;
+ }
+ parent = self.getElement(parent);
+ var children = (parent.getElementsByTagName(tagName)
+ || self._document.all);
+ if (typeof(className) == 'undefined' || className === null) {
+ return MochiKit.Base.extend(null, children);
+ }
+
+ var elements = [];
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ var cls = child.className;
+ if (!cls) {
+ continue;
+ }
+ var classNames = cls.split(' ');
+ for (var j = 0; j < classNames.length; j++) {
+ if (classNames[j] == className) {
+ elements.push(child);
+ break;
+ }
+ }
+ }
+
+ return elements;
+ },
+
+ _newCallStack: function (path, once) {
+ var rval = function () {
+ var callStack = arguments.callee.callStack;
+ for (var i = 0; i < callStack.length; i++) {
+ if (callStack[i].apply(this, arguments) === false) {
+ break;
+ }
+ }
+ if (once) {
+ try {
+ this[path] = null;
+ } catch (e) {
+ // pass
+ }
+ }
+ };
+ rval.callStack = [];
+ return rval;
+ },
+
+ /** @id MochiKit.DOM.addToCallStack */
+ addToCallStack: function (target, path, func, once) {
+ var self = MochiKit.DOM;
+ var existing = target[path];
+ var regfunc = existing;
+ if (!(typeof(existing) == 'function'
+ && typeof(existing.callStack) == "object"
+ && existing.callStack !== null)) {
+ regfunc = self._newCallStack(path, once);
+ if (typeof(existing) == 'function') {
+ regfunc.callStack.push(existing);
+ }
+ target[path] = regfunc;
+ }
+ regfunc.callStack.push(func);
+ },
+
+ /** @id MochiKit.DOM.addLoadEvent */
+ addLoadEvent: function (func) {
+ var self = MochiKit.DOM;
+ self.addToCallStack(self._window, "onload", func, true);
+
+ },
+
+ /** @id MochiKit.DOM.focusOnLoad */
+ focusOnLoad: function (element) {
+ var self = MochiKit.DOM;
+ self.addLoadEvent(function () {
+ element = self.getElement(element);
+ if (element) {
+ element.focus();
+ }
+ });
+ },
+
+ /** @id MochiKit.DOM.setElementClass */
+ setElementClass: function (element, className) {
+ var self = MochiKit.DOM;
+ var obj = self.getElement(element);
+ if (self.attributeArray.compliant) {
+ obj.setAttribute("class", className);
+ } else {
+ obj.setAttribute("className", className);
+ }
+ },
+
+ /** @id MochiKit.DOM.toggleElementClass */
+ toggleElementClass: function (className/*, element... */) {
+ var self = MochiKit.DOM;
+ for (var i = 1; i < arguments.length; i++) {
+ var obj = self.getElement(arguments[i]);
+ if (!self.addElementClass(obj, className)) {
+ self.removeElementClass(obj, className);
+ }
+ }
+ },
+
+ /** @id MochiKit.DOM.addElementClass */
+ addElementClass: function (element, className) {
+ var self = MochiKit.DOM;
+ var obj = self.getElement(element);
+ var cls = obj.className;
+ // trivial case, no className yet
+ if (cls == undefined || cls.length === 0) {
+ self.setElementClass(obj, className);
+ return true;
+ }
+ // the other trivial case, already set as the only class
+ if (cls == className) {
+ return false;
+ }
+ var classes = cls.split(" ");
+ for (var i = 0; i < classes.length; i++) {
+ // already present
+ if (classes[i] == className) {
+ return false;
+ }
+ }
+ // append class
+ self.setElementClass(obj, cls + " " + className);
+ return true;
+ },
+
+ /** @id MochiKit.DOM.removeElementClass */
+ removeElementClass: function (element, className) {
+ var self = MochiKit.DOM;
+ var obj = self.getElement(element);
+ var cls = obj.className;
+ // trivial case, no className yet
+ if (cls == undefined || cls.length === 0) {
+ return false;
+ }
+ // other trivial case, set only to className
+ if (cls == className) {
+ self.setElementClass(obj, "");
+ return true;
+ }
+ var classes = cls.split(" ");
+ for (var i = 0; i < classes.length; i++) {
+ // already present
+ if (classes[i] == className) {
+ // only check sane case where the class is used once
+ classes.splice(i, 1);
+ self.setElementClass(obj, classes.join(" "));
+ return true;
+ }
+ }
+ // not found
+ return false;
+ },
+
+ /** @id MochiKit.DOM.swapElementClass */
+ swapElementClass: function (element, fromClass, toClass) {
+ var obj = MochiKit.DOM.getElement(element);
+ var res = MochiKit.DOM.removeElementClass(obj, fromClass);
+ if (res) {
+ MochiKit.DOM.addElementClass(obj, toClass);
+ }
+ return res;
+ },
+
+ /** @id MochiKit.DOM.hasElementClass */
+ hasElementClass: function (element, className/*...*/) {
+ var obj = MochiKit.DOM.getElement(element);
+ var cls = obj.className;
+ if (!cls) {
+ return false;
+ }
+ var classes = cls.split(" ");
+ for (var i = 1; i < arguments.length; i++) {
+ var good = false;
+ for (var j = 0; j < classes.length; j++) {
+ if (classes[j] == arguments[i]) {
+ good = true;
+ break;
+ }
+ }
+ if (!good) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /** @id MochiKit.DOM.escapeHTML */
+ escapeHTML: function (s) {
+ return s.replace(/&/g, "&amp;"
+ ).replace(/"/g, "&quot;"
+ ).replace(/</g, "&lt;"
+ ).replace(/>/g, "&gt;");
+ },
+
+ /** @id MochiKit.DOM.toHTML */
+ toHTML: function (dom) {
+ return MochiKit.DOM.emitHTML(dom).join("");
+ },
+
+ /** @id MochiKit.DOM.emitHTML */
+ emitHTML: function (dom, /* optional */lst) {
+ if (typeof(lst) == 'undefined' || lst === null) {
+ lst = [];
+ }
+ // queue is the call stack, we're doing this non-recursively
+ var queue = [dom];
+ var self = MochiKit.DOM;
+ var escapeHTML = self.escapeHTML;
+ var attributeArray = self.attributeArray;
+ while (queue.length) {
+ dom = queue.pop();
+ if (typeof(dom) == 'string') {
+ lst.push(dom);
+ } else if (dom.nodeType == 1) {
+ // we're not using higher order stuff here
+ // because safari has heisenbugs.. argh.
+ //
+ // I think it might have something to do with
+ // garbage collection and function calls.
+ lst.push('<' + dom.tagName.toLowerCase());
+ var attributes = [];
+ var domAttr = attributeArray(dom);
+ for (var i = 0; i < domAttr.length; i++) {
+ var a = domAttr[i];
+ attributes.push([
+ " ",
+ a.name,
+ '="',
+ escapeHTML(a.value),
+ '"'
+ ]);
+ }
+ attributes.sort();
+ for (i = 0; i < attributes.length; i++) {
+ var attrs = attributes[i];
+ for (var j = 0; j < attrs.length; j++) {
+ lst.push(attrs[j]);
+ }
+ }
+ if (dom.hasChildNodes()) {
+ lst.push(">");
+ // queue is the FILO call stack, so we put the close tag
+ // on first
+ queue.push("</" + dom.tagName.toLowerCase() + ">");
+ var cnodes = dom.childNodes;
+ for (i = cnodes.length - 1; i >= 0; i--) {
+ queue.push(cnodes[i]);
+ }
+ } else {
+ lst.push('/>');
+ }
+ } else if (dom.nodeType == 3) {
+ lst.push(escapeHTML(dom.nodeValue));
+ }
+ }
+ return lst;
+ },
+
+ /** @id MochiKit.DOM.scrapeText */
+ scrapeText: function (node, /* optional */asArray) {
+ var rval = [];
+ (function (node) {
+ var cn = node.childNodes;
+ if (cn) {
+ for (var i = 0; i < cn.length; i++) {
+ arguments.callee.call(this, cn[i]);
+ }
+ }
+ var nodeValue = node.nodeValue;
+ if (typeof(nodeValue) == 'string') {
+ rval.push(nodeValue);
+ }
+ })(MochiKit.DOM.getElement(node));
+ if (asArray) {
+ return rval;
+ } else {
+ return rval.join("");
+ }
+ },
+
+ /** @id MochiKit.DOM.removeEmptyTextNodes */
+ removeEmptyTextNodes: function (element) {
+ element = MochiKit.DOM.getElement(element);
+ for (var i = 0; i < element.childNodes.length; i++) {
+ var node = element.childNodes[i];
+ if (node.nodeType == 3 && !/\S/.test(node.nodeValue)) {
+ node.parentNode.removeChild(node);
+ }
+ }
+ },
+
+ /** @id MochiKit.DOM.makeClipping */
+ makeClipping: function (element) {
+ element = MochiKit.DOM.getElement(element);
+ var oldOverflow = element.style.overflow;
+ if ((MochiKit.Style.getStyle(element, 'overflow') || 'visible') != 'hidden') {
+ element.style.overflow = 'hidden';
+ }
+ return oldOverflow;
+ },
+
+ /** @id MochiKit.DOM.undoClipping */
+ undoClipping: function (element, overflow) {
+ element = MochiKit.DOM.getElement(element);
+ if (!overflow) {
+ return;
+ }
+ element.style.overflow = overflow;
+ },
+
+ /** @id MochiKit.DOM.makePositioned */
+ makePositioned: function (element) {
+ element = MochiKit.DOM.getElement(element);
+ var pos = MochiKit.Style.getStyle(element, 'position');
+ if (pos == 'static' || !pos) {
+ element.style.position = 'relative';
+ // Opera returns the offset relative to the positioning context,
+ // when an element is position relative but top and left have
+ // not been defined
+ if (/Opera/.test(navigator.userAgent)) {
+ element.style.top = 0;
+ element.style.left = 0;
+ }
+ }
+ },
+
+ /** @id MochiKit.DOM.undoPositioned */
+ undoPositioned: function (element) {
+ element = MochiKit.DOM.getElement(element);
+ if (element.style.position == 'relative') {
+ element.style.position = element.style.top = element.style.left = element.style.bottom = element.style.right = '';
+ }
+ },
+
+ /** @id MochiKit.DOM.getFirstElementByTagAndClassName */
+ getFirstElementByTagAndClassName: function (tagName, className,
+ /* optional */parent) {
+ var self = MochiKit.DOM;
+ if (typeof(tagName) == 'undefined' || tagName === null) {
+ tagName = '*';
+ }
+ if (typeof(parent) == 'undefined' || parent === null) {
+ parent = self._document;
+ }
+ parent = self.getElement(parent);
+ var children = (parent.getElementsByTagName(tagName)
+ || self._document.all);
+ if (typeof(className) == 'undefined' || className === null) {
+ return children[0];
+ }
+
+ for (var i = 0; i < children.length; i++) {
+ var child = children[i];
+ var classNames = child.className.split(' ');
+ for (var j = 0; j < classNames.length; j++) {
+ if (classNames[j] == className) {
+ return child;
+ }
+ }
+ }
+ },
+
+ /** @id MochiKit.DOM.getFirstParentByTagAndClassName */
+ getFirstParentByTagAndClassName: function (elem, tagName, className) {
+ var self = MochiKit.DOM;
+ elem = self.getElement(elem);
+ if (typeof(tagName) == 'undefined' || tagName === null) {
+ tagName = '*';
+ } else {
+ tagName = tagName.toUpperCase();
+ }
+ if (typeof(className) == 'undefined' || className === null) {
+ className = null;
+ }
+
+ var classList = '';
+ var curTagName = '';
+ while (elem && elem.tagName) {
+ elem = elem.parentNode;
+ if (tagName == '*' && className === null) {
+ return elem;
+ }
+ classList = elem.className.split(' ');
+ curTagName = elem.tagName.toUpperCase();
+ if (className === null && tagName == curTagName) {
+ return elem;
+ } else if (className !== null) {
+ for (var i = 0; i < classList.length; i++) {
+ if (tagName == '*' && classList[i] == className) {
+ return elem;
+ } else if (tagName == curTagName && classList[i] == className) {
+ return elem;
+ }
+ }
+ }
+ }
+ return elem;
+ },
+
+ /** @id MochiKit.DOM.isParent */
+ isParent: function (child, element) {
+ if (!child.parentNode || child == element) {
+ return false;
+ }
+
+ if (child.parentNode == element) {
+ return true;
+ }
+
+ return MochiKit.DOM.isParent(child.parentNode, element);
+ },
+
+ __new__: function (win) {
+
+ var m = MochiKit.Base;
+ if (typeof(document) != "undefined") {
+ this._document = document;
+ var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+ this._xhtml = (document.documentElement &&
+ document.createElementNS &&
+ document.documentElement.namespaceURI === kXULNSURI);
+ } else if (MochiKit.MockDOM) {
+ this._document = MochiKit.MockDOM.document;
+ }
+ this._window = win;
+
+ this.domConverters = new m.AdapterRegistry();
+
+ var __tmpElement = this._document.createElement("span");
+ var attributeArray;
+ if (__tmpElement && __tmpElement.attributes &&
+ __tmpElement.attributes.length > 0) {
+ // for braindead browsers (IE) that insert extra junk
+ var filter = m.filter;
+ attributeArray = function (node) {
+ return filter(attributeArray.ignoreAttrFilter, node.attributes);
+ };
+ attributeArray.ignoreAttr = {};
+ var attrs = __tmpElement.attributes;
+ var ignoreAttr = attributeArray.ignoreAttr;
+ for (var i = 0; i < attrs.length; i++) {
+ var a = attrs[i];
+ ignoreAttr[a.name] = a.value;
+ }
+ attributeArray.ignoreAttrFilter = function (a) {
+ return (attributeArray.ignoreAttr[a.name] != a.value);
+ };
+ attributeArray.compliant = false;
+ attributeArray.renames = {
+ "class": "className",
+ "checked": "defaultChecked",
+ "usemap": "useMap",
+ "for": "htmlFor",
+ "readonly": "readOnly",
+ "colspan": "colSpan",
+ "bgcolor": "bgColor",
+ "cellspacing": "cellSpacing",
+ "cellpadding": "cellPadding"
+ };
+ } else {
+ attributeArray = function (node) {
+ /***
+
+ Return an array of attributes for a given node,
+ filtering out attributes that don't belong for
+ that are inserted by "Certain Browsers".
+
+ ***/
+ return node.attributes;
+ };
+ attributeArray.compliant = true;
+ attributeArray.renames = {};
+ }
+ this.attributeArray = attributeArray;
+
+ // FIXME: this really belongs in Base, and could probably be cleaner
+ var _deprecated = function(fromModule, arr) {
+ var modules = arr[1].split('.');
+ var str = '';
+ var obj = {};
+
+ str += 'if (!MochiKit.' + modules[1] + ') { throw new Error("';
+ str += 'This function has been deprecated and depends on MochiKit.';
+ str += modules[1] + '.");}';
+ str += 'return MochiKit.' + modules[1] + '.' + arr[0];
+ str += '.apply(this, arguments);';
+
+ obj[modules[2]] = new Function(str);
+ MochiKit.Base.update(MochiKit[fromModule], obj);
+ }
+ for (var i; i < MochiKit.DOM.DEPRECATED.length; i++) {
+ _deprecated('DOM', MochiKit.DOM.DEPRECATED[i]);
+ }
+
+ // shorthand for createDOM syntax
+ var createDOMFunc = this.createDOMFunc;
+ /** @id MochiKit.DOM.UL */
+ this.UL = createDOMFunc("ul");
+ /** @id MochiKit.DOM.OL */
+ this.OL = createDOMFunc("ol");
+ /** @id MochiKit.DOM.LI */
+ this.LI = createDOMFunc("li");
+ /** @id MochiKit.DOM.TD */
+ this.TD = createDOMFunc("td");
+ /** @id MochiKit.DOM.TR */
+ this.TR = createDOMFunc("tr");
+ /** @id MochiKit.DOM.TBODY */
+ this.TBODY = createDOMFunc("tbody");
+ /** @id MochiKit.DOM.THEAD */
+ this.THEAD = createDOMFunc("thead");
+ /** @id MochiKit.DOM.TFOOT */
+ this.TFOOT = createDOMFunc("tfoot");
+ /** @id MochiKit.DOM.TABLE */
+ this.TABLE = createDOMFunc("table");
+ /** @id MochiKit.DOM.TH */
+ this.TH = createDOMFunc("th");
+ /** @id MochiKit.DOM.INPUT */
+ this.INPUT = createDOMFunc("input");
+ /** @id MochiKit.DOM.SPAN */
+ this.SPAN = createDOMFunc("span");
+ /** @id MochiKit.DOM.A */
+ this.A = createDOMFunc("a");
+ /** @id MochiKit.DOM.DIV */
+ this.DIV = createDOMFunc("div");
+ /** @id MochiKit.DOM.IMG */
+ this.IMG = createDOMFunc("img");
+ /** @id MochiKit.DOM.BUTTON */
+ this.BUTTON = createDOMFunc("button");
+ /** @id MochiKit.DOM.TT */
+ this.TT = createDOMFunc("tt");
+ /** @id MochiKit.DOM.PRE */
+ this.PRE = createDOMFunc("pre");
+ /** @id MochiKit.DOM.H1 */
+ this.H1 = createDOMFunc("h1");
+ /** @id MochiKit.DOM.H2 */
+ this.H2 = createDOMFunc("h2");
+ /** @id MochiKit.DOM.H3 */
+ this.H3 = createDOMFunc("h3");
+ /** @id MochiKit.DOM.BR */
+ this.BR = createDOMFunc("br");
+ /** @id MochiKit.DOM.HR */
+ this.HR = createDOMFunc("hr");
+ /** @id MochiKit.DOM.LABEL */
+ this.LABEL = createDOMFunc("label");
+ /** @id MochiKit.DOM.TEXTAREA */
+ this.TEXTAREA = createDOMFunc("textarea");
+ /** @id MochiKit.DOM.FORM */
+ this.FORM = createDOMFunc("form");
+ /** @id MochiKit.DOM.P */
+ this.P = createDOMFunc("p");
+ /** @id MochiKit.DOM.SELECT */
+ this.SELECT = createDOMFunc("select");
+ /** @id MochiKit.DOM.OPTION */
+ this.OPTION = createDOMFunc("option");
+ /** @id MochiKit.DOM.OPTGROUP */
+ this.OPTGROUP = createDOMFunc("optgroup");
+ /** @id MochiKit.DOM.LEGEND */
+ this.LEGEND = createDOMFunc("legend");
+ /** @id MochiKit.DOM.FIELDSET */
+ this.FIELDSET = createDOMFunc("fieldset");
+ /** @id MochiKit.DOM.STRONG */
+ this.STRONG = createDOMFunc("strong");
+ /** @id MochiKit.DOM.CANVAS */
+ this.CANVAS = createDOMFunc("canvas");
+
+ /** @id MochiKit.DOM.$ */
+ this.$ = this.getElement;
+
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ m.nameFunctions(this);
+
+ }
+});
+
+
+MochiKit.DOM.__new__(((typeof(window) == "undefined") ? this : window));
+
+//
+// XXX: Internet Explorer blows
+//
+if (MochiKit.__export__) {
+ withWindow = MochiKit.DOM.withWindow;
+ withDocument = MochiKit.DOM.withDocument;
+}
+
+MochiKit.Base._exportSymbols(this, MochiKit.DOM);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/DateTime.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/DateTime.js
new file mode 100644
index 0000000000..c0b03ee9db
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/DateTime.js
@@ -0,0 +1,216 @@
+/***
+
+MochiKit.DateTime 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.DateTime');
+}
+
+if (typeof(MochiKit) == 'undefined') {
+ MochiKit = {};
+}
+
+if (typeof(MochiKit.DateTime) == 'undefined') {
+ MochiKit.DateTime = {};
+}
+
+MochiKit.DateTime.NAME = "MochiKit.DateTime";
+MochiKit.DateTime.VERSION = "1.4";
+MochiKit.DateTime.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+MochiKit.DateTime.toString = function () {
+ return this.__repr__();
+};
+
+/** @id MochiKit.DateTime.isoDate */
+MochiKit.DateTime.isoDate = function (str) {
+ str = str + "";
+ if (typeof(str) != "string" || str.length === 0) {
+ return null;
+ }
+ var iso = str.split('-');
+ if (iso.length === 0) {
+ return null;
+ }
+ return new Date(iso[0], iso[1] - 1, iso[2]);
+};
+
+MochiKit.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}))?)?)?)?)?/;
+
+/** @id MochiKit.DateTime.isoTimestamp */
+MochiKit.DateTime.isoTimestamp = function (str) {
+ str = str + "";
+ if (typeof(str) != "string" || str.length === 0) {
+ return null;
+ }
+ var res = str.match(MochiKit.DateTime._isoRegexp);
+ if (typeof(res) == "undefined" || res === null) {
+ return null;
+ }
+ var year, month, day, hour, min, sec, msec;
+ year = parseInt(res[1], 10);
+ if (typeof(res[2]) == "undefined" || res[2] === '') {
+ return new Date(year);
+ }
+ month = parseInt(res[2], 10) - 1;
+ day = parseInt(res[3], 10);
+ if (typeof(res[4]) == "undefined" || res[4] === '') {
+ return new Date(year, month, day);
+ }
+ hour = parseInt(res[4], 10);
+ min = parseInt(res[5], 10);
+ sec = (typeof(res[6]) != "undefined" && res[6] !== '') ? parseInt(res[6], 10) : 0;
+ if (typeof(res[7]) != "undefined" && res[7] !== '') {
+ msec = Math.round(1000.0 * parseFloat("0." + res[7]));
+ } else {
+ msec = 0;
+ }
+ if ((typeof(res[8]) == "undefined" || res[8] === '') && (typeof(res[9]) == "undefined" || res[9] === '')) {
+ return new Date(year, month, day, hour, min, sec, msec);
+ }
+ var ofs;
+ if (typeof(res[9]) != "undefined" && res[9] !== '') {
+ ofs = parseInt(res[10], 10) * 3600000;
+ if (typeof(res[11]) != "undefined" && res[11] !== '') {
+ ofs += parseInt(res[11], 10) * 60000;
+ }
+ if (res[9] == "-") {
+ ofs = -ofs;
+ }
+ } else {
+ ofs = 0;
+ }
+ return new Date(Date.UTC(year, month, day, hour, min, sec, msec) - ofs);
+};
+
+/** @id MochiKit.DateTime.toISOTime */
+MochiKit.DateTime.toISOTime = function (date, realISO/* = false */) {
+ if (typeof(date) == "undefined" || date === null) {
+ return null;
+ }
+ var hh = date.getHours();
+ var mm = date.getMinutes();
+ var ss = date.getSeconds();
+ var lst = [
+ ((realISO && (hh < 10)) ? "0" + hh : hh),
+ ((mm < 10) ? "0" + mm : mm),
+ ((ss < 10) ? "0" + ss : ss)
+ ];
+ return lst.join(":");
+};
+
+/** @id MochiKit.DateTime.toISOTimeStamp */
+MochiKit.DateTime.toISOTimestamp = function (date, realISO/* = false*/) {
+ if (typeof(date) == "undefined" || date === null) {
+ return null;
+ }
+ var sep = realISO ? "T" : " ";
+ var foot = realISO ? "Z" : "";
+ if (realISO) {
+ date = new Date(date.getTime() + (date.getTimezoneOffset() * 60000));
+ }
+ return MochiKit.DateTime.toISODate(date) + sep + MochiKit.DateTime.toISOTime(date, realISO) + foot;
+};
+
+/** @id MochiKit.DateTime.toISODate */
+MochiKit.DateTime.toISODate = function (date) {
+ if (typeof(date) == "undefined" || date === null) {
+ return null;
+ }
+ var _padTwo = MochiKit.DateTime._padTwo;
+ return [
+ date.getFullYear(),
+ _padTwo(date.getMonth() + 1),
+ _padTwo(date.getDate())
+ ].join("-");
+};
+
+/** @id MochiKit.DateTime.americanDate */
+MochiKit.DateTime.americanDate = function (d) {
+ d = d + "";
+ if (typeof(d) != "string" || d.length === 0) {
+ return null;
+ }
+ var a = d.split('/');
+ return new Date(a[2], a[0] - 1, a[1]);
+};
+
+MochiKit.DateTime._padTwo = function (n) {
+ return (n > 9) ? n : "0" + n;
+};
+
+/** @id MochiKit.DateTime.toPaddedAmericanDate */
+MochiKit.DateTime.toPaddedAmericanDate = function (d) {
+ if (typeof(d) == "undefined" || d === null) {
+ return null;
+ }
+ var _padTwo = MochiKit.DateTime._padTwo;
+ return [
+ _padTwo(d.getMonth() + 1),
+ _padTwo(d.getDate()),
+ d.getFullYear()
+ ].join('/');
+};
+
+/** @id MochiKit.DateTime.toAmericanDate */
+MochiKit.DateTime.toAmericanDate = function (d) {
+ if (typeof(d) == "undefined" || d === null) {
+ return null;
+ }
+ return [d.getMonth() + 1, d.getDate(), d.getFullYear()].join('/');
+};
+
+MochiKit.DateTime.EXPORT = [
+ "isoDate",
+ "isoTimestamp",
+ "toISOTime",
+ "toISOTimestamp",
+ "toISODate",
+ "americanDate",
+ "toPaddedAmericanDate",
+ "toAmericanDate"
+];
+
+MochiKit.DateTime.EXPORT_OK = [];
+MochiKit.DateTime.EXPORT_TAGS = {
+ ":common": MochiKit.DateTime.EXPORT,
+ ":all": MochiKit.DateTime.EXPORT
+};
+
+MochiKit.DateTime.__new__ = function () {
+ // MochiKit.Base.nameFunctions(this);
+ var base = this.NAME + ".";
+ for (var k in this) {
+ var o = this[k];
+ if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
+ try {
+ o.NAME = base + k;
+ } catch (e) {
+ // pass
+ }
+ }
+ }
+};
+
+MochiKit.DateTime.__new__();
+
+if (typeof(MochiKit.Base) != "undefined") {
+ MochiKit.Base._exportSymbols(this, MochiKit.DateTime);
+} else {
+ (function (globals, module) {
+ if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
+ || (MochiKit.__export__ === false)) {
+ var all = module.EXPORT_TAGS[":all"];
+ for (var i = 0; i < all.length; i++) {
+ globals[all[i]] = module[all[i]];
+ }
+ }
+ })(this, MochiKit.DateTime);
+}
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/DragAndDrop.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/DragAndDrop.js
new file mode 100644
index 0000000000..c471ffe900
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/DragAndDrop.js
@@ -0,0 +1,824 @@
+/***
+MochiKit.DragAndDrop 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+ Mochi-ized By Thomas Herve (_firstname_@nimail.org)
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.DragAndDrop');
+ dojo.require('MochiKit.Base');
+ dojo.require('MochiKit.DOM');
+ dojo.require('MochiKit.Iter');
+ dojo.require('MochiKit.Visual');
+ dojo.require('MochiKit.Signal');
+}
+
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+ JSAN.use("MochiKit.DOM", []);
+ JSAN.use("MochiKit.Visual", []);
+ JSAN.use("MochiKit.Iter", []);
+ JSAN.use("MochiKit.Signal", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined' ||
+ typeof(MochiKit.DOM) == 'undefined' ||
+ typeof(MochiKit.Visual) == 'undefined' ||
+ typeof(MochiKit.Signal) == 'undefined' ||
+ typeof(MochiKit.Iter) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM, MochiKit.Visual, MochiKit.Signal and MochiKit.Iter!";
+}
+
+if (typeof(MochiKit.DragAndDrop) == 'undefined') {
+ MochiKit.DragAndDrop = {};
+}
+
+MochiKit.DragAndDrop.NAME = 'MochiKit.DragAndDrop';
+MochiKit.DragAndDrop.VERSION = '1.4';
+
+MochiKit.DragAndDrop.__repr__ = function () {
+ return '[' + this.NAME + ' ' + this.VERSION + ']';
+};
+
+MochiKit.DragAndDrop.toString = function () {
+ return this.__repr__();
+};
+
+MochiKit.DragAndDrop.EXPORT = [
+ "Droppable",
+ "Draggable"
+];
+
+MochiKit.DragAndDrop.EXPORT_OK = [
+ "Droppables",
+ "Draggables"
+];
+
+MochiKit.DragAndDrop.Droppables = {
+ /***
+
+ Manage all droppables. Shouldn't be used, use the Droppable object instead.
+
+ ***/
+ drops: [],
+
+ remove: function (element) {
+ this.drops = MochiKit.Base.filter(function (d) {
+ return d.element != MochiKit.DOM.getElement(element);
+ }, this.drops);
+ },
+
+ register: function (drop) {
+ this.drops.push(drop);
+ },
+
+ unregister: function (drop) {
+ this.drops = MochiKit.Base.filter(function (d) {
+ return d != drop;
+ }, this.drops);
+ },
+
+ prepare: function (element) {
+ MochiKit.Base.map(function (drop) {
+ if (drop.isAccepted(element)) {
+ if (drop.options.activeclass) {
+ MochiKit.DOM.addElementClass(drop.element,
+ drop.options.activeclass);
+ }
+ drop.options.onactive(drop.element, element);
+ }
+ }, this.drops);
+ },
+
+ findDeepestChild: function (drops) {
+ deepest = drops[0];
+
+ for (i = 1; i < drops.length; ++i) {
+ if (MochiKit.DOM.isParent(drops[i].element, deepest.element)) {
+ deepest = drops[i];
+ }
+ }
+ return deepest;
+ },
+
+ show: function (point, element) {
+ if (!this.drops.length) {
+ return;
+ }
+ var affected = [];
+
+ if (this.last_active) {
+ this.last_active.deactivate();
+ }
+ MochiKit.Iter.forEach(this.drops, function (drop) {
+ if (drop.isAffected(point, element)) {
+ affected.push(drop);
+ }
+ });
+ if (affected.length > 0) {
+ drop = this.findDeepestChild(affected);
+ MochiKit.Position.within(drop.element, point.page.x, point.page.y);
+ drop.options.onhover(element, drop.element,
+ MochiKit.Position.overlap(drop.options.overlap, drop.element));
+ drop.activate();
+ }
+ },
+
+ fire: function (event, element) {
+ if (!this.last_active) {
+ return;
+ }
+ MochiKit.Position.prepare();
+
+ if (this.last_active.isAffected(event.mouse(), element)) {
+ this.last_active.options.ondrop(element,
+ this.last_active.element, event);
+ }
+ },
+
+ reset: function (element) {
+ MochiKit.Base.map(function (drop) {
+ if (drop.options.activeclass) {
+ MochiKit.DOM.removeElementClass(drop.element,
+ drop.options.activeclass);
+ }
+ drop.options.ondesactive(drop.element, element);
+ }, this.drops);
+ if (this.last_active) {
+ this.last_active.deactivate();
+ }
+ }
+};
+
+/** @id MochiKit.DragAndDrop.Droppable */
+MochiKit.DragAndDrop.Droppable = function (element, options) {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls(element, options);
+ }
+ this.__init__(element, options);
+};
+
+MochiKit.DragAndDrop.Droppable.prototype = {
+ /***
+
+ A droppable object. Simple use is to create giving an element:
+
+ new MochiKit.DragAndDrop.Droppable('myelement');
+
+ Generally you'll want to define the 'ondrop' function and maybe the
+ 'accept' option to filter draggables.
+
+ ***/
+ __class__: MochiKit.DragAndDrop.Droppable,
+
+ __init__: function (element, /* optional */options) {
+ var d = MochiKit.DOM;
+ var b = MochiKit.Base;
+ this.element = d.getElement(element);
+ this.options = b.update({
+
+ /** @id MochiKit.DragAndDrop.greedy */
+ greedy: true,
+
+ /** @id MochiKit.DragAndDrop.hoverclass */
+ hoverclass: null,
+
+ /** @id MochiKit.DragAndDrop.activeclass */
+ activeclass: null,
+
+ /** @id MochiKit.DragAndDrop.hoverfunc */
+ hoverfunc: b.noop,
+
+ /** @id MochiKit.DragAndDrop.accept */
+ accept: null,
+
+ /** @id MochiKit.DragAndDrop.onactive */
+ onactive: b.noop,
+
+ /** @id MochiKit.DragAndDrop.ondesactive */
+ ondesactive: b.noop,
+
+ /** @id MochiKit.DragAndDrop.onhover */
+ onhover: b.noop,
+
+ /** @id MochiKit.DragAndDrop.ondrop */
+ ondrop: b.noop,
+
+ /** @id MochiKit.DragAndDrop.containment */
+ containment: [],
+ tree: false
+ }, options || {});
+
+ // cache containers
+ this.options._containers = [];
+ b.map(MochiKit.Base.bind(function (c) {
+ this.options._containers.push(d.getElement(c));
+ }, this), this.options.containment);
+
+ d.makePositioned(this.element); // fix IE
+
+ MochiKit.DragAndDrop.Droppables.register(this);
+ },
+
+ /** @id MochiKit.DragAndDrop.isContained */
+ isContained: function (element) {
+ if (this.options._containers.length) {
+ var containmentNode;
+ if (this.options.tree) {
+ containmentNode = element.treeNode;
+ } else {
+ containmentNode = element.parentNode;
+ }
+ return MochiKit.Iter.some(this.options._containers, function (c) {
+ return containmentNode == c;
+ });
+ } else {
+ return true;
+ }
+ },
+
+ /** @id MochiKit.DragAndDrop.isAccepted */
+ isAccepted: function (element) {
+ return ((!this.options.accept) || MochiKit.Iter.some(
+ this.options.accept, function (c) {
+ return MochiKit.DOM.hasElementClass(element, c);
+ }));
+ },
+
+ /** @id MochiKit.DragAndDrop.isAffected */
+ isAffected: function (point, element) {
+ return ((this.element != element) &&
+ this.isContained(element) &&
+ this.isAccepted(element) &&
+ MochiKit.Position.within(this.element, point.page.x,
+ point.page.y));
+ },
+
+ /** @id MochiKit.DragAndDrop.deactivate */
+ deactivate: function () {
+ /***
+
+ A droppable is deactivate when a draggable has been over it and left.
+
+ ***/
+ if (this.options.hoverclass) {
+ MochiKit.DOM.removeElementClass(this.element,
+ this.options.hoverclass);
+ }
+ this.options.hoverfunc(this.element, false);
+ MochiKit.DragAndDrop.Droppables.last_active = null;
+ },
+
+ /** @id MochiKit.DragAndDrop.activate */
+ activate: function () {
+ /***
+
+ A droppable is active when a draggable is over it.
+
+ ***/
+ if (this.options.hoverclass) {
+ MochiKit.DOM.addElementClass(this.element, this.options.hoverclass);
+ }
+ this.options.hoverfunc(this.element, true);
+ MochiKit.DragAndDrop.Droppables.last_active = this;
+ },
+
+ /** @id MochiKit.DragAndDrop.destroy */
+ destroy: function () {
+ /***
+
+ Delete this droppable.
+
+ ***/
+ MochiKit.DragAndDrop.Droppables.unregister(this);
+ },
+
+ /** @id MochiKit.DragAndDrop.repr */
+ repr: function () {
+ return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
+ }
+};
+
+MochiKit.DragAndDrop.Draggables = {
+ /***
+
+ Manage draggables elements. Not intended to direct use.
+
+ ***/
+ drags: [],
+
+ register: function (draggable) {
+ if (this.drags.length === 0) {
+ var conn = MochiKit.Signal.connect;
+ this.eventMouseUp = conn(document, 'onmouseup', this, this.endDrag);
+ this.eventMouseMove = conn(document, 'onmousemove', this,
+ this.updateDrag);
+ this.eventKeypress = conn(document, 'onkeypress', this,
+ this.keyPress);
+ }
+ this.drags.push(draggable);
+ },
+
+ unregister: function (draggable) {
+ this.drags = MochiKit.Base.filter(function (d) {
+ return d != draggable;
+ }, this.drags);
+ if (this.drags.length === 0) {
+ var disc = MochiKit.Signal.disconnect;
+ disc(this.eventMouseUp);
+ disc(this.eventMouseMove);
+ disc(this.eventKeypress);
+ }
+ },
+
+ activate: function (draggable) {
+ // allows keypress events if window is not currently focused
+ // fails for Safari
+ window.focus();
+ this.activeDraggable = draggable;
+ },
+
+ deactivate: function () {
+ this.activeDraggable = null;
+ },
+
+ updateDrag: function (event) {
+ if (!this.activeDraggable) {
+ return;
+ }
+ var pointer = event.mouse();
+ // Mozilla-based browsers fire successive mousemove events with
+ // the same coordinates, prevent needless redrawing (moz bug?)
+ if (this._lastPointer && (MochiKit.Base.repr(this._lastPointer.page) ==
+ MochiKit.Base.repr(pointer.page))) {
+ return;
+ }
+ this._lastPointer = pointer;
+ this.activeDraggable.updateDrag(event, pointer);
+ },
+
+ endDrag: function (event) {
+ if (!this.activeDraggable) {
+ return;
+ }
+ this._lastPointer = null;
+ this.activeDraggable.endDrag(event);
+ this.activeDraggable = null;
+ },
+
+ keyPress: function (event) {
+ if (this.activeDraggable) {
+ this.activeDraggable.keyPress(event);
+ }
+ },
+
+ notify: function (eventName, draggable, event) {
+ MochiKit.Signal.signal(this, eventName, draggable, event);
+ }
+};
+
+/** @id MochiKit.DragAndDrop.Draggable */
+MochiKit.DragAndDrop.Draggable = function (element, options) {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls(element, options);
+ }
+ this.__init__(element, options);
+};
+
+MochiKit.DragAndDrop.Draggable.prototype = {
+ /***
+
+ A draggable object. Simple instantiate :
+
+ new MochiKit.DragAndDrop.Draggable('myelement');
+
+ ***/
+ __class__ : MochiKit.DragAndDrop.Draggable,
+
+ __init__: function (element, /* optional */options) {
+ var v = MochiKit.Visual;
+ var b = MochiKit.Base;
+ options = b.update({
+
+ /** @id MochiKit.DragAndDrop.handle */
+ handle: false,
+
+ /** @id MochiKit.DragAndDrop.starteffect */
+ starteffect: function (innerelement) {
+ this._savedOpacity = MochiKit.Style.getStyle(innerelement, 'opacity') || 1.0;
+ new v.Opacity(innerelement, {duration:0.2, from:this._savedOpacity, to:0.7});
+ },
+ /** @id MochiKit.DragAndDrop.reverteffect */
+ reverteffect: function (innerelement, top_offset, left_offset) {
+ var dur = Math.sqrt(Math.abs(top_offset^2) +
+ Math.abs(left_offset^2))*0.02;
+ return new v.Move(innerelement,
+ {x: -left_offset, y: -top_offset, duration: dur});
+ },
+
+ /** @id MochiKit.DragAndDrop.endeffect */
+ endeffect: function (innerelement) {
+ new v.Opacity(innerelement, {duration:0.2, from:0.7, to:this._savedOpacity});
+ },
+
+ /** @id MochiKit.DragAndDrop.onchange */
+ onchange: b.noop,
+
+ /** @id MochiKit.DragAndDrop.zindex */
+ zindex: 1000,
+
+ /** @id MochiKit.DragAndDrop.revert */
+ revert: false,
+
+ /** @id MochiKit.DragAndDrop.scroll */
+ scroll: false,
+
+ /** @id MochiKit.DragAndDrop.scrollSensitivity */
+ scrollSensitivity: 20,
+
+ /** @id MochiKit.DragAndDrop.scrollSpeed */
+ scrollSpeed: 15,
+ // false, or xy or [x, y] or function (x, y){return [x, y];}
+
+ /** @id MochiKit.DragAndDrop.snap */
+ snap: false
+ }, options || {});
+
+ var d = MochiKit.DOM;
+ this.element = d.getElement(element);
+
+ if (options.handle && (typeof(options.handle) == 'string')) {
+ this.handle = d.getFirstElementByTagAndClassName(null,
+ options.handle, this.element);
+ }
+ if (!this.handle) {
+ this.handle = d.getElement(options.handle);
+ }
+ if (!this.handle) {
+ this.handle = this.element;
+ }
+
+ if (options.scroll && !options.scroll.scrollTo && !options.scroll.outerHTML) {
+ options.scroll = d.getElement(options.scroll);
+ this._isScrollChild = MochiKit.DOM.isChildNode(this.element, options.scroll);
+ }
+
+ d.makePositioned(this.element); // fix IE
+
+ this.delta = this.currentDelta();
+ this.options = options;
+ this.dragging = false;
+
+ this.eventMouseDown = MochiKit.Signal.connect(this.handle,
+ 'onmousedown', this, this.initDrag);
+ MochiKit.DragAndDrop.Draggables.register(this);
+ },
+
+ /** @id MochiKit.DragAndDrop.destroy */
+ destroy: function () {
+ MochiKit.Signal.disconnect(this.eventMouseDown);
+ MochiKit.DragAndDrop.Draggables.unregister(this);
+ },
+
+ /** @id MochiKit.DragAndDrop.currentDelta */
+ currentDelta: function () {
+ var s = MochiKit.Style.getStyle;
+ return [
+ parseInt(s(this.element, 'left') || '0'),
+ parseInt(s(this.element, 'top') || '0')];
+ },
+
+ /** @id MochiKit.DragAndDrop.initDrag */
+ initDrag: function (event) {
+ if (!event.mouse().button.left) {
+ return;
+ }
+ // abort on form elements, fixes a Firefox issue
+ var src = event.target();
+ var tagName = (src.tagName || '').toUpperCase();
+ if (tagName === 'INPUT' || tagName === 'SELECT' ||
+ tagName === 'OPTION' || tagName === 'BUTTON' ||
+ tagName === 'TEXTAREA') {
+ return;
+ }
+
+ if (this._revert) {
+ this._revert.cancel();
+ this._revert = null;
+ }
+
+ var pointer = event.mouse();
+ var pos = MochiKit.Position.cumulativeOffset(this.element);
+ this.offset = [pointer.page.x - pos.x, pointer.page.y - pos.y];
+
+ MochiKit.DragAndDrop.Draggables.activate(this);
+ event.stop();
+ },
+
+ /** @id MochiKit.DragAndDrop.startDrag */
+ startDrag: function (event) {
+ this.dragging = true;
+ if (this.options.selectclass) {
+ MochiKit.DOM.addElementClass(this.element,
+ this.options.selectclass);
+ }
+ if (this.options.zindex) {
+ this.originalZ = parseInt(MochiKit.Style.getStyle(this.element,
+ 'z-index') || '0');
+ this.element.style.zIndex = this.options.zindex;
+ }
+
+ if (this.options.ghosting) {
+ this._clone = this.element.cloneNode(true);
+ this.ghostPosition = MochiKit.Position.absolutize(this.element);
+ this.element.parentNode.insertBefore(this._clone, this.element);
+ }
+
+ if (this.options.scroll) {
+ if (this.options.scroll == window) {
+ var where = this._getWindowScroll(this.options.scroll);
+ this.originalScrollLeft = where.left;
+ this.originalScrollTop = where.top;
+ } else {
+ this.originalScrollLeft = this.options.scroll.scrollLeft;
+ this.originalScrollTop = this.options.scroll.scrollTop;
+ }
+ }
+
+ MochiKit.DragAndDrop.Droppables.prepare(this.element);
+ MochiKit.DragAndDrop.Draggables.notify('start', this, event);
+ if (this.options.starteffect) {
+ this.options.starteffect(this.element);
+ }
+ },
+
+ /** @id MochiKit.DragAndDrop.updateDrag */
+ updateDrag: function (event, pointer) {
+ if (!this.dragging) {
+ this.startDrag(event);
+ }
+ MochiKit.Position.prepare();
+ MochiKit.DragAndDrop.Droppables.show(pointer, this.element);
+ MochiKit.DragAndDrop.Draggables.notify('drag', this, event);
+ this.draw(pointer);
+ this.options.onchange(this);
+
+ if (this.options.scroll) {
+ this.stopScrolling();
+ var p, q;
+ if (this.options.scroll == window) {
+ var s = this._getWindowScroll(this.options.scroll);
+ p = new MochiKit.Style.Coordinates(s.left, s.top);
+ q = new MochiKit.Style.Coordinates(s.left + s.width,
+ s.top + s.height);
+ } else {
+ p = MochiKit.Position.page(this.options.scroll);
+ p.x += this.options.scroll.scrollLeft;
+ p.y += this.options.scroll.scrollTop;
+ p.x += (window.pageXOffset || document.documentElement.scrollLeft || document.body.scrollLeft || 0);
+ p.y += (window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop || 0);
+ q = new MochiKit.Style.Coordinates(p.x + this.options.scroll.offsetWidth,
+ p.y + this.options.scroll.offsetHeight);
+ }
+ var speed = [0, 0];
+ if (pointer.page.x > (q.x - this.options.scrollSensitivity)) {
+ speed[0] = pointer.page.x - (q.x - this.options.scrollSensitivity);
+ } else if (pointer.page.x < (p.x + this.options.scrollSensitivity)) {
+ speed[0] = pointer.page.x - (p.x + this.options.scrollSensitivity);
+ }
+ if (pointer.page.y > (q.y - this.options.scrollSensitivity)) {
+ speed[1] = pointer.page.y - (q.y - this.options.scrollSensitivity);
+ } else if (pointer.page.y < (p.y + this.options.scrollSensitivity)) {
+ speed[1] = pointer.page.y - (p.y + this.options.scrollSensitivity);
+ }
+ this.startScrolling(speed);
+ }
+
+ // fix AppleWebKit rendering
+ if (/AppleWebKit'/.test(navigator.appVersion)) {
+ window.scrollBy(0, 0);
+ }
+ event.stop();
+ },
+
+ /** @id MochiKit.DragAndDrop.finishDrag */
+ finishDrag: function (event, success) {
+ var dr = MochiKit.DragAndDrop;
+ this.dragging = false;
+ if (this.options.selectclass) {
+ MochiKit.DOM.removeElementClass(this.element,
+ this.options.selectclass);
+ }
+
+ if (this.options.ghosting) {
+ // XXX: from a user point of view, it would be better to remove
+ // the node only *after* the MochiKit.Visual.Move end when used
+ // with revert.
+ MochiKit.Position.relativize(this.element, this.ghostPosition);
+ MochiKit.DOM.removeElement(this._clone);
+ this._clone = null;
+ }
+
+ if (success) {
+ dr.Droppables.fire(event, this.element);
+ }
+ dr.Draggables.notify('end', this, event);
+
+ var revert = this.options.revert;
+ if (revert && typeof(revert) == 'function') {
+ revert = revert(this.element);
+ }
+
+ var d = this.currentDelta();
+ if (revert && this.options.reverteffect) {
+ this._revert = this.options.reverteffect(this.element,
+ d[1] - this.delta[1], d[0] - this.delta[0]);
+ } else {
+ this.delta = d;
+ }
+
+ if (this.options.zindex) {
+ this.element.style.zIndex = this.originalZ;
+ }
+
+ if (this.options.endeffect) {
+ this.options.endeffect(this.element);
+ }
+
+ dr.Draggables.deactivate();
+ dr.Droppables.reset(this.element);
+ },
+
+ /** @id MochiKit.DragAndDrop.keyPress */
+ keyPress: function (event) {
+ if (event.key().string != "KEY_ESCAPE") {
+ return;
+ }
+ this.finishDrag(event, false);
+ event.stop();
+ },
+
+ /** @id MochiKit.DragAndDrop.endDrag */
+ endDrag: function (event) {
+ if (!this.dragging) {
+ return;
+ }
+ this.stopScrolling();
+ this.finishDrag(event, true);
+ event.stop();
+ },
+
+ /** @id MochiKit.DragAndDrop.draw */
+ draw: function (point) {
+ var pos = MochiKit.Position.cumulativeOffset(this.element);
+ var d = this.currentDelta();
+ pos.x -= d[0];
+ pos.y -= d[1];
+
+ if (this.options.scroll && (this.options.scroll != window && this._isScrollChild)) {
+ pos.x -= this.options.scroll.scrollLeft - this.originalScrollLeft;
+ pos.y -= this.options.scroll.scrollTop - this.originalScrollTop;
+ }
+
+ var p = [point.page.x - pos.x - this.offset[0],
+ point.page.y - pos.y - this.offset[1]];
+
+ if (this.options.snap) {
+ if (typeof(this.options.snap) == 'function') {
+ p = this.options.snap(p[0], p[1]);
+ } else {
+ if (this.options.snap instanceof Array) {
+ var i = -1;
+ p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
+ i += 1;
+ return Math.round(v/this.options.snap[i]) *
+ this.options.snap[i];
+ }, this), p);
+ } else {
+ p = MochiKit.Base.map(MochiKit.Base.bind(function (v) {
+ return Math.round(v/this.options.snap) *
+ this.options.snap;
+ }, this), p);
+ }
+ }
+ }
+ var style = this.element.style;
+ if ((!this.options.constraint) ||
+ (this.options.constraint == 'horizontal')) {
+ style.left = p[0] + 'px';
+ }
+ if ((!this.options.constraint) ||
+ (this.options.constraint == 'vertical')) {
+ style.top = p[1] + 'px';
+ }
+ if (style.visibility == 'hidden') {
+ style.visibility = ''; // fix gecko rendering
+ }
+ },
+
+ /** @id MochiKit.DragAndDrop.stopScrolling */
+ stopScrolling: function () {
+ if (this.scrollInterval) {
+ clearInterval(this.scrollInterval);
+ this.scrollInterval = null;
+ MochiKit.DragAndDrop.Draggables._lastScrollPointer = null;
+ }
+ },
+
+ /** @id MochiKit.DragAndDrop.startScrolling */
+ startScrolling: function (speed) {
+ if (!speed[0] && !speed[1]) {
+ return;
+ }
+ this.scrollSpeed = [speed[0] * this.options.scrollSpeed,
+ speed[1] * this.options.scrollSpeed];
+ this.lastScrolled = new Date();
+ this.scrollInterval = setInterval(MochiKit.Base.bind(this.scroll, this), 10);
+ },
+
+ /** @id MochiKit.DragAndDrop.scroll */
+ scroll: function () {
+ var current = new Date();
+ var delta = current - this.lastScrolled;
+ this.lastScrolled = current;
+
+ if (this.options.scroll == window) {
+ var s = this._getWindowScroll(this.options.scroll);
+ if (this.scrollSpeed[0] || this.scrollSpeed[1]) {
+ var dm = delta / 1000;
+ this.options.scroll.scrollTo(s.left + dm * this.scrollSpeed[0],
+ s.top + dm * this.scrollSpeed[1]);
+ }
+ } else {
+ this.options.scroll.scrollLeft += this.scrollSpeed[0] * delta / 1000;
+ this.options.scroll.scrollTop += this.scrollSpeed[1] * delta / 1000;
+ }
+
+ var d = MochiKit.DragAndDrop;
+
+ MochiKit.Position.prepare();
+ d.Droppables.show(d.Draggables._lastPointer, this.element);
+ d.Draggables.notify('drag', this);
+ if (this._isScrollChild) {
+ d.Draggables._lastScrollPointer = d.Draggables._lastScrollPointer || d.Draggables._lastPointer;
+ d.Draggables._lastScrollPointer.x += this.scrollSpeed[0] * delta / 1000;
+ d.Draggables._lastScrollPointer.y += this.scrollSpeed[1] * delta / 1000;
+ if (d.Draggables._lastScrollPointer.x < 0) {
+ d.Draggables._lastScrollPointer.x = 0;
+ }
+ if (d.Draggables._lastScrollPointer.y < 0) {
+ d.Draggables._lastScrollPointer.y = 0;
+ }
+ this.draw(d.Draggables._lastScrollPointer);
+ }
+
+ this.options.onchange(this);
+ },
+
+ _getWindowScroll: function (win) {
+ var vp, w, h;
+ MochiKit.DOM.withWindow(win, function () {
+ vp = MochiKit.Style.getViewportPosition(win.document);
+ });
+ if (win.innerWidth) {
+ w = win.innerWidth;
+ h = win.innerHeight;
+ } else if (win.document.documentElement && win.document.documentElement.clientWidth) {
+ w = win.document.documentElement.clientWidth;
+ h = win.document.documentElement.clientHeight;
+ } else {
+ w = win.document.body.offsetWidth;
+ h = win.document.body.offsetHeight;
+ }
+ return {top: vp.x, left: vp.y, width: w, height: h};
+ },
+
+ /** @id MochiKit.DragAndDrop.repr */
+ repr: function () {
+ return '[' + this.__class__.NAME + ", options:" + MochiKit.Base.repr(this.options) + "]";
+ }
+};
+
+MochiKit.DragAndDrop.__new__ = function () {
+ MochiKit.Base.nameFunctions(this);
+
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
+ };
+};
+
+MochiKit.DragAndDrop.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.DragAndDrop);
+
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Format.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Format.js
new file mode 100644
index 0000000000..937b681f70
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Format.js
@@ -0,0 +1,304 @@
+/***
+
+MochiKit.Format 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Format');
+}
+
+if (typeof(MochiKit) == 'undefined') {
+ MochiKit = {};
+}
+
+if (typeof(MochiKit.Format) == 'undefined') {
+ MochiKit.Format = {};
+}
+
+MochiKit.Format.NAME = "MochiKit.Format";
+MochiKit.Format.VERSION = "1.4";
+MochiKit.Format.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+MochiKit.Format.toString = function () {
+ return this.__repr__();
+};
+
+MochiKit.Format._numberFormatter = function (placeholder, header, footer, locale, isPercent, precision, leadingZeros, separatorAt, trailingZeros) {
+ return function (num) {
+ num = parseFloat(num);
+ if (typeof(num) == "undefined" || num === null || isNaN(num)) {
+ return placeholder;
+ }
+ var curheader = header;
+ var curfooter = footer;
+ if (num < 0) {
+ num = -num;
+ } else {
+ curheader = curheader.replace(/-/, "");
+ }
+ var me = arguments.callee;
+ var fmt = MochiKit.Format.formatLocale(locale);
+ if (isPercent) {
+ num = num * 100.0;
+ curfooter = fmt.percent + curfooter;
+ }
+ num = MochiKit.Format.roundToFixed(num, precision);
+ var parts = num.split(/\./);
+ var whole = parts[0];
+ var frac = (parts.length == 1) ? "" : parts[1];
+ var res = "";
+ while (whole.length < leadingZeros) {
+ whole = "0" + whole;
+ }
+ if (separatorAt) {
+ while (whole.length > separatorAt) {
+ var i = whole.length - separatorAt;
+ //res = res + fmt.separator + whole.substring(i, whole.length);
+ res = fmt.separator + whole.substring(i, whole.length) + res;
+ whole = whole.substring(0, i);
+ }
+ }
+ res = whole + res;
+ if (precision > 0) {
+ while (frac.length < trailingZeros) {
+ frac = frac + "0";
+ }
+ res = res + fmt.decimal + frac;
+ }
+ return curheader + res + curfooter;
+ };
+};
+
+/** @id MochiKit.Format.numberFormatter */
+MochiKit.Format.numberFormatter = function (pattern, placeholder/* = "" */, locale/* = "default" */) {
+ // http://java.sun.com/docs/books/tutorial/i18n/format/numberpattern.html
+ // | 0 | leading or trailing zeros
+ // | # | just the number
+ // | , | separator
+ // | . | decimal separator
+ // | % | Multiply by 100 and format as percent
+ if (typeof(placeholder) == "undefined") {
+ placeholder = "";
+ }
+ var match = pattern.match(/((?:[0#]+,)?[0#]+)(?:\.([0#]+))?(%)?/);
+ if (!match) {
+ throw TypeError("Invalid pattern");
+ }
+ var header = pattern.substr(0, match.index);
+ var footer = pattern.substr(match.index + match[0].length);
+ if (header.search(/-/) == -1) {
+ header = header + "-";
+ }
+ var whole = match[1];
+ var frac = (typeof(match[2]) == "string" && match[2] != "") ? match[2] : "";
+ var isPercent = (typeof(match[3]) == "string" && match[3] != "");
+ var tmp = whole.split(/,/);
+ var separatorAt;
+ if (typeof(locale) == "undefined") {
+ locale = "default";
+ }
+ if (tmp.length == 1) {
+ separatorAt = null;
+ } else {
+ separatorAt = tmp[1].length;
+ }
+ var leadingZeros = whole.length - whole.replace(/0/g, "").length;
+ var trailingZeros = frac.length - frac.replace(/0/g, "").length;
+ var precision = frac.length;
+ var rval = MochiKit.Format._numberFormatter(
+ placeholder, header, footer, locale, isPercent, precision,
+ leadingZeros, separatorAt, trailingZeros
+ );
+ var m = MochiKit.Base;
+ if (m) {
+ var fn = arguments.callee;
+ var args = m.concat(arguments);
+ rval.repr = function () {
+ return [
+ self.NAME,
+ "(",
+ map(m.repr, args).join(", "),
+ ")"
+ ].join("");
+ };
+ }
+ return rval;
+};
+
+/** @id MochiKit.Format.formatLocale */
+MochiKit.Format.formatLocale = function (locale) {
+ if (typeof(locale) == "undefined" || locale === null) {
+ locale = "default";
+ }
+ if (typeof(locale) == "string") {
+ var rval = MochiKit.Format.LOCALE[locale];
+ if (typeof(rval) == "string") {
+ rval = arguments.callee(rval);
+ MochiKit.Format.LOCALE[locale] = rval;
+ }
+ return rval;
+ } else {
+ return locale;
+ }
+};
+
+/** @id MochiKit.Format.twoDigitAverage */
+MochiKit.Format.twoDigitAverage = function (numerator, denominator) {
+ if (denominator) {
+ var res = numerator / denominator;
+ if (!isNaN(res)) {
+ return MochiKit.Format.twoDigitFloat(numerator / denominator);
+ }
+ }
+ return "0";
+};
+
+/** @id MochiKit.Format.twoDigitFloat */
+MochiKit.Format.twoDigitFloat = function (someFloat) {
+ var sign = (someFloat < 0 ? '-' : '');
+ var s = Math.floor(Math.abs(someFloat) * 100).toString();
+ if (s == '0') {
+ return s;
+ }
+ if (s.length < 3) {
+ while (s.charAt(s.length - 1) == '0') {
+ s = s.substring(0, s.length - 1);
+ }
+ return sign + '0.' + s;
+ }
+ var head = sign + s.substring(0, s.length - 2);
+ var tail = s.substring(s.length - 2, s.length);
+ if (tail == '00') {
+ return head;
+ } else if (tail.charAt(1) == '0') {
+ return head + '.' + tail.charAt(0);
+ } else {
+ return head + '.' + tail;
+ }
+};
+
+/** @id MochiKit.Format.lstrip */
+MochiKit.Format.lstrip = function (str, /* optional */chars) {
+ str = str + "";
+ if (typeof(str) != "string") {
+ return null;
+ }
+ if (!chars) {
+ return str.replace(/^\s+/, "");
+ } else {
+ return str.replace(new RegExp("^[" + chars + "]+"), "");
+ }
+};
+
+/** @id MochiKit.Format.rstrip */
+MochiKit.Format.rstrip = function (str, /* optional */chars) {
+ str = str + "";
+ if (typeof(str) != "string") {
+ return null;
+ }
+ if (!chars) {
+ return str.replace(/\s+$/, "");
+ } else {
+ return str.replace(new RegExp("[" + chars + "]+$"), "");
+ }
+};
+
+/** @id MochiKit.Format.strip */
+MochiKit.Format.strip = function (str, /* optional */chars) {
+ var self = MochiKit.Format;
+ return self.rstrip(self.lstrip(str, chars), chars);
+};
+
+/** @id MochiKit.Format.truncToFixed */
+MochiKit.Format.truncToFixed = function (aNumber, precision) {
+ aNumber = Math.floor(aNumber * Math.pow(10, precision));
+ var res = (aNumber * Math.pow(10, -precision)).toFixed(precision);
+ if (res.charAt(0) == ".") {
+ res = "0" + res;
+ }
+ return res;
+};
+
+/** @id MochiKit.Format.roundToFixed */
+MochiKit.Format.roundToFixed = function (aNumber, precision) {
+ return MochiKit.Format.truncToFixed(
+ aNumber + 0.5 * Math.pow(10, -precision),
+ precision
+ );
+};
+
+/** @id MochiKit.Format.percentFormat */
+MochiKit.Format.percentFormat = function (someFloat) {
+ return MochiKit.Format.twoDigitFloat(100 * someFloat) + '%';
+};
+
+MochiKit.Format.EXPORT = [
+ "truncToFixed",
+ "roundToFixed",
+ "numberFormatter",
+ "formatLocale",
+ "twoDigitAverage",
+ "twoDigitFloat",
+ "percentFormat",
+ "lstrip",
+ "rstrip",
+ "strip"
+];
+
+MochiKit.Format.LOCALE = {
+ en_US: {separator: ",", decimal: ".", percent: "%"},
+ de_DE: {separator: ".", decimal: ",", percent: "%"},
+ fr_FR: {separator: " ", decimal: ",", percent: "%"},
+ "default": "en_US"
+};
+
+MochiKit.Format.EXPORT_OK = [];
+MochiKit.Format.EXPORT_TAGS = {
+ ':all': MochiKit.Format.EXPORT,
+ ':common': MochiKit.Format.EXPORT
+};
+
+MochiKit.Format.__new__ = function () {
+ // MochiKit.Base.nameFunctions(this);
+ var base = this.NAME + ".";
+ var k, v, o;
+ for (k in this.LOCALE) {
+ o = this.LOCALE[k];
+ if (typeof(o) == "object") {
+ o.repr = function () { return this.NAME; };
+ o.NAME = base + "LOCALE." + k;
+ }
+ }
+ for (k in this) {
+ o = this[k];
+ if (typeof(o) == 'function' && typeof(o.NAME) == 'undefined') {
+ try {
+ o.NAME = base + k;
+ } catch (e) {
+ // pass
+ }
+ }
+ }
+};
+
+MochiKit.Format.__new__();
+
+if (typeof(MochiKit.Base) != "undefined") {
+ MochiKit.Base._exportSymbols(this, MochiKit.Format);
+} else {
+ (function (globals, module) {
+ if ((typeof(JSAN) == 'undefined' && typeof(dojo) == 'undefined')
+ || (MochiKit.__export__ === false)) {
+ var all = module.EXPORT_TAGS[":all"];
+ for (var i = 0; i < all.length; i++) {
+ globals[all[i]] = module[all[i]];
+ }
+ }
+ })(this, MochiKit.Format);
+}
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Iter.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Iter.js
new file mode 100644
index 0000000000..c2fcbeee05
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Iter.js
@@ -0,0 +1,851 @@
+/***
+
+MochiKit.Iter 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Iter');
+ dojo.require('MochiKit.Base');
+}
+
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.Iter depends on MochiKit.Base!";
+}
+
+if (typeof(MochiKit.Iter) == 'undefined') {
+ MochiKit.Iter = {};
+}
+
+MochiKit.Iter.NAME = "MochiKit.Iter";
+MochiKit.Iter.VERSION = "1.4";
+MochiKit.Base.update(MochiKit.Iter, {
+ __repr__: function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+ },
+ toString: function () {
+ return this.__repr__();
+ },
+
+ /** @id MochiKit.Iter.registerIteratorFactory */
+ registerIteratorFactory: function (name, check, iterfactory, /* optional */ override) {
+ MochiKit.Iter.iteratorRegistry.register(name, check, iterfactory, override);
+ },
+
+ /** @id MochiKit.Iter.iter */
+ iter: function (iterable, /* optional */ sentinel) {
+ var self = MochiKit.Iter;
+ if (arguments.length == 2) {
+ return self.takewhile(
+ function (a) { return a != sentinel; },
+ iterable
+ );
+ }
+ if (typeof(iterable.next) == 'function') {
+ return iterable;
+ } else if (typeof(iterable.iter) == 'function') {
+ return iterable.iter();
+ /*
+ } else if (typeof(iterable.__iterator__) == 'function') {
+ //
+ // XXX: We can't support JavaScript 1.7 __iterator__ directly
+ // because of Object.prototype.__iterator__
+ //
+ return iterable.__iterator__();
+ */
+ }
+
+ try {
+ return self.iteratorRegistry.match(iterable);
+ } catch (e) {
+ var m = MochiKit.Base;
+ if (e == m.NotFound) {
+ e = new TypeError(typeof(iterable) + ": " + m.repr(iterable) + " is not iterable");
+ }
+ throw e;
+ }
+ },
+
+ /** @id MochiKit.Iter.count */
+ count: function (n) {
+ if (!n) {
+ n = 0;
+ }
+ var m = MochiKit.Base;
+ return {
+ repr: function () { return "count(" + n + ")"; },
+ toString: m.forwardCall("repr"),
+ next: m.counter(n)
+ };
+ },
+
+ /** @id MochiKit.Iter.cycle */
+ cycle: function (p) {
+ var self = MochiKit.Iter;
+ var m = MochiKit.Base;
+ var lst = [];
+ var iterator = self.iter(p);
+ return {
+ repr: function () { return "cycle(...)"; },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ try {
+ var rval = iterator.next();
+ lst.push(rval);
+ return rval;
+ } catch (e) {
+ if (e != self.StopIteration) {
+ throw e;
+ }
+ if (lst.length === 0) {
+ this.next = function () {
+ throw self.StopIteration;
+ };
+ } else {
+ var i = -1;
+ this.next = function () {
+ i = (i + 1) % lst.length;
+ return lst[i];
+ };
+ }
+ return this.next();
+ }
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.repeat */
+ repeat: function (elem, /* optional */n) {
+ var m = MochiKit.Base;
+ if (typeof(n) == 'undefined') {
+ return {
+ repr: function () {
+ return "repeat(" + m.repr(elem) + ")";
+ },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ return elem;
+ }
+ };
+ }
+ return {
+ repr: function () {
+ return "repeat(" + m.repr(elem) + ", " + n + ")";
+ },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ if (n <= 0) {
+ throw MochiKit.Iter.StopIteration;
+ }
+ n -= 1;
+ return elem;
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.next */
+ next: function (iterator) {
+ return iterator.next();
+ },
+
+ /** @id MochiKit.Iter.izip */
+ izip: function (p, q/*, ...*/) {
+ var m = MochiKit.Base;
+ var self = MochiKit.Iter;
+ var next = self.next;
+ var iterables = m.map(self.iter, arguments);
+ return {
+ repr: function () { return "izip(...)"; },
+ toString: m.forwardCall("repr"),
+ next: function () { return m.map(next, iterables); }
+ };
+ },
+
+ /** @id MochiKit.Iter.ifilter */
+ ifilter: function (pred, seq) {
+ var m = MochiKit.Base;
+ seq = MochiKit.Iter.iter(seq);
+ if (pred === null) {
+ pred = m.operator.truth;
+ }
+ return {
+ repr: function () { return "ifilter(...)"; },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ while (true) {
+ var rval = seq.next();
+ if (pred(rval)) {
+ return rval;
+ }
+ }
+ // mozilla warnings aren't too bright
+ return undefined;
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.ifilterfalse */
+ ifilterfalse: function (pred, seq) {
+ var m = MochiKit.Base;
+ seq = MochiKit.Iter.iter(seq);
+ if (pred === null) {
+ pred = m.operator.truth;
+ }
+ return {
+ repr: function () { return "ifilterfalse(...)"; },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ while (true) {
+ var rval = seq.next();
+ if (!pred(rval)) {
+ return rval;
+ }
+ }
+ // mozilla warnings aren't too bright
+ return undefined;
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.islice */
+ islice: function (seq/*, [start,] stop[, step] */) {
+ var self = MochiKit.Iter;
+ var m = MochiKit.Base;
+ seq = self.iter(seq);
+ var start = 0;
+ var stop = 0;
+ var step = 1;
+ var i = -1;
+ if (arguments.length == 2) {
+ stop = arguments[1];
+ } else if (arguments.length == 3) {
+ start = arguments[1];
+ stop = arguments[2];
+ } else {
+ start = arguments[1];
+ stop = arguments[2];
+ step = arguments[3];
+ }
+ return {
+ repr: function () {
+ return "islice(" + ["...", start, stop, step].join(", ") + ")";
+ },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ var rval;
+ while (i < start) {
+ rval = seq.next();
+ i++;
+ }
+ if (start >= stop) {
+ throw self.StopIteration;
+ }
+ start += step;
+ return rval;
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.imap */
+ imap: function (fun, p, q/*, ...*/) {
+ var m = MochiKit.Base;
+ var self = MochiKit.Iter;
+ var iterables = m.map(self.iter, m.extend(null, arguments, 1));
+ var map = m.map;
+ var next = self.next;
+ return {
+ repr: function () { return "imap(...)"; },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ return fun.apply(this, map(next, iterables));
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.applymap */
+ applymap: function (fun, seq, self) {
+ seq = MochiKit.Iter.iter(seq);
+ var m = MochiKit.Base;
+ return {
+ repr: function () { return "applymap(...)"; },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ return fun.apply(self, seq.next());
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.chain */
+ chain: function (p, q/*, ...*/) {
+ // dumb fast path
+ var self = MochiKit.Iter;
+ var m = MochiKit.Base;
+ if (arguments.length == 1) {
+ return self.iter(arguments[0]);
+ }
+ var argiter = m.map(self.iter, arguments);
+ return {
+ repr: function () { return "chain(...)"; },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ while (argiter.length > 1) {
+ try {
+ return argiter[0].next();
+ } catch (e) {
+ if (e != self.StopIteration) {
+ throw e;
+ }
+ argiter.shift();
+ }
+ }
+ if (argiter.length == 1) {
+ // optimize last element
+ var arg = argiter.shift();
+ this.next = m.bind("next", arg);
+ return this.next();
+ }
+ throw self.StopIteration;
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.takewhile */
+ takewhile: function (pred, seq) {
+ var self = MochiKit.Iter;
+ seq = self.iter(seq);
+ return {
+ repr: function () { return "takewhile(...)"; },
+ toString: MochiKit.Base.forwardCall("repr"),
+ next: function () {
+ var rval = seq.next();
+ if (!pred(rval)) {
+ this.next = function () {
+ throw self.StopIteration;
+ };
+ this.next();
+ }
+ return rval;
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.dropwhile */
+ dropwhile: function (pred, seq) {
+ seq = MochiKit.Iter.iter(seq);
+ var m = MochiKit.Base;
+ var bind = m.bind;
+ return {
+ "repr": function () { return "dropwhile(...)"; },
+ "toString": m.forwardCall("repr"),
+ "next": function () {
+ while (true) {
+ var rval = seq.next();
+ if (!pred(rval)) {
+ break;
+ }
+ }
+ this.next = bind("next", seq);
+ return rval;
+ }
+ };
+ },
+
+ _tee: function (ident, sync, iterable) {
+ sync.pos[ident] = -1;
+ var m = MochiKit.Base;
+ var listMin = m.listMin;
+ return {
+ repr: function () { return "tee(" + ident + ", ...)"; },
+ toString: m.forwardCall("repr"),
+ next: function () {
+ var rval;
+ var i = sync.pos[ident];
+
+ if (i == sync.max) {
+ rval = iterable.next();
+ sync.deque.push(rval);
+ sync.max += 1;
+ sync.pos[ident] += 1;
+ } else {
+ rval = sync.deque[i - sync.min];
+ sync.pos[ident] += 1;
+ if (i == sync.min && listMin(sync.pos) != sync.min) {
+ sync.min += 1;
+ sync.deque.shift();
+ }
+ }
+ return rval;
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.tee */
+ tee: function (iterable, n/* = 2 */) {
+ var rval = [];
+ var sync = {
+ "pos": [],
+ "deque": [],
+ "max": -1,
+ "min": -1
+ };
+ if (arguments.length == 1 || typeof(n) == "undefined" || n === null) {
+ n = 2;
+ }
+ var self = MochiKit.Iter;
+ iterable = self.iter(iterable);
+ var _tee = self._tee;
+ for (var i = 0; i < n; i++) {
+ rval.push(_tee(i, sync, iterable));
+ }
+ return rval;
+ },
+
+ /** @id MochiKit.Iter.list */
+ list: function (iterable) {
+ // Fast-path for Array and Array-like
+ var rval;
+ if (iterable instanceof Array) {
+ return iterable.slice();
+ }
+ // this is necessary to avoid a Safari crash
+ if (typeof(iterable) == "function" &&
+ !(iterable instanceof Function) &&
+ typeof(iterable.length) == 'number') {
+ rval = [];
+ for (var i = 0; i < iterable.length; i++) {
+ rval.push(iterable[i]);
+ }
+ return rval;
+ }
+
+ var self = MochiKit.Iter;
+ iterable = self.iter(iterable);
+ var rval = [];
+ try {
+ while (true) {
+ rval.push(iterable.next());
+ }
+ } catch (e) {
+ if (e != self.StopIteration) {
+ throw e;
+ }
+ return rval;
+ }
+ // mozilla warnings aren't too bright
+ return undefined;
+ },
+
+
+ /** @id MochiKit.Iter.reduce */
+ reduce: function (fn, iterable, /* optional */initial) {
+ var i = 0;
+ var x = initial;
+ var self = MochiKit.Iter;
+ iterable = self.iter(iterable);
+ if (arguments.length < 3) {
+ try {
+ x = iterable.next();
+ } catch (e) {
+ if (e == self.StopIteration) {
+ e = new TypeError("reduce() of empty sequence with no initial value");
+ }
+ throw e;
+ }
+ i++;
+ }
+ try {
+ while (true) {
+ x = fn(x, iterable.next());
+ }
+ } catch (e) {
+ if (e != self.StopIteration) {
+ throw e;
+ }
+ }
+ return x;
+ },
+
+ /** @id MochiKit.Iter.range */
+ range: function (/* [start,] stop[, step] */) {
+ var start = 0;
+ var stop = 0;
+ var step = 1;
+ if (arguments.length == 1) {
+ stop = arguments[0];
+ } else if (arguments.length == 2) {
+ start = arguments[0];
+ stop = arguments[1];
+ } else if (arguments.length == 3) {
+ start = arguments[0];
+ stop = arguments[1];
+ step = arguments[2];
+ } else {
+ throw new TypeError("range() takes 1, 2, or 3 arguments!");
+ }
+ if (step === 0) {
+ throw new TypeError("range() step must not be 0");
+ }
+ return {
+ next: function () {
+ if ((step > 0 && start >= stop) || (step < 0 && start <= stop)) {
+ throw MochiKit.Iter.StopIteration;
+ }
+ var rval = start;
+ start += step;
+ return rval;
+ },
+ repr: function () {
+ return "range(" + [start, stop, step].join(", ") + ")";
+ },
+ toString: MochiKit.Base.forwardCall("repr")
+ };
+ },
+
+ /** @id MochiKit.Iter.sum */
+ sum: function (iterable, start/* = 0 */) {
+ if (typeof(start) == "undefined" || start === null) {
+ start = 0;
+ }
+ var x = start;
+ var self = MochiKit.Iter;
+ iterable = self.iter(iterable);
+ try {
+ while (true) {
+ x += iterable.next();
+ }
+ } catch (e) {
+ if (e != self.StopIteration) {
+ throw e;
+ }
+ }
+ return x;
+ },
+
+ /** @id MochiKit.Iter.exhaust */
+ exhaust: function (iterable) {
+ var self = MochiKit.Iter;
+ iterable = self.iter(iterable);
+ try {
+ while (true) {
+ iterable.next();
+ }
+ } catch (e) {
+ if (e != self.StopIteration) {
+ throw e;
+ }
+ }
+ },
+
+ /** @id MochiKit.Iter.forEach */
+ forEach: function (iterable, func, /* optional */self) {
+ var m = MochiKit.Base;
+ if (arguments.length > 2) {
+ func = m.bind(func, self);
+ }
+ // fast path for array
+ if (m.isArrayLike(iterable)) {
+ try {
+ for (var i = 0; i < iterable.length; i++) {
+ func(iterable[i]);
+ }
+ } catch (e) {
+ if (e != MochiKit.Iter.StopIteration) {
+ throw e;
+ }
+ }
+ } else {
+ self = MochiKit.Iter;
+ self.exhaust(self.imap(func, iterable));
+ }
+ },
+
+ /** @id MochiKit.Iter.every */
+ every: function (iterable, func) {
+ var self = MochiKit.Iter;
+ try {
+ self.ifilterfalse(func, iterable).next();
+ return false;
+ } catch (e) {
+ if (e != self.StopIteration) {
+ throw e;
+ }
+ return true;
+ }
+ },
+
+ /** @id MochiKit.Iter.sorted */
+ sorted: function (iterable, /* optional */cmp) {
+ var rval = MochiKit.Iter.list(iterable);
+ if (arguments.length == 1) {
+ cmp = MochiKit.Base.compare;
+ }
+ rval.sort(cmp);
+ return rval;
+ },
+
+ /** @id MochiKit.Iter.reversed */
+ reversed: function (iterable) {
+ var rval = MochiKit.Iter.list(iterable);
+ rval.reverse();
+ return rval;
+ },
+
+ /** @id MochiKit.Iter.some */
+ some: function (iterable, func) {
+ var self = MochiKit.Iter;
+ try {
+ self.ifilter(func, iterable).next();
+ return true;
+ } catch (e) {
+ if (e != self.StopIteration) {
+ throw e;
+ }
+ return false;
+ }
+ },
+
+ /** @id MochiKit.Iter.iextend */
+ iextend: function (lst, iterable) {
+ if (MochiKit.Base.isArrayLike(iterable)) {
+ // fast-path for array-like
+ for (var i = 0; i < iterable.length; i++) {
+ lst.push(iterable[i]);
+ }
+ } else {
+ var self = MochiKit.Iter;
+ iterable = self.iter(iterable);
+ try {
+ while (true) {
+ lst.push(iterable.next());
+ }
+ } catch (e) {
+ if (e != self.StopIteration) {
+ throw e;
+ }
+ }
+ }
+ return lst;
+ },
+
+ /** @id MochiKit.Iter.groupby */
+ groupby: function(iterable, /* optional */ keyfunc) {
+ var m = MochiKit.Base;
+ var self = MochiKit.Iter;
+ if (arguments.length < 2) {
+ keyfunc = m.operator.identity;
+ }
+ iterable = self.iter(iterable);
+
+ // shared
+ var pk = undefined;
+ var k = undefined;
+ var v;
+
+ function fetch() {
+ v = iterable.next();
+ k = keyfunc(v);
+ };
+
+ function eat() {
+ var ret = v;
+ v = undefined;
+ return ret;
+ };
+
+ var first = true;
+ var compare = m.compare;
+ return {
+ repr: function () { return "groupby(...)"; },
+ next: function() {
+ // iterator-next
+
+ // iterate until meet next group
+ while (compare(k, pk) === 0) {
+ fetch();
+ if (first) {
+ first = false;
+ break;
+ }
+ }
+ pk = k;
+ return [k, {
+ next: function() {
+ // subiterator-next
+ if (v == undefined) { // Is there something to eat?
+ fetch();
+ }
+ if (compare(k, pk) !== 0) {
+ throw self.StopIteration;
+ }
+ return eat();
+ }
+ }];
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.groupby_as_array */
+ groupby_as_array: function (iterable, /* optional */ keyfunc) {
+ var m = MochiKit.Base;
+ var self = MochiKit.Iter;
+ if (arguments.length < 2) {
+ keyfunc = m.operator.identity;
+ }
+
+ iterable = self.iter(iterable);
+ var result = [];
+ var first = true;
+ var prev_key;
+ var compare = m.compare;
+ while (true) {
+ try {
+ var value = iterable.next();
+ var key = keyfunc(value);
+ } catch (e) {
+ if (e == self.StopIteration) {
+ break;
+ }
+ throw e;
+ }
+ if (first || compare(key, prev_key) !== 0) {
+ var values = [];
+ result.push([key, values]);
+ }
+ values.push(value);
+ first = false;
+ prev_key = key;
+ }
+ return result;
+ },
+
+ /** @id MochiKit.Iter.arrayLikeIter */
+ arrayLikeIter: function (iterable) {
+ var i = 0;
+ return {
+ repr: function () { return "arrayLikeIter(...)"; },
+ toString: MochiKit.Base.forwardCall("repr"),
+ next: function () {
+ if (i >= iterable.length) {
+ throw MochiKit.Iter.StopIteration;
+ }
+ return iterable[i++];
+ }
+ };
+ },
+
+ /** @id MochiKit.Iter.hasIterateNext */
+ hasIterateNext: function (iterable) {
+ return (iterable && typeof(iterable.iterateNext) == "function");
+ },
+
+ /** @id MochiKit.Iter.iterateNextIter */
+ iterateNextIter: function (iterable) {
+ return {
+ repr: function () { return "iterateNextIter(...)"; },
+ toString: MochiKit.Base.forwardCall("repr"),
+ next: function () {
+ var rval = iterable.iterateNext();
+ if (rval === null || rval === undefined) {
+ throw MochiKit.Iter.StopIteration;
+ }
+ return rval;
+ }
+ };
+ }
+});
+
+
+MochiKit.Iter.EXPORT_OK = [
+ "iteratorRegistry",
+ "arrayLikeIter",
+ "hasIterateNext",
+ "iterateNextIter",
+];
+
+MochiKit.Iter.EXPORT = [
+ "StopIteration",
+ "registerIteratorFactory",
+ "iter",
+ "count",
+ "cycle",
+ "repeat",
+ "next",
+ "izip",
+ "ifilter",
+ "ifilterfalse",
+ "islice",
+ "imap",
+ "applymap",
+ "chain",
+ "takewhile",
+ "dropwhile",
+ "tee",
+ "list",
+ "reduce",
+ "range",
+ "sum",
+ "exhaust",
+ "forEach",
+ "every",
+ "sorted",
+ "reversed",
+ "some",
+ "iextend",
+ "groupby",
+ "groupby_as_array"
+];
+
+MochiKit.Iter.__new__ = function () {
+ var m = MochiKit.Base;
+ // Re-use StopIteration if exists (e.g. SpiderMonkey)
+ if (typeof(StopIteration) != "undefined") {
+ this.StopIteration = StopIteration;
+ } else {
+ /** @id MochiKit.Iter.StopIteration */
+ this.StopIteration = new m.NamedError("StopIteration");
+ }
+ this.iteratorRegistry = new m.AdapterRegistry();
+ // Register the iterator factory for arrays
+ this.registerIteratorFactory(
+ "arrayLike",
+ m.isArrayLike,
+ this.arrayLikeIter
+ );
+
+ this.registerIteratorFactory(
+ "iterateNext",
+ this.hasIterateNext,
+ this.iterateNextIter
+ );
+
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ m.nameFunctions(this);
+
+};
+
+MochiKit.Iter.__new__();
+
+//
+// XXX: Internet Explorer blows
+//
+if (MochiKit.__export__) {
+ reduce = MochiKit.Iter.reduce;
+}
+
+MochiKit.Base._exportSymbols(this, MochiKit.Iter);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Logging.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Logging.js
new file mode 100644
index 0000000000..ac7678b5e6
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Logging.js
@@ -0,0 +1,321 @@
+/***
+
+MochiKit.Logging 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Logging');
+ dojo.require('MochiKit.Base');
+}
+
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.Logging depends on MochiKit.Base!";
+}
+
+if (typeof(MochiKit.Logging) == 'undefined') {
+ MochiKit.Logging = {};
+}
+
+MochiKit.Logging.NAME = "MochiKit.Logging";
+MochiKit.Logging.VERSION = "1.4";
+MochiKit.Logging.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.Logging.toString = function () {
+ return this.__repr__();
+};
+
+
+MochiKit.Logging.EXPORT = [
+ "LogLevel",
+ "LogMessage",
+ "Logger",
+ "alertListener",
+ "logger",
+ "log",
+ "logError",
+ "logDebug",
+ "logFatal",
+ "logWarning"
+];
+
+
+MochiKit.Logging.EXPORT_OK = [
+ "logLevelAtLeast",
+ "isLogMessage",
+ "compareLogMessage"
+];
+
+
+/** @id MochiKit.Logging.LogMessage */
+MochiKit.Logging.LogMessage = function (num, level, info) {
+ this.num = num;
+ this.level = level;
+ this.info = info;
+ this.timestamp = new Date();
+};
+
+MochiKit.Logging.LogMessage.prototype = {
+ /** @id MochiKit.Logging.LogMessage.prototype.repr */
+ repr: function () {
+ var m = MochiKit.Base;
+ return 'LogMessage(' +
+ m.map(
+ m.repr,
+ [this.num, this.level, this.info]
+ ).join(', ') + ')';
+ },
+ /** @id MochiKit.Logging.LogMessage.prototype.toString */
+ toString: MochiKit.Base.forwardCall("repr")
+};
+
+MochiKit.Base.update(MochiKit.Logging, {
+ /** @id MochiKit.Logging.logLevelAtLeast */
+ logLevelAtLeast: function (minLevel) {
+ var self = MochiKit.Logging;
+ if (typeof(minLevel) == 'string') {
+ minLevel = self.LogLevel[minLevel];
+ }
+ return function (msg) {
+ var msgLevel = msg.level;
+ if (typeof(msgLevel) == 'string') {
+ msgLevel = self.LogLevel[msgLevel];
+ }
+ return msgLevel >= minLevel;
+ };
+ },
+
+ /** @id MochiKit.Logging.isLogMessage */
+ isLogMessage: function (/* ... */) {
+ var LogMessage = MochiKit.Logging.LogMessage;
+ for (var i = 0; i < arguments.length; i++) {
+ if (!(arguments[i] instanceof LogMessage)) {
+ return false;
+ }
+ }
+ return true;
+ },
+
+ /** @id MochiKit.Logging.compareLogMessage */
+ compareLogMessage: function (a, b) {
+ return MochiKit.Base.compare([a.level, a.info], [b.level, b.info]);
+ },
+
+ /** @id MochiKit.Logging.alertListener */
+ alertListener: function (msg) {
+ alert(
+ "num: " + msg.num +
+ "\nlevel: " + msg.level +
+ "\ninfo: " + msg.info.join(" ")
+ );
+ }
+
+});
+
+/** @id MochiKit.Logging.Logger */
+MochiKit.Logging.Logger = function (/* optional */maxSize) {
+ this.counter = 0;
+ if (typeof(maxSize) == 'undefined' || maxSize === null) {
+ maxSize = -1;
+ }
+ this.maxSize = maxSize;
+ this._messages = [];
+ this.listeners = {};
+ this.useNativeConsole = false;
+};
+
+MochiKit.Logging.Logger.prototype = {
+ /** @id MochiKit.Logging.Logger.prototype.clear */
+ clear: function () {
+ this._messages.splice(0, this._messages.length);
+ },
+
+ /** @id MochiKit.Logging.Logger.prototype.logToConsole */
+ logToConsole: function (msg) {
+ if (typeof(window) != "undefined" && window.console
+ && window.console.log) {
+ // Safari and FireBug 0.4
+ // Percent replacement is a workaround for cute Safari crashing bug
+ window.console.log(msg.replace(/%/g, '\uFF05'));
+ } else if (typeof(opera) != "undefined" && opera.postError) {
+ // Opera
+ opera.postError(msg);
+ } else if (typeof(printfire) == "function") {
+ // FireBug 0.3 and earlier
+ printfire(msg);
+ } else if (typeof(Debug) != "undefined" && Debug.writeln) {
+ // IE Web Development Helper (?)
+ // http://www.nikhilk.net/Entry.aspx?id=93
+ Debug.writeln(msg);
+ } else if (typeof(debug) != "undefined" && debug.trace) {
+ // Atlas framework (?)
+ // http://www.nikhilk.net/Entry.aspx?id=93
+ debug.trace(msg);
+ }
+ },
+
+ /** @id MochiKit.Logging.Logger.prototype.dispatchListeners */
+ dispatchListeners: function (msg) {
+ for (var k in this.listeners) {
+ var pair = this.listeners[k];
+ if (pair.ident != k || (pair[0] && !pair[0](msg))) {
+ continue;
+ }
+ pair[1](msg);
+ }
+ },
+
+ /** @id MochiKit.Logging.Logger.prototype.addListener */
+ addListener: function (ident, filter, listener) {
+ if (typeof(filter) == 'string') {
+ filter = MochiKit.Logging.logLevelAtLeast(filter);
+ }
+ var entry = [filter, listener];
+ entry.ident = ident;
+ this.listeners[ident] = entry;
+ },
+
+ /** @id MochiKit.Logging.Logger.prototype.removeListener */
+ removeListener: function (ident) {
+ delete this.listeners[ident];
+ },
+
+ /** @id MochiKit.Logging.Logger.prototype.baseLog */
+ baseLog: function (level, message/*, ...*/) {
+ var msg = new MochiKit.Logging.LogMessage(
+ this.counter,
+ level,
+ MochiKit.Base.extend(null, arguments, 1)
+ );
+ this._messages.push(msg);
+ this.dispatchListeners(msg);
+ if (this.useNativeConsole) {
+ this.logToConsole(msg.level + ": " + msg.info.join(" "));
+ }
+ this.counter += 1;
+ while (this.maxSize >= 0 && this._messages.length > this.maxSize) {
+ this._messages.shift();
+ }
+ },
+
+ /** @id MochiKit.Logging.Logger.prototype.getMessages */
+ getMessages: function (howMany) {
+ var firstMsg = 0;
+ if (!(typeof(howMany) == 'undefined' || howMany === null)) {
+ firstMsg = Math.max(0, this._messages.length - howMany);
+ }
+ return this._messages.slice(firstMsg);
+ },
+
+ /** @id MochiKit.Logging.Logger.prototype.getMessageText */
+ getMessageText: function (howMany) {
+ if (typeof(howMany) == 'undefined' || howMany === null) {
+ howMany = 30;
+ }
+ var messages = this.getMessages(howMany);
+ if (messages.length) {
+ var lst = map(function (m) {
+ return '\n [' + m.num + '] ' + m.level + ': ' + m.info.join(' ');
+ }, messages);
+ lst.unshift('LAST ' + messages.length + ' MESSAGES:');
+ return lst.join('');
+ }
+ return '';
+ },
+
+ /** @id MochiKit.Logging.Logger.prototype.debuggingBookmarklet */
+ debuggingBookmarklet: function (inline) {
+ if (typeof(MochiKit.LoggingPane) == "undefined") {
+ alert(this.getMessageText());
+ } else {
+ MochiKit.LoggingPane.createLoggingPane(inline || false);
+ }
+ }
+};
+
+MochiKit.Logging.__new__ = function () {
+ this.LogLevel = {
+ ERROR: 40,
+ FATAL: 50,
+ WARNING: 30,
+ INFO: 20,
+ DEBUG: 10
+ };
+
+ var m = MochiKit.Base;
+ m.registerComparator("LogMessage",
+ this.isLogMessage,
+ this.compareLogMessage
+ );
+
+ var partial = m.partial;
+
+ var Logger = this.Logger;
+ var baseLog = Logger.prototype.baseLog;
+ m.update(this.Logger.prototype, {
+ debug: partial(baseLog, 'DEBUG'),
+ log: partial(baseLog, 'INFO'),
+ error: partial(baseLog, 'ERROR'),
+ fatal: partial(baseLog, 'FATAL'),
+ warning: partial(baseLog, 'WARNING')
+ });
+
+ // indirectly find logger so it can be replaced
+ var self = this;
+ var connectLog = function (name) {
+ return function () {
+ self.logger[name].apply(self.logger, arguments);
+ };
+ };
+
+ /** @id MochiKit.Logging.log */
+ this.log = connectLog('log');
+ /** @id MochiKit.Logging.logError */
+ this.logError = connectLog('error');
+ /** @id MochiKit.Logging.logDebug */
+ this.logDebug = connectLog('debug');
+ /** @id MochiKit.Logging.logFatal */
+ this.logFatal = connectLog('fatal');
+ /** @id MochiKit.Logging.logWarning */
+ this.logWarning = connectLog('warning');
+ this.logger = new Logger();
+ this.logger.useNativeConsole = true;
+
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ m.nameFunctions(this);
+
+};
+
+if (typeof(printfire) == "undefined" &&
+ typeof(document) != "undefined" && document.createEvent &&
+ typeof(dispatchEvent) != "undefined") {
+ // FireBug really should be less stupid about this global function
+ printfire = function () {
+ printfire.args = arguments;
+ var ev = document.createEvent("Events");
+ ev.initEvent("printfire", false, true);
+ dispatchEvent(ev);
+ };
+}
+
+MochiKit.Logging.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.Logging);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/LoggingPane.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/LoggingPane.js
new file mode 100644
index 0000000000..3798ae404e
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/LoggingPane.js
@@ -0,0 +1,374 @@
+/***
+
+MochiKit.LoggingPane 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.LoggingPane');
+ dojo.require('MochiKit.Logging');
+ dojo.require('MochiKit.Base');
+}
+
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Logging", []);
+ JSAN.use("MochiKit.Base", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined' || typeof(MochiKit.Logging) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.LoggingPane depends on MochiKit.Base and MochiKit.Logging!";
+}
+
+if (typeof(MochiKit.LoggingPane) == 'undefined') {
+ MochiKit.LoggingPane = {};
+}
+
+MochiKit.LoggingPane.NAME = "MochiKit.LoggingPane";
+MochiKit.LoggingPane.VERSION = "1.4";
+MochiKit.LoggingPane.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.LoggingPane.toString = function () {
+ return this.__repr__();
+};
+
+/** @id MochiKit.LoggingPane.createLoggingPane */
+MochiKit.LoggingPane.createLoggingPane = function (inline/* = false */) {
+ var m = MochiKit.LoggingPane;
+ inline = !(!inline);
+ if (m._loggingPane && m._loggingPane.inline != inline) {
+ m._loggingPane.closePane();
+ m._loggingPane = null;
+ }
+ if (!m._loggingPane || m._loggingPane.closed) {
+ m._loggingPane = new m.LoggingPane(inline, MochiKit.Logging.logger);
+ }
+ return m._loggingPane;
+};
+
+/** @id MochiKit.LoggingPane.LoggingPane */
+MochiKit.LoggingPane.LoggingPane = function (inline/* = false */, logger/* = MochiKit.Logging.logger */) {
+
+ /* Use a div if inline, pop up a window if not */
+ /* Create the elements */
+ if (typeof(logger) == "undefined" || logger === null) {
+ logger = MochiKit.Logging.logger;
+ }
+ this.logger = logger;
+ var update = MochiKit.Base.update;
+ var updatetree = MochiKit.Base.updatetree;
+ var bind = MochiKit.Base.bind;
+ var clone = MochiKit.Base.clone;
+ var win = window;
+ var uid = "_MochiKit_LoggingPane";
+ if (typeof(MochiKit.DOM) != "undefined") {
+ win = MochiKit.DOM.currentWindow();
+ }
+ if (!inline) {
+ // name the popup with the base URL for uniqueness
+ var url = win.location.href.split("?")[0].replace(/[#:\/.><&-]/g, "_");
+ var name = uid + "_" + url;
+ var nwin = win.open("", name, "dependent,resizable,height=200");
+ if (!nwin) {
+ alert("Not able to open debugging window due to pop-up blocking.");
+ return undefined;
+ }
+ nwin.document.write(
+ '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" '
+ + '"http://www.w3.org/TR/html4/loose.dtd">'
+ + '<html><head><title>[MochiKit.LoggingPane]</title></head>'
+ + '<body></body></html>'
+ );
+ nwin.document.close();
+ nwin.document.title += ' ' + win.document.title;
+ win = nwin;
+ }
+ var doc = win.document;
+ this.doc = doc;
+
+ // Connect to the debug pane if it already exists (i.e. in a window orphaned by the page being refreshed)
+ var debugPane = doc.getElementById(uid);
+ var existing_pane = !!debugPane;
+ if (debugPane && typeof(debugPane.loggingPane) != "undefined") {
+ debugPane.loggingPane.logger = this.logger;
+ debugPane.loggingPane.buildAndApplyFilter();
+ return debugPane.loggingPane;
+ }
+
+ if (existing_pane) {
+ // clear any existing contents
+ var child;
+ while ((child = debugPane.firstChild)) {
+ debugPane.removeChild(child);
+ }
+ } else {
+ debugPane = doc.createElement("div");
+ debugPane.id = uid;
+ }
+ debugPane.loggingPane = this;
+ var levelFilterField = doc.createElement("input");
+ var infoFilterField = doc.createElement("input");
+ var filterButton = doc.createElement("button");
+ var loadButton = doc.createElement("button");
+ var clearButton = doc.createElement("button");
+ var closeButton = doc.createElement("button");
+ var logPaneArea = doc.createElement("div");
+ var logPane = doc.createElement("div");
+
+ /* Set up the functions */
+ var listenerId = uid + "_Listener";
+ this.colorTable = clone(this.colorTable);
+ var messages = [];
+ var messageFilter = null;
+
+ /** @id MochiKit.LoggingPane.messageLevel */
+ var messageLevel = function (msg) {
+ var level = msg.level;
+ if (typeof(level) == "number") {
+ level = MochiKit.Logging.LogLevel[level];
+ }
+ return level;
+ };
+
+ /** @id MochiKit.LoggingPane.messageText */
+ var messageText = function (msg) {
+ return msg.info.join(" ");
+ };
+
+ /** @id MochiKit.LoggingPane.addMessageText */
+ var addMessageText = bind(function (msg) {
+ var level = messageLevel(msg);
+ var text = messageText(msg);
+ var c = this.colorTable[level];
+ var p = doc.createElement("span");
+ p.className = "MochiKit-LogMessage MochiKit-LogLevel-" + level;
+ 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;
+ p.appendChild(doc.createTextNode(level + ": " + text));
+ logPane.appendChild(p);
+ logPane.appendChild(doc.createElement("br"));
+ if (logPaneArea.offsetHeight > logPaneArea.scrollHeight) {
+ logPaneArea.scrollTop = 0;
+ } else {
+ logPaneArea.scrollTop = logPaneArea.scrollHeight;
+ }
+ }, this);
+
+ /** @id MochiKit.LoggingPane.addMessage */
+ var addMessage = function (msg) {
+ messages[messages.length] = msg;
+ addMessageText(msg);
+ };
+
+ /** @id MochiKit.LoggingPane.buildMessageFilter */
+ var buildMessageFilter = function () {
+ var levelre, infore;
+ try {
+ /* Catch any exceptions that might arise due to invalid regexes */
+ levelre = new RegExp(levelFilterField.value);
+ infore = new RegExp(infoFilterField.value);
+ } catch(e) {
+ /* If there was an error with the regexes, do no filtering */
+ logDebug("Error in filter regex: " + e.message);
+ return null;
+ }
+
+ return function (msg) {
+ return (
+ levelre.test(messageLevel(msg)) &&
+ infore.test(messageText(msg))
+ );
+ };
+ };
+
+ /** @id MochiKit.LoggingPane.clearMessagePane */
+ var clearMessagePane = function () {
+ while (logPane.firstChild) {
+ logPane.removeChild(logPane.firstChild);
+ }
+ };
+
+ /** @id MochiKit.LoggingPane.clearMessages */
+ var clearMessages = function () {
+ messages = [];
+ clearMessagePane();
+ };
+
+ /** @id MochiKit.LoggingPane.closePane */
+ var closePane = bind(function () {
+ if (this.closed) {
+ return;
+ }
+ this.closed = true;
+ if (MochiKit.LoggingPane._loggingPane == this) {
+ MochiKit.LoggingPane._loggingPane = null;
+ }
+ this.logger.removeListener(listenerId);
+ try {
+ try {
+ debugPane.loggingPane = null;
+ } catch(e) { logFatal("Bookmarklet was closed incorrectly."); }
+ if (inline) {
+ debugPane.parentNode.removeChild(debugPane);
+ } else {
+ this.win.close();
+ }
+ } catch(e) {}
+ }, this);
+
+ /** @id MochiKit.LoggingPane.filterMessages */
+ var filterMessages = function () {
+ clearMessagePane();
+
+ for (var i = 0; i < messages.length; i++) {
+ var msg = messages[i];
+ if (messageFilter === null || messageFilter(msg)) {
+ addMessageText(msg);
+ }
+ }
+ };
+
+ this.buildAndApplyFilter = function () {
+ messageFilter = buildMessageFilter();
+
+ filterMessages();
+
+ this.logger.removeListener(listenerId);
+ this.logger.addListener(listenerId, messageFilter, addMessage);
+ };
+
+
+ /** @id MochiKit.LoggingPane.loadMessages */
+ var loadMessages = bind(function () {
+ messages = this.logger.getMessages();
+ filterMessages();
+ }, this);
+
+ /** @id MochiKit.LoggingPane.filterOnEnter */
+ var filterOnEnter = bind(function (event) {
+ event = event || window.event;
+ key = event.which || event.keyCode;
+ if (key == 13) {
+ this.buildAndApplyFilter();
+ }
+ }, this);
+
+ /* Create the debug pane */
+ var style = "display: block; z-index: 1000; left: 0px; bottom: 0px; position: fixed; width: 100%; background-color: white; font: " + this.logFont;
+ if (inline) {
+ style += "; height: 10em; border-top: 2px solid black";
+ } else {
+ style += "; height: 100%;";
+ }
+ debugPane.style.cssText = style;
+
+ if (!existing_pane) {
+ doc.body.appendChild(debugPane);
+ }
+
+ /* Create the filter fields */
+ style = {"cssText": "width: 33%; display: inline; font: " + this.logFont};
+
+ updatetree(levelFilterField, {
+ "value": "FATAL|ERROR|WARNING|INFO|DEBUG",
+ "onkeypress": filterOnEnter,
+ "style": style
+ });
+ debugPane.appendChild(levelFilterField);
+
+ updatetree(infoFilterField, {
+ "value": ".*",
+ "onkeypress": filterOnEnter,
+ "style": style
+ });
+ debugPane.appendChild(infoFilterField);
+
+ /* Create the buttons */
+ style = "width: 8%; display:inline; font: " + this.logFont;
+
+ filterButton.appendChild(doc.createTextNode("Filter"));
+ filterButton.onclick = bind("buildAndApplyFilter", this);
+ filterButton.style.cssText = style;
+ debugPane.appendChild(filterButton);
+
+ loadButton.appendChild(doc.createTextNode("Load"));
+ loadButton.onclick = loadMessages;
+ loadButton.style.cssText = style;
+ debugPane.appendChild(loadButton);
+
+ clearButton.appendChild(doc.createTextNode("Clear"));
+ clearButton.onclick = clearMessages;
+ clearButton.style.cssText = style;
+ debugPane.appendChild(clearButton);
+
+ closeButton.appendChild(doc.createTextNode("Close"));
+ closeButton.onclick = closePane;
+ closeButton.style.cssText = style;
+ debugPane.appendChild(closeButton);
+
+ /* Create the logging pane */
+ logPaneArea.style.cssText = "overflow: auto; width: 100%";
+ logPane.style.cssText = "width: 100%; height: " + (inline ? "8em" : "100%");
+
+ logPaneArea.appendChild(logPane);
+ debugPane.appendChild(logPaneArea);
+
+ this.buildAndApplyFilter();
+ loadMessages();
+
+ if (inline) {
+ this.win = undefined;
+ } else {
+ this.win = win;
+ }
+ this.inline = inline;
+ this.closePane = closePane;
+ this.closed = false;
+
+
+ return this;
+};
+
+MochiKit.LoggingPane.LoggingPane.prototype = {
+ "logFont": "8pt Verdana,sans-serif",
+ "colorTable": {
+ "ERROR": "red",
+ "FATAL": "darkred",
+ "WARNING": "blue",
+ "INFO": "black",
+ "DEBUG": "green"
+ }
+};
+
+
+MochiKit.LoggingPane.EXPORT_OK = [
+ "LoggingPane"
+];
+
+MochiKit.LoggingPane.EXPORT = [
+ "createLoggingPane"
+];
+
+MochiKit.LoggingPane.__new__ = function () {
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": MochiKit.Base.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ MochiKit.Base.nameFunctions(this);
+
+ MochiKit.LoggingPane._loggingPane = null;
+
+};
+
+MochiKit.LoggingPane.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.LoggingPane);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/MochiKit.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/MochiKit.js
new file mode 100644
index 0000000000..3a13b241fe
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/MochiKit.js
@@ -0,0 +1,154 @@
+/***
+
+MochiKit.MochiKit 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(MochiKit) == 'undefined') {
+ MochiKit = {};
+}
+
+if (typeof(MochiKit.MochiKit) == 'undefined') {
+ /** @id MochiKit.MochiKit */
+ MochiKit.MochiKit = {};
+}
+
+MochiKit.MochiKit.NAME = "MochiKit.MochiKit";
+MochiKit.MochiKit.VERSION = "1.4";
+MochiKit.MochiKit.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+/** @id MochiKit.MochiKit.toString */
+MochiKit.MochiKit.toString = function () {
+ return this.__repr__();
+};
+
+/** @id MochiKit.MochiKit.SUBMODULES */
+MochiKit.MochiKit.SUBMODULES = [
+ "Base",
+ "Iter",
+ "Logging",
+ "DateTime",
+ "Format",
+ "Async",
+ "DOM",
+ "Selector",
+ "Style",
+ "LoggingPane",
+ "Color",
+ "Signal",
+ "Position",
+ "Visual"
+];
+
+if (typeof(JSAN) != 'undefined' || typeof(dojo) != 'undefined') {
+ if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.MochiKit');
+ dojo.require("MochiKit.*");
+ }
+ if (typeof(JSAN) != 'undefined') {
+ (function (lst) {
+ for (var i = 0; i < lst.length; i++) {
+ JSAN.use("MochiKit." + lst[i], []);
+ }
+ })(MochiKit.MochiKit.SUBMODULES);
+ }
+ (function () {
+ var extend = MochiKit.Base.extend;
+ var self = MochiKit.MochiKit;
+ var modules = self.SUBMODULES;
+ var EXPORT = [];
+ var EXPORT_OK = [];
+ var EXPORT_TAGS = {};
+ var i, k, m, all;
+ for (i = 0; i < modules.length; i++) {
+ m = MochiKit[modules[i]];
+ extend(EXPORT, m.EXPORT);
+ extend(EXPORT_OK, m.EXPORT_OK);
+ for (k in m.EXPORT_TAGS) {
+ EXPORT_TAGS[k] = extend(EXPORT_TAGS[k], m.EXPORT_TAGS[k]);
+ }
+ all = m.EXPORT_TAGS[":all"];
+ if (!all) {
+ all = extend(null, m.EXPORT, m.EXPORT_OK);
+ }
+ var j;
+ for (j = 0; j < all.length; j++) {
+ k = all[j];
+ self[k] = m[k];
+ }
+ }
+ self.EXPORT = EXPORT;
+ self.EXPORT_OK = EXPORT_OK;
+ self.EXPORT_TAGS = EXPORT_TAGS;
+ }());
+
+} else {
+ if (typeof(MochiKit.__compat__) == 'undefined') {
+ MochiKit.__compat__ = true;
+ }
+ (function () {
+ if (typeof(document) == "undefined") {
+ return;
+ }
+ var scripts = document.getElementsByTagName("script");
+ var kXULNSURI = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
+ var base = null;
+ var baseElem = null;
+ var allScripts = {};
+ var i;
+ for (i = 0; i < scripts.length; i++) {
+ var src = scripts[i].getAttribute("src");
+ if (!src) {
+ continue;
+ }
+ allScripts[src] = true;
+ if (src.match(/MochiKit.js$/)) {
+ base = src.substring(0, src.lastIndexOf('MochiKit.js'));
+ baseElem = scripts[i];
+ }
+ }
+ if (base === null) {
+ return;
+ }
+ var modules = MochiKit.MochiKit.SUBMODULES;
+ for (var i = 0; i < modules.length; i++) {
+ if (MochiKit[modules[i]]) {
+ continue;
+ }
+ var uri = base + modules[i] + '.js';
+ if (uri in allScripts) {
+ continue;
+ }
+ if (document.documentElement &&
+ document.documentElement.namespaceURI == kXULNSURI) {
+ // XUL
+ var s = document.createElementNS(kXULNSURI, 'script');
+ s.setAttribute("id", "MochiKit_" + base + modules[i]);
+ s.setAttribute("src", uri);
+ s.setAttribute("type", "application/x-javascript");
+ baseElem.parentNode.appendChild(s);
+ } else {
+ // HTML
+ /*
+ DOM can not be used here because Safari does
+ deferred loading of scripts unless they are
+ in the document or inserted with document.write
+
+ This is not XHTML compliant. If you want XHTML
+ compliance then you must use the packed version of MochiKit
+ or include each script individually (basically unroll
+ these document.write calls into your XHTML source)
+
+ */
+ document.write('<script src="' + uri +
+ '" type="text/javascript"></script>');
+ }
+ };
+ })();
+}
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/MockDOM.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/MockDOM.js
new file mode 100644
index 0000000000..92558cb7bf
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/MockDOM.js
@@ -0,0 +1,115 @@
+/***
+
+MochiKit.MockDOM 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(MochiKit) == "undefined") {
+ MochiKit = {};
+}
+
+if (typeof(MochiKit.MockDOM) == "undefined") {
+ MochiKit.MockDOM = {};
+}
+
+MochiKit.MockDOM.NAME = "MochiKit.MockDOM";
+MochiKit.MockDOM.VERSION = "1.4";
+
+MochiKit.MockDOM.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+/** @id MochiKit.MockDOM.toString */
+MochiKit.MockDOM.toString = function () {
+ return this.__repr__();
+};
+
+/** @id MochiKit.MockDOM.createDocument */
+MochiKit.MockDOM.createDocument = function () {
+ var doc = new MochiKit.MockDOM.MockElement("DOCUMENT");
+ doc.body = doc.createElement("BODY");
+ doc.appendChild(doc.body);
+ return doc;
+};
+
+/** @id MochiKit.MockDOM.MockElement */
+MochiKit.MockDOM.MockElement = function (name, data, ownerDocument) {
+ this.tagName = this.nodeName = name.toUpperCase();
+ this.ownerDocument = ownerDocument || null;
+ if (name == "DOCUMENT") {
+ this.nodeType = 9;
+ this.childNodes = [];
+ } else if (typeof(data) == "string") {
+ this.nodeValue = data;
+ this.nodeType = 3;
+ } else {
+ this.nodeType = 1;
+ this.childNodes = [];
+ }
+ if (name.substring(0, 1) == "<") {
+ var nameattr = name.substring(
+ name.indexOf('"') + 1, name.lastIndexOf('"'));
+ name = name.substring(1, name.indexOf(" "));
+ this.tagName = this.nodeName = name.toUpperCase();
+ this.setAttribute("name", nameattr);
+ }
+};
+
+MochiKit.MockDOM.MockElement.prototype = {
+ /** @id MochiKit.MockDOM.MockElement.prototype.createElement */
+ createElement: function (tagName) {
+ return new MochiKit.MockDOM.MockElement(tagName, null, this.nodeType == 9 ? this : this.ownerDocument);
+ },
+ /** @id MochiKit.MockDOM.MockElement.prototype.createTextNode */
+ createTextNode: function (text) {
+ return new MochiKit.MockDOM.MockElement("text", text, this.nodeType == 9 ? this : this.ownerDocument);
+ },
+ /** @id MochiKit.MockDOM.MockElement.prototype.setAttribute */
+ setAttribute: function (name, value) {
+ this[name] = value;
+ },
+ /** @id MochiKit.MockDOM.MockElement.prototype.getAttribute */
+ getAttribute: function (name) {
+ return this[name];
+ },
+ /** @id MochiKit.MockDOM.MockElement.prototype.appendChild */
+ appendChild: function (child) {
+ this.childNodes.push(child);
+ },
+ /** @id MochiKit.MockDOM.MockElement.prototype.toString */
+ toString: function () {
+ return "MockElement(" + this.tagName + ")";
+ },
+ /** @id MochiKit.MockDOM.MockElement.prototype.getElementsByTagName */
+ getElementsByTagName: function (tagName) {
+ var foundElements = [];
+ MochiKit.Base.nodeWalk(this, function(node){
+ if (tagName == '*' || tagName == node.tagName) {
+ foundElements.push(node);
+ return node.childNodes;
+ }
+ });
+ return foundElements;
+ }
+};
+
+ /** @id MochiKit.MockDOM.EXPORT_OK */
+MochiKit.MockDOM.EXPORT_OK = [
+ "mockElement",
+ "createDocument"
+];
+
+ /** @id MochiKit.MockDOM.EXPORT */
+MochiKit.MockDOM.EXPORT = [
+ "document"
+];
+
+MochiKit.MockDOM.__new__ = function () {
+ this.document = this.createDocument();
+};
+
+MochiKit.MockDOM.__new__();
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Position.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Position.js
new file mode 100644
index 0000000000..23b0f181ce
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Position.js
@@ -0,0 +1,258 @@
+/***
+
+MochiKit.Position 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005-2006 Bob Ippolito and others. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Position');
+ dojo.require('MochiKit.Base');
+ dojo.require('MochiKit.DOM');
+ dojo.require('MochiKit.Style');
+}
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use('MochiKit.Base', []);
+ JSAN.use('MochiKit.DOM', []);
+ JSAN.use('MochiKit.Style', []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined' ||
+ typeof(MochiKit.Style) == 'undefined' ||
+ typeof(MochiKit.DOM) == 'undefined') {
+ throw '';
+ }
+} catch (e) {
+ throw 'MochiKit.Style depends on MochiKit.Base, MochiKit.DOM, and MochiKit.Style!';
+}
+
+if (typeof(MochiKit.Position) == 'undefined') {
+ MochiKit.Position = {};
+}
+
+MochiKit.Position.NAME = 'MochiKit.Position';
+MochiKit.Position.VERSION = '1.4';
+MochiKit.Position.__repr__ = function () {
+ return '[' + this.NAME + ' ' + this.VERSION + ']';
+};
+MochiKit.Position.toString = function () {
+ return this.__repr__();
+};
+
+MochiKit.Position.EXPORT_OK = [];
+
+MochiKit.Position.EXPORT = [
+];
+
+
+MochiKit.Base.update(MochiKit.Position, {
+ // set to true if needed, warning: firefox performance problems
+ // NOT neeeded for page scrolling, only if draggable contained in
+ // scrollable elements
+ includeScrollOffsets: false,
+
+ /** @id MochiKit.Position.prepare */
+ prepare: function () {
+ var deltaX = window.pageXOffset
+ || document.documentElement.scrollLeft
+ || document.body.scrollLeft
+ || 0;
+ var deltaY = window.pageYOffset
+ || document.documentElement.scrollTop
+ || document.body.scrollTop
+ || 0;
+ this.windowOffset = new MochiKit.Style.Coordinates(deltaX, deltaY);
+ },
+
+ /** @id MochiKit.Position.cumulativeOffset */
+ cumulativeOffset: function (element) {
+ var valueT = 0;
+ var valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ } while (element);
+ return new MochiKit.Style.Coordinates(valueL, valueT);
+ },
+
+ /** @id MochiKit.Position.realOffset */
+ realOffset: function (element) {
+ var valueT = 0;
+ var valueL = 0;
+ do {
+ valueT += element.scrollTop || 0;
+ valueL += element.scrollLeft || 0;
+ element = element.parentNode;
+ } while (element);
+ return new MochiKit.Style.Coordinates(valueL, valueT);
+ },
+
+ /** @id MochiKit.Position.within */
+ within: function (element, x, y) {
+ if (this.includeScrollOffsets) {
+ return this.withinIncludingScrolloffsets(element, x, y);
+ }
+ this.xcomp = x;
+ this.ycomp = y;
+ this.offset = this.cumulativeOffset(element);
+ if (element.style.position == "fixed") {
+ this.offset.x += this.windowOffset.x;
+ this.offset.y += this.windowOffset.y;
+ }
+
+ return (y >= this.offset.y &&
+ y < this.offset.y + element.offsetHeight &&
+ x >= this.offset.x &&
+ x < this.offset.x + element.offsetWidth);
+ },
+
+ /** @id MochiKit.Position.withinIncludingScrolloffsets */
+ withinIncludingScrolloffsets: function (element, x, y) {
+ var offsetcache = this.realOffset(element);
+
+ this.xcomp = x + offsetcache.x - this.windowOffset.x;
+ this.ycomp = y + offsetcache.y - this.windowOffset.y;
+ this.offset = this.cumulativeOffset(element);
+
+ return (this.ycomp >= this.offset.y &&
+ this.ycomp < this.offset.y + element.offsetHeight &&
+ this.xcomp >= this.offset.x &&
+ this.xcomp < this.offset.x + element.offsetWidth);
+ },
+
+ // within must be called directly before
+ /** @id MochiKit.Position.overlap */
+ overlap: function (mode, element) {
+ if (!mode) {
+ return 0;
+ }
+ if (mode == 'vertical') {
+ return ((this.offset.y + element.offsetHeight) - this.ycomp) /
+ element.offsetHeight;
+ }
+ if (mode == 'horizontal') {
+ return ((this.offset.x + element.offsetWidth) - this.xcomp) /
+ element.offsetWidth;
+ }
+ },
+
+ /** @id MochiKit.Position.absolutize */
+ absolutize: function (element) {
+ element = MochiKit.DOM.getElement(element);
+ if (element.style.position == 'absolute') {
+ return;
+ }
+ MochiKit.Position.prepare();
+
+ var offsets = MochiKit.Position.positionedOffset(element);
+ var width = element.clientWidth;
+ var height = element.clientHeight;
+
+ var oldStyle = {
+ 'position': element.style.position,
+ 'left': offsets.x - parseFloat(element.style.left || 0),
+ 'top': offsets.y - parseFloat(element.style.top || 0),
+ 'width': element.style.width,
+ 'height': element.style.height
+ };
+
+ element.style.position = 'absolute';
+ element.style.top = offsets.y + 'px';
+ element.style.left = offsets.x + 'px';
+ element.style.width = width + 'px';
+ element.style.height = height + 'px';
+
+ return oldStyle;
+ },
+
+ /** @id MochiKit.Position.positionedOffset */
+ positionedOffset: function (element) {
+ var valueT = 0, valueL = 0;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+ element = element.offsetParent;
+ if (element) {
+ p = MochiKit.Style.getStyle(element, 'position');
+ if (p == 'relative' || p == 'absolute') {
+ break;
+ }
+ }
+ } while (element);
+ return new MochiKit.Style.Coordinates(valueL, valueT);
+ },
+
+ /** @id MochiKit.Position.relativize */
+ relativize: function (element, oldPos) {
+ element = MochiKit.DOM.getElement(element);
+ if (element.style.position == 'relative') {
+ return;
+ }
+ MochiKit.Position.prepare();
+
+ var top = parseFloat(element.style.top || 0) -
+ (oldPos['top'] || 0);
+ var left = parseFloat(element.style.left || 0) -
+ (oldPos['left'] || 0);
+
+ element.style.position = oldPos['position'];
+ element.style.top = top + 'px';
+ element.style.left = left + 'px';
+ element.style.width = oldPos['width'];
+ element.style.height = oldPos['height'];
+ },
+
+ /** @id MochiKit.Position.clone */
+ clone: function (source, target) {
+ source = MochiKit.DOM.getElement(source);
+ target = MochiKit.DOM.getElement(target);
+ target.style.position = 'absolute';
+ var offsets = this.cumulativeOffset(source);
+ target.style.top = offsets.y + 'px';
+ target.style.left = offsets.x + 'px';
+ target.style.width = source.offsetWidth + 'px';
+ target.style.height = source.offsetHeight + 'px';
+ },
+
+ /** @id MochiKit.Position.page */
+ page: function (forElement) {
+ var valueT = 0;
+ var valueL = 0;
+
+ var element = forElement;
+ do {
+ valueT += element.offsetTop || 0;
+ valueL += element.offsetLeft || 0;
+
+ // Safari fix
+ if (element.offsetParent == document.body && MochiKit.Style.getStyle(element, 'position') == 'absolute') {
+ break;
+ }
+ } while (element = element.offsetParent);
+
+ element = forElement;
+ do {
+ valueT -= element.scrollTop || 0;
+ valueL -= element.scrollLeft || 0;
+ } while (element = element.parentNode);
+
+ return new MochiKit.Style.Coordinates(valueL, valueT);
+ }
+});
+
+MochiKit.Position.__new__ = function (win) {
+ var m = MochiKit.Base;
+ this.EXPORT_TAGS = {
+ ':common': this.EXPORT,
+ ':all': m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ m.nameFunctions(this);
+};
+
+MochiKit.Position.__new__(this); \ No newline at end of file
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Selector.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Selector.js
new file mode 100644
index 0000000000..f5d1afac31
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Selector.js
@@ -0,0 +1,431 @@
+/***
+
+MochiKit.Selector 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito and others. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Selector');
+ dojo.require('MochiKit.Base');
+ dojo.require('MochiKit.DOM');
+ dojo.require('MochiKit.Iter');
+}
+
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+ JSAN.use("MochiKit.DOM", []);
+ JSAN.use("MochiKit.Iter", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) === 'undefined' ||
+ typeof(MochiKit.DOM) === 'undefined' ||
+ typeof(MochiKit.Iter) === 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.Selector depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!";
+}
+
+if (typeof(MochiKit.Selector) == 'undefined') {
+ MochiKit.Selector = {};
+}
+
+MochiKit.Selector.NAME = "MochiKit.Selector";
+
+MochiKit.Selector.VERSION = "1.4";
+
+MochiKit.Selector.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.Selector.toString = function () {
+ return this.__repr__();
+};
+
+MochiKit.Selector.EXPORT = [
+ "Selector",
+ "findChildElements",
+ "findDocElements",
+ "$$"
+];
+
+MochiKit.Selector.EXPORT_OK = [
+];
+
+MochiKit.Selector.Selector = function (expression) {
+ this.params = {classNames: [], pseudoClassNames: []};
+ this.expression = expression.toString().replace(/(^\s+|\s+$)/g, '');
+ this.parseExpression();
+ this.compileMatcher();
+};
+
+MochiKit.Selector.Selector.prototype = {
+ /***
+
+ Selector class: convenient object to make CSS selections.
+
+ ***/
+ __class__: MochiKit.Selector.Selector,
+
+ /** @id MochiKit.Selector.Selector.prototype.parseExpression */
+ parseExpression: function () {
+ function abort(message) {
+ throw 'Parse error in selector: ' + message;
+ }
+
+ if (this.expression == '') {
+ abort('empty expression');
+ }
+
+ var repr = MochiKit.Base.repr;
+ var params = this.params;
+ var expr = this.expression;
+ var match, modifier, clause, rest;
+ while (match = expr.match(/^(.*)\[([a-z0-9_:-]+?)(?:([~\|!^$*]?=)(?:"([^"]*)"|([^\]\s]*)))?\]$/i)) {
+ params.attributes = params.attributes || [];
+ params.attributes.push({name: match[2], operator: match[3], value: match[4] || match[5] || ''});
+ expr = match[1];
+ }
+
+ if (expr == '*') {
+ return this.params.wildcard = true;
+ }
+
+ while (match = expr.match(/^([^a-z0-9_-])?([a-z0-9_-]+(?:\([^)]*\))?)(.*)/i)) {
+ modifier = match[1];
+ clause = match[2];
+ rest = match[3];
+ switch (modifier) {
+ case '#':
+ params.id = clause;
+ break;
+ case '.':
+ params.classNames.push(clause);
+ break;
+ case ':':
+ params.pseudoClassNames.push(clause);
+ break;
+ case '':
+ case undefined:
+ params.tagName = clause.toUpperCase();
+ break;
+ default:
+ abort(repr(expr));
+ }
+ expr = rest;
+ }
+
+ if (expr.length > 0) {
+ abort(repr(expr));
+ }
+ },
+
+ /** @id MochiKit.Selector.Selector.prototype.buildMatchExpression */
+ buildMatchExpression: function () {
+ var repr = MochiKit.Base.repr;
+ var params = this.params;
+ var conditions = [];
+ var clause, i;
+
+ function childElements(element) {
+ return "MochiKit.Base.filter(function (node) { return node.nodeType == 1; }, " + element + ".childNodes)";
+ }
+
+ if (params.wildcard) {
+ conditions.push('true');
+ }
+ if (clause = params.id) {
+ conditions.push('element.id == ' + repr(clause));
+ }
+ if (clause = params.tagName) {
+ conditions.push('element.tagName.toUpperCase() == ' + repr(clause));
+ }
+ if ((clause = params.classNames).length > 0) {
+ for (i = 0; i < clause.length; i++) {
+ conditions.push('MochiKit.DOM.hasElementClass(element, ' + repr(clause[i]) + ')');
+ }
+ }
+ if ((clause = params.pseudoClassNames).length > 0) {
+ for (i = 0; i < clause.length; i++) {
+ var match = clause[i].match(/^([^(]+)(?:\((.*)\))?$/);
+ var pseudoClass = match[1];
+ var pseudoClassArgument = match[2];
+ switch (pseudoClass) {
+ case 'root':
+ conditions.push('element.nodeType == 9 || element === element.ownerDocument.documentElement'); break;
+ case 'nth-child':
+ case 'nth-last-child':
+ case 'nth-of-type':
+ case 'nth-last-of-type':
+ match = pseudoClassArgument.match(/^((?:(\d+)n\+)?(\d+)|odd|even)$/);
+ if (!match) {
+ throw "Invalid argument to pseudo element nth-child: " + pseudoClassArgument;
+ }
+ var a, b;
+ if (match[0] == 'odd') {
+ a = 2;
+ b = 1;
+ } else if (match[0] == 'even') {
+ a = 2;
+ b = 0;
+ } else {
+ a = match[2] && parseInt(match) || null;
+ b = parseInt(match[3]);
+ }
+ conditions.push('this.nthChild(element,' + a + ',' + b
+ + ',' + !!pseudoClass.match('^nth-last') // Reverse
+ + ',' + !!pseudoClass.match('of-type$') // Restrict to same tagName
+ + ')');
+ break;
+ case 'first-child':
+ conditions.push('this.nthChild(element, null, 1)');
+ break;
+ case 'last-child':
+ conditions.push('this.nthChild(element, null, 1, true)');
+ break;
+ case 'first-of-type':
+ conditions.push('this.nthChild(element, null, 1, false, true)');
+ break;
+ case 'last-of-type':
+ conditions.push('this.nthChild(element, null, 1, true, true)');
+ break;
+ case 'only-child':
+ conditions.push(childElements('element.parentNode') + '.length == 1');
+ break;
+ case 'only-of-type':
+ conditions.push('MochiKit.Base.filter(function (node) { return node.tagName == element.tagName; }, ' + childElements('element.parentNode') + ').length == 1');
+ break;
+ case 'empty':
+ conditions.push('element.childNodes.length == 0');
+ break;
+ case 'enabled':
+ conditions.push('(this.isUIElement(element) && element.disabled === false)');
+ break;
+ case 'disabled':
+ conditions.push('(this.isUIElement(element) && element.disabled === true)');
+ break;
+ case 'checked':
+ conditions.push('(this.isUIElement(element) && element.checked === true)');
+ break;
+ case 'not':
+ var subselector = new MochiKit.Selector.Selector(pseudoClassArgument);
+ conditions.push('!( ' + subselector.buildMatchExpression() + ')')
+ break;
+ }
+ }
+ }
+ if (clause = params.attributes) {
+ MochiKit.Base.map(function (attribute) {
+ var value = 'MochiKit.DOM.getNodeAttribute(element, ' + repr(attribute.name) + ')';
+ var splitValueBy = function (delimiter) {
+ return value + '.split(' + repr(delimiter) + ')';
+ }
+
+ switch (attribute.operator) {
+ case '=':
+ conditions.push(value + ' == ' + repr(attribute.value));
+ break;
+ case '~=':
+ conditions.push(value + ' && MochiKit.Base.findValue(' + splitValueBy(' ') + ', ' + repr(attribute.value) + ') > -1');
+ break;
+ case '^=':
+ conditions.push(value + '.substring(0, ' + attribute.value.length + ') == ' + repr(attribute.value));
+ break;
+ case '$=':
+ conditions.push(value + '.substring(' + value + '.length - ' + attribute.value.length + ') == ' + repr(attribute.value));
+ break;
+ case '*=':
+ conditions.push(value + '.match(' + repr(attribute.value) + ')');
+ break;
+ case '|=':
+ conditions.push(
+ value + ' && ' + splitValueBy('-') + '[0].toUpperCase() == ' + repr(attribute.value.toUpperCase())
+ );
+ break;
+ case '!=':
+ conditions.push(value + ' != ' + repr(attribute.value));
+ break;
+ case '':
+ case undefined:
+ conditions.push(value + ' != null');
+ break;
+ default:
+ throw 'Unknown operator ' + attribute.operator + ' in selector';
+ }
+ }, clause);
+ }
+
+ return conditions.join(' && ');
+ },
+
+ /** @id MochiKit.Selector.Selector.prototype.compileMatcher */
+ compileMatcher: function () {
+ this.match = new Function('element', 'if (!element.tagName) return false; \
+ return ' + this.buildMatchExpression());
+ },
+
+ /** @id MochiKit.Selector.Selector.prototype.nthChild */
+ nthChild: function (element, a, b, reverse, sametag){
+ var siblings = MochiKit.Base.filter(function (node) {
+ return node.nodeType == 1;
+ }, element.parentNode.childNodes);
+ if (sametag) {
+ siblings = MochiKit.Base.filter(function (node) {
+ return node.tagName == element.tagName;
+ }, siblings);
+ }
+ if (reverse) {
+ siblings = MochiKit.Iter.reversed(siblings);
+ }
+ if (a) {
+ var actualIndex = MochiKit.Base.findIdentical(siblings, element);
+ return ((actualIndex + 1 - b) / a) % 1 == 0;
+ } else {
+ return b == MochiKit.Base.findIdentical(siblings, element) + 1;
+ }
+ },
+
+ /** @id MochiKit.Selector.Selector.prototype.isUIElement */
+ isUIElement: function (element) {
+ return MochiKit.Base.findValue(['input', 'button', 'select', 'option', 'textarea', 'object'],
+ element.tagName.toLowerCase()) > -1;
+ },
+
+ /** @id MochiKit.Selector.Selector.prototype.findElements */
+ findElements: function (scope, axis) {
+ var element;
+
+ if (axis == undefined) {
+ axis = "";
+ }
+
+ function inScope(element, scope) {
+ if (axis == "") {
+ return MochiKit.DOM.isChildNode(element, scope);
+ } else if (axis == ">") {
+ return element.parentNode == scope;
+ } else if (axis == "+") {
+ return element == nextSiblingElement(scope);
+ } else if (axis == "~") {
+ var sibling = scope;
+ while (sibling = nextSiblingElement(sibling)) {
+ if (element == sibling) {
+ return true;
+ }
+ }
+ return false;
+ } else {
+ throw "Invalid axis: " + axis;
+ }
+ }
+
+ if (element = MochiKit.DOM.getElement(this.params.id)) {
+ if (this.match(element)) {
+ if (!scope || inScope(element, scope)) {
+ return [element];
+ }
+ }
+ }
+
+ function nextSiblingElement(node) {
+ node = node.nextSibling;
+ while (node && node.nodeType != 1) {
+ node = node.nextSibling;
+ }
+ return node;
+ }
+
+ if (axis == "") {
+ scope = (scope || MochiKit.DOM.currentDocument()).getElementsByTagName(this.params.tagName || '*');
+ } else if (axis == ">") {
+ if (!scope) {
+ throw "> combinator not allowed without preceeding expression";
+ }
+ scope = MochiKit.Base.filter(function (node) {
+ return node.nodeType == 1;
+ }, scope.childNodes);
+ } else if (axis == "+") {
+ if (!scope) {
+ throw "+ combinator not allowed without preceeding expression";
+ }
+ scope = nextSiblingElement(scope) && [nextSiblingElement(scope)];
+ } else if (axis == "~") {
+ if (!scope) {
+ throw "~ combinator not allowed without preceeding expression";
+ }
+ var newscope = [];
+ while (nextSiblingElement(scope)) {
+ scope = nextSiblingElement(scope);
+ newscope.push(scope);
+ }
+ scope = newscope;
+ }
+
+ if (!scope) {
+ return [];
+ }
+
+ var results = MochiKit.Base.filter(MochiKit.Base.bind(function (scopeElt) {
+ return this.match(scopeElt);
+ }, this), scope);
+
+ return results;
+ },
+
+ /** @id MochiKit.Selector.Selector.prototype.repr */
+ repr: function () {
+ return 'Selector(' + this.expression + ')';
+ },
+
+ toString: MochiKit.Base.forwardCall("repr")
+};
+
+MochiKit.Base.update(MochiKit.Selector, {
+
+ /** @id MochiKit.Selector.findChildElements */
+ findChildElements: function (element, expressions) {
+ return MochiKit.Base.flattenArray(MochiKit.Base.map(function (expression) {
+ var nextScope = "";
+ return MochiKit.Iter.reduce(function (results, expr) {
+ if (match = expr.match(/^[>+~]$/)) {
+ nextScope = match[0];
+ return results;
+ } else {
+ var selector = new MochiKit.Selector.Selector(expr);
+ var elements = MochiKit.Iter.reduce(function (elements, result) {
+ return MochiKit.Base.extend(elements, selector.findElements(result || element, nextScope));
+ }, results, []);
+ nextScope = "";
+ return elements;
+ }
+ }, expression.replace(/(^\s+|\s+$)/g, '').split(/\s+/), [null]);
+ }, expressions));
+ },
+
+ findDocElements: function () {
+ return MochiKit.Selector.findChildElements(MochiKit.DOM.currentDocument(), arguments);
+ },
+
+ __new__: function () {
+ var m = MochiKit.Base;
+
+ this.$$ = this.findDocElements;
+
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ m.nameFunctions(this);
+ }
+});
+
+MochiKit.Selector.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.Selector);
+
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Signal.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Signal.js
new file mode 100644
index 0000000000..fd267a994e
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Signal.js
@@ -0,0 +1,899 @@
+/***
+
+MochiKit.Signal 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2006 Jonathan Gardner, Beau Hartshorne, Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Signal');
+ dojo.require('MochiKit.Base');
+ dojo.require('MochiKit.DOM');
+ dojo.require('MochiKit.Style');
+}
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use('MochiKit.Base', []);
+ JSAN.use('MochiKit.DOM', []);
+ JSAN.use('MochiKit.Style', []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined') {
+ throw '';
+ }
+} catch (e) {
+ throw 'MochiKit.Signal depends on MochiKit.Base!';
+}
+
+try {
+ if (typeof(MochiKit.DOM) == 'undefined') {
+ throw '';
+ }
+} catch (e) {
+ throw 'MochiKit.Signal depends on MochiKit.DOM!';
+}
+
+try {
+ if (typeof(MochiKit.Style) == 'undefined') {
+ throw '';
+ }
+} catch (e) {
+ throw 'MochiKit.Signal depends on MochiKit.Style!';
+}
+
+if (typeof(MochiKit.Signal) == 'undefined') {
+ MochiKit.Signal = {};
+}
+
+MochiKit.Signal.NAME = 'MochiKit.Signal';
+MochiKit.Signal.VERSION = '1.4';
+
+MochiKit.Signal._observers = [];
+
+/** @id MochiKit.Signal.Event */
+MochiKit.Signal.Event = function (src, e) {
+ this._event = e || window.event;
+ this._src = src;
+};
+
+MochiKit.Base.update(MochiKit.Signal.Event.prototype, {
+
+ __repr__: function () {
+ var repr = MochiKit.Base.repr;
+ var str = '{event(): ' + repr(this.event()) +
+ ', src(): ' + repr(this.src()) +
+ ', type(): ' + repr(this.type()) +
+ ', target(): ' + repr(this.target());
+
+ if (this.type() &&
+ this.type().indexOf('key') === 0 ||
+ this.type().indexOf('mouse') === 0 ||
+ this.type().indexOf('click') != -1 ||
+ this.type() == 'contextmenu') {
+ str += ', modifier(): ' + '{alt: ' + repr(this.modifier().alt) +
+ ', ctrl: ' + repr(this.modifier().ctrl) +
+ ', meta: ' + repr(this.modifier().meta) +
+ ', shift: ' + repr(this.modifier().shift) +
+ ', any: ' + repr(this.modifier().any) + '}';
+ }
+
+ if (this.type() && this.type().indexOf('key') === 0) {
+ str += ', key(): {code: ' + repr(this.key().code) +
+ ', string: ' + repr(this.key().string) + '}';
+ }
+
+ if (this.type() && (
+ this.type().indexOf('mouse') === 0 ||
+ this.type().indexOf('click') != -1 ||
+ this.type() == 'contextmenu')) {
+
+ str += ', mouse(): {page: ' + repr(this.mouse().page) +
+ ', client: ' + repr(this.mouse().client);
+
+ if (this.type() != 'mousemove') {
+ str += ', button: {left: ' + repr(this.mouse().button.left) +
+ ', middle: ' + repr(this.mouse().button.middle) +
+ ', right: ' + repr(this.mouse().button.right) + '}}';
+ } else {
+ str += '}';
+ }
+ }
+ if (this.type() == 'mouseover' || this.type() == 'mouseout') {
+ str += ', relatedTarget(): ' + repr(this.relatedTarget());
+ }
+ str += '}';
+ return str;
+ },
+
+ /** @id MochiKit.Signal.Event.prototype.toString */
+ toString: function () {
+ return this.__repr__();
+ },
+
+ /** @id MochiKit.Signal.Event.prototype.src */
+ src: function () {
+ return this._src;
+ },
+
+ /** @id MochiKit.Signal.Event.prototype.event */
+ event: function () {
+ return this._event;
+ },
+
+ /** @id MochiKit.Signal.Event.prototype.type */
+ type: function () {
+ return this._event.type || undefined;
+ },
+
+ /** @id MochiKit.Signal.Event.prototype.target */
+ target: function () {
+ return this._event.target || this._event.srcElement;
+ },
+
+ _relatedTarget: null,
+ /** @id MochiKit.Signal.Event.prototype.relatedTarget */
+ relatedTarget: function () {
+ if (this._relatedTarget !== null) {
+ return this._relatedTarget;
+ }
+
+ var elem = null;
+ if (this.type() == 'mouseover') {
+ elem = (this._event.relatedTarget ||
+ this._event.fromElement);
+ } else if (this.type() == 'mouseout') {
+ elem = (this._event.relatedTarget ||
+ this._event.toElement);
+ }
+ if (elem !== null) {
+ this._relatedTarget = elem;
+ return elem;
+ }
+
+ return undefined;
+ },
+
+ _modifier: null,
+ /** @id MochiKit.Signal.Event.prototype.modifier */
+ modifier: function () {
+ if (this._modifier !== null) {
+ return this._modifier;
+ }
+ var m = {};
+ m.alt = this._event.altKey;
+ m.ctrl = this._event.ctrlKey;
+ m.meta = this._event.metaKey || false; // IE and Opera punt here
+ m.shift = this._event.shiftKey;
+ m.any = m.alt || m.ctrl || m.shift || m.meta;
+ this._modifier = m;
+ return m;
+ },
+
+ _key: null,
+ /** @id MochiKit.Signal.Event.prototype.key */
+ key: function () {
+ if (this._key !== null) {
+ return this._key;
+ }
+ var k = {};
+ if (this.type() && this.type().indexOf('key') === 0) {
+
+ /*
+
+ If you're looking for a special key, look for it in keydown or
+ keyup, but never keypress. If you're looking for a Unicode
+ chracter, look for it with keypress, but never keyup or
+ keydown.
+
+ Notes:
+
+ FF key event behavior:
+ key event charCode keyCode
+ DOWN ku,kd 0 40
+ DOWN kp 0 40
+ ESC ku,kd 0 27
+ ESC kp 0 27
+ a ku,kd 0 65
+ a kp 97 0
+ shift+a ku,kd 0 65
+ shift+a kp 65 0
+ 1 ku,kd 0 49
+ 1 kp 49 0
+ shift+1 ku,kd 0 0
+ shift+1 kp 33 0
+
+ IE key event behavior:
+ (IE doesn't fire keypress events for special keys.)
+ key event keyCode
+ DOWN ku,kd 40
+ DOWN kp undefined
+ ESC ku,kd 27
+ ESC kp 27
+ a ku,kd 65
+ a kp 97
+ shift+a ku,kd 65
+ shift+a kp 65
+ 1 ku,kd 49
+ 1 kp 49
+ shift+1 ku,kd 49
+ shift+1 kp 33
+
+ Safari key event behavior:
+ (Safari sets charCode and keyCode to something weird for
+ special keys.)
+ key event charCode keyCode
+ DOWN ku,kd 63233 40
+ DOWN kp 63233 63233
+ ESC ku,kd 27 27
+ ESC kp 27 27
+ a ku,kd 97 65
+ a kp 97 97
+ shift+a ku,kd 65 65
+ shift+a kp 65 65
+ 1 ku,kd 49 49
+ 1 kp 49 49
+ shift+1 ku,kd 33 49
+ shift+1 kp 33 33
+
+ */
+
+ /* look for special keys here */
+ if (this.type() == 'keydown' || this.type() == 'keyup') {
+ k.code = this._event.keyCode;
+ k.string = (MochiKit.Signal._specialKeys[k.code] ||
+ 'KEY_UNKNOWN');
+ this._key = k;
+ return k;
+
+ /* look for characters here */
+ } else if (this.type() == 'keypress') {
+
+ /*
+
+ Special key behavior:
+
+ IE: does not fire keypress events for special keys
+ FF: sets charCode to 0, and sets the correct keyCode
+ Safari: sets keyCode and charCode to something stupid
+
+ */
+
+ k.code = 0;
+ k.string = '';
+
+ if (typeof(this._event.charCode) != 'undefined' &&
+ this._event.charCode !== 0 &&
+ !MochiKit.Signal._specialMacKeys[this._event.charCode]) {
+ k.code = this._event.charCode;
+ k.string = String.fromCharCode(k.code);
+ } else if (this._event.keyCode &&
+ typeof(this._event.charCode) == 'undefined') { // IE
+ k.code = this._event.keyCode;
+ k.string = String.fromCharCode(k.code);
+ }
+
+ this._key = k;
+ return k;
+ }
+ }
+ return undefined;
+ },
+
+ _mouse: null,
+ /** @id MochiKit.Signal.Event.prototype.mouse */
+ mouse: function () {
+ if (this._mouse !== null) {
+ return this._mouse;
+ }
+
+ var m = {};
+ var e = this._event;
+
+ if (this.type() && (
+ this.type().indexOf('mouse') === 0 ||
+ this.type().indexOf('click') != -1 ||
+ this.type() == 'contextmenu')) {
+
+ m.client = new MochiKit.Style.Coordinates(0, 0);
+ if (e.clientX || e.clientY) {
+ m.client.x = (!e.clientX || e.clientX < 0) ? 0 : e.clientX;
+ m.client.y = (!e.clientY || e.clientY < 0) ? 0 : e.clientY;
+ }
+
+ m.page = new MochiKit.Style.Coordinates(0, 0);
+ if (e.pageX || e.pageY) {
+ m.page.x = (!e.pageX || e.pageX < 0) ? 0 : e.pageX;
+ m.page.y = (!e.pageY || e.pageY < 0) ? 0 : e.pageY;
+ } else {
+ /*
+
+ The IE shortcut can be off by two. We fix it. See:
+ http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
+
+ This is similar to the method used in
+ MochiKit.Style.getElementPosition().
+
+ */
+ var de = MochiKit.DOM._document.documentElement;
+ var b = MochiKit.DOM._document.body;
+
+ m.page.x = e.clientX +
+ (de.scrollLeft || b.scrollLeft) -
+ (de.clientLeft || 0);
+
+ m.page.y = e.clientY +
+ (de.scrollTop || b.scrollTop) -
+ (de.clientTop || 0);
+
+ }
+ if (this.type() != 'mousemove') {
+ m.button = {};
+ m.button.left = false;
+ m.button.right = false;
+ m.button.middle = false;
+
+ /* we could check e.button, but which is more consistent */
+ if (e.which) {
+ m.button.left = (e.which == 1);
+ m.button.middle = (e.which == 2);
+ m.button.right = (e.which == 3);
+
+ /*
+
+ Mac browsers and right click:
+
+ - Safari doesn't fire any click events on a right
+ click:
+ http://bugs.webkit.org/show_bug.cgi?id=6595
+
+ - Firefox fires the event, and sets ctrlKey = true
+
+ - Opera fires the event, and sets metaKey = true
+
+ oncontextmenu is fired on right clicks between
+ browsers and across platforms.
+
+ */
+
+ } else {
+ m.button.left = !!(e.button & 1);
+ m.button.right = !!(e.button & 2);
+ m.button.middle = !!(e.button & 4);
+ }
+ }
+ this._mouse = m;
+ return m;
+ }
+ return undefined;
+ },
+
+ /** @id MochiKit.Signal.Event.prototype.stop */
+ stop: function () {
+ this.stopPropagation();
+ this.preventDefault();
+ },
+
+ /** @id MochiKit.Signal.Event.prototype.stopPropagation */
+ stopPropagation: function () {
+ if (this._event.stopPropagation) {
+ this._event.stopPropagation();
+ } else {
+ this._event.cancelBubble = true;
+ }
+ },
+
+ /** @id MochiKit.Signal.Event.prototype.preventDefault */
+ preventDefault: function () {
+ if (this._event.preventDefault) {
+ this._event.preventDefault();
+ } else if (this._confirmUnload === null) {
+ this._event.returnValue = false;
+ }
+ },
+
+ _confirmUnload: null,
+
+ /** @id MochiKit.Signal.Event.prototype.confirmUnload */
+ confirmUnload: function (msg) {
+ if (this.type() == 'beforeunload') {
+ this._confirmUnload = msg;
+ this._event.returnValue = msg;
+ }
+ }
+});
+
+/* Safari sets keyCode to these special values onkeypress. */
+MochiKit.Signal._specialMacKeys = {
+ 3: 'KEY_ENTER',
+ 63289: 'KEY_NUM_PAD_CLEAR',
+ 63276: 'KEY_PAGE_UP',
+ 63277: 'KEY_PAGE_DOWN',
+ 63275: 'KEY_END',
+ 63273: 'KEY_HOME',
+ 63234: 'KEY_ARROW_LEFT',
+ 63232: 'KEY_ARROW_UP',
+ 63235: 'KEY_ARROW_RIGHT',
+ 63233: 'KEY_ARROW_DOWN',
+ 63302: 'KEY_INSERT',
+ 63272: 'KEY_DELETE'
+};
+
+/* for KEY_F1 - KEY_F12 */
+(function () {
+ var _specialMacKeys = MochiKit.Signal._specialMacKeys;
+ for (i = 63236; i <= 63242; i++) {
+ // no F0
+ _specialMacKeys[i] = 'KEY_F' + (i - 63236 + 1);
+ }
+})();
+
+/* Standard keyboard key codes. */
+MochiKit.Signal._specialKeys = {
+ 8: 'KEY_BACKSPACE',
+ 9: 'KEY_TAB',
+ 12: 'KEY_NUM_PAD_CLEAR', // weird, for Safari and Mac FF only
+ 13: 'KEY_ENTER',
+ 16: 'KEY_SHIFT',
+ 17: 'KEY_CTRL',
+ 18: 'KEY_ALT',
+ 19: 'KEY_PAUSE',
+ 20: 'KEY_CAPS_LOCK',
+ 27: 'KEY_ESCAPE',
+ 32: 'KEY_SPACEBAR',
+ 33: 'KEY_PAGE_UP',
+ 34: 'KEY_PAGE_DOWN',
+ 35: 'KEY_END',
+ 36: 'KEY_HOME',
+ 37: 'KEY_ARROW_LEFT',
+ 38: 'KEY_ARROW_UP',
+ 39: 'KEY_ARROW_RIGHT',
+ 40: 'KEY_ARROW_DOWN',
+ 44: 'KEY_PRINT_SCREEN',
+ 45: 'KEY_INSERT',
+ 46: 'KEY_DELETE',
+ 59: 'KEY_SEMICOLON', // weird, for Safari and IE only
+ 91: 'KEY_WINDOWS_LEFT',
+ 92: 'KEY_WINDOWS_RIGHT',
+ 93: 'KEY_SELECT',
+ 106: 'KEY_NUM_PAD_ASTERISK',
+ 107: 'KEY_NUM_PAD_PLUS_SIGN',
+ 109: 'KEY_NUM_PAD_HYPHEN-MINUS',
+ 110: 'KEY_NUM_PAD_FULL_STOP',
+ 111: 'KEY_NUM_PAD_SOLIDUS',
+ 144: 'KEY_NUM_LOCK',
+ 145: 'KEY_SCROLL_LOCK',
+ 186: 'KEY_SEMICOLON',
+ 187: 'KEY_EQUALS_SIGN',
+ 188: 'KEY_COMMA',
+ 189: 'KEY_HYPHEN-MINUS',
+ 190: 'KEY_FULL_STOP',
+ 191: 'KEY_SOLIDUS',
+ 192: 'KEY_GRAVE_ACCENT',
+ 219: 'KEY_LEFT_SQUARE_BRACKET',
+ 220: 'KEY_REVERSE_SOLIDUS',
+ 221: 'KEY_RIGHT_SQUARE_BRACKET',
+ 222: 'KEY_APOSTROPHE'
+ // undefined: 'KEY_UNKNOWN'
+};
+
+(function () {
+ /* for KEY_0 - KEY_9 */
+ var _specialKeys = MochiKit.Signal._specialKeys;
+ for (var i = 48; i <= 57; i++) {
+ _specialKeys[i] = 'KEY_' + (i - 48);
+ }
+
+ /* for KEY_A - KEY_Z */
+ for (i = 65; i <= 90; i++) {
+ _specialKeys[i] = 'KEY_' + String.fromCharCode(i);
+ }
+
+ /* for KEY_NUM_PAD_0 - KEY_NUM_PAD_9 */
+ for (i = 96; i <= 105; i++) {
+ _specialKeys[i] = 'KEY_NUM_PAD_' + (i - 96);
+ }
+
+ /* for KEY_F1 - KEY_F12 */
+ for (i = 112; i <= 123; i++) {
+ // no F0
+ _specialKeys[i] = 'KEY_F' + (i - 112 + 1);
+ }
+})();
+
+/* Internal object to keep track of created signals. */
+MochiKit.Signal.Ident = function (ident) {
+ this.source = ident.source;
+ this.signal = ident.signal;
+ this.listener = ident.listener;
+ this.isDOM = ident.isDOM;
+ this.objOrFunc = ident.objOrFunc;
+ this.funcOrStr = ident.funcOrStr;
+ this.connected = ident.connected;
+};
+
+MochiKit.Signal.Ident.prototype = {};
+
+MochiKit.Base.update(MochiKit.Signal, {
+
+ __repr__: function () {
+ return '[' + this.NAME + ' ' + this.VERSION + ']';
+ },
+
+ toString: function () {
+ return this.__repr__();
+ },
+
+ _unloadCache: function () {
+ var self = MochiKit.Signal;
+ var observers = self._observers;
+
+ for (var i = 0; i < observers.length; i++) {
+ if (observers[i].signal !== 'onload' && observers[i].signal !== 'onunload') {
+ self._disconnect(observers[i]);
+ }
+ }
+ },
+
+ _listener: function (src, sig, func, obj, isDOM) {
+ var self = MochiKit.Signal;
+ var E = self.Event;
+ if (!isDOM) {
+ return MochiKit.Base.bind(func, obj);
+ }
+ obj = obj || src;
+ if (typeof(func) == "string") {
+ if (sig === 'onload' || sig === 'onunload') {
+ return function (nativeEvent) {
+ obj[func].apply(obj, [new E(src, nativeEvent)]);
+
+ var ident = new MochiKit.Signal.Ident({
+ source: src, signal: sig, objOrFunc: obj, funcOrStr: func});
+
+ MochiKit.Signal._disconnect(ident);
+ };
+ } else {
+ return function (nativeEvent) {
+ obj[func].apply(obj, [new E(src, nativeEvent)]);
+ };
+ }
+ } else {
+ if (sig === 'onload' || sig === 'onunload') {
+ return function (nativeEvent) {
+ func.apply(obj, [new E(src, nativeEvent)]);
+ MochiKit.Signal.disconnect(src, sig, func);
+
+ var ident = new MochiKit.Signal.Ident({
+ source: src, signal: sig, objOrFunc: func});
+
+ MochiKit.Signal._disconnect(ident);
+ };
+ } else {
+ return function (nativeEvent) {
+ func.apply(obj, [new E(src, nativeEvent)]);
+ };
+ }
+ }
+ },
+
+ _browserAlreadyHasMouseEnterAndLeave: function () {
+ return /MSIE/.test(navigator.userAgent);
+ },
+
+ _mouseEnterListener: function (src, sig, func, obj) {
+ var E = MochiKit.Signal.Event;
+ return function (nativeEvent) {
+ var e = new E(src, nativeEvent);
+ try {
+ e.relatedTarget().nodeName;
+ } catch (err) {
+ /* probably hit a permission denied error; possibly one of
+ * firefox's screwy anonymous DIVs inside an input element.
+ * Allow this event to propogate up.
+ */
+ return;
+ }
+ e.stop();
+ if (MochiKit.DOM.isChildNode(e.relatedTarget(), src)) {
+ /* We've moved between our node and a child. Ignore. */
+ return;
+ }
+ e.type = function () { return sig; };
+ if (typeof(func) == "string") {
+ return obj[func].apply(obj, [e]);
+ } else {
+ return func.apply(obj, [e]);
+ }
+ };
+ },
+
+ _getDestPair: function (objOrFunc, funcOrStr) {
+ var obj = null;
+ var func = null;
+ if (typeof(funcOrStr) != 'undefined') {
+ obj = objOrFunc;
+ func = funcOrStr;
+ if (typeof(funcOrStr) == 'string') {
+ if (typeof(objOrFunc[funcOrStr]) != "function") {
+ throw new Error("'funcOrStr' must be a function on 'objOrFunc'");
+ }
+ } else if (typeof(funcOrStr) != 'function') {
+ throw new Error("'funcOrStr' must be a function or string");
+ }
+ } else if (typeof(objOrFunc) != "function") {
+ throw new Error("'objOrFunc' must be a function if 'funcOrStr' is not given");
+ } else {
+ func = objOrFunc;
+ }
+ return [obj, func];
+ },
+
+ /** @id MochiKit.Signal.connect */
+ connect: function (src, sig, objOrFunc/* optional */, funcOrStr) {
+ src = MochiKit.DOM.getElement(src);
+ var self = MochiKit.Signal;
+
+ if (typeof(sig) != 'string') {
+ throw new Error("'sig' must be a string");
+ }
+
+ var destPair = self._getDestPair(objOrFunc, funcOrStr);
+ var obj = destPair[0];
+ var func = destPair[1];
+ if (typeof(obj) == 'undefined' || obj === null) {
+ obj = src;
+ }
+
+ var isDOM = !!(src.addEventListener || src.attachEvent);
+ if (isDOM && (sig === "onmouseenter" || sig === "onmouseleave")
+ && !self._browserAlreadyHasMouseEnterAndLeave()) {
+ var listener = self._mouseEnterListener(src, sig.substr(2), func, obj);
+ if (sig === "onmouseenter") {
+ sig = "onmouseover";
+ } else {
+ sig = "onmouseout";
+ }
+ } else {
+ var listener = self._listener(src, sig, func, obj, isDOM);
+ }
+
+ if (src.addEventListener) {
+ src.addEventListener(sig.substr(2), listener, false);
+ } else if (src.attachEvent) {
+ src.attachEvent(sig, listener); // useCapture unsupported
+ }
+
+ var ident = new MochiKit.Signal.Ident({
+ source: src,
+ signal: sig,
+ listener: listener,
+ isDOM: isDOM,
+ objOrFunc: objOrFunc,
+ funcOrStr: funcOrStr,
+ connected: true
+ });
+ self._observers.push(ident);
+
+ if (!isDOM && typeof(src.__connect__) == 'function') {
+ var args = MochiKit.Base.extend([ident], arguments, 1);
+ src.__connect__.apply(src, args);
+ }
+
+ return ident;
+ },
+
+ _disconnect: function (ident) {
+ // already disconnected
+ if (!ident.connected) {
+ return;
+ }
+ ident.connected = false;
+ // check isDOM
+ if (!ident.isDOM) {
+ return;
+ }
+ var src = ident.source;
+ var sig = ident.signal;
+ var listener = ident.listener;
+
+ if (src.removeEventListener) {
+ src.removeEventListener(sig.substr(2), listener, false);
+ } else if (src.detachEvent) {
+ src.detachEvent(sig, listener); // useCapture unsupported
+ } else {
+ throw new Error("'src' must be a DOM element");
+ }
+ },
+
+ /** @id MochiKit.Signal.disconnect */
+ disconnect: function (ident) {
+ var self = MochiKit.Signal;
+ var observers = self._observers;
+ var m = MochiKit.Base;
+ if (arguments.length > 1) {
+ // compatibility API
+ var src = MochiKit.DOM.getElement(arguments[0]);
+ var sig = arguments[1];
+ var obj = arguments[2];
+ var func = arguments[3];
+ for (var i = observers.length - 1; i >= 0; i--) {
+ var o = observers[i];
+ if (o.source === src && o.signal === sig && o.objOrFunc === obj && o.funcOrStr === func) {
+ self._disconnect(o);
+ if (!self._lock) {
+ observers.splice(i, 1);
+ } else {
+ self._dirty = true;
+ }
+ return true;
+ }
+ }
+ } else {
+ var idx = m.findIdentical(observers, ident);
+ if (idx >= 0) {
+ self._disconnect(ident);
+ if (!self._lock) {
+ observers.splice(idx, 1);
+ } else {
+ self._dirty = true;
+ }
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /** @id MochiKit.Signal.disconnectAllTo */
+ disconnectAllTo: function (objOrFunc, /* optional */funcOrStr) {
+ var self = MochiKit.Signal;
+ var observers = self._observers;
+ var disconnect = self._disconnect;
+ var locked = self._lock;
+ var dirty = self._dirty;
+ if (typeof(funcOrStr) === 'undefined') {
+ funcOrStr = null;
+ }
+ for (var i = observers.length - 1; i >= 0; i--) {
+ var ident = observers[i];
+ if (ident.objOrFunc === objOrFunc &&
+ (funcOrStr === null || ident.funcOrStr === funcOrStr)) {
+ disconnect(ident);
+ if (locked) {
+ dirty = true;
+ } else {
+ observers.splice(i, 1);
+ }
+ }
+ }
+ self._dirty = dirty;
+ },
+
+ /** @id MochiKit.Signal.disconnectAll */
+ disconnectAll: function (src/* optional */, sig) {
+ src = MochiKit.DOM.getElement(src);
+ var m = MochiKit.Base;
+ var signals = m.flattenArguments(m.extend(null, arguments, 1));
+ var self = MochiKit.Signal;
+ var disconnect = self._disconnect;
+ var observers = self._observers;
+ var i, ident;
+ var locked = self._lock;
+ var dirty = self._dirty;
+ if (signals.length === 0) {
+ // disconnect all
+ for (i = observers.length - 1; i >= 0; i--) {
+ ident = observers[i];
+ if (ident.source === src) {
+ disconnect(ident);
+ if (!locked) {
+ observers.splice(i, 1);
+ } else {
+ dirty = true;
+ }
+ }
+ }
+ } else {
+ var sigs = {};
+ for (i = 0; i < signals.length; i++) {
+ sigs[signals[i]] = true;
+ }
+ for (i = observers.length - 1; i >= 0; i--) {
+ ident = observers[i];
+ if (ident.source === src && ident.signal in sigs) {
+ disconnect(ident);
+ if (!locked) {
+ observers.splice(i, 1);
+ } else {
+ dirty = true;
+ }
+ }
+ }
+ }
+ self._dirty = dirty;
+ },
+
+ /** @id MochiKit.Signal.signal */
+ signal: function (src, sig) {
+ var self = MochiKit.Signal;
+ var observers = self._observers;
+ src = MochiKit.DOM.getElement(src);
+ var args = MochiKit.Base.extend(null, arguments, 2);
+ var errors = [];
+ self._lock = true;
+ for (var i = 0; i < observers.length; i++) {
+ var ident = observers[i];
+ if (ident.source === src && ident.signal === sig &&
+ ident.connected) {
+ try {
+ ident.listener.apply(src, args);
+ } catch (e) {
+ errors.push(e);
+ }
+ }
+ }
+ self._lock = false;
+ if (self._dirty) {
+ self._dirty = false;
+ for (var i = observers.length - 1; i >= 0; i--) {
+ if (!observers[i].connected) {
+ observers.splice(i, 1);
+ }
+ }
+ }
+ if (errors.length == 1) {
+ throw errors[0];
+ } else if (errors.length > 1) {
+ var e = new Error("Multiple errors thrown in handling 'sig', see errors property");
+ e.errors = errors;
+ throw e;
+ }
+ }
+
+});
+
+MochiKit.Signal.EXPORT_OK = [];
+
+MochiKit.Signal.EXPORT = [
+ 'connect',
+ 'disconnect',
+ 'signal',
+ 'disconnectAll',
+ 'disconnectAllTo'
+];
+
+MochiKit.Signal.__new__ = function (win) {
+ var m = MochiKit.Base;
+ this._document = document;
+ this._window = win;
+ this._lock = false;
+ this._dirty = false;
+
+ try {
+ this.connect(window, 'onunload', this._unloadCache);
+ } catch (e) {
+ // pass: might not be a browser
+ }
+
+ this.EXPORT_TAGS = {
+ ':common': this.EXPORT,
+ ':all': m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ m.nameFunctions(this);
+};
+
+MochiKit.Signal.__new__(this);
+
+//
+// XXX: Internet Explorer blows
+//
+if (MochiKit.__export__) {
+ connect = MochiKit.Signal.connect;
+ disconnect = MochiKit.Signal.disconnect;
+ disconnectAll = MochiKit.Signal.disconnectAll;
+ signal = MochiKit.Signal.signal;
+}
+
+MochiKit.Base._exportSymbols(this, MochiKit.Signal);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Sortable.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Sortable.js
new file mode 100644
index 0000000000..8976ec0b27
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Sortable.js
@@ -0,0 +1,589 @@
+/***
+Copyright (c) 2005 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
+ Mochi-ized By Thomas Herve (_firstname_@nimail.org)
+
+See scriptaculous.js for full license.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Sortable');
+ dojo.require('MochiKit.Base');
+ dojo.require('MochiKit.DOM');
+ dojo.require('MochiKit.Iter');
+}
+
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+ JSAN.use("MochiKit.DOM", []);
+ JSAN.use("MochiKit.Iter", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined' ||
+ typeof(MochiKit.DOM) == 'undefined' ||
+ typeof(MochiKit.Iter) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.DragAndDrop depends on MochiKit.Base, MochiKit.DOM and MochiKit.Iter!";
+}
+
+if (typeof(MochiKit.Sortable) == 'undefined') {
+ MochiKit.Sortable = {};
+}
+
+MochiKit.Sortable.NAME = 'MochiKit.Sortable';
+MochiKit.Sortable.VERSION = '1.4';
+
+MochiKit.Sortable.__repr__ = function () {
+ return '[' + this.NAME + ' ' + this.VERSION + ']';
+};
+
+MochiKit.Sortable.toString = function () {
+ return this.__repr__();
+};
+
+MochiKit.Sortable.EXPORT = [
+];
+
+MochiKit.Sortable.EXPORT_OK = [
+];
+
+MochiKit.Base.update(MochiKit.Sortable, {
+ /***
+
+ Manage sortables. Mainly use the create function to add a sortable.
+
+ ***/
+ sortables: {},
+
+ _findRootElement: function (element) {
+ while (element.tagName.toUpperCase() != "BODY") {
+ if (element.id && MochiKit.Sortable.sortables[element.id]) {
+ return element;
+ }
+ element = element.parentNode;
+ }
+ },
+
+ /** @id MochiKit.Sortable.options */
+ options: function (element) {
+ element = MochiKit.Sortable._findRootElement(MochiKit.DOM.getElement(element));
+ if (!element) {
+ return;
+ }
+ return MochiKit.Sortable.sortables[element.id];
+ },
+
+ /** @id MochiKit.Sortable.destroy */
+ destroy: function (element){
+ var s = MochiKit.Sortable.options(element);
+ var b = MochiKit.Base;
+ var d = MochiKit.DragAndDrop;
+
+ if (s) {
+ MochiKit.Signal.disconnect(s.startHandle);
+ MochiKit.Signal.disconnect(s.endHandle);
+ b.map(function (dr) {
+ d.Droppables.remove(dr);
+ }, s.droppables);
+ b.map(function (dr) {
+ dr.destroy();
+ }, s.draggables);
+
+ delete MochiKit.Sortable.sortables[s.element.id];
+ }
+ },
+
+ /** @id MochiKit.Sortable.create */
+ create: function (element, options) {
+ element = MochiKit.DOM.getElement(element);
+ var self = MochiKit.Sortable;
+
+ /** @id MochiKit.Sortable.options */
+ options = MochiKit.Base.update({
+
+ /** @id MochiKit.Sortable.element */
+ element: element,
+
+ /** @id MochiKit.Sortable.tag */
+ tag: 'li', // assumes li children, override with tag: 'tagname'
+
+ /** @id MochiKit.Sortable.dropOnEmpty */
+ dropOnEmpty: false,
+
+ /** @id MochiKit.Sortable.tree */
+ tree: false,
+
+ /** @id MochiKit.Sortable.treeTag */
+ treeTag: 'ul',
+
+ /** @id MochiKit.Sortable.overlap */
+ overlap: 'vertical', // one of 'vertical', 'horizontal'
+
+ /** @id MochiKit.Sortable.constraint */
+ constraint: 'vertical', // one of 'vertical', 'horizontal', false
+ // also takes array of elements (or ids); or false
+
+ /** @id MochiKit.Sortable.containment */
+ containment: [element],
+
+ /** @id MochiKit.Sortable.handle */
+ handle: false, // or a CSS class
+
+ /** @id MochiKit.Sortable.only */
+ only: false,
+
+ /** @id MochiKit.Sortable.hoverclass */
+ hoverclass: null,
+
+ /** @id MochiKit.Sortable.ghosting */
+ ghosting: false,
+
+ /** @id MochiKit.Sortable.scroll */
+ scroll: false,
+
+ /** @id MochiKit.Sortable.scrollSensitivity */
+ scrollSensitivity: 20,
+
+ /** @id MochiKit.Sortable.scrollSpeed */
+ scrollSpeed: 15,
+
+ /** @id MochiKit.Sortable.format */
+ format: /^[^_]*_(.*)$/,
+
+ /** @id MochiKit.Sortable.onChange */
+ onChange: MochiKit.Base.noop,
+
+ /** @id MochiKit.Sortable.onUpdate */
+ onUpdate: MochiKit.Base.noop,
+
+ /** @id MochiKit.Sortable.accept */
+ accept: null
+ }, options);
+
+ // clear any old sortable with same element
+ self.destroy(element);
+
+ // build options for the draggables
+ var options_for_draggable = {
+ revert: true,
+ ghosting: options.ghosting,
+ scroll: options.scroll,
+ scrollSensitivity: options.scrollSensitivity,
+ scrollSpeed: options.scrollSpeed,
+ constraint: options.constraint,
+ handle: options.handle
+ };
+
+ if (options.starteffect) {
+ options_for_draggable.starteffect = options.starteffect;
+ }
+
+ if (options.reverteffect) {
+ options_for_draggable.reverteffect = options.reverteffect;
+ } else if (options.ghosting) {
+ options_for_draggable.reverteffect = function (innerelement) {
+ innerelement.style.top = 0;
+ innerelement.style.left = 0;
+ };
+ }
+
+ if (options.endeffect) {
+ options_for_draggable.endeffect = options.endeffect;
+ }
+
+ if (options.zindex) {
+ options_for_draggable.zindex = options.zindex;
+ }
+
+ // build options for the droppables
+ var options_for_droppable = {
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass,
+ onhover: self.onHover,
+ tree: options.tree,
+ accept: options.accept
+ }
+
+ var options_for_tree = {
+ onhover: self.onEmptyHover,
+ overlap: options.overlap,
+ containment: options.containment,
+ hoverclass: options.hoverclass,
+ accept: options.accept
+ }
+
+ // fix for gecko engine
+ MochiKit.DOM.removeEmptyTextNodes(element);
+
+ options.draggables = [];
+ options.droppables = [];
+
+ // drop on empty handling
+ if (options.dropOnEmpty || options.tree) {
+ new MochiKit.DragAndDrop.Droppable(element, options_for_tree);
+ options.droppables.push(element);
+ }
+ MochiKit.Base.map(function (e) {
+ // handles are per-draggable
+ var handle = options.handle ?
+ MochiKit.DOM.getFirstElementByTagAndClassName(null,
+ options.handle, e) : e;
+ options.draggables.push(
+ new MochiKit.DragAndDrop.Draggable(e,
+ MochiKit.Base.update(options_for_draggable,
+ {handle: handle})));
+ new MochiKit.DragAndDrop.Droppable(e, options_for_droppable);
+ if (options.tree) {
+ e.treeNode = element;
+ }
+ options.droppables.push(e);
+ }, (self.findElements(element, options) || []));
+
+ if (options.tree) {
+ MochiKit.Base.map(function (e) {
+ new MochiKit.DragAndDrop.Droppable(e, options_for_tree);
+ e.treeNode = element;
+ options.droppables.push(e);
+ }, (self.findTreeElements(element, options) || []));
+ }
+
+ // keep reference
+ self.sortables[element.id] = options;
+
+ options.lastValue = self.serialize(element);
+ options.startHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'start',
+ MochiKit.Base.partial(self.onStart, element));
+ options.endHandle = MochiKit.Signal.connect(MochiKit.DragAndDrop.Draggables, 'end',
+ MochiKit.Base.partial(self.onEnd, element));
+ },
+
+ /** @id MochiKit.Sortable.onStart */
+ onStart: function (element, draggable) {
+ var self = MochiKit.Sortable;
+ var options = self.options(element);
+ options.lastValue = self.serialize(options.element);
+ },
+
+ /** @id MochiKit.Sortable.onEnd */
+ onEnd: function (element, draggable) {
+ var self = MochiKit.Sortable;
+ self.unmark();
+ var options = self.options(element);
+ if (options.lastValue != self.serialize(options.element)) {
+ options.onUpdate(options.element);
+ }
+ },
+
+ // return all suitable-for-sortable elements in a guaranteed order
+
+ /** @id MochiKit.Sortable.findElements */
+ findElements: function (element, options) {
+ return MochiKit.Sortable.findChildren(
+ element, options.only, options.tree ? true : false, options.tag);
+ },
+
+ /** @id MochiKit.Sortable.findTreeElements */
+ findTreeElements: function (element, options) {
+ return MochiKit.Sortable.findChildren(
+ element, options.only, options.tree ? true : false, options.treeTag);
+ },
+
+ /** @id MochiKit.Sortable.findChildren */
+ findChildren: function (element, only, recursive, tagName) {
+ if (!element.hasChildNodes()) {
+ return null;
+ }
+ tagName = tagName.toUpperCase();
+ if (only) {
+ only = MochiKit.Base.flattenArray([only]);
+ }
+ var elements = [];
+ MochiKit.Base.map(function (e) {
+ if (e.tagName &&
+ e.tagName.toUpperCase() == tagName &&
+ (!only ||
+ MochiKit.Iter.some(only, function (c) {
+ return MochiKit.DOM.hasElementClass(e, c);
+ }))) {
+ elements.push(e);
+ }
+ if (recursive) {
+ var grandchildren = MochiKit.Sortable.findChildren(e, only, recursive, tagName);
+ if (grandchildren && grandchildren.length > 0) {
+ elements = elements.concat(grandchildren);
+ }
+ }
+ }, element.childNodes);
+ return elements;
+ },
+
+ /** @id MochiKit.Sortable.onHover */
+ onHover: function (element, dropon, overlap) {
+ if (MochiKit.DOM.isParent(dropon, element)) {
+ return;
+ }
+ var self = MochiKit.Sortable;
+
+ if (overlap > .33 && overlap < .66 && self.options(dropon).tree) {
+ return;
+ } else if (overlap > 0.5) {
+ self.mark(dropon, 'before');
+ if (dropon.previousSibling != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = 'hidden'; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, dropon);
+ if (dropon.parentNode != oldParentNode) {
+ self.options(oldParentNode).onChange(element);
+ }
+ self.options(dropon.parentNode).onChange(element);
+ }
+ } else {
+ self.mark(dropon, 'after');
+ var nextElement = dropon.nextSibling || null;
+ if (nextElement != element) {
+ var oldParentNode = element.parentNode;
+ element.style.visibility = 'hidden'; // fix gecko rendering
+ dropon.parentNode.insertBefore(element, nextElement);
+ if (dropon.parentNode != oldParentNode) {
+ self.options(oldParentNode).onChange(element);
+ }
+ self.options(dropon.parentNode).onChange(element);
+ }
+ }
+ },
+
+ _offsetSize: function (element, type) {
+ if (type == 'vertical' || type == 'height') {
+ return element.offsetHeight;
+ } else {
+ return element.offsetWidth;
+ }
+ },
+
+ /** @id MochiKit.Sortable.onEmptyHover */
+ onEmptyHover: function (element, dropon, overlap) {
+ var oldParentNode = element.parentNode;
+ var self = MochiKit.Sortable;
+ var droponOptions = self.options(dropon);
+
+ if (!MochiKit.DOM.isParent(dropon, element)) {
+ var index;
+
+ var children = self.findElements(dropon, {tag: droponOptions.tag,
+ only: droponOptions.only});
+ var child = null;
+
+ if (children) {
+ var offset = self._offsetSize(dropon, droponOptions.overlap) * (1.0 - overlap);
+
+ for (index = 0; index < children.length; index += 1) {
+ if (offset - self._offsetSize(children[index], droponOptions.overlap) >= 0) {
+ offset -= self._offsetSize(children[index], droponOptions.overlap);
+ } else if (offset - (self._offsetSize (children[index], droponOptions.overlap) / 2) >= 0) {
+ child = index + 1 < children.length ? children[index + 1] : null;
+ break;
+ } else {
+ child = children[index];
+ break;
+ }
+ }
+ }
+
+ dropon.insertBefore(element, child);
+
+ self.options(oldParentNode).onChange(element);
+ droponOptions.onChange(element);
+ }
+ },
+
+ /** @id MochiKit.Sortable.unmark */
+ unmark: function () {
+ var m = MochiKit.Sortable._marker;
+ if (m) {
+ MochiKit.Style.hideElement(m);
+ }
+ },
+
+ /** @id MochiKit.Sortable.mark */
+ mark: function (dropon, position) {
+ // mark on ghosting only
+ var d = MochiKit.DOM;
+ var self = MochiKit.Sortable;
+ var sortable = self.options(dropon.parentNode);
+ if (sortable && !sortable.ghosting) {
+ return;
+ }
+
+ if (!self._marker) {
+ self._marker = d.getElement('dropmarker') ||
+ document.createElement('DIV');
+ MochiKit.Style.hideElement(self._marker);
+ d.addElementClass(self._marker, 'dropmarker');
+ self._marker.style.position = 'absolute';
+ document.getElementsByTagName('body').item(0).appendChild(self._marker);
+ }
+ var offsets = MochiKit.Position.cumulativeOffset(dropon);
+ self._marker.style.left = offsets.x + 'px';
+ self._marker.style.top = offsets.y + 'px';
+
+ if (position == 'after') {
+ if (sortable.overlap == 'horizontal') {
+ self._marker.style.left = (offsets.x + dropon.clientWidth) + 'px';
+ } else {
+ self._marker.style.top = (offsets.y + dropon.clientHeight) + 'px';
+ }
+ }
+ MochiKit.Style.showElement(self._marker);
+ },
+
+ _tree: function (element, options, parent) {
+ var self = MochiKit.Sortable;
+ var children = self.findElements(element, options) || [];
+
+ for (var i = 0; i < children.length; ++i) {
+ var match = children[i].id.match(options.format);
+
+ if (!match) {
+ continue;
+ }
+
+ var child = {
+ id: encodeURIComponent(match ? match[1] : null),
+ element: element,
+ parent: parent,
+ children: [],
+ position: parent.children.length,
+ container: self._findChildrenElement(children[i], options.treeTag.toUpperCase())
+ }
+
+ /* Get the element containing the children and recurse over it */
+ if (child.container) {
+ self._tree(child.container, options, child)
+ }
+
+ parent.children.push (child);
+ }
+
+ return parent;
+ },
+
+ /* Finds the first element of the given tag type within a parent element.
+ Used for finding the first LI[ST] within a L[IST]I[TEM].*/
+ _findChildrenElement: function (element, containerTag) {
+ if (element && element.hasChildNodes) {
+ containerTag = containerTag.toUpperCase();
+ for (var i = 0; i < element.childNodes.length; ++i) {
+ if (element.childNodes[i].tagName.toUpperCase() == containerTag) {
+ return element.childNodes[i];
+ }
+ }
+ }
+ return null;
+ },
+
+ /** @id MochiKit.Sortable.tree */
+ tree: function (element, options) {
+ element = MochiKit.DOM.getElement(element);
+ var sortableOptions = MochiKit.Sortable.options(element);
+ options = MochiKit.Base.update({
+ tag: sortableOptions.tag,
+ treeTag: sortableOptions.treeTag,
+ only: sortableOptions.only,
+ name: element.id,
+ format: sortableOptions.format
+ }, options || {});
+
+ var root = {
+ id: null,
+ parent: null,
+ children: new Array,
+ container: element,
+ position: 0
+ }
+
+ return MochiKit.Sortable._tree(element, options, root);
+ },
+
+ /**
+ * Specifies the sequence for the Sortable.
+ * @param {Node} element Element to use as the Sortable.
+ * @param {Object} newSequence New sequence to use.
+ * @param {Object} options Options to use fro the Sortable.
+ */
+ setSequence: function (element, newSequence, options) {
+ var self = MochiKit.Sortable;
+ var b = MochiKit.Base;
+ element = MochiKit.DOM.getElement(element);
+ options = b.update(self.options(element), options || {});
+
+ var nodeMap = {};
+ b.map(function (n) {
+ var m = n.id.match(options.format);
+ if (m) {
+ nodeMap[m[1]] = [n, n.parentNode];
+ }
+ n.parentNode.removeChild(n);
+ }, self.findElements(element, options));
+
+ b.map(function (ident) {
+ var n = nodeMap[ident];
+ if (n) {
+ n[1].appendChild(n[0]);
+ delete nodeMap[ident];
+ }
+ }, newSequence);
+ },
+
+ /* Construct a [i] index for a particular node */
+ _constructIndex: function (node) {
+ var index = '';
+ do {
+ if (node.id) {
+ index = '[' + node.position + ']' + index;
+ }
+ } while ((node = node.parent) != null);
+ return index;
+ },
+
+ /** @id MochiKit.Sortable.sequence */
+ sequence: function (element, options) {
+ element = MochiKit.DOM.getElement(element);
+ var self = MochiKit.Sortable;
+ var options = MochiKit.Base.update(self.options(element), options || {});
+
+ return MochiKit.Base.map(function (item) {
+ return item.id.match(options.format) ? item.id.match(options.format)[1] : '';
+ }, MochiKit.DOM.getElement(self.findElements(element, options) || []));
+ },
+
+ /**
+ * Serializes the content of a Sortable. Useful to send this content through a XMLHTTPRequest.
+ * These options override the Sortable options for the serialization only.
+ * @param {Node} element Element to serialize.
+ * @param {Object} options Serialization options.
+ */
+ serialize: function (element, options) {
+ element = MochiKit.DOM.getElement(element);
+ var self = MochiKit.Sortable;
+ options = MochiKit.Base.update(self.options(element), options || {});
+ var name = encodeURIComponent(options.name || element.id);
+
+ if (options.tree) {
+ return MochiKit.Base.flattenArray(MochiKit.Base.map(function (item) {
+ return [name + self._constructIndex(item) + "[id]=" +
+ encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));
+ }, self.tree(element, options).children)).join('&');
+ } else {
+ return MochiKit.Base.map(function (item) {
+ return name + "[]=" + encodeURIComponent(item);
+ }, self.sequence(element, options)).join('&');
+ }
+ }
+});
+
+// trunk compatibility
+MochiKit.Sortable.Sortable = MochiKit.Sortable;
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Style.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Style.js
new file mode 100644
index 0000000000..93e77862af
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Style.js
@@ -0,0 +1,445 @@
+/***
+
+MochiKit.Style 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005-2006 Bob Ippolito, Beau Hartshorne. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Style');
+ dojo.require('MochiKit.Base');
+ dojo.require('MochiKit.DOM');
+}
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use('MochiKit.Base', []);
+ JSAN.use('MochiKit.DOM', []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined') {
+ throw '';
+ }
+} catch (e) {
+ throw 'MochiKit.Style depends on MochiKit.Base!';
+}
+
+try {
+ if (typeof(MochiKit.DOM) == 'undefined') {
+ throw '';
+ }
+} catch (e) {
+ throw 'MochiKit.Style depends on MochiKit.DOM!';
+}
+
+
+if (typeof(MochiKit.Style) == 'undefined') {
+ MochiKit.Style = {};
+}
+
+MochiKit.Style.NAME = 'MochiKit.Style';
+MochiKit.Style.VERSION = '1.4';
+MochiKit.Style.__repr__ = function () {
+ return '[' + this.NAME + ' ' + this.VERSION + ']';
+};
+MochiKit.Style.toString = function () {
+ return this.__repr__();
+};
+
+MochiKit.Style.EXPORT_OK = [];
+
+MochiKit.Style.EXPORT = [
+ 'setStyle',
+ 'setOpacity',
+ 'getStyle',
+ 'getElementDimensions',
+ 'elementDimensions', // deprecated
+ 'setElementDimensions',
+ 'getElementPosition',
+ 'elementPosition', // deprecated
+ 'setElementPosition',
+ 'setDisplayForElement',
+ 'hideElement',
+ 'showElement',
+ 'getViewportDimensions',
+ 'getViewportPosition',
+ 'Dimensions',
+ 'Coordinates'
+];
+
+
+/*
+
+ Dimensions
+
+*/
+/** @id MochiKit.Style.Dimensions */
+MochiKit.Style.Dimensions = function (w, h) {
+ this.w = w;
+ this.h = h;
+};
+
+MochiKit.Style.Dimensions.prototype.__repr__ = function () {
+ var repr = MochiKit.Base.repr;
+ return '{w: ' + repr(this.w) + ', h: ' + repr(this.h) + '}';
+};
+
+MochiKit.Style.Dimensions.prototype.toString = function () {
+ return this.__repr__();
+};
+
+
+/*
+
+ Coordinates
+
+*/
+/** @id MochiKit.Style.Coordinates */
+MochiKit.Style.Coordinates = function (x, y) {
+ this.x = x;
+ this.y = y;
+};
+
+MochiKit.Style.Coordinates.prototype.__repr__ = function () {
+ var repr = MochiKit.Base.repr;
+ return '{x: ' + repr(this.x) + ', y: ' + repr(this.y) + '}';
+};
+
+MochiKit.Style.Coordinates.prototype.toString = function () {
+ return this.__repr__();
+};
+
+
+MochiKit.Base.update(MochiKit.Style, {
+
+ /** @id MochiKit.Style.getStyle */
+ getStyle: function (elem, cssProperty) {
+ var dom = MochiKit.DOM;
+ var d = dom._document;
+
+ elem = dom.getElement(elem);
+ cssProperty = MochiKit.Base.camelize(cssProperty);
+
+ if (!elem || elem == d) {
+ return undefined;
+ }
+ if (cssProperty == 'opacity' && elem.filters) {
+ var opacity = (MochiKit.Style.getStyle(elem, 'filter') || '').match(/alpha\(opacity=(.*)\)/);
+ if (opacity && opacity[1]) {
+ return parseFloat(opacity[1]) / 100;
+ }
+ return 1.0;
+ }
+ var value = elem.style ? elem.style[cssProperty] : null;
+ if (!value) {
+ if (d.defaultView && d.defaultView.getComputedStyle) {
+ var css = d.defaultView.getComputedStyle(elem, null);
+ cssProperty = cssProperty.replace(/([A-Z])/g, '-$1'
+ ).toLowerCase(); // from dojo.style.toSelectorCase
+ value = css ? css.getPropertyValue(cssProperty) : null;
+ } else if (elem.currentStyle) {
+ value = elem.currentStyle[cssProperty];
+ }
+ }
+ if (cssProperty == 'opacity') {
+ value = parseFloat(value);
+ }
+
+ if (/Opera/.test(navigator.userAgent) && (MochiKit.Base.find(['left', 'top', 'right', 'bottom'], cssProperty) != -1)) {
+ if (MochiKit.Style.getStyle(elem, 'position') == 'static') {
+ value = 'auto';
+ }
+ }
+
+ return value == 'auto' ? null : value;
+ },
+
+ /** @id MochiKit.Style.setStyle */
+ setStyle: function (elem, style) {
+ elem = MochiKit.DOM.getElement(elem);
+ for (var name in style) {
+ if (name == 'opacity') {
+ MochiKit.Style.setOpacity(elem, style[name]);
+ } else {
+ elem.style[MochiKit.Base.camelize(name)] = style[name];
+ }
+ }
+ },
+
+ /** @id MochiKit.Style.setOpacity */
+ setOpacity: function (elem, o) {
+ elem = MochiKit.DOM.getElement(elem);
+ var self = MochiKit.Style;
+ if (o == 1) {
+ var toSet = /Gecko/.test(navigator.userAgent) && !(/Konqueror|AppleWebKit|KHTML/.test(navigator.userAgent));
+ elem.style["opacity"] = toSet ? 0.999999 : 1.0;
+ if (/MSIE/.test(navigator.userAgent)) {
+ elem.style['filter'] =
+ self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '');
+ }
+ } else {
+ if (o < 0.00001) {
+ o = 0;
+ }
+ elem.style["opacity"] = o;
+ if (/MSIE/.test(navigator.userAgent)) {
+ elem.style['filter'] =
+ self.getStyle(elem, 'filter').replace(/alpha\([^\)]*\)/gi, '') + 'alpha(opacity=' + o * 100 + ')';
+ }
+ }
+ },
+
+ /*
+
+ getElementPosition is adapted from YAHOO.util.Dom.getXY v0.9.0.
+ Copyright: Copyright (c) 2006, Yahoo! Inc. All rights reserved.
+ License: BSD, http://developer.yahoo.net/yui/license.txt
+
+ */
+
+ /** @id MochiKit.Style.getElementPosition */
+ getElementPosition: function (elem, /* optional */relativeTo) {
+ var self = MochiKit.Style;
+ var dom = MochiKit.DOM;
+ elem = dom.getElement(elem);
+
+ if (!elem ||
+ (!(elem.x && elem.y) &&
+ (!elem.parentNode === null ||
+ self.getStyle(elem, 'display') == 'none'))) {
+ return undefined;
+ }
+
+ var c = new self.Coordinates(0, 0);
+ var box = null;
+ var parent = null;
+
+ var d = MochiKit.DOM._document;
+ var de = d.documentElement;
+ var b = d.body;
+
+ if (!elem.parentNode && elem.x && elem.y) {
+ /* it's just a MochiKit.Style.Coordinates object */
+ c.x += elem.x || 0;
+ c.y += elem.y || 0;
+ } else if (elem.getBoundingClientRect) { // IE shortcut
+ /*
+
+ The IE shortcut can be off by two. We fix it. See:
+ http://msdn.microsoft.com/workshop/author/dhtml/reference/methods/getboundingclientrect.asp
+
+ This is similar to the method used in
+ MochiKit.Signal.Event.mouse().
+
+ */
+ box = elem.getBoundingClientRect();
+
+ c.x += box.left +
+ (de.scrollLeft || b.scrollLeft) -
+ (de.clientLeft || 0);
+
+ c.y += box.top +
+ (de.scrollTop || b.scrollTop) -
+ (de.clientTop || 0);
+
+ } else if (elem.offsetParent) {
+ c.x += elem.offsetLeft;
+ c.y += elem.offsetTop;
+ parent = elem.offsetParent;
+
+ if (parent != elem) {
+ while (parent) {
+ c.x += parent.offsetLeft;
+ c.y += parent.offsetTop;
+ parent = parent.offsetParent;
+ }
+ }
+
+ /*
+
+ Opera < 9 and old Safari (absolute) incorrectly account for
+ body offsetTop and offsetLeft.
+
+ */
+ var ua = navigator.userAgent.toLowerCase();
+ if ((typeof(opera) != 'undefined' &&
+ parseFloat(opera.version()) < 9) ||
+ (ua.indexOf('AppleWebKit') != -1 &&
+ self.getStyle(elem, 'position') == 'absolute')) {
+
+ c.x -= b.offsetLeft;
+ c.y -= b.offsetTop;
+
+ }
+ }
+
+ if (typeof(relativeTo) != 'undefined') {
+ relativeTo = arguments.callee(relativeTo);
+ if (relativeTo) {
+ c.x -= (relativeTo.x || 0);
+ c.y -= (relativeTo.y || 0);
+ }
+ }
+
+ if (elem.parentNode) {
+ parent = elem.parentNode;
+ } else {
+ parent = null;
+ }
+
+ while (parent) {
+ var tagName = parent.tagName.toUpperCase();
+ if (tagName === 'BODY' || tagName === 'HTML') {
+ break;
+ }
+ var disp = self.getStyle(parent, 'display');
+ // Handle strange Opera bug for some display
+ if (disp != 'inline' && disp != 'table-row') {
+ c.x -= parent.scrollLeft;
+ c.y -= parent.scrollTop;
+ }
+ if (parent.parentNode) {
+ parent = parent.parentNode;
+ } else {
+ parent = null;
+ }
+ }
+
+ return c;
+ },
+
+ /** @id MochiKit.Style.setElementPosition */
+ setElementPosition: function (elem, newPos/* optional */, units) {
+ elem = MochiKit.DOM.getElement(elem);
+ if (typeof(units) == 'undefined') {
+ units = 'px';
+ }
+ var newStyle = {};
+ var isUndefNull = MochiKit.Base.isUndefinedOrNull;
+ if (!isUndefNull(newPos.x)) {
+ newStyle['left'] = newPos.x + units;
+ }
+ if (!isUndefNull(newPos.y)) {
+ newStyle['top'] = newPos.y + units;
+ }
+ MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
+ },
+
+ /** @id MochiKit.Style.getElementDimensions */
+ getElementDimensions: function (elem) {
+ var self = MochiKit.Style;
+ var dom = MochiKit.DOM;
+ if (typeof(elem.w) == 'number' || typeof(elem.h) == 'number') {
+ return new self.Dimensions(elem.w || 0, elem.h || 0);
+ }
+ elem = dom.getElement(elem);
+ if (!elem) {
+ return undefined;
+ }
+ var disp = self.getStyle(elem, 'display');
+ // display can be empty/undefined on WebKit/KHTML
+ if (disp != 'none' && disp !== '' && typeof(disp) != 'undefined') {
+ return new self.Dimensions(elem.offsetWidth || 0,
+ elem.offsetHeight || 0);
+ }
+ var s = elem.style;
+ var originalVisibility = s.visibility;
+ var originalPosition = s.position;
+ s.visibility = 'hidden';
+ s.position = 'absolute';
+ s.display = '';
+ var originalWidth = elem.offsetWidth;
+ var originalHeight = elem.offsetHeight;
+ s.display = 'none';
+ s.position = originalPosition;
+ s.visibility = originalVisibility;
+ return new self.Dimensions(originalWidth, originalHeight);
+ },
+
+ /** @id MochiKit.Style.setElementDimensions */
+ setElementDimensions: function (elem, newSize/* optional */, units) {
+ elem = MochiKit.DOM.getElement(elem);
+ if (typeof(units) == 'undefined') {
+ units = 'px';
+ }
+ var newStyle = {};
+ var isUndefNull = MochiKit.Base.isUndefinedOrNull;
+ if (!isUndefNull(newSize.w)) {
+ newStyle['width'] = newSize.w + units;
+ }
+ if (!isUndefNull(newSize.h)) {
+ newStyle['height'] = newSize.h + units;
+ }
+ MochiKit.DOM.updateNodeAttributes(elem, {'style': newStyle});
+ },
+
+ /** @id MochiKit.Style.setDisplayForElement */
+ setDisplayForElement: function (display, element/*, ...*/) {
+ var elements = MochiKit.Base.extend(null, arguments, 1);
+ var getElement = MochiKit.DOM.getElement;
+ for (var i = 0; i < elements.length; i++) {
+ element = getElement(elements[i]);
+ if (element) {
+ element.style.display = display;
+ }
+ }
+ },
+
+ /** @id MochiKit.Style.getViewportDimensions */
+ getViewportDimensions: function () {
+ var d = new MochiKit.Style.Dimensions();
+
+ var w = MochiKit.DOM._window;
+ var b = MochiKit.DOM._document.body;
+
+ if (w.innerWidth) {
+ d.w = w.innerWidth;
+ d.h = w.innerHeight;
+ } else if (b.parentElement.clientWidth) {
+ d.w = b.parentElement.clientWidth;
+ d.h = b.parentElement.clientHeight;
+ } else if (b && b.clientWidth) {
+ d.w = b.clientWidth;
+ d.h = b.clientHeight;
+ }
+ return d;
+ },
+
+ /** @id MochiKit.Style.getViewportPosition */
+ getViewportPosition: function () {
+ var c = new MochiKit.Style.Coordinates(0, 0);
+ var d = MochiKit.DOM._document;
+ var de = d.documentElement;
+ var db = d.body;
+ if (de && (de.scrollTop || de.scrollLeft)) {
+ c.x = de.scrollLeft;
+ c.y = de.scrollTop;
+ } else if (db) {
+ c.x = db.scrollLeft;
+ c.y = db.scrollTop;
+ }
+ return c;
+ },
+
+ __new__: function () {
+ var m = MochiKit.Base;
+
+ this.elementPosition = this.getElementPosition;
+ this.elementDimensions = this.getElementDimensions;
+
+ this.hideElement = m.partial(this.setDisplayForElement, 'none');
+ this.showElement = m.partial(this.setDisplayForElement, 'block');
+
+ this.EXPORT_TAGS = {
+ ':common': this.EXPORT,
+ ':all': m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ m.nameFunctions(this);
+ }
+});
+
+MochiKit.Style.__new__();
+MochiKit.Base._exportSymbols(this, MochiKit.Style);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Test.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Test.js
new file mode 100644
index 0000000000..494a5b440c
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Test.js
@@ -0,0 +1,181 @@
+/***
+
+MochiKit.Test 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Test');
+ dojo.require('MochiKit.Base');
+}
+
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) == 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.Test depends on MochiKit.Base!";
+}
+
+if (typeof(MochiKit.Test) == 'undefined') {
+ MochiKit.Test = {};
+}
+
+MochiKit.Test.NAME = "MochiKit.Test";
+MochiKit.Test.VERSION = "1.4";
+MochiKit.Test.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.Test.toString = function () {
+ return this.__repr__();
+};
+
+
+MochiKit.Test.EXPORT = ["runTests"];
+MochiKit.Test.EXPORT_OK = [];
+
+MochiKit.Test.runTests = function (obj) {
+ if (typeof(obj) == "string") {
+ obj = JSAN.use(obj);
+ }
+ var suite = new MochiKit.Test.Suite();
+ suite.run(obj);
+};
+
+MochiKit.Test.Suite = function () {
+ this.testIndex = 0;
+ MochiKit.Base.bindMethods(this);
+};
+
+MochiKit.Test.Suite.prototype = {
+ run: function (obj) {
+ try {
+ obj(this);
+ } catch (e) {
+ this.traceback(e);
+ }
+ },
+ traceback: function (e) {
+ var items = MochiKit.Iter.sorted(MochiKit.Base.items(e));
+ print("not ok " + this.testIndex + " - Error thrown");
+ for (var i = 0; i < items.length; i++) {
+ var kv = items[i];
+ if (kv[0] == "stack") {
+ kv[1] = kv[1].split(/\n/)[0];
+ }
+ this.print("# " + kv.join(": "));
+ }
+ },
+ print: function (s) {
+ print(s);
+ },
+ is: function (got, expected, /* optional */message) {
+ var res = 1;
+ var msg = null;
+ try {
+ res = MochiKit.Base.compare(got, expected);
+ } catch (e) {
+ msg = "Can not compare " + typeof(got) + ":" + typeof(expected);
+ }
+ if (res) {
+ msg = "Expected value did not compare equal";
+ }
+ if (!res) {
+ return this.testResult(true, message);
+ }
+ return this.testResult(false, message,
+ [[msg], ["got:", got], ["expected:", expected]]);
+ },
+
+ testResult: function (pass, msg, failures) {
+ this.testIndex += 1;
+ if (pass) {
+ this.print("ok " + this.testIndex + " - " + msg);
+ return;
+ }
+ this.print("not ok " + this.testIndex + " - " + msg);
+ if (failures) {
+ for (var i = 0; i < failures.length; i++) {
+ this.print("# " + failures[i].join(" "));
+ }
+ }
+ },
+
+ isDeeply: function (got, expected, /* optional */message) {
+ var m = MochiKit.Base;
+ var res = 1;
+ try {
+ res = m.compare(got, expected);
+ } catch (e) {
+ // pass
+ }
+ if (res === 0) {
+ return this.ok(true, message);
+ }
+ var gk = m.keys(got);
+ var ek = m.keys(expected);
+ gk.sort();
+ ek.sort();
+ if (m.compare(gk, ek)) {
+ // differing keys
+ var cmp = {};
+ var i;
+ for (i = 0; i < gk.length; i++) {
+ cmp[gk[i]] = "got";
+ }
+ for (i = 0; i < ek.length; i++) {
+ if (ek[i] in cmp) {
+ delete cmp[ek[i]];
+ } else {
+ cmp[ek[i]] = "expected";
+ }
+ }
+ var diffkeys = m.keys(cmp);
+ diffkeys.sort();
+ var gotkeys = [];
+ var expkeys = [];
+ while (diffkeys.length) {
+ var k = diffkeys.shift();
+ if (k in Object.prototype) {
+ continue;
+ }
+ (cmp[k] == "got" ? gotkeys : expkeys).push(k);
+ }
+
+
+ }
+
+ return this.testResult((!res), msg,
+ (msg ? [["got:", got], ["expected:", expected]] : undefined)
+ );
+ },
+
+ ok: function (res, message) {
+ return this.testResult(res, message);
+ }
+};
+
+MochiKit.Test.__new__ = function () {
+ var m = MochiKit.Base;
+
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+ m.nameFunctions(this);
+
+};
+
+MochiKit.Test.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.Test);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/Visual.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/Visual.js
new file mode 100644
index 0000000000..b7d8d87b22
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/Visual.js
@@ -0,0 +1,1981 @@
+/***
+
+MochiKit.Visual 1.4
+
+See <http://mochikit.com/> for documentation, downloads, license, etc.
+
+(c) 2005 Bob Ippolito and others. All rights Reserved.
+
+***/
+
+if (typeof(dojo) != 'undefined') {
+ dojo.provide('MochiKit.Visual');
+ dojo.require('MochiKit.Base');
+ dojo.require('MochiKit.DOM');
+ dojo.require('MochiKit.Style');
+ dojo.require('MochiKit.Color');
+ dojo.require('MochiKit.Position');
+}
+
+if (typeof(JSAN) != 'undefined') {
+ JSAN.use("MochiKit.Base", []);
+ JSAN.use("MochiKit.DOM", []);
+ JSAN.use("MochiKit.Style", []);
+ JSAN.use("MochiKit.Color", []);
+ JSAN.use("MochiKit.Position", []);
+}
+
+try {
+ if (typeof(MochiKit.Base) === 'undefined' ||
+ typeof(MochiKit.DOM) === 'undefined' ||
+ typeof(MochiKit.Style) === 'undefined' ||
+ typeof(MochiKit.Position) === 'undefined' ||
+ typeof(MochiKit.Color) === 'undefined') {
+ throw "";
+ }
+} catch (e) {
+ throw "MochiKit.Visual depends on MochiKit.Base, MochiKit.DOM, MochiKit.Style, MochiKit.Position and MochiKit.Color!";
+}
+
+if (typeof(MochiKit.Visual) == "undefined") {
+ MochiKit.Visual = {};
+}
+
+MochiKit.Visual.NAME = "MochiKit.Visual";
+MochiKit.Visual.VERSION = "1.4";
+
+MochiKit.Visual.__repr__ = function () {
+ return "[" + this.NAME + " " + this.VERSION + "]";
+};
+
+MochiKit.Visual.toString = function () {
+ return this.__repr__();
+};
+
+MochiKit.Visual._RoundCorners = function (e, options) {
+ e = MochiKit.DOM.getElement(e);
+ this._setOptions(options);
+ if (this.options.__unstable__wrapElement) {
+ e = this._doWrap(e);
+ }
+
+ var color = this.options.color;
+ var C = MochiKit.Color.Color;
+ if (this.options.color === "fromElement") {
+ color = C.fromBackground(e);
+ } else if (!(color instanceof C)) {
+ color = C.fromString(color);
+ }
+ this.isTransparent = (color.asRGB().a <= 0);
+
+ var bgColor = this.options.bgColor;
+ if (this.options.bgColor === "fromParent") {
+ bgColor = C.fromBackground(e.offsetParent);
+ } else if (!(bgColor instanceof C)) {
+ bgColor = C.fromString(bgColor);
+ }
+
+ this._roundCornersImpl(e, color, bgColor);
+};
+
+MochiKit.Visual._RoundCorners.prototype = {
+ _doWrap: function (e) {
+ var parent = e.parentNode;
+ var doc = MochiKit.DOM.currentDocument();
+ if (typeof(doc.defaultView) === "undefined"
+ || doc.defaultView === null) {
+ return e;
+ }
+ var style = doc.defaultView.getComputedStyle(e, null);
+ if (typeof(style) === "undefined" || style === null) {
+ return e;
+ }
+ var wrapper = MochiKit.DOM.DIV({"style": {
+ display: "block",
+ // convert padding to margin
+ marginTop: style.getPropertyValue("padding-top"),
+ marginRight: style.getPropertyValue("padding-right"),
+ marginBottom: style.getPropertyValue("padding-bottom"),
+ marginLeft: style.getPropertyValue("padding-left"),
+ // remove padding so the rounding looks right
+ padding: "0px"
+ /*
+ paddingRight: "0px",
+ paddingLeft: "0px"
+ */
+ }});
+ wrapper.innerHTML = e.innerHTML;
+ e.innerHTML = "";
+ e.appendChild(wrapper);
+ return e;
+ },
+
+ _roundCornersImpl: function (e, color, bgColor) {
+ if (this.options.border) {
+ this._renderBorder(e, bgColor);
+ }
+ if (this._isTopRounded()) {
+ this._roundTopCorners(e, color, bgColor);
+ }
+ if (this._isBottomRounded()) {
+ this._roundBottomCorners(e, color, bgColor);
+ }
+ },
+
+ _renderBorder: function (el, bgColor) {
+ var borderValue = "1px solid " + this._borderColor(bgColor);
+ var borderL = "border-left: " + borderValue;
+ var borderR = "border-right: " + borderValue;
+ var style = "style='" + borderL + ";" + borderR + "'";
+ el.innerHTML = "<div " + style + ">" + el.innerHTML + "</div>";
+ },
+
+ _roundTopCorners: function (el, color, bgColor) {
+ var corner = this._createCorner(bgColor);
+ for (var i = 0; i < this.options.numSlices; i++) {
+ corner.appendChild(
+ this._createCornerSlice(color, bgColor, i, "top")
+ );
+ }
+ el.style.paddingTop = 0;
+ el.insertBefore(corner, el.firstChild);
+ },
+
+ _roundBottomCorners: function (el, color, bgColor) {
+ var corner = this._createCorner(bgColor);
+ for (var i = (this.options.numSlices - 1); i >= 0; i--) {
+ corner.appendChild(
+ this._createCornerSlice(color, bgColor, i, "bottom")
+ );
+ }
+ el.style.paddingBottom = 0;
+ el.appendChild(corner);
+ },
+
+ _createCorner: function (bgColor) {
+ var dom = MochiKit.DOM;
+ return dom.DIV({style: {backgroundColor: bgColor.toString()}});
+ },
+
+ _createCornerSlice: function (color, bgColor, n, position) {
+ var slice = MochiKit.DOM.SPAN();
+
+ var inStyle = slice.style;
+ inStyle.backgroundColor = color.toString();
+ inStyle.display = "block";
+ inStyle.height = "1px";
+ inStyle.overflow = "hidden";
+ inStyle.fontSize = "1px";
+
+ var borderColor = this._borderColor(color, bgColor);
+ if (this.options.border && n === 0) {
+ inStyle.borderTopStyle = "solid";
+ inStyle.borderTopWidth = "1px";
+ inStyle.borderLeftWidth = "0px";
+ inStyle.borderRightWidth = "0px";
+ inStyle.borderBottomWidth = "0px";
+ // assumes css compliant box model
+ inStyle.height = "0px";
+ inStyle.borderColor = borderColor.toString();
+ } else if (borderColor) {
+ inStyle.borderColor = borderColor.toString();
+ inStyle.borderStyle = "solid";
+ inStyle.borderWidth = "0px 1px";
+ }
+
+ if (!this.options.compact && (n == (this.options.numSlices - 1))) {
+ inStyle.height = "2px";
+ }
+
+ this._setMargin(slice, n, position);
+ this._setBorder(slice, n, position);
+
+ return slice;
+ },
+
+ _setOptions: function (options) {
+ this.options = {
+ corners: "all",
+ color: "fromElement",
+ bgColor: "fromParent",
+ blend: true,
+ border: false,
+ compact: false,
+ __unstable__wrapElement: false
+ };
+ MochiKit.Base.update(this.options, options);
+
+ this.options.numSlices = (this.options.compact ? 2 : 4);
+ },
+
+ _whichSideTop: function () {
+ var corners = this.options.corners;
+ if (this._hasString(corners, "all", "top")) {
+ return "";
+ }
+
+ var has_tl = (corners.indexOf("tl") != -1);
+ var has_tr = (corners.indexOf("tr") != -1);
+ if (has_tl && has_tr) {
+ return "";
+ }
+ if (has_tl) {
+ return "left";
+ }
+ if (has_tr) {
+ return "right";
+ }
+ return "";
+ },
+
+ _whichSideBottom: function () {
+ var corners = this.options.corners;
+ if (this._hasString(corners, "all", "bottom")) {
+ return "";
+ }
+
+ var has_bl = (corners.indexOf('bl') != -1);
+ var has_br = (corners.indexOf('br') != -1);
+ if (has_bl && has_br) {
+ return "";
+ }
+ if (has_bl) {
+ return "left";
+ }
+ if (has_br) {
+ return "right";
+ }
+ return "";
+ },
+
+ _borderColor: function (color, bgColor) {
+ if (color == "transparent") {
+ return bgColor;
+ } else if (this.options.border) {
+ return this.options.border;
+ } else if (this.options.blend) {
+ return bgColor.blendedColor(color);
+ }
+ return "";
+ },
+
+
+ _setMargin: function (el, n, corners) {
+ var marginSize = this._marginSize(n) + "px";
+ var whichSide = (
+ corners == "top" ? this._whichSideTop() : this._whichSideBottom()
+ );
+ var style = el.style;
+
+ if (whichSide == "left") {
+ style.marginLeft = marginSize;
+ style.marginRight = "0px";
+ } else if (whichSide == "right") {
+ style.marginRight = marginSize;
+ style.marginLeft = "0px";
+ } else {
+ style.marginLeft = marginSize;
+ style.marginRight = marginSize;
+ }
+ },
+
+ _setBorder: function (el, n, corners) {
+ var borderSize = this._borderSize(n) + "px";
+ var whichSide = (
+ corners == "top" ? this._whichSideTop() : this._whichSideBottom()
+ );
+
+ var style = el.style;
+ if (whichSide == "left") {
+ style.borderLeftWidth = borderSize;
+ style.borderRightWidth = "0px";
+ } else if (whichSide == "right") {
+ style.borderRightWidth = borderSize;
+ style.borderLeftWidth = "0px";
+ } else {
+ style.borderLeftWidth = borderSize;
+ style.borderRightWidth = borderSize;
+ }
+ },
+
+ _marginSize: function (n) {
+ if (this.isTransparent) {
+ return 0;
+ }
+
+ var o = this.options;
+ if (o.compact && o.blend) {
+ var smBlendedMarginSizes = [1, 0];
+ return smBlendedMarginSizes[n];
+ } else if (o.compact) {
+ var compactMarginSizes = [2, 1];
+ return compactMarginSizes[n];
+ } else if (o.blend) {
+ var blendedMarginSizes = [3, 2, 1, 0];
+ return blendedMarginSizes[n];
+ } else {
+ var marginSizes = [5, 3, 2, 1];
+ return marginSizes[n];
+ }
+ },
+
+ _borderSize: function (n) {
+ var o = this.options;
+ var borderSizes;
+ if (o.compact && (o.blend || this.isTransparent)) {
+ return 1;
+ } else if (o.compact) {
+ borderSizes = [1, 0];
+ } else if (o.blend) {
+ borderSizes = [2, 1, 1, 1];
+ } else if (o.border) {
+ borderSizes = [0, 2, 0, 0];
+ } else if (this.isTransparent) {
+ borderSizes = [5, 3, 2, 1];
+ } else {
+ return 0;
+ }
+ return borderSizes[n];
+ },
+
+ _hasString: function (str) {
+ for (var i = 1; i< arguments.length; i++) {
+ if (str.indexOf(arguments[i]) != -1) {
+ return true;
+ }
+ }
+ return false;
+ },
+
+ _isTopRounded: function () {
+ return this._hasString(this.options.corners,
+ "all", "top", "tl", "tr"
+ );
+ },
+
+ _isBottomRounded: function () {
+ return this._hasString(this.options.corners,
+ "all", "bottom", "bl", "br"
+ );
+ },
+
+ _hasSingleTextChild: function (el) {
+ return (el.childNodes.length == 1 && el.childNodes[0].nodeType == 3);
+ }
+};
+
+/** @id MochiKit.Visual.roundElement */
+MochiKit.Visual.roundElement = function (e, options) {
+ new MochiKit.Visual._RoundCorners(e, options);
+};
+
+/** @id MochiKit.Visual.roundClass */
+MochiKit.Visual.roundClass = function (tagName, className, options) {
+ var elements = MochiKit.DOM.getElementsByTagAndClassName(
+ tagName, className
+ );
+ for (var i = 0; i < elements.length; i++) {
+ MochiKit.Visual.roundElement(elements[i], options);
+ }
+};
+
+/** @id MochiKit.Visual.tagifyText */
+MochiKit.Visual.tagifyText = function (element, /* optional */tagifyStyle) {
+ /***
+
+ Change a node text to character in tags.
+
+ @param tagifyStyle: the style to apply to character nodes, default to
+ 'position: relative'.
+
+ ***/
+ tagifyStyle = tagifyStyle || 'position:relative';
+ if (/MSIE/.test(navigator.userAgent)) {
+ tagifyStyle += ';zoom:1';
+ }
+ element = MochiKit.DOM.getElement(element);
+ var ma = MochiKit.Base.map;
+ ma(function (child) {
+ if (child.nodeType == 3) {
+ ma(function (character) {
+ element.insertBefore(
+ MochiKit.DOM.SPAN({style: tagifyStyle},
+ character == ' ' ? String.fromCharCode(160) : character), child);
+ }, child.nodeValue.split(''));
+ MochiKit.DOM.removeElement(child);
+ }
+ }, element.childNodes);
+};
+
+/** @id MochiKit.Visual.forceRerendering */
+MochiKit.Visual.forceRerendering = function (element) {
+ try {
+ element = MochiKit.DOM.getElement(element);
+ var n = document.createTextNode(' ');
+ element.appendChild(n);
+ element.removeChild(n);
+ } catch(e) {
+ }
+};
+
+/** @id MochiKit.Visual.multiple */
+MochiKit.Visual.multiple = function (elements, effect, /* optional */options) {
+ /***
+
+ Launch the same effect subsequently on given elements.
+
+ ***/
+ options = MochiKit.Base.update({
+ speed: 0.1, delay: 0.0
+ }, options || {});
+ var masterDelay = options.delay;
+ var index = 0;
+ MochiKit.Base.map(function (innerelement) {
+ options.delay = index * options.speed + masterDelay;
+ new effect(innerelement, options);
+ index += 1;
+ }, elements);
+};
+
+MochiKit.Visual.PAIRS = {
+ 'slide': ['slideDown', 'slideUp'],
+ 'blind': ['blindDown', 'blindUp'],
+ 'appear': ['appear', 'fade'],
+ 'size': ['grow', 'shrink']
+};
+
+/** @id MochiKit.Visual.toggle */
+MochiKit.Visual.toggle = function (element, /* optional */effect, /* optional */options) {
+ /***
+
+ Toggle an item between two state depending of its visibility, making
+ a effect between these states. Default effect is 'appear', can be
+ 'slide' or 'blind'.
+
+ ***/
+ element = MochiKit.DOM.getElement(element);
+ effect = (effect || 'appear').toLowerCase();
+ options = MochiKit.Base.update({
+ queue: {position: 'end', scope: (element.id || 'global'), limit: 1}
+ }, options || {});
+ var v = MochiKit.Visual;
+ v[MochiKit.Style.getStyle(element, 'display') != 'none' ?
+ v.PAIRS[effect][1] : v.PAIRS[effect][0]](element, options);
+};
+
+/***
+
+Transitions: define functions calculating variations depending of a position.
+
+***/
+
+MochiKit.Visual.Transitions = {};
+
+/** @id MochiKit.Visual.Transitions.linear */
+MochiKit.Visual.Transitions.linear = function (pos) {
+ return pos;
+};
+
+/** @id MochiKit.Visual.Transitions.sinoidal */
+MochiKit.Visual.Transitions.sinoidal = function (pos) {
+ return (-Math.cos(pos*Math.PI)/2) + 0.5;
+};
+
+/** @id MochiKit.Visual.Transitions.reverse */
+MochiKit.Visual.Transitions.reverse = function (pos) {
+ return 1 - pos;
+};
+
+/** @id MochiKit.Visual.Transitions.flicker */
+MochiKit.Visual.Transitions.flicker = function (pos) {
+ return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4;
+};
+
+/** @id MochiKit.Visual.Transitions.wobble */
+MochiKit.Visual.Transitions.wobble = function (pos) {
+ return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5;
+};
+
+/** @id MochiKit.Visual.Transitions.pulse */
+MochiKit.Visual.Transitions.pulse = function (pos, pulses) {
+ if (!pulses) {
+ return (Math.floor(pos*10) % 2 === 0 ?
+ (pos*10 - Math.floor(pos*10)) : 1 - (pos*10 - Math.floor(pos*10)));
+ }
+ return (Math.round((pos % (1/pulses)) * pulses) == 0 ?
+ ((pos * pulses * 2) - Math.floor(pos * pulses * 2)) :
+ 1 - ((pos * pulses * 2) - Math.floor(pos * pulses * 2)));
+};
+
+/** @id MochiKit.Visual.Transitions.none */
+MochiKit.Visual.Transitions.none = function (pos) {
+ return 0;
+};
+
+/** @id MochiKit.Visual.Transitions.full */
+MochiKit.Visual.Transitions.full = function (pos) {
+ return 1;
+};
+
+/***
+
+Core effects
+
+***/
+
+MochiKit.Visual.ScopedQueue = function () {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls();
+ }
+ this.__init__();
+};
+
+MochiKit.Base.update(MochiKit.Visual.ScopedQueue.prototype, {
+ __init__: function () {
+ this.effects = [];
+ this.interval = null;
+ },
+
+ /** @id MochiKit.Visual.ScopedQueue.prototype.add */
+ add: function (effect) {
+ var timestamp = new Date().getTime();
+
+ var position = (typeof(effect.options.queue) == 'string') ?
+ effect.options.queue : effect.options.queue.position;
+
+ var ma = MochiKit.Base.map;
+ switch (position) {
+ case 'front':
+ // move unstarted effects after this effect
+ ma(function (e) {
+ if (e.state == 'idle') {
+ e.startOn += effect.finishOn;
+ e.finishOn += effect.finishOn;
+ }
+ }, this.effects);
+ break;
+ case 'end':
+ var finish;
+ // start effect after last queued effect has finished
+ ma(function (e) {
+ var i = e.finishOn;
+ if (i >= (finish || i)) {
+ finish = i;
+ }
+ }, this.effects);
+ timestamp = finish || timestamp;
+ break;
+ case 'break':
+ ma(function (e) {
+ e.finalize();
+ }, this.effects);
+ break;
+ }
+
+ effect.startOn += timestamp;
+ effect.finishOn += timestamp;
+ if (!effect.options.queue.limit ||
+ this.effects.length < effect.options.queue.limit) {
+ this.effects.push(effect);
+ }
+
+ if (!this.interval) {
+ this.interval = this.startLoop(MochiKit.Base.bind(this.loop, this),
+ 40);
+ }
+ },
+
+ /** @id MochiKit.Visual.ScopedQueue.prototype.startLoop */
+ startLoop: function (func, interval) {
+ return setInterval(func, interval);
+ },
+
+ /** @id MochiKit.Visual.ScopedQueue.prototype.remove */
+ remove: function (effect) {
+ this.effects = MochiKit.Base.filter(function (e) {
+ return e != effect;
+ }, this.effects);
+ if (!this.effects.length) {
+ this.stopLoop(this.interval);
+ this.interval = null;
+ }
+ },
+
+ /** @id MochiKit.Visual.ScopedQueue.prototype.stopLoop */
+ stopLoop: function (interval) {
+ clearInterval(interval);
+ },
+
+ /** @id MochiKit.Visual.ScopedQueue.prototype.loop */
+ loop: function () {
+ var timePos = new Date().getTime();
+ MochiKit.Base.map(function (effect) {
+ effect.loop(timePos);
+ }, this.effects);
+ }
+});
+
+MochiKit.Visual.Queues = {
+ instances: {},
+
+ get: function (queueName) {
+ if (typeof(queueName) != 'string') {
+ return queueName;
+ }
+
+ if (!this.instances[queueName]) {
+ this.instances[queueName] = new MochiKit.Visual.ScopedQueue();
+ }
+ return this.instances[queueName];
+ }
+};
+
+MochiKit.Visual.Queue = MochiKit.Visual.Queues.get('global');
+
+MochiKit.Visual.DefaultOptions = {
+ transition: MochiKit.Visual.Transitions.sinoidal,
+ duration: 1.0, // seconds
+ fps: 25.0, // max. 25fps due to MochiKit.Visual.Queue implementation
+ sync: false, // true for combining
+ from: 0.0,
+ to: 1.0,
+ delay: 0.0,
+ queue: 'parallel'
+};
+
+MochiKit.Visual.Base = function () {};
+
+MochiKit.Visual.Base.prototype = {
+ /***
+
+ Basic class for all Effects. Define a looping mechanism called for each step
+ of an effect. Don't instantiate it, only subclass it.
+
+ ***/
+
+ __class__ : MochiKit.Visual.Base,
+
+ /** @id MochiKit.Visual.Base.prototype.start */
+ start: function (options) {
+ var v = MochiKit.Visual;
+ this.options = MochiKit.Base.setdefault(options || {},
+ v.DefaultOptions);
+ this.currentFrame = 0;
+ this.state = 'idle';
+ this.startOn = this.options.delay*1000;
+ this.finishOn = this.startOn + (this.options.duration*1000);
+ this.event('beforeStart');
+ if (!this.options.sync) {
+ v.Queues.get(typeof(this.options.queue) == 'string' ?
+ 'global' : this.options.queue.scope).add(this);
+ }
+ },
+
+ /** @id MochiKit.Visual.Base.prototype.loop */
+ loop: function (timePos) {
+ if (timePos >= this.startOn) {
+ if (timePos >= this.finishOn) {
+ return this.finalize();
+ }
+ var pos = (timePos - this.startOn) / (this.finishOn - this.startOn);
+ var frame =
+ Math.round(pos * this.options.fps * this.options.duration);
+ if (frame > this.currentFrame) {
+ this.render(pos);
+ this.currentFrame = frame;
+ }
+ }
+ },
+
+ /** @id MochiKit.Visual.Base.prototype.render */
+ render: function (pos) {
+ if (this.state == 'idle') {
+ this.state = 'running';
+ this.event('beforeSetup');
+ this.setup();
+ this.event('afterSetup');
+ }
+ if (this.state == 'running') {
+ if (this.options.transition) {
+ pos = this.options.transition(pos);
+ }
+ pos *= (this.options.to - this.options.from);
+ pos += this.options.from;
+ this.event('beforeUpdate');
+ this.update(pos);
+ this.event('afterUpdate');
+ }
+ },
+
+ /** @id MochiKit.Visual.Base.prototype.cancel */
+ cancel: function () {
+ if (!this.options.sync) {
+ MochiKit.Visual.Queues.get(typeof(this.options.queue) == 'string' ?
+ 'global' : this.options.queue.scope).remove(this);
+ }
+ this.state = 'finished';
+ },
+
+ /** @id MochiKit.Visual.Base.prototype.finalize */
+ finalize: function () {
+ this.render(1.0);
+ this.cancel();
+ this.event('beforeFinish');
+ this.finish();
+ this.event('afterFinish');
+ },
+
+ setup: function () {
+ },
+
+ finish: function () {
+ },
+
+ update: function (position) {
+ },
+
+ /** @id MochiKit.Visual.Base.prototype.event */
+ event: function (eventName) {
+ if (this.options[eventName + 'Internal']) {
+ this.options[eventName + 'Internal'](this);
+ }
+ if (this.options[eventName]) {
+ this.options[eventName](this);
+ }
+ },
+
+ /** @id MochiKit.Visual.Base.prototype.repr */
+ repr: function () {
+ return '[' + this.__class__.NAME + ', options:' +
+ MochiKit.Base.repr(this.options) + ']';
+ }
+};
+
+ /** @id MochiKit.Visual.Parallel */
+MochiKit.Visual.Parallel = function (effects, options) {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls(effects, options);
+ }
+
+ this.__init__(effects, options);
+};
+
+MochiKit.Visual.Parallel.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Parallel.prototype, {
+ /***
+
+ Run multiple effects at the same time.
+
+ ***/
+
+ __class__ : MochiKit.Visual.Parallel,
+
+ __init__: function (effects, options) {
+ this.effects = effects || [];
+ this.start(options);
+ },
+
+ /** @id MochiKit.Visual.Parallel.prototype.update */
+ update: function (position) {
+ MochiKit.Base.map(function (effect) {
+ effect.render(position);
+ }, this.effects);
+ },
+
+ /** @id MochiKit.Visual.Parallel.prototype.finish */
+ finish: function () {
+ MochiKit.Base.map(function (effect) {
+ effect.finalize();
+ }, this.effects);
+ }
+});
+
+/** @id MochiKit.Visual.Opacity */
+MochiKit.Visual.Opacity = function (element, options) {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls(element, options);
+ }
+ this.__init__(element, options);
+};
+
+MochiKit.Visual.Opacity.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Opacity.prototype, {
+ /***
+
+ Change the opacity of an element.
+
+ @param options: 'from' and 'to' change the starting and ending opacities.
+ Must be between 0.0 and 1.0. Default to current opacity and 1.0.
+
+ ***/
+
+ __class__ : MochiKit.Visual.Opacity,
+
+ __init__: function (element, /* optional */options) {
+ var b = MochiKit.Base;
+ var s = MochiKit.Style;
+ this.element = MochiKit.DOM.getElement(element);
+ // make this work on IE on elements without 'layout'
+ if (this.element.currentStyle &&
+ (!this.element.currentStyle.hasLayout)) {
+ s.setStyle(this.element, {zoom: 1});
+ }
+ options = b.update({
+ from: s.getStyle(this.element, 'opacity') || 0.0,
+ to: 1.0
+ }, options || {});
+ this.start(options);
+ },
+
+ /** @id MochiKit.Visual.Opacity.prototype.update */
+ update: function (position) {
+ MochiKit.Style.setStyle(this.element, {'opacity': position});
+ }
+});
+
+/** @id MochiKit.Visual.Move.prototype */
+MochiKit.Visual.Move = function (element, options) {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls(element, options);
+ }
+ this.__init__(element, options);
+};
+
+MochiKit.Visual.Move.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Move.prototype, {
+ /***
+
+ Move an element between its current position to a defined position
+
+ @param options: 'x' and 'y' for final positions, default to 0, 0.
+
+ ***/
+
+ __class__ : MochiKit.Visual.Move,
+
+ __init__: function (element, /* optional */options) {
+ this.element = MochiKit.DOM.getElement(element);
+ options = MochiKit.Base.update({
+ x: 0,
+ y: 0,
+ mode: 'relative'
+ }, options || {});
+ this.start(options);
+ },
+
+ /** @id MochiKit.Visual.Move.prototype.setup */
+ setup: function () {
+ // Bug in Opera: Opera returns the 'real' position of a static element
+ // or relative element that does not have top/left explicitly set.
+ // ==> Always set top and left for position relative elements in your
+ // stylesheets (to 0 if you do not need them)
+ MochiKit.DOM.makePositioned(this.element);
+
+ var s = this.element.style;
+ var originalVisibility = s.visibility;
+ var originalDisplay = s.display;
+ if (originalDisplay == 'none') {
+ s.visibility = 'hidden';
+ s.display = '';
+ }
+
+ this.originalLeft = parseFloat(MochiKit.Style.getStyle(this.element, 'left') || '0');
+ this.originalTop = parseFloat(MochiKit.Style.getStyle(this.element, 'top') || '0');
+
+ if (this.options.mode == 'absolute') {
+ // absolute movement, so we need to calc deltaX and deltaY
+ this.options.x -= this.originalLeft;
+ this.options.y -= this.originalTop;
+ }
+ if (originalDisplay == 'none') {
+ s.visibility = originalVisibility;
+ s.display = originalDisplay;
+ }
+ },
+
+ /** @id MochiKit.Visual.Move.prototype.update */
+ update: function (position) {
+ MochiKit.Style.setStyle(this.element, {
+ left: Math.round(this.options.x * position + this.originalLeft) + 'px',
+ top: Math.round(this.options.y * position + this.originalTop) + 'px'
+ });
+ }
+});
+
+/** @id MochiKit.Visual.Scale */
+MochiKit.Visual.Scale = function (element, percent, options) {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls(element, percent, options);
+ }
+ this.__init__(element, percent, options);
+};
+
+MochiKit.Visual.Scale.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Scale.prototype, {
+ /***
+
+ Change the size of an element.
+
+ @param percent: final_size = percent*original_size
+
+ @param options: several options changing scale behaviour
+
+ ***/
+
+ __class__ : MochiKit.Visual.Scale,
+
+ __init__: function (element, percent, /* optional */options) {
+ this.element = MochiKit.DOM.getElement(element);
+ options = MochiKit.Base.update({
+ scaleX: true,
+ scaleY: true,
+ scaleContent: true,
+ scaleFromCenter: false,
+ scaleMode: 'box', // 'box' or 'contents' or {} with provided values
+ scaleFrom: 100.0,
+ scaleTo: percent
+ }, options || {});
+ this.start(options);
+ },
+
+ /** @id MochiKit.Visual.Scale.prototype.setup */
+ setup: function () {
+ this.restoreAfterFinish = this.options.restoreAfterFinish || false;
+ this.elementPositioning = MochiKit.Style.getStyle(this.element,
+ 'position');
+
+ var ma = MochiKit.Base.map;
+ var b = MochiKit.Base.bind;
+ this.originalStyle = {};
+ ma(b(function (k) {
+ this.originalStyle[k] = this.element.style[k];
+ }, this), ['top', 'left', 'width', 'height', 'fontSize']);
+
+ this.originalTop = this.element.offsetTop;
+ this.originalLeft = this.element.offsetLeft;
+
+ var fontSize = MochiKit.Style.getStyle(this.element,
+ 'font-size') || '100%';
+ ma(b(function (fontSizeType) {
+ if (fontSize.indexOf(fontSizeType) > 0) {
+ this.fontSize = parseFloat(fontSize);
+ this.fontSizeType = fontSizeType;
+ }
+ }, this), ['em', 'px', '%']);
+
+ this.factor = (this.options.scaleTo - this.options.scaleFrom)/100;
+
+ if (/^content/.test(this.options.scaleMode)) {
+ this.dims = [this.element.scrollHeight, this.element.scrollWidth];
+ } else if (this.options.scaleMode == 'box') {
+ this.dims = [this.element.offsetHeight, this.element.offsetWidth];
+ } else {
+ this.dims = [this.options.scaleMode.originalHeight,
+ this.options.scaleMode.originalWidth];
+ }
+ },
+
+ /** @id MochiKit.Visual.Scale.prototype.update */
+ update: function (position) {
+ var currentScale = (this.options.scaleFrom/100.0) +
+ (this.factor * position);
+ if (this.options.scaleContent && this.fontSize) {
+ MochiKit.Style.setStyle(this.element, {
+ fontSize: this.fontSize * currentScale + this.fontSizeType
+ });
+ }
+ this.setDimensions(this.dims[0] * currentScale,
+ this.dims[1] * currentScale);
+ },
+
+ /** @id MochiKit.Visual.Scale.prototype.finish */
+ finish: function () {
+ if (this.restoreAfterFinish) {
+ MochiKit.Style.setStyle(this.element, this.originalStyle);
+ }
+ },
+
+ /** @id MochiKit.Visual.Scale.prototype.setDimensions */
+ setDimensions: function (height, width) {
+ var d = {};
+ var r = Math.round;
+ if (/MSIE/.test(navigator.userAgent)) {
+ r = Math.ceil;
+ }
+ if (this.options.scaleX) {
+ d.width = r(width) + 'px';
+ }
+ if (this.options.scaleY) {
+ d.height = r(height) + 'px';
+ }
+ if (this.options.scaleFromCenter) {
+ var topd = (height - this.dims[0])/2;
+ var leftd = (width - this.dims[1])/2;
+ if (this.elementPositioning == 'absolute') {
+ if (this.options.scaleY) {
+ d.top = this.originalTop - topd + 'px';
+ }
+ if (this.options.scaleX) {
+ d.left = this.originalLeft - leftd + 'px';
+ }
+ } else {
+ if (this.options.scaleY) {
+ d.top = -topd + 'px';
+ }
+ if (this.options.scaleX) {
+ d.left = -leftd + 'px';
+ }
+ }
+ }
+ MochiKit.Style.setStyle(this.element, d);
+ }
+});
+
+/** @id MochiKit.Visual.Highlight */
+MochiKit.Visual.Highlight = function (element, options) {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls(element, options);
+ }
+ this.__init__(element, options);
+};
+
+MochiKit.Visual.Highlight.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Highlight.prototype, {
+ /***
+
+ Highlight an item of the page.
+
+ @param options: 'startcolor' for choosing highlighting color, default
+ to '#ffff99'.
+
+ ***/
+
+ __class__ : MochiKit.Visual.Highlight,
+
+ __init__: function (element, /* optional */options) {
+ this.element = MochiKit.DOM.getElement(element);
+ options = MochiKit.Base.update({
+ startcolor: '#ffff99'
+ }, options || {});
+ this.start(options);
+ },
+
+ /** @id MochiKit.Visual.Highlight.prototype.setup */
+ setup: function () {
+ var b = MochiKit.Base;
+ var s = MochiKit.Style;
+ // Prevent executing on elements not in the layout flow
+ if (s.getStyle(this.element, 'display') == 'none') {
+ this.cancel();
+ return;
+ }
+ // Disable background image during the effect
+ this.oldStyle = {
+ backgroundImage: s.getStyle(this.element, 'background-image')
+ };
+ s.setStyle(this.element, {
+ backgroundImage: 'none'
+ });
+
+ if (!this.options.endcolor) {
+ this.options.endcolor =
+ MochiKit.Color.Color.fromBackground(this.element).toHexString();
+ }
+ if (b.isUndefinedOrNull(this.options.restorecolor)) {
+ this.options.restorecolor = s.getStyle(this.element,
+ 'background-color');
+ }
+ // init color calculations
+ this._base = b.map(b.bind(function (i) {
+ return parseInt(
+ this.options.startcolor.slice(i*2 + 1, i*2 + 3), 16);
+ }, this), [0, 1, 2]);
+ this._delta = b.map(b.bind(function (i) {
+ return parseInt(this.options.endcolor.slice(i*2 + 1, i*2 + 3), 16)
+ - this._base[i];
+ }, this), [0, 1, 2]);
+ },
+
+ /** @id MochiKit.Visual.Highlight.prototype.update */
+ update: function (position) {
+ var m = '#';
+ MochiKit.Base.map(MochiKit.Base.bind(function (i) {
+ m += MochiKit.Color.toColorPart(Math.round(this._base[i] +
+ this._delta[i]*position));
+ }, this), [0, 1, 2]);
+ MochiKit.Style.setStyle(this.element, {
+ backgroundColor: m
+ });
+ },
+
+ /** @id MochiKit.Visual.Highlight.prototype.finish */
+ finish: function () {
+ MochiKit.Style.setStyle(this.element,
+ MochiKit.Base.update(this.oldStyle, {
+ backgroundColor: this.options.restorecolor
+ }));
+ }
+});
+
+/** @id MochiKit.Visual.ScrollTo */
+MochiKit.Visual.ScrollTo = function (element, options) {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls(element, options);
+ }
+ this.__init__(element, options);
+};
+
+MochiKit.Visual.ScrollTo.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.ScrollTo.prototype, {
+ /***
+
+ Scroll to an element in the page.
+
+ ***/
+
+ __class__ : MochiKit.Visual.ScrollTo,
+
+ __init__: function (element, /* optional */options) {
+ this.element = MochiKit.DOM.getElement(element);
+ this.start(options || {});
+ },
+
+ /** @id MochiKit.Visual.ScrollTo.prototype.setup */
+ setup: function () {
+ var p = MochiKit.Position;
+ p.prepare();
+ var offsets = p.cumulativeOffset(this.element);
+ if (this.options.offset) {
+ offsets.y += this.options.offset;
+ }
+ var max;
+ if (window.innerHeight) {
+ max = window.innerHeight - window.height;
+ } else if (document.documentElement &&
+ document.documentElement.clientHeight) {
+ max = document.documentElement.clientHeight -
+ document.body.scrollHeight;
+ } else if (document.body) {
+ max = document.body.clientHeight - document.body.scrollHeight;
+ }
+ this.scrollStart = p.windowOffset.y;
+ this.delta = (offsets.y > max ? max : offsets.y) - this.scrollStart;
+ },
+
+ /** @id MochiKit.Visual.ScrollTo.prototype.update */
+ update: function (position) {
+ var p = MochiKit.Position;
+ p.prepare();
+ window.scrollTo(p.windowOffset.x, this.scrollStart + (position * this.delta));
+ }
+});
+
+MochiKit.Visual.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/;
+
+MochiKit.Visual.Morph = function (element, options) {
+ var cls = arguments.callee;
+ if (!(this instanceof cls)) {
+ return new cls(element, options);
+ }
+ this.__init__(element, options);
+};
+
+MochiKit.Visual.Morph.prototype = new MochiKit.Visual.Base();
+
+MochiKit.Base.update(MochiKit.Visual.Morph.prototype, {
+ /***
+
+ Morph effect: make a transformation from current style to the given style,
+ automatically making a transition between the two.
+
+ ***/
+
+ __class__ : MochiKit.Visual.Morph,
+
+ __init__: function (element, /* optional */options) {
+ this.element = MochiKit.DOM.getElement(element);
+ this.start(options || {});
+ },
+
+ /** @id MochiKit.Visual.Morph.prototype.setup */
+ setup: function () {
+ var b = MochiKit.Base;
+ var style = this.options.style;
+ this.styleStart = {};
+ this.styleEnd = {};
+ this.units = {};
+ var value, unit;
+ for (var s in style) {
+ value = style[s];
+ s = b.camelize(s);
+ if (MochiKit.Visual.CSS_LENGTH.test(value)) {
+ var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ unit = (components.length == 3) ? components[2] : null;
+ this.styleEnd[s] = value;
+ this.units[s] = unit;
+ value = MochiKit.Style.getStyle(this.element, s);
+ components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/);
+ value = parseFloat(components[1]);
+ this.styleStart[s] = value;
+ } else {
+ var c = MochiKit.Color.Color;
+ value = c.fromString(value);
+ if (value) {
+ this.units[s] = "color";
+ this.styleEnd[s] = value.toHexString();
+ value = MochiKit.Style.getStyle(this.element, s);
+ this.styleStart[s] = c.fromString(value).toHexString();
+
+ this.styleStart[s] = b.map(b.bind(function (i) {
+ return parseInt(
+ this.styleStart[s].slice(i*2 + 1, i*2 + 3), 16);
+ }, this), [0, 1, 2]);
+ this.styleEnd[s] = b.map(b.bind(function (i) {
+ return parseInt(
+ this.styleEnd[s].slice(i*2 + 1, i*2 + 3), 16);
+ }, this), [0, 1, 2]);
+ }
+ }
+ }
+ },
+
+ /** @id MochiKit.Visual.Morph.prototype.update */
+ update: function (position) {
+ var value;
+ for (var s in this.styleStart) {
+ if (this.units[s] == "color") {
+ var m = '#';
+ var start = this.styleStart[s];
+ var end = this.styleEnd[s];
+ MochiKit.Base.map(MochiKit.Base.bind(function (i) {
+ m += MochiKit.Color.toColorPart(Math.round(start[i] +
+ (end[i] - start[i])*position));
+ }, this), [0, 1, 2]);
+ this.element.style[s] = m;
+ } else {
+ value = this.styleStart[s] + Math.round((this.styleEnd[s] - this.styleStart[s]) * position * 1000) / 1000 + this.units[s];
+ this.element.style[s] = value;
+ }
+ }
+ }
+});
+
+/***
+
+Combination effects.
+
+***/
+
+/** @id MochiKit.Visual.fade */
+MochiKit.Visual.fade = function (element, /* optional */ options) {
+ /***
+
+ Fade a given element: change its opacity and hide it in the end.
+
+ @param options: 'to' and 'from' to change opacity.
+
+ ***/
+ var s = MochiKit.Style;
+ var oldOpacity = s.getStyle(element, 'opacity');
+ options = MochiKit.Base.update({
+ from: s.getStyle(element, 'opacity') || 1.0,
+ to: 0.0,
+ afterFinishInternal: function (effect) {
+ if (effect.options.to !== 0) {
+ return;
+ }
+ s.hideElement(effect.element);
+ s.setStyle(effect.element, {'opacity': oldOpacity});
+ }
+ }, options || {});
+ return new MochiKit.Visual.Opacity(element, options);
+};
+
+/** @id MochiKit.Visual.appear */
+MochiKit.Visual.appear = function (element, /* optional */ options) {
+ /***
+
+ Make an element appear.
+
+ @param options: 'to' and 'from' to change opacity.
+
+ ***/
+ var s = MochiKit.Style;
+ var v = MochiKit.Visual;
+ options = MochiKit.Base.update({
+ from: (s.getStyle(element, 'display') == 'none' ? 0.0 :
+ s.getStyle(element, 'opacity') || 0.0),
+ to: 1.0,
+ // force Safari to render floated elements properly
+ afterFinishInternal: function (effect) {
+ v.forceRerendering(effect.element);
+ },
+ beforeSetupInternal: function (effect) {
+ s.setStyle(effect.element, {'opacity': effect.options.from});
+ s.showElement(effect.element);
+ }
+ }, options || {});
+ return new v.Opacity(element, options);
+};
+
+/** @id MochiKit.Visual.puff */
+MochiKit.Visual.puff = function (element, /* optional */ options) {
+ /***
+
+ 'Puff' an element: grow it to double size, fading it and make it hidden.
+
+ ***/
+ var s = MochiKit.Style;
+ var v = MochiKit.Visual;
+ element = MochiKit.DOM.getElement(element);
+ var oldStyle = {
+ position: s.getStyle(element, 'position'),
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height,
+ opacity: s.getStyle(element, 'opacity')
+ };
+ options = MochiKit.Base.update({
+ beforeSetupInternal: function (effect) {
+ MochiKit.Position.absolutize(effect.effects[0].element);
+ },
+ afterFinishInternal: function (effect) {
+ s.hideElement(effect.effects[0].element);
+ s.setStyle(effect.effects[0].element, oldStyle);
+ },
+ scaleContent: true,
+ scaleFromCenter: true
+ }, options || {});
+ return new v.Parallel(
+ [new v.Scale(element, 200,
+ {sync: true, scaleFromCenter: options.scaleFromCenter,
+ scaleContent: options.scaleContent, restoreAfterFinish: true}),
+ new v.Opacity(element, {sync: true, to: 0.0 })],
+ options);
+};
+
+/** @id MochiKit.Visual.blindUp */
+MochiKit.Visual.blindUp = function (element, /* optional */ options) {
+ /***
+
+ Blind an element up: change its vertical size to 0.
+
+ ***/
+ var d = MochiKit.DOM;
+ element = d.getElement(element);
+ var elemClip = d.makeClipping(element);
+ options = MochiKit.Base.update({
+ scaleContent: false,
+ scaleX: false,
+ restoreAfterFinish: true,
+ afterFinishInternal: function (effect) {
+ MochiKit.Style.hideElement(effect.element);
+ d.undoClipping(effect.element, elemClip);
+ }
+ }, options || {});
+
+ return new MochiKit.Visual.Scale(element, 0, options);
+};
+
+/** @id MochiKit.Visual.blindDown */
+MochiKit.Visual.blindDown = function (element, /* optional */ options) {
+ /***
+
+ Blind an element down: restore its vertical size.
+
+ ***/
+ var d = MochiKit.DOM;
+ var s = MochiKit.Style;
+ element = d.getElement(element);
+ var elementDimensions = s.getElementDimensions(element);
+ var elemClip;
+ options = MochiKit.Base.update({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.h,
+ originalWidth: elementDimensions.w},
+ restoreAfterFinish: true,
+ afterSetupInternal: function (effect) {
+ elemClip = d.makeClipping(effect.element);
+ s.setStyle(effect.element, {height: '0px'});
+ s.showElement(effect.element);
+ },
+ afterFinishInternal: function (effect) {
+ d.undoClipping(effect.element, elemClip);
+ }
+ }, options || {});
+ return new MochiKit.Visual.Scale(element, 100, options);
+};
+
+/** @id MochiKit.Visual.switchOff */
+MochiKit.Visual.switchOff = function (element, /* optional */ options) {
+ /***
+
+ Apply a switch-off-like effect.
+
+ ***/
+ var d = MochiKit.DOM;
+ element = d.getElement(element);
+ var oldOpacity = MochiKit.Style.getStyle(element, 'opacity');
+ var elemClip;
+ options = MochiKit.Base.update({
+ duration: 0.3,
+ scaleFromCenter: true,
+ scaleX: false,
+ scaleContent: false,
+ restoreAfterFinish: true,
+ beforeSetupInternal: function (effect) {
+ d.makePositioned(effect.element);
+ elemClip = d.makeClipping(effect.element);
+ },
+ afterFinishInternal: function (effect) {
+ MochiKit.Style.hideElement(effect.element);
+ d.undoClipping(effect.element, elemClip);
+ d.undoPositioned(effect.element);
+ MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity});
+ }
+ }, options || {});
+ var v = MochiKit.Visual;
+ return new v.appear(element, {
+ duration: 0.4,
+ from: 0,
+ transition: v.Transitions.flicker,
+ afterFinishInternal: function (effect) {
+ new v.Scale(effect.element, 1, options);
+ }
+ });
+};
+
+/** @id MochiKit.Visual.dropOut */
+MochiKit.Visual.dropOut = function (element, /* optional */ options) {
+ /***
+
+ Make an element fall and disappear.
+
+ ***/
+ var d = MochiKit.DOM;
+ var s = MochiKit.Style;
+ element = d.getElement(element);
+ var oldStyle = {
+ top: s.getStyle(element, 'top'),
+ left: s.getStyle(element, 'left'),
+ opacity: s.getStyle(element, 'opacity')
+ };
+
+ options = MochiKit.Base.update({
+ duration: 0.5,
+ distance: 100,
+ beforeSetupInternal: function (effect) {
+ d.makePositioned(effect.effects[0].element);
+ },
+ afterFinishInternal: function (effect) {
+ s.hideElement(effect.effects[0].element);
+ d.undoPositioned(effect.effects[0].element);
+ s.setStyle(effect.effects[0].element, oldStyle);
+ }
+ }, options || {});
+ var v = MochiKit.Visual;
+ return new v.Parallel(
+ [new v.Move(element, {x: 0, y: options.distance, sync: true}),
+ new v.Opacity(element, {sync: true, to: 0.0})],
+ options);
+};
+
+/** @id MochiKit.Visual.shake */
+MochiKit.Visual.shake = function (element, /* optional */ options) {
+ /***
+
+ Move an element from left to right several times.
+
+ ***/
+ var d = MochiKit.DOM;
+ var v = MochiKit.Visual;
+ var s = MochiKit.Style;
+ element = d.getElement(element);
+ options = MochiKit.Base.update({
+ x: -20,
+ y: 0,
+ duration: 0.05,
+ afterFinishInternal: function (effect) {
+ d.undoPositioned(effect.element);
+ s.setStyle(effect.element, oldStyle);
+ }
+ }, options || {});
+ var oldStyle = {
+ top: s.getStyle(element, 'top'),
+ left: s.getStyle(element, 'left') };
+ return new v.Move(element,
+ {x: 20, y: 0, duration: 0.05, afterFinishInternal: function (effect) {
+ new v.Move(effect.element,
+ {x: -40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
+ new v.Move(effect.element,
+ {x: 40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
+ new v.Move(effect.element,
+ {x: -40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
+ new v.Move(effect.element,
+ {x: 40, y: 0, duration: 0.1, afterFinishInternal: function (effect) {
+ new v.Move(effect.element, options
+ ) }}) }}) }}) }}) }});
+};
+
+/** @id MochiKit.Visual.slideDown */
+MochiKit.Visual.slideDown = function (element, /* optional */ options) {
+ /***
+
+ Slide an element down.
+ It needs to have the content of the element wrapped in a container
+ element with fixed height.
+
+ ***/
+ var d = MochiKit.DOM;
+ var b = MochiKit.Base;
+ var s = MochiKit.Style;
+ element = d.getElement(element);
+ if (!element.firstChild) {
+ throw "MochiKit.Visual.slideDown must be used on a element with a child";
+ }
+ d.removeEmptyTextNodes(element);
+ var oldInnerBottom = s.getStyle(element.firstChild, 'bottom') || 0;
+ var elementDimensions = s.getElementDimensions(element);
+ var elemClip;
+ options = b.update({
+ scaleContent: false,
+ scaleX: false,
+ scaleFrom: 0,
+ scaleMode: {originalHeight: elementDimensions.h,
+ originalWidth: elementDimensions.w},
+ restoreAfterFinish: true,
+ afterSetupInternal: function (effect) {
+ d.makePositioned(effect.element);
+ d.makePositioned(effect.element.firstChild);
+ if (/Opera/.test(navigator.userAgent)) {
+ s.setStyle(effect.element, {top: ''});
+ }
+ elemClip = d.makeClipping(effect.element);
+ s.setStyle(effect.element, {height: '0px'});
+ s.showElement(effect.element);
+ },
+ afterUpdateInternal: function (effect) {
+ s.setStyle(effect.element.firstChild,
+ {bottom: (effect.dims[0] - effect.element.clientHeight) + 'px'});
+ },
+ afterFinishInternal: function (effect) {
+ d.undoClipping(effect.element, elemClip);
+ // IE will crash if child is undoPositioned first
+ if (/MSIE/.test(navigator.userAgent)) {
+ d.undoPositioned(effect.element);
+ d.undoPositioned(effect.element.firstChild);
+ } else {
+ d.undoPositioned(effect.element.firstChild);
+ d.undoPositioned(effect.element);
+ }
+ s.setStyle(effect.element.firstChild,
+ {bottom: oldInnerBottom});
+ }
+ }, options || {});
+
+ return new MochiKit.Visual.Scale(element, 100, options);
+};
+
+/** @id MochiKit.Visual.slideUp */
+MochiKit.Visual.slideUp = function (element, /* optional */ options) {
+ /***
+
+ Slide an element up.
+ It needs to have the content of the element wrapped in a container
+ element with fixed height.
+
+ ***/
+ var d = MochiKit.DOM;
+ var b = MochiKit.Base;
+ var s = MochiKit.Style;
+ element = d.getElement(element);
+ if (!element.firstChild) {
+ throw "MochiKit.Visual.slideUp must be used on a element with a child";
+ }
+ d.removeEmptyTextNodes(element);
+ var oldInnerBottom = s.getStyle(element.firstChild, 'bottom');
+ var elemClip;
+ options = b.update({
+ scaleContent: false,
+ scaleX: false,
+ scaleMode: 'box',
+ scaleFrom: 100,
+ restoreAfterFinish: true,
+ beforeStartInternal: function (effect) {
+ d.makePositioned(effect.element);
+ d.makePositioned(effect.element.firstChild);
+ if (/Opera/.test(navigator.userAgent)) {
+ s.setStyle(effect.element, {top: ''});
+ }
+ elemClip = d.makeClipping(effect.element);
+ s.showElement(effect.element);
+ },
+ afterUpdateInternal: function (effect) {
+ s.setStyle(effect.element.firstChild,
+ {bottom: (effect.dims[0] - effect.element.clientHeight) + 'px'});
+ },
+ afterFinishInternal: function (effect) {
+ s.hideElement(effect.element);
+ d.undoClipping(effect.element, elemClip);
+ d.undoPositioned(effect.element.firstChild);
+ d.undoPositioned(effect.element);
+ s.setStyle(effect.element.firstChild, {bottom: oldInnerBottom});
+ }
+ }, options || {});
+ return new MochiKit.Visual.Scale(element, 0, options);
+};
+
+// Bug in opera makes the TD containing this element expand for a instance
+// after finish
+/** @id MochiKit.Visual.squish */
+MochiKit.Visual.squish = function (element, /* optional */ options) {
+ /***
+
+ Reduce an element and make it disappear.
+
+ ***/
+ var d = MochiKit.DOM;
+ var b = MochiKit.Base;
+ var elemClip;
+ options = b.update({
+ restoreAfterFinish: true,
+ beforeSetupInternal: function (effect) {
+ elemClip = d.makeClipping(effect.element);
+ },
+ afterFinishInternal: function (effect) {
+ MochiKit.Style.hideElement(effect.element);
+ d.undoClipping(effect.element, elemClip);
+ }
+ }, options || {});
+
+ return new MochiKit.Visual.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, options);
+};
+
+/** @id MochiKit.Visual.grow */
+MochiKit.Visual.grow = function (element, /* optional */ options) {
+ /***
+
+ Grow an element to its original size. Make it zero-sized before
+ if necessary.
+
+ ***/
+ var d = MochiKit.DOM;
+ var v = MochiKit.Visual;
+ var s = MochiKit.Style;
+ element = d.getElement(element);
+ options = MochiKit.Base.update({
+ direction: 'center',
+ moveTransition: v.Transitions.sinoidal,
+ scaleTransition: v.Transitions.sinoidal,
+ opacityTransition: v.Transitions.full,
+ scaleContent: true,
+ scaleFromCenter: false
+ }, options || {});
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: s.getStyle(element, 'opacity')
+ };
+
+ var dims = s.getElementDimensions(element);
+ var initialMoveX, initialMoveY;
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ initialMoveX = initialMoveY = moveX = moveY = 0;
+ break;
+ case 'top-right':
+ initialMoveX = dims.w;
+ initialMoveY = moveY = 0;
+ moveX = -dims.w;
+ break;
+ case 'bottom-left':
+ initialMoveX = moveX = 0;
+ initialMoveY = dims.h;
+ moveY = -dims.h;
+ break;
+ case 'bottom-right':
+ initialMoveX = dims.w;
+ initialMoveY = dims.h;
+ moveX = -dims.w;
+ moveY = -dims.h;
+ break;
+ case 'center':
+ initialMoveX = dims.w / 2;
+ initialMoveY = dims.h / 2;
+ moveX = -dims.w / 2;
+ moveY = -dims.h / 2;
+ break;
+ }
+
+ var optionsParallel = MochiKit.Base.update({
+ beforeSetupInternal: function (effect) {
+ s.setStyle(effect.effects[0].element, {height: '0px'});
+ s.showElement(effect.effects[0].element);
+ },
+ afterFinishInternal: function (effect) {
+ d.undoClipping(effect.effects[0].element);
+ d.undoPositioned(effect.effects[0].element);
+ s.setStyle(effect.effects[0].element, oldStyle);
+ }
+ }, options || {});
+
+ return new v.Move(element, {
+ x: initialMoveX,
+ y: initialMoveY,
+ duration: 0.01,
+ beforeSetupInternal: function (effect) {
+ s.hideElement(effect.element);
+ d.makeClipping(effect.element);
+ d.makePositioned(effect.element);
+ },
+ afterFinishInternal: function (effect) {
+ new v.Parallel(
+ [new v.Opacity(effect.element, {
+ sync: true, to: 1.0, from: 0.0,
+ transition: options.opacityTransition
+ }),
+ new v.Move(effect.element, {
+ x: moveX, y: moveY, sync: true,
+ transition: options.moveTransition
+ }),
+ new v.Scale(effect.element, 100, {
+ scaleMode: {originalHeight: dims.h,
+ originalWidth: dims.w},
+ sync: true,
+ scaleFrom: /Opera/.test(navigator.userAgent) ? 1 : 0,
+ transition: options.scaleTransition,
+ scaleContent: options.scaleContent,
+ scaleFromCenter: options.scaleFromCenter,
+ restoreAfterFinish: true
+ })
+ ], optionsParallel
+ );
+ }
+ });
+};
+
+/** @id MochiKit.Visual.shrink */
+MochiKit.Visual.shrink = function (element, /* optional */ options) {
+ /***
+
+ Shrink an element and make it disappear.
+
+ ***/
+ var d = MochiKit.DOM;
+ var v = MochiKit.Visual;
+ var s = MochiKit.Style;
+ element = d.getElement(element);
+ options = MochiKit.Base.update({
+ direction: 'center',
+ moveTransition: v.Transitions.sinoidal,
+ scaleTransition: v.Transitions.sinoidal,
+ opacityTransition: v.Transitions.none,
+ scaleContent: true,
+ scaleFromCenter: false
+ }, options || {});
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ height: element.style.height,
+ width: element.style.width,
+ opacity: s.getStyle(element, 'opacity')
+ };
+
+ var dims = s.getElementDimensions(element);
+ var moveX, moveY;
+
+ switch (options.direction) {
+ case 'top-left':
+ moveX = moveY = 0;
+ break;
+ case 'top-right':
+ moveX = dims.w;
+ moveY = 0;
+ break;
+ case 'bottom-left':
+ moveX = 0;
+ moveY = dims.h;
+ break;
+ case 'bottom-right':
+ moveX = dims.w;
+ moveY = dims.h;
+ break;
+ case 'center':
+ moveX = dims.w / 2;
+ moveY = dims.h / 2;
+ break;
+ }
+ var elemClip;
+
+ var optionsParallel = MochiKit.Base.update({
+ beforeStartInternal: function (effect) {
+ elemClip = d.makePositioned(effect.effects[0].element);
+ d.makeClipping(effect.effects[0].element);
+ },
+ afterFinishInternal: function (effect) {
+ s.hideElement(effect.effects[0].element);
+ d.undoClipping(effect.effects[0].element, elemClip);
+ d.undoPositioned(effect.effects[0].element);
+ s.setStyle(effect.effects[0].element, oldStyle);
+ }
+ }, options || {});
+
+ return new v.Parallel(
+ [new v.Opacity(element, {
+ sync: true, to: 0.0, from: 1.0,
+ transition: options.opacityTransition
+ }),
+ new v.Scale(element, /Opera/.test(navigator.userAgent) ? 1 : 0, {
+ sync: true, transition: options.scaleTransition,
+ scaleContent: options.scaleContent,
+ scaleFromCenter: options.scaleFromCenter,
+ restoreAfterFinish: true
+ }),
+ new v.Move(element, {
+ x: moveX, y: moveY, sync: true, transition: options.moveTransition
+ })
+ ], optionsParallel
+ );
+};
+
+/** @id MochiKit.Visual.pulsate */
+MochiKit.Visual.pulsate = function (element, /* optional */ options) {
+ /***
+
+ Pulse an element between appear/fade.
+
+ ***/
+ var d = MochiKit.DOM;
+ var v = MochiKit.Visual;
+ var b = MochiKit.Base;
+ var oldOpacity = MochiKit.Style.getStyle(element, 'opacity');
+ options = b.update({
+ duration: 3.0,
+ from: 0,
+ afterFinishInternal: function (effect) {
+ MochiKit.Style.setStyle(effect.element, {'opacity': oldOpacity});
+ }
+ }, options || {});
+ var transition = options.transition || v.Transitions.sinoidal;
+ var reverser = b.bind(function (pos) {
+ return transition(1 - v.Transitions.pulse(pos, options.pulses));
+ }, transition);
+ b.bind(reverser, transition);
+ return new v.Opacity(element, b.update({
+ transition: reverser}, options));
+};
+
+/** @id MochiKit.Visual.fold */
+MochiKit.Visual.fold = function (element, /* optional */ options) {
+ /***
+
+ Fold an element, first vertically, then horizontally.
+
+ ***/
+ var d = MochiKit.DOM;
+ var v = MochiKit.Visual;
+ var s = MochiKit.Style;
+ element = d.getElement(element);
+ var oldStyle = {
+ top: element.style.top,
+ left: element.style.left,
+ width: element.style.width,
+ height: element.style.height
+ };
+ var elemClip = d.makeClipping(element);
+ options = MochiKit.Base.update({
+ scaleContent: false,
+ scaleX: false,
+ afterFinishInternal: function (effect) {
+ new v.Scale(element, 1, {
+ scaleContent: false,
+ scaleY: false,
+ afterFinishInternal: function (effect) {
+ s.hideElement(effect.element);
+ d.undoClipping(effect.element, elemClip);
+ s.setStyle(effect.element, oldStyle);
+ }
+ });
+ }
+ }, options || {});
+ return new v.Scale(element, 5, options);
+};
+
+
+// Compatibility with MochiKit 1.0
+MochiKit.Visual.Color = MochiKit.Color.Color;
+MochiKit.Visual.getElementsComputedStyle = MochiKit.DOM.computedStyle;
+
+/* end of Rico adaptation */
+
+MochiKit.Visual.__new__ = function () {
+ var m = MochiKit.Base;
+
+ m.nameFunctions(this);
+
+ this.EXPORT_TAGS = {
+ ":common": this.EXPORT,
+ ":all": m.concat(this.EXPORT, this.EXPORT_OK)
+ };
+
+};
+
+MochiKit.Visual.EXPORT = [
+ "roundElement",
+ "roundClass",
+ "tagifyText",
+ "multiple",
+ "toggle",
+ "Parallel",
+ "Opacity",
+ "Move",
+ "Scale",
+ "Highlight",
+ "ScrollTo",
+ "Morph",
+ "fade",
+ "appear",
+ "puff",
+ "blindUp",
+ "blindDown",
+ "switchOff",
+ "dropOut",
+ "shake",
+ "slideDown",
+ "slideUp",
+ "squish",
+ "grow",
+ "shrink",
+ "pulsate",
+ "fold"
+];
+
+MochiKit.Visual.EXPORT_OK = [
+ "Base",
+ "PAIRS"
+];
+
+MochiKit.Visual.__new__();
+
+MochiKit.Base._exportSymbols(this, MochiKit.Visual);
diff --git a/dom/tests/mochitest/ajax/mochikit/MochiKit/__package__.js b/dom/tests/mochitest/ajax/mochikit/MochiKit/__package__.js
new file mode 100644
index 0000000000..8d644b19e9
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/MochiKit/__package__.js
@@ -0,0 +1,18 @@
+dojo.kwCompoundRequire({
+ "common": [
+ "MochiKit.Base",
+ "MochiKit.Iter",
+ "MochiKit.Logging",
+ "MochiKit.DateTime",
+ "MochiKit.Format",
+ "MochiKit.Async",
+ "MochiKit.DOM",
+ "MochiKit.Style",
+ "MochiKit.LoggingPane",
+ "MochiKit.Color",
+ "MochiKit.Signal",
+ "MochiKit.Position",
+ "MochiKit.Visual"
+ ]
+});
+dojo.provide("MochiKit.*");
diff --git a/dom/tests/mochitest/ajax/mochikit/manifest.json b/dom/tests/mochitest/ajax/mochikit/manifest.json
new file mode 100644
index 0000000000..5bf0e943de
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/manifest.json
@@ -0,0 +1 @@
+{testcases:['tests/MochiKit-Async.html','tests/MochiKit-Base.html','tests/MochiKit-DateTime.html','tests/MochiKit-DOM.html','tests/MochiKit-Style.html','tests/MochiKit-Format.html','tests/MochiKit-Iter.html','tests/MochiKit-Logging.html','tests/MochiKit-MochiKit.html','tests/MochiKit-Color.html','tests/MochiKit-Selector.html','tests/MochiKit-Signal.html','tests/MochiKit-Visual.html']}
diff --git a/dom/tests/mochitest/ajax/mochikit/mochitest.ini b/dom/tests/mochitest/ajax/mochikit/mochitest.ini
new file mode 100644
index 0000000000..25f301e302
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/mochitest.ini
@@ -0,0 +1,26 @@
+[DEFAULT]
+support-files =
+ manifest.json
+ MochiKit/Async.js
+ MochiKit/Base.js
+ MochiKit/Color.js
+ MochiKit/Controls.js
+ MochiKit/DOM.js
+ MochiKit/DateTime.js
+ MochiKit/DragAndDrop.js
+ MochiKit/Format.js
+ MochiKit/Iter.js
+ MochiKit/Logging.js
+ MochiKit/LoggingPane.js
+ MochiKit/MochiKit.js
+ MochiKit/MockDOM.js
+ MochiKit/Position.js
+ MochiKit/Selector.js
+ MochiKit/Signal.js
+ MochiKit/Sortable.js
+ MochiKit/Style.js
+ MochiKit/Test.js
+ MochiKit/Visual.js
+ MochiKit/__package__.js
+
+[test_Mochikit.html]
diff --git a/dom/tests/mochitest/ajax/mochikit/test_Mochikit.html b/dom/tests/mochitest/ajax/mochikit/test_Mochikit.html
new file mode 100644
index 0000000000..a94ce14a4f
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/test_Mochikit.html
@@ -0,0 +1,15 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+ <title>Test for Mochikit</title>
+ <script src="/MochiKit/Base.js"></script>
+ <script src="/MochiKit/Async.js"></script>
+ <script src="/tests/SimpleTest/SimpleTest.js"></script>
+ <script type="text/javascript" src="../lib/AJAX_setup.js"></script>
+ <link rel="stylesheet" type="text/css" href="../lib/test.css" />
+</head>
+<body>
+ <iframe width="100%" height="500" id="testframe" src=""></iframe>
+</body>
+</html>
+
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/FakeJSAN.js b/dom/tests/mochitest/ajax/mochikit/tests/FakeJSAN.js
new file mode 100644
index 0000000000..639519ecf0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/FakeJSAN.js
@@ -0,0 +1,40 @@
+var JSAN = {
+ global: this,
+ use: function (module, symbols) {
+ var components = module.split(/\./);
+ var fn = components.join('/') + '.js';
+ var o = JSAN.global;
+ var i, c;
+ for (i = 0; i < components.length; i++) {
+ o = o[components[i]];
+ if (typeof(o) == 'undefined') {
+ break;
+ }
+ }
+ if (typeof(o) != 'undefined') {
+ return o;
+ }
+
+ load(fn);
+ o = JSAN.global;
+ for (i = 0; i < components.length; i++) {
+ o = o[components[i]];
+ if (typeof(o) == 'undefined') {
+ return undefined;
+ }
+ }
+ if (!symbols) {
+ var tags = o.EXPORT_TAGS;
+ if (tags) {
+ symbols = tags[':common'] || tags[':all'];
+ }
+ }
+ if (symbols) {
+ for (i = 0; i < symbols.length; i++) {
+ c = symbols[i];
+ JSAN.global[c] = o[c];
+ }
+ }
+ return o;
+ }
+};
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Async.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Async.html
new file mode 100644
index 0000000000..32889ea821
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Async.html
@@ -0,0 +1,408 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Async.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript">
+try {
+
+ var increment = function (res) {
+ return res + 1;
+ }
+
+ var throwStuff = function (res) {
+ throw new GenericError(res);
+ }
+
+ var catchStuff = function (res) {
+ return res.message;
+ }
+
+ var returnError = function (res) {
+ return new GenericError(res);
+ }
+
+ var anythingOkCallback = function (msg) {
+ return function (res) {
+ ok(true, msg);
+ return res;
+ }
+ }
+
+ var testEqCallback = function () {
+ /*
+ sort of emulate how deferreds work in Twisted
+ for "convenient" testing
+ */
+ var args = [];
+ for (var i = 0; i < arguments.length; i++) {
+ args.push(arguments[i]);
+ }
+ return function (res) {
+ var nargs = args.slice();
+ nargs.unshift(res);
+ is.apply(this, nargs);
+ return res;
+ }
+ }
+
+ var neverHappen = function (d) {
+ ok(false, "this should never happen");
+ }
+
+ /*
+ Test normal Deferred operation
+ */
+ var d = new Deferred();
+ d.addCallback(testEqCallback(1, "pre-deferred callback"));
+ d.callback(1);
+ d.addCallback(increment);
+ d.addCallback(testEqCallback(2, "post-deferred callback"));
+ d.addCallback(throwStuff);
+ d.addCallback(neverHappen);
+ d.addErrback(catchStuff);
+ d.addCallback(testEqCallback(2, "throw -> err, catch -> success"));
+ d.addCallback(returnError);
+ d.addCallback(neverHappen);
+ d.addErrback(catchStuff);
+ d.addCallback(testEqCallback(2, "return -> err, catch -> succcess"));
+
+ /*
+ Test Deferred cancellation
+ */
+ var cancelled = function (d) {
+ ok(true, "canceller called!");
+ }
+
+ var cancelledError = function (res) {
+ ok(res instanceof CancelledError, "CancelledError here");
+ }
+
+ d = new Deferred(cancelled);
+ d.addCallback(neverHappen);
+ d.addErrback(cancelledError);
+ d.cancel();
+
+ /*
+ Test succeed / fail
+ */
+
+ d = succeed(1).addCallback(testEqCallback(1, "succeed"));
+
+ // default error
+ d = fail().addCallback(neverHappen);
+ d = d.addErrback(anythingOkCallback("default fail"));
+
+ // default wrapped error
+ d = fail("web taco").addCallback(neverHappen).addErrback(catchStuff);
+ d = d.addCallback(testEqCallback("web taco", "wrapped fail"));
+
+ // default unwrapped error
+ d = fail(new GenericError("ugh")).addCallback(neverHappen).addErrback(catchStuff);
+ d = d.addCallback(testEqCallback("ugh", "unwrapped fail"));
+
+ /*
+ Test deferred dependencies
+ */
+
+ var deferredIncrement = function (res) {
+ var rval = succeed(res);
+ rval.addCallback(increment);
+ return rval;
+ }
+
+ d = succeed(1).addCallback(deferredIncrement);
+ d = d.addCallback(testEqCallback(2, "dependent deferred succeed"));
+
+ var deferredFailure = function (res) {
+ return fail(res);
+ }
+
+ d = succeed("ugh").addCallback(deferredFailure).addErrback(catchStuff);
+ d = d.addCallback(testEqCallback("ugh", "dependent deferred fail"));
+
+ /*
+ Test double-calling, double-failing, etc.
+ */
+ try {
+ succeed(1).callback(2);
+ neverHappen();
+ } catch (e) {
+ ok(e instanceof AlreadyCalledError, "double-call");
+ }
+ try {
+ fail(1).errback(2);
+ neverHappen();
+ } catch (e) {
+ ok(e instanceof AlreadyCalledError, "double-fail");
+ }
+ try {
+ d = succeed(1);
+ d.cancel();
+ d = d.callback(2);
+ ok(true, "swallowed one callback, no canceller");
+ d.callback(3);
+ neverHappen();
+ } catch (e) {
+ ok(e instanceof AlreadyCalledError, "swallow cancel");
+ }
+ try {
+ d = new Deferred(cancelled);
+ d.cancel();
+ d = d.callback(1);
+ neverHappen();
+ } catch (e) {
+ ok(e instanceof AlreadyCalledError, "non-swallowed cancel");
+ }
+
+ /* Test incorrect Deferred usage */
+
+ d = new Deferred();
+ try {
+ d.callback(new Deferred());
+ neverHappen();
+ } catch (e) {
+ ok (e instanceof Error, "deferred not allowed for callback");
+ }
+ d = new Deferred();
+ try {
+ d.errback(new Deferred());
+ neverHappen();
+ } catch (e) {
+ ok (e instanceof Error, "deferred not allowed for errback");
+ }
+
+ d = new Deferred();
+ (new Deferred()).addCallback(function () { return d; }).callback(1);
+ try {
+ d.addCallback(function () {});
+ neverHappen();
+ } catch (e) {
+ ok (e instanceof Error, "chained deferred not allowed to be re-used");
+ }
+
+ /*
+ evalJSONRequest test
+ */
+ var fakeReq = {"responseText":'[1,2,3,4,"asdf",{"a":["b", "c"]}]'};
+ var obj = [1,2,3,4,"asdf",{"a":["b", "c"]}];
+ isDeeply(obj, evalJSONRequest(fakeReq), "evalJSONRequest");
+
+ try {
+ MochiKit.Async.getXMLHttpRequest();
+ ok(true, "getXMLHttpRequest");
+ } catch (e) {
+ ok(false, "no love from getXMLHttpRequest");
+ }
+
+ var lock = new DeferredLock();
+ var lst = [];
+ var pushNumber = function (x) {
+ return function (res) { lst.push(x); }
+ };
+ lock.acquire().addCallback(pushNumber(1));
+ is( compare(lst, [1]), 0, "lock acquired" );
+ lock.acquire().addCallback(pushNumber(2));
+ is( compare(lst, [1]), 0, "lock waiting for release" );
+ lock.acquire().addCallback(pushNumber(3));
+ is( compare(lst, [1]), 0, "lock waiting for release" );
+ lock.release();
+ is( compare(lst, [1, 2]), 0, "lock passed on" );
+ lock.release();
+ is( compare(lst, [1, 2, 3]), 0, "lock passed on" );
+ lock.release();
+ try {
+ lock.release();
+ ok( false, "over-release didn't raise" );
+ } catch (e) {
+ ok( true, "over-release raised" );
+ }
+ lock.acquire().addCallback(pushNumber(1));
+ is( compare(lst, [1, 2, 3, 1]), 0, "lock acquired" );
+ lock.release();
+ is( compare(lst, [1, 2, 3, 1]), 0, "lock released" );
+
+ var d = new Deferred();
+ lst = [];
+ d.addCallback(operator.add, 2);
+ d.addBoth(operator.add, 4);
+ d.addCallback(bind(lst.push, lst));
+ d.callback(1);
+ is( lst[0], 7, "auto-partial addCallback addBoth" );
+ d.addCallback(function () { throw new Error(); });
+ ebTest = function(a, b) {
+ map(bind(lst.push, lst), arguments);
+ };
+ d.addErrback(ebTest, "foo");
+ is( lst[1], "foo", "auto-partial errback" );
+ is( lst.length, 3, "auto-partial errback" );
+
+ /*
+ Test DeferredList
+ */
+
+ var callList = [new Deferred(), new Deferred(), new Deferred()];
+ callList[0].addCallback(increment);
+ callList[1].addCallback(increment);
+ callList[2].addCallback(increment);
+ var defList = new DeferredList(callList);
+ ok(defList instanceof Deferred, "DeferredList looks like a Deferred");
+
+ callList[0].callback(3);
+ callList[1].callback(5);
+ callList[2].callback(4);
+
+ defList.addCallback(function (lst) {
+ is( arrayEqual(lst, [[true, 4], [true, 6], [true, 5]]), 1,
+ "deferredlist result ok" );
+ });
+
+ /*
+ Test fireOnOneCallback
+ */
+
+ var callList2 = [new Deferred(), new Deferred(), new Deferred()];
+ callList2[0].addCallback(increment);
+ callList2[1].addCallback(increment);
+ callList2[2].addCallback(increment);
+ var defList2 = new DeferredList(callList2, true);
+ callList2[1].callback(5);
+ callList2[0].callback(3);
+ callList2[2].callback(4);
+
+ defList2.addCallback(function (lst) {
+ is( arrayEqual(lst, [1, 6]), 1, "deferredlist fireOnOneCallback ok" );
+ });
+
+ /*
+ Test fireOnOneErrback
+ */
+
+ var callList3 = [new Deferred(), new Deferred(), new Deferred()];
+ callList3[0].addCallback(increment);
+ callList3[1].addCallback(throwStuff);
+ callList3[2].addCallback(increment);
+ var defList3 = new DeferredList(callList3, false, true);
+ defList3.callback = neverHappen;
+ callList3[0].callback(3);
+ callList3[1].callback("foo");
+ callList3[2].callback(4);
+
+ defList3.addErrback(function (err) {
+ is( err.message, "foo", "deferredlist fireOnOneErrback ok" );
+ });
+
+ /*
+ Test consumeErrors
+ */
+
+ var callList4 = [new Deferred(), new Deferred(), new Deferred()];
+ callList4[0].addCallback(increment);
+ callList4[1].addCallback(throwStuff);
+ callList4[2].addCallback(increment);
+ var defList4 = new DeferredList(callList4, false, false, true);
+ defList4.addErrback(neverHappen);
+ callList4[1].addCallback(function (arg) {
+ is(arg, null, "deferredlist consumeErrors ok" );
+ });
+ callList4[0].callback(3);
+ callList4[1].callback("foo");
+ callList4[2].callback(4);
+
+ /*
+ Test gatherResults
+ */
+
+ var callList5 = [new Deferred(), new Deferred(), new Deferred()];
+ callList5[0].addCallback(increment);
+ callList5[1].addCallback(increment);
+ callList5[2].addCallback(increment);
+ var gatherRet = gatherResults(callList5);
+ callList5[0].callback(3);
+ callList5[1].callback(5);
+ callList5[2].callback(4);
+
+ gatherRet.addCallback(function (lst) {
+ is( arrayEqual(lst, [4, 6, 5]), 1,
+ "gatherResults result ok" );
+ });
+
+ /*
+ Test maybeDeferred
+ */
+
+ var maybeDef = maybeDeferred(increment, 4);
+ maybeDef.addCallback(testEqCallback(5, "maybeDeferred sync ok"));
+
+ var maybeDef2 = deferredIncrement(8);
+ maybeDef2.addCallback(testEqCallback(9, "maybeDeferred async ok"));
+
+ ok( true, "synchronous test suite finished!");
+
+ var t = (new Date().getTime());
+ SimpleTest.waitForExplicitFinish();
+ checkCallLater = function (originalTime) {
+ is(originalTime, t, "argument passed in OK");
+ is(arguments.length, 1, "argument count right");
+ };
+ var lock = new DeferredLock();
+ withLock = function (msg) {
+ var cb = partial.apply(null, extend(null, arguments, 1));
+ var d = lock.acquire().addCallback(cb);
+ d.addErrback(ok, false, msg);
+ d.addCallback(function () {
+ ok(true, msg);
+ lock.release();
+ });
+ return d;
+ }
+ withLock("callLater", function () {
+ return callLater(0.05, checkCallLater, t);
+ });
+ withLock("wait", function () {
+ return wait(0.05, t).addCallback(checkCallLater);
+ });
+ withLock("loadJSONDoc", function () {
+ var d = loadJSONDoc("test_MochiKit-Async.json");
+ d.addCallback(function (doc) {
+ is(doc.passed, true, "loadJSONDoc passed");
+ });
+ d.addErrback(function (doc) {
+ ok(false, "loadJSONDoc failed");
+ });
+ return d;
+ });
+ lock.acquire().addCallback(function () {
+ ok(true, "async suite finished");
+ SimpleTest.finish();
+ });
+
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+ SimpleTest.finish();
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Base.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Base.html
new file mode 100644
index 0000000000..3db71e1e75
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Base.html
@@ -0,0 +1,34 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_Base.js"></script>
+<script type="text/javascript">
+try {
+ tests.test_Base({ok:ok,is:is});
+ ok( true, "test suite finished!");
+} catch (err) {
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Color.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Color.html
new file mode 100644
index 0000000000..bad32dfb18
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Color.html
@@ -0,0 +1,84 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="../MochiKit/Logging.js"></script>
+ <script type="text/javascript" src="../MochiKit/Color.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+ <style type="text/css">.redtext {color: red}</style>
+</head>
+<body>
+<div style="position:absolute; top: 0px; left:0px; width:0px; height:0px">
+ <span style="color: red" id="c_direct"></span>
+ <span class="redtext" id="c_indirect"></span>
+</div>
+<pre id="test">
+<script type="text/javascript" src="test_Color.js"></script>
+<script type="text/javascript">
+try {
+
+ var t = {ok:ok, is:is};
+ tests.test_Color({ok:ok, is:is});
+ is(
+ Color.fromText(SPAN()).toHexString(),
+ "#000000",
+ "fromText no style"
+ );
+
+ is(
+ Color.fromText("c_direct").toHexString(),
+ Color.fromName("red").toHexString(),
+ "fromText direct style"
+ );
+
+ is(
+ Color.fromText("c_indirect").toHexString(),
+ Color.fromName("red").toHexString(),
+ "fromText indirect style"
+ );
+
+ is(
+ Color.fromComputedStyle("c_direct", "color").toHexString(),
+ Color.fromName("red").toHexString(),
+ "fromComputedStyle direct style"
+ );
+
+ is(
+ Color.fromComputedStyle("c_indirect", "color").toHexString(),
+ Color.fromName("red").toHexString(),
+ "fromComputedStyle indirect style"
+ );
+
+ is(
+ Color.fromBackground((SPAN(null, 'test'))).toHexString(),
+ Color.fromName("white").toHexString(),
+ "fromBackground with DOM"
+ );
+
+
+ // Done!
+
+ ok( true, "test suite finished!");
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DOM.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DOM.html
new file mode 100644
index 0000000000..45036d9c74
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DOM.html
@@ -0,0 +1,316 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<div style="display: none;">
+ <form id="form_test">
+ <select name="select">
+ <option value="foo" selected="selected">foo</option>
+ <option value="bar">bar</option>
+ <option value="baz">baz</option>
+ </select>
+ <select name="selmultiple" multiple="multiple">
+ <option value="bar" selected="selected">bar</option>
+ <option value="baz" selected="selected">baz</option>
+ <option value="foo">foo</option>
+ </select>
+ <input type="hidden" name="hidden" value="test" />
+ <input type="radio" name="radio_off" value="1" />
+ <input type="radio" name="radio_off" value="2" />
+ <input type="radio" name="radio_off" value="3" />
+ <input type="radio" name="radio_on" value="1" />
+ <input type="radio" name="radio_on" value="2" checked="checked" />
+ <input type="radio" name="radio_on" value="3" />
+ </form>
+ <form id="form_test2">
+ <select name="selempty">
+ <option value="" selected="selected">foo</option>
+ </select>
+ <select name="selempty2">
+ <option selected="selected">foo</option>
+ </select>
+ </form>
+ <div id="parentTwo" class="two">
+ <div id="parentOne" class="one">
+ <div id="parentZero" class="zero">
+ <span id="child">child</span>
+ </div>
+ </div>
+ </div>
+</div>
+
+<pre id="test">
+<script type="text/javascript">
+try {
+
+ lst = [];
+ o = {"blah": function () { lst.push("original"); }};
+ addToCallStack(o, "blah", function () { lst.push("new"); }, true);
+ addToCallStack(o, "blah", function () { lst.push("stuff"); }, true);
+ is( typeof(o.blah), 'function', 'addToCallStack has a function' );
+ is( o.blah.callStack.length, 3, 'callStack length 3' );
+ o.blah();
+ is( lst.join(" "), "original new stuff", "callStack in correct order" );
+ is( o.blah, null, "set to null" );
+ lst = [];
+ o = {"blah": function () { lst.push("original"); }};
+ addToCallStack(o, "blah",
+ function () { lst.push("new"); return false;}, false);
+ addToCallStack(o, "blah", function () { lst.push("stuff"); }, false);
+ o.blah();
+ is( lst.join(" "), "original new", "callStack in correct order (abort)" );
+ o.blah();
+ is( lst.join(" "), "original new original new", "callStack in correct order (again)" );
+
+
+ is( escapeHTML("<>\"&bar"), "&lt;&gt;&quot;&amp;bar", "escapeHTML" ); // for emacs highlighting: "
+
+ var isDOM = function (value, expected, message) {
+ is( escapeHTML(toHTML(value)), escapeHTML(expected), message );
+ };
+
+ var d = document.createElement('span');
+ updateNodeAttributes(d, {"foo": "bar", "baz": "wibble"});
+ isDOM( d, '<span baz="wibble" foo="bar"/>', "updateNodeAttributes" );
+
+ var d = document.createElement('span');
+ appendChildNodes(d, 'word up', [document.createElement('span')]);
+ isDOM( d, '<span>word up<span/></span>', 'appendChildNodes' );
+
+ replaceChildNodes(d, 'Think Different');
+ isDOM( d, '<span>Think Different</span>', 'replaceChildNodes' );
+
+
+ insertSiblingNodesBefore(d.childNodes[0], 'word up', document.createElement('span'));
+ isDOM( d, '<span>word up<span/>Think Different</span>', 'insertSiblingNodesBefore' );
+
+ insertSiblingNodesAfter(d.childNodes[0], 'purple monkey', document.createElement('span'));
+ isDOM( d, '<span>word uppurple monkey<span/><span/>Think Different</span>', 'insertSiblingNodesAfter' );
+
+ d = createDOM("span");
+ isDOM( d, "<span/>", "createDOM empty" );
+
+
+ d = createDOM("span", {"foo": "bar", "baz": "wibble"});
+ isDOM( d, '<span baz="wibble" foo="bar"/>', "createDOM attributes" );
+
+ d = createDOM("span", {"foo": "bar", "baz": "wibble", "spam": "egg"}, "one", "two", "three");
+ is( getNodeAttribute(d, 'foo'), "bar", "createDOM attribute" );
+ is( getNodeAttribute(d, 'baz'), "wibble", "createDOM attribute" );
+ removeNodeAttribute(d, "spam");
+ is( scrapeText(d), "onetwothree", "createDOM contents" );
+
+ isDOM( d, '<span baz="wibble" foo="bar">onetwothree</span>', "createDOM contents" );
+
+ d = createDOM("span", null, function (f) {
+ return this.nodeName.toLowerCase() + "hi" + f.nodeName.toLowerCase();});
+ isDOM( d, '<span>spanhispan</span>', 'createDOM function call' );
+
+ d = createDOM("span", null, {msg: "hi", dom: function (f) {
+ return f.nodeName.toLowerCase() + this.msg; }});
+ isDOM( d, '<span>spanhi</span>', 'createDOM this.dom() call' );
+
+ d = createDOM("span", null, {msg: "hi", __dom__: function (f) {
+ return f.nodeName.toLowerCase() + this.msg; }});
+ isDOM( d, '<span>spanhi</span>', 'createDOM this.__dom__() call' );
+
+ d = createDOM("span", null, range(4));
+ isDOM( d, '<span>0123</span>', 'createDOM iterable' );
+
+
+ var d = {"taco": "pork"};
+ registerDOMConverter("taco",
+ function (o) { return !isUndefinedOrNull(o.taco); },
+ function (o) { return "Goddamn, I like " + o.taco + " tacos"; }
+ );
+ d = createDOM("span", null, d);
+ // not yet public API
+ domConverters.unregister("taco");
+
+ isDOM( d, "<span>Goddamn, I like pork tacos</span>", "createDOM with custom converter" );
+
+ is(
+ escapeHTML(toHTML(SPAN(null))),
+ escapeHTML(toHTML(createDOM("span", null))),
+ "createDOMFunc vs createDOM"
+ );
+
+ is( scrapeText(d), "Goddamn, I like pork tacos", "scrape OK" );
+ is( scrapeText(d, true).join(""), "Goddamn, I like pork tacos", "scrape Array OK" );
+
+ var st = DIV(null, STRONG(null, "d"), "oor ", STRONG(null, "f", SPAN(null, "r"), "a"), "me");
+ is( scrapeText(st), "door frame", "scrape in-order" );
+
+
+ ok( !isUndefinedOrNull(getElement("test")), "getElement might work" );
+ ok( !isUndefinedOrNull($("test")), "$alias$$ CASH MONEY alias might work" );
+
+ d = createDOM("span", null, "one", "two");
+ swapDOM(d.childNodes[0], document.createTextNode("uno"));
+ isDOM( d, "<span>unotwo</span>", "swapDOM" );
+
+ is( scrapeText(d, true).join(" "), "uno two", "multi-node scrapeText" );
+ /*
+
+ TODO:
+ addLoadEvent (async test?)
+
+ */
+
+ d = createDOM("span", {"class": "foo"});
+ setElementClass(d, "bar baz");
+ ok( d.className == "bar baz", "setElementClass");
+ toggleElementClass("bar", d);
+ ok( d.className == "baz", "toggleElementClass: " + d.className);
+ toggleElementClass("bar", d);
+ ok( hasElementClass(d, "baz", "bar"),
+ "toggleElementClass 2: " + d.className);
+ addElementClass(d, "bar");
+ ok( hasElementClass(d, "baz", "bar"),
+ "toggleElementClass 3: " + d.className);
+ ok( addElementClass(d, "blah"), "addElementClass return");
+ ok( hasElementClass(d, "baz", "bar", "blah"), "addElementClass action");
+ ok( !hasElementClass(d, "not"), "hasElementClass single");
+ ok( !hasElementClass(d, "baz", "not"), "hasElementClass multiple");
+ ok( removeElementClass(d, "blah"), "removeElementClass" );
+ ok( !removeElementClass(d, "blah"), "removeElementClass again" );
+ ok( !hasElementClass(d, "blah"), "removeElementClass again (hasElement)" );
+ removeElementClass(d, "baz");
+ ok( !swapElementClass(d, "blah", "baz"), "false swapElementClass" );
+ ok( !hasElementClass(d, "baz"), "false swapElementClass from" );
+ ok( !hasElementClass(d, "blah"), "false swapElementClass to" );
+ addElementClass(d, "blah");
+ ok( swapElementClass(d, "blah", "baz"), "swapElementClass" );
+ ok( hasElementClass(d, "baz"), "swapElementClass has toClass" );
+ ok( !hasElementClass(d, "blah"), "swapElementClass !has fromClass" );
+ ok( !swapElementClass(d, "blah", "baz"), "swapElementClass twice" );
+ ok( hasElementClass(d, "baz"), "swapElementClass has toClass" );
+ ok( !hasElementClass(d, "blah"), "swapElementClass !has fromClass" );
+
+ TABLE;
+ TBODY;
+ TR;
+ var t = TABLE(null,
+ TBODY({"class": "foo bar", "id":"tbody0"},
+ TR({"class": "foo", "id":"tr0"}),
+ TR({"class": "bar", "id":"tr1"})
+ )
+ );
+
+ var matchElements = getElementsByTagAndClassName;
+ is(
+ map(itemgetter("id"), matchElements(null, "foo", t)).join(" "),
+ "tbody0 tr0",
+ "getElementsByTagAndClassName found all tags with foo class"
+ );
+ is(
+ map(itemgetter("id"), matchElements("tr", "foo", t)).join(" "),
+ "tr0",
+ "getElementsByTagAndClassName found all tr tags with foo class"
+ );
+ is(
+ map(itemgetter("id"), matchElements("tr", null, t)).join(" "),
+ "tr0 tr1",
+ "getElementsByTagAndClassName found all tr tags"
+ );
+
+ var oldDoc = document;
+ var doc = MochiKit.MockDOM.createDocument();
+ is( currentDocument(), document, "currentDocument() correct" );
+ withDocument(doc, function () {
+ ok( document != doc, "global doc unchanged" );
+ is( currentDocument(), doc, "currentDocument() correct" );
+ var h1 = H1();
+ var span = SPAN(null, "foo", h1);
+ appendChildNodes(currentDocument().body, span);
+ });
+ is( document, oldDoc, "doc restored" );
+ is( doc.childNodes.length, 1, "doc has one child" );
+ is( doc.body.childNodes.length, 1, "body has one child" );
+ var sp = doc.body.childNodes[0];
+ is( sp.nodeName, "SPAN", "only child is SPAN" );
+ is( sp.childNodes.length, 2, "SPAN has two childNodes" );
+ is( sp.childNodes[0].nodeValue, "foo", "first node is text" );
+ is( sp.childNodes[1].nodeName, "H1", "second child is H1" );
+
+ is( currentDocument(), document, "currentDocument() correct" );
+ try {
+ withDocument(doc, function () {
+ ok( document != doc, "global doc unchanged" );
+ is( currentDocument(), doc, "currentDocument() correct" );
+ throw new Error("foo");
+ });
+ ok( false, "didn't throw" );
+ } catch (e) {
+ ok( true, "threw" );
+ }
+
+ var mockWindow = {"foo": "bar"};
+ is (currentWindow(), window, "currentWindow ok");
+ withWindow(mockWindow, function () {
+ is(currentWindow(), mockWindow, "withWindow ok");
+ });
+ is (currentWindow(), window, "currentWindow ok");
+
+ doc = MochiKit.MockDOM.createDocument();
+ var frm;
+ withDocument(doc, function () {
+ frm = FORM({name: "ignore"},
+ INPUT({name:"foo", value:"bar"}),
+ INPUT({name:"foo", value:"bar"}),
+ INPUT({name:"baz", value:"bar"})
+ );
+ });
+ var kv = formContents(frm);
+ is( kv[0].join(","), "foo,foo,baz", "mock formContents names" );
+ is( kv[1].join(","), "bar,bar,bar", "mock formContents values" );
+ is( queryString(frm), "foo=bar&foo=bar&baz=bar", "mock queryString hook" );
+
+ var kv = formContents("form_test");
+ is( kv[0].join(","), "select,selmultiple,selmultiple,hidden,radio_on", "formContents names" );
+ is( kv[1].join(","), "foo,bar,baz,test,2", "formContents values" );
+ is( queryString("form_test"), "select=foo&selmultiple=bar&selmultiple=baz&hidden=test&radio_on=2", "queryString hook" );
+ kv = formContents("form_test2");
+ is( kv[0].join(","), "selempty,selempty2", "formContents names empty option values" );
+ is( kv[1].join(","), ",foo", "formContents empty option values" );
+ is( queryString("form_test2"), "selempty=&selempty2=foo", "queryString empty option values" );
+
+ var d = DIV(null, SPAN(), " \n\t", SPAN(), "foo", SPAN(), " ");
+ is( d.childNodes.length, 6, "removeEmptyNodes test conditions correct" );
+ removeEmptyTextNodes(d);
+ is( d.childNodes.length, 4, "removeEmptyNodes" );
+
+ is( getFirstParentByTagAndClassName('child', 'div', 'two'), getElement("parentTwo"), "getFirstParentByTagAndClassName found parent" );
+ is( getFirstParentByTagAndClassName('child', 'div'), getElement("parentZero"), "getFirstParentByTagAndClassName found parent (any class)" );
+ is( getFirstParentByTagAndClassName('child', '*', 'two'), getElement("parentTwo"), "getFirstParentByTagAndClassName found parent (any tag)" );
+
+ ok( true, "test suite finished!");
+
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DateTime.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DateTime.html
new file mode 100644
index 0000000000..43ad9d4abd
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DateTime.html
@@ -0,0 +1,39 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/DateTime.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_DateTime.js"></script>
+<script type="text/javascript">
+try {
+
+ tests.test_DateTime({ok:ok, is:is});
+ ok( true, "test suite finished!");
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DragAndDrop.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DragAndDrop.html
new file mode 100644
index 0000000000..a191a53bee
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-DragAndDrop.html
@@ -0,0 +1,54 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="../MochiKit/Color.js"></script>
+ <script type="text/javascript" src="../MochiKit/Signal.js"></script>
+ <script type="text/javascript" src="../MochiKit/Visual.js"></script>
+ <script type="text/javascript" src="../MochiKit/DragAndDrop.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+ <style type="text/css">
+ .drop-hover {
+ }
+ #drag1 {
+ visibility: hidden;
+ }
+ #drop1 {
+ visibility: hidden;
+ }
+ </style>
+</head>
+<body>
+<div id='drag1'>drag1</div>
+<div id='drop1'>drop1</div>
+<pre id="test">
+<script type="text/javascript" src="test_DragAndDrop.js"></script>
+<script type="text/javascript">
+try {
+
+ // Counting the number of tests is really lame
+ tests.test_DragAndDrop({ok:ok, is:is});
+ ok( true, "test suite finished!");
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Format.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Format.html
new file mode 100644
index 0000000000..58bffa6bf8
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Format.html
@@ -0,0 +1,39 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Format.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_Format.js"></script>
+<script type="text/javascript">
+try {
+
+ tests.test_Format({ok:ok, is:is});
+ ok( true, "test suite finished!");
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Iter.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Iter.html
new file mode 100644
index 0000000000..8086acc2db
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Iter.html
@@ -0,0 +1,38 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_Iter.js"></script>
+<script type="text/javascript">
+try {
+
+ tests.test_Iter({ok:ok, is:is});
+ ok( true, "test suite finished!");
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-JSAN.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-JSAN.html
new file mode 100644
index 0000000000..53a0e0ed04
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-JSAN.html
@@ -0,0 +1,32 @@
+<html>
+<head>
+ <script type="text/javascript" src="JSAN.js"></script>
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript">
+ // TODO: Make this a harness for the other tests
+ JSAN.use('Test.More');
+ JSAN.addRepository('..');
+ var lst = [];
+ plan({"tests": 1});
+ var wc = {};
+ wc['MochiKit'] = true;
+ for (var k in window) { wc[k] = true; }
+ for (var k in window) { wc[k] = true; }
+ JSAN.use('MochiKit.MochiKit', []);
+ for (var k in window) {
+ if (!(k in wc) && !(k.charAt(0) == '[')) {
+ lst.push(k);
+ }
+ }
+ lst.sort();
+ pollution = lst.join(" ");
+ is(pollution, "compare reduce", "namespace pollution?");
+ JSAN.use('MochiKit.MochiKit');
+
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Logging.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Logging.html
new file mode 100644
index 0000000000..d92229a6e0
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Logging.html
@@ -0,0 +1,40 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Logging.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript" src="test_Logging.js"></script>
+<script type="text/javascript">
+try {
+
+ tests.test_Logging({ok:ok, is:is});
+ ok( true, "test suite finished!");
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-MochiKit.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-MochiKit.html
new file mode 100644
index 0000000000..d1a8b60d89
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-MochiKit.html
@@ -0,0 +1,18 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body>
+
+<pre id="test">
+<script type="text/javascript">
+ is( isUndefined(null), false, "null is not undefined" );
+ is( isUndefined(""), false, "empty string is not undefined" );
+ is( isUndefined(undefined), true, "undefined is undefined" );
+ is( isUndefined({}.foo), true, "missing property is undefined" );
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Selector.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Selector.html
new file mode 100644
index 0000000000..503acef071
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Selector.html
@@ -0,0 +1,274 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="../MochiKit/Selector.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+ <style type="text/css">
+ p, #sequence {
+ display: none;
+ }
+ </style>
+</head>
+<body>
+ <p>Test originally from <a href="http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector" rel="bookmark">this blog entry</a>.</p>
+
+ <p>Here are some links in a normal paragraph: <a href="http://www.google.com/" title="Google!">Google</a>, <a href="http://groups.google.com/">Google Groups</a>. This link has <code>class="blog"</code>: <a href="http://diveintomark.org/" class="blog" fakeattribute="bla">diveintomark</a></p>
+ <div id="foo">
+ <p>Everything inside the red border is inside a div with <code>id="foo"</code>.</p>
+ <p>This is a normal link: <a href="http://www.yahoo.com/">Yahoo</a></p>
+
+ <a style="display: none" href="http://www.example.com/outsidep">This a is not inside a p</a>
+
+ <p>This link has <code>class="blog"</code>: <a href="http://simon.incutio.com/" class="blog">Simon Willison's Weblog</a></p>
+ <p>This <span><a href="http://www.example.com/insidespan">link</a></span> is inside a span, not directly child of p</p>
+ <p lang="en-us">Nonninn</p>
+ <p lang="is-IS">Sniðugt</p>
+ <p>
+ <input type="button" name="enabled" value="enabled" id="enabled">
+ <input type="button" name="disabled" value="disabled" id="disabled" disabled="1" />
+ <input type="checkbox" name="checked" value="checked" id="checked" checked="1" />
+ </p>
+ </div>
+
+ <div id="sequence">
+ <a href="http://www.example.com/link1">Link 1</a>
+ <a href="http://www.example.com/link2">Link 2</a>
+ <a href="http://www.example.com/link3">Link 3</a>
+ <a href="http://www.example.com/link4">Link 4</a>
+ <p>Something else</p>
+ <a href="http://www.example.com/link5">Link 5</a>
+ <a href="http://www.example.com/link6">Link 6</a>
+ <a href="http://www.example.com/link7">Link 7</a>
+ <a href="http://www.example.com/link8">Link 8</a>
+ </div>
+
+ <div id="multiclass" class="multiple classnames here"></div>
+<pre id="test">
+<script type="text/javascript">
+try {
+
+ var testExpected = function (res, exp, lbl) {
+ for (var i=0; i < res.length; i ++) {
+ is( res[i].href, exp[i], lbl + ' (' + i + ')');
+ }
+ };
+
+ var expected = ['http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector',
+ 'http://www.google.com/',
+ 'http://groups.google.com/',
+ 'http://diveintomark.org/',
+ 'http://www.yahoo.com/',
+ 'http://www.example.com/outsidep',
+ 'http://simon.incutio.com/',
+ 'http://www.example.com/insidespan',
+ 'http://www.example.com/link1',
+ 'http://www.example.com/link2',
+ 'http://www.example.com/link3',
+ 'http://www.example.com/link4',
+ 'http://www.example.com/link5',
+ 'http://www.example.com/link6',
+ 'http://www.example.com/link7',
+ 'http://www.example.com/link8'];
+ var results = $$('a');
+ testExpected(results, expected, "'a' selector");
+
+ expected = ['http://diveintomark.org/', 'http://simon.incutio.com/'];
+ results = $$('p a.blog');
+ testExpected(results, expected, "'p a.blog' selector");
+
+ expected = ['http://www.yahoo.com/',
+ 'http://www.example.com/outsidep',
+ 'http://simon.incutio.com/',
+ 'http://www.example.com/insidespan',
+ 'http://www.example.com/link1',
+ 'http://www.example.com/link2',
+ 'http://www.example.com/link3',
+ 'http://www.example.com/link4',
+ 'http://www.example.com/link5',
+ 'http://www.example.com/link6',
+ 'http://www.example.com/link7',
+ 'http://www.example.com/link8'];
+ results = $$('div a');
+ testExpected(results, expected, "'div a' selector");
+
+ expected = ['http://www.yahoo.com/',
+ 'http://www.example.com/outsidep',
+ 'http://simon.incutio.com/',
+ 'http://www.example.com/insidespan'];
+ results = $$('div#foo a');
+ testExpected(results, expected, "'div#foo a' selector");
+
+ expected = ['http://simon.incutio.com/',
+ 'http://www.example.com/insidespan'];
+ results = $$('#foo a.blog');
+ testExpected(results, expected, "'#foo a.blog' selector");
+
+ expected = ['http://diveintomark.org/',
+ 'http://simon.incutio.com/',
+ 'http://www.example.com/insidespan'];
+ results = $$('.blog');
+ testExpected(results, expected, "'.blog' selector");
+
+ expected = ['http://www.google.com/',
+ 'http://www.yahoo.com/',
+ 'http://www.example.com/outsidep',
+ 'http://www.example.com/insidespan',
+ 'http://www.example.com/link1',
+ 'http://www.example.com/link2',
+ 'http://www.example.com/link3',
+ 'http://www.example.com/link4',
+ 'http://www.example.com/link5',
+ 'http://www.example.com/link6',
+ 'http://www.example.com/link7',
+ 'http://www.example.com/link8'];
+ results = $$('a[href^="http://www"]');
+ testExpected(results, expected, "'a[href^=http://www]' selector");
+
+ expected = ['http://diveintomark.org/'];
+ results = $$('a[href$="org/"]');
+ testExpected(results, expected, "'a[href$=org/]' selector");
+
+ expected = ['http://www.google.com/',
+ 'http://groups.google.com/'];
+ results = $$('a[href*="google"]');
+ testExpected(results, expected, "'a[href*=google]' selector");
+
+ expected = ['http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector'];
+ results = $$('a[rel="bookmark"]');
+ testExpected(results, expected, "'a[rel=bookmark]' selector");
+
+ expected = ['http://diveintomark.org/'];
+ results = $$('a[fakeattribute]');
+ testExpected(results, expected, "'a[fakeattribute]' selector");
+
+ /* This doesn't work in IE due to silly DOM implementation
+ expected = ['http://www.google.com/'];
+ results = $$('a[title]');
+ testExpected(results, expected, "'a[title]' selector");
+ */
+
+ results = $$('p[lang|="en"]');
+ is( results[0].firstChild.nodeValue, 'Nonninn', "'p[lang|=en]' selector");
+
+ expected = ['http://simon.incutio.com/archive/2003/03/25/#getElementsBySelector',
+ 'http://www.google.com/',
+ 'http://groups.google.com/',
+ 'http://diveintomark.org/',
+ 'http://www.yahoo.com/',
+ 'http://simon.incutio.com/',
+ 'http://www.example.com/insidespan'];
+ results = $$('p > a');
+ testExpected(results, expected, "'p > a' selector");
+
+ expected = ['http://www.example.com/insidespan'];
+ results = $$('span > a');
+ testExpected(results, expected, "'span > a' selector");
+
+ expected = ['http://groups.google.com/',
+ 'http://www.example.com/link2',
+ 'http://www.example.com/link3',
+ 'http://www.example.com/link4',
+ 'http://www.example.com/link6',
+ 'http://www.example.com/link7',
+ 'http://www.example.com/link8'];
+ results = $$('a + a');
+ testExpected(results, expected, "'a + a' selector");
+
+ expected = ['http://www.example.com/link1',
+ 'http://www.example.com/link3',
+ 'http://www.example.com/link6',
+ 'http://www.example.com/link8'];
+ results = $$('#sequence a:nth-child(odd)');
+ testExpected(results, expected, "'#sequence a:nth-child(odd)' selector");
+
+ expected = ['http://www.example.com/link1',
+ 'http://www.example.com/link3',
+ 'http://www.example.com/link5',
+ 'http://www.example.com/link7'];
+ results = $$('#sequence a:nth-of-type(odd)');
+ testExpected(results, expected, "'#sequence a:nth-of-type(odd)' selector");
+
+ expected = ['http://www.example.com/link1',
+ 'http://www.example.com/link4',
+ 'http://www.example.com/link7'];
+ results = $$('#sequence a:nth-of-type(3n+1)');
+ testExpected(results, expected, "'#sequence a:nth-of-type(3n+1)' selector");
+
+ expected = ['http://www.example.com/link5'];
+ results = $$('#sequence a:nth-child(6)');
+ testExpected(results, expected, "'#sequence a:nth-child(6)' selector");
+
+ expected = ['http://www.example.com/link5'];
+ results = $$('#sequence a:nth-of-type(5)');
+ testExpected(results, expected, "'#sequence a:nth-of-type(5)' selector");
+
+ expected = [$('enabled'), $('checked')];
+ results = $$('body :enabled');
+ for (var i=0; i < results.length; i ++) {
+ is( results[i], expected[i], "'body :enabled" + ' (' + i + ')');
+ }
+
+ expected = [$('disabled')];
+ results = $$('body :disabled');
+ for (var i=0; i < results.length; i ++) {
+ is( results[i], expected[i], "'body :disabled" + ' (' + i + ')');
+ }
+
+ expected = [$('checked')];
+ results = $$('body :checked');
+ for (var i=0; i < results.length; i ++) {
+ is( results[i], expected[i], "'body :checked" + ' (' + i + ')');
+ }
+
+ expected = document.getElementsByTagName('p');
+ results = $$('a[href$=outsidep] ~ *');
+ for (var i=0; i < results.length; i ++) {
+ is( results[i], expected[i+4], "'a[href$=outsidep] ~ *' selector" + ' (' + i + ')');
+ }
+
+ expected = [document.documentElement];
+ results = $$(':root');
+ for (var i=0; i < results.length; i ++) {
+ is( results[i], expected[i], "':root' selector" + ' (' + i + ')');
+ }
+
+ expected = [$('multiclass')];
+ results = $$('[class~=classnames]');
+ for (var i=0; i < results.length; i ++) {
+ is( results[i], expected[i], "'~=' attribute test" + ' (' + i + ')');
+ }
+
+ var doc = MochiKit.MockDOM.createDocument();
+ appendChildNodes(doc.body, A({"href": "http://www.example.com/insideAnotherDocument"}, "Inside a document"));
+ withDocument(doc, function(){
+ is( $$(":root")[0], doc, ":root on a different document" );
+ is( $$("a")[0], doc.body.firstChild, "a inside a different document" );
+ });
+
+ ok( true, "test suite finished!");
+
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Signal.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Signal.html
new file mode 100644
index 0000000000..9c37416d68
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Signal.html
@@ -0,0 +1,43 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="../MochiKit/Signal.js"></script>
+ <script type="text/javascript" src="../MochiKit/Logging.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+
+</head>
+<body>
+
+Please ignore this button: <input type="submit" id="submit" /><br />
+
+<pre id="test">
+<script type="text/javascript" src="test_Signal.js"></script>
+<script type="text/javascript">
+try {
+
+ tests.test_Signal({ok:ok, is:is});
+ ok(true, "test suite finished!");
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok(false, s);
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Style.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Style.html
new file mode 100644
index 0000000000..b01adc6e7e
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Style.html
@@ -0,0 +1,141 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/MockDOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="../MochiKit/Color.js"></script>
+ <script type="text/javascript" src="../MochiKit/Logging.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+</head>
+<body style="border: 0; margin: 0; padding: 0;">
+
+<div id="styleTest" style="position: absolute; left: 400px; top: 100px; width: 100px; height: 100px; background: rgb(255, 0, 0); opacity: 0.5; filter: alpha(opacity=50); font-size: 10px">TEST<span id="styleSubTest">SUB</span></div>
+
+<pre id="test">
+<script type="text/javascript">
+
+try {
+
+ // initial
+ var pos = getElementPosition('styleTest');
+ is(pos.x, 400, 'initial x position');
+ is(pos.y, 100, 'initial y position');
+
+ // moved
+ var newPos = new MochiKit.Style.Coordinates(500, 200);
+ setElementPosition('styleTest', newPos);
+ pos = getElementPosition('styleTest');
+ is(pos.x, 500, 'updated x position');
+ is(pos.y, 200, 'updated y position');
+
+ // moved with relativeTo
+ anotherPos = new MochiKit.Style.Coordinates(100, 100);
+ pos = getElementPosition('styleTest', anotherPos);
+ is(pos.x, 400, 'updated x position (using relativeTo parameter)');
+ is(pos.y, 100, 'updated y position (using relativeTo parameter)');
+
+ // Coordinates object
+ pos = getElementPosition({x: 123, y: 321});
+ is(pos.x, 123, 'passthrough x position');
+ is(pos.y, 321, 'passthrough y position');
+
+ // Coordinates object with relativeTo
+ pos = getElementPosition({x: 123, y: 321}, {x: 100, y: 50});
+ is(pos.x, 23, 'passthrough x position (using relativeTo parameter)');
+ is(pos.y, 271, 'passthrough y position (using relativeTo parameter)');
+
+ pos = getElementPosition('garbage');
+ is(typeof(pos), 'undefined',
+ 'invalid element should return an undefined position');
+
+ // Only set one coordinate
+ setElementPosition('styleTest', {'x': 300});
+ pos = getElementPosition('styleTest');
+ is(pos.x, 300, 'updated only x position');
+ is(pos.y, 200, 'not updated y position');
+
+ var mc = MochiKit.Color.Color;
+ var red = mc.fromString('rgb(255,0,0)');
+ var color = null;
+
+ color = mc.fromString(getStyle('styleTest', 'background-color'));
+ is(color.toHexString(), red.toHexString(),
+ 'test getStyle selector case');
+
+ color = mc.fromString(getStyle('styleTest', 'backgroundColor'));
+ is(color.toHexString(), red.toHexString(),
+ 'test getStyle camel case');
+
+ is(getStyle('styleSubTest', 'font-size'), '10px',
+ 'test computed getStyle selector case');
+
+ is(getStyle('styleSubTest', 'fontSize'), '10px',
+ 'test computed getStyle camel case');
+
+ is(eval(getStyle('styleTest', 'opacity')), 0.5,
+ 'test getStyle opacity');
+
+ is(getStyle('styleTest', 'opacity'), 0.5, 'test getOpacity');
+
+ setStyle('styleTest', {'opacity': 0.2});
+ is(getStyle('styleTest', 'opacity'), 0.2, 'test setOpacity');
+
+ setStyle('styleTest', {'opacity': 0});
+ is(getStyle('styleTest', 'opacity'), 0, 'test setOpacity');
+
+ setStyle('styleTest', {'opacity': 1});
+ var t = getStyle('styleTest', 'opacity');
+ ok(t > 0.999 && t <= 1, 'test setOpacity');
+
+ var dims = getElementDimensions('styleTest');
+ is(dims.w, 100, 'getElementDimensions w ok');
+ is(dims.h, 100, 'getElementDimensions h ok');
+
+ setElementDimensions('styleTest', {'w': 200, 'h': 150});
+ dims = getElementDimensions('styleTest');
+ is(dims.w, 200, 'setElementDimensions w ok');
+ is(dims.h, 150, 'setElementDimensions h ok');
+
+ setElementDimensions('styleTest', {'w': 150});
+ dims = getElementDimensions('styleTest');
+ is(dims.w, 150, 'setElementDimensions only w ok');
+ is(dims.h, 150, 'setElementDimensions h not updated ok');
+
+ hideElement('styleTest');
+ dims = getElementDimensions('styleTest');
+ is(dims.w, 150, 'getElementDimensions w ok when display none');
+ is(dims.h, 150, 'getElementDimensions h ok when display none');
+
+ dims = getViewportDimensions();
+ is(dims.w > 0, true, 'test getViewportDimensions w');
+ is(dims.h > 0, true, 'test getViewportDimensions h');
+
+ pos = getViewportPosition();
+ is(pos.x, 0, 'test getViewportPosition x');
+ is(pos.y, 0, 'test getViewportPosition y');
+
+ ok( true, "test suite finished!");
+
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+
+}
+</script>
+</pre>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Visual.html b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Visual.html
new file mode 100644
index 0000000000..e4a40c7e48
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/MochiKit-Visual.html
@@ -0,0 +1,190 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/Base.js"></script>
+ <script type="text/javascript" src="../MochiKit/Iter.js"></script>
+ <script type="text/javascript" src="../MochiKit/DOM.js"></script>
+ <script type="text/javascript" src="../MochiKit/Async.js"></script>
+ <script type="text/javascript" src="../MochiKit/Style.js"></script>
+ <script type="text/javascript" src="../MochiKit/Color.js"></script>
+ <script type="text/javascript" src="../MochiKit/Signal.js"></script>
+ <script type="text/javascript" src="../MochiKit/Position.js"></script>
+ <script type="text/javascript" src="../MochiKit/Visual.js"></script>
+ <script type="text/javascript" src="SimpleTest/SimpleTest.js"></script>
+
+ <link rel="stylesheet" type="text/css" href="SimpleTest/test.css">
+ <style type="text/css">
+ #elt1, #elt2, #ctn1 {
+ visibility: hidden;
+ font-size: 1em;
+ margin: 2px;
+ }
+ #elt3 {
+ display: none;
+ }
+ #ctn1 {
+ height: 2px;
+ }
+ </style>
+</head>
+<body>
+
+<div id='elt1'>elt1</div>
+<div id='ctn1'><div id='elt2'></div></div>
+<div id='elt3'>elt3</div>
+<pre id="test">
+<script type="text/javascript">
+try {
+ var TestQueue = function () {
+ };
+
+ TestQueue.prototype = new MochiKit.Visual.ScopedQueue();
+
+ MochiKit.Base.update(TestQueue.prototype, {
+ startLoop: function (func, interval) {
+ this.started = true;
+ var timePos = new Date().getTime();
+ while (this.started) {
+ timePos += interval;
+ MochiKit.Base.map(function (effect) {
+ effect.loop(timePos);
+ }, this.effects);
+ }
+ },
+ stopLoop: function () {
+ this.started = false;
+ }
+ });
+
+ var gl = new TestQueue();
+ MochiKit.Visual.Queues.instances['global'] = gl;
+ MochiKit.Visual.Queues.instances['elt1'] = gl;
+ MochiKit.Visual.Queues.instances['elt2'] = gl;
+ MochiKit.Visual.Queues.instances['elt3'] = gl;
+ MochiKit.Visual.Queues.instances['ctn1'] = gl;
+ MochiKit.Visual.Queue = gl;
+
+ pulsate("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display != 'none', true, "pulsate ok");
+ }});
+
+ pulsate("elt1", {pulses: 2, afterFinish: function () {
+ is(getElement('elt1').style.display != 'none', true, "pulsate with numbered pulses ok");
+ }});
+
+ shake("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display != 'none', true, "shake ok");
+ }});
+
+ fade("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display, 'none', "fade ok");
+ }});
+
+ appear("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display != 'none', true, "appear ok");
+ }});
+
+ toggle("elt1", "size", {afterFinish: function () {
+ is(getElement('elt1').style.display, 'none', "toggle size ok");
+ }});
+
+ toggle("elt1", "size", {afterFinish: function () {
+ is(getElement('elt1').style.display != 'none', true, "toggle size reverse ok");
+ }});
+
+ Morph("elt1", {"style": {"font-size": "2em"}, afterFinish: function () {
+ is(getStyle("elt1", "font-size"), "2em", "Morph OK");
+ }});
+
+ Morph("elt1", {"style": {"font-size": "1em", "margin-left": "4px"}, afterFinish: function () {
+ is(getStyle("elt1", "font-size"), "1em", "Morph multiple (font) OK");
+ is(getStyle("elt1", "margin-left"), "4px", "Morph multiple (margin) OK");
+ }});
+
+ switchOff("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display, 'none', "switchOff ok");
+ }});
+
+ grow("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display != 'none', true, "grow ok");
+ }});
+
+ shrink("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display, 'none', "shrink ok");
+ }});
+
+ showElement('elt1');
+ dropOut("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display, 'none', "dropOut ok");
+ }});
+
+ showElement('elt1');
+ puff("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display, 'none', "puff ok");
+ }});
+
+ showElement('elt1');
+ fold("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display, 'none', "fold ok");
+ }});
+
+ showElement('elt1');
+ squish("elt1", {afterFinish: function () {
+ is(getElement('elt1').style.display, 'none', "squish ok");
+ }});
+
+ slideUp("ctn1", {afterFinish: function () {
+ is(getElement('ctn1').style.display, 'none', "slideUp ok");
+ }});
+
+ slideDown("ctn1", {afterFinish: function () {
+ is(getElement('ctn1').style.display != 'none', true, "slideDown ok");
+ }});
+
+ blindDown("ctn1", {afterFinish: function () {
+ is(getElement('ctn1').style.display != 'none', true, "blindDown ok");
+ }});
+
+ blindUp("ctn1", {afterFinish: function () {
+ is(getElement('ctn1').style.display, 'none', "blindUp ok");
+ }});
+
+ multiple(["elt1", "ctn1"], appear, {afterFinish: function (effect) {
+ is(effect.element.style.display != 'none', true, "multiple ok");
+ }});
+
+ toggle("elt3", "size", {afterFinish: function () {
+ is(getElement('elt3').style.display != 'none', true, "toggle with css ok");
+ }});
+
+ toggle("elt3", "size", {afterFinish: function () {
+ is(getElement('elt3').style.display, 'none', "toggle with css ok");
+ }});
+
+ var toTests = [roundElement, roundClass, tagifyText, Opacity, Move, Scale, Highlight, ScrollTo, Morph];
+ for (var m in toTests) {
+ toTests[m]("elt1");
+ ok(true, toTests[m].NAME + " doesn't need 'new' keyword");
+ }
+ ok(true, "visual suite finished");
+
+} catch (err) {
+
+ var s = "test suite failure!\n";
+ var o = {};
+ var k = null;
+ for (k in err) {
+ // ensure unique keys?!
+ if (!o[k]) {
+ s += k + ": " + err[k] + "\n";
+ o[k] = err[k];
+ }
+ }
+ ok ( false, s );
+ SimpleTest.finish();
+
+}
+</script>
+</pre>
+</body>
+</html>
+
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/SimpleTest.js b/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/SimpleTest.js
new file mode 100644
index 0000000000..53c2a87939
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/SimpleTest.js
@@ -0,0 +1,473 @@
+/**
+ * SimpleTest, a partial Test.Simple/Test.More API compatible test library.
+ *
+ * Why?
+ *
+ * Test.Simple doesn't work on IE < 6.
+ * TODO:
+ * * Support the Test.Simple API used by MochiKit, to be able to test MochiKit
+ * itself against IE 5.5
+ *
+**/
+
+if (typeof(SimpleTest) == "undefined") {
+ var SimpleTest = {};
+}
+
+var parentRunner = null;
+if (typeof(parent) != "undefined" && parent.TestRunner) {
+ parentRunner = parent.TestRunner;
+} else if (parent && parent.wrappedJSObject &&
+ parent.wrappedJSObject.TestRunner) {
+ parentRunner = parent.wrappedJSObject.TestRunner;
+}
+
+// Check to see if the TestRunner is present and has logging
+if (parentRunner) {
+ SimpleTest._logEnabled = parentRunner.logEnabled;
+}
+
+SimpleTest._tests = [];
+SimpleTest._stopOnLoad = true;
+
+/**
+ * Something like assert.
+**/
+SimpleTest.ok = function (condition, name) {
+ if (arguments.length > 2) {
+ const diag = "Too many arguments passed to `ok(condition, name)`";
+ SimpleTest.record(false, name, diag);
+ } else {
+ SimpleTest.record(condition, name);
+ }
+}
+
+SimpleTest.record = function (condition, name, diag) {
+ var test = {'result': !!condition, 'name': name, 'diag': diag || ""};
+ if (SimpleTest._logEnabled)
+ SimpleTest._logResult(test, "TEST-PASS", "TEST-UNEXPECTED-FAIL");
+ SimpleTest._tests.push(test);
+};
+
+/**
+ * Roughly equivalent to ok(a==b, name)
+**/
+SimpleTest.is = function (a, b, name) {
+ var repr = MochiKit.Base.repr;
+ SimpleTest.record(a == b, name, "got " + repr(a) + ", expected " + repr(b));
+};
+
+SimpleTest.isnot = function (a, b, name) {
+ var repr = MochiKit.Base.repr;
+ SimpleTest.record(a != b, name, "Didn't expect " + repr(a) + ", but got it.");
+};
+
+// --------------- Test.Builder/Test.More todo() -----------------
+
+SimpleTest.todo = function(condition, name, diag) {
+ var test = {'result': !!condition, 'name': name, 'diag': diag || "", todo: true};
+ if (SimpleTest._logEnabled)
+ SimpleTest._logResult(test, "TEST-UNEXPECTED-PASS", "TEST-KNOWN-FAIL");
+ SimpleTest._tests.push(test);
+};
+
+SimpleTest._logResult = function(test, passString, failString) {
+ var msg = test.result ? passString : failString;
+ msg += " | ";
+ if (parentRunner.currentTestURL)
+ msg += parentRunner.currentTestURL;
+ msg += " | " + test.name;
+ var diag = "";
+ if (test.diag)
+ diag = " - " + test.diag;
+ if (test.result) {
+ if (test.todo)
+ parentRunner.logger.error(msg + diag);
+ else
+ parentRunner.logger.log(msg);
+ } else {
+ if (test.todo)
+ parentRunner.logger.log(msg);
+ else
+ parentRunner.logger.error(msg + diag);
+ }
+};
+
+/**
+ * Copies of is and isnot with the call to ok replaced by a call to todo.
+**/
+
+SimpleTest.todo_is = function (a, b, name) {
+ var repr = MochiKit.Base.repr;
+ SimpleTest.todo(a == b, name, "got " + repr(a) + ", expected " + repr(b));
+};
+
+SimpleTest.todo_isnot = function (a, b, name) {
+ var repr = MochiKit.Base.repr;
+ SimpleTest.todo(a != b, name, "Didn't expect " + repr(a) + ", but got it.");
+};
+
+
+/**
+ * Makes a test report, returns it as a DIV element.
+**/
+SimpleTest.report = function () {
+ var DIV = MochiKit.DOM.DIV;
+ var passed = 0;
+ var failed = 0;
+ var todo = 0;
+ var results = MochiKit.Base.map(
+ function (test) {
+ var cls, msg;
+ if (test.todo && !test.result) {
+ todo++;
+ cls = "test_todo";
+ msg = "todo - " + test.name + " " + test.diag;
+ } else if (test.result &&!test.todo) {
+ passed++;
+ cls = "test_ok";
+ msg = "ok - " + test.name;
+ } else {
+ failed++;
+ cls = "test_not_ok";
+ msg = "not ok - " + test.name + " " + test.diag;
+ }
+ return DIV({"class": cls}, msg);
+ },
+ SimpleTest._tests
+ );
+ var summary_class = ((failed == 0) ? 'all_pass' : 'some_fail');
+ return DIV({'class': 'tests_report'},
+ DIV({'class': 'tests_summary ' + summary_class},
+ DIV({'class': 'tests_passed'}, "Passed: " + passed),
+ DIV({'class': 'tests_failed'}, "Failed: " + failed),
+ DIV({'class': 'tests_todo'}, "Todo: " + todo)),
+ results
+ );
+};
+
+/**
+ * Toggle element visibility
+**/
+SimpleTest.toggle = function(el) {
+ if (MochiKit.Style.computedStyle(el, 'display') == 'block') {
+ el.style.display = 'none';
+ } else {
+ el.style.display = 'block';
+ }
+};
+
+/**
+ * Toggle visibility for divs with a specific class.
+**/
+SimpleTest.toggleByClass = function (cls, evt) {
+ var elems = getElementsByTagAndClassName('div', cls);
+ MochiKit.Base.map(SimpleTest.toggle, elems);
+ if (evt)
+ evt.preventDefault();
+};
+
+/**
+ * Shows the report in the browser
+**/
+
+SimpleTest.showReport = function() {
+ var togglePassed = A({'href': '#'}, "Toggle passed tests");
+ var toggleFailed = A({'href': '#'}, "Toggle failed tests");
+ togglePassed.onclick = partial(SimpleTest.toggleByClass, 'test_ok');
+ toggleFailed.onclick = partial(SimpleTest.toggleByClass, 'test_not_ok');
+ var body = document.body; // Handles HTML documents
+ if (!body) {
+ // Do the XML thing
+ body = document.getElementsByTagNameNS("http://www.w3.org/1999/xhtml",
+ "body")[0]
+ }
+ var firstChild = body.childNodes[0];
+ var addNode;
+ if (firstChild) {
+ addNode = function (el) {
+ body.insertBefore(el, firstChild);
+ };
+ } else {
+ addNode = function (el) {
+ body.appendChild(el)
+ };
+ }
+ addNode(togglePassed);
+ addNode(SPAN(null, " "));
+ addNode(toggleFailed);
+ addNode(SimpleTest.report());
+};
+
+/**
+ * Tells SimpleTest to don't finish the test when the document is loaded,
+ * useful for asynchronous tests.
+ *
+ * When SimpleTest.waitForExplicitFinish is called,
+ * explicit SimpleTest.finish() is required.
+**/
+SimpleTest.waitForExplicitFinish = function () {
+ SimpleTest._stopOnLoad = false;
+};
+
+/**
+ * Talks to the TestRunner if being ran on a iframe and the parent has a
+ * TestRunner object.
+**/
+SimpleTest.talkToRunner = function () {
+ if (parentRunner) {
+ parentRunner.testFinished(document);
+ }
+};
+
+/**
+ * Finishes the tests. This is automatically called, except when
+ * SimpleTest.waitForExplicitFinish() has been invoked.
+**/
+SimpleTest.finish = function () {
+ SimpleTest.showReport();
+ SimpleTest.talkToRunner();
+};
+
+
+addLoadEvent(function() {
+ if (SimpleTest._stopOnLoad) {
+ SimpleTest.finish();
+ }
+});
+
+// --------------- Test.Builder/Test.More isDeeply() -----------------
+
+
+SimpleTest.DNE = {dne: 'Does not exist'};
+SimpleTest.LF = "\r\n";
+SimpleTest._isRef = function (object) {
+ var type = typeof(object);
+ return type == 'object' || type == 'function';
+};
+
+
+SimpleTest._deepCheck = function (e1, e2, stack, seen) {
+ var ok = false;
+ // Either they're both references or both not.
+ var sameRef = !(!SimpleTest._isRef(e1) ^ !SimpleTest._isRef(e2));
+ if (e1 == null && e2 == null) {
+ ok = true;
+ } else if (e1 != null ^ e2 != null) {
+ ok = false;
+ } else if (e1 == SimpleTest.DNE ^ e2 == SimpleTest.DNE) {
+ ok = false;
+ } else if (sameRef && e1 == e2) {
+ // Handles primitives and any variables that reference the same
+ // object, including functions.
+ ok = true;
+ } else if (SimpleTest.isa(e1, 'Array') && SimpleTest.isa(e2, 'Array')) {
+ ok = SimpleTest._eqArray(e1, e2, stack, seen);
+ } else if (typeof e1 == "object" && typeof e2 == "object") {
+ ok = SimpleTest._eqAssoc(e1, e2, stack, seen);
+ } else {
+ // If we get here, they're not the same (function references must
+ // always simply rererence the same function).
+ stack.push({ vals: [e1, e2] });
+ ok = false;
+ }
+ return ok;
+};
+
+SimpleTest._eqArray = function (a1, a2, stack, seen) {
+ // Return if they're the same object.
+ if (a1 == a2) return true;
+
+ // JavaScript objects have no unique identifiers, so we have to store
+ // references to them all in an array, and then compare the references
+ // directly. It's slow, but probably won't be much of an issue in
+ // practice. Start by making a local copy of the array to as to avoid
+ // confusing a reference seen more than once (such as [a, a]) for a
+ // circular reference.
+ for (var j = 0; j < seen.length; j++) {
+ if (seen[j][0] == a1) {
+ return seen[j][1] == a2;
+ }
+ }
+
+ // If we get here, we haven't seen a1 before, so store it with reference
+ // to a2.
+ seen.push([ a1, a2 ]);
+
+ var ok = true;
+ // Only examines enumerable attributes. Only works for numeric arrays!
+ // Associative arrays return 0. So call _eqAssoc() for them, instead.
+ var max = a1.length > a2.length ? a1.length : a2.length;
+ if (max == 0) return SimpleTest._eqAssoc(a1, a2, stack, seen);
+ for (var i = 0; i < max; i++) {
+ var e1 = i > a1.length - 1 ? SimpleTest.DNE : a1[i];
+ var e2 = i > a2.length - 1 ? SimpleTest.DNE : a2[i];
+ stack.push({ type: 'Array', idx: i, vals: [e1, e2] });
+ if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
+ stack.pop();
+ } else {
+ break;
+ }
+ }
+ return ok;
+};
+
+SimpleTest._eqAssoc = function (o1, o2, stack, seen) {
+ // Return if they're the same object.
+ if (o1 == o2) return true;
+
+ // JavaScript objects have no unique identifiers, so we have to store
+ // references to them all in an array, and then compare the references
+ // directly. It's slow, but probably won't be much of an issue in
+ // practice. Start by making a local copy of the array to as to avoid
+ // confusing a reference seen more than once (such as [a, a]) for a
+ // circular reference.
+ seen = seen.slice(0);
+ for (var j = 0; j < seen.length; j++) {
+ if (seen[j][0] == o1) {
+ return seen[j][1] == o2;
+ }
+ }
+
+ // If we get here, we haven't seen o1 before, so store it with reference
+ // to o2.
+ seen.push([ o1, o2 ]);
+
+ // They should be of the same class.
+
+ var ok = true;
+ // Only examines enumerable attributes.
+ var o1Size = 0; for (var i in o1) o1Size++;
+ var o2Size = 0; for (var i in o2) o2Size++;
+ var bigger = o1Size > o2Size ? o1 : o2;
+ for (var i in bigger) {
+ var e1 = o1[i] == undefined ? SimpleTest.DNE : o1[i];
+ var e2 = o2[i] == undefined ? SimpleTest.DNE : o2[i];
+ stack.push({ type: 'Object', idx: i, vals: [e1, e2] });
+ if (ok = SimpleTest._deepCheck(e1, e2, stack, seen)) {
+ stack.pop();
+ } else {
+ break;
+ }
+ }
+ return ok;
+};
+
+SimpleTest._formatStack = function (stack) {
+ var variable = '$Foo';
+ for (var i = 0; i < stack.length; i++) {
+ var entry = stack[i];
+ var type = entry['type'];
+ var idx = entry['idx'];
+ if (idx != null) {
+ if (/^\d+$/.test(idx)) {
+ // Numeric array index.
+ variable += '[' + idx + ']';
+ } else {
+ // Associative array index.
+ idx = idx.replace("'", "\\'");
+ variable += "['" + idx + "']";
+ }
+ }
+ }
+
+ var vals = stack[stack.length-1]['vals'].slice(0, 2);
+ var vars = [
+ variable.replace('$Foo', 'got'),
+ variable.replace('$Foo', 'expected')
+ ];
+
+ var out = "Structures begin differing at:" + SimpleTest.LF;
+ for (var i = 0; i < vals.length; i++) {
+ var val = vals[i];
+ if (val == null) {
+ val = 'undefined';
+ } else {
+ val == SimpleTest.DNE ? "Does not exist" : "'" + val + "'";
+ }
+ }
+
+ out += vars[0] + ' = ' + vals[0] + SimpleTest.LF;
+ out += vars[1] + ' = ' + vals[1] + SimpleTest.LF;
+
+ return ' ' + out;
+};
+
+
+SimpleTest.isDeeply = function (it, as, name) {
+ var ok;
+ // ^ is the XOR operator.
+ if (SimpleTest._isRef(it) ^ SimpleTest._isRef(as)) {
+ // One's a reference, one isn't.
+ ok = false;
+ } else if (!SimpleTest._isRef(it) && !SimpleTest._isRef(as)) {
+ // Neither is an object.
+ ok = SimpleTest.is(it, as, name);
+ } else {
+ // We have two objects. Do a deep comparison.
+ var stack = [], seen = [];
+ if ( SimpleTest._deepCheck(it, as, stack, seen)) {
+ ok = SimpleTest.ok(true, name);
+ } else {
+ ok = SimpleTest.ok(false, name, SimpleTest._formatStack(stack));
+ }
+ }
+ return ok;
+};
+
+SimpleTest.typeOf = function (object) {
+ var c = Object.prototype.toString.apply(object);
+ var name = c.substring(8, c.length - 1);
+ if (name != 'Object') return name;
+ // It may be a non-core class. Try to extract the class name from
+ // the constructor function. This may not work in all implementations.
+ if (/function ([^(\s]+)/.test(Function.toString.call(object.constructor))) {
+ return RegExp.$1;
+ }
+ // No idea. :-(
+ return name;
+};
+
+SimpleTest.isa = function (object, clas) {
+ return SimpleTest.typeOf(object) == clas;
+};
+
+if ( parent.SimpleTest && parent.runAJAXTest ) (function(){
+ var oldRecord = SimpleTest.record;
+
+ SimpleTest.record = function(condition, name, diag, stack) {
+ parent.SimpleTest.record( condition, name, diag, stack );
+ return oldRecord( condition, name, diag, stack );
+ };
+
+ var oldFinish = SimpleTest.finish;
+
+ SimpleTest.finish = function() {
+ oldFinish();
+ parent.runAJAXTest();
+ };
+})();
+
+// Global symbols:
+var ok = SimpleTest.ok;
+var record = SimpleTest.record;
+var is = SimpleTest.is;
+var isnot = SimpleTest.isnot;
+var todo = SimpleTest.todo;
+var todo_is = SimpleTest.todo_is;
+var todo_isnot = SimpleTest.todo_isnot;
+var isDeeply = SimpleTest.isDeeply;
+var oldOnError = window.onerror;
+window.onerror = function (ev) {
+ is(0, 1, "Error thrown during test: " + ev);
+ if (oldOnError) {
+ try {
+ oldOnError(ev);
+ } catch (e) {
+ }
+ }
+ if (SimpleTest._stopOnLoad == false) {
+ // Need to finish() manually here
+ SimpleTest.finish();
+ }
+}
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/TestRunner.js b/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/TestRunner.js
new file mode 100644
index 0000000000..a4e3130759
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/TestRunner.js
@@ -0,0 +1,177 @@
+/**
+ * TestRunner: A test runner for SimpleTest
+ * TODO:
+ *
+ * * Avoid moving iframes: That causes reloads on mozilla and opera.
+ *
+ *
+**/
+var TestRunner = {};
+TestRunner.logEnabled = false;
+TestRunner._iframes = {};
+TestRunner._iframeDocuments = {};
+TestRunner._iframeRows = {};
+TestRunner._currentTest = 0;
+TestRunner._urls = [];
+TestRunner._testsDiv = DIV();
+TestRunner._progressDiv = DIV();
+TestRunner._summaryDiv = DIV(null,
+ H1(null, "Tests Summary"),
+ TABLE(null,
+ THEAD(null,
+ TR(null,
+ TH(null, "Test"),
+ TH(null, "Passed"),
+ TH(null, "Failed")
+ )
+ ),
+ TBODY()
+ )
+);
+
+/**
+ * This function is called after generating the summary.
+**/
+TestRunner.onComplete = null;
+
+/**
+ * If logEnabled is true, this is the logger that will be used.
+**/
+TestRunner.logger = MochiKit.Logging.logger;
+
+/**
+ * Toggle element visibility
+**/
+TestRunner._toggle = function(el) {
+ if (el.className == "noshow") {
+ el.className = "";
+ el.style.cssText = "";
+ } else {
+ el.className = "noshow";
+ el.style.cssText = "width:0px; height:0px; border:0px;";
+ }
+};
+
+
+/**
+ * Creates the iframe that contains a test
+**/
+TestRunner._makeIframe = function (url) {
+ var iframe = document.createElement('iframe');
+ iframe.src = url;
+ iframe.name = url;
+ iframe.width = "500";
+ var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
+ var tr = TR(null, TD({'colspan': '3'}, iframe));
+ iframe._row = tr;
+ tbody.appendChild(tr);
+ return iframe;
+};
+
+/**
+ * TestRunner entry point.
+ *
+ * The arguments are the URLs of the test to be ran.
+ *
+**/
+TestRunner.runTests = function (/*url...*/) {
+ if (TestRunner.logEnabled)
+ TestRunner.logger.log("SimpleTest START");
+
+ var body = document.getElementsByTagName("body")[0];
+ appendChildNodes(body,
+ TestRunner._testsDiv,
+ TestRunner._progressDiv,
+ TestRunner._summaryDiv
+ );
+ for (var i = 0; i < arguments.length; i++) {
+ TestRunner._urls.push(arguments[i]);
+ }
+ TestRunner.runNextTest();
+};
+
+/**
+ * Run the next test. If no test remains, calls makeSummary
+**/
+TestRunner.runNextTest = function() {
+ if (TestRunner._currentTest < TestRunner._urls.length) {
+ var url = TestRunner._urls[TestRunner._currentTest];
+ var progress = SPAN(null,
+ "Running ", A({href:url}, url), "..."
+ );
+
+ if (TestRunner.logEnabled)
+ TestRunner.logger.log(scrapeText(progress));
+
+ TestRunner._progressDiv.appendChild(progress);
+ TestRunner._iframes[url] = TestRunner._makeIframe(url);
+ } else {
+ TestRunner.makeSummary();
+ if (TestRunner.onComplete)
+ TestRunner.onComplete();
+ }
+};
+
+/**
+ * This stub is called by SimpleTest when a test is finished.
+**/
+TestRunner.testFinished = function (doc) {
+ appendChildNodes(TestRunner._progressDiv, SPAN(null, "Done"), BR());
+ var finishedURL = TestRunner._urls[TestRunner._currentTest];
+
+ if (TestRunner.logEnabled)
+ TestRunner.logger.debug("SimpleTest finished " + finishedURL);
+
+ TestRunner._iframeDocuments[finishedURL] = doc;
+ // TestRunner._iframes[finishedURL].style.display = "none";
+ TestRunner._toggle(TestRunner._iframes[finishedURL]);
+ TestRunner._currentTest++;
+ TestRunner.runNextTest();
+};
+
+/**
+ * Display the summary in the browser
+**/
+TestRunner.makeSummary = function() {
+ if (TestRunner.logEnabled)
+ TestRunner.logger.log("SimpleTest FINISHED");
+ var rows = [];
+ for (var url in TestRunner._iframeDocuments) {
+ var doc = TestRunner._iframeDocuments[url];
+ var nOK = withDocument(doc,
+ partial(getElementsByTagAndClassName, 'div', 'test_ok')
+ ).length;
+ var nNotOK = withDocument(doc,
+ partial(getElementsByTagAndClassName, 'div', 'test_not_ok')
+ ).length;
+ var toggle = partial(TestRunner._toggle, TestRunner._iframes[url]);
+ var jsurl = "TestRunner._toggle(TestRunner._iframes['" + url + "'])";
+ var row = TR(
+ {'style': {'backgroundColor': nNotOK > 0 ? "#f00":"#0f0"}},
+ TD(null, url),
+ TD(null, nOK),
+ TD(null, nNotOK)
+ );
+ row.onclick = toggle;
+ var tbody = TestRunner._summaryDiv.getElementsByTagName("tbody")[0];
+ tbody.insertBefore(row, TestRunner._iframes[url]._row)
+ }
+};
+
+if ( parent.SimpleTest && parent.runAJAXTest ) {
+ TestRunner.makeSummary = function() {
+ for (var url in TestRunner._iframeDocuments) {
+ var doc = TestRunner._iframeDocuments[url];
+
+ var OK = withDocument(doc, partial(getElementsByTagAndClassName, 'div', 'test_ok'));
+ for ( var i = 0; i < OK.length; i++ )
+ parent.SimpleTest.ok( true, OK[i].innerHTML );
+
+ var NotOK = withDocument(doc, partial(getElementsByTagAndClassName, 'div', 'test_not_ok'));
+ for ( var i = 0; i < NotOK.length; i++ )
+ parent.SimpleTest.ok( false, NotOK[i].innerHTML );
+ }
+
+ parent.runAJAXTest();
+ };
+}
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/test.css b/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/test.css
new file mode 100644
index 0000000000..38a401402f
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/test.css
@@ -0,0 +1,28 @@
+.test_ok {
+ color: green;
+ display: none;
+}
+.test_not_ok {
+ color: red;
+ display: block;
+}
+
+.test_ok, .test_not_ok {
+ border-bottom-width: 2px;
+ border-bottom-style: solid;
+ border-bottom-color: black;
+}
+
+.all_pass {
+ background-color: lime;
+}
+
+.some_fail {
+ background-color: red;
+}
+
+.tests_report {
+ border-width: 2px;
+ border-style: solid;
+ width: 20em;
+}
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/cli.js b/dom/tests/mochitest/ajax/mochikit/tests/cli.js
new file mode 100644
index 0000000000..18434604c8
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/cli.js
@@ -0,0 +1,6 @@
+MochiKit = {__export__: true};
+load('tests/FakeJSAN.js')
+JSAN.use('MochiKit.MockDOM');
+var window = this;
+var document = MochiKit.MockDOM.document;
+JSAN.use('MochiKit.MochiKit');
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/index.html b/dom/tests/mochitest/ajax/mochikit/tests/index.html
new file mode 100644
index 0000000000..da46bd32ce
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/index.html
@@ -0,0 +1,25 @@
+<html>
+<head>
+ <script type="text/javascript" src="../MochiKit/MochiKit.js"></script>
+ <script type="text/javascript" src="SimpleTest/TestRunner.js"></script>
+</head>
+<body>
+<script type="text/javascript">
+TestRunner.runTests(
+ 'MochiKit-Async.html',
+ 'MochiKit-Base.html',
+ 'MochiKit-DateTime.html',
+ 'MochiKit-DOM.html',
+ 'MochiKit-Style.html',
+ 'MochiKit-Format.html',
+ 'MochiKit-Iter.html',
+ 'MochiKit-Logging.html',
+ 'MochiKit-MochiKit.html',
+ 'MochiKit-Color.html',
+ 'MochiKit-Selector.html',
+ 'MochiKit-Signal.html',
+ 'MochiKit-Visual.html'
+);
+</script>
+</body>
+</html>
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/standalone.js b/dom/tests/mochitest/ajax/mochikit/tests/standalone.js
new file mode 100644
index 0000000000..d48571238f
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/standalone.js
@@ -0,0 +1,16 @@
+load('tests/cli.js');
+
+JSAN.use('MochiKit.Test');
+
+print("[[ MochiKit.Base ]]");
+runTests('tests.test_Base');
+print("[[ MochiKit.Color ]]");
+runTests('tests.test_Color');
+print("[[ MochiKit.DateTime ]]");
+runTests('tests.test_DateTime');
+print("[[ MochiKit.Format ]]");
+runTests('tests.test_Format');
+print("[[ MochiKit.Iter ]]");
+runTests('tests.test_Iter');
+print("[[ MochiKit.Logging ]]");
+runTests('tests.test_Logging');
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/test_Base.js b/dom/tests/mochitest/ajax/mochikit/tests/test_Base.js
new file mode 100644
index 0000000000..2cbf2848d1
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/test_Base.js
@@ -0,0 +1,509 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Base'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Base'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Base = function (t) {
+ // test bind
+ var not_self = {"toString": function () { return "not self"; } };
+ var self = {"toString": function () { return "self"; } };
+ var func = function (arg) { return this.toString() + " " + arg; };
+ var boundFunc = bind(func, self);
+ not_self.boundFunc = boundFunc;
+
+ t.is( isEmpty([], [], ""), true, "isEmpty true" )
+ t.is( isEmpty([], [1], ""), true, "isEmpty true" )
+ t.is( isNotEmpty([], [], ""), false, "isNotEmpty false" )
+ t.is( isNotEmpty([], [1], ""), false, "isNotEmpty false" )
+
+ t.is( isEmpty([1], [1], "1"), false, "isEmpty false" )
+ t.is( isEmpty([1], [1], "1"), false, "isEmpty false" )
+ t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" )
+ t.is( isNotEmpty([1], [1], "1"), true, "isNotEmpty true" )
+
+ t.is( boundFunc("foo"), "self foo", "boundFunc bound to self properly" );
+ t.is( not_self.boundFunc("foo"), "self foo", "boundFunc bound to self on another obj" );
+ t.is( bind(boundFunc, not_self)("foo"), "not self foo", "boundFunc successfully rebound!" );
+ t.is( bind(boundFunc, undefined, "foo")(), "self foo", "boundFunc partial no self change" );
+ t.is( bind(boundFunc, not_self, "foo")(), "not self foo", "boundFunc partial self change" );
+
+ // test method
+ not_self = {"toString": function () { return "not self"; } };
+ self = {"toString": function () { return "self"; } };
+ func = function (arg) { return this.toString() + " " + arg; };
+ var boundMethod = method(self, func);
+ not_self.boundMethod = boundMethod;
+
+ t.is( boundMethod("foo"), "self foo", "boundMethod bound to self properly" );
+ t.is( not_self.boundMethod("foo"), "self foo", "boundMethod bound to self on another obj" );
+ t.is( method(not_self, boundMethod)("foo"), "not self foo", "boundMethod successfully rebound!" );
+ t.is( method(undefined, boundMethod, "foo")(), "self foo", "boundMethod partial no self change" );
+ t.is( method(not_self, boundMethod, "foo")(), "not self foo", "boundMethod partial self change" );
+
+
+
+
+ // test bindMethods
+
+ var O = function (value) {
+ bindMethods(this);
+ this.value = value;
+ };
+ O.prototype.func = function () {
+ return this.value;
+ };
+
+ var o = new O("boring");
+ var p = {};
+ p.func = o.func;
+ var func = o.func;
+ t.is( o.func(), "boring", "bindMethods doesn't break shit" );
+ t.is( p.func(), "boring", "bindMethods works on other objects" );
+ t.is( func(), "boring", "bindMethods works on functions" );
+
+ var p = clone(o);
+ t.ok( p instanceof O, "cloned correct inheritance" );
+ var q = clone(p);
+ t.ok( q instanceof O, "clone-cloned correct inheritance" );
+ q.foo = "bar";
+ t.is( p.foo, undefined, "clone-clone is copy-on-write" );
+ p.bar = "foo";
+ t.is( o.bar, undefined, "clone is copy-on-write" );
+ t.is( q.bar, "foo", "clone-clone has proper delegation" );
+ // unbind
+ p.func = bind(p.func, null);
+ t.is( p.func(), "boring", "clone function calls correct" );
+ q.value = "awesome";
+ t.is( q.func(), "awesome", "clone really does work" );
+
+ // test boring boolean funcs
+
+ t.is( isCallable(isCallable), true, "isCallable returns true on itself" );
+ t.is( isCallable(1), false, "isCallable returns false on numbers" );
+
+ t.is( isUndefined(null), false, "null is not undefined" );
+ t.is( isUndefined(""), false, "empty string is not undefined" );
+ t.is( isUndefined(undefined), true, "undefined is undefined" );
+ t.is( isUndefined({}.foo), true, "missing property is undefined" );
+
+ t.is( isUndefinedOrNull(null), true, "null is undefined or null" );
+ t.is( isUndefinedOrNull(""), false, "empty string is not undefined or null" );
+ t.is( isUndefinedOrNull(undefined), true, "undefined is undefined or null" );
+ t.is( isUndefinedOrNull({}.foo), true, "missing property is undefined or null" );
+
+ // test extension of arrays
+ var a = [];
+ var b = [];
+ var three = [1, 2, 3];
+
+ extend(a, three, 1);
+ t.ok( objEqual(a, [2, 3]), "extend to an empty array" );
+ extend(a, three, 1)
+ t.ok( objEqual(a, [2, 3, 2, 3]), "extend to a non-empty array" );
+
+ extend(b, three);
+ t.ok( objEqual(b, three), "extend of an empty array" );
+
+ t.is( compare(1, 2), -1, "numbers compare lt" );
+ t.is( compare(2, 1), 1, "numbers compare gt" );
+ t.is( compare(1, 1), 0, "numbers compare eq" );
+ t.is( compare([1], [1]), 0, "arrays compare eq" );
+ t.is( compare([1], [1, 2]), -1, "arrays compare lt (length)" );
+ t.is( compare([1, 2], [2, 1]), -1, "arrays compare lt (contents)" );
+ t.is( compare([1, 2], [1]), 1, "arrays compare gt (length)" );
+ t.is( compare([2, 1], [1, 1]), 1, "arrays compare gt (contents)" );
+
+ // test partial application
+ var a = [];
+ var func = function (a, b) {
+ if (arguments.length != 2) {
+ return "bad args";
+ } else {
+ return this.value + a + b;
+ }
+ };
+ var self = {"value": 1, "func": func};
+ var self2 = {"value": 2};
+ t.is( self.func(2, 3), 6, "setup for test is correct" );
+ self.funcTwo = partial(self.func, 2);
+ t.is( self.funcTwo(3), 6, "partial application works" );
+ t.is( self.funcTwo(3), 6, "partial application works still" );
+ t.is( bind(self.funcTwo, self2)(3), 7, "rebinding partial works" );
+ self.funcTwo = bind(bind(self.funcTwo, self2), null);
+ t.is( self.funcTwo(3), 6, "re-unbinding partial application works" );
+
+
+ // nodeWalk test
+ // ... looks a lot like a DOM tree on purpose
+ var tree = {
+ "id": "nodeWalkTestTree",
+ "test:int": "1",
+ "childNodes": [
+ {
+ "test:int": "2",
+ "childNodes": [
+ {"test:int": "5"},
+ "ignored string",
+ {"ignored": "object"},
+ ["ignored", "list"],
+ {
+ "test:skipchildren": "1",
+ "childNodes": [{"test:int": 6}]
+ }
+ ]
+ },
+ {"test:int": "3"},
+ {"test:int": "4"}
+ ]
+ }
+
+ var visitedNodes = [];
+ nodeWalk(tree, function (node) {
+ var attr = node["test:int"];
+ if (attr) {
+ visitedNodes.push(attr);
+ }
+ if (node["test:skipchildren"]) {
+ return;
+ }
+ return node.childNodes;
+ });
+
+ t.ok( objEqual(visitedNodes, ["1", "2", "3", "4", "5"]), "nodeWalk looks like it works");
+
+ // test map
+ var minusOne = function (x) { return x - 1; };
+ var res = map(minusOne, [1, 2, 3]);
+ t.ok( objEqual(res, [0, 1, 2]), "map works" );
+
+ var res2 = xmap(minusOne, 1, 2, 3);
+ t.ok( objEqual(res2, res), "xmap works" );
+
+ res = map(operator.add, [1, 2, 3], [2, 4, 6]);
+ t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works" );
+
+ res = map(operator.add, [1, 2, 3], [2, 4, 6, 8]);
+ t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (q long)" );
+
+ res = map(operator.add, [1, 2, 3, 4], [2, 4, 6]);
+ t.ok( objEqual(res, [3, 6, 9]), "map(fn, p, q) works (p long)" );
+
+ res = map(null, [1, 2, 3], [2, 4, 6]);
+ t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "map(null, p, q) works" );
+
+ res = zip([1, 2, 3], [2, 4, 6]);
+ t.ok( objEqual(res, [[1, 2], [2, 4], [3, 6]]), "zip(p, q) works" );
+
+ res = map(null, [1, 2, 3]);
+ t.ok( objEqual(res, [1, 2, 3]), "map(null, lst) works" );
+
+
+
+
+ t.is( isNotEmpty("foo"), true, "3 char string is not empty" );
+ t.is( isNotEmpty(""), false, "0 char string is empty" );
+ t.is( isNotEmpty([1, 2, 3]), true, "3 element list is not empty" );
+ t.is( isNotEmpty([]), false, "0 element list is empty" );
+
+ // test filter
+ var greaterThanThis = function (x) { return x > this; };
+ var greaterThanOne = function (x) { return x > 1; };
+ var res = filter(greaterThanOne, [-1, 0, 1, 2, 3]);
+ t.ok( objEqual(res, [2, 3]), "filter works" );
+ var res = filter(greaterThanThis, [-1, 0, 1, 2, 3], 1);
+ t.ok( objEqual(res, [2, 3]), "filter self works" );
+ var res2 = xfilter(greaterThanOne, -1, 0, 1, 2, 3);
+ t.ok( objEqual(res2, res), "xfilter works" );
+
+ t.is(objMax(1, 2, 9, 12, 42, -16, 16), 42, "objMax works (with numbers)");
+ t.is(objMin(1, 2, 9, 12, 42, -16, 16), -16, "objMin works (with numbers)");
+
+ // test adapter registry
+
+ var R = new AdapterRegistry();
+ R.register("callable", isCallable, function () { return "callable"; });
+ R.register("arrayLike", isArrayLike, function () { return "arrayLike"; });
+ t.is( R.match(function () {}), "callable", "registry found callable" );
+ t.is( R.match([]), "arrayLike", "registry found ArrayLike" );
+ try {
+ R.match(null);
+ t.ok( false, "non-matching didn't raise!" );
+ } catch (e) {
+ t.is( e, NotFound, "non-matching raised correctly" );
+ }
+ R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" });
+ R.register("undefined", isUndefined, function () { return "undefined" });
+ t.is( R.match(undefined), "undefinedOrNull", "priorities are as documented" );
+ t.ok( R.unregister("undefinedOrNull"), "removed adapter" );
+ t.is( R.match(undefined), "undefined", "adapter was removed" );
+ R.register("undefinedOrNull", isUndefinedOrNull, function () { return "undefinedOrNull" }, true);
+ t.is( R.match(undefined), "undefinedOrNull", "override works" );
+
+ var a1 = {"a": 1, "b": 2, "c": 2};
+ var a2 = {"a": 2, "b": 1, "c": 2};
+ t.is( keyComparator("a")(a1, a2), -1, "keyComparator 1 lt" );
+ t.is( keyComparator("c")(a1, a2), 0, "keyComparator 1 eq" );
+ t.is( keyComparator("c", "b")(a1, a2), 1, "keyComparator 2 eq gt" );
+ t.is( keyComparator("c", "a")(a1, a2), -1, "keyComparator 2 eq lt" );
+ t.is( reverseKeyComparator("a")(a1, a2), 1, "reverseKeyComparator" );
+ t.is( compare(concat([1], [2], [3]), [1, 2, 3]), 0, "concat" );
+ t.is( repr("foo"), '"foo"', "string repr" );
+ t.is( repr(1), '1', "number repr" );
+ t.is( listMin([1, 3, 5, 3, -1]), -1, "listMin" );
+ t.is( objMin(1, 3, 5, 3, -1), -1, "objMin" );
+ t.is( listMax([1, 3, 5, 3, -1]), 5, "listMax" );
+ t.is( objMax(1, 3, 5, 3, -1), 5, "objMax" );
+
+ var v = keys(a1);
+ v.sort();
+ t.is( compare(v, ["a", "b", "c"]), 0, "keys" );
+ v = items(a1);
+ v.sort();
+ t.is( compare(v, [["a", 1], ["b", 2], ["c", 2]]), 0, "items" );
+
+ var StringMap = function() {};
+ a = new StringMap();
+ a.foo = "bar";
+ b = new StringMap();
+ b.foo = "bar";
+ try {
+ compare(a, b);
+ t.ok( false, "bad comparison registered!?" );
+ } catch (e) {
+ t.ok( e instanceof TypeError, "bad comparison raised TypeError" );
+ }
+
+ t.is( repr(a), "[object Object]", "default repr for StringMap" );
+ var isStringMap = function () {
+ for (var i = 0; i < arguments.length; i++) {
+ if (!(arguments[i] instanceof StringMap)) {
+ return false;
+ }
+ }
+ return true;
+ };
+
+ registerRepr("stringMap",
+ isStringMap,
+ function (obj) {
+ return "StringMap(" + repr(items(obj)) + ")";
+ }
+ );
+
+ t.is( repr(a), 'StringMap([["foo", "bar"]])', "repr worked" );
+
+ // not public API
+ MochiKit.Base.reprRegistry.unregister("stringMap");
+
+ t.is( repr(a), "[object Object]", "default repr for StringMap" );
+
+ registerComparator("stringMap",
+ isStringMap,
+ function (a, b) {
+ // no sorted(...) in base
+ a = items(a);
+ b = items(b);
+ a.sort(compare);
+ b.sort(compare);
+ return compare(a, b);
+ }
+ );
+
+ t.is( compare(a, b), 0, "registerComparator" );
+
+ update(a, {"foo": "bar"}, {"wibble": "baz"}, undefined, null, {"grr": 1});
+ t.is( a.foo, "bar", "update worked (first obj)" );
+ t.is( a.wibble, "baz", "update worked (second obj)" );
+ t.is( a.grr, 1, "update worked (skipped undefined and null)" );
+ t.is( compare(a, b), 1, "update worked (comparison)" );
+
+
+ setdefault(a, {"foo": "unf"}, {"bar": "web taco"} );
+ t.is( a.foo, "bar", "setdefault worked (skipped existing)" );
+ t.is( a.bar, "web taco", "setdefault worked (set non-existing)" );
+
+ var c = items(merge({"foo": "bar"}, {"wibble": "baz"}));
+ c.sort(compare);
+ t.is( compare(c, [["foo", "bar"], ["wibble", "baz"]]), 0, "merge worked" );
+
+ // not public API
+ MochiKit.Base.comparatorRegistry.unregister("stringMap");
+
+ try {
+ compare(a, b);
+ t.ok( false, "bad comparison registered!?" );
+ } catch (e) {
+ t.ok( e instanceof TypeError, "bad comparison raised TypeError" );
+ }
+
+ var o = {"__repr__": function () { return "__repr__"; }};
+ t.is( repr(o), "__repr__", "__repr__ protocol" );
+ t.is( repr(MochiKit.Base), MochiKit.Base.__repr__(), "__repr__ protocol when repr is defined" );
+ var o = {"NAME": "NAME"};
+ t.is( repr(o), "NAME", "NAME protocol (obj)" );
+ o = function () { return "TACO" };
+ o.NAME = "NAME";
+ t.is( repr(o), "NAME", "NAME protocol (func)" );
+
+ t.is( repr(MochiKit.Base.nameFunctions), "MochiKit.Base.nameFunctions", "test nameFunctions" );
+ // Done!
+
+ t.is( urlEncode("1+2=2").toUpperCase(), "1%2B2%3D2", "urlEncode" );
+ t.is( queryString(["a", "b"], [1, "two"]), "a=1&b=two", "queryString");
+ t.is( queryString({"a": 1}), "a=1", "one item alternate form queryString" );
+ var o = {"a": 1, "b": 2, "c": function() {}};
+ var res = queryString(o).split("&");
+ res.sort();
+ t.is( res.join("&"), "a=1&b=2", "two item alternate form queryString, function skip" );
+ var res = parseQueryString("1+1=2&b=3%3D2");
+ t.is( res["1 1"], "2", "parseQueryString pathological name" );
+ t.is( res.b, "3=2", "parseQueryString second name:value pair" );
+ var res = parseQueryString("foo=one&foo=two", true);
+ t.is( res["foo"].join(" "), "one two", "parseQueryString useArrays" );
+ var res = parseQueryString("?foo=2&bar=1");
+ t.is( res["foo"], "2", "parseQueryString strip leading question mark");
+
+ t.is( serializeJSON("foo\n\r\b\f\t"), "\"foo\\n\\r\\b\\f\\t\"", "string JSON" );
+ t.is( serializeJSON(null), "null", "null JSON");
+ try {
+ serializeJSON(undefined);
+ t.ok(false, "undefined should not be serializable");
+ } catch (e) {
+ t.ok(e instanceof TypeError, "undefined not serializable");
+ }
+ t.is( serializeJSON(1), "1", "1 JSON");
+ t.is( serializeJSON(1.23), "1.23", "1.23 JSON");
+ t.is( serializeJSON(serializeJSON), null, "function JSON (null, not string)" );
+ t.is( serializeJSON([1, "2", 3.3]), "[1, \"2\", 3.3]", "array JSON" );
+ var res = evalJSON(serializeJSON({"a":1, "b":2}));
+ t.is( res.a, 1, "evalJSON on an object (1)" );
+ t.is( res.b, 2, "evalJSON on an object (2)" );
+ var res = {"a": 1, "b": 2, "json": function () { return this; }};
+ var res = evalJSON(serializeJSON(res));
+ t.is( res.a, 1, "evalJSON on an object that jsons self (1)" );
+ t.is( res.b, 2, "evalJSON on an object that jsons self (2)" );
+ var strJSON = {"a": 1, "b": 2, "json": function () { return "json"; }};
+ t.is( serializeJSON(strJSON), "\"json\"", "json serialization calling" );
+ t.is( serializeJSON([strJSON]), "[\"json\"]", "json serialization calling in a structure" );
+ t.is( evalJSON('/* {"result": 1} */').result, 1, "json comment stripping" );
+ t.is( evalJSON('/* {"*/ /*": 1} */')['*/ /*'], 1, "json comment stripping" );
+ registerJSON("isDateLike",
+ isDateLike,
+ function (d) {
+ return "this was a date";
+ }
+ );
+ t.is( serializeJSON(new Date()), "\"this was a date\"", "json registry" );
+ MochiKit.Base.jsonRegistry.unregister("isDateLike");
+
+ var a = {"foo": {"bar": 12, "wibble": 13}};
+ var b = {"foo": {"baz": 4, "bar": 16}, "bar": 4};
+ updatetree(a, b);
+ var expect = [["bar", 16], ["baz", 4], ["wibble", 13]];
+ var got = items(a.foo);
+ got.sort(compare);
+ t.is( repr(got), repr(expect), "updatetree merge" );
+ t.is( a.bar, 4, "updatetree insert" );
+
+ var c = counter();
+ t.is( c(), 1, "counter starts at 1" );
+ t.is( c(), 2, "counter increases" );
+ c = counter(2);
+ t.is( c(), 2, "counter starts at 2" );
+ t.is( c(), 3, "counter increases" );
+
+ t.is( findValue([1, 2, 3], 4), -1, "findValue returns -1 on not found");
+ t.is( findValue([1, 2, 3], 1), 0, "findValue returns correct index");
+ t.is( findValue([1, 2, 3], 1, 1), -1, "findValue honors start");
+ t.is( findValue([1, 2, 3], 2, 0, 1), -1, "findValue honors end");
+ t.is( findIdentical([1, 2, 3], 4), -1, "findIdentical returns -1");
+ t.is( findIdentical([1, 2, 3], 1), 0, "findIdentical returns correct index");
+ t.is( findIdentical([1, 2, 3], 1, 1), -1, "findIdentical honors start");
+ t.is( findIdentical([1, 2, 3], 2, 0, 1), -1, "findIdentical honors end");
+ t.is( isNull(undefined), false, "isNull doesn't match undefined" );
+
+ var flat = flattenArguments(1, "2", 3, [4, [5, [6, 7], 8, [], 9]]);
+ var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9];
+ t.is( repr(flat), repr(expect), "flattenArguments" );
+
+ var fn = function () {
+ return [this, concat(arguments)];
+ }
+ t.is( methodcaller("toLowerCase")("FOO"), "foo", "methodcaller with a method name" );
+ t.is( repr(methodcaller(fn, 2, 3)(1)), "[1, [2, 3]]", "methodcaller with a function" );
+
+ var f1 = function (x) { return [1, x]; };
+ var f2 = function (x) { return [2, x]; };
+ var f3 = function (x) { return [3, x]; };
+ t.is( repr(f1(f2(f3(4)))), "[1, [2, [3, 4]]]", "test the compose test" );
+ t.is( repr(compose(f1,f2,f3)(4)), "[1, [2, [3, 4]]]", "three fn composition works" );
+ t.is( repr(compose(compose(f1,f2),f3)(4)), "[1, [2, [3, 4]]]", "associative left" );
+ t.is( repr(compose(f1,compose(f2,f3))(4)), "[1, [2, [3, 4]]]", "associative right" );
+
+ try {
+ compose(f1, "foo");
+ t.ok( false, "wrong compose argument not raised!" );
+ } catch (e) {
+ t.is( e.name, 'TypeError', "wrong compose argument raised correctly" );
+ }
+
+ t.is(camelize('one'), 'one', 'one word');
+ t.is(camelize('one-two'), 'oneTwo', 'two words');
+ t.is(camelize('one-two-three'), 'oneTwoThree', 'three words');
+ t.is(camelize('1-one'), '1One', 'letter and word');
+ t.is(camelize('one-'), 'one', 'trailing hyphen');
+ t.is(camelize('-one'), 'One', 'starting hyphen');
+ t.is(camelize('o-two'), 'oTwo', 'one character and word');
+
+ var flat = flattenArray([1, "2", 3, [4, [5, [6, 7], 8, [], 9]]]);
+ var expect = [1, "2", 3, 4, 5, 6, 7, 8, 9];
+ t.is( repr(flat), repr(expect), "flattenArray" );
+
+ /* mean */
+ try {
+ mean();
+ t.ok( false, "no arguments didn't raise!" );
+ } catch (e) {
+ t.is( e.name, 'TypeError', "no arguments raised correctly" );
+ }
+ t.is( mean(1), 1, 'single argument (arg list)');
+ t.is( mean([1]), 1, 'single argument (array)');
+ t.is( mean(1,2,3), 2, 'three arguments (arg list)');
+ t.is( mean([1,2,3]), 2, 'three arguments (array)');
+ t.is( average(1), 1, 'test the average alias');
+
+ /* median */
+ try {
+ median();
+ t.ok( false, "no arguments didn't raise!" );
+ } catch (e) {
+ t.is( e.name, 'TypeError', "no arguments raised correctly" );
+ }
+ t.is( median(1), 1, 'single argument (arg list)');
+ t.is( median([1]), 1, 'single argument (array)');
+ t.is( median(3,1,2), 2, 'three arguments (arg list)');
+ t.is( median([3,1,2]), 2, 'three arguments (array)');
+ t.is( median(3,1,2,4), 2.5, 'four arguments (arg list)');
+ t.is( median([3,1,2,4]), 2.5, 'four arguments (array)');
+
+ /* #185 */
+ t.is( serializeJSON(parseQueryString("")), "{}", "parseQueryString('')" );
+ t.is( serializeJSON(parseQueryString("", true)), "{}", "parseQueryString('', true)" );
+
+ /* #109 */
+ t.is( queryString({ids: [1,2,3]}), "ids=1&ids=2&ids=3", "queryString array value" );
+ t.is( queryString({ids: "123"}), "ids=123", "queryString string value" );
+
+ /* test values */
+ var o = {a: 1, b: 2, c: 4, d: -1};
+ var got = values(o);
+ got.sort();
+ t.is( repr(got), repr([-1, 1, 2, 4]), "values()" );
+
+ t.is( queryString([["foo", "bar"], ["baz", "wibble"]]), "foo=baz&bar=wibble" );
+ o = parseQueryString("foo=1=1=1&bar=2&baz&wibble=");
+ t.is( o.foo, "1=1=1", "parseQueryString multiple = first" );
+ t.is( o.bar, "2", "parseQueryString multiple = second" );
+ t.is( o.baz, "", "parseQueryString multiple = third" );
+ t.is( o.wibble, "", "parseQueryString multiple = fourth" );
+
+};
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/test_Color.js b/dom/tests/mochitest/ajax/mochikit/tests/test_Color.js
new file mode 100644
index 0000000000..c736c8db34
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/test_Color.js
@@ -0,0 +1,137 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Color'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Color'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Color = function (t) {
+ var approx = function (a, b, msg) {
+ return t.is(a.toPrecision(4), b.toPrecision(4), msg);
+ };
+
+ t.is( Color.whiteColor().toHexString(), "#ffffff", "whiteColor has right hex" );
+ t.is( Color.blackColor().toHexString(), "#000000", "blackColor has right hex" );
+ t.is( Color.blueColor().toHexString(), "#0000ff", "blueColor has right hex" );
+ t.is( Color.redColor().toHexString(), "#ff0000", "redColor has right hex" );
+ t.is( Color.greenColor().toHexString(), "#00ff00", "greenColor has right hex" );
+ t.is( compare(Color.whiteColor(), Color.whiteColor()), 0, "default colors compare right" );
+ t.ok( Color.whiteColor() == Color.whiteColor(), "default colors are interned" );
+ t.is( Color.whiteColor().toRGBString(), "rgb(255,255,255)", "toRGBString white" );
+ t.is( Color.blueColor().toRGBString(), "rgb(0,0,255)", "toRGBString blue" );
+ t.is( Color.fromRGB(190/255, 222/255, 173/255).toHexString(), "#bedead", "fromRGB works" );
+ t.is( Color.fromRGB(226/255, 15.9/255, 182/255).toHexString(), "#e210b6", "fromRGB < 16 works" );
+ t.is( Color.fromRGB({r:190/255,g:222/255,b:173/255}).toHexString(), "#bedead", "alt fromRGB works" );
+ t.is( Color.fromHexString("#bedead").toHexString(), "#bedead", "round-trip hex" );
+ t.is( Color.fromString("#bedead").toHexString(), "#bedead", "round-trip string(hex)" );
+ t.is( Color.fromRGBString("rgb(190,222,173)").toHexString(), "#bedead", "round-trip rgb" );
+ t.is( Color.fromString("rgb(190,222,173)").toHexString(), "#bedead", "round-trip rgb" );
+
+ var hsl = Color.redColor().asHSL();
+ approx( hsl.h, 0.0, "red hsl.h" );
+ approx( hsl.s, 1.0, "red hsl.s" );
+ approx( hsl.l, 0.5, "red hsl.l" );
+ hsl = Color.fromRGB(0, 0, 0.5).asHSL();
+ approx( hsl.h, 2/3, "darkblue hsl.h" );
+ approx( hsl.s, 1.0, "darkblue hsl.s" );
+ approx( hsl.l, 0.25, "darkblue hsl.l" );
+ hsl = Color.fromString("#4169E1").asHSL();
+ approx( hsl.h, (5/8), "4169e1 h");
+ approx( hsl.s, (8/11), "4169e1 s");
+ approx( hsl.l, (29/51), "4169e1 l");
+ hsl = Color.fromString("#555544").asHSL();
+ approx( hsl.h, (1/6), "555544 h" );
+ approx( hsl.s, (1/9), "555544 s" );
+ approx( hsl.l, (3/10), "555544 l" );
+ hsl = Color.fromRGB(0.5, 1, 0.5).asHSL();
+ approx( hsl.h, 1/3, "aqua hsl.h" );
+ approx( hsl.s, 1.0, "aqua hsl.s" );
+ approx( hsl.l, 0.75, "aqua hsl.l" );
+ t.is(
+ Color.fromHSL(hsl.h, hsl.s, hsl.l).toHexString(),
+ Color.fromRGB(0.5, 1, 0.5).toHexString(),
+ "fromHSL works with components"
+ );
+ t.is(
+ Color.fromHSL(hsl).toHexString(),
+ Color.fromRGB(0.5, 1, 0.5).toHexString(),
+ "fromHSL alt form"
+ );
+ t.is(
+ Color.fromString("hsl(120,100%,75%)").toHexString(),
+ "#80ff80",
+ "fromHSLString"
+ );
+ t.is(
+ Color.fromRGB(0.5, 1, 0.5).toHSLString(),
+ "hsl(120,100.0%,75.00%)",
+ "toHSLString"
+ );
+ t.is( Color.fromHSL(0, 0, 0).toHexString(), "#000000", "fromHSL to black" );
+ hsl = Color.blackColor().asHSL();
+ approx( hsl.h, 0.0, "black hsl.h" );
+ approx( hsl.s, 0.0, "black hsl.s" );
+ approx( hsl.l, 0.0, "black hsl.l" );
+ hsl.h = 1.0;
+ hsl = Color.blackColor().asHSL();
+ approx( hsl.h, 0.0, "asHSL returns copy" );
+ var rgb = Color.brownColor().asRGB();
+ approx( rgb.r, 153/255, "brown rgb.r" );
+ approx( rgb.g, 102/255, "brown rgb.g" );
+ approx( rgb.b, 51/255, "brown rgb.b" );
+ rgb.r = 0;
+ rgb = Color.brownColor().asRGB();
+ approx( rgb.r, 153/255, "asRGB returns copy" );
+
+ t.is( Color.fromName("aqua").toHexString(), "#00ffff", "aqua fromName" );
+ t.is( Color.fromString("aqua").toHexString(), "#00ffff", "aqua fromString" );
+ t.is( Color.fromName("transparent"), Color.transparentColor(), "transparent fromName" );
+ t.is( Color.fromString("transparent"), Color.transparentColor(), "transparent fromString" );
+ t.is( Color.transparentColor().toRGBString(), "rgba(0,0,0,0)", "transparent toRGBString" );
+ t.is( Color.fromRGBString("rgba( 0, 255, 255, 50%)").asRGB().a, 0.5, "rgba parsing alpha correctly" );
+ t.is( Color.fromRGBString("rgba( 0, 255, 255, 50%)").toRGBString(), "rgba(0,255,255,0.5)", "rgba output correctly" );
+ t.is( Color.fromRGBString("rgba( 0, 255, 255, 1)").toHexString(), "#00ffff", "fromRGBString with spaces and alpha" );
+ t.is( Color.fromRGBString("rgb( 0, 255, 255)").toHexString(), "#00ffff", "fromRGBString with spaces" );
+ t.is( Color.fromRGBString("rgb( 0, 100%, 255)").toHexString(), "#00ffff", "fromRGBString with percents" );
+
+ var hsv = Color.redColor().asHSV();
+ approx( hsv.h, 0.0, "red hsv.h" );
+ approx( hsv.s, 1.0, "red hsv.s" );
+ approx( hsv.v, 1.0, "red hsv.v" );
+ t.is( Color.fromHSV(hsv).toHexString(), Color.redColor().toHexString(), "red hexstring" );
+ hsv = Color.fromRGB(0, 0, 0.5).asHSV();
+ approx( hsv.h, 2/3, "darkblue hsv.h" );
+ approx( hsv.s, 1.0, "darkblue hsv.s" );
+ approx( hsv.v, 0.5, "darkblue hsv.v" );
+ t.is( Color.fromHSV(hsv).toHexString(), Color.fromRGB(0, 0, 0.5).toHexString(), "darkblue hexstring" );
+ hsv = Color.fromString("#4169E1").asHSV();
+ approx( hsv.h, 5/8, "4169e1 h");
+ approx( hsv.s, 32/45, "4169e1 s");
+ approx( hsv.v, 15/17, "4169e1 l");
+ t.is( Color.fromHSV(hsv).toHexString(), "#4169e1", "4169e1 hexstring" );
+ hsv = Color.fromString("#555544").asHSV();
+ approx( hsv.h, 1/6, "555544 h" );
+ approx( hsv.s, 1/5, "555544 s" );
+ approx( hsv.v, 1/3, "555544 l" );
+ t.is( Color.fromHSV(hsv).toHexString(), "#555544", "555544 hexstring" );
+ hsv = Color.fromRGB(0.5, 1, 0.5).asHSV();
+ approx( hsv.h, 1/3, "aqua hsv.h" );
+ approx( hsv.s, 0.5, "aqua hsv.s" );
+ approx( hsv.v, 1, "aqua hsv.v" );
+ t.is(
+ Color.fromHSV(hsv.h, hsv.s, hsv.v).toHexString(),
+ Color.fromRGB(0.5, 1, 0.5).toHexString(),
+ "fromHSV works with components"
+ );
+ t.is(
+ Color.fromHSV(hsv).toHexString(),
+ Color.fromRGB(0.5, 1, 0.5).toHexString(),
+ "fromHSV alt form"
+ );
+ hsv = Color.fromRGB(1, 1, 1).asHSV()
+ approx( hsv.h, 0, 'white hsv.h' );
+ approx( hsv.s, 0, 'white hsv.s' );
+ approx( hsv.v, 1, 'white hsv.v' );
+ t.is(
+ Color.fromHSV(0, 0, 1).toHexString(),
+ '#ffffff',
+ 'HSV saturation'
+ );
+};
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/test_DateTime.js b/dom/tests/mochitest/ajax/mochikit/tests/test_DateTime.js
new file mode 100644
index 0000000000..cc2d958e3c
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/test_DateTime.js
@@ -0,0 +1,45 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.DateTime'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.DateTime'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_DateTime = function (t) {
+ var testDate = isoDate('2005-2-3');
+ t.is(testDate.getFullYear(), 2005, "isoDate year ok");
+ t.is(testDate.getDate(), 3, "isoDate day ok");
+ t.is(testDate.getMonth(), 1, "isoDate month ok");
+ t.ok(objEqual(testDate, new Date("February 3, 2005")), "matches string date");
+ t.is(toISODate(testDate), '2005-02-03', 'toISODate ok');
+
+ var testDate = isoDate('2005-06-08');
+ t.is(testDate.getFullYear(), 2005, "isoDate year ok");
+ t.is(testDate.getDate(), 8, "isoDate day ok");
+ t.is(testDate.getMonth(), 5, "isoDate month ok");
+ t.ok(objEqual(testDate, new Date("June 8, 2005")), "matches string date");
+ t.is(toISODate(testDate), '2005-06-08', 'toISODate ok');
+
+ t.is(compare(new Date("February 3, 2005"), new Date(2005, 1, 3)), 0, "dates compare eq");
+ t.is(compare(new Date("February 3, 2005"), new Date(2005, 2, 3)), -1, "dates compare lt");
+ t.is(compare(new Date("February 3, 2005"), new Date(2005, 0, 3)), 1, "dates compare gt");
+
+ var testDate = isoDate('2005-2-3');
+ t.is(compare(americanDate('2/3/2005'), testDate), 0, "americanDate eq");
+ t.is(compare('2/3/2005', toAmericanDate(testDate)), 0, "toAmericanDate eq");
+
+ var testTimestamp = isoTimestamp('2005-2-3 22:01:03');
+ t.is(compare(testTimestamp, new Date(2005,1,3,22,1,3)), 0, "isoTimestamp eq");
+ t.is(compare(testTimestamp, isoTimestamp('2005-2-3T22:01:03')), 0, "isoTimestamp (real ISO) eq");
+ t.is(compare(toISOTimestamp(testTimestamp), '2005-02-03 22:01:03'), 0, "toISOTimestamp eq");
+ testTimestamp = isoTimestamp('2005-2-3T22:01:03Z');
+ t.is(toISOTimestamp(testTimestamp, true), '2005-02-03T22:01:03Z', "toISOTimestamp (real ISO) eq");
+
+ var localTZ = Math.round((new Date(2005,1,3,22,1,3)).getTimezoneOffset()/60)
+ var direction = (localTZ < 0) ? "+" : "-";
+ localTZ = Math.abs(localTZ);
+ localTZ = direction + ((localTZ < 10) ? "0" : "") + localTZ;
+ testTimestamp = isoTimestamp("2005-2-3T22:01:03" + localTZ);
+ var testDateTimestamp = new Date(2005,1,3,22,1,3);
+ t.is(compare(testTimestamp, testDateTimestamp), 0, "equal with local tz");
+ testTimestamp = isoTimestamp("2005-2-3T17:01:03-05");
+ var testDateTimestamp = new Date(Date.UTC(2005,1,3,22,1,3));
+ t.is(compare(testTimestamp, testDateTimestamp), 0, "equal with specific tz");
+};
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/test_DragAndDrop.js b/dom/tests/mochitest/ajax/mochikit/tests/test_DragAndDrop.js
new file mode 100644
index 0000000000..d3a3c58379
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/test_DragAndDrop.js
@@ -0,0 +1,30 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Signal'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Signal'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_DragAndDrop = function (t) {
+
+ var drag1 = new MochiKit.DragAndDrop.Draggable('drag1', {'revert': true, 'ghosting': true});
+
+ var drop1 = new MochiKit.DragAndDrop.Droppable('drop1', {'hoverclass': 'drop-hover'});
+ drop1.activate();
+ t.is(hasElementClass('drop1', 'drop-hover'), true, "hoverclass ok");
+ drop1.deactivate();
+ t.is(hasElementClass('drop1', 'drop-hover'), false, "remove hoverclass ok");
+ drop1.destroy();
+
+ t.is( isEmpty(MochiKit.DragAndDrop.Droppables.drops), true, "Unregister droppable ok");
+
+ var onhover = function (element) {
+ t.is(element, getElement('drag1'), 'onhover ok');
+ };
+ var drop2 = new MochiKit.DragAndDrop.Droppable('drop1', {'onhover': onhover});
+ var pos = getElementPosition('drop1');
+ pos = {"x": pos.x + 5, "y": pos.y + 5};
+ MochiKit.DragAndDrop.Droppables.show({"page": pos}, getElement('drag1'));
+
+ drag1.destroy();
+ t.is( isEmpty(MochiKit.DragAndDrop.Draggables.drops), true, "Unregister draggable ok");
+
+};
+
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/test_Format.js b/dom/tests/mochitest/ajax/mochikit/tests/test_Format.js
new file mode 100644
index 0000000000..785cebf823
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/test_Format.js
@@ -0,0 +1,80 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Format'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Format'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Format = function (t) {
+ t.is( truncToFixed(0.1234, 3), "0.123", "truncToFixed truncate" );
+ t.is( truncToFixed(0.12, 3), "0.120", "truncToFixed trailing zeros" );
+ t.is( truncToFixed(0.15, 1), "0.1", "truncToFixed no round" );
+ t.is( truncToFixed(0.15, 0), "0", "truncToFixed zero (edge case)" );
+
+ t.is( roundToFixed(0.1234, 3), "0.123", "roundToFixed truncate" );
+ t.is( roundToFixed(0.12, 3), "0.120", "roundToFixed trailing zeros" );
+ t.is( roundToFixed(0.15, 1), "0.2", "roundToFixed round" );
+ t.is( roundToFixed(0.15, 0), "0", "roundToFixed zero (edge case)" );
+
+ t.is( twoDigitFloat(-0.1234), "-0.12", "twoDigitFloat -0.1234 correct");
+ t.is( twoDigitFloat(-0.1), "-0.1", "twoDigitFloat -0.1 correct");
+ t.is( twoDigitFloat(-0), "0", "twoDigitFloat -0 correct");
+ t.is( twoDigitFloat(0), "0", "twoDigitFloat 0 correct");
+ t.is( twoDigitFloat(1), "1", "twoDigitFloat 1 correct");
+ t.is( twoDigitFloat(1.0), "1", "twoDigitFloat 1.0 correct");
+ t.is( twoDigitFloat(1.2), "1.2", "twoDigitFloat 1.2 correct");
+ t.is( twoDigitFloat(1.234), "1.23", "twoDigitFloat 1.234 correct");
+ t.is( percentFormat(123), "12300%", "percentFormat 123 correct");
+ t.is( percentFormat(1.23), "123%", "percentFormat 123 correct");
+ t.is( twoDigitAverage(1, 0), "0", "twoDigitAverage dbz correct");
+ t.is( twoDigitAverage(1, 1), "1", "twoDigitAverage 1 correct");
+ t.is( twoDigitAverage(1, 10), "0.1", "twoDigitAverage .1 correct");
+ function reprIs(a, b) {
+ arguments[0] = repr(a);
+ arguments[1] = repr(b);
+ t.is.apply(this, arguments);
+ }
+ reprIs( lstrip("\r\t\n foo \n\t\r"), "foo \n\t\r", "lstrip whitespace chars" );
+ reprIs( rstrip("\r\t\n foo \n\t\r"), "\r\t\n foo", "rstrip whitespace chars" );
+ reprIs( strip("\r\t\n foo \n\t\r"), "foo", "strip whitespace chars" );
+ reprIs( lstrip("\r\n\t \r", "\r"), "\n\t \r", "lstrip custom chars" );
+ reprIs( rstrip("\r\n\t \r", "\r"), "\r\n\t ", "rstrip custom chars" );
+ reprIs( strip("\r\n\t \r", "\r"), "\n\t ", "strip custom chars" );
+
+ var nf = numberFormatter("$###,###.00 footer");
+ t.is( nf(1000.1), "$1,000.10 footer", "trailing zeros" );
+ t.is( nf(1000000.1), "$1,000,000.10 footer", "two seps" );
+ t.is( nf(100), "$100.00 footer", "shorter than sep" );
+ t.is( nf(100.555), "$100.56 footer", "rounding" );
+ t.is( nf(-100.555), "$-100.56 footer", "default neg" );
+ nf = numberFormatter("-$###,###.00");
+ t.is( nf(-100.555), "-$100.56", "custom neg" );
+ nf = numberFormatter("0000.0000");
+ t.is( nf(0), "0000.0000", "leading and trailing" );
+ t.is( nf(1.1), "0001.1000", "leading and trailing" );
+ t.is( nf(12345.12345), "12345.1235", "no need for leading/trailing" );
+ nf = numberFormatter("0000.0000");
+ t.is( nf("taco"), "", "default placeholder" );
+ nf = numberFormatter("###,###.00", "foo", "de_DE");
+ t.is( nf("taco"), "foo", "custom placeholder" );
+ t.is( nf(12345.12345), "12.345,12", "de_DE locale" );
+ nf = numberFormatter("#%");
+ t.is( nf(1), "100%", "trivial percent" );
+ t.is( nf(0.55), "55%", "percent" );
+
+ var customLocale = {
+ separator: " apples and ",
+ decimal: " bagels at ",
+ percent: "am for breakfast"};
+ var customFormatter = numberFormatter("###,###.0%", "No breakfast", customLocale);
+ t.is( customFormatter(23.458), "2 apples and 345 bagels at 8am for breakfast", "custom locale" );
+
+ nf = numberFormatter("###,###");
+ t.is( nf(123), "123", "large number format" );
+ t.is( nf(1234), "1,234", "large number format" );
+ t.is( nf(12345), "12,345", "large number format" );
+ t.is( nf(123456), "123,456", "large number format" );
+ t.is( nf(1234567), "1,234,567", "large number format" );
+ t.is( nf(12345678), "12,345,678", "large number format" );
+ t.is( nf(123456789), "123,456,789", "large number format" );
+ t.is( nf(1234567890), "1,234,567,890", "large number format" );
+ t.is( nf(12345678901), "12,345,678,901", "large number format" );
+ t.is( nf(123456789012), "123,456,789,012", "large number format" );
+};
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/test_Iter.js b/dom/tests/mochitest/ajax/mochikit/tests/test_Iter.js
new file mode 100644
index 0000000000..d0ff146ad1
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/test_Iter.js
@@ -0,0 +1,176 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Iter'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Iter'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Iter = function (t) {
+ t.is( sum([1, 2, 3, 4, 5]), 15, "sum works on Arrays" );
+ t.is( compare(list([1, 2, 3]), [1, 2, 3]), 0, "list([x]) == [x]" );
+ t.is( compare(list(range(6, 0, -1)), [6, 5, 4, 3, 2, 1]), 0, "list(range(6, 0, -1)");
+ t.is( compare(list(range(6)), [0, 1, 2, 3, 4, 5]), 0, "list(range(6))" );
+ var moreThanTwo = partial(operator.lt, 2);
+ t.is( sum(ifilter(moreThanTwo, range(6))), 12, "sum(ifilter(, range()))" );
+ t.is( sum(ifilterfalse(moreThanTwo, range(6))), 3, "sum(ifilterfalse(, range()))" );
+
+ var c = count(10);
+ t.is( compare([c.next(), c.next(), c.next()], [10, 11, 12]), 0, "count()" );
+ c = cycle([1, 2]);
+ t.is( compare([c.next(), c.next(), c.next()], [1, 2, 1]), 0, "cycle()" );
+ c = repeat("foo", 3);
+ t.is( compare(list(c), ["foo", "foo", "foo"]), 0, "repeat()" );
+ c = izip([1, 2], [3, 4, 5], repeat("foo"));
+ t.is( compare(list(c), [[1, 3, "foo"], [2, 4, "foo"]]), 0, "izip()" );
+
+ t.is( compare(list(range(5)), [0, 1, 2, 3, 4]), 0, "range(x)" );
+ c = islice(range(10), 0, 10, 2);
+ t.is( compare(list(c), [0, 2, 4, 6, 8]), 0, "islice(x, y, z)" );
+
+ c = imap(operator.add, [1, 2, 3], [2, 4, 6]);
+ t.is( compare(list(c), [3, 6, 9]), 0, "imap(fn, p, q)" );
+
+ c = filter(partial(operator.lt, 1), iter([1, 2, 3]));
+ t.is( compare(c, [2, 3]), 0, "filter(fn, iterable)" );
+
+ c = map(partial(operator.add, -1), iter([1, 2, 3]));
+ t.is( compare(c, [0, 1, 2]), 0, "map(fn, iterable)" );
+
+ c = map(operator.add, iter([1, 2, 3]), [2, 4, 6]);
+ t.is( compare(c, [3, 6, 9]), 0, "map(fn, iterable, q)" );
+
+ c = map(operator.add, iter([1, 2, 3]), iter([2, 4, 6]));
+ t.is( compare(c, [3, 6, 9]), 0, "map(fn, iterable, iterable)" );
+
+ c = applymap(operator.add, [[1, 2], [2, 4], [3, 6]]);
+ t.is( compare(list(c), [3, 6, 9]), 0, "applymap()" );
+
+ c = applymap(function (a) { return [this, a]; }, [[1], [2]], 1);
+ t.is( compare(list(c), [[1, 1], [1, 2]]), 0, "applymap(self)" );
+
+ c = chain(range(2), range(3));
+ t.is( compare(list(c), [0, 1, 0, 1, 2]), 0, "chain(p, q)" );
+
+ var lessThanFive = partial(operator.gt, 5);
+ c = takewhile(lessThanFive, count());
+ t.is( compare(list(c), [0, 1, 2, 3, 4]), 0, "takewhile()" );
+
+ c = dropwhile(lessThanFive, range(10));
+ t.is( compare(list(c), [5, 6, 7, 8, 9]), 0, "dropwhile()" );
+
+ c = tee(range(5), 3);
+ t.is( compare(list(c[0]), list(c[1])), 0, "tee(..., 3) p0 == p1" );
+ t.is( compare(list(c[2]), [0, 1, 2, 3, 4]), 0, "tee(..., 3) p2 == fixed" );
+
+ t.is( compare(reduce(operator.add, range(10)), 45), 0, "reduce(op.add)" );
+
+ try {
+ reduce(operator.add, []);
+ t.ok( false, "reduce didn't raise anything with empty list and no start?!" );
+ } catch (e) {
+ if (e instanceof TypeError) {
+ t.ok( true, "reduce raised TypeError correctly" );
+ } else {
+ t.ok( false, "reduce raised the wrong exception?" );
+ }
+ }
+
+ t.is( reduce(operator.add, [], 10), 10, "range initial value OK empty" );
+ t.is( reduce(operator.add, [1], 10), 11, "range initial value OK populated" );
+
+ t.is( compare(iextend([1], range(2)), [1, 0, 1]), 0, "iextend(...)" );
+
+ var x = [];
+ exhaust(imap(bind(x.push, x), range(5)));
+ t.is( compare(x, [0, 1, 2, 3, 4]), 0, "exhaust(...)" );
+
+ t.is( every([1, 2, 3, 4, 5, 4], lessThanFive), false, "every false" );
+ t.is( every([1, 2, 3, 4, 4], lessThanFive), true, "every true" );
+ t.is( some([1, 2, 3, 4, 4], lessThanFive), true, "some true" );
+ t.is( some([5, 6, 7, 8, 9], lessThanFive), false, "some false" );
+ t.is( some([5, 6, 7, 8, 4], lessThanFive), true, "some true" );
+
+ var rval = [];
+ forEach(range(2), rval.push, rval);
+ t.is( compare(rval, [0, 1]), 0, "forEach works bound" );
+
+ function foo(o) {
+ rval.push(o);
+ }
+ forEach(range(2), foo);
+ t.is( compare(rval, [0, 1, 0, 1]), 0, "forEach works unbound" );
+
+ t.is( compare(sorted([3, 2, 1]), [1, 2, 3]), 0, "sorted default" );
+ rval = sorted(["aaa", "bb", "c"], keyComparator("length"));
+ t.is(compare(rval, ["c", "bb", "aaa"]), 0, "sorted custom");
+
+ t.is( compare(reversed(range(4)), [3, 2, 1, 0]), 0, "reversed iterator" );
+ t.is( compare(reversed([5, 6, 7]), [7, 6, 5]), 0, "reversed list" );
+
+ var o = {lst: [1, 2, 3], iterateNext: function () { return this.lst.shift(); }};
+ t.is( compare(list(o), [1, 2, 3]), 0, "iterateNext" );
+
+
+ function except(exc, func) {
+ try {
+ func();
+ t.ok(false, exc.name + " was not raised.");
+ } catch (e) {
+ if (e == exc) {
+ t.ok( true, "raised " + exc.name + " correctly" );
+ } else {
+ t.ok( false, "raised the wrong exception?" );
+ }
+ }
+ }
+
+ odd = partial(operator.and, 1)
+
+ // empty
+ grouped = groupby([]);
+ except(StopIteration, grouped.next);
+
+ // exhaust sub-iterator
+ grouped = groupby([2,4,6,7], odd);
+ kv = grouped.next(); k = kv[0], subiter = kv[1];
+ t.is(k, 0, "odd(2) = odd(4) = odd(6) == 0");
+ t.is(subiter.next(), 2, "sub-iterator.next() == 2");
+ t.is(subiter.next(), 4, "sub-iterator.next() == 4");
+ t.is(subiter.next(), 6, "sub-iterator.next() == 6");
+ except(StopIteration, subiter.next);
+ kv = grouped.next(); key = kv[0], subiter = kv[1];
+ t.is(key, 1, "odd(7) == 1");
+ t.is(subiter.next(), 7, "sub-iterator.next() == 7");
+ except(StopIteration, subiter.next);
+
+ // not consume sub-iterator
+ grouped = groupby([2,4,6,7], odd);
+ kv = grouped.next(); key = kv[0], subiter = kv[1];
+ t.is(key, 0, "0 = odd(2) = odd(4) = odd(6)");
+ kv = grouped.next(); key = kv[0], subiter = kv[1];
+ t.is(key, 1, "1 = odd(7)");
+ except(StopIteration, grouped.next);
+
+ // consume sub-iterator partially
+ grouped = groupby([3,1,1,2], odd);
+ kv = grouped.next(); key = kv[0], subiter = kv[1];
+ t.is(key, 1, "odd(1) == 1");
+ t.is(subiter.next(), 3, "sub-iterator.next() == 3");
+ kv = grouped.next(); key = kv[0], v = kv[1];
+ t.is(key, 0, "skip (1,1), odd(2) == 0");
+ except(StopIteration, grouped.next);
+
+ // null
+ grouped = groupby([null,null]);
+ kv = grouped.next(); k = kv[0], v = kv[1];
+ t.is(k, null, "null ok");
+
+ // groupby - array version
+ isEqual = (t.isDeeply || function (a, b, msg) {
+ return t.ok(compare(a, b) == 0, msg);
+ });
+ isEqual(groupby_as_array([ ] ), [ ], "empty");
+ isEqual(groupby_as_array([1,1,1]), [ [1,[1,1,1]] ], "[1,1,1]: [1,1,1]");
+ isEqual(groupby_as_array([1,2,2]), [ [1,[1] ], [2,[2,2]] ], "[1,2,2]: [1], [2,2]");
+ isEqual(groupby_as_array([1,1,2]), [ [1,[1,1] ], [2,[2 ]] ], "[1,1,2]: [1,1], [2]");
+ isEqual(groupby_as_array([null,null] ), [ [null,[null,null]] ], "[null,null]: [null,null]");
+ grouped = groupby_as_array([1,1,3,2,4,6,8], odd);
+ isEqual(grouped, [[1, [1,1,3]], [0,[2,4,6,8]]], "[1,1,3,2,4,6,7] odd: [1,1,3], [2,4,6,8]");
+};
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/test_Logging.js b/dom/tests/mochitest/ajax/mochikit/tests/test_Logging.js
new file mode 100644
index 0000000000..66f4989b02
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/test_Logging.js
@@ -0,0 +1,75 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Logging'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Logging'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Logging = function (t) {
+
+ // just in case
+ logger.clear();
+
+ t.is( logLevelAtLeast('DEBUG')('INFO'), false, 'logLevelAtLeast false' );
+ t.is( logLevelAtLeast('WARNING')('INFO'), false, 'logLevelAtLeast true' );
+ t.ok( logger instanceof Logger, "global logger installed" );
+
+ var allMessages = [];
+ logger.addListener("allMessages", null,
+ bind(allMessages.push, allMessages));
+
+ var fatalMessages = [];
+ logger.addListener("fatalMessages", "FATAL",
+ bind(fatalMessages.push, fatalMessages));
+
+ var firstTwo = [];
+ logger.addListener("firstTwo", null,
+ bind(firstTwo.push, firstTwo));
+
+
+ log("foo");
+ var msgs = logger.getMessages();
+ t.is( msgs.length, 1, 'global log() put one message in queue' );
+ t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+ var msg = msgs.pop();
+ t.is( compare(msg.info, ["foo"]), 0, "info matches" );
+ t.is( msg.level, "INFO", "level matches" );
+
+ logDebug("debugFoo");
+ t.is( msgs.length, 0, 'getMessages() returns copy' );
+ msgs = logger.getMessages();
+ t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+ t.is( msgs.length, 2, 'logDebug()' );
+ msg = msgs.pop();
+ t.is( compare(msg.info, ["debugFoo"]), 0, "info matches" );
+ t.is( msg.level, "DEBUG", "level matches" );
+
+ logger.removeListener("firstTwo");
+
+ logError("errorFoo");
+ msgs = logger.getMessages();
+ t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+ t.is( msgs.length, 3, 'logError()' );
+ msg = msgs.pop();
+ t.is( compare(msg.info, ["errorFoo"]), 0, "info matches" );
+ t.is( msg.level, "ERROR", "level matches" );
+
+ logWarning("warningFoo");
+ msgs = logger.getMessages();
+ t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+ t.is( msgs.length, 4, 'logWarning()' );
+ msg = msgs.pop();
+ t.is( compare(msg.info, ["warningFoo"]), 0, "info matches" );
+ t.is( msg.level, "WARNING", "level matches" );
+
+ logFatal("fatalFoo");
+ msgs = logger.getMessages();
+ t.is( compare(allMessages, msgs), 0, "allMessages listener" );
+ t.is( msgs.length, 5, 'logFatal()' );
+ msg = msgs.pop();
+ t.is( compare(fatalMessages, [msg]), 0, "fatalMessages listener" );
+ t.is( compare(msg.info, ["fatalFoo"]), 0, "info matches" );
+ t.is( msg.level, "FATAL", "level matches" );
+
+ logger.removeListener("allMessages");
+ logger.removeListener("fatalMessages");
+
+ t.is( compare(firstTwo, logger.getMessages().slice(0, 2)), 0, "firstTwo" );
+};
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/test_MochiKit-Async.json b/dom/tests/mochitest/ajax/mochikit/tests/test_MochiKit-Async.json
new file mode 100644
index 0000000000..037e18c818
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/test_MochiKit-Async.json
@@ -0,0 +1 @@
+{"passed": true}
diff --git a/dom/tests/mochitest/ajax/mochikit/tests/test_Signal.js b/dom/tests/mochitest/ajax/mochikit/tests/test_Signal.js
new file mode 100644
index 0000000000..6a905952f7
--- /dev/null
+++ b/dom/tests/mochitest/ajax/mochikit/tests/test_Signal.js
@@ -0,0 +1,441 @@
+if (typeof(dojo) != 'undefined') { dojo.require('MochiKit.Signal'); }
+if (typeof(JSAN) != 'undefined') { JSAN.use('MochiKit.Signal'); }
+if (typeof(tests) == 'undefined') { tests = {}; }
+
+tests.test_Signal = function (t) {
+
+ var submit = MochiKit.DOM.getElement('submit');
+ var ident = null;
+ var i = 0;
+ var aFunction = function() {
+ t.ok(this === submit, "aFunction should have 'this' as submit");
+ i++;
+ if (typeof(this.someVar) != 'undefined') {
+ i += this.someVar;
+ }
+ };
+
+ var aObject = {};
+ aObject.aMethod = function() {
+ t.ok(this === aObject, "aMethod should have 'this' as aObject");
+ i++;
+ };
+
+ ident = connect('submit', 'onclick', aFunction);
+ MochiKit.DOM.getElement('submit').click();
+ t.is(i, 1, 'HTML onclick event can be connected to a function');
+
+ disconnect(ident);
+ MochiKit.DOM.getElement('submit').click();
+ t.is(i, 1, 'HTML onclick can be disconnected from a function');
+
+ var submit = MochiKit.DOM.getElement('submit');
+
+ ident = connect(submit, 'onclick', aFunction);
+ submit.click();
+ t.is(i, 2, 'Checking that a DOM element can be connected to a function');
+
+ disconnect(ident);
+ submit.click();
+ t.is(i, 2, '...and then disconnected');
+
+ if (MochiKit.DOM.getElement('submit').fireEvent ||
+ (document.createEvent &&
+ typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) {
+
+ /*
+
+ Adapted from:
+ http://www.devdaily.com/java/jwarehouse/jforum/tests/selenium/javascript/htmlutils.js.shtml
+ License: Apache
+ Copyright: Copyright 2004 ThoughtWorks, Inc
+
+ */
+ var triggerMouseEvent = function(element, eventType, canBubble) {
+ element = MochiKit.DOM.getElement(element);
+ canBubble = (typeof(canBubble) == 'undefined') ? true : canBubble;
+ if (element.fireEvent) {
+ var newEvt = document.createEventObject();
+ newEvt.clientX = 1;
+ newEvt.clientY = 1;
+ newEvt.button = 1;
+ element.fireEvent('on' + eventType, newEvt);
+ } else if (document.createEvent && (typeof(document.createEvent('MouseEvents').initMouseEvent) == 'function')) {
+ var evt = document.createEvent('MouseEvents');
+ evt.initMouseEvent(eventType, canBubble, true, // event, bubbles, cancelable
+ document.defaultView, 1, // view, # of clicks
+ 1, 0, 0, 0, // screenX, screenY, clientX, clientY
+ false, false, false, false, // ctrlKey, altKey, shiftKey, metaKey
+ 0, null); // buttonCode, relatedTarget
+ element.dispatchEvent(evt);
+ }
+ };
+
+ var eventTest = function(e) {
+ i++;
+ t.ok((typeof(e.event()) === 'object'), 'checking that event() is an object');
+ t.ok((typeof(e.type()) === 'string'), 'checking that type() is a string');
+ t.ok((e.target() === MochiKit.DOM.getElement('submit')), 'checking that target is "submit"');
+ t.ok((typeof(e.modifier()) === 'object'), 'checking that modifier() is an object');
+ t.ok(e.modifier().alt === false, 'checking that modifier().alt is defined, but false');
+ t.ok(e.modifier().ctrl === false, 'checking that modifier().ctrl is defined, but false');
+ t.ok(e.modifier().meta === false, 'checking that modifier().meta is defined, but false');
+ t.ok(e.modifier().shift === false, 'checking that modifier().shift is defined, but false');
+ t.ok((typeof(e.mouse()) === 'object'), 'checking that mouse() is an object');
+ t.ok((typeof(e.mouse().button) === 'object'), 'checking that mouse().button is an object');
+ t.ok(e.mouse().button.left === true, 'checking that mouse().button.left is true');
+ t.ok(e.mouse().button.middle === false, 'checking that mouse().button.middle is false');
+ t.ok(e.mouse().button.right === false, 'checking that mouse().button.right is false');
+ t.ok((typeof(e.mouse().page) === 'object'), 'checking that mouse().page is an object');
+ t.ok((typeof(e.mouse().page.x) === 'number'), 'checking that mouse().page.x is a number');
+ t.ok((typeof(e.mouse().page.y) === 'number'), 'checking that mouse().page.y is a number');
+ t.ok((typeof(e.mouse().client) === 'object'), 'checking that mouse().client is an object');
+ t.ok((typeof(e.mouse().client.x) === 'number'), 'checking that mouse().client.x is a number');
+ t.ok((typeof(e.mouse().client.y) === 'number'), 'checking that mouse().client.y is a number');
+
+ /* these should not be defined */
+ t.ok((typeof(e.relatedTarget()) === 'undefined'), 'checking that relatedTarget() is undefined');
+ t.ok((typeof(e.key()) === 'undefined'), 'checking that key() is undefined');
+ };
+
+
+ ident = connect('submit', 'onmousedown', eventTest);
+ triggerMouseEvent('submit', 'mousedown', false);
+ t.is(i, 3, 'Connecting an event to an HTML object and firing a synthetic event');
+
+ disconnect(ident);
+ triggerMouseEvent('submit', 'mousedown', false);
+ t.is(i, 3, 'Disconnecting an event to an HTML object and firing a synthetic event');
+
+
+
+ }
+
+ // non-DOM tests
+
+ var hasNoSignals = {};
+
+ var hasSignals = {someVar: 1};
+
+ var i = 0;
+
+ var aFunction = function() {
+ i++;
+ if (typeof(this.someVar) != 'undefined') {
+ i += this.someVar;
+ }
+ };
+
+ var bFunction = function(someArg, someOtherArg) {
+ i += someArg + someOtherArg;
+ };
+
+
+ var aObject = {};
+ aObject.aMethod = function() {
+ i++;
+ };
+
+ aObject.bMethod = function() {
+ i++;
+ };
+
+ var bObject = {};
+ bObject.bMethod = function() {
+ i++;
+ };
+
+
+ ident = connect(hasSignals, 'signalOne', aFunction);
+ signal(hasSignals, 'signalOne');
+ t.is(i, 2, 'Connecting function');
+ i = 0;
+
+ disconnect(ident);
+ signal(hasSignals, 'signalOne');
+ t.is(i, 0, 'New style disconnecting function');
+ i = 0;
+
+
+ ident = connect(hasSignals, 'signalOne', bFunction);
+ signal(hasSignals, 'signalOne', 1, 2);
+ t.is(i, 3, 'Connecting function');
+ i = 0;
+
+ disconnect(ident);
+ signal(hasSignals, 'signalOne', 1, 2);
+ t.is(i, 0, 'New style disconnecting function');
+ i = 0;
+
+
+ connect(hasSignals, 'signalOne', aFunction);
+ signal(hasSignals, 'signalOne');
+ t.is(i, 2, 'Connecting function');
+ i = 0;
+
+ disconnect(hasSignals, 'signalOne', aFunction);
+ signal(hasSignals, 'signalOne');
+ t.is(i, 0, 'Old style disconnecting function');
+ i = 0;
+
+
+ ident = connect(hasSignals, 'signalOne', aObject, aObject.aMethod);
+ signal(hasSignals, 'signalOne');
+ t.is(i, 1, 'Connecting obj-function');
+ i = 0;
+
+ disconnect(ident);
+ signal(hasSignals, 'signalOne');
+ t.is(i, 0, 'New style disconnecting obj-function');
+ i = 0;
+
+ connect(hasSignals, 'signalOne', aObject, aObject.aMethod);
+ signal(hasSignals, 'signalOne');
+ t.is(i, 1, 'Connecting obj-function');
+ i = 0;
+
+ disconnect(hasSignals, 'signalOne', aObject, aObject.aMethod);
+ signal(hasSignals, 'signalOne');
+ t.is(i, 0, 'Disconnecting obj-function');
+ i = 0;
+
+
+ ident = connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+ signal(hasSignals, 'signalTwo');
+ t.is(i, 1, 'Connecting obj-string');
+ i = 0;
+
+ disconnect(ident);
+ signal(hasSignals, 'signalTwo');
+ t.is(i, 0, 'New style disconnecting obj-string');
+ i = 0;
+
+
+ connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+ signal(hasSignals, 'signalTwo');
+ t.is(i, 1, 'Connecting obj-string');
+ i = 0;
+
+ disconnect(hasSignals, 'signalTwo', aObject, 'aMethod');
+ signal(hasSignals, 'signalTwo');
+ t.is(i, 0, 'Old style disconnecting obj-string');
+ i = 0;
+
+
+ var shouldRaise = function() { return undefined.attr; };
+
+ try {
+ connect(hasSignals, 'signalOne', shouldRaise);
+ signal(hasSignals, 'signalOne');
+ t.ok(false, 'An exception was not raised');
+ } catch (e) {
+ t.ok(true, 'An exception was raised');
+ }
+ disconnect(hasSignals, 'signalOne', shouldRaise);
+ t.is(i, 0, 'Exception raised, signal should not have fired');
+ i = 0;
+
+
+ connect(hasSignals, 'signalOne', aObject, 'aMethod');
+ connect(hasSignals, 'signalOne', aObject, 'bMethod');
+ signal(hasSignals, 'signalOne');
+ t.is(i, 2, 'Connecting one signal to two slots in one object');
+ i = 0;
+
+ disconnect(hasSignals, 'signalOne', aObject, 'aMethod');
+ disconnect(hasSignals, 'signalOne', aObject, 'bMethod');
+ signal(hasSignals, 'signalOne');
+ t.is(i, 0, 'Disconnecting one signal from two slots in one object');
+ i = 0;
+
+
+ connect(hasSignals, 'signalOne', aObject, 'aMethod');
+ connect(hasSignals, 'signalOne', bObject, 'bMethod');
+ signal(hasSignals, 'signalOne');
+ t.is(i, 2, 'Connecting one signal to two slots in two objects');
+ i = 0;
+
+ disconnect(hasSignals, 'signalOne', aObject, 'aMethod');
+ disconnect(hasSignals, 'signalOne', bObject, 'bMethod');
+ signal(hasSignals, 'signalOne');
+ t.is(i, 0, 'Disconnecting one signal from two slots in two objects');
+ i = 0;
+
+
+ try {
+ connect(nothing, 'signalOne', aObject, 'aMethod');
+ signal(nothing, 'signalOne');
+ t.ok(false, 'An exception was not raised when connecting undefined');
+ } catch (e) {
+ t.ok(true, 'An exception was raised when connecting undefined');
+ }
+
+ try {
+ disconnect(nothing, 'signalOne', aObject, 'aMethod');
+ t.ok(false, 'An exception was not raised when disconnecting undefined');
+ } catch (e) {
+ t.ok(true, 'An exception was raised when disconnecting undefined');
+ }
+
+
+ try {
+ connect(hasSignals, 'signalOne', nothing);
+ signal(hasSignals, 'signalOne');
+ t.ok(false, 'An exception was not raised when connecting an undefined function');
+ } catch (e) {
+ t.ok(true, 'An exception was raised when connecting an undefined function');
+ }
+
+ try {
+ disconnect(hasSignals, 'signalOne', nothing);
+ t.ok(false, 'An exception was not raised when disconnecting an undefined function');
+ } catch (e) {
+ t.ok(true, 'An exception was raised when disconnecting an undefined function');
+ }
+
+
+ try {
+ connect(hasSignals, 'signalOne', aObject, aObject.nothing);
+ signal(hasSignals, 'signalOne');
+ t.ok(false, 'An exception was not raised when connecting an undefined method');
+ } catch (e) {
+ t.ok(true, 'An exception was raised when connecting an undefined method');
+ }
+
+ try {
+ connect(hasSignals, 'signalOne', aObject, 'nothing');
+ signal(hasSignals, 'signalOne');
+ t.ok(false, 'An exception was not raised when connecting an undefined method (as string)');
+ } catch (e) {
+ t.ok(true, 'An exception was raised when connecting an undefined method (as string)');
+ }
+
+ t.is(i, 0, 'Signals should not have fired');
+
+ connect(hasSignals, 'signalOne', aFunction);
+ connect(hasSignals, 'signalOne', aObject, 'aMethod');
+ disconnectAll(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalOne');
+ t.is(i, 0, 'disconnectAll works with single explicit signal');
+ i = 0;
+
+ connect(hasSignals, 'signalOne', aFunction);
+ connect(hasSignals, 'signalOne', aObject, 'aMethod');
+ connect(hasSignals, 'signalTwo', aFunction);
+ connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+ disconnectAll(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalOne');
+ t.is(i, 0, 'disconnectAll works with single explicit signal');
+ signal(hasSignals, 'signalTwo');
+ t.is(i, 3, 'disconnectAll does not disconnect unrelated signals');
+ i = 0;
+
+ connect(hasSignals, 'signalOne', aFunction);
+ connect(hasSignals, 'signalOne', aObject, 'aMethod');
+ connect(hasSignals, 'signalTwo', aFunction);
+ connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+ disconnectAll(hasSignals, 'signalOne', 'signalTwo');
+ signal(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalTwo');
+ t.is(i, 0, 'disconnectAll works with two explicit signals');
+ i = 0;
+
+ connect(hasSignals, 'signalOne', aFunction);
+ connect(hasSignals, 'signalOne', aObject, 'aMethod');
+ connect(hasSignals, 'signalTwo', aFunction);
+ connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+ disconnectAll(hasSignals, ['signalOne', 'signalTwo']);
+ signal(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalTwo');
+ t.is(i, 0, 'disconnectAll works with two explicit signals as a list');
+ i = 0;
+
+ connect(hasSignals, 'signalOne', aFunction);
+ connect(hasSignals, 'signalOne', aObject, 'aMethod');
+ connect(hasSignals, 'signalTwo', aFunction);
+ connect(hasSignals, 'signalTwo', aObject, 'aMethod');
+ disconnectAll(hasSignals);
+ signal(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalTwo');
+ t.is(i, 0, 'disconnectAll works with implicit signals');
+ i = 0;
+
+ var toggle = function() {
+ disconnectAll(hasSignals, 'signalOne');
+ connect(hasSignals, 'signalOne', aFunction);
+ i++;
+ };
+
+ connect(hasSignals, 'signalOne', aFunction);
+ connect(hasSignals, 'signalTwo', function() { i++; });
+ connect(hasSignals, 'signalTwo', toggle);
+ connect(hasSignals, 'signalTwo', function() { i++; }); // #147
+ connect(hasSignals, 'signalTwo', function() { i++; });
+ signal(hasSignals, 'signalTwo');
+ t.is(i, 4, 'disconnectAll fired in a signal loop works');
+ i = 0;
+ disconnectAll('signalOne');
+ disconnectAll('signalTwo');
+
+ var testfunc = function () { arguments.callee.count++; };
+ testfunc.count = 0;
+ var testObj = {
+ methOne: function () { this.countOne++; }, countOne: 0,
+ methTwo: function () { this.countTwo++; }, countTwo: 0
+ };
+ connect(hasSignals, 'signalOne', testfunc);
+ connect(hasSignals, 'signalTwo', testfunc);
+ signal(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalTwo');
+ t.is(testfunc.count, 2, 'disconnectAllTo func precondition');
+ disconnectAllTo(testfunc);
+ signal(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalTwo');
+ t.is(testfunc.count, 2, 'disconnectAllTo func');
+
+ connect(hasSignals, 'signalOne', testObj, 'methOne');
+ connect(hasSignals, 'signalTwo', testObj, 'methTwo');
+ signal(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalTwo');
+ t.is(testObj.countOne, 1, 'disconnectAllTo obj precondition');
+ t.is(testObj.countTwo, 1, 'disconnectAllTo obj precondition');
+ disconnectAllTo(testObj);
+ signal(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalTwo');
+ t.is(testObj.countOne, 1, 'disconnectAllTo obj');
+ t.is(testObj.countTwo, 1, 'disconnectAllTo obj');
+
+ testObj.countOne = testObj.countTwo = 0;
+ connect(hasSignals, 'signalOne', testObj, 'methOne');
+ connect(hasSignals, 'signalTwo', testObj, 'methTwo');
+ disconnectAllTo(testObj, 'methOne');
+ signal(hasSignals, 'signalOne');
+ signal(hasSignals, 'signalTwo');
+ t.is(testObj.countOne, 0, 'disconnectAllTo obj+str');
+ t.is(testObj.countTwo, 1, 'disconnectAllTo obj+str');
+
+ has__Connect = {
+ count: 0,
+ __connect__: function (ident) {
+ this.count += arguments.length;
+ disconnect(ident);
+ }
+ };
+
+ connect(has__Connect, 'signalOne', aFunction);
+ t.is(has__Connect.count, 3, '__connect__ is called when it exists');
+ signal(has__Connect, 'signalOne');
+ t.is(has__Connect.count, 3, '__connect__ can disconnect the signal');
+
+ var events = {};
+ var test_ident = connect(events, "test", function() {
+ var fail_ident = connect(events, "fail", function () {
+ events.failed = true;
+ });
+ disconnect(fail_ident);
+ signal(events, "fail");
+ });
+ signal(events, "test");
+ t.is(events.failed, undefined, 'disconnected slots do not fire');
+
+};