diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2013-02-11 05:48:20 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2013-02-11 05:48:20 +0000 |
commit | 4951c1b04bf66f81cf648b76af3795245d56381a (patch) | |
tree | 7e6182a46d4d246716438cdb9ecd4480ef3d4b65 /sca-cpp/trunk/modules | |
parent | 5c0eab60028407c84e2fee6a4fa1fbc03716d1d2 (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 'sca-cpp/trunk/modules')
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/component.js | 152 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/ui.js | 110 |
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) |