From d7069b5a2e7859ab14c5a909d5e5fc6bc84b80cb Mon Sep 17 00:00:00 2001 From: jsdelfino Date: Thu, 3 Jan 2013 07:41:53 +0000 Subject: Improve app hosting management app, restructure UI and refactor REST services and data model to use an SQL database. git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1428193 13f79535-47bb-0310-9956-ffa450edef68 --- sca-cpp/trunk/modules/js/htdocs/atomutil.js | 8 +- sca-cpp/trunk/modules/js/htdocs/component.js | 708 +++++++++++--------- sca-cpp/trunk/modules/js/htdocs/ui.css | 929 ++++++++++++++++++--------- sca-cpp/trunk/modules/js/htdocs/ui.js | 329 ++++++++-- sca-cpp/trunk/modules/js/htdocs/util.js | 131 +++- 5 files changed, 1453 insertions(+), 652 deletions(-) (limited to 'sca-cpp/trunk/modules/js/htdocs') diff --git a/sca-cpp/trunk/modules/js/htdocs/atomutil.js b/sca-cpp/trunk/modules/js/htdocs/atomutil.js index 068b5de2fd..3d4e9d08d2 100644 --- a/sca-cpp/trunk/modules/js/htdocs/atomutil.js +++ b/sca-cpp/trunk/modules/js/htdocs/atomutil.js @@ -42,7 +42,7 @@ atom.entryElementValues = function(e) { var u = isNil(lu)? mklist() : mklist(mklist(element, "'updated", elementValue(car(lu)))); var lc = filter(selector(mklist(element, "'content")), e); - var c = isNil(lc)? mklist() : mklist(mklist(element, "'content", elementValue(car(lc)))); + var c = isNil(lc)? mklist() : isAttribute(elementValue(car(lc)))? mklist() : mklist(mklist(element, "'content", elementValue(car(lc)))); return append(append(append(mklist(element, "'entry", t, i), a), u), c); }; @@ -127,9 +127,9 @@ atom.entryElement = function(l) { return append(append(append(append( mklist(element, "'entry", mklist(attribute, "'xmlns", "http://www.w3.org/2005/Atom"), mklist(element, "'title", mklist(attribute, "'type", "text"), title), mklist(element, "'id", id)), - isNil(author)? mklist() : mklist(element, "'author", - (email? mklist(element, "'email", elementValue(author)) : mklist(element, "'name", elementValue(author))))), - isNil(updated)? mklist() : mklist(element, "'updated", elementValue(updated))), + isNil(author)? mklist() : mklist(mklist(element, "'author", + (email? mklist(element, "'email", elementValue(author)) : mklist(element, "'name", elementValue(author)))))), + isNil(updated)? mklist() : mklist(mklist(element, "'updated", elementValue(updated)))), isNil(content)? mklist() : mklist(append(mklist(element, "'content", mklist(attribute, "'type", text? "text" : "application/xml")), text? mklist(elementValue(content)) : elementChildren(content)))), diff --git a/sca-cpp/trunk/modules/js/htdocs/component.js b/sca-cpp/trunk/modules/js/htdocs/component.js index c3799ef708..a34ebfac92 100644 --- a/sca-cpp/trunk/modules/js/htdocs/component.js +++ b/sca-cpp/trunk/modules/js/htdocs/component.js @@ -38,11 +38,11 @@ var JSONClient = {}; */ JSONClient.escapeJSONChar = function(c) { if(c == "\"" || c == "\\") return "\\" + c; - if (c == "\b") return "\\b"; - if (c == "\f") return "\\f"; - if (c == "\n") return "\\n"; - if (c == "\r") return "\\r"; - if (c == "\t") return "\\t"; + if(c == "\b") return "\\b"; + if(c == "\f") return "\\f"; + if(c == "\n") return "\\n"; + if(c == "\r") return "\\r"; + if(c == "\t") return "\\t"; var hex = c.charCodeAt(0).toString(16); if(hex.length == 1) return "\\u000" + hex; if(hex.length == 2) return "\\u00" + hex; @@ -109,11 +109,6 @@ function HTTPBindingClient(name, uri, domain) { this.apply = this.createApplyMethod(); } -/** - * JSON-RPC request counter. - */ -HTTPBindingClient.jsonrpcID = 1; - /** * HTTPBindingClient implementation */ @@ -129,7 +124,7 @@ HTTPBindingClient.prototype.createApplyMethod = function() { args.push(arguments[i]); var cb = null; - if (typeof args[args.length - 1] == "function") + if(typeof args[args.length - 1] == "function") cb = args.pop(); var req = HTTPBindingClient.makeJSONRequest(methodName, args, cb); @@ -139,13 +134,18 @@ HTTPBindingClient.prototype.createApplyMethod = function() { return fn; }; +/** + * JSON-RPC request counter. + */ +HTTPBindingClient.jsonrpcID = 1; + /** * Make a JSON-RPC request. */ HTTPBindingClient.makeJSONRequest = function(methodName, args, cb) { var req = {}; req.id = HTTPBindingClient.jsonrpcID++; - if (cb) + if(cb) req.cb = cb; var obj = {}; obj.id = req.id; @@ -164,8 +164,8 @@ HTTPBindingClient.jsonResult = function(http) { try { var contentType = http.getResponseHeader("Content-Type"); var parts = contentType.split(/\s*;\s*/); - for (var i = 0; i < parts.length; i++) { - if (parts[i].substring(0, 8) == "charset=") + for(var i = 0; i < parts.length; i++) { + if(parts[i].substring(0, 8) == "charset=") return parts[i].substring(8, parts[i].length); } } catch (e) {} @@ -183,49 +183,204 @@ HTTPBindingClient.jsonResult = function(http) { return res; }; +/** + * Schedule async requests, and limit to 4 concurrent running requests. + */ +HTTPBindingClient.queuedRequests = new Array(); +HTTPBindingClient.runningRequests = 0; +HTTPBindingClient.scheduleAsyncRequest = function(f) { + // Queue the request function + HTTPBindingClient.queuedRequests.push(f); + + // 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) + return true; + + // Run the first request in the queue + var req = HTTPBindingClient.queuedRequests.shift(); + HTTPBindingClient.runningRequests++; + setTimeout(function runAsyncRequest() { + try { + return req(function asyncRequestDone() { + // Execute any requests left in the queue + HTTPBindingClient.runningRequests--; + runAsyncRequests(); + return true; + }); + } catch(e) { + // Execute any requests left in the queue + HTTPBindingClient.runningRequests--; + runAsyncRequests(); + } + }, 0); + + // Execute any requests left in the queue + runAsyncRequests(); + })(); + return true; +}; + +/** + * Get a cache item from local storage. + */ +HTTPBindingClient.getCacheItem = function(k) { + var ls = lstorage || localStorage; + return ls.getItem('cache.d.' + k); +}; + +/** + * Set a cache item in local storage. + */ +HTTPBindingClient.setCacheItem = function(k, v) { + HTTPBindingClient.collectCacheItems(); + var ls = lstorage || localStorage; + try { + var s = ls.getItem('cache.size'); + var size = parseInt(s); + var ov = ls.getItem('cache.d.' + k); + var nsize = size - (ov != null? ov.length : 0) + (v != null? v.length : 0); + if (nsize != size) + ls.setItem('cache.size', nsize.toString()); + } catch(e) {} + return ls.setItem('cache.d.' + k, v); +}; + +/** +* Remove a cache item from local storage. +*/ +HTTPBindingClient.removeCacheItem = function(k) { + var ls = lstorage || localStorage; + try { + var s = ls.getItem('cache.size'); + var size = parseInt(s); + var ov = ls.getItem('cache.d' + k); + if (ov != null) { + var nsize = size - ov.length; + ls.setItem('cache.size', nsize.toString()); + } + } catch(e) {} + return ls.removeItem('cache.d.' + k); +}; + +/** + * Keep local storage cache entries under 2MB. + */ +HTTPBindingClient.maxCacheSize = /* 20000; */ 2097152; +HTTPBindingClient.collectCacheSize = /* 10000; */ 1048576; +HTTPBindingClient.collectCacheItems = function() { + var ls = window.lstorage || localStorage; + var nkeys = window.lstorage? function() { return ls.length(); } : function() { return ls.length; }; + try { + // Get the current cache size + var size = 0; + var s = ls.getItem('cache.size'); + if(s == null) { + // Calculate and store initial cache size + //debug('calculating cache size'); + var n = nkeys(); + for(var i = 0; i < n; i++) { + var k = ls.key(i); + if(k == null || k.substr(0, 8) != 'cache.d.') + continue; + var v = ls.getItem(k); + if(v == null) + continue; + size += v.length; + } + ls.setItem('cache.size', size.toString()); + } else + size = parseInt(s); + + // Nothing to do if it's below the max size + //debug('cache.size', size); + if (size <= HTTPBindingClient.maxCacheSize) + return false; + + // Collect random cache entries until we reach our min size + //debug('collecting cache items'); + var keys = new Array(); + var n = nkeys(); + for(var i = 0; i < n; i++) { + var k = ls.key(i); + if(k == null || k.substr(0, 8) != 'cache.d.') + continue; + keys.push(k); + } + while (keys.length != 0 && size >= HTTPBindingClient.collectCacheSize) { + var r = Math.floor(keys.length * Math.random()); + if (r == keys.length) + continue; + var k = keys[r]; + var v = ls.getItem(k); + //debug('collect cache item', k); + ls.removeItem(k); + keys.splice(r, 1); + if (v != null) + size = size - v.length; + } + + // Store the new cache size + //debug('updated cache.size', size); + ls.setItem('cache.size', size.toString()); + return true; + } catch(e) {} + return false; +}; + /** * Apply a function remotely using JSON-RPC. */ HTTPBindingClient.prototype.jsonApply = function(req) { - // Connect to the service - var http = HTTPBindingClient.getHTTPRequest(); var hascb = req.cb? true : false; - http.open("POST", this.uri, hascb); - http.setRequestHeader("Accept", "*/*"); - http.setRequestHeader("Content-Type", "application/json-rpc"); - // Construct call back if we have one + // Call asynchronously with a callback if(hascb) { - http.onreadystatechange = function() { - if(http.readyState == 4) { - // Pass the result or exception - if(http.status == 200) { - var res = null; - try { - res = HTTPBindingClient.jsonResult(http); + var u = this.uri; + return HTTPBindingClient.scheduleAsyncRequest(function jsonApplyRequest(done) { + var http = new XMLHttpRequest(); + http.open("POST", u, true); + http.setRequestHeader("Accept", "*/*"); + http.setRequestHeader("Content-Type", "application/json-rpc"); + http.onreadystatechange = function() { + if(http.readyState == 4) { + // Pass the result or exception + if(http.status == 200) { + var res = null; try { - req.cb(res); - } catch(cbe) {} - } catch(e) { + res = HTTPBindingClient.jsonResult(http); + try { + req.cb(res); + } catch(cbe) {} + } catch(e) { + try { + req.cb(null, e); + } catch(cbe) {} + } + } else { try { - req.cb(null, e); + req.cb(null, HTTPBindingClient.Exception(http.status, http.statusText)); } catch(cbe) {} } - } else - try { - req.cb(null, HTTPBindingClient.Exception(http.status, http.statusText)); - } catch(cbe) {} - } - }; + return done(); + } + }; - // Send the request - http.send(req.data); - return req.id; + // Send the request + http.send(req.data); + return req.id; + }); } - // Send the request and return the result or exception + // Call synchronously and return the result or exception + var http = new XMLHttpRequest(); + http.open("POST", this.uri, false); + http.setRequestHeader("Accept", "*/*"); + http.setRequestHeader("Content-Type", "application/json-rpc"); http.send(req.data); - if (http.status == 200) + if(http.status == 200) return HTTPBindingClient.jsonResult(http); throw new HTTPBindingClient.Exception(http.status, http.statusText); }; @@ -234,95 +389,104 @@ HTTPBindingClient.prototype.jsonApply = function(req) { /** * REST GET method. */ -HTTPBindingClient.prototype.get = function(id, cb) { +HTTPBindingClient.prototype.get = function(id, cb, mode) { var u = id? (this.uri? this.uri + '/' + id : id) : this.uri; var hascb = cb? true : false; // Get from local storage first - var ls = window.lstorage || localStorage; var item = null; - try { item = ls.getItem(u); } catch(e) {} - //log('localStorage.getItem', u, item); - if (item != null && item != '') { - if (!hascb) - return item; - - // Pass local result to callback - try { - cb(item); - } catch (cbe) {} + if(mode != 'remote') { + item = HTTPBindingClient.getCacheItem(u); + if(item != null && item != '') { + if(!hascb) + return item; + + // Pass local result to callback + try { + cb(item); + } catch (cbe) {} + } } - // Connect to the service - var http = HTTPBindingClient.getHTTPRequest(); - http.open("GET", u, hascb); - http.setRequestHeader("Accept", "*/*"); - - // Construct call back if we have one - if (hascb) { - http.onreadystatechange = function() { - //log('readystate', http.readyState, 'status', http.status, 'headers', http.getAllResponseHeaders()); - if (http.readyState == 4) { - // Pass result if different from local result - if (http.status == 200) { - - if (http.getResponseHeader("X-Login") != null) { - // Detect redirect to a login page - try { - var le = new HTTPBindingClient.Exception(403, 'X-Login'); - if (window.onloginredirect) - window.onloginredirect(le); - return cb(null, le); - } catch(cbe) {} + // Call asynchronously with a callback + if(hascb) { + return HTTPBindingClient.scheduleAsyncRequest(function getRequest(done) { + var http = new XMLHttpRequest(); + http.open("GET", u, true); + http.setRequestHeader("Accept", "*/*"); + http.onreadystatechange = function() { + //debug('readystate', http.readyState, 'status', http.status, 'headers', http.getAllResponseHeaders()); + if(http.readyState == 4) { + // Pass result if different from local result + if(http.status == 200) { + var xl = http.getResponseHeader("X-Login"); + if(xl != null && xl != '') { + // Detect redirect to a login page + try { + var le = new HTTPBindingClient.Exception(403, 'X-Login'); + if(window.onloginredirect) + window.onloginredirect(le); + cb(null, le); + return done(); + } catch(cbe) {} - } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { - // Report empty response - try { - return cb(null, new HTTPBindingClient.Exception(403, 'No-Content')); - } catch(cbe) {} + } + var ct = http.getResponseHeader("Content-Type"); + if(http.responseText == '' || ct == null || ct == '') { + // Report empty response + try { + cb(null, new HTTPBindingClient.Exception(403, 'No-Content')); + return done(); + } catch(cbe) {} - } else { - if (item == null || http.responseText != item) { - // Store retrieved entry in local storage - if (http.responseText != null) { - //log('localStorage.setItem', u, http.responseText); - try { ls.setItem(u, http.responseText); } catch(e) {} + } else { + if(item == null || http.responseText != item) { + // Store retrieved entry in local storage + if(http.responseText != null) + HTTPBindingClient.setCacheItem(u, http.responseText); + try { + cb(http.responseText); + return done(); + } catch(cbe) {} } + } + } + else { + // Pass exception if we didn't have a local result + if(item == null) { try { - return cb(http.responseText); + cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); + return done(); } catch(cbe) {} } } + return done(); } - else { - // Pass exception if we didn't have a local result - if (item == null) { - try { - return cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); - } catch(cbe) {} - } - } - } - }; + }; - // Send the request - http.send(null); - return true; + // Send the request + http.send(null); + return true; + }); } - // Send the request and return the result or exception + // Call synchronously and return the result or exception + var http = new XMLHttpRequest(); + http.open("GET", u, false); + http.setRequestHeader("Accept", "*/*"); http.send(null); - if (http.status == 200) { - if (http.getResponseHeader("X-Login") != null) { - + if(http.status == 200) { + var xl = http.getResponseHeader("X-Login"); + if(xl != null && xl != '') { // Detect redirect to a login page var le = new HTTPBindingClient.Exception(403, 'X-Login'); - if (window.onloginredirect) + if(window.onloginredirect) window.onloginredirect(le); throw le; - } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { - + } + var ct = http.getResponseHeader("Content-Type"); + if(http.responseText == '' || ct == null || ct == '') { // Report empty response throw new HTTPBindingClient.Exception(403, 'No-Content'); } @@ -332,207 +496,187 @@ HTTPBindingClient.prototype.get = function(id, cb) { }; /** - * REST GET method, does not use the local cache. + * REST POST method. */ -HTTPBindingClient.prototype.getnocache = function(id, cb) { - var u = id? (this.uri? this.uri + '/' + id : id) : this.uri; +HTTPBindingClient.prototype.post = function (entry, cb) { var hascb = cb? true : false; - // Connect to the service - var http = HTTPBindingClient.getHTTPRequest(); - http.open("GET", u, hascb); - http.setRequestHeader("Accept", "*/*"); - - // Construct call back if we have one - if (hascb) { - http.onreadystatechange = function() { - if (http.readyState == 4) { - if (http.status == 200) { - - if (http.getResponseHeader("X-Login") != null) { - // Detect redirect to a login page - try { - var le = new HTTPBindingClient.Exception(403, 'X-Login'); - if (window.onloginredirect) - window.onloginredirect(le); - return cb(null, le); - } catch(cbe) {} - - } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { - // Report empty response + // Call asynchronously with a callback + if(hascb) { + var u = this.uri; + return HTTPBindingClient.scheduleAsyncRequest(function postRequest(done) { + var http = new XMLHttpRequest(); + http.open("POST", u, true); + http.setRequestHeader("Accept", "*/*"); + http.setRequestHeader("Content-Type", "application/atom+xml"); + http.onreadystatechange = function() { + if(http.readyState == 4) { + if(http.status == 201) { + // Successful result try { - return cb(null, new HTTPBindingClient.Exception(403, 'No-Content')); + cb(http.responseText); } catch(cbe) {} - - } else { + } + else { + // Report status code as an exception try { - return cb(http.responseText); + cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); } catch(cbe) {} } - } else { - try { - return cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); - } catch(cbe) {} + return done(); } - } - }; - - // Send the request - http.send(null); - return true; - } - - // Send the request and return the result or exception - http.send(null); - if (http.status == 200) { - if (http.getResponseHeader("X-Login") != null) { - - // Detect redirect to a login page - var le = new HTTPBindingClient.Exception(403, 'X-Login'); - if (window.onloginredirect) - window.onloginredirect(le); - throw le; - - } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { - - // Report empty response - throw new HTTPBindingClient.Exception(403, 'No-Content'); - } - return http.responseText; + }; + // Send the request + http.send(entry); + return true; + }); } - throw new HTTPBindingClient.Exception(http.status, http.statusText); -}; -/** - * REST POST method. - */ -HTTPBindingClient.prototype.post = function (entry, cb) { - - // Connect to the service - var http = HTTPBindingClient.getHTTPRequest(); + // Call synchronously + var http = new XMLHttpRequest(); var hascb = cb? true : false; - http.open("POST", this.uri, hascb); + http.open("POST", this.uri, false); http.setRequestHeader("Accept", "*/*"); http.setRequestHeader("Content-Type", "application/atom+xml"); - - // Construct call back if we have one - if (hascb) { - http.onreadystatechange = function() { - // Pass the result or exception - if (http.readyState == 4) { - if (http.status == 201) { - try { - cb(http.responseText); - } catch(cbe) {} - } - else { - try { - cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); - } catch(cbe) {} - } - } - }; - // Send the request - http.send(entry); - return true; - } - - // Send the request and return the result or exception http.send(entry); - if (http.status == 201) + if(http.status == 201) return http.responseText; + + // Return status code as an exception throw new HTTPBindingClient.Exception(http.status, http.statusText); }; /** * REST PUT method. */ -HTTPBindingClient.prototype.put = function (id, entry, cb) { - var u = this.uri + '/' + id; +HTTPBindingClient.prototype.put = function(id, entry, cb, mode) { + var u = id? (this.uri? this.uri + '/' + id : id) : this.uri; + var hascb = cb? true : false; // Update local storage - var ls = window.lstorage || localStorage; - try { ls.setItem(u, entry); } catch(e) {} - //log('localStorage.setItem', u, entry); + var oentry = null; + if(mode != 'remote') { + oentry = HTTPBindingClient.getCacheItem(u); + HTTPBindingClient.setCacheItem(u, entry); + } - // Connect to the service - var http = HTTPBindingClient.getHTTPRequest(); - var hascb = cb? true : false; - http.open("PUT", u, hascb); - http.setRequestHeader("Accept", "*/*"); - http.setRequestHeader("Content-Type", "application/atom+xml"); + // Call asynchronously with a callback + if(hascb) { + return HTTPBindingClient.scheduleAsyncRequest(function putRequest(done) { + var http = new XMLHttpRequest(); + http.open("PUT", u, true); + http.setRequestHeader("Accept", "*/*"); + http.setRequestHeader("Content-Type", "application/atom+xml"); + http.onreadystatechange = function() { + if(http.readyState == 4) { + if(http.status == 200) { + // Successful result + try { + cb(); + } catch(cbe) {} + } else { + if(http.status == 404) { + // Undo local storage update + if(mode != 'remote') { + try { + if(oentry != null) + HTTPBindingClient.setCacheItem(u, oentry); + else + HTTPBindingClient.removeCacheItem(u); + } catch(e) {} + } + } - // Construct call back if we have one - if (hascb) { - http.onreadystatechange = function() { - if (http.readyState == 4) { - // Pass any exception - if (http.status == 200) { - try { - cb(); - } catch(cbe) {} - } else { - try { - cb(new HTTPBindingClient.Exception(http.status, http.statusText)); - } catch(cbe) {} + // Report status code as an exception + try { + cb(new HTTPBindingClient.Exception(http.status, http.statusText)); + } catch(cbe) {} + } + return done(); } - } - }; - // Send the request - http.send(entry); - return true; + }; + + // Send the request + http.send(entry); + return true; + }); } - // Send the request and return any exception + // Call synchronously + var http = new XMLHttpRequest(); + http.open("PUT", u, false); + http.setRequestHeader("Accept", "*/*"); + http.setRequestHeader("Content-Type", "application/atom+xml"); http.send(entry); - if (http.status == 200) + if(http.status == 200) return true; + if(http.status == 404) { + // Undo local storage update + if(mode != 'remote') { + try { + if(oentry != null) + HTTPBindingClient.setCacheItem(u, oentry); + else + HTTPBindingClient.removeCacheItem(u); + } catch(e) {} + } + } + + // Return status code as an exception throw new HTTPBindingClient.Exception(http.status, http.statusText); }; /** * REST DELETE method. */ -HTTPBindingClient.prototype.del = function (id, cb) { - var u = this.uri + '/' + id; +HTTPBindingClient.prototype.del = function(id, cb, mode) { + var u = id? (this.uri? this.uri + '/' + id : id) : this.uri; + var hascb = cb? true : false; // Update local storage var ls = window.lstorage || localStorage; - try { ls.removeItem(u); } catch(e) {} - //log('localStorage.removeItem', u); - - // Connect to the service - var http = HTTPBindingClient.getHTTPRequest(); - var hascb = cb? true : false; - http.open("DELETE", u, hascb); - http.setRequestHeader("Accept", "*/*"); + if(mode != 'remote') + HTTPBindingClient.removeCacheItem(u); - // Construct call back if we have one - if (cb) { - http.onreadystatechange = function() { - if (http.readyState == 4) { - // Pass any exception - if (http.status == 200) { - try { - cb(); - } catch(cbe) {} - } - else { - try { - cb(new HTTPBindingClient.Exception(http.status, http.statusText)); - } catch(cbe) {} + // Call asynchronously with a callback + if(hascb) { + return HTTPBindingClient.scheduleAsyncRequest(function delRequest(done) { + var http = new XMLHttpRequest(); + http.open("DELETE", u, true); + http.setRequestHeader("Accept", "*/*"); + http.onreadystatechange = function() { + if(http.readyState == 4) { + if(http.status == 200) { + // Successful result + try { + cb(); + } catch(cbe) {} + } + else { + // Report status code as an exception + try { + cb(new HTTPBindingClient.Exception(http.status, http.statusText)); + } catch(cbe) {} + } + return done(); } - } - }; - // Send the request - http.send(null); - return true; + }; + + // Send the request + http.send(null); + return true; + }); } - // Send the request and return any exception + // Call synchronously + var http = new XMLHttpRequest(); + http.open("DELETE", u, false); + http.setRequestHeader("Accept", "*/*"); http.send(null); - if (http.status == 200) + if(http.status == 200) return true; + + // Report status code as an exception throw new HTTPBindingClient.Exception(http.status, http.statusText); }; @@ -551,38 +695,6 @@ HTTPBindingClient.Exception.prototype.toString = function() { return this.name + ": " + this.message; }; -/** - * XMLHttpRequest wrapper. - */ -HTTPBindingClient.msxmlNames = [ "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" ]; - -HTTPBindingClient.getHTTPRequest = function() { - if (HTTPBindingClient.httpFactory) - return HTTPBindingClient.httpFactory(); - - // Mozilla XMLHttpRequest - try { - HTTPBindingClient.httpFactory = function() { - return new XMLHttpRequest(); - }; - return HTTPBindingClient.httpFactory(); - } catch(e) {} - - // Microsoft MSXML ActiveX - for (var i = 0; i < HTTPBindingClient.msxmlNames.length; i++) { - try { - HTTPBindingClient.httpFactory = function() { - return new ActiveXObject(HTTPBindingClient.msxmlNames[i]); - }; - return HTTPBindingClient.httpFactory(); - } catch (e) {} - } - - // Can't create XMLHttpRequest - HTTPBindingClient.httpFactory = null; - throw new HTTPBindingClient.Exception(0, "Can't create XMLHttpRequest object"); -}; - /** * Public API. */ @@ -600,7 +712,7 @@ sca.httpclient = function(name, uri, domain) { * Return a component proxy. */ sca.component = function(name, domain) { - if (!domain) + if(!domain) return new HTTPBindingClient(name, '/c/' + name, domain); return new HTTPBindingClient(name, '/' + domain + '/c/' + name, domain); }; @@ -609,7 +721,7 @@ sca.component = function(name, domain) { * Return a reference proxy. */ sca.reference = function(comp, rname) { - if (!comp.domain) + if(!comp.domain) return new HTTPBindingClient(comp.name + '/' + rname, '/r/' + comp.name + '/' + rname, comp.domain); return new HTTPBindingClient(comp.name + '/' + rname, '/' + comp.domain + '/r/' + comp.name + '/' + rname, comp.domain); }; @@ -622,13 +734,13 @@ sca.defun = function(ref) { return function() { var args = new Array(); args[0] = name; - for (i = 0, n = arguments.length; i < n; i++) + for(i = 0, n = arguments.length; i < n; i++) args[i + 1] = arguments[i]; return this.apply.apply(this, args); }; } - for (f = 1; f < arguments.length; f++) { + for(f = 1; f < arguments.length; f++) { var fn = arguments[f]; ref[fn]= defapply(fn); } diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.css b/sca-cpp/trunk/modules/js/htdocs/ui.css index ddc21b2095..cdc9e31aef 100644 --- a/sca-cpp/trunk/modules/js/htdocs/ui.css +++ b/sca-cpp/trunk/modules/js/htdocs/ui.css @@ -17,10 +17,14 @@ * under the License. */ -body { +/** + * Main body. + */ +body, .body { margin-top: 0px; margin-bottom: 2px; margin-left: 2px; margin-right: 2px; -font-family: Arial; font-style: normal; font-variant: normal; font-size: 14px; +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 14px; background-color: #ffffff; opacity: 1; +-webkit-font-smoothing: subpixel-antialiased; -webkit-text-size-adjust: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: rgba(0,0,0,0); @@ -30,35 +34,33 @@ cursor: default; } .delayed { -visibility: hidden; -} - -.fixed { -position: fixed; +display: none; } -.devicewidth { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +.installer { +position: relative; width: 0px; height: 0px; display: none; visibility: hidden; background: transparent; } -.mainbody { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; --webkit-backface-visibility: hidden; +.filler { +position: relative; left: 0px; top: 0px; width: 1px; background: transparent; z-index: -20; } +/** + * Main view. + */ .viewcontainer3dm { -position: absolute; left: 0px; top: 35px; width: 100%; +position: fixed; left: 0px; top: 70px; right: 0px; bottom: 25px; padding-top: 2px; padding-bottom: 2px; -webkit-backface-visibility: hidden; } .viewcontainer3d { -position: absolute; left: 0px; top: 35px; width: 100%; +position: fixed; left: 0px; top: 70px; right: 0px; bottom: 25px; padding-top: 2px; padding-bottom: 2px; -webkit-backface-visibility: hidden; } .leftviewloading3dm { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; -z-index: -10; background-color: #ffffff; +position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; +z-index: -5; background-color: #ffffff; -webkit-transform: translate(100%, 0px); -moz-transform: translate(100%, 0px); -ms-transform: translate(100%, 0px); @@ -68,8 +70,8 @@ transform: translate(100%, 0px); } .rightviewloading3dm { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; -z-index: -10; background-color: #ffffff; +position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; +z-index: -5; background-color: #ffffff; -webkit-transform: translate(-100%, 0px); -moz-transform: translate(-100%, 0px); -ms-transform: translate(-100%, 0px); @@ -79,8 +81,8 @@ transform: translate(-100%, 0px); } .viewloading3d { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; -visibility: hidden; z-index: -10; background-color: #ffffff; +position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; +z-index: -5; background-color: #ffffff; -webkit-transform: translate(100%, 0px); -moz-transform: translate(100%, 0px); -ms-transform: translate(100%, 0px); @@ -90,7 +92,7 @@ transform: translate(100%, 0px); } .viewloaded3dm { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; z-index: 0; background-color: #ffffff; -webkit-transition: -webkit-transform 0.4s ease-in-out; -moz-transition: -moz-transform 0.4s ease-in-out; @@ -106,7 +108,7 @@ transform: translate(0px, 0px); } .viewloaded3d { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; z-index: 0; background-color: #ffffff; -webkit-transform: translate(0px, 0px); -moz-transform: translate(0px, 0px); @@ -117,8 +119,8 @@ transform: translate(0px, 0px); } .viewunloading3dm { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; -z-index: 0; background-color: #ffffff; +position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; +z-index: -10; background-color: #ffffff; -webkit-transform: translate(0px, 0px); -moz-transform: translate(0px, 0px); -ms-transform: translate(0px, 0px); @@ -128,7 +130,7 @@ transform: translate(0px, 0px); } .leftviewunloaded3dm { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; z-index: -10; background-color: #ffffff; -webkit-transition: -webkit-transform 0.4s ease-in-out; -moz-transition: -moz-transform 0.4s ease-in-out; @@ -144,7 +146,7 @@ transform: translate(-100%, 0px); } .rightviewunloaded3dm { -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; z-index: -10; background-color: #ffffff; -webkit-transition: -webkit-transform 0.4s ease-in-out; -moz-transition: -moz-transform 0.4s ease-in-out; @@ -159,44 +161,109 @@ transform: translate(100%, 0px); -webkit-backface-visibility: hidden; } -.body { -width: 100%; height: 5000px; overflow: visible; +.viewunloaded3d { +position: absolute; left: 0px; top: 0px; right: 0px; bottom: 0px; +z-index: -10; background-color: #ffffff; +-webkit-transform: translate(-100%, 0px); +-moz-transform: translate(-100%, 0px); +-ms-transform: translate(-100%, 0px); +-o-transform: translate(-100%, 0px); +transform: translate(-100%, 0px); +-webkit-backface-visibility: hidden; +} + +.viewcontent { +position: absolute; left: 0px; top: 2px; right: 0px; bottom: 0px; +overflow-x: hidden; overflow-y: scroll; -webkit-overflow-scrolling: touch; -webkit-backface-visibility: hidden; } -.viewhead { -position: absolute; left: 0px; top: 35px; height: 35px; line-height: 35px; width: 100%; z-index: 8; -font-size: 110%; font-weight: bold; background-color: #f1f1f1; color: #000000; -border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; -border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; -overflow: hidden; +.viewform { +position: absolute; left: 0px; top: 2px; right: 0px; bottom: 0px; +overflow-x: hidden; overflow-y: scroll; -webkit-overflow-scrolling: touch; -webkit-backface-visibility: hidden; } -.viewheadbackground { -position: absolute; left: 0px; top: 35px; height: 35px; line-height: 35px; width: 2500px; z-index: 7; -background-color: #f1f1f1; +/** + * View header and footer. + */ +.viewhead { +position: fixed; left: 0px; top: 35px; height: 35px; line-height: 35px; width: 100%; z-index: 8; +font-size: 15px; font-weight: bold; background-color: #f5f5f5; color: #000000; border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; -overflow: hidden; -webkit-backface-visibility: hidden; } .viewfoot { -position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 8; +position: fixed; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 8; font-size: 12px; background-color: #ffffff; color: #404040; border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; -overflow: hidden; -webkit-backface-visibility: hidden; } -.status { -position: absolute; left: 0px; bottom: 0px; height: 35px; line-height: 35px; width: 100%; z-index: 9; -font-size: 12px; background-color: #ffffff; color: #404040; +.note { +font-size: 12px; color: #808080; +text-transform: none; +} + +/** + * Menu toolbar. + */ +.tbarmenu { +position: fixed; top: 0px; left: 0px; z-index: 10; width: 100%; margin: 0px; padding: 0px; border-collapse: separate; +height: 35px; line-height: 35px; background-color: #2c2c2c; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #2c2c2c; border-bottom-color: #2c2c2c; +-webkit-backface-visibility: hidden; +} + +.tbarleft { +padding-left: 2px; padding-right: 6px; white-space: nowrap; float: left; +text-transform: uppercase; +} + +.tbarright { +padding-left: 6px; padding-right: 2px; white-space: nowrap; float: right; +} + +.tbaramenu { +font-size: 15px; color: #cccccc; text-decoration: none; white-space: nowrap; +} + +.tbarsmenu { +font-size: 15px; font-weight: bold; color: #ffffff; text-decoration: none; white-space: nowrap; +} + +.amenu { +padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #808080; text-decoration: none; float: left; +} + +.smenu { +padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; float: left; +} + +.cmenu { +font-size: 15px; padding-left: 6px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; float: left; +padding-left: 45px; +} + +.bcmenu { +font-size: 22px; padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; +} + +.rmenu { +padding-left: 2px; padding-right: 2px; white-space: nowrap; white-space: nowrap; float: right; +} + +/** + * Status bar. + */ +.status3d { +position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 9; +background-color: #ffffff; color: #404040; border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; -overflow: hidden; -webkit-transform: translate(0px, 0px); -moz-transform: translate(0px, 0px); -ms-transform: translate(0px, 0px); @@ -205,232 +272,244 @@ transform: translate(0px, 0px); -webkit-backface-visibility: hidden; } -.statusout3 { -position: absolute; left: 0px; bottom: 0px; height: 35px; line-height: 35px; width: 100%; z-index: 9; -font-size: 12px; background-color: #ffffff; color: #404040; +.statusout3d { +position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 9; +background-color: #ffffff; color: #404040; border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; -overflow: hidden; --webkit-transition: -webkit-transform 0.4s ease-in-out 3s; --moz-transition: -moz-transform 0.4s ease-in-out 3s; --ms-transition: -ms-transform 0.4s ease-in-out 3s; --o-transition: -o-transform 0.4s ease-in-out 3s; -transition: transform 0.4s ease-in-out 3s; --webkit-transform: translate(0px, 35px); --moz-transform: translate(0px, 35px); --ms-transform: translate(0px, 35px); --o-transform: translate(0px, 35px); -transform: translate(0px, 35px); --webkit-backface-visibility: hidden; -} - -.statusout1 { -position: absolute; left: 0px; bottom: 0px; height: 35px; line-height: 35px; width: 100%; z-index: 9; -font-size: 12px; background-color: #ffffff; color: #404040; +-webkit-transition: -webkit-transform 0.4s ease-in-out; +-moz-transition: -moz-transform 0.4s ease-in-out; +-ms-transition: -ms-transform 0.4s ease-in-out; +-o-transition: -o-transform 0.4s ease-in-out; +transition: transform 0.4s ease-in-out; +-webkit-transform: translate(0px, 25px); +-moz-transform: translate(0px, 25px); +-ms-transform: translate(0px, 25px); +-o-transform: translate(0px, 25px); +transform: translate(0px, 25px); +-webkit-backface-visibility: hidden; +} + +.status3dm { +position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 9; +background-color: #ffffff; color: #404040; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; +border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; +-webkit-transform: translate(0px, 0px); +-moz-transform: translate(0px, 0px); +-ms-transform: translate(0px, 0px); +-o-transform: translate(0px, 0px); +transform: translate(0px, 0px); +-webkit-backface-visibility: hidden; +} + +.statusout3dm { +position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 9; +background-color: #ffffff; color: #404040; border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; -overflow: hidden; --webkit-transition: -webkit-transform 0.4s ease-in-out 1s; --moz-transition: -moz-transform 0.4s ease-in-out 1s; --ms-transition: -ms-transform 0.4s ease-in-out 1s; --o-transition: -o-transform 0.4s ease-in-out 1s; -transition: transform 0.4s ease-in-out 1s; --webkit-transform: translate(0px, 35px); --moz-transform: translate(0px, 35px); --ms-transform: translate(0px, 35px); --o-transform: translate(0px, 35px); -transform: translate(0px, 35px); +-webkit-transition: -webkit-transform 0.4s ease-in-out; +-moz-transition: -moz-transform 0.4s ease-in-out; +-ms-transition: -ms-transform 0.4s ease-in-out; +-o-transition: -o-transform 0.4s ease-in-out; +transition: transform 0.4s ease-in-out; +-webkit-transform: translate(0px, 25px); +-moz-transform: translate(0px, 25px); +-ms-transform: translate(0px, 25px); +-o-transform: translate(0px, 25px); +transform: translate(0px, 25px); -webkit-backface-visibility: hidden; } .okstatus { -font-size: 110%; font-weight: bold; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none; -background-color: #f1f1f1; color: #000000; +font-size: 14px; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none; +background-color: #f5f5f5; color: #000000; width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right; } .errorstatus { -font-size: 110%; font-weight: bold; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none; +font-size: 14px; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none; background-color: #d14836; color: #ffffff; width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right; } -.viewfootbackground { -position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 2500px; z-index: 7; -background-color: #ffffff; -border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; -border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; -overflow: hidden; --webkit-backface-visibility: hidden; -} - -.viewcontent { -position: absolute; left: 0px; top: 38px; width: 100%; --webkit-backface-visibility: hidden; +/** + * Working status animation. + */ +.working { +position: fixed; z-index: 15; display: none; width: 60px; height: 60px; left: 50%; top: 50%; border-bottom-color: transparent; +margin: -50px 0 0 -50px; border: 20px solid #c0c0c0; border-right-color: transparent; +border-radius: 50%; -webkit-border-radius: 50%; -moz-border-radius: 50%; +-webkit-box-shadow: 0 0 45px 5px #f5f5f5; -moz-box-shadow: 0 0 45px 5px #f5f5f5; -ms-box-shadow: 0 0 45px 5px #f5f5f5; +-o-box-shadow: 0 0 45px 5px #f5f5f5; box-shadow: 0 0 45px 5px #f5f5f5; +-webkit-animation: spin 1s linear infinite; +-moz-animation: spin 1s linear infinite; +-ms-animation: spin 1s linear infinite; +-o-animation: spin 1s linear infinite; +animation: spin 1s linear infinite; } -.viewform { -position: absolute; left: 0px; top: 40px; width: 100%; +@-webkit-keyframes spin { +from { -webkit-transform: rotate(0deg); opacity: 0.4; } +50% { -webkit-transform: rotate(180deg); opacity: 1; } +to { -webkit-transform: rotate(360deg); opacity: 0.4; } } -table { -border: 0px; border-collapse: collapse; border-color: #a2bae7; border-style: solid; -font-family: Arial; font-style: normal; font-variant: normal; font-size: 14px; -overflow: visible; +@-moz-keyframes spin { +from { -moz-transform: rotate(0deg); opacity: 0.4; } +50% { -moz-transform: rotate(180deg); opacity: 1; } +to { -moz-transform: rotate(360deg); opacity: 0.4; } } -.trb { -border-bottom: 1px; border-bottom-style: solid; border-color: #dcdcdc; +@-ms-keyframes spin { +from { -ms-transform: rotate(0deg); opacity: 0.4; } +50% { -ms-transform: rotate(180deg); opacity: 1; } +to { -ms-transform: rotate(360deg); opacity: 0.4; } } -th { -font-size: 110%; font-weight: bold; background-color: #f1f1f1; color: #000000; -text-align: left; padding-left: 2px; padding-right: 8px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; white-space: nowrap; -border-top: 1px; border-bottom: 1px; border-left: 1px; border-right: 1px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; border-left-color: #e5e5e5; border-right-color: #e5e5e5; -overflow: hidden; +@-o-keyframes spin { +from { -o-transform: rotate(0deg); opacity: 0.4; } +50% { -o-transform: rotate(180deg); opacity: 1; } +to { -o-transform: rotate(360deg); opacity: 0.4; } } -.section { -font-size: 110%; font-weight: bold; background-color: #f1f1f1; color: #000000; height: 30px; line-height: 30px; -text-align: left; padding-top: 0px; padding-bottom: 0px; padding-left: 2px; padding-right: 2px; white-space: nowrap; -border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; border-left-color: #e5e5e5; border-right-color: #e5e5e5; -overflow: hidden; +@keyframes spin { +from { transform: rotate(0deg); opacity: 0.4; } +50% { transform: rotate(180deg); opacity: 1; } +to { transform: rotate(360deg); opacity: 0.4; } } -.hsection { -width: 100%; height: 0px; visibility: hidden; -border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-bottom-color: #000000; background-color: #ffffff; -padding-left: 2px; padding-right: 2px; padding-top: 0px; padding-bottom: 0px; margin-bottom: 0px; margin-left: auto; margin-right: auto; text-align: center; +/** + * Refreshing status animation. + */ +.refreshing { +z-index: 14; display: none; width: 10px; height: 10px; border-bottom-color: transparent; vertical-align: top; +border: 5px solid #c0c0c0; border-right-color: transparent; +border-radius: 50%; -webkit-border-radius: 50%; -moz-border-radius: 50%; +-webkit-box-shadow: 0 0 10px 5px #f5f5f5; -moz-box-shadow: 0 0 10px 5px #f5f5f5; -ms-box-shadow: 0 0 10px 5px #f5f5f5; +-o-box-shadow: 0 0 10px 5px #f5f5f5; box-shadow: 0 0 10px 5px #f5f5f5; +-webkit-animation: spin 1s linear infinite; +-moz-animation: spin 1s linear infinite; +-ms-animation: spin 1s linear infinite; +-o-animation: spin 1s linear infinite; +animation: spin 1s linear infinite; +} + +/** + * Scrollbars. + */ +.flatscrollbars::-webkit-scrollbar{ +width: 10px; height: 10px; background-color: #ffffff; +box-shadow: inset 1px 1px 0 rgba(0,0,0,.1), inset -1px -1px 0 rgba(0,0,0,.07); } -.fsection{ -width: 100%; height: 0px; visibility: hidden; -border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #a2bae7; -padding: 0px; margin-top: 0px; margin-left: auto; margin-right: auto; text-align: center; +.flatscrollbars::-webkit-scrollbar:hover{ +background-color: #eeeeee; } -.bluetext { -color: #4787ed; +.flatscrollbars::-webkit-resizer{ +-webkit-border-radius: 4px; +background-color: #666666; } -.redtext { -color: #d14836; +.flatscrollbars::-webkit-scrollbar-thumb{ +min-height: 0.8em; min-width: 0.8em; background-color: rgba(0, 0, 0, .2); +box-shadow: inset 1px 1px 0 rgba(0,0,0,.1), inset -1px -1px 0 rgba(0,0,0,.07); } -.mirror { -display: inline-block; --webkit-transform: scaleX(-1); --moz-transform: scaleX(-1); --ms-transform: scaleX(-1); --o-transform: scaleX(-1); -transform: scaleX(-1); +.flatscrollbars::-webkit-scrollbar-thumb:hover{ +background-color: #bbbbbb; } -.greentext { -color: #009900; +.flatscrollbars::-webkit-scrollbar-thumb:active{ +background-color: #888888; } +/** + * Base HTML elements. + */ .text { padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; } -.link { -padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; -} - -.checkbox { -padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; -} - -.thl { -border-left: 0px; -} - -.thr { -border-right: 0px; +.bluetext { +color: #4787ed; } -.ths { -padding: 0px; +.redtext { +color: #d14836; } -td { -padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: nowrap; vertical-align: middle; border: 0px; +.greentext { +color: #3d9400; } -.tdl { -border-right: 1px; border-style: solid; border-color: #a2bae7; width: 10px; +h1 { +font-size: 20px; font-weight: bold; vertical-align: middle; margin-top: 5px; margin-bottom: 5px; margin-left: 2px; margin-right: 2px; white-space: nowrap; } -.tdr { -border-left: 1px; border-style: solid; border-color: #a2bae7; +h2 { +font-size: 18px; font-weight: bold; vertical-align: middle; margin-top: 5px; margin-bottom: 5px; margin-left: 2px; margin-right: 2px; white-space: nowrap; } -.tdw { -padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: normal; vertical-align: middle; +.hw1 { +font-size: 20px; font-weight: bold; vertical-align: middle; margin-top: 5px; margin-bottom: 5px; margin-left: 2px; margin-right: 2px; white-space: normal; } -.datatd { -border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: middle; +.hw2 { +font-size: 18px; font-weight: bold; vertical-align: middle; margin-top: 5px; margin-bottom: 5px; margin-left: 2px; margin-right: 2px; white-space: normal; } -.datatdl { -border-right: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: middle; +.hd1 { +font-size: 20px; font-weight: bold; white-space: nowrap; padding-top: 3px; padding-bottom: 4px; vertical-align: middle; } -.datatdltop { -border-right: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: top; +.hd2 { +font-size: 18px; font-weight: bold; white-space: nowrap; padding-top: 3px; padding-bottom: 4px; vertical-align: middle; } -.datatdr { -border-left: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; vertical-align: middle; +.section { +font-size: 15px; font-weight: bold; background-color: #f5f5f5; color: #000000; height: 30px; line-height: 30px; width: 100%; display: block; +text-align: left; padding-top: 0px; padding-bottom: 0px; padding-left: 2px; padding-right: 2px; white-space: nowrap; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; border-left-color: #e5e5e5; border-right-color: #e5e5e5; } -.datatable { -border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; -overflow: visible; +.link { +padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; } -.databg { -opacity: .6; --ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; -filter: alpha(opacity=60); +a:link { +color: #357ae8; text-decoration: none; white-space: nowrap; cursor: pointer; } -.guide { -border: 1px; border-style: solid; border-color: #c0c0c0; +a:visited { +color: #357ae8; text-decoration: none; white-space: nowrap; cursor: pointer; } -iframe { -border: 0px; margin: 0px; padding: 0px; +.label{ +font-weight: bold; padding-top: 6px; } -.fakeframe { -padding: 3px; background-color: #dcdcdc; color: #000000; +.lightlabel{ +font-weight: normal; color: #808080; padding-top: 6px; } input { +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 15px; vertical-align: middle; -font-family: Arial; font-style: normal; font-variant: normal; font-size: 15px; -outline: none; --webkit-text-size-adjust: 100%; -} - -button { -vertical-align: middle; -font-family: Arial; font-style: normal; font-variant: normal; font-size: 15px; outline: none; -webkit-text-size-adjust: 100%; } textarea { -font-family: Arial; font-style: normal; font-variant: normal; font-size: 15px; +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 15px; outline: none; overflow: auto; resize: none; } .flatentry { -font-family: Arial; font-style: normal; font-variant: normal; font-size: 15px; +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 15px; +vertical-align: middle; -webkit-appearance: none; appearance: none; border: 1px solid #d9d9d9!important; border-top: 1px solid silver!important; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; @@ -438,13 +517,29 @@ border-radius: 1px; -webkit-border-radius: 1px; -moz-border-radius: 1px; margin: 1px!important; padding: 3px 1px 3px 3px; } -.graphentry { -font-family: Arial; font-style: normal; font-variant: normal; font-size: 13px; +.readentry { +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 15px; +vertical-align: middle; color: #808080; -webkit-appearance: none; appearance: none; +border: 0px; +box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; +border-radius: 1px; -webkit-border-radius: 1px; -moz-border-radius: 1px; +margin: 1px!important; padding: 3px 1px 3px 3px; +overflow: hidden; text-overflow: ellipsis; +} + +.searchentry { +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 15px; +vertical-align: middle; +-webkit-appearance: searchfield; -moz-appearance: searchfield; -ms-appearance: searchfield; appearance: searchfield; border: 1px solid #d9d9d9!important; border-top: 1px solid silver!important; box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; border-radius: 1px; -webkit-border-radius: 1px; -moz-border-radius: 1px; -margin: 0px; padding: 0px; +margin: 1px!important; padding: 3px 1px 3px 3px; +} + +.checkbox { +padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; } .flatcheckbox { @@ -459,117 +554,117 @@ outline: none; -moz-outline-style: none; outline: none; -moz-outline-style: none; } -.editablesvg { -background-color: transparent; -font-family: inherit; font-style: inherit; font-variant: inherit; font-size: inherit; font-weight: inherit; -padding: 0px; margin: 0px; -overflow: auto; resize: none; -outline: none; -moz-outline-style: none; --webkit-appearance: none; -webkit-text-size-adjust: 100%; +iframe { +border: 0px; margin: 0px; padding: 0px; +} + +img { border: 0px; } -a:link { -color: #357ae8; text-decoration: none; white-space: nowrap; cursor: pointer; +/** + * Tables. + */ +table { +border: 0px; border-collapse: collapse; border-color: #a2bae7; border-style: solid; +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 14px; } -a:visited { -color: #357ae8; text-decoration: none; white-space: nowrap; cursor: pointer; +.table { +width: 100%; } -.tbarmenu { -position: absolute; top: 0px; left: 0px; z-index: 10; width: 100%; margin: 0px; padding: 0px; border-collapse: separate; -height: 35px; line-height: 35px; background-color: #2c2c2c; -border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #2c2c2c; border-bottom-color: #2c2c2c; --webkit-backface-visibility: hidden; +th { +font-size: 15px; font-weight: bold; background-color: #f5f5f5; color: #000000; +text-align: left; padding-left: 2px; padding-right: 8px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; white-space: nowrap; +border-top: 1px; border-bottom: 1px; border-left: 1px; border-right: 1px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; border-left-color: #e5e5e5; border-right-color: #e5e5e5; } -.tbarbackground { -position: absolute; top: 0px; left: 0px; z-index: 9; width: 2500px; margin: 0px; padding: 0px; border-collapse: separate; -height: 35px; line-height: 35px; background-color: #2c2c2c; -border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #2c2c2c; border-bottom-color: #2c2c2c; -overflow: hidden; --webkit-backface-visibility: hidden; +.thl { +border-left: 0px; } -.tbarleft { -padding-left: 2px; padding-right: 6px; white-space: nowrap; float: left; +.thr { +border-right: 0px; } -.tbarright { -padding-left: 6px; padding-right: 2px; white-space: nowrap; float: right; +.ths { +padding: 0px; } -.tbaramenu { -font-size: 110%; color: #cccccc; text-decoration: none; white-space: nowrap; +td { +padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: nowrap; vertical-align: middle; border: 0px; } -.tbarsmenu { -font-size: 110%; font-weight: bold; color: #ffffff; text-decoration: none; white-space: nowrap; +.tdl { +border-right: 1px; border-style: solid; border-color: #a2bae7; width: 10px; } -.amenu { -padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #808080; text-decoration: none; float: left; +.tdr { +border-left: 1px; border-style: solid; border-color: #a2bae7; } -.smenu { -padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; float: left; +.tdw { +padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: normal; vertical-align: middle; } -.cmenu { -font-size: 18px; padding-left: 6px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; -width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right; +.datatd { +border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: middle; } -.bcmenu { -font-size: 22px; padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; +.datatdl { +border-right: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: middle; } -.rmenu { -padding-left: 2px; padding-right: 2px; white-space: nowrap; white-space: nowrap; float: right; +.datatdltop { +border-right: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: top; } -h1 { -font-size: 150%; font-weight: bold; vertical-align: middle; margin-top: 5px; margin-bottom: 5px; margin-left: 2px; margin-right: 2px; white-space: nowrap; +.datatdr { +border-left: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; vertical-align: middle; } -h2 { -font-size: 120%; font-weight: bold; vertical-align: middle; margin-top: 5px; margin-bottom: 5px; margin-left: 2px; margin-right: 2px; white-space: nowrap; +.list { +width: 100%; } -.hd1 { -font-size: 150%; font-weight: bold; white-space: nowrap; +.datatable { +border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 100%; } -.hd2 { -font-size: 120%; font-weight: bold; white-space: nowrap; +.databg { +opacity: .6; +-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; +filter: alpha(opacity=60); } -img { -border: 0px; +/** + * Buttons. + */ +button { +vertical-align: middle; +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 15px; +outline: none; +-webkit-text-size-adjust: 100%; } .plusminus { font-size: 18px; font-family: "Courier New"; } -.imgbutton { -width: 142px; height: 64px; margin-left: 20px; margin-right: 20px; padding: 0px; border: 1px; cursor: pointer; -} - .graybutton { -display: inline-block; text-align: center; color: #444; font-weight: bold; -padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; +display: inline-block; text-align: center; color: #444; font-weight: bold; font-size: 14px; text-transform: uppercase; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-left: 2px; margin-right: 2px; height: 28px; line-height: 28px; min-width: 30px; -webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; -border: 1px solid gainsboro; background-color: whiteSmoke; -background-image: -webkit-gradient(linear,left top,left bottom,from(whiteSmoke),to(#f1f1f1)); -background-image: -webkit-linear-gradient(top,whiteSmoke,#f1f1f1); -background-image: -moz-linear-gradient(top,whiteSmoke,#f1f1f1); -background-image: -ms-linear-gradient(top,whiteSmoke,#f1f1f1); -background-image: -o-linear-gradient(top,whiteSmoke,#f1f1f1); -background-image: linear-gradient(top,whiteSmoke,#f1f1f1); cursor: default; +border: 1px solid gainsboro; background-color: #f5f5f5; +background-image: -webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#f1f1f1)); +background-image: -webkit-linear-gradient(top,#f5f5f5,#f1f1f1); +background-image: -moz-linear-gradient(top,#f5f5f5,#f1f1f1); +background-image: -ms-linear-gradient(top,#f5f5f5,#f1f1f1); +background-image: -o-linear-gradient(top,#f5f5f5,#f1f1f1); +background-image: linear-gradient(top,#f5f5f5,#f1f1f1); } .graybutton:hover { @@ -583,22 +678,63 @@ background-image: linear-gradient(top,#f8f8f8,#f1f1f1); } .graybutton:active { -background-color: #f6f6f6; -background-image: -webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#f1f1f1)); -background-image: -webkit-linear-gradient(top,#f6f6f6,#f1f1f1); -background-image: -moz-linear-gradient(top,#f6f6f6,#f1f1f1); -background-image: -ms-linear-gradient(top,#f6f6f6,#f1f1f1); -background-image: -o-linear-gradient(top,#f6f6f6,#f1f1f1); -background-image: linear-gradient(top,#f6f6f6,#f1f1f1); --webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -ms-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +-o-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); } .graybutton:disabled { color: #c0c0c0; } +.graybutton:hover:disabled { +color: #c0c0c0; +} + +.lightbutton { +display: inline-block; text-align: center; color: #444; font-weight: normal; font-size: 14px; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-left: 2px; margin-right: 2px; +height: 28px; line-height: 28px; min-width: 30px; +-webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; +cursor: default; +border: 1px solid gainsboro; background-color: #f5f5f5; +background-image: -webkit-gradient(linear,left top,left bottom,from(#f5f5f5),to(#f1f1f1)); +background-image: -webkit-linear-gradient(top,#f5f5f5,#f1f1f1); +background-image: -moz-linear-gradient(top,#f5f5f5,#f1f1f1); +background-image: -ms-linear-gradient(top,#f5f5f5,#f1f1f1); +background-image: -o-linear-gradient(top,#f5f5f5,#f1f1f1); +background-image: linear-gradient(top,#f5f5f5,#f1f1f1); +} + +.lightbutton:hover { +border: 1px solid #c6c6c6; color: #333; text-shadow: 0 1px rgba(0, 0, 0, 0.3); background-color: #f8f8f8; +background-image: -webkit-gradient(linear,left top,left bottom,from(#f8f8f8),to(#f1f1f1)); +background-image: -webkit-linear-gradient(top,#f8f8f8,#f1f1f1); +background-image: -moz-linear-gradient(top,#f8f8f8,#f1f1f1); +background-image: -ms-linear-gradient(top,#f8f8f8,#f1f1f1); +background-image: -o-linear-gradient(top,#f8f8f8,#f1f1f1); +background-image: linear-gradient(top,#f8f8f8,#f1f1f1); +} + +.lightbutton:active { +-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -ms-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +-o-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.lightbutton:disabled { +color: #c0c0c0; +} + +.lightbutton:hover:disabled { +color: #c0c0c0; +} + .bluebutton { -border: 1px solid #3079ed; color: white; text-shadow: 0 1px rgba(0, 0, 0, 0.1); background-color: #4d90fe; +display: inline-block; text-align: center; font-weight: bold; font-size: 14px; text-transform: uppercase; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-left: 2px; margin-right: 2px; +height: 28px; line-height: 28px; min-width: 30px; +-webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; +cursor: default; +border: 1px solid #3079ed; color: #ffffff; text-shadow: 0 1px rgba(0, 0, 0, 0.1); background-color: #4d90fe; background-image: -webkit-gradient(linear,left top,left bottom,from(#4d90fe),to(#4787ed)); background-image: -webkit-linear-gradient(top,#4d90fe,#4787ed); background-image: -moz-linear-gradient(top,#4d90fe,#4787ed); @@ -607,12 +743,8 @@ background-image: -o-linear-gradient(top,#4d90fe,#4787ed); background-image: linear-gradient(top,#4d90fe,#4787ed); } -.bluebutton:disabled { -color: #c0c0c0; -} - .bluebutton:hover { -border: 1px solid #2f5bb7; color: white; text-shadow: 0 1px rgba(0, 0, 0, 0.3); background-color: #357ae8; +border: 1px solid #2f5bb7; color: #ffffff; text-shadow: 0 1px rgba(0, 0, 0, 0.3); background-color: #357ae8; background-image: -webkit-gradient(linear,left top,left bottom,from(#4d90fe),to(#357ae8)); background-image: -webkit-linear-gradient(top,#4d90fe,#357ae8); background-image: -moz-linear-gradient(top,#4d90fe,#357ae8); @@ -621,89 +753,306 @@ background-image: -o-linear-gradient(top,#4d90fe,#357ae8); background-image: linear-gradient(top,#4d90fe,#357ae8); } +.bluebutton:active { +-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -ms-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +-o-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.bluebutton:disabled { +color: #c0c0c0; +} + .bluebutton:hover:disabled { color: #c0c0c0; } +.greenbutton { +display: inline-block; text-align: center; font-weight: bold; font-size: 14px; text-transform: uppercase; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-left: 2px; margin-right: 2px; +height: 28px; line-height: 28px; min-width: 30px; +-webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; +cursor: default; +border: 1px solid #29691d; color: #ffffff; text-shadow: 0 1px rgba(0, 0, 0, 0.1); background-color: #3d9400; +background-image: -webkit-gradient(linear,left top,left bottom,from(#3d9400),to(#398a00)); +background-image: -webkit-linear-gradient(top,#3d9400,#398a00); +background-image: -moz-linear-gradient(top,#3d9400,#398a00); +background-image: -ms-linear-gradient(top,#3d9400,#398a00); +background-image: -o-linear-gradient(top,#3d9400,#398a00); +background-image: linear-gradient(top,#3d9400,#398a00); +} + +.greenbutton:hover { +border: 1px solid #2d6200; color: #ffffff; text-shadow: 0 1px rgba(0, 0, 0, 0.3); background-color: #097b24; +background-image: -webkit-gradient(linear,left top,left bottom,from(#3d9400),to(#097b24)); +background-image: -webkit-linear-gradient(top,#3d9400,#097b24); +background-image: -moz-linear-gradient(top,#3d9400,#097b24); +background-image: -ms-linear-gradient(top,#3d9400,#097b24); +background-image: -o-linear-gradient(top,#3d9400,#097b24); +background-image: linear-gradient(top,#3d9400,#097b24); +} + +.greenbutton:active { +-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -ms-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +-o-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.greenbutton:disabled { +color: #c0c0c0; +} + +.greenbutton:hover:disabled { +color: #c0c0c0; +} + .redbutton { -border: 1px solid transparent; color: white; text-shadow: 0 1px rgba(0, 0, 0, 0.1); background-color: #d14836; +display: inline-block; text-align: center; font-weight: bold; font-size: 14px; text-transform: uppercase; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-left: 2px; margin-right: 2px; +height: 28px; line-height: 28px; min-width: 30px; +-webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; +cursor: default; +border: 1px solid transparent; color: #ffffff; text-shadow: 0 1px rgba(0, 0, 0, 0.1); background-color: #d14836; background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b39),to(#d14836)); background-image: -webkit-linear-gradient(top,#dd4b39,#d14836); background-image: -moz-linear-gradient(top,#dd4b39,#d14836); background-image: -ms-linear-gradient(top,#dd4b39,#d14836); background-image: -o-linear-gradient(top,#dd4b39,#d14836); background-image: linear-gradient(top,#dd4b39,#d14836); --webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); -ms-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); --o-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); -} - -.redbutton:disabled { -color: #c0c0c0; } .redbutton:hover { -border: 1px solid #b0281a; border-bottom-color: #af301f; color: white; background-color: #c53727; +border: 1px solid #b0281a; border-bottom-color: #af301f; color: #ffffff; text-shadow: 0 1px rgba(0, 0, 0, 0.3); background-color: #c53727; +background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b39),to(#c53727)); background-image: -webkit-linear-gradient(top,#dd4b39,#c53727); background-image: -moz-linear-gradient(top,#dd4b39,#c53727); background-image: -ms-linear-gradient(top,#dd4b39,#c53727); background-image: -o-linear-gradient(top,#dd4b39,#c53727); background-image: linear-gradient(top,#dd4b39,#c53727); --webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -ms-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); --o-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); +} + +.redbutton:active { +-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -ms-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +-o-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.redbutton:disabled { +color: #c0c0c0; } .redbutton:hover:disabled { color: #c0c0c0; } +/** + * Store. + */ +.imgbutton { +width: 142px; height: 64px; margin-left: 20px; margin-right: 20px; padding: 0px; border: 1px; cursor: pointer; +} + .box { -width: 150px; display: inline-block; +width: 148px; display: inline-block; overflow: hidden; text-overflow: ellipsis; border: 1px; border-style: solid; border-color: #dcdcdc; border-collapse: collapse; white-space: nowrap; margin: 2px; padding: 2px; vertical-align: top; } .appicon { -float: left; -height: 50px; width: 50px; vertical-align: top; margin: 0px; padding: 0px; +float: left; width: 50px; vertical-align: top; padding-right: 4px; padding-top: 2px; padding-bottom: 4px; +overflow: hidden; text-overflow: ellipsis; } -.apptitle { -font-weight: bold; +.appdetails { +font-size: 13px; color: #808080; overflow: hidden; text-overflow: ellipsis; } -.note { -font-size: 12px; color: #808080; +.apptitle { +font-size: 14px; font-weight: bold; overflow: hidden; text-overflow: ellipsis; } +/** + * Editor. + */ .pagediv { -position: absolute; display: block; overflow: visible; +position: absolute; left: 0px; top: 0px; width: 1024px; height: 1024px; +z-index: 2; overflow: hidden; +} + +.playdiv { +position: absolute; left: 0px; top: 0px; width: 1024px; height: 1024px; +z-index: 1; overflow: hidden; +} + +.guide { +border: 1px; border-style: solid; border-color: #fcff00; +} + +.draggable3d { +position: absolute; +-webkit-transition: -webkit-transform 0.016s linear; +-moz-transition: -moz-transform 0.016s linear; +-ms-transition: -ms-transform 0.016s linear; +-o-transition: -o-transform 0.016s linear; +transition: transform 0.016s linear; +-webkit-backface-visibility: hidden; +} + +.draggable3dm { +position: absolute; +-webkit-transition: -webkit-transform 0.016s linear; +-moz-transition: -moz-transform 0.016s linear; +-ms-transition: -ms-transform 0.016s linear; +-o-transition: -o-transform 0.016s linear; +transition: transform 0.016s linear; +-webkit-backface-visibility: hidden; +} + +/** + * Palette. + */ +.palettecontainer3dm { +position: absolute; left: 0px; top: 0px; width: 0px; bottom: 0px; padding-top: 2px; padding-bottom: 2px; +-webkit-backface-visibility: hidden; +} + +.palettecontainer3d { +position: absolute; left: 0px; top: 0px; width: 0px; bottom: 0px; padding-top: 2px; padding-bottom: 2px; +-webkit-backface-visibility: hidden; +} + +.paletteloading3d { +position: absolute; left: 0px; top: 0px; bottom: 0px; +z-index: 6; background-color: #ffffff; +-webkit-transform: translate(-150px, 0px); +-moz-transform: translate(-150px, 0px); +-ms-transform: translate(-150px, 0px); +-o-transform: translate(-150px, 0px); +transform: translate(-150px, 0px); +-webkit-backface-visibility: hidden; +} + +.paletteloading3dm { +position: absolute; left: 0px; top: 0px; bottom: 0px; +z-index: 6; background-color: #ffffff; +-webkit-transform: translate(-150px, 0px); +-moz-transform: translate(-150px, 0px); +-ms-transform: translate(-150px, 0px); +-o-transform: translate(-150px, 0px); +transform: translate(-150px, 0px); +-webkit-backface-visibility: hidden; +} + +.paletteloaded3d { +position: absolute; left: 0px; top: 0px; bottom: 0px; +z-index: 6; background-color: #ffffff; +-webkit-transform: translate(0px, 0px); +-moz-transform: translate(0px, 0px); +-ms-transform: translate(0px, 0px); +-o-transform: translate(0px, 0px); +transform: translate(0px, 0px); +-webkit-backface-visibility: hidden; +} + +.paletteloaded3dm { +position: absolute; left: 0px; top: 0px; bottom: 0px; +z-index: 6; background-color: #ffffff; +-webkit-transition: -webkit-transform 0.4s ease-in-out; +-moz-transition: -moz-transform 0.4s ease-in-out; +-ms-transition: -ms-transform 0.4s ease-in-out; +-o-transition: -o-transform 0.4s ease-in-out; +transition: transform 0.4s ease-in-out; +-webkit-transform: translate(0px, 0px); +-moz-transform: translate(0px, 0px); +-ms-transform: translate(0px, 0px); +-o-transform: translate(0px, 0px); +transform: translate(0px, 0px); +-webkit-backface-visibility: hidden; +} + +.paletteunloading3dm { +position: absolute; left: 0px; top: 0px; bottom: 0px; +z-index: 6; background-color: #ffffff; +-webkit-transform: translate(0px, 0px); +-moz-transform: translate(0px, 0px); +-ms-transform: translate(0px, 0px); +-o-transform: translate(0px, 0px); +transform: translate(0px, 0px); +-webkit-backface-visibility: hidden; +} + +.paletteunloaded3dm { +position: absolute; left: 0px; top: 0px; bottom: 0px; +z-index: 6; background-color: #ffffff; +-webkit-transition: -webkit-transform 0.4s ease-in-out; +-moz-transition: -moz-transform 0.4s ease-in-out; +-ms-transition: -ms-transform 0.4s ease-in-out; +-o-transition: -o-transform 0.4s ease-in-out; +transition: transform 0.4s ease-in-out; +-webkit-transform: translate(-150px, 0px); +-moz-transform: translate(-150px, 0px); +-ms-transform: translate(-150px, 0px); +-o-transform: translate(-150px, 0px); +transform: translate(-150px, 0px); -webkit-backface-visibility: hidden; } -.graphdiv { -position: absolute; display: block; overflow: visible; +.paletteunloaded { +position: absolute; left: 0px; top: 0px; bottom: 0px; +z-index: 6; background-color: #ffffff; +-webkit-transform: translate(-150px, 0px); +-moz-transform: translate(-150px, 0px); +-ms-transform: translate(-150px, 0px); +-o-transform: translate(-150px, 0px); +transform: translate(-150px, 0px); -webkit-backface-visibility: hidden; } +.palettecontent { +position: absolute; left: 0px; top: 0px; bottom: 0px; width: 150px; +padding-right: 4px; padding-top: 4px; padding-bottom: 6px; z-index: 6; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 1px; +background-color: #ffffff; border-style: solid; border-color: #e5e5e5; +overflow-y: scroll; overflow-x: hidden; -webkit-overflow-scrolling: touch; +} + +.palettetable { +border-top: 1px; border-bottom: 1px; border-left: 1px; border-right: 1px; border-style: solid; border-color: #dcdcdc; +background-color: #ffffff; width: 100%; +} + +.palettetd { +border-top: 1px; border-bottom: 1px; border-left: 1px; border-right: 1px; border-style: solid; border-color: #dcdcdc; vertical-align: middle; +height: 25px; padding-bottom: 6px; padding-top: 4px; +} + +/** + * Graph. + */ .g { -position: absolute; display: block; overflow: visible; +position: absolute; display: block; -webkit-backface-visibility: hidden; } .path { -position: absolute; background: transparent; display: block; overflow: visible; -visibility: visible; +position: absolute; background: transparent; display: block; -webkit-backface-visibility: hidden; } .gtitle { position: absolute; margin: 4px; padding: 0px; line-height: 15px; vertical-align: middle; white-space: nowrap; -font-family: Arial; font-style: normal; font-variant: normal; font-size: 13px; cursor: default; -background: transparent; display: block; overflow: visible; +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 14px; cursor: default; +background: transparent; display: block; -webkit-text-size-adjust: none; -webkit-touch-callout: none; -webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } +.graphentry { +font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 14px; +-webkit-appearance: none; appearance: none; +border: 1px solid #d9d9d9!important; border-top: 1px solid silver!important; +box-sizing: border-box; -moz-box-sizing: border-box; -webkit-box-sizing: border-box; +border-radius: 1px; -webkit-border-radius: 1px; -moz-border-radius: 1px; +margin: 0px; padding: 0px; +} + diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.js b/sca-cpp/trunk/modules/js/htdocs/ui.js index fb53598390..0c80b92bcf 100644 --- a/sca-cpp/trunk/modules/js/htdocs/ui.js +++ b/sca-cpp/trunk/modules/js/htdocs/ui.js @@ -31,6 +31,8 @@ ui.elementByID = function(node, id) { return null; for (var i in node.childNodes) { var child = node.childNodes[i]; + if (isNil(child)) + continue; if (child.id == id) return child; var gchild = ui.elementByID(child, id); @@ -46,7 +48,16 @@ ui.elementByID = function(node, id) { function $(id) { if (id == document) return document; - return ui.elementByID($(document), id); + return memo(document, '$' + id, function() { + return ui.elementByID($(document), id); + }); +} + +/** + * Un-memoize elements previously found by id. + */ +ui.unmemo$ = function(prefix) { + return prefix? unmemo(document, '$' + prefix) : unmemo(document); }; /** @@ -114,10 +125,26 @@ ui.fragmentParams = function(url) { }; /** - * Convert a base64-encoded image to a data URL. + * Convert a base64-encoded PNG image to a data URL. */ -ui.b64img = function(b64) { - return 'data:image/png;base64,' + b64; +ui.b64png = function(b64) { + return 'data:image/png;base64,' + b64.trim(); +}; + +/** + * Convert a base64-encoded JPEG image to a data URL. + */ +ui.b64jpeg = function(b64) { + return 'data:image/jpeg;base64,' + b64.trim(); +}; + +/** + * Convert a data URL to a base64-encoded image. + */ +ui.imgb64 = function(img) { + if (img.startsWith('data:')) + return img.split(',')[1] + return ''; }; /** @@ -130,6 +157,16 @@ ui.declareCSS = function(s) { return e; }; +/** + * Include a CSS stylesheet. + */ +ui.includeCSS = function(s) { + var e = ui.declareCSS(s); + var head = document.getElementsByTagName('head')[0]; + head.appendChild(e); + return e; +}; + /** * Declare a script. */ @@ -151,15 +188,15 @@ ui.innerScripts = function(e) { * Evaluate a script. */ ui.evalScript = function(s) { - return eval('(function() {\n' + s + '\n})();'); + return eval('(function evalscript() { try { \n' + s + '\n} catch(e) { debug(e.stack); throw e; }})();'); }; /** * Include a script. */ ui.includeScript = function(s) { - //log('include', s); - return eval(s); + //debug('include', s); + return eval('try { \n' + s + '\n} catch(e) { debug(e.stack); throw e; }'); }; /** @@ -171,12 +208,138 @@ ui.isMobile = function() { if (ui.mobiledetected) return ui.mobile; var ua = navigator.userAgent; - if (ua.match(/iPhone/i) || ua.match(/iPad/i) || ua.match(/Android/i) || ua.match(/Blackberry/i) || ua.match(/WebOs/i)) + if (ua.match(/iPhone/i) || ua.match(/iPad/i) || ua.match(/iPod/i) || ua.match(/Android/i) || ua.match(/Blackberry/i) || ua.match(/WebOs/i)) ui.mobile = true; ui.mobiledetected = true; return ui.mobile; }; +/** + * Return true if the client is Webkit based. + */ +ui.isWebkit = function() { + return navigator.userAgent.match(/WebKit/i); +}; + +/** + * Return the Webkit version. + */ +ui.webkitVersion = function() { + return Number(navigator.userAgent.replace(/.*AppleWebKit\/(\d+\.\d+).*/, '$1')); +}; + +/** + * Return true if the client is Firefox. + */ +ui.isFirefox = function() { + return navigator.userAgent.match(/Firefox/i); +}; + +/** + * Return the Firefox version. + */ +ui.firefoxVersion = function() { + return Number(navigator.userAgent.replace(/.*Firefox\/(\d+\.\d+).*/, '$1')); +}; + +/** + * Return true if the client is Safari. + */ +ui.isSafari = function() { + return navigator.userAgent.match(/Safari/i); +}; + +/** + * Return true if the client is Chrome. + */ +ui.isChrome = function() { + return navigator.userAgent.match(/Chrome/i); +}; + +/** + * Return true if the client is Internet Explorer. + */ +ui.isMSIE = function() { + return navigator.userAgent.match(/MSIE/i); +}; + +/** + * Return the Internet Explorer version. + */ +ui.msieVersion = function() { + return Number(navigator.userAgent.replace(/.*MSIE (\d+\.\d+).*/, '$1')); +}; + +/** + * Run a UI rendering function asynchronously. + */ +ui.asyncFrame = null; +ui.async = function(f) { + if (isNil(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); +}; + +/** + * Delay the execution of a function. + */ +ui.delayed = {} +ui.delay = function(f, t) { + var id = window.setTimeout(function() { + delete ui.delayed[id]; + return f(); + }, isNil(t)? 16 : t); + ui.delayed[id] = id; + return id; +}; + +/** + * Cancel the execution of a delayed function. + */ +ui.cancelDelay = function(id) { + delete ui.delayed[id]; + return window.clearTimeout(id); +}; + +/** + * Run a UI animation. + */ +ui.animationFrame = null; +ui.animation = function(f) { + if (isNil(ui.animationFrame)) + // Use requestAnimationFrame when available, fallback to setInterval + ui.animationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || + window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || + function(f) { + if (!('interval' in f) || isNil(f.interval)) { + // First call, setup the interval + f.interval = window.setInterval(function animation() { + f.clearInterval = true; + try { + f(); + } catch(ex) {} + // If the animation function didn't call ui.animation again to + // request another animation frame, clear the interval + if (f.clearInterval) { + f.clearInterval = false; + window.clearInterval(f.interval); + f.interval = null; + } + }, 16); + } else { + // Called to request another animation frame, do not clear the + // interval + f.clearInterval = false; + } + }; + return ui.animationFrame.call(window, f); +}; + /** * Convert a CSS position to a numeric position. */ @@ -192,46 +355,49 @@ ui.pixpos = function(p) { }; /** - * Default orientation change behavior. + * Default page load behavior. */ -ui.onorientationchange = function(e) { +ui.filler = null; +ui.onload = function() { - // Scroll to the top and hide the address bar + // Add a filler div to make sure we can scroll + if (ui.isMobile()) { + ui.filler = document.createElement('div'); + ui.filler.id = 'filler'; + ui.filler.className = 'filler'; + ui.filler.style.height = ui.pixpos(window.orientation == 0? screen.height : screen.width * 2); + document.body.appendChild(ui.filler); + } else { + // Style scroll bars + var h = document.getElementsByTagName('html'); + if (!isNil(h)) + h[0].className = h[0].className? h[0].classname + ' flatscrollbars' : 'flatscrollbars'; + } + + // Scroll to hide the address bar + document.body.style.display = 'block'; window.scrollTo(0, 0); - // Change fixed position elements to absolute then back to fixed - // to make sure they're correctly layed out after the orientation - // change - map(function(e) { - e.style.position = 'absolute'; - return e; - }, ui.elementsByClassName(document, 'fixed')); - - setTimeout(function() { - map(function(e) { - e.style.position = 'fixed'; - return e; - }, ui.elementsByClassName(document, 'fixed')); - }, 0); + // Set unload handler + window.onunload = function() { + window.scrollTo(0, 0); + return true; + }; + return true; }; /** - * Default page load behavior. + * Default orientation change behavior. */ -ui.onload = function() { +ui.onorientationchange = function(e) { - // Scroll to the top and hide the address bar - window.scrollTo(0, 0); + // Adjust filler height + if (!isNil(ui.filler)) + ui.filler.style.height = ui.pixpos(window.orientation == 0? screen.height : screen.width); - // Initialize fixed position elements only after the page is loaded, - // to workaround layout issues with fixed position on mobile devices - setTimeout(function() { - map(function(e) { - e.style.position = 'fixed'; - return e; - }, ui.elementsByClassName(document, 'fixed')); - }, 0); + // Scroll to hide the address bar + window.scrollTo(0, 0); return true; }; @@ -239,7 +405,7 @@ ui.onload = function() { * Navigate to a new document. */ ui.navigate = function(url, win) { - //log('navigate', url, win); + //debug('navigate', url, win); // Open a new window if (win == '_blank') { @@ -264,6 +430,27 @@ ui.navigate = function(url, win) { if (win == '_view') { if (!window.top.onnavigate) return window.top.open(url, '_self'); + + // Cleanup window event handlers + window.onclick = null; + if (!ui.isMobile()) { + window.onmousedown = null; + window.onmouseup = null; + window.onmousemove = null; + } else { + window.ontouchstart = null; + window.ontouchend = null; + window.ontouchmove = null; + } + + // Cleanup memoized element lookups + ui.unmemo$(); + + // Cancel any timers + for (d in ui.delayed) + ui.cancelDelay(d); + + // Navigate window.top.onnavigate(url); return false; } @@ -369,7 +556,7 @@ ui.datatable = function(l) { } return '' + rows(l, 0) + '
'; -} +}; /** * Convert a list of elements to an HTML single column table. @@ -405,5 +592,67 @@ ui.datalist = function(l) { } return '' + rows(l, 0) + '
'; -} +}; + +/** + * Read a file and convert it to a data url. + */ +ui.readfile = function(file, onerror, onprogress, onload) { + var reader = new FileReader(); + reader.onerror = function(e) { + return onerror(); + }; + reader.onprogress = function(e) { + return onprogress(e.lengthComputable? Math.round((e.loaded / e.total) * 90) : 50); + }; + reader.onload = function(r) { + return onload(r.target.result); + }; + return reader.readAsDataURL(file); +}; + +/** + * Read an image url and convert it to a data url. + */ +ui.readimageurl = function(url, onerror, onprogress, onload, width, height) { + // Create a canvas to draw the image + var canvas = document.createElement('canvas'); + if (width) + canvas.width = width; + if (height) + canvas.height = height; + + // Create an image + var img = new Image(); + img.onerror = function(e) { + return onerror(); + }; + img.onload = function() { + // Draw the image + var ctx = canvas.getContext('2d'); + if (width || height) + ctx.drawImage(img, 0, 0, width, height); + else + ctx.drawImage(img, 0, 0); + + // Convert new canvas image to a data url + return onload(canvas.toDataURL('image/png')); + }; + + // Load the image + onprogress(90); + img.src = url; + return true; +}; + +/** + * Read an image file or url and convert it to a data url. + */ +ui.readimage = function(img, onerror, onprogress, onload, width, height) { + if (isString(img)) + return ui.readimageurl(img, onerror, onprogress, onload, width, height); + return ui.readfile(img, onerror, onprogress, function(url) { + return ui.readimageurl(url, onerror, onprogress, onload, width, height); + }, width, height); +}; diff --git a/sca-cpp/trunk/modules/js/htdocs/util.js b/sca-cpp/trunk/modules/js/htdocs/util.js index 0f7de94289..1cf086c60e 100644 --- a/sca-cpp/trunk/modules/js/htdocs/util.js +++ b/sca-cpp/trunk/modules/js/htdocs/util.js @@ -296,9 +296,19 @@ function memo(obj, key, f) { /** * Un-memoize stored results. */ -function unmemo(obj) { - obj.memo = {}; - return true; +function unmemo(obj, prefix) { + if (!prefix) { + obj.memo = {}; + return true; + } + if (!('memo' in obj)) { + obj.memo = {}; + return true; + } + for (key in obj.memo) { + if (key.substring(0, prefix.length) == prefix) + delete obj.memo[key]; + } } /** @@ -307,6 +317,32 @@ function unmemo(obj) { var lstorage = {}; lstorage.enabled = true; +/** + * Get a key. + */ +lstorage.key = function(i) { + if (!lstorage.enabled) + return null; + try { + return localStorage.key(i); + } catch(e) { + return null; + } +}; + +/** + * Return the number of keys. + */ +lstorage.length = function() { + if (!lstorage.enabled) + return 0; + try { + return localStorage.length; + } catch(e) { + return 0; + } +}; + /** * Get an item. */ @@ -318,7 +354,7 @@ lstorage.getItem = function(k) { } catch(e) { return null; } -} +}; /** * Set an item. @@ -331,7 +367,7 @@ lstorage.setItem = function(k, v) { } catch(e) { return null; } -} +}; /** * Remove an item. @@ -344,7 +380,7 @@ lstorage.removeItem = function(k) { } catch(e) { return null; } -} +}; /** * Returns a list of the properties of an object. @@ -372,31 +408,28 @@ function domainname(host) { } /** - * Return true if a host name is a subdomain. + * Convert a host name to a top domain name. */ -function issubdomain(host) { - return host.split('.').length > 2; +function topdomainname(host) { + var d = reverse(domainname(host).split('.')); + return reverse(mklist(car(d), cadr(d))).join('.'); } /** - * Return true if the document cookie contains auth information. + * Return true if a host name is a subdomain. */ -function hasauthcookie() { - return !isNil(document.cookie) && - (document.cookie.indexOf('TuscanyOpenAuth=') != -1 || - document.cookie.indexOf('TuscanyOAuth1=') != -1 || - document.cookie.indexOf('TuscanyOAuth2=') != -1 || - document.cookie.indexOf('TuscanyOpenIDAuth=') != -1); +function issubdomain(host) { + return host.split('.').length > 2; } /** * Clear auth information from the document cookie. */ function clearauthcookie() { - document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; - document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/; secure; httponly'; + document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/; secure; httponly'; + document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/; secure; httponly'; + document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/; secure; httponly'; return true; } @@ -413,6 +446,64 @@ function format() { return s; } +/** + * Parse an XML dateTime. + */ +function xmldatetime(xml) { + var re = /^([0-9]{4,})-([0-9]{2})-([0-9]{2})T([0-9]{2}):([0-9]{2}):([0-9]{2})(\.[0-9]+)?(Z|([+-])([0-9]{2}):([0-9]{2}))?$/; + var match = xml.match(re); + if (!match) + return new Date(); + return new Date(Date.UTC(match[1], parseInt(match[2]) - 1, match[3], + match[9]? parseInt(match[4]) + parseInt(match[10]) * (match[9] == '+'? 1 : -1) : match[4], + match[9]? parseInt(match[5]) + parseInt(match[11]) * (match[9] == '+'? 1 : -1) : match[5], + match[6], 0)); +} + +/** + * Encode a string to a url-safe base64 format. + */ +function safeb64encode(s) { + return btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, ''); +} + +/** + * Decode a url-safe base64 encoded string. + */ +function safeb64decode(s) { + return atob((s.replace(/\-/g, '+').replace(/\_/g, '/') + '===').substring(0, s.length + (s.length % 4))); +} + +/** + * Return a uuid4. + */ +function uuid4() { + if (window.crypto && window.crypto.getRandomValues) { + var b = new Uint16Array(8); + window.crypto.getRandomValues(b); + function s4(n) { + var s = '000' + n.toString(16); + return s.substr(s.length - 4); + } + return s4(b[0]) + s4(b[1]) + '-' + s4(b[2]) + '-' + s4(b[3]) + '-' + s4(b[4]) + '-' + s4(b[5]) + s4(b[6]) + s4(b[7]); + } else { + return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) { + var r = Math.random() * 16 | 0 + return (c == 'x'? r : (r & 0x3 | 0x8)).toString(16); + }); + } +} + +/** + * Convert an hexadecimal string to ascii. + */ +function hex2ascii(x) { + var a = ''; + for (var i = 0; i < x.length; i += 2) + a += String.fromCharCode(parseInt(x.substr(i, 2), 16)); + return a; +} + /** * Functions with side effects. Use with moderation. */ -- cgit v1.2.3