summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk/modules/js/htdocs
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk/modules/js/htdocs')
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/atomutil.js8
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/component.js708
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/ui.css929
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/ui.js329
-rw-r--r--sca-cpp/trunk/modules/js/htdocs/util.js131
5 files changed, 1453 insertions, 652 deletions
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;
@@ -110,11 +110,6 @@ function HTTPBindingClient(name, uri, domain) {
}
/**
- * 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);
@@ -140,12 +135,17 @@ HTTPBindingClient.prototype.createApplyMethod = function() {
};
/**
+ * 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) {}
@@ -184,48 +184,203 @@ HTTPBindingClient.jsonResult = function(http) {
};
/**
+ * 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);
};
@@ -552,38 +696,6 @@ HTTPBindingClient.Exception.prototype.toString = function() {
};
/**
- * 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 '';
};
/**
@@ -131,6 +158,16 @@ ui.declareCSS = function(s) {
};
/**
+ * 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.
*/
ui.declareScript = function(s) {
@@ -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,13 +208,139 @@ 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.
*/
ui.numpos = function(p) {
@@ -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 '<table class="datatable ' + (window.name == 'dataFrame'? ' databg' : '') + '" style="width: 100%;">' + rows(l, 0) + '</table>';
-}
+};
/**
* Convert a list of elements to an HTML single column table.
@@ -405,5 +592,67 @@ ui.datalist = function(l) {
}
return '<table class="datatable ' + (window.name == 'dataFrame'? ' databg' : '') + '" style="width: 100%;">' + rows(l, 0) + '</table>';
-}
+};
+
+/**
+ * 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];
+ }
}
/**
@@ -308,6 +318,32 @@ 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.
*/
lstorage.getItem = function(k) {
@@ -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;
}
@@ -414,6 +447,64 @@ function format() {
}
/**
+ * 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.
*/