diff options
author | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
---|---|---|
committer | Matt A. Tobin <mattatobin@localhost.localdomain> | 2018-02-02 04:16:08 -0500 |
commit | 5f8de423f190bbb79a62f804151bc24824fa32d8 (patch) | |
tree | 10027f336435511475e392454359edea8e25895d /dom/tests/mochitest/ajax/mochikit | |
parent | 49ee0794b5d912db1f95dce6eb52d781dc210db5 (diff) | |
download | UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.gz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.lz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.tar.xz UXP-5f8de423f190bbb79a62f804151bc24824fa32d8.zip |
Add m-esr52 at 52.6.0
Diffstat (limited to 'dom/tests/mochitest/ajax/mochikit')
55 files changed, 17679 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 000000000..55f4857b9 --- /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 000000000..ec1350e60 --- /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(/(\&\;|\&\#38\;|\&|\&)/); + 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 000000000..708f49017 --- /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 000000000..c044ef2ab --- /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 000000000..02fe5bfb9 --- /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, "&" + ).replace(/"/g, """ + ).replace(/</g, "<" + ).replace(/>/g, ">"); + }, + + /** @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 000000000..c0b03ee9d --- /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 000000000..c471ffe90 --- /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 000000000..937b681f7 --- /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 000000000..c2fcbeee0 --- /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 000000000..4d25c3e78 --- /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 lame 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 000000000..3798ae404 --- /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 000000000..3a13b241f --- /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 000000000..92558cb7b --- /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 000000000..23b0f181c --- /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 000000000..f5d1afac3 --- /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 000000000..3e5789160 --- /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 crazy 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 000000000..8976ec0b2 --- /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 000000000..93e77862a --- /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 000000000..494a5b440 --- /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 000000000..b7d8d87b2 --- /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 000000000..8d644b19e --- /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 000000000..5bf0e943d --- /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 000000000..25f301e30 --- /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 000000000..a94ce14a4 --- /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 000000000..639519ecf --- /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 000000000..32889ea82 --- /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 000000000..3db71e1e7 --- /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 000000000..bad32dfb1 --- /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 000000000..45036d9c7 --- /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"), "<>"&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 000000000..43ad9d4ab --- /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 000000000..a191a53be --- /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 000000000..58bffa6bf --- /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 000000000..8086acc2d --- /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 000000000..53a0e0ed0 --- /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 000000000..d92229a6e --- /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 000000000..d1a8b60d8 --- /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 000000000..503acef07 --- /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 000000000..9c37416d6 --- /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 000000000..b01adc6e7 --- /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 000000000..e4a40c7e4 --- /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 000000000..73709775d --- /dev/null +++ b/dom/tests/mochitest/ajax/mochikit/tests/SimpleTest/SimpleTest.js @@ -0,0 +1,463 @@ +/** + * 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, 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.ok(a == b, name, "got " + repr(a) + ", expected " + repr(b)); +}; + +SimpleTest.isnot = function (a, b, name) { + var repr = MochiKit.Base.repr; + SimpleTest.ok(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 oldOK = SimpleTest.ok; + + SimpleTest.ok = function(condition, name, diag) { + parent.SimpleTest.ok( condition, name, diag ); + return oldOK( condition, name, diag ); + }; + + var oldFinish = SimpleTest.finish; + + SimpleTest.finish = function() { + oldFinish(); + parent.runAJAXTest(); + }; +})(); + +// Global symbols: +var ok = SimpleTest.ok; +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 000000000..a4e313075 --- /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 000000000..38a401402 --- /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 000000000..18434604c --- /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 000000000..da46bd32c --- /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 000000000..d48571238 --- /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 000000000..2cbf2848d --- /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 000000000..17d418d8c --- /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.ok( Color.whiteColor().toRGBString(), "rgb(255,255,255)", "toRGBString white" ); + t.ok( 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 000000000..cc2d958e3 --- /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 000000000..d3a3c5837 --- /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 000000000..785cebf82 --- /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 000000000..d0ff146ad --- /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 000000000..66f4989b0 --- /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 000000000..037e18c81 --- /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 000000000..6a905952f --- /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'); + +}; |