summaryrefslogtreecommitdiff
path: root/frontend/gamma/js/MochiKit/Async.js
Side-by-side diff
Diffstat (limited to 'frontend/gamma/js/MochiKit/Async.js') (more/less context) (show whitespace changes)
-rw-r--r--frontend/gamma/js/MochiKit/Async.js118
1 files changed, 92 insertions, 26 deletions
diff --git a/frontend/gamma/js/MochiKit/Async.js b/frontend/gamma/js/MochiKit/Async.js
index c7408e7..cc43835 100644
--- a/frontend/gamma/js/MochiKit/Async.js
+++ b/frontend/gamma/js/MochiKit/Async.js
@@ -1,80 +1,91 @@
/***
MochiKit.Async 1.5
See <http://mochikit.com/> for documentation, downloads, license, etc.
(c) 2005 Bob Ippolito. All rights Reserved.
***/
-MochiKit.Base._module('Async', '1.5', ['Base']);
+MochiKit.Base.module(MochiKit, 'Async', '1.5', ['Base']);
/** @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;
+ this.finalized = 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 + ')';
+ return 'Deferred(' + this.id + ', ' + this.state() + ')';
},
toString: MochiKit.Base.forwardCall("repr"),
_nextId: MochiKit.Base.counter(),
+ /** @id MochiKit.Async.Deferred.prototype.state */
+ state: function () {
+ if (this.fired == -1) {
+ return 'unfired';
+ } else if (this.fired === 0) {
+ return 'success';
+ } else {
+ return 'error';
+ }
+ },
+
/** @id MochiKit.Async.Deferred.prototype.cancel */
- cancel: function () {
+ cancel: function (e) {
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));
+ if (typeof(e) === 'string') {
+ e = new self.GenericError(e);
+ } else if (!(e instanceof Error)) {
+ e = new self.CancelledError(this);
+ }
+ this.errback(e);
}
} else if ((this.fired === 0) && (this.results[0] instanceof self.Deferred)) {
- this.results[0].cancel();
+ this.results[0].cancel(e);
}
},
_resback: function (res) {
/***
The primitive that means either callback or errback
***/
this.fired = ((res instanceof Error) ? 1 : 0);
this.results[this.fired] = res;
+ if (this.paused === 0) {
this._fire();
+ }
},
_check: function () {
if (this.fired != -1) {
if (!this.silentlyCancelled) {
throw new MochiKit.Async.AlreadyCalledError(this);
}
this.silentlyCancelled = false;
return;
}
},
@@ -120,73 +131,95 @@ MochiKit.Async.Deferred.prototype = {
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");
}
+ if (this.finalized) {
+ throw new Error("Finalized Deferreds can not be re-used");
+ }
this.chain.push([cb, eb]);
if (this.fired >= 0) {
this._fire();
}
return this;
},
+ /** @id MochiKit.Async.Deferred.prototype.setFinalizer */
+ setFinalizer: function (fn) {
+ if (this.chained) {
+ throw new Error("Chained Deferreds can not be re-used");
+ }
+ if (this.finalized) {
+ throw new Error("Finalized Deferreds can not be re-used");
+ }
+ if (arguments.length > 1) {
+ fn = MochiKit.Base.partial.apply(null, arguments);
+ }
+ this._finalizer = fn;
+ 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();
- }
+ self._resback(res);
};
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 (this.chain.length == 0 && this.paused === 0 && this._finalizer) {
+ this.finalized = true;
+ this._finalizer(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) {
@@ -240,25 +273,25 @@ MochiKit.Base.update(MochiKit.Async, {
// 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)) {
+ if (!status && (this.response || 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);
@@ -328,25 +361,26 @@ MochiKit.Base.update(MochiKit.Async, {
},
_doXHR: function (url, opts) {
var m = MochiKit.Base;
opts = m.update({
method: 'GET',
sendContent: ''
/*
queryString: undefined,
username: undefined,
password: undefined,
headers: undefined,
- mimeType: undefined
+ mimeType: undefined,
+ responseType: 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.
@@ -362,24 +396,27 @@ MochiKit.Base.update(MochiKit.Async, {
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);
}
}
+ if ("responseType" in opts && "responseType" in req) {
+ req.responseType = opts.responseType;
+ }
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;
@@ -395,34 +432,62 @@ MochiKit.Base.update(MochiKit.Async, {
/** @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.loadScript */
+ loadScript: function (url) {
+ var d = new MochiKit.Async.Deferred();
+ var script = document.createElement("script");
+ script.type = "text/javascript";
+ script.src = url;
+ script.onload = function () {
+ script.onload = null;
+ script.onerror = null;
+ script.onreadystatechange = null;
+ script = null;
+ d.callback();
+ };
+ script.onerror = function (msg) {
+ script.onload = null;
+ script.onerror = null;
+ script.onreadystatechange = null;
+ script = null;
+ msg = "Failed to load script at " + url + ": " + msg;
+ d.errback(new URIError(msg, url));
+ }
+ script.onreadystatechange = function () {
+ if (script.readyState == "loaded" || script.readyState == "complete") {
+ script.onload();
+ } else {
+ // IE doesn't bother to report errors...
+ MochiKit.Async.callLater(10, script.onerror, "Script loading timed out")
+ }
+ };
+ document.getElementsByTagName("head")[0].appendChild(script);
+ 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));
+ var cb = MochiKit.Base.bind("callback", d, value);
+ var timeout = setTimeout(cb, Math.floor(seconds * 1000));
d.canceller = function () {
try {
clearTimeout(timeout);
} catch (e) {
// pass
}
};
return d;
},
/** @id MochiKit.Async.callLater */
callLater: function (seconds, func) {
@@ -501,24 +566,25 @@ MochiKit.Async.DeferredList = function (list, /* optional */fireOnOneCallback, f
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.constructor = MochiKit.Async.DeferredList;
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);
}