summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules
diff options
context:
space:
mode:
authorjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2013-02-11 05:48:20 +0000
committerjsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68>2013-02-11 05:48:20 +0000
commit4951c1b04bf66f81cf648b76af3795245d56381a (patch)
tree7e6182a46d4d246716438cdb9ecd4480ef3d4b65 /sca-cpp/trunk/modules
parent5c0eab60028407c84e2fee6a4fa1fbc03716d1d2 (diff)
Improvements to the app management UI.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1444660 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/component.js152
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/ui.js110
2 files changed, 205 insertions, 57 deletions
diff --git a/sca-cpp/trunk/modules/js/htdocs/component.js b/sca-cpp/trunk/modules/js/htdocs/component.js
index a34ebfac92..0a8ec5f5d5 100644
--- a/sca-cpp/trunk/modules/js/htdocs/component.js
+++ b/sca-cpp/trunk/modules/js/htdocs/component.js
@@ -184,43 +184,113 @@ HTTPBindingClient.jsonResult = function(http) {
};
/**
- * Schedule async requests, and limit to 4 concurrent running requests.
+ * Schedule async requests, limiting the number of concurrent running requests.
*/
HTTPBindingClient.queuedRequests = new Array();
-HTTPBindingClient.runningRequests = 0;
-HTTPBindingClient.scheduleAsyncRequest = function(f) {
+HTTPBindingClient.runningRequests = new Array();
+HTTPBindingClient.concurrentRequests = 2;
+
+HTTPBindingClient.scheduleAsyncRequest = function(f, cancelable) {
+ //debug('schedule async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+
// Queue the request function
- HTTPBindingClient.queuedRequests.push(f);
+ var req = new Object();
+ req.f = f;
+ req.cancelable = cancelable;
+ req.canceled = false;
+ HTTPBindingClient.queuedRequests.push(req);
+
+ // Execute any requests in the queue
+ setTimeout(function() {
+ HTTPBindingClient.runAsyncRequests(true);
+ }, 0);
+ return true;
+};
- // Execute requests in the queue
- (function runAsyncRequests() {
- // Stop now if we already have enough requests running or there's no request in the queue
- //debug('runAsyncRequests', 'running', HTTPBindingClient.runningRequests, 'queued', HTTPBindingClient.queuedRequests.length);
- if(HTTPBindingClient.runningRequests >= 4 || HTTPBindingClient.queuedRequests.length == 0)
+HTTPBindingClient.forgetRequest = function(req) {
+ req.http = null;
+
+ // Remove a request from the list of running requests
+ for (i in HTTPBindingClient.runningRequests) {
+ if (HTTPBindingClient.runningRequests[i] == req) {
+ HTTPBindingClient.runningRequests.splice(i, 1);
+ //debug('forget async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
return true;
+ }
+ }
+ return false;
+};
+
+HTTPBindingClient.cancelRequests = function() {
+ //debug('cancel async requests, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+
+ // Cancel any cancelable in flight HTTP requests
+ for (i in HTTPBindingClient.queuedRequests) {
+ var req = HTTPBindingClient.queuedRequests[i];
+ if (req.cancelable)
+ req.canceled = true;
+ }
+ for (i in HTTPBindingClient.runningRequests) {
+ var req = HTTPBindingClient.runningRequests[i];
+ if (req.cancelable) {
+ req.canceled = true;
+ if (req.http) {
+ req.http.abort();
+ req.http = null;
+ //debug('abort async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+ }
+ }
+ }
- // Run the first request in the queue
- var req = HTTPBindingClient.queuedRequests.shift();
- HTTPBindingClient.runningRequests++;
- setTimeout(function runAsyncRequest() {
+ // Flush the queue
+ setTimeout(function() {
+ HTTPBindingClient.runAsyncRequests(true);
+ }, 0);
+}
+
+HTTPBindingClient.runAsyncRequests = function(fromui) {
+ // Stop now if we already have enough requests running or there's no request in the queue
+ if(HTTPBindingClient.runningRequests.length >= HTTPBindingClient.concurrentRequests || HTTPBindingClient.queuedRequests.length == 0)
+ return true;
+
+ // Run the first request in the queue
+ var req = HTTPBindingClient.queuedRequests.shift();
+ if (!req.canceled) {
+ HTTPBindingClient.runningRequests.push(req);
+ //debug('run async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+ var runAsyncRequest = function() {
+ if (req.canceled) {
+ HTTPBindingClient.forgetRequest(req);
+ //debug('canceled timed async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+ return false;
+ }
try {
- return req(function asyncRequestDone() {
+ req.http = new XMLHttpRequest();
+ return req.f(req.http, function asyncRequestDone() {
// Execute any requests left in the queue
- HTTPBindingClient.runningRequests--;
- runAsyncRequests();
+ HTTPBindingClient.forgetRequest(req);
+ //debug('done async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+ HTTPBindingClient.runAsyncRequests(false);
return true;
});
} catch(e) {
// Execute any requests left in the queue
- HTTPBindingClient.runningRequests--;
- runAsyncRequests();
+ HTTPBindingClient.forgetRequest(req);
+ //debug('err async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+ HTTPBindingClient.runAsyncRequests(false);
}
- }, 0);
+ return false;
+ };
+ if (false)
+ setTimeout(runAsyncRequest, 0);
+ else
+ runAsyncRequest();
+ } else {
+ //debug('canceled queued async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length);
+ }
- // Execute any requests left in the queue
- runAsyncRequests();
- })();
- return true;
+ // Execute any requests left in the queue
+ HTTPBindingClient.runAsyncRequests(fromui);
};
/**
@@ -339,8 +409,7 @@ HTTPBindingClient.prototype.jsonApply = function(req) {
// Call asynchronously with a callback
if(hascb) {
var u = this.uri;
- return HTTPBindingClient.scheduleAsyncRequest(function jsonApplyRequest(done) {
- var http = new XMLHttpRequest();
+ return HTTPBindingClient.scheduleAsyncRequest(function jsonApplyRequest(http, done) {
http.open("POST", u, true);
http.setRequestHeader("Accept", "*/*");
http.setRequestHeader("Content-Type", "application/json-rpc");
@@ -371,7 +440,7 @@ HTTPBindingClient.prototype.jsonApply = function(req) {
// Send the request
http.send(req.data);
return req.id;
- });
+ }, false);
}
// Call synchronously and return the result or exception
@@ -402,16 +471,15 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) {
return item;
// Pass local result to callback
- try {
+ setTimeout(function() {
cb(item);
- } catch (cbe) {}
+ }, 0);
}
}
// Call asynchronously with a callback
if(hascb) {
- return HTTPBindingClient.scheduleAsyncRequest(function getRequest(done) {
- var http = new XMLHttpRequest();
+ return HTTPBindingClient.scheduleAsyncRequest(function getRequest(http, done) {
http.open("GET", u, true);
http.setRequestHeader("Accept", "*/*");
http.onreadystatechange = function() {
@@ -420,7 +488,8 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) {
// Pass result if different from local result
if(http.status == 200) {
var xl = http.getResponseHeader("X-Login");
- if(xl != null && xl != '') {
+ var ct = http.getResponseHeader("Content-Type");
+ if(xl != null && xl != '' && ct != null && ct.indexOf('text/html') == 0) {
// Detect redirect to a login page
try {
var le = new HTTPBindingClient.Exception(403, 'X-Login');
@@ -431,7 +500,6 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) {
} catch(cbe) {}
}
- var ct = http.getResponseHeader("Content-Type");
if(http.responseText == '' || ct == null || ct == '') {
// Report empty response
try {
@@ -467,7 +535,7 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) {
// Send the request
http.send(null);
return true;
- });
+ }, true);
}
// Call synchronously and return the result or exception
@@ -477,7 +545,8 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) {
http.send(null);
if(http.status == 200) {
var xl = http.getResponseHeader("X-Login");
- if(xl != null && xl != '') {
+ var ct = http.getResponseHeader("Content-Type");
+ if(xl != null && xl != '' && ct != null && ct.indexOf('text/html') == 0) {
// Detect redirect to a login page
var le = new HTTPBindingClient.Exception(403, 'X-Login');
if(window.onloginredirect)
@@ -504,8 +573,7 @@ HTTPBindingClient.prototype.post = function (entry, cb) {
// Call asynchronously with a callback
if(hascb) {
var u = this.uri;
- return HTTPBindingClient.scheduleAsyncRequest(function postRequest(done) {
- var http = new XMLHttpRequest();
+ return HTTPBindingClient.scheduleAsyncRequest(function postRequest(http, done) {
http.open("POST", u, true);
http.setRequestHeader("Accept", "*/*");
http.setRequestHeader("Content-Type", "application/atom+xml");
@@ -529,7 +597,7 @@ HTTPBindingClient.prototype.post = function (entry, cb) {
// Send the request
http.send(entry);
return true;
- });
+ }, false);
}
// Call synchronously
@@ -562,8 +630,7 @@ HTTPBindingClient.prototype.put = function(id, entry, cb, mode) {
// Call asynchronously with a callback
if(hascb) {
- return HTTPBindingClient.scheduleAsyncRequest(function putRequest(done) {
- var http = new XMLHttpRequest();
+ return HTTPBindingClient.scheduleAsyncRequest(function putRequest(http, done) {
http.open("PUT", u, true);
http.setRequestHeader("Accept", "*/*");
http.setRequestHeader("Content-Type", "application/atom+xml");
@@ -599,7 +666,7 @@ HTTPBindingClient.prototype.put = function(id, entry, cb, mode) {
// Send the request
http.send(entry);
return true;
- });
+ }, false);
}
// Call synchronously
@@ -640,8 +707,7 @@ HTTPBindingClient.prototype.del = function(id, cb, mode) {
// Call asynchronously with a callback
if(hascb) {
- return HTTPBindingClient.scheduleAsyncRequest(function delRequest(done) {
- var http = new XMLHttpRequest();
+ return HTTPBindingClient.scheduleAsyncRequest(function delRequest(http, done) {
http.open("DELETE", u, true);
http.setRequestHeader("Accept", "*/*");
http.onreadystatechange = function() {
@@ -665,7 +731,7 @@ HTTPBindingClient.prototype.del = function(id, cb, mode) {
// Send the request
http.send(null);
return true;
- });
+ }, false);
}
// Call synchronously
diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.js b/sca-cpp/trunk/modules/js/htdocs/ui.js
index 3aa9e1052a..2bd21f6ed4 100644
--- a/sca-cpp/trunk/modules/js/htdocs/ui.js
+++ b/sca-cpp/trunk/modules/js/htdocs/ui.js
@@ -29,6 +29,8 @@ var ui = {};
ui.elementByID = function(node, id) {
if (node.skipNode == true)
return null;
+ if (node == document)
+ return document.getElementById(id);
for (var i in node.childNodes) {
var child = node.childNodes[i];
if (isNull(child))
@@ -43,6 +45,21 @@ ui.elementByID = function(node, id) {
};
/**
+ * Remove ids in a tree of elements.
+ */
+ui.removeElementIDs = function(node) {
+ if (!isNull(node.id))
+ node.id = null;
+ for (var i in node.childNodes) {
+ var child = node.childNodes[i];
+ if (isNull(child))
+ continue;
+ ui.removeElementIDs(child);
+ }
+ return true;
+};
+
+/**
* Return the current document, or a child element with the given id.
*/
function $(id) {
@@ -229,6 +246,20 @@ ui.webkitVersion = function() {
};
/**
+ * Return the Safari version.
+ */
+ui.browserVersion = function() {
+ return Number(navigator.userAgent.replace(/.*Version\/(\d+\.\d+).*/, '$1'));
+};
+
+/**
+ * Return true if the client is Android based.
+ */
+ui.isAndroid = function() {
+ return navigator.userAgent.match(/Android/i);
+};
+
+/**
* Return true if the client is Firefox.
*/
ui.isFirefox = function() {
@@ -273,16 +304,11 @@ ui.msieVersion = function() {
/**
* Run a UI rendering function asynchronously.
*/
-ui.asyncFrame = null;
-ui.async = function(f) {
- if (isNull(ui.asyncFrame))
- // Use requestAnimationFrame when available, fallback to setTimeout
- ui.asyncFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame ||
- window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame ||
- function(f) {
- return window.setTimeout(f, 16);
- };
- return ui.asyncFrame.call(window, f);
+ui.async = function(f, t) {
+ window.setTimeout(function() {
+ return f();
+ }, isNull(t)? 0 : t);
+ return true;
};
/**
@@ -290,10 +316,10 @@ ui.async = function(f) {
*/
ui.delayed = {}
ui.delay = function(f, t) {
- var id = window.setTimeout(function() {
+ var id = window.setTimeout(function() {
delete ui.delayed[id];
return f();
- }, isNull(t)? 16 : t);
+ }, isNull(t)? 0 : t);
ui.delayed[id] = id;
return id;
};
@@ -443,6 +469,9 @@ ui.navigate = function(url, win) {
window.ontouchmove = null;
}
+ // Cancel any cancelable HTTP requests
+ HTTPBindingClient.cancelRequests();
+
// Cleanup memoized element lookups
ui.unmemo$();
@@ -460,12 +489,65 @@ ui.navigate = function(url, win) {
}
/**
+ * Bind a click handler to a widget.
+ */
+ui.ontouchstart = function(widget, e) {
+ //debug('ontouchstart');
+ widget.down = true;
+ widget.moved = false;
+ var t = e.touches[0];
+ widget.moveX = t.clientX;
+ widget.moveY = t.clientY;
+};
+
+ui.ontouchmove = function(widget, e) {
+ //debug('ontouchmove');
+ var t = e.touches[0];
+ if (t.clientX != widget.moveX) {
+ widget.moveX = t.clientX;
+ widget.moved = true;
+ }
+ if (t.clientY != widget.moveY) {
+ widget.moveY = t.clientY;
+ widget.moved = true;
+ }
+};
+
+ui.ontouchend = function(widget, e) {
+ //debug('ontouchend');
+ widget.down = false;
+ if (!widget.moved) {
+ e.preventDefault();
+ return widget.onclick(e);
+ }
+};
+
+ui.onclick = function(widget, handler) {
+ if (ui.isMobile()) {
+ widget.ontouchstart = function(e) {
+ return ui.ontouchstart(widget, e);
+ };
+ widget.ontouchmove = function(e) {
+ return ui.ontouchmove(widget, e);
+ };
+ widget.ontouchend = function(e) {
+ return ui.ontouchend(widget, e);
+ };
+ }
+ widget.onclick = function(e) {
+ //debug('onclick');
+ return handler(e);
+ };
+ return widget;
+};
+
+/**
* Build a portable <a href> tag.
*/
ui.href = function(id, loc, target, html) {
if (target == '_blank')
return '<a id="' + id + '" href="' + loc + '" target="_blank">' + html + '</a>';
- return '<a id="' + id + '" href="' + loc + '" onclick="return ui.navigate(\'' + loc + '\', \'' + target + '\');">' + html + '</a>';
+ return '<a id="' + id + '" href="' + loc + '" ' + (ui.isMobile()? 'ontouchstart="return ui.ontouchstart(this, event);" ontouchmove="return ui.ontouchmove(this, event);" ontouchend="return ui.ontouchend(this, event);" ' : '') + 'onclick="return ui.navigate(\'' + loc + '\', \'' + target + '\');">' + html + '</a>';
};
/**
@@ -489,7 +571,7 @@ ui.menufunc = function(id, name, fun, hilight) {
function Menu() {
this.content = function() {
function href(id, fun, html) {
- return '<a id="' + id + '" href="/" onclick="' + fun + '">' + html + '</a>';
+ return '<a id="' + id + '" href="/" ' + (ui.isMobile()? 'ontouchstart="return ui.ontouchstart(this, event);" ontouchmove="return ui.ontouchmove(this, event);" ontouchend="return ui.ontouchend(this, event);" ' : '') + 'onclick="' + fun + '">' + html + '</a>';
}
if (hilight == true)