diff options
Diffstat (limited to 'sca-cpp/trunk/modules/js/htdocs')
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/component.js | 481 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/jsonutil.js | 100 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/ui.css | 1020 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/ui.js | 903 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/util.js | 520 | ||||
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/xmlutil.js | 69 |
6 files changed, 1541 insertions, 1552 deletions
diff --git a/sca-cpp/trunk/modules/js/htdocs/component.js b/sca-cpp/trunk/modules/js/htdocs/component.js index 0a8ec5f5d5..8d3f727f54 100644 --- a/sca-cpp/trunk/modules/js/htdocs/component.js +++ b/sca-cpp/trunk/modules/js/htdocs/component.js @@ -15,16 +15,6 @@ * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. - * - * The JSON-RPC client code is based on Jan-Klaas' JavaScript - * o lait library (jsolait). - * - * $Id: jsonrpc.js,v 1.36.2.3 2006/03/08 15:09:37 mclark Exp $ - * - * Copyright (c) 2003-2004 Jan-Klaas Kollhof - * Copyright (c) 2005 Michael Clark, Metaparadigm Pte Ltd - * - * Licensed under the Apache License, Version 2.0 (the "License"). */ /** @@ -34,72 +24,6 @@ var JSONClient = {}; /** - * Escape a character. - */ -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"; - var hex = c.charCodeAt(0).toString(16); - if(hex.length == 1) return "\\u000" + hex; - if(hex.length == 2) return "\\u00" + hex; - if(hex.length == 3) return "\\u0" + hex; - return "\\u" + hex; -}; - -/** - * Encode a string into JSON format. - */ -JSONClient.escapeJSONString = function(s) { - // The following should suffice but Safari's regex is broken (doesn't support callback substitutions) - // return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g, JSONClient.escapeJSONChar) + "\""; - - // Rather inefficient way to do it - var parts = s.split(""); - for(var i = 0; i < parts.length; i++) { - var c = parts[i]; - if(c == '"' || c == '\\' || c.charCodeAt(0) < 32 || c.charCodeAt(0) >= 128) - parts[i] = JSONClient.escapeJSONChar(parts[i]); - } - return "\"" + parts.join("") + "\""; -}; - -/** - * Marshall objects to JSON format. - */ -JSONClient.toJSON = function(o) { - if(o == null) - return "null"; - if(o.constructor == String) - return JSONClient.escapeJSONString(o); - if(o.constructor == Number) - return o.toString(); - if(o.constructor == Boolean) - return o.toString(); - if(o.constructor == Date) - return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}'; - if(o.constructor == Array) { - var v = []; - for(var i = 0; i < o.length; i++) - v.push(JSONClient.toJSON(o[i])); - return "[" + v.join(", ") + "]"; - } - var v = []; - for(attr in o) { - if(o[attr] == null) - v.push("\"" + attr + "\": null"); - else if(typeof o[attr] == "function") - ; // Skip - else - v.push(JSONClient.escapeJSONString(attr) + ": " + JSONClient.toJSON(o[attr])); - } - return "{" + v.join(", ") + "}"; -}; - -/** * Construct an HTTPBindingClient. */ function HTTPBindingClient(name, uri, domain) { @@ -114,6 +38,17 @@ function HTTPBindingClient(name, uri, domain) { */ /** + * Run a function asynchronously. + */ +HTTPBindingClient.delaying = false; +HTTPBindingClient.delay = function(f) { + if (HTTPBindingClient.delaying) + return window.setTimeout(f, 0); + else + return f(); +}; + +/** * Generate client proxy apply method. */ HTTPBindingClient.prototype.createApplyMethod = function() { @@ -121,10 +56,10 @@ HTTPBindingClient.prototype.createApplyMethod = function() { var methodName = arguments[0]; var args = []; for(var i = 1; i < arguments.length; i++) - args.push(arguments[i]); + args[args.length] = arguments[i]; - var cb = null; - if(typeof args[args.length - 1] == "function") + var cb; + if(typeof args[args.length - 1] == 'function') cb = args.pop(); var req = HTTPBindingClient.makeJSONRequest(methodName, args, cb); @@ -151,7 +86,7 @@ HTTPBindingClient.makeJSONRequest = function(methodName, args, cb) { obj.id = req.id; obj.method = methodName; obj.params = args; - req.data = JSONClient.toJSON(obj); + req.data = JSON.stringify(obj); return req; }; @@ -159,62 +94,39 @@ HTTPBindingClient.makeJSONRequest = function(methodName, args, cb) { * Return the JSON result from an XMLHttpRequest. */ HTTPBindingClient.jsonResult = function(http) { - // Get the charset - function httpCharset(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=") - return parts[i].substring(8, parts[i].length); - } - } catch (e) {} - return "UTF-8"; - } - if(!HTTPBindingClient.charset) - HTTPBindingClient.charset = httpCharset(http); - - // Unmarshall the JSON response - var obj; - eval("obj = " + http.responseText); - if(obj.error) - throw new HTTPBindingClient.Exception(obj.error.code, obj.error.msg); - var res = obj.result; - return res; + var obj = JSON.parse(http.responseText); + return obj.result; }; /** * Schedule async requests, limiting the number of concurrent running requests. */ -HTTPBindingClient.queuedRequests = new Array(); -HTTPBindingClient.runningRequests = new Array(); -HTTPBindingClient.concurrentRequests = 2; +HTTPBindingClient.queuedRequests = []; +HTTPBindingClient.runningRequests = []; +HTTPBindingClient.concurrentRequests = 4; HTTPBindingClient.scheduleAsyncRequest = function(f, cancelable) { - //debug('schedule async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + debug('component schedule async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length); // Queue the request function var req = new Object(); req.f = f; req.cancelable = cancelable; req.canceled = false; - HTTPBindingClient.queuedRequests.push(req); + HTTPBindingClient.queuedRequests[HTTPBindingClient.queuedRequests.length] = req; // Execute any requests in the queue - setTimeout(function() { - HTTPBindingClient.runAsyncRequests(true); - }, 0); - return true; + return HTTPBindingClient.runAsyncRequests(); }; HTTPBindingClient.forgetRequest = function(req) { - req.http = null; + req.http = undefined; // Remove a request from the list of running requests - for (i in HTTPBindingClient.runningRequests) { + for (var i in HTTPBindingClient.runningRequests) { if (HTTPBindingClient.runningRequests[i] == req) { HTTPBindingClient.runningRequests.splice(i, 1); - //debug('forget async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + debug('forget async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length); return true; } } @@ -222,33 +134,32 @@ HTTPBindingClient.forgetRequest = function(req) { }; HTTPBindingClient.cancelRequests = function() { - //debug('cancel async requests, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + debug('component cancel async requests', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length); // Cancel any cancelable in flight HTTP requests - for (i in HTTPBindingClient.queuedRequests) { + for (var i in HTTPBindingClient.queuedRequests) { var req = HTTPBindingClient.queuedRequests[i]; if (req.cancelable) req.canceled = true; } - for (i in HTTPBindingClient.runningRequests) { + for (var i in HTTPBindingClient.runningRequests) { var req = HTTPBindingClient.runningRequests[i]; if (req.cancelable) { req.canceled = true; if (req.http) { + req.http.aborted = true; req.http.abort(); - req.http = null; - //debug('abort async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + req.http = undefined; + debug('component abort async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length); } } } // Flush the queue - setTimeout(function() { - HTTPBindingClient.runAsyncRequests(true); - }, 0); + return HTTPBindingClient.runAsyncRequests(); } -HTTPBindingClient.runAsyncRequests = function(fromui) { +HTTPBindingClient.runAsyncRequests = function() { // Stop now if we already have enough requests running or there's no request in the queue if(HTTPBindingClient.runningRequests.length >= HTTPBindingClient.concurrentRequests || HTTPBindingClient.queuedRequests.length == 0) return true; @@ -256,41 +167,38 @@ HTTPBindingClient.runAsyncRequests = function(fromui) { // Run the first request in the queue var req = HTTPBindingClient.queuedRequests.shift(); if (!req.canceled) { - HTTPBindingClient.runningRequests.push(req); - //debug('run async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); - var runAsyncRequest = function() { + HTTPBindingClient.runningRequests[HTTPBindingClient.runningRequests.length] = req; + debug('component run async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length); if (req.canceled) { HTTPBindingClient.forgetRequest(req); - //debug('canceled timed async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + debug('component canceled timed async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length); return false; } + HTTPBindingClient.delay(function asyncRequest() { try { req.http = new XMLHttpRequest(); + req.http.aborted = false; return req.f(req.http, function asyncRequestDone() { // Execute any requests left in the queue HTTPBindingClient.forgetRequest(req); - //debug('done async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); - HTTPBindingClient.runAsyncRequests(false); + debug('component done async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length); + HTTPBindingClient.runAsyncRequests(); return true; }); } catch(e) { // Execute any requests left in the queue HTTPBindingClient.forgetRequest(req); - //debug('err async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); - HTTPBindingClient.runAsyncRequests(false); + debug('component async request error', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length, 'error', e); + HTTPBindingClient.runAsyncRequests(); } return false; - }; - if (false) - setTimeout(runAsyncRequest, 0); - else - runAsyncRequest(); + }); } else { - //debug('canceled queued async request, running ' + HTTPBindingClient.runningRequests.length + ' queued ' + HTTPBindingClient.queuedRequests.length); + debug('component canceled queued async request', 'running', HTTPBindingClient.runningRequests.length, 'queued', HTTPBindingClient.queuedRequests.length); } // Execute any requests left in the queue - HTTPBindingClient.runAsyncRequests(fromui); + HTTPBindingClient.runAsyncRequests(); }; /** @@ -298,24 +206,24 @@ HTTPBindingClient.runAsyncRequests = function(fromui) { */ HTTPBindingClient.getCacheItem = function(k) { var ls = lstorage || localStorage; - return ls.getItem('cache.d.' + k); + return ls.getItem('dc.d.' + k); }; /** * Set a cache item in local storage. */ HTTPBindingClient.setCacheItem = function(k, v) { + if (v && v.length > 65535) + return HTTPBindingClient.removeCacheItem(k); 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); + var s = ls.getItem('dc.size'); + var size = s? parseInt(s) : 0; + var ov = ls.getItem('dc.d.' + k); + var nsize = size - (ov? ov.length : 0) + (v? v.length : 0); if (nsize != size) - ls.setItem('cache.size', nsize.toString()); - } catch(e) {} - return ls.setItem('cache.d.' + k, v); + ls.setItem('dc.size', nsize.toString()); + return ls.setItem('dc.d.' + k, v); }; /** @@ -323,16 +231,14 @@ HTTPBindingClient.setCacheItem = function(k, v) { */ 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 s = ls.getItem('dc.size'); + var size = s? parseInt(s) : 0; + var ov = ls.getItem('dc.d.' + k); + if (ov) { var nsize = size - ov.length; - ls.setItem('cache.size', nsize.toString()); + ls.setItem('dc.size', nsize.toString()); } - } catch(e) {} - return ls.removeItem('cache.d.' + k); + return ls.removeItem('dc.d.' + k); }; /** @@ -343,41 +249,41 @@ 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) { + var s = ls.getItem('dc.size'); + if(!s) { // Calculate and store initial cache size - //debug('calculating cache size'); + debug('component 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.') + if(!k || k.substr(0, 5) != 'dc.d.') continue; var v = ls.getItem(k); - if(v == null) + if(!v) continue; size += v.length; } - ls.setItem('cache.size', size.toString()); + ls.setItem('dc.size', size.toString()); } else size = parseInt(s); // Nothing to do if it's below the max size - //debug('cache.size', size); + debug('component 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(); + debug('component collecting cache items'); + var keys = []; var n = nkeys(); for(var i = 0; i < n; i++) { var k = ls.key(i); - if(k == null || k.substr(0, 8) != 'cache.d.') + if(!k || k.substr(0, 5) != 'dc.d.') continue; - keys.push(k); + keys[keys.length] = k; } while (keys.length != 0 && size >= HTTPBindingClient.collectCacheSize) { var r = Math.floor(keys.length * Math.random()); @@ -385,19 +291,17 @@ HTTPBindingClient.collectCacheItems = function() { continue; var k = keys[r]; var v = ls.getItem(k); - //debug('collect cache item', k); + debug('component collect cache item', k); ls.removeItem(k); keys.splice(r, 1); - if (v != null) + if (v) size = size - v.length; } // Store the new cache size - //debug('updated cache.size', size); - ls.setItem('cache.size', size.toString()); + debug('component updated cache size', size); + ls.setItem('dc.size', size.toString()); return true; - } catch(e) {} - return false; }; /** @@ -410,28 +314,19 @@ HTTPBindingClient.prototype.jsonApply = function(req) { if(hascb) { var u = this.uri; return HTTPBindingClient.scheduleAsyncRequest(function jsonApplyRequest(http, done) { - http.open("POST", u, true); - http.setRequestHeader("Accept", "*/*"); - http.setRequestHeader("Content-Type", "application/json-rpc"); + http.open('POST', u, true); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('Content-Type', 'application/json-rpc'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); http.onreadystatechange = function() { if(http.readyState == 4) { // Pass the result or exception if(http.status == 200) { - var res = null; - try { - res = HTTPBindingClient.jsonResult(http); - try { + var res = HTTPBindingClient.jsonResult(http); req.cb(res); - } catch(cbe) {} - } catch(e) { - try { - req.cb(null, e); - } catch(cbe) {} - } - } else { - try { - req.cb(null, HTTPBindingClient.Exception(http.status, http.statusText)); - } catch(cbe) {} + } if(!http.aborted) { + error('jsonApply error', 'status', http.status, http.statusText); + req.cb(undefined, new Error('' + http.status + ' ' + http.statusText)); } return done(); } @@ -445,13 +340,15 @@ HTTPBindingClient.prototype.jsonApply = function(req) { // 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.open('POST', this.uri, false); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('Content-Type', 'application/json-rpc'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); http.send(req.data); if(http.status == 200) return HTTPBindingClient.jsonResult(http); - throw new HTTPBindingClient.Exception(http.status, http.statusText); + error('jsonApply error', 'status', http.status, http.statusText); + throw new Error('' + http.status + ' ' + http.statusText); }; @@ -463,69 +360,64 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) { var hascb = cb? true : false; // Get from local storage first - var item = null; + var item; if(mode != 'remote') { item = HTTPBindingClient.getCacheItem(u); - if(item != null && item != '') { + if(item && item != '') { if(!hascb) return item; // Pass local result to callback - setTimeout(function() { cb(item); - }, 0); } } // Call asynchronously with a callback if(hascb) { return HTTPBindingClient.scheduleAsyncRequest(function getRequest(http, done) { - http.open("GET", u, true); - http.setRequestHeader("Accept", "*/*"); + http.open('GET', u, true); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); http.onreadystatechange = function() { - //debug('readystate', http.readyState, 'status', http.status, 'headers', http.getAllResponseHeaders()); if(http.readyState == 4) { + // Pass result if different from local result + //debug('readystate', http.readyState, 'status', http.status, 'headers', http.getAllResponseHeaders()); if(http.status == 200) { - var xl = http.getResponseHeader("X-Login"); - var ct = http.getResponseHeader("Content-Type"); - if(xl != null && xl != '' && ct != null && ct.indexOf('text/html') == 0) { - // Detect redirect to a login page - try { - var le = new HTTPBindingClient.Exception(403, 'X-Login'); - if(window.onloginredirect) - window.onloginredirect(le); - cb(null, le); - return done(); - } catch(cbe) {} + var ct = http.getResponseHeader('Content-Type'); + if(http.responseText == '' || !ct || ct == '') { - } - if(http.responseText == '' || ct == null || ct == '') { // Report empty response - try { - cb(null, new HTTPBindingClient.Exception(403, 'No-Content')); + error('get received empty response', 'url', u); + cb(undefined, new Error('500 No-Content')); return done(); - } catch(cbe) {} - } else { - if(item == null || http.responseText != item) { + } else if(!item || http.responseText != item) { + // Store retrieved entry in local storage + //debug('received response', 'url', u, 'response', http.responseText); if(http.responseText != null) HTTPBindingClient.setCacheItem(u, http.responseText); - try { cb(http.responseText); return done(); - } catch(cbe) {} } - } - } - else { + } else if (http.status == 403) { + + // Redirect to login page + error('get received 403 response', 'url', u); + var le = new Error('' + http.status + ' ' + http.statusText); + if(window.onloginredirect) + window.onloginredirect(le); + cb(undefined, le); + return done(); + + } else if(!http.aborted) { + // Pass exception if we didn't have a local result - if(item == null) { - try { - cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); + error('get received error', 'url', u, 'status', http.status, http.statusText); + if(!item) { + cb(undefined, new Error('' + http.status + ' ' + http.statusText)); return done(); - } catch(cbe) {} } } return done(); @@ -540,28 +432,29 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) { // Call synchronously and return the result or exception var http = new XMLHttpRequest(); - http.open("GET", u, false); - http.setRequestHeader("Accept", "*/*"); + http.open('GET', u, false); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); http.send(null); if(http.status == 200) { - var xl = http.getResponseHeader("X-Login"); - var ct = http.getResponseHeader("Content-Type"); - if(xl != null && xl != '' && ct != null && ct.indexOf('text/html') == 0) { - // Detect redirect to a login page - var le = new HTTPBindingClient.Exception(403, 'X-Login'); - if(window.onloginredirect) - window.onloginredirect(le); - throw le; - - } - var ct = http.getResponseHeader("Content-Type"); - if(http.responseText == '' || ct == null || ct == '') { + var ct = http.getResponseHeader('Content-Type'); + if(http.responseText == '' || !ct || ct == '') { // Report empty response - throw new HTTPBindingClient.Exception(403, 'No-Content'); + error('get received empty response', 'url', u); + throw new Error('500 No Content'); } return http.responseText; } - throw new HTTPBindingClient.Exception(http.status, http.statusText); + if(http.status == 403) { + // Redirect to login page + error('get received 403 response', 'url', u); + var le = new Error('' + http.status + ' ' + http.statusText); + if(window.onloginredirect) + window.onloginredirect(le); + throw le; + } + error('get received error', 'url', u, 'status', http.status, http.statusText); + throw new Error('' + http.status + ' ' + http.statusText); }; /** @@ -574,22 +467,20 @@ HTTPBindingClient.prototype.post = function (entry, cb) { if(hascb) { var u = this.uri; return HTTPBindingClient.scheduleAsyncRequest(function postRequest(http, done) { - http.open("POST", u, true); - http.setRequestHeader("Accept", "*/*"); - http.setRequestHeader("Content-Type", "application/atom+xml"); + http.open('POST', u, true); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('Content-Type', 'application/atom+xml'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); http.onreadystatechange = function() { if(http.readyState == 4) { if(http.status == 201) { + // Successful result - try { cb(http.responseText); - } catch(cbe) {} } else { // Report status code as an exception - try { - cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); - } catch(cbe) {} + cb(undefined, new Error('' + http.status + ' ' + http.statusText)); } return done(); } @@ -603,15 +494,16 @@ HTTPBindingClient.prototype.post = function (entry, cb) { // Call synchronously var http = new XMLHttpRequest(); var hascb = cb? true : false; - http.open("POST", this.uri, false); - http.setRequestHeader("Accept", "*/*"); - http.setRequestHeader("Content-Type", "application/atom+xml"); + http.open('POST', this.uri, false); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('Content-Type', 'application/atom+xml'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); http.send(entry); if(http.status == 201) return http.responseText; // Return status code as an exception - throw new HTTPBindingClient.Exception(http.status, http.statusText); + throw new Error('' + http.status + ' ' + http.statusText); }; /** @@ -622,7 +514,7 @@ HTTPBindingClient.prototype.put = function(id, entry, cb, mode) { var hascb = cb? true : false; // Update local storage - var oentry = null; + var oentry; if(mode != 'remote') { oentry = HTTPBindingClient.getCacheItem(u); HTTPBindingClient.setCacheItem(u, entry); @@ -631,33 +523,31 @@ HTTPBindingClient.prototype.put = function(id, entry, cb, mode) { // Call asynchronously with a callback if(hascb) { return HTTPBindingClient.scheduleAsyncRequest(function putRequest(http, done) { - http.open("PUT", u, true); - http.setRequestHeader("Accept", "*/*"); - http.setRequestHeader("Content-Type", "application/atom+xml"); + http.open('PUT', u, true); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('Content-Type', 'application/atom+xml'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); 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) + if(oentry) HTTPBindingClient.setCacheItem(u, oentry); else HTTPBindingClient.removeCacheItem(u); - } catch(e) {} } } // Report status code as an exception - try { - cb(new HTTPBindingClient.Exception(http.status, http.statusText)); - } catch(cbe) {} + cb(new Error('' + http.status + ' ' + http.statusText)); } return done(); } @@ -671,26 +561,25 @@ HTTPBindingClient.prototype.put = function(id, entry, cb, mode) { // Call synchronously var http = new XMLHttpRequest(); - http.open("PUT", u, false); - http.setRequestHeader("Accept", "*/*"); - http.setRequestHeader("Content-Type", "application/atom+xml"); + http.open('PUT', u, false); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('Content-Type', 'application/atom+xml'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); http.send(entry); if(http.status == 200) return true; if(http.status == 404) { // Undo local storage update if(mode != 'remote') { - try { - if(oentry != null) + if(oentry) HTTPBindingClient.setCacheItem(u, oentry); else HTTPBindingClient.removeCacheItem(u); - } catch(e) {} } } // Return status code as an exception - throw new HTTPBindingClient.Exception(http.status, http.statusText); + throw new Error('' + http.status + ' ' + http.statusText); }; /** @@ -708,21 +597,19 @@ HTTPBindingClient.prototype.del = function(id, cb, mode) { // Call asynchronously with a callback if(hascb) { return HTTPBindingClient.scheduleAsyncRequest(function delRequest(http, done) { - http.open("DELETE", u, true); - http.setRequestHeader("Accept", "*/*"); + http.open('DELETE', u, true); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); 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) {} + cb(new Error('' + http.status + ' ' + http.statusText)); } return done(); } @@ -736,29 +623,15 @@ HTTPBindingClient.prototype.del = function(id, cb, mode) { // Call synchronously var http = new XMLHttpRequest(); - http.open("DELETE", u, false); - http.setRequestHeader("Accept", "*/*"); + http.open('DELETE', u, false); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); http.send(null); if(http.status == 200) return true; // Report status code as an exception - throw new HTTPBindingClient.Exception(http.status, http.statusText); -}; - -/** - * HTTPBindingClient exceptions. - */ -HTTPBindingClient.Exception = function(code, message) { - this.name = "HTTPBindingClientException"; - this.code = code; - this.message = message; -}; - -HTTPBindingClient.Exception.prototype = new Error(); - -HTTPBindingClient.Exception.prototype.toString = function() { - return this.name + ": " + this.message; + throw new Error('' + http.status + ' ' + http.statusText); }; /** @@ -770,7 +643,7 @@ var sca = {}; /** * Return an HTTP client proxy. */ -sca.httpclient = function(name, uri, domain) { +sca.httpClient = function(name, uri, domain) { return new HTTPBindingClient(name, uri, domain); }; @@ -798,15 +671,15 @@ sca.reference = function(comp, rname) { sca.defun = function(ref) { function defapply(name) { return function() { - var args = new Array(); + var args = []; args[0] = name; - for(i = 0, n = arguments.length; i < n; i++) + for(var i = 0; i < arguments.length; i++) args[i + 1] = arguments[i]; return this.apply.apply(this, args); }; } - for(f = 1; f < arguments.length; f++) { + for(var f = 1; f < arguments.length; f++) { var fn = arguments[f]; ref[fn]= defapply(fn); } diff --git a/sca-cpp/trunk/modules/js/htdocs/jsonutil.js b/sca-cpp/trunk/modules/js/htdocs/jsonutil.js index 9960a5d82f..9a95d44d5c 100644 --- a/sca-cpp/trunk/modules/js/htdocs/jsonutil.js +++ b/sca-cpp/trunk/modules/js/htdocs/jsonutil.js @@ -63,12 +63,11 @@ json.jsPropertiesToValues = function(propertiesSoFar, o, i) { var v = json.jsValToValue(jsv); if (typeof p == 'string') { - var n = '' + p; - if (n.slice(0, 1) == '@') - return json.jsPropertiesToValues(cons(mklist(attribute, "'" + n.slice(1), v), propertiesSoFar), o, cdr(i)); + if (p[0] == '@') + return json.jsPropertiesToValues(cons(mklist(attribute, "'" + p.substring(1), v), propertiesSoFar), o, cdr(i)); if (isList(v) && !json.isJSArray(v)) - return json.jsPropertiesToValues(cons(cons(element, cons("'" + n, v)), propertiesSoFar), o, cdr(i)); - return json.jsPropertiesToValues(cons(mklist(element, "'" + n, v), propertiesSoFar), o, cdr(i)); + return json.jsPropertiesToValues(cons(cons(element, cons("'" + p, v)), propertiesSoFar), o, cdr(i)); + return json.jsPropertiesToValues(cons(mklist(element, "'" + p, v), propertiesSoFar), o, cdr(i)); } return json.jsPropertiesToValues(cons(v, propertiesSoFar), o, cdr(i)); }; @@ -80,9 +79,9 @@ json.jsValToValue = function(jsv) { if (jsv == null) return null; if (isList(jsv)) - return json.jsPropertiesToValues(mklist(), jsv, reverse(range(0, jsv.length))); + return json.jsPropertiesToValues(nil, jsv, reverse(seq(0, jsv.length))); if (typeof jsv == 'object') - return json.jsPropertiesToValues(mklist(), jsv, reverse(properties(jsv))); + return json.jsPropertiesToValues(nil, jsv, reverse(properties(jsv))); if (typeof jsv == 'string') return '' + jsv; return jsv; @@ -94,7 +93,7 @@ json.jsValToValue = function(jsv) { json.isJSON = function(l) { if (isNull(l)) return false; - var s = car(l).slice(0, 1); + var s = car(l)[0]; return s == "[" || s == "{"; }; @@ -102,10 +101,8 @@ json.isJSON = function(l) { * Convert a list of strings representing a JSON document to a list of values. */ json.readJSON = function(l) { - var s = writeStrings(l); - var obj; - eval('obj = { \"val\": ' + s + " }"); - return json.jsValToValue(obj.val); + var v = JSON.parse(writeStrings(l)); + return json.jsValToValue(v); }; /** @@ -126,7 +123,7 @@ json.valueToJSVal = function(v) { if (!isList(v)) return v; if (json.isJSArray(v)) - return json.valuesToJSElements(range(0, v.length), v, 0); + return json.valuesToJSElements(seq(0, v.length), v, 0); return json.valuesToJSProperties({}, v); }; @@ -139,14 +136,14 @@ json.valuesToJSProperties = function(o, l) { var token = car(l); if (isTaggedList(token, attribute)) { var pv = json.valueToJSVal(attributeValue(token)); - o['@' + attributeName(token).slice(1)] = pv; + o['@' + attributeName(token).substring(1)] = pv; } else if (isTaggedList(token, element)) { if (elementHasValue(token)) { var pv = json.valueToJSVal(elementValue(token)); - o[elementName(token).slice(1)] = pv; + o[elementName(token).substring(1)] = pv; } else { var child = {}; - o[elementName(token).slice(1)] = child; + o[elementName(token).substring(1)] = child; json.valuesToJSProperties(child, elementChildren(token)); } } @@ -159,11 +156,10 @@ json.valuesToJSProperties = function(o, l) { json.writeJSON = function(l) { var jsv; if (json.isJSArray(l)) - jsv = json.valuesToJSElements(range(0, l.length), l, 0); + jsv = json.valuesToJSElements(seq(0, l.length), l, 0); else jsv = json.valuesToJSProperties({}, l); - var s = json.toJSON(jsv); - return mklist(s); + return mklist(JSON.stringify(jsv)); } /** @@ -193,69 +189,3 @@ json.jsonResultValue = function(s) { return val; }; -/** - * Escape a character. - */ -json.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"; - var hex = c.charCodeAt(0).toString(16); - if(hex.length == 1) return "\\u000" + hex; - if(hex.length == 2) return "\\u00" + hex; - if(hex.length == 3) return "\\u0" + hex; - return "\\u" + hex; -}; - -/** - * Encode a string into JSON format. - */ -json.escapeJSONString = function(s) { - // The following should suffice but Safari's regex is broken (doesn't support callback substitutions) - // return "\"" + s.replace(/([^\u0020-\u007f]|[\\\"])/g, json.escapeJSONChar) + "\""; - - // Rather inefficient way to do it - var parts = s.split(""); - for(var i = 0; i < parts.length; i++) { - var c = parts[i]; - if(c == '"' || c == '\\' || c.charCodeAt(0) < 32 || c.charCodeAt(0) >= 128) - parts[i] = json.escapeJSONChar(parts[i]); - } - return "\"" + parts.join("") + "\""; -}; - -/** - * Marshall objects to JSON format. - */ -json.toJSON = function(o) { - if(o == null) - return "null"; - if(o.constructor == String) - return json.escapeJSONString(o); - if(o.constructor == Number) - return o.toString(); - if(o.constructor == Boolean) - return o.toString(); - if(o.constructor == Date) - return '{javaClass: "java.util.Date", time: ' + o.valueOf() +'}'; - if(o.constructor == Array) { - var v = []; - for(var i = 0; i < o.length; i++) - v.push(json.toJSON(o[i])); - return "[" + v.join(", ") + "]"; - } - var v = []; - for(attr in o) { - if(o[attr] == null) - v.push("\"" + attr + "\": null"); - else if(typeof o[attr] == "function") - ; // Skip - else - v.push(json.escapeJSONString(attr) + ": " + json.toJSON(o[attr])); - } - return "{" + v.join(", ") + "}"; -}; - diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.css b/sca-cpp/trunk/modules/js/htdocs/ui.css index cdc9e31aef..69299eb882 100644 --- a/sca-cpp/trunk/modules/js/htdocs/ui.css +++ b/sca-cpp/trunk/modules/js/htdocs/ui.css @@ -21,16 +21,14 @@ * Main body. */ body, .body { -margin-top: 0px; margin-bottom: 2px; margin-left: 2px; margin-right: 2px; -font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 14px; -background-color: #ffffff; opacity: 1; +margin-top: 0px; margin-bottom: 2px; margin-left: 0px; margin-right: 0px; +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 14px; +cursor: default; -webkit-font-smoothing: subpixel-antialiased; --webkit-text-size-adjust: none; +-webkit-text-size-adjust: none; -moz-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; -cursor: default; --webkit-backface-visibility: hidden; +-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; } .delayed { @@ -38,174 +36,63 @@ display: none; } .installer { -position: relative; width: 0px; height: 0px; display: none; visibility: hidden; background: transparent; +position: absolute; width: 0px; height: 0px; display: none; visibility: hidden; } .filler { -position: relative; left: 0px; top: 0px; width: 1px; background: transparent; z-index: -20; +position: absolute; left: 0px; top: 0px; width: 1px; z-index: -20; } /** - * Main view. + * Views. */ .viewcontainer3dm { -position: fixed; left: 0px; top: 70px; right: 0px; bottom: 25px; padding-top: 2px; padding-bottom: 2px; --webkit-backface-visibility: hidden; +position: absolute; left: 0px; top: 0px; right: 0px; } .viewcontainer3d { -position: fixed; left: 0px; top: 70px; right: 0px; bottom: 25px; padding-top: 2px; padding-bottom: 2px; --webkit-backface-visibility: hidden; -} - -.leftviewloading3dm { -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); --o-transform: translate(100%, 0px); -transform: translate(100%, 0px); --webkit-backface-visibility: hidden; -} - -.rightviewloading3dm { -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); --o-transform: translate(-100%, 0px); -transform: translate(-100%, 0px); --webkit-backface-visibility: hidden; -} - -.viewloading3d { -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); --o-transform: translate(100%, 0px); -transform: translate(100%, 0px); --webkit-backface-visibility: hidden; -} - -.viewloaded3dm { -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; --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; -} - -.viewloaded3d { -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); --ms-transform: translate(0px, 0px); --o-transform: translate(0px, 0px); -transform: translate(0px, 0px); --webkit-backface-visibility: hidden; -} - -.viewunloading3dm { -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); --o-transform: translate(0px, 0px); -transform: translate(0px, 0px); --webkit-backface-visibility: hidden; -} - -.leftviewunloaded3dm { -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; --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(-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; -} - -.rightviewunloaded3dm { -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; --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(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; -} - -.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; +position: absolute; left: 0px; top: 0px; right: 0px; } .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; +position: absolute; left: 0px; top: 0px; width: 100%; padding-top: 35px; 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; -} - -/** - * 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; --webkit-backface-visibility: hidden; +position: absolute; left: 0px; top: 0px; width: 100%; padding-top: 35px; overflow: hidden; } .viewfoot { -position: fixed; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 8; +position: fixed; left: 0px; bottom: 0px; height: 0px; 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; --webkit-backface-visibility: hidden; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; +-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; } -.note { -font-size: 12px; color: #808080; -text-transform: none; +.centeredform { +max-width: 800px; margin: auto; padding-left: 2px; padding-right: 2px; +} + +.centeredpage { +max-width: 800px; margin: auto; padding-left: 2px; padding-right: 2px; +} + +.grid100 { +position: absolute; left: 0px; top: 0px; right: 0px; height: 460px; +z-index: 3; overflow: hidden; +-webkit-backface-visibility: hidden; -mozz-backface-visibility: hidden; +} + +.grid320 { +position: absolute; left: 0px; top: 0px; width: 320px; height: 460px; +z-index: 4; overflow: hidden; +-webkit-backface-visibility: hidden; -mozz-backface-visibility: hidden; +} + +.gridfluid { +position: absolute; left: 0px; top: 0px; height: 460px; +z-index: 4; overflow: visible; +-webkit-backface-visibility: hidden; -mozz-backface-visibility: hidden; } /** @@ -213,47 +100,51 @@ text-transform: none; */ .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; +height: 35px; line-height: 35px; background-color: #f5f5f5; font-size: 18px; overflow: hidden; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #f5f5f5; border-bottom-color: #f5f5f5; +-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; +opacity: 0.95; } -.tbarleft { -padding-left: 2px; padding-right: 6px; white-space: nowrap; float: left; -text-transform: uppercase; +.tbartitle { +position: absolute; top: 0px; left: 0px; width: 100%; text-align: center; z-index: 11; } -.tbarright { -padding-left: 6px; padding-right: 2px; white-space: nowrap; float: right; +.tbaritems { +position: absolute; top: 0px; left: 0px; width: 100%; z-index: 12; } -.tbaramenu { -font-size: 15px; color: #cccccc; text-decoration: none; white-space: nowrap; +.tbarleft { +padding-left: 6px; padding-right: 6px; float: left; display: inline-block; } -.tbarsmenu { -font-size: 15px; font-weight: bold; color: #ffffff; text-decoration: none; white-space: nowrap; +.tbarcenter { +padding-left: 6px; padding-right: 6px; font-size: 24px!important; +display: inline-block; max-width: 160px; overflow: hidden; text-overflow: ellipsis; } -.amenu { -padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #808080; text-decoration: none; float: left; +.tbarright { +padding-left: 6px; padding-right: 6px; float: right; display: inline-block; +} + +.tbaramenu { +color: #357ae8; text-decoration: none; } -.smenu { -padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; float: left; +.tbarsmenu { +font-weight: bold; color: #357ae8; text-decoration: none; } -.cmenu { -font-size: 15px; padding-left: 6px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; float: left; -padding-left: 45px; +.tbarbluemenu { +color: #357ae8; text-decoration: none; } -.bcmenu { -font-size: 22px; padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; +.tbarredmenu { +color: #d14836; text-decoration: none; } -.rmenu { -padding-left: 2px; padding-right: 2px; white-space: nowrap; white-space: nowrap; float: right; +.tbargreenmenu { +color: #3d9400; text-decoration: none; } /** @@ -261,74 +152,51 @@ padding-left: 2px; padding-right: 2px; white-space: nowrap; white-space: nowrap; */ .status3d { position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 9; -background-color: #ffffff; color: #404040; +background-color: #f5f5f5; 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; +border-style: solid; border-top-color: #f5f5f5; border-bottom-color: #ffffff; +transform: translate(0px, 0px); -webkit-transform: translate(0px, 0px); -moz-transform: translate(0px, 0px); -ms-transform: translate(0px, 0px); +-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; +opacity: 0.95; } .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; --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; +background-color: #f5f5f5; color: #404040; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #f5f5f5; border-bottom-color: #ffffff; +transform: translate(0px, 25px); -webkit-transform: translate(0px, 25px); -moz-transform: translate(0px, 25px); -ms-transform: translate(0px, 25px); +transition: transform 0.4s ease-in-out; -webkit-transition: -webkit-transform 0.4s ease-in-out; -moz-transition: transform 0.4s ease-in-out; +-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; +opacity: 0.95; } .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; +background-color: #f5f5f5; color: #404040; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #f5f5f5; border-bottom-color: #ffffff; +transform: translate(0px, 0px); -webkit-transform: translate(0px, 0px); -moz-transform: translate(0px, 0px); -ms-transform: translate(0px, 0px); +-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; +opacity: 0.95; } .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; --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; +background-color: #f5f5f5; color: #404040; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #f5f5f5; border-bottom-color: #ffffff; +transform: translate(0px, 25px); -webkit-transform: translate(0px, 25px); -moz-transform: translate(0px, 25px); -ms-transform: translate(0px, 25px); +transition: transform 0.4s ease-in-out; -webkit-transition: -webkit-transform 0.4s ease-in-out; -moz-transition: transform 0.4s ease-in-out; +-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; +opacity: 0.95; } .okstatus { -font-size: 14px; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none; -background-color: #f5f5f5; color: #000000; +font-size: 14px; padding-left: 6px; padding-right: 6px; text-decoration: none; +color: #000000; width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right; } .errorstatus { -font-size: 14px; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none; +font-size: 14px; padding-left: 6px; padding-right: 6px; text-decoration: none; background-color: #d14836; color: #ffffff; width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right; } @@ -339,60 +207,35 @@ width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: r .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; -} - -@-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; } -} - -@-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; } +border-radius: 60px; -webkit-border-radius: 60px; -moz-border-radius: 60px; +animation: spin 0.8s linear infinite; -webkit-animation: webkit-spin 0.8s linear infinite; -moz-animation: moz-spin 0.8s linear infinite; +-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; } -@-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; } +@keyframes spin { +0% { transform: rotate(0deg); opacity: 0.4; } +50% { transform: rotate(180deg); opacity: 1; } +100% { transform: rotate(360deg); opacity: 0.4; } } -@-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; } +@-webkit-keyframes webkit-spin { +0% { -webkit-transform: rotate(0deg); opacity: 0.4; } +50% { -webkit-transform: rotate(180deg); opacity: 1; } +100% { -webkit-transform: rotate(360deg); opacity: 0.4; } } -@keyframes spin { -from { transform: rotate(0deg); opacity: 0.4; } +@-moz-keyframes moz-spin { +0% { transform: rotate(0deg); opacity: 0.4; } 50% { transform: rotate(180deg); opacity: 1; } -to { transform: rotate(360deg); opacity: 0.4; } +100% { transform: rotate(360deg); opacity: 0.4; } } -/** - * 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; +border-radius: 10px; -webkit-border-radius: 10px; -moz-border-radius: 10px; +animation: spin 0.8s linear infinite; -webkit-animation: webkit-spin 0.8s linear infinite; -moz-animation: moz-spin 0.8s linear infinite; +-webkit-backface-visibility: hidden; -moz-backface-visibility: hidden; } /** @@ -400,7 +243,7 @@ animation: spin 1s linear infinite; */ .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); +-webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.1), inset -1px -1px 0 rgba(0,0,0,.07); } .flatscrollbars::-webkit-scrollbar:hover { @@ -414,7 +257,7 @@ background-color: #666666; .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); +-webkit-box-shadow: inset 1px 1px 0 rgba(0,0,0,.1), inset -1px -1px 0 rgba(0,0,0,.07); } .flatscrollbars::-webkit-scrollbar-thumb:hover { @@ -429,129 +272,191 @@ background-color: #888888; * Base HTML elements. */ .text { -padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; +padding-top: 6px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-left: 0px; margin-right: 0px; vertical-align: middle; +line-height: 16px; min-height: 22px; min-width: 30px; +display: inline-block; +} + +.note { +font-size: 14px; color: #808080; text-transform: none; min-width: 30px; +} + +.doc { +padding-left: 4px; padding-right: 4px; min-width: 30px; +} + +.intro { +font-size: 15px; padding-left: 4px; padding-right: 4px; color: #000000; min-width: 30px; +} + +.help { +font-size: 14px; padding-left: 4px; padding-right: 4px; color: #808080; min-width: 30px; } .bluetext { -color: #4787ed; +color: #4787ed; min-width: 30px; } .redtext { -color: #d14836; +color: #d14836; min-width: 30px; } .greentext { -color: #3d9400; +color: #3d9400; min-width: 30px; } 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; +font-size: 24px; font-weight: normal; vertical-align: middle; white-space: normal; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-bottom: 6px; margin-left: 0px; margin-right: 0px; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; } 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; -} - -.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; -} - -.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; +font-size: 20px; font-weight: normal; vertical-align: middle; white-space: normal; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-bottom: 6px; margin-left: 0px; margin-right: 0px; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; } .hd1 { -font-size: 20px; font-weight: bold; white-space: nowrap; padding-top: 3px; padding-bottom: 4px; vertical-align: middle; +font-size: 24px; font-weight: normal; vertical-align: middle; white-space: normal; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-bottom: 6px; margin-left: 0px; margin-right: 0px; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; } .hd2 { -font-size: 18px; font-weight: bold; white-space: nowrap; padding-top: 3px; padding-bottom: 4px; vertical-align: middle; +font-size: 20px; font-weight: normal; vertical-align: middle; white-space: normal; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-bottom: 6px; margin-left: 0px; margin-right: 0px; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; +} + +.width100 { +width: 312px; } .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; +font-size: 20px; font-weight: normal; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; margin-left: 0px; margin-right: 0px; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #d9d9d9; border-bottom-color: #d9d9d9; border-left-color: #d9d9d9; border-right-color: #d9d9d9; +display: inline-block; line-height: 26px; min-height: 28px; min-width: 30px; } .link { -padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; +padding-top: 3px; padding-bottom: 4px; vertical-align: middle; +display: inline-block; line-height: 16px; min-height: 16px; min-width: 30px; } a:link { -color: #357ae8; text-decoration: none; white-space: nowrap; cursor: pointer; +/*color: #357ae8; text-decoration: none; cursor: pointer;*/ +color: inherit; text-decoration: none; cursor: pointer; } a:visited { -color: #357ae8; text-decoration: none; white-space: nowrap; cursor: pointer; +/*color: #357ae8; text-decoration: none; cursor: pointer;*/ +color: inherit; text-decoration: none; cursor: pointer; } .label { -font-weight: bold; padding-top: 6px; -} - -.lightlabel{ -font-weight: normal; color: #808080; padding-top: 6px; +font-weight: normal; color: #808080; +padding-top: 6px; padding-bottom: 2px; padding-left: 4px; padding-right: 4px; margin-left: 0px; margin-right: 0px; vertical-align: middle; +display: inline-block; line-height: 16px; min-height: 20px; min-width: 30px; } input { -font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 15px; +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 16px; min-width: 30px; +background-image: none; vertical-align: middle; outline: none; --webkit-text-size-adjust: 100%; +-webkit-text-size-adjust: 100%; -moz-text-size-adjust: 100%; } textarea { -font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 15px; +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 16px; +background-image: none; outline: none; overflow: auto; resize: none; } +.entry { +padding-left: 4px; padding-right: 4px; padding-top: 0px; padding-bottom: 0px; margin: 0px; +} + +.password { +padding-left: 4px; padding-right: 4px; padding-top: 0px; padding-bottom: 0px; margin: 0px; +} + .flatentry { -font-family: "Lucida Grande", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 15px; -vertical-align: middle; --webkit-appearance: none; appearance: none; +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 16px; vertical-align: middle; +height: 28px; width: 100%; +-webkit-appearance: none; -moz-appearance: none!important; +box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; 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: 1px!important; padding: 3px 1px 3px 3px; +border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; +margin: 1px!important; padding: 3px 3px 3px 3px; +} + +.flattextarea { +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 16px; vertical-align: middle; +width: 100%; +-webkit-appearance: none; -moz-appearance: none!important; +box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; +border: 1px solid #d9d9d9!important; border-top: 1px solid silver!important; +border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; +margin: 1px!important; padding: 3px 3px 3px 3px; +} + +.ifiller { +-webkit-appearance: none; -moz-appearance: none; +border: 0px; margin: 0px; padding: 0px; +overflow: hidden; width: 100%; height: 0px; } .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; +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 16px; vertical-align: middle; +height: 28px; width: 100%; +-webkit-appearance: none; -moz-appearance: none; +box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; +border: 1px solid #ffffff!important; border-top: 1px solid ffffff!important; +border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; +margin: 1px!important; padding: 3px 3px 3px 3px; overflow: hidden; text-overflow: ellipsis; } +.readtextarea { +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 16px; vertical-align: middle; +width: 100%; +-webkit-appearance: none; -moz-appearance: none; +box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; +border: 1px solid #ffffff!important; border-top: 1px solid ffffff!important; +border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; +margin: 1px!important; padding: 3px 3px 3px 3px; +overflow: hidden; text-overflow: ellipsis; +} + +.bigentry { +font-size: 18px!important; +} + .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; +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 16px; vertical-align: middle; +height: 28px; width: 100%; +-webkit-appearance: searchfield; -moz-appearance: searchfield; +box-sizing: border-box; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; 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: 1px!important; padding: 3px 1px 3px 3px; +border-radius: 3px; -webkit-border-radius: 3px; -moz-border-radius: 3px; +margin: 1px!important; padding: 3px 3px 3px 3px; } .checkbox { -padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; +padding-top: 3px; padding-bottom: 4px; vertical-align: middle; } .flatcheckbox { } .editablewidget { --webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; user-select: text; -outline: none; -moz-outline-style: none; -} - -.noneditablewidget { -outline: none; -moz-outline-style: none; +-webkit-user-select: text; -moz-user-select: text; -ms-user-select: text; +outline: none; outline-style: none; +display: block; } iframe { @@ -559,25 +464,44 @@ border: 0px; margin: 0px; padding: 0px; } img { +padding: 0px; margin: 0px; border: 0px; +border-radius: 0px; -webkit-border-radius: 0px; -moz-border-radius: 0px; +display: inline-block; +} + +.img { +padding: 0px; margin: 0px; border: 0px; +max-width: 320px; max-height: 460px; border: 0px; +border-radius: 0px; -webkit-border-radius: 0px; -moz-border-radius: 0px; +background-repeat: no-repeat; float: left; +display: inline-block; +} + +.thumbnail { +padding: 0px; margin: 0px; border: 0px; +max-width: 50x; max-height: 50px; +border: 0px; +border-radius: 6px; -webkit-border-radius: 6px; -moz-border-radius: 6px; +background-repeat: no-repeat; float: left; +display: inline-block; } /** * 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; +border: 0px; border-collapse: collapse; border-color: #f5f5f5; border-style: solid; +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 14px; } .table { -width: 100%; } 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; +font-size: 18px; font-weight: normal; background-color: #ffffff; color: #000000; +padding-left: 2px; padding-right: 8px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; +border-top: 1px; border-bottom: 1px; border-left: 1px; border-right: 1px; border-style: solid; border-top-color: #f5f5f5; border-bottom-color: #f5f5f5; border-left-color: #f5f5f5; border-right-color: #f5f5f5; } .thl { @@ -593,7 +517,7 @@ padding: 0px; } td { -padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: nowrap; vertical-align: middle; border: 0px; +padding-left: 2px; padding-top: 2px; padding-right: 8px; vertical-align: middle; border: 0px; } .tdl { @@ -609,33 +533,30 @@ padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: normal; ve } .datatd { -border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: middle; +border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #f5f5f5; width: 10px; vertical-align: middle; } .datatdl { -border-right: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: middle; +border-right: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #f5f5f5; width: 10px; vertical-align: middle; } .datatdltop { -border-right: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: top; +border-right: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #f5f5f5; width: 10px; vertical-align: top; } .datatdr { -border-left: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; vertical-align: middle; +border-left: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #f5f5f5; vertical-align: middle; } .list { -width: 100%; } .datatable { -border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 100%; +border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #f5f5f5; } .databg { -opacity: .6; --ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; -filter: alpha(opacity=60); +opacity: 0.95; } /** @@ -643,416 +564,65 @@ filter: alpha(opacity=60); */ 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"; +font-family: "Helvetica Neue", Helvetica, Arial; font-style: normal; font-variant: normal; font-size: 18px; +-webkit-text-size-adjust: 100%; -moz-text-size-adjust: 100%; } -.graybutton { -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; -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); +button::-moz-focus-inner { +outline: none!important; border: 0px!important; } -.graybutton: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); +.submit { +visibility: hidden; height: 0px; width: 0px; max-height: 0px; padding: 0px; margin: 0px; } -.graybutton: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); +.symbolbutton { +text-align: center; vertical-align: middle; font-family: "Courier"; font-size: 28px!important; +display: inline-block; min-height: 28px; min-width: 30px; padding-top: 0px; } -.graybutton:disabled { -color: #c0c0c0; +.minusbutton { +text-align: center; vertical-align: top; font-family: "Courier"; font-size: 28px!important; +display: inline-block; min-height: 28px; min-width: 30px; padding-top: 0px; } -.graybutton:hover:disabled { -color: #c0c0c0; +.bigbutton { +font-size: 24px!important; padding: 10px!important; height: 50px!important; } -.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); +.graybutton { +color: #808080!important; font-size: 18px; +padding-top: 0px; padding-bottom: 0px; padding-left: 6px; padding-right: 6px; margin-left: 0px; margin-right: 0px; text-align: center; vertical-align: top; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; } -.lightbutton:disabled { -color: #c0c0c0; +.blackbutton { +color: #000000!important; font-size: 18px; +padding-top: 0px; padding-bottom: 0px; padding-left: 6px; padding-right: 6px; margin-left: 0px; margin-right: 0px; text-align: center; vertical-align: top; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; } -.lightbutton:hover:disabled { -color: #c0c0c0; +.lightbutton { +color: #808080!important; font-size: 18px; +padding-top: 0px; padding-bottom: 0px; padding-left: 6px; padding-right: 6px; margin-left: 0px; margin-right: 0px; text-align: center; vertical-align: top; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; } .bluebutton { -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); -background-image: -ms-linear-gradient(top,#4d90fe,#4787ed); -background-image: -o-linear-gradient(top,#4d90fe,#4787ed); -background-image: linear-gradient(top,#4d90fe,#4787ed); -} - -.bluebutton:hover { -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); -background-image: -ms-linear-gradient(top,#4d90fe,#357ae8); -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; +color: #4d90fe!important; font-size: 18px; +padding-top: 0px; padding-bottom: 0px; padding-left: 6px; padding-right: 6px; margin-left: 0px; margin-right: 0px; text-align: center; vertical-align: top; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; } .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; +color: #3d9400!important; font-size: 18px; +padding-top: 0px; padding-bottom: 0px; padding-left: 6px; padding-right: 6px; margin-left: 0px; margin-right: 0px; text-align: center; vertical-align: top; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; } .redbutton { -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); -} - -.redbutton:hover { -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); -} - -.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: 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; width: 50px; vertical-align: top; padding-right: 4px; padding-top: 2px; padding-bottom: 4px; -overflow: hidden; text-overflow: ellipsis; -} - -.appdetails { -font-size: 13px; color: #808080; overflow: hidden; text-overflow: ellipsis; -} - -.apptitle { -font-size: 14px; font-weight: bold; overflow: hidden; text-overflow: ellipsis; -} - -/** - * Editor. - */ -.pagediv { -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; -} - -.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; --webkit-backface-visibility: hidden; -} - -.path { -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: "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; +color: #d14836!important; font-size: 18px; +padding-top: 0px; padding-bottom: 0px; padding-left: 6px; padding-right: 6px; margin-left: 0px; margin-right: 0px; text-align: center; vertical-align: top; +display: inline-block; line-height: 28px; min-height: 28px; min-width: 30px; } diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.js b/sca-cpp/trunk/modules/js/htdocs/ui.js index 2bd21f6ed4..64acf6c14f 100644 --- a/sca-cpp/trunk/modules/js/htdocs/ui.js +++ b/sca-cpp/trunk/modules/js/htdocs/ui.js @@ -26,37 +26,8 @@ var ui = {}; /** * Return a child element of a node with the given id. */ -ui.elementByID = function(node, id) { - if (node.skipNode == true) - return null; - if (node == document) +ui.elementByID = function(id) { return document.getElementById(id); - for (var i in node.childNodes) { - var child = node.childNodes[i]; - if (isNull(child)) - continue; - if (child.id == id) - return child; - var gchild = ui.elementByID(child, id); - if (gchild != null) - return gchild; - } - return null; -}; - -/** - * Remove ids in a tree of elements. - */ -ui.removeElementIDs = function(node) { - if (!isNull(node.id)) - node.id = null; - for (var i in node.childNodes) { - var child = node.childNodes[i]; - if (isNull(child)) - continue; - ui.removeElementIDs(child); - } - return true; }; /** @@ -65,16 +36,25 @@ ui.removeElementIDs = function(node) { function $(id) { if (id == document) return document; - return memo(document, '$' + id, function() { - return ui.elementByID($(document), id); - }); + return document.getElementById(id); } /** - * Un-memoize elements previously found by id. + * Remove ids from a tree of elements. */ -ui.unmemo$ = function(prefix) { - return prefix? unmemo(document, '$' + prefix) : unmemo(document); +ui.removeElementIDs = function(node) { + function cleanIDs(node) { + for(var i = 0; i < node.childNodes.length; i++) { + var c = node.childNodes[i]; + if(c.nodeType == 1) { + if (c.id != null) + c.id = null; + cleanIDs(c); + } + } + return true; + } + return cleanIDs(node); }; /** @@ -105,7 +85,7 @@ ui.fragment = function(url) { /** * Return the path and parameters of a URL. */ -ui.pathandparams = function(url) { +ui.pathAndParams = function(url) { var u = '' + url; var ds = u.indexOf('//'); var u2 = ds > 0? u.substring(ds + 2) : u; @@ -117,7 +97,7 @@ ui.pathandparams = function(url) { * Return a dictionary of query parameters in a URL. */ ui.queryParams = function(url) { - var qp = new Array(); + var qp = []; var qs = ui.query(url).split('&'); for (var i = 0; i < qs.length; i++) { var e = qs[i].indexOf('='); @@ -131,7 +111,7 @@ ui.queryParams = function(url) { * Return a dictionary of fragment parameters in a URL. */ ui.fragmentParams = function(url) { - var qp = new Array(); + var qp = []; var qs = ui.fragment(url).split('&'); for (var i = 0; i < qs.length; i++) { var e = qs[i].indexOf('='); @@ -142,23 +122,79 @@ ui.fragmentParams = function(url) { }; /** + * Get a style property a DOM element. + */ +ui.getStyle = function(e, name) { + return e.style.getPropertyValue(name); +}; + +/** + * Set a style property of a DOM element. + */ +ui.setStyle = function(e, name, v, async) { + if (e.style.getPropertyValue(name) == v) + return false; + if (!async) + return e.style.setProperty(name, v, null); + ui.render(function() { + return e.style.setProperty(name, v, null); + }); + return true; +}; + +/** + * Remove a style property from a DOM element. + */ +ui.removeStyle = function(e, name, async) { + if (!async) + return e.style.removeProperty(name); + ui.render(function() { + return e.style.removeProperty(name); + }); + return true; +}; + +/** + * Set the CSS class of a DOM element. + */ +ui.getClass = function(e) { + return e.className; +}; + +/** + * Set the CSS class of a DOM element. + */ +ui.setClass = function(e, v, async) { + if (e.className == v) + return false; + if (!async) { + e.className = v; + return true; + } + ui.render(function() { + e.className = v; + }); + return true; +}; + +/** * Convert a base64-encoded PNG image to a data URL. */ -ui.b64png = function(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) { +ui.b64JPEG = function(b64) { return 'data:image/jpeg;base64,' + b64.trim(); }; /** * Convert a data URL to a base64-encoded image. */ -ui.imgb64 = function(img) { +ui.imgB64 = function(img) { if (img.startsWith('data:')) return img.split(',')[1] return ''; @@ -198,36 +234,36 @@ ui.declareScript = function(s) { * Return the scripts elements under a given element. */ ui.innerScripts = function(e) { - return map(function(s) { return s.text; }, nodeList(e.getElementsByTagName('script'))); + return nodeList(e.getElementsByTagName('script')); }; /** * Evaluate a script. */ ui.evalScript = function(s) { - return eval('(function evalscript() { try { \n' + s + '\n} catch(e) { debug(e.stack); throw e; }})();'); + return eval('(function evalscript() {\n' + s + '\n})();'); }; /** * Include a script. */ ui.includeScript = function(s) { - //debug('include', s); - return eval('try { \n' + s + '\n} catch(e) { debug(e.stack); throw e; }'); + debug('ui.include', s); + return eval(s); }; /** * Return true if the client is a mobile device. */ -ui.mobiledetected = false; +ui.mobileDetected = false; ui.mobile = false; ui.isMobile = function() { - if (ui.mobiledetected) + if (ui.mobileDetected) return ui.mobile; var ua = navigator.userAgent; - 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)) + 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) || ua.match(/Mobile.*Firefox/i)) ui.mobile = true; - ui.mobiledetected = true; + ui.mobileDetected = true; return ui.mobile; }; @@ -246,17 +282,17 @@ ui.webkitVersion = function() { }; /** - * Return the Safari version. + * Return true if the client is Android based. */ -ui.browserVersion = function() { - return Number(navigator.userAgent.replace(/.*Version\/(\d+\.\d+).*/, '$1')); +ui.isAndroid = function() { + return navigator.userAgent.match(/Android/i); }; /** - * Return true if the client is Android based. + * Return the Android version. */ -ui.isAndroid = function() { - return navigator.userAgent.match(/Android/i); +ui.androidVersion = function() { + return Number(navigator.userAgent.replace(/.*Version\/(\d+\.\d+).*/, '$1')); }; /** @@ -281,6 +317,13 @@ ui.isSafari = function() { }; /** + * Return the Safari version. + */ +ui.safariVersion = function() { + return Number(navigator.userAgent.replace(/.*Version\/(\d+\.\d+).*/, '$1')); +}; + +/** * Return true if the client is Chrome. */ ui.isChrome = function() { @@ -288,6 +331,13 @@ ui.isChrome = function() { }; /** + * Return the Chrome version. + */ +ui.chromeVersion = function() { + return Number(navigator.userAgent.replace(/.*Chrome\/(\d+\.\d+).*/, '$1')); +}; + +/** * Return true if the client is Internet Explorer. */ ui.isMSIE = function() { @@ -302,53 +352,18 @@ ui.msieVersion = function() { }; /** - * Run a UI rendering function asynchronously. - */ -ui.async = function(f, t) { - window.setTimeout(function() { - return f(); - }, isNull(t)? 0 : t); - return true; -}; - -/** - * Delay the execution of a function. - */ -ui.delayed = {} -ui.delay = function(f, t) { - var id = window.setTimeout(function() { - delete ui.delayed[id]; - return f(); - }, isNull(t)? 0 : 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 (isNull(ui.animationFrame)) - // Use requestAnimationFrame when available, fallback to setInterval - ui.animationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || - window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || +ui.animationFrame = window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.msRequestAnimationFrame || function(f) { - if (!('interval' in f) || isNull(f.interval)) { + if (isNull(f.interval)) { // First call, setup the interval f.interval = window.setInterval(function animation() { f.clearInterval = true; - try { + + // Call the animation function f(); - } catch(ex) {} + // If the animation function didn't call ui.animation again to // request another animation frame, clear the interval if (f.clearInterval) { @@ -363,50 +378,333 @@ ui.animation = function(f) { f.clearInterval = false; } }; + +ui.animation = function(f) { return ui.animationFrame.call(window, f); }; /** + * Run a UI rendering function asynchronously. + */ +ui.render = function(f) { + return ui.animation(f); +}; + +/** + * Delay the execution of a function. + */ +ui.unimportant = {} +ui.delay = function(f, t, unimportant) { + var id = window.setTimeout(function delayed() { + delete ui.unimportant[id]; + return f(); + }, isNull(t)? 0 : t); + if (unimportant) + ui.unimportant[id] = id; + return id; +}; + +/** + * Cancel the execution of a delayed function. + */ +ui.cancelDelay = function(id) { + delete ui.unimportant[id]; + return window.clearTimeout(id); +}; + +/** * Convert a CSS position to a numeric position. */ -ui.numpos = function(p) { - return p == ''? 0 : Number(p.substr(0, p.length - 2)); +ui.npos = function(p) { + return p == null || p == ''? 0 : Number(p.substr(0, p.length - 2)); }; /** * Convert a numeric position to a CSS pixel position. */ -ui.pixpos = function(p) { +ui.pxpos = function(p) { return p + 'px'; }; /** + * Show a status message. + */ +ui.statusElement = undefined; + +ui.initStatus = function() { + ui.statusElement = $('status'); + if (isNull(ui.statusElement)) + return; + ui.setClass(ui.statusElement, ui.isMobile()? 'status3dm' : 'status3d'); + ui.setStyle(ui.statusElement, 'display', 'none'); + + function divtransitionend(e) { + ui.setClass(e.target, ui.isMobile()? 'status3dm' : 'status3d'); + ui.setStyle(e.target, 'display', 'none'); + e.target.error = false; + } + ui.statusElement.addEventListener('webkitTransitionEnd', divtransitionend, false); + ui.statusElement.addEventListener('transitionend', divtransitionend, false); + return true; +}; + +ui.status = function(s, c) { + debug('ui.status', s); + if(isNull(ui.statusElement) || ui.statusElement.error) + return s; + ui.statusElement.innerHTML = '<span class="' + (c? c : 'okstatus') + '">' + s + '</span>'; + ui.setClass(ui.statusElement, ui.isMobile()? 'status3dm' : 'status3d'); + ui.setStyle(ui.statusElement, 'display', 'block'); + ui.statusElement.error = c == 'errorstatus'; + if(ui.statusElement.delay) + ui.cancelDelay(ui.statusElement.delay); + ui.statusElement.delay = ui.delay(function hidestatus() { + ui.setClass(ui.statusElement, ui.isMobile()? 'statusout3dm' : 'statusout3d'); + ui.statusElement.error = false; + }, c == 'errorstatus'? 8000 : 3000); + return s; +}; + +/** + * Show an error message. + */ +ui.error = function(s) { + debug('ui.error', s); + return ui.status(s, 'errorstatus'); +}; + +/** + * Show the online/offline status. + */ +ui.onlineStatus = function() { + return navigator.onLine? true : errorstatus('Offline'); +}; + +/** + * Show the working/ready indicator. + */ +ui.workingElement = undefined; +ui.initWorking = function() { + ui.workingElement = $('working'); +}; + +ui.working = function() { + debug('ui.working'); + if (isNull(ui.workingElement)) + return false; + return ui.setStyle(ui.workingElement, 'display', 'block'); +}; + +ui.ready = function() { + debug('ui.ready'); + if (isNull(ui.workingElement)) + return false; + return ui.setStyle(ui.workingElement, 'display', 'none'); +}; + +/** + * Get and cache a resource. + */ +ui.appcache = {}; +ui.appcache.get = function(uri, mode) { + debug('ui.appcache.get', uri, mode); + + // Get resource from local storage first + var h = uri.indexOf('#'); + var u = h == -1? uri : uri.substring(0, h); + if(mode != 'remote') { + var item = lstorage.getItem('ui.r.' + u); + if(item != null && item != '') + return item; + if(mode == 'local') + return undefined; + } + + // Get resource from network + var http = new XMLHttpRequest(); + http.open("GET", mode == 'remote'? (u + '?t=' + new Date().getTime() + '&r=' + Math.random()) : u, false); + http.setRequestHeader('Accept', '*/*'); + http.setRequestHeader('X-Cache-Control', 'no-cache'); + http.send(null); + if(http.status == 200) { + var ct = http.getResponseHeader("Content-Type"); + if(http.responseText == '' || ct == null || ct == '') { + error('http error', u, 'No-Content'); + return undefined; + } + lstorage.setItem('ui.r.' + u, http.responseText); + return http.responseText; + } + error('http error', u, http.status, http.statusText); + + // Redirect to login page + if(http.status == 403 && window.top.location.href.pathname != '/logout/dologout/') { + if(window.onloginredirect) + window.onloginredirect(new Error('403 ' + http.statusText)); + } + return undefined; +}; + +/** + * Remove a resource from the cache. + */ +ui.appcache.remove = function(uri) { + debug('ui.appcache.remove', uri); + var h = uri.indexOf('#'); + var u = h == -1? uri : uri.substring(0, h); + return lstorage.removeItem(u); +}; + +/** + * Default app cache handling behavior. + */ +ui.onappcache = function(manifest, resources) { + + if(ui.isMobile() && !ui.isFirefox()) { + // On mobile devices, trigger usage of an application cache manifest + // Except on mobile Firefox which fails to send cookies with cache manifest requests + window.onappcachechecking = function(e) { + debug('appcache checking', e); + ui.working(); + }; + window.onappcacheerror = function(e) { + debug('appcache error', e); + ui.onlineStatus(); + ui.ready(); + return false; + }; + window.onappcachenoupdate = function(e) { + debug('appcache noupdate', e); + ui.ready(); + }; + window.onappcachedownloading = function(e) { + debug('appcache downloading', e); + ui.working(); + ui.status('Updating'); + }; + window.onappcacheprogress = function(e) { + debug('appcache progress', e); + ui.working(); + ui.status('Updating'); + }; + window.onappcacheupdateready = function(e) { + debug('appcache updateready', e); + + // Update offline resources in local storage and reload the page + ui.status('Updating'); + applicationCache.swapCache(); + ui.delay(function swapappcache() { + debug('appcache swapped', e); + map(function(res) { + ui.appcache.remove(car(res)); + ui.appcache.get(car(res), 'remote'); + }, resources); + ui.status('Installed'); + ui.ready(); + + debug('reloading'); + window.location.reload(); + }); + }; + window.onappcachecached = function(e) { + debug('appcache cached', e); + + // Install offline resources in local storage + ui.status('Installing'); + ui.delay(function installoffline() { + map(function(res) { + ui.appcache.remove(car(res)); + ui.appcache.get(car(res), 'remote'); + }, resources); + ui.status('Installed'); + ui.ready(); + }); + }; + + window.onloadappcache = function() { + debug('appcache iframe loaded'); + }; + + var installer = $('installer'); + installer.innerHTML = '<iframe src="' + manifest + '/" class="installer"></iframe>'; + + } else { + // On non-mobile devices, check for cache-manifest changes ourselves. + ui.working(); + var lcmf = ui.appcache.get(manifest + '/cache-manifest.cmf', 'local'); + var rcmf = ui.appcache.get(manifest + '/cache-manifest.cmf', 'remote'); + if(lcmf == rcmf) { + ui.ready(); + return true; + } + + debug('cache-manifest changed, reloading'); + ui.status(isNull(lcmf)? 'Installing' : 'Updating'); + ui.delay(function reloadapp() { + map(function(res) { + ui.appcache.remove(car(res)); + ui.appcache.get(car(res), 'remote'); + }, resources); + ui.ready(); + if(!isNull(lcmf)) { + ui.status('Installed'); + ui.ready(); + + debug('reloading'); + window.location.reload(); + } + }); + } +}; + +/** * Default page load behavior. */ ui.filler = null; ui.onload = function() { + debug('ui.onload'); + + // Initialize status and working elements + ui.initStatus(); + ui.initWorking(); + + // Set orientation change handler + document.body.onorientationchange = function(e) { + return ui.onorientationchange(e); + }; + + // Handle network offline/online events. + window.addEventListener('offline', function(e) { + debug('going offline'); + ui.status('Offline'); + }, false); + window.addEventListener('online', function(e) { + debug('going online'); + ui.status('Online'); + }, false); // 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); + ui.setClass(ui.filler, 'filler'); + ui.setStyle(ui.filler, 'height', ui.pxpos(window.orientation == 0? Math.floor(window.innerHeight * 1.5) : Math.floor(window.innerHeight * 1.5))); document.body.appendChild(ui.filler); } else { // Style scroll bars - var h = document.getElementsByTagName('html'); - if (!isNull(h)) - h[0].className = h[0].className? h[0].classname + ' flatscrollbars' : 'flatscrollbars'; + var h = nodeList(document.getElementsByTagName('html')); + if (!isNull(h)) { + ui.setClass(car(h), car(h).className? car(h).classname + ' flatscrollbars' : 'flatscrollbars'); + } } // Scroll to hide the address bar - document.body.style.display = 'block'; - window.scrollTo(0, 0); + ui.setStyle(document.body, 'display', 'block'); + document.body.scrollTop = 0; // Set unload handler window.onunload = function() { - window.scrollTo(0, 0); + document.body.scrollTop = 0; return true; }; @@ -417,13 +715,15 @@ ui.onload = function() { * Default orientation change behavior. */ ui.onorientationchange = function(e) { + debug('ui.onorientationchange'); // Adjust filler height if (!isNull(ui.filler)) - ui.filler.style.height = ui.pixpos(window.orientation == 0? screen.height : screen.width); + ui.setStyle(ui.filler, 'height', ui.pxpos(window.orientation == 0? Math.floor(window.innerHeight * 1.5) : Math.floor(window.innerHeight * 1.5))); - // Scroll to hide the address bar - window.scrollTo(0, 0); + // Scroll to refresh the page + document.body.scrollTop = document.body.scrollTop + 1; + document.body.scrollTop = document.body.scrollTop - 1; return true; }; @@ -431,22 +731,52 @@ ui.onorientationchange = function(e) { * Navigate to a new document. */ ui.navigate = function(url, win) { - //debug('navigate', url, win); + debug('ui.navigate', url, win); + if (url == '' || url == '#') + return false; + + function cleanup() { + // 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; + } + + // Cancel any cancelable HTTP requests + if (typeof HTTPBindingClient != 'undefined') + HTTPBindingClient.cancelRequests(); + + // Automatically cancel unimportant timers + for (var d in ui.unimportant) + ui.cancelDelay(d); + return true; + } // Open a new window if (win == '_blank') { + debug('window.open', url, win); window.top.open(url, win); return false; } // Open a new document in the current window if (win == '_self') { + cleanup(); + debug('window.open', url, win); window.top.open(url, win); return false; } // Reload the current window if (win == '_reload') { + cleanup(); + debug('window.reload', url); window.top.location = url; window.top.location.reload(); return false; @@ -454,36 +784,18 @@ ui.navigate = function(url, win) { // Let the current top window handle the navigation if (win == '_view') { - if (!window.top.onnavigate) - return window.top.open(url, '_self'); + cleanup(); - // 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; + if (!window.top.onnavigate) { + debug('window.open', url, '_self'); + window.top.open(url, '_self'); + return false; } - - // Cancel any cancelable HTTP requests - HTTPBindingClient.cancelRequests(); - - // Cleanup memoized element lookups - ui.unmemo$(); - - // Cancel any timers - for (d in ui.delayed) - ui.cancelDelay(d); - - // Navigate window.top.onnavigate(url); return false; } + debug('window.open', url, win); window.top.open(url, win); return false; } @@ -492,7 +804,7 @@ ui.navigate = function(url, win) { * Bind a click handler to a widget. */ ui.ontouchstart = function(widget, e) { - //debug('ontouchstart'); + debug('ui.ontouchstart', widget.id); widget.down = true; widget.moved = false; var t = e.touches[0]; @@ -514,10 +826,11 @@ ui.ontouchmove = function(widget, e) { }; ui.ontouchend = function(widget, e) { - //debug('ontouchend'); + debug('ui.ontouchend', widget.id); widget.down = false; if (!widget.moved) { e.preventDefault(); + debug('ui.fastonclick', widget.id); return widget.onclick(e); } }; @@ -535,7 +848,7 @@ ui.onclick = function(widget, handler) { }; } widget.onclick = function(e) { - //debug('onclick'); + debug('ui.onclick', widget.id); return handler(e); }; return widget; @@ -544,61 +857,131 @@ ui.onclick = function(widget, handler) { /** * Build a portable <a href> tag. */ -ui.href = function(id, loc, target, html) { +ui.href = function(id, loc, target, clazz, html) { if (target == '_blank') - return '<a id="' + id + '" href="' + loc + '" target="_blank">' + html + '</a>'; - return '<a id="' + id + '" href="' + loc + '" ' + (ui.isMobile()? 'ontouchstart="return ui.ontouchstart(this, event);" ontouchmove="return ui.ontouchmove(this, event);" ontouchend="return ui.ontouchend(this, event);" ' : '') + 'onclick="return ui.navigate(\'' + loc + '\', \'' + target + '\');">' + html + '</a>'; + return '<a href="' + loc + '" target="_blank"><span id="' + id + '" class="' + clazz + '">' + html + '</span></a>'; + return '<a href="' + loc + '" ' + + (ui.isMobile()? 'ontouchstart="return ui.ontouchstart(this, event);" ontouchmove="return ui.ontouchmove(this, event);" ontouchend="return ui.ontouchend(this, event);" ' : '') + + 'onclick="return ui.navigate(\'' + loc + '\', \'' + target + '\');"><span id="' + id + '" class="' + clazz + '">' + html + '</span></a>'; +}; + +/** + * Update a <a href> tag. + */ +ui.updateHref = function(item, loc, target) { + if (!isNull(loc) && !isNull(target)) { + var link = item.parentNode; + if (target == '_blank') { + link.href = loc; + link.target = '_blank'; + } else { + link.href = loc; + link.setAttribute('onclick', 'return ui.navigate(\'' + loc + '\', \'' + target + '\');'); + } + } + return item; }; /** * Build a menu bar. */ -ui.menu = function(id, name, href, target, hilight) { +ui.menuItem = function(id, name, href, target, hilight) { function Menu() { this.content = function() { if (hilight == true) - return ui.href(id, href, target, '<span class="tbarsmenu">' + name + '</span>'); + return ui.href(id, href, target, 'tbarsmenu', name); else if (hilight == false) - return ui.href(id, href, target, '<span class="tbaramenu">' + name + '</span>'); + return ui.href(id, href, target, 'tbaramenu', name); else - return ui.href(id, href, target, '<span class="' + hilight + '">' + name + '</span>'); + return ui.href(id, href, target, hilight, name); }; } return new Menu(); }; -ui.menufunc = function(id, name, fun, hilight) { +ui.textItem = function(id, name, hilight) { + function Item() { + this.content = function() { + return name; + }; + } + return new Item(); +}; + +ui.menuFunc = function(id, name, fun, hilight) { function Menu() { this.content = function() { - function href(id, fun, html) { - return '<a id="' + id + '" href="/" ' + (ui.isMobile()? 'ontouchstart="return ui.ontouchstart(this, event);" ontouchmove="return ui.ontouchmove(this, event);" ontouchend="return ui.ontouchend(this, event);" ' : '') + 'onclick="' + fun + '">' + html + '</a>'; + function href(id, fun, clazz, html) { + return '<a href="/" ' + + (ui.isMobile()? 'ontouchstart="return ui.ontouchstart(this, event);" ontouchmove="return ui.ontouchmove(this, event);" ontouchend="return ui.ontouchend(this, event);" ' : '') + + 'onclick="' + fun + '"><span id="' + id + '" class="' + clazz + '">' + html + '</span></a>'; } if (hilight == true) - return href(id, fun, '<span class="tbarsmenu">' + name + '</span>'); + return href(id, fun, 'tbarsmenu', name); else if (hilight == false) - return href(id, fun, '<span class="tbaramenu">' + name + '</span>'); + return href(id, fun, 'tbaramenu', name); else - return href(id, fun, '<span class="' + hilight + '">' + name + '</span>'); + return href(id, fun, hilight, name); }; } return new Menu(); }; -ui.menubar = function(left, right) { - var bar = ''; - for (i in left) - bar = bar + '<span class="tbarleft">' + left[i].content() + '</span>'; - for (i in right) - bar = bar + '<span class="tbarright">' + right[i].content() + '</span>'; - return bar; +ui.menuBar = function(left, center, right) { + return '<span class="tbartitle">' + + reduce(function(bar, item) { + return bar + '<span class="tbarcenter">' + item.content() + '</span>'; + }, '', center) + + '</span><span class="tbaritems">' + + reduce(function(bar, item) { + return bar + '<span class="tbarleft">' + item.content() + '</span>'; + }, '', left) + + reduce(function(bar, item) { + return bar + '<span class="tbarright">' + item.content() + '</span>'; + }, '', right) + + '</span>'; +}; + +ui.cmenuBar = function(items) { + return reduce(function(bar, item) { + return bar + '<span class="tbarcenter">' + item.content() + '</span>'; + }, '', items); }; /** - * Convert a list of elements to an HTML table. + * Update a menu item. */ -ui.datatable = function(l) { +ui.updateMenuItem = function(item, name, href, target, hilight) { + if (!isNull(name)) { + if (item.innerHTML != name) + item.innerHTML = name; + } + if (!isNull(hilight)) { + if (hilight == true) + ui.setClass(item, 'tbarsmenu'); + else if (hilight == false) + ui.setClass(item, 'tbaramenu'); + else + ui.setClass(item, hilight); + } + if (!isNull(href) && !isNull(target)) { + var link = item.parentNode; + if (target == '_blank') { + link.href = href; + link.target = '_blank'; + } else { + link.href = href; + link.setAttribute('onclick', 'return ui.navigate(\'' + href + '\', \'' + target + '\');'); + } + } + return item; +}; +/** + * Convert a list of elements to an HTML table. + */ +ui.dataTable = function(l) { function indent(i) { if (i == 0) return ''; @@ -621,30 +1004,23 @@ ui.datatable = function(l) { // Generate table row for a simple element value if (elementHasValue(e)) { var v = elementValue(e); - if (!isList(v)) { - return '<tr><td class="datatdl">' + indent(i) + elementName(e).slice(1) + '</td>' + - '<td class="datatdr tdw">' + (v != null? v : '') + '</td></tr>' + - rows(cdr(l), i); - } - + if (!isList(v)) + return '<tr><td class="datatdl">' + indent(i) + elementName(e).substring(1) + '</td>' + + '<td class="datatdr tdw">' + (v != null? v : '') + '</td></tr>' + rows(cdr(l), i); return rows(expandElementValues(elementName(e), v), i) + rows(cdr(l), i); } // Generate table row for an element with children - return '<tr><td class="datatdl">' + indent(i) + elementName(e).slice(1) + '</td>' + - '<td class="datatdr tdw">' + '</td></tr>' + - rows(elementChildren(e), i + 1) + - rows(cdr(l), i); + return '<tr><td class="datatdl">' + indent(i) + elementName(e).substring(1) + '</td>' + + '<td class="datatdr tdw">' + '</td></tr>' + rows(elementChildren(e), i + 1) + rows(cdr(l), i); } - 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. */ -ui.datalist = function(l) { - +ui.dataList = function(l) { function rows(l, i) { if (isNull(l)) return ''; @@ -661,25 +1037,21 @@ ui.datalist = function(l) { // Generate table row for a simple element value if (elementHasValue(e)) { var v = elementValue(e); - if (!isList(v)) { - return '<tr><td class="datatd tdw">' + (v != null? v : '') + '</td></tr>' + - rows(cdr(l), i); - } - + if (!isList(v)) + return '<tr><td class="datatd tdw">' + (v != null? v : '') + '</td></tr>' + rows(cdr(l), i); return rows(expandElementValues(elementName(e), v), i) + rows(cdr(l), i); } // Generate rows for an element's children return rows(elementChildren(e), i + 1) + rows(cdr(l), i); } - 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) { +ui.readFile = function(file, onerror, onprogress, onload) { var reader = new FileReader(); reader.onerror = function(e) { return onerror(); @@ -694,31 +1066,147 @@ ui.readfile = function(file, onerror, onprogress, onload) { }; /** - * Read an image url and convert it to a data url. + * Draw an image on a canvas and convert it to a data URL. */ -ui.readimageurl = function(url, onerror, onprogress, onload, width, height) { - // Create a canvas to draw the image +ui.drawImage = function(img, onload, width, height, crop) { + // Rotate an image + function rotate(icanvas, onload) { + debug('ui.drawImage.rotate'); + var img = document.createElement('img'); + img.onload = function() { var canvas = document.createElement('canvas'); - if (width) - canvas.width = width; - if (height) - canvas.height = height; + canvas.width = icanvas.height; + canvas.height = icanvas.width; + var ctx = canvas.getContext('2d'); + ctx.setTransform(0, 1, -1, 0, icanvas.height, 0); + ctx.drawImage(img, 0, 0, icanvas.width, icanvas.height); + onload(canvas); + }; + img.src = icanvas.toDataURL('image/png') + return true; + } + + // Draw the image on a canvas and convert it to a JPEG data URL + function draw(img, onload, sx, sy, swidth, sheight, tx, ty, twidth, theight) { + debug('ui.drawImage.draw', sx, sy, swidth, sheight, tx, ty, twidth, theight); + var canvas = document.createElement('canvas'); + canvas.width = twidth; + canvas.height = theight; + var ctx = canvas.getContext('2d'); + ctx.drawImage(img, sx, sy, swidth, sheight, tx, ty, twidth, theight); + return onload(canvas); + } + + // Resize and optionally crop an image + function resize(img, onload, width, height, oncrop) { + debug('ui.drawImage.resize'); + var iwidth = img.width; + var iheight = img.height; + if (width || height || crop) { + if (crop) { + // Crop to fit target canvas size + var tratio = width / height; + var oratio = iwidth / iheight; + if (tratio > oratio) { + var scale = width / iwidth; + var cwidth = iwidth; + var cheight = height / scale; + var cut = (iheight - cheight) / 2; + // Crop top and bottom edges, then resize + return draw(img, onload, 0, cut, cwidth, cut + cheight, 0, 0, width, height); + } else if (tratio < oratio) { + var scale = height / iheight; + var cwidth = width / scale; + var cheight = iheight; + var cut = (iwidth - cwidth) / 2; + // Crop left and right edges, then resize + return draw(img, onload, cut, 0, cut + cwidth, cheight, 0, 0, width, height); + } else { + // Just resize + return draw(img, onload, 0, 0, iwidth, iheight, 0, 0, width, height); + } + } else { + // Resize to make the image fit + if (iwidth <= width && iheight == height) { + return draw(img, onload, 0, 0, iwidth, iheight, 0, 0, iwidth, iheight); + } else { + var tratio = width / height; + var oratio = iwidth / iheight; + if (tratio > oratio) { + // Resize to make height fit + var scale = height / iheight; + var swidth = iwidth * scale; + var sheight = height; + return draw(img, onload, 0, 0, iwidth, iheight, 0, 0, swidth, sheight); + } else if (tratio < oratio) { + // Resize to make width fit + var scale = width / iwidth; + var swidth = width; + var sheight = iheight * scale; + return draw(img, onload, 0, 0, iwidth, iheight, 0, 0, swidth, sheight); + } else { + // Resize to make both width and height fit + return draw(img, onload, 0, 0, iwidth, iheight, 0, 0, width, height); + } + } + } + } else { + // Draw image as is + return draw(img, onload, 0, 0, iwidth, iheight, 0, 0, iwidth, iheight); + } + } + + // Draw the image, optionally rotate, scale and crop it + (function drawImage() { + var iwidth = img.width; + var iheight = img.height; + document.body.removeChild(img); + var nwidth = img.width; + var nheight = img.height; + debug('ui.drawImage', 'img.width', iwidth, 'img.height', iheight, 'nwidth', nwidth, 'nheight', nheight, 'width', width, 'height', height, 'crop', crop); + + if (iwidth != iheight && iwidth == nheight) + // Rotate and resize the image + return resize(img, function(canvas) { + return rotate(canvas, function(canvas) { + return onload(canvas.toDataURL('image/jpeg', 0.95)); + }); + }, height, width, crop); + else { + // Just resize the image + return resize(img, function(canvas) { + return onload(canvas.toDataURL('image/jpeg', 0.95)); + }, width, height, crop); + } + })(); +} + +/** + * Read an image url and convert it to a data url. + */ +ui.readImageURL = function(url, onerror, onprogress, onload, width, height, crop) { + if(!width && !height && !crop && url.substring(0, 5) == 'data:') { + // Just use the given data URL if we're not resizing the image + debug('ui.readImageURL', 'original url'); + onprogress(90); + ui.delay(function() { + return onload(url); + }); + return true; + } // Create an image - var img = new Image(); + var img = document.createElement('img'); + ui.setStyle(img, 'visibility', 'hidden'); + document.body.appendChild(img); img.onerror = function(e) { + document.body.removeChild(img); 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')); + debug('ui.readImageURL', 'new data url'); + return ui.drawImage(img, onload, width, height, crop); }; // Load the image @@ -730,11 +1218,24 @@ ui.readimageurl = function(url, onerror, onprogress, onload, width, height) { /** * Read an image file or url and convert it to a data url. */ -ui.readimage = function(img, onerror, onprogress, onload, width, height) { +ui.readImageFile = function(img, onerror, onprogress, onload, width, height, crop) { 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); + return ui.readImageURL(img, onerror, onprogress, onload, width, height, crop); + return ui.readFile(img, onerror, onprogress, function onfile(url) { + return ui.readImageURL(url, onerror, onprogress, onload, width, height, crop); + }); +}; + +/** + * Read an image and convert it to a data url. + */ +ui.readImage = function(img, onload, width, height, crop) { + if(!width && !height && img.src.substring(0, 5) == 'data:') { + // Just use the given data URL if we're not resizing the image + return onload(img.src); + } + + // Draw the image + return ui.drawImage(img, onload, width, height, crop); }; diff --git a/sca-cpp/trunk/modules/js/htdocs/util.js b/sca-cpp/trunk/modules/js/htdocs/util.js index a8fec3994d..00ebd7a0c6 100644 --- a/sca-cpp/trunk/modules/js/htdocs/util.js +++ b/sca-cpp/trunk/modules/js/htdocs/util.js @@ -24,200 +24,298 @@ /** * Scheme-like lists. */ +function cell(car, cdr) { + this.car = car; + this.cdr = cdr; +} + +cell.prototype.toString = function() { + return writeValue(this); +}; + function cons(car, cdr) { - var a = new Array(); - a.push(car); - return a.concat(cdr); + return new cell(car, cdr); } -function car(l) { - return l[0]; +var nil = new cell(undefined, null); + +function mklist() { + if(arguments.length == 0) + return nil; + var l = nil; + for(var i = arguments.length - 1; i >= 0; i--) + l = cons(arguments[i], l); + return l; } -function first(l) { - return l[0]; +function mkalist(a) { + if(a.length == 0) + return nil; + var l = nil; + for(var i = a.length - 1; i >= 0; i--) + l = cons(a[i], l); + return l; } -function cdr(l) { - return l.slice(1); +function car(l) { + if(l.cdr == null) + throw new Error('car out of bounds'); + //error('car out of bounds'); + return l.car; } -function rest(l) { - return l.slice(1); +function cdr(l) { + if(l.cdr == null) + throw new Error('cdr out of bounds'); + //error('cdr out of bounds'); + return l.cdr; } function cadr(l) { - return l[1]; + return car(cdr(l)); } function cddr(l) { - return l.slice(2); + return cdr(cdr(l)); } function caddr(l) { - return l[2]; + return car(cdr(cdr(l))); } function cdddr(l) { - return l.slice(3); + return cdr(cdr(cdr(l))); } function cadddr(l) { - return l[3]; + return car(cdr(cdr(cdr(l)))); +} + +function last(l) { + if(l == nil) + throw new Error('last out of bounds'); + //error('last out of bounds'); + if(cdr(l) == nil) + return car(l); + return last(cdr(l)); } function append(a, b) { - return a.concat(b); + if(a == nil) + return b; + return cons(car(a), append(cdr(a), b)); } function reverse(l) { - return l.slice(0).reverse(); + function reverseIter(acc, l) { + if(l == nil) + return acc; + return reverseIter(cons(car(l), acc), cdr(l)); + } + return reverseIter(nil, l); } -function range(a, b) { - var l = new Array(); - for (var x = a; x < b; x++) - l.push(x); - return l; +function seq(start, end) { + if(start == end) + return mklist(start); + if(start < end) + return cons(start, seq(start + 1, end)); + return cons(start, seq(start - 1, end)); } function isNull(v) { - return (v == null || typeof v == 'undefined' || (v.constructor == Array && v.length == 0)); + return v == nil || v == null || typeof v == 'undefined'; } function isSymbol(v) { - return (typeof v == 'string' && v.slice(0, 1) == "'"); + return typeof v == 'string' && v[0] == "'"; } function isString(v) { - return (typeof v == 'string' && v.slice(0, 1) != "'"); + return typeof v == 'string' && v[0] != "'"; } function isList(v) { - return (v != null && typeof v != 'undefined' && v.constructor == Array); + return v != null && typeof v != 'undefined' && typeof v.cdr != 'undefined'; } function isTaggedList(v, t) { - return (isList(v) && !isNull(v) && car(v) == t); + return isList(v) && v != nil && car(v) == t; } -var emptylist = new Array(); - -function mklist() { - if (arguments.length == 0) - return emptylist; - var a = new Array(); - for (i = 0; i < arguments.length; i++) - a[i] = arguments[i]; +function mkarray(l) { + return reduce(function(a, v) { + a[a.length] = v; return a; + }, [], l); } function length(l) { - return l.length; + function lengthRef(c, l) { + if(l == nil) + return c; + return lengthRef(c + 1, cdr(l)); + } + return lengthRef(0, l); } /** * Scheme-like associations. */ function assoc(k, l) { - if (isNull(l)) - return emptylist; - var n = l.length; - for(var i = 0; i < n; i++) { - if (k == car(l[i])) - return l[i]; - } - return emptylist; + if(l == nil) + return nil; + var c = car(l); + if(isList(c) && c != nil && k == car(c)) + return c; + return assoc(k, cdr(l)); } /** * Map, filter and reduce functions. */ function map(f, l) { - if (isNull(l)) - return l; - var n = l.length; - var a = new Array(); - for(var i = 0; i < n; i++) { - a.push(f(l[i])); - } - return a; + if(l == nil) + return nil; + return cons(f(car(l)), map(f, cdr(l))); } function filter(f, l) { - if (isNull(l)) - return l; - var n = l.length; - var a = new Array(); - for(var i = 0; i < n; i++) { - if (f(l[i])) - a.push(l[i]); - } - return a; + if(l == nil) + return nil; + if (f(car(l))) + return cons(car(l), filter(f, cdr(l))); + return filter(f, cdr(l)); } function reduce(f, i, l) { - if (isNull(l)) - return i; - return reduce(f, f(i, car(l)), cdr(l)); + function reduceAccumulate(acc, l) { + if(l == nil) + return acc; + return reduceAccumulate(f(acc, car(l)), cdr(l)); + }; + return reduceAccumulate(i, l); } /** - * Split a path into a list of segments. + * Sort. */ +function sort(f, l) { + return mkalist(mkarray(l).sort(f)); +} + +/** + * String split, join and tokenize functions. + */ +function split(s, d) { + return mkalist(s.split(d)); +} + +function join(l, d) { + return mkarray(l).join(d); +} + function tokens(path) { - return filter(function(s) { return length(s) != 0; }, path.split("/")); + return filter(function(s) { return s.length != 0; }, split(path, '/')); } /** - * Debug log a value. + * Log values to debug log. */ -var rconsole; +if(window.debugging == undefined) + window.debugging = false; +var remoteLog; +var bufferedLog; + +function debug() { + if (!window.debugging) + return false; + var s = ''; + for(var i = 0; i < arguments.length; i++) { + s += writeValue(arguments[i]); + if(i < arguments.length) + s += ' '; + } + if(remoteLog) + remoteLog.log(s); + if (bufferedLog) + bufferedLog[bufferedLog.length] = s; + return console.log(s); +} -function debug(v) { - try { +function error() { var s = ''; - for (i = 0; i < arguments.length; i++) { - s = s + writeValue(arguments[i]); + for(var i = 0; i < arguments.length; i++) { + s += writeValue(arguments[i]); + var a = arguments[i]; + if(a != null && typeof a == 'object' && typeof a.stack != 'undefined') { + s += ' '; + s += writeValue(a.stack); + } if(i < arguments.length) s = s + ' '; } - if (rconsole) { - try { - rconsole.log(s); - } catch (e) {} + if(remoteLog) + remoteLog.error(s); + if (bufferedLog) { + try { throw new Error(); } catch(t) { bufferedLog[bufferedLog.length] = writeValue(t.stack); } + bufferedLog[bufferedLog.length] = s; + } + return console.error(s); +} + +/** + * Log uncaught errors. + */ +if (typeof window != 'undefined') { + window.onerror = function(msg, url, line) { + error('window.onerror', msg, url, line); + return false; + }; +} + +/** + * Buffer log entries in memory. + */ +function bufferLog() { + bufferedLog = []; + return true; } - try { - console.log(s); - } catch (e) {} - } catch (e) {} + +function printLog() { + if (!bufferedLog) + return false; + for(var i in bufferedLog) + console.log(bufferedLog[i]); + return true; +} + +function clearLog() { + bufferedLog = []; return true; } /** - * Dump an object to the console. + * Dump an object to the log. */ function dump(o) { - try { - for (f in o) { - try { - debug('dump ' + f + '=' + o[f]); - } catch (e) {} - } - } catch (e) {} + if (!window.debugging) + return false; + for(var f in o) + debug('dump', f, '=', o[f]); return true; } /** * Return true if the current browser is Internet Explorer. */ -function isIE() { - if (typeof isIE.detected != 'undefined') - return isIE.detected; - isIE.detected = navigator.appName == 'Microsoft Internet Explorer'; - return isIE.detected; -}; +function isMSIE() { + if(typeof isMSIE.detected != 'undefined') + return isMSIE.detected; + isMSIE.detected = navigator.userAgent.match(/MSIE/i); + return isMSIE.detected; +} /** * External build configuration. @@ -227,32 +325,19 @@ if (isNull(config)) config = {}; /** - * Simple assert function. + * Assertion. */ -function AssertException() { -} - -AssertException.prototype.toString = function () { - return 'AssertException'; -}; - function assert(exp) { if(!exp) - throw new AssertException(); + throw new Error('assertion failed'); + return true; } /** * Write a list of strings. */ function writeStrings(l) { - if (isNull(l)) - return ''; - var s = ''; - var n = l.length; - for(var i = 0; i < n; i++) { - s = s + l[i]; - } - return s; + return reduce(function(a, s) { return a + s; }, '', l); } /** @@ -268,14 +353,14 @@ function writeValue(v) { } function writeList(l) { - if (isNull(l)) + if(l == nil) return ''; return ' ' + writeValue(car(l)) + writeList(cdr(l)); } if(!isList(v)) return writePrimitive(v); - if (isNull(v)) + if(v == nil) return '()'; return '(' + writeValue(car(v)) + writeList(cdr(v)) + ')'; } @@ -284,7 +369,7 @@ function writeValue(v) { * Apply a function and memoize its result. */ function memo(obj, key, f) { - if (!('memo' in obj)) { + if(typeof obj.memo == 'undefined') { obj.memo = {}; return obj.memo[key] = f(); } @@ -301,14 +386,15 @@ function unmemo(obj, prefix) { obj.memo = {}; return true; } - if (!('memo' in obj)) { + if(typeof obj.memo == 'undefined') { obj.memo = {}; return true; } - for (key in obj.memo) { + for(var key in obj.memo) { if(key.substring(0, prefix.length) == prefix) delete obj.memo[key]; } + return true; } /** @@ -322,12 +408,8 @@ lstorage.enabled = true; */ lstorage.key = function(i) { if(!lstorage.enabled) - return null; - try { + return undefined; return localStorage.key(i); - } catch(e) { - return null; - } }; /** @@ -336,11 +418,7 @@ lstorage.key = function(i) { lstorage.length = function() { if(!lstorage.enabled) return 0; - try { return localStorage.length; - } catch(e) { - return 0; - } }; /** @@ -348,12 +426,8 @@ lstorage.length = function() { */ lstorage.getItem = function(k) { if(!lstorage.enabled) - return null; - try { + return undefined; return localStorage.getItem(k); - } catch(e) { - return null; - } }; /** @@ -361,12 +435,11 @@ lstorage.getItem = function(k) { */ lstorage.setItem = function(k, v) { if(!lstorage.enabled) - return null; - try { + return v; + if (localStorage.getItem(k) != v) return localStorage.setItem(k, v); - } catch(e) { - return null; - } + else + return v; }; /** @@ -374,62 +447,72 @@ lstorage.setItem = function(k, v) { */ lstorage.removeItem = function(k) { if(!lstorage.enabled) - return null; - try { + return undefined; return localStorage.removeItem(k); - } catch(e) { - return null; - } }; /** * Returns a list of the properties of an object. */ function properties(o) { - var a = new Array(); - for (p in o) - a.push(p); - return a; + var l = nil; + for(var p in o) + l = cons(p, l); + return reverse(l); +} + +/** + * Convert a DOM node list to a regular list. + */ +function nodeList(n) { + if (n == null || n.length == 0) + return nil; + var l = nil; + for (var i = n.length - 1; i >= 0; i--) + l = cons(n[i], l); + return l; } /** * Convert a host name to a domain name. */ -function domainname(host) { +function domainName(host) { var ds = host.indexOf('//'); if(ds != -1) - return domainname(host.substring(ds + 2)); + return domainName(host.substring(ds + 2)); var s = host.indexOf('/'); if(s != -1) - return domainname(host.substring(0, s)); - var h = reverse(host.split('.')); - var d = (!isNull(cddr(h)) && caddr(h) == 'www')? mklist(car(h), cadr(h), caddr(h)) : mklist(car(h), cadr(h)); - return reverse(d).join('.'); + return domainName(host.substring(0, s)); + var h = reverse(split(host, '.')); + var d = (cddr(h) != nil && caddr(h) == 'www')? mklist(car(h), cadr(h), caddr(h)) : mklist(car(h), cadr(h)); + return join(reverse(d), '.'); } /** * Convert a host name to a top domain name. */ -function topdomainname(host) { - var d = reverse(domainname(host).split('.')); - return reverse(mklist(car(d), cadr(d))).join('.'); +function topDomainName(host) { + var d = reverse(split(domainName(host),'.')); + return join(mklist(car(d), cadr(d)), '.'); } /** * Return true if a host name is a subdomain. */ -function issubdomain(host) { - return host.split('.').length > 2; +function isSubDomain(host) { + return length(split(host, '.')) > 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=/; 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'; +function clearAuthCookie() { + var d = new Date(1970,01,01).toGMTString(); + var dn = domainName(window.location.hostname); + document.cookie = 'TuscanyOpenAuth=; expires=' + d + '; domain=.' + dn + '; path=/; secure; httponly'; + document.cookie = 'TuscanyOAuth1=; expires=' + d + '; domain=.' + dn + '; path=/; secure; httponly'; + document.cookie = 'TuscanyOAuth2=; expires=' + d + '; domain=.' + dn + '; path=/; secure; httponly'; + document.cookie = 'TuscanyOpenIDAuth=; expires=' + d + '; domain=.' + dn + '; path=/; secure; httponly'; return true; } @@ -439,7 +522,7 @@ function clearauthcookie() { function format() { var i = 0; var s = ''; - for (a in arguments) { + for(var a = 0; a < arguments.length; a++) { s = i == 0? arguments[a] : s.replace('{' + a + '}', arguments[a]); i++; } @@ -449,7 +532,7 @@ function format() { /** * Parse an XML dateTime. */ -function xmldatetime(xml) { +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) @@ -463,14 +546,14 @@ function xmldatetime(xml) { /** * Encode a string to a url-safe base64 format. */ -function safeb64encode(s) { +function safeB64Encode(s) { return btoa(s).replace(/\+/g, '-').replace(/\//g, '_').replace(/\=+$/, ''); } /** * Decode a url-safe base64 encoded string. */ -function safeb64decode(s) { +function safeB64Decode(s) { return atob((s.replace(/\-/g, '+').replace(/\_/g, '/') + '===').substring(0, s.length + (s.length % 4))); } @@ -497,7 +580,7 @@ function uuid4() { /** * Convert an hexadecimal string to ascii. */ -function hex2ascii(x) { +function hex2Ascii(x) { var a = ''; for(var i = 0; i < x.length; i += 2) a += String.fromCharCode(parseInt(x.substr(i, 2), 16)); @@ -512,7 +595,7 @@ function hex2ascii(x) { * Set the car of a list. */ function setcar(l, v) { - l[0] = v; + l.car = v; return l; } @@ -520,7 +603,7 @@ function setcar(l, v) { * Set the cadr of a list. */ function setcadr(l, v) { - l[1] = v; + l.cdr.car = v; return l; } @@ -528,35 +611,104 @@ function setcadr(l, v) { * Set the caddr of a list. */ function setcaddr(l, v) { - l[2] = v; + l.cdr.cdr.car = v; return l; } /** - * Append the elements of a list to a list. + * Set the cdr of a list. */ -function setappend(a, b) { - if (isNull(b)) +function setcdr(a, b) { + a.cdr = b; return a; - a.push(car(b)); - return setappend(a, cdr(b)); } /** - * Set the cdr of a list. + * Set the contents of a list. */ -function setcdr(a, b) { - a.length = 1; - return setappend(a, b); +function setList(a, b) { + if(b == a) + return a; + a.car = b.car; + a.cdr = b.cdr; + return a; } /** - * Set the contents of a list. + * Append the elements of a list to a list. */ -function setlist(a, b) { - if (b == a) - return b; - a.length = 0; - return setappend(a, b); +function setAppend(a, b) { + if(b.cdr == null) + return a; + return setList(a, append(a, b)); } +/** + * Uncomment to run the tests. + */ +/* +(function testUtil() { + console.log('Testing...'); + + assert(car(cons(1, nil)) == 1); + assert(car(mklist(1)) == 1); + assert(cadr(mklist(1, 2)) == 2); + + assert(0 == length(nil)); + assert(1 == length(mklist(1))); + assert(2 == length(cons(1, mklist(2)))); + + assert(car(append(mklist(1), mklist(2))) == 1); + assert(car(cdr(append(mklist(1), mklist(2)))) == 2); + assert(car(cdr(cdr(append(mklist(1), mklist(2, 3))))) == 3); + assert(isNull(cdr(cdr(cdr(append(mklist(1), mklist(2, 3))))))); + assert(last(mklist(1, 2, 3)) == 3); + assert('' + mklist(1, 2, 3) == '(1 2 3)'); + + function square(v) { return v * v; } + assert(isNull(map(square, nil))); + var m = map(square, mklist(2, 3)); + assert(car(m) == 4); + assert(car(cdr(m)) == 9); + + function add(x, y) { return x + y; } + assert(reduce(add, 0, mklist(1, 2, 3)) == 6); + + function isPositive(x) { return x >= 0; } + assert(car(filter(isPositive, mklist(1, -1, 2, -2))) == 1); + assert(cadr(filter(isPositive, mklist(1, -1, 2, -2))) == 2); + + assert(isNull(reverse(nil))); + assert(car(reverse(mklist(1, 2, 3))) == 3); + assert(cadr(reverse(mklist(1, 2, 3))) == 2); + + var l = mklist(mklist('x', 'X'), mklist('a', 'A'), mklist('y', 'Y'), mklist('a', 'AA')); + assert(car(assoc('a', l)) == 'a'); + assert(isNull(assoc('z', l))); + + var s = seq(0.0, 1000.0); + assert(1001 == length(s)); + function seqreduce(acc, v) { return acc + 1.0; } + assert(1001 == reduce(seqreduce, 0.0, s)); + + function compare(a, b) { return a < b? -1 : a == b? 0 : 1; } + var l2 = sort(compare, mklist(4, 3, 1, 2)); + assert(car(l2) == 1); + assert(last(l2) == 4); + + var t = new Date(); + var p = nil; + for(var i = 0; i < 100000; i++) { + p = cons(i, p); + } + for(var i = 0; i < 100000; i++) { + var x = car(p); + p = cdr(p); + } + console.log('list perf', new Date() - t, 'ms'); + + console.log('OK'); + return true; +})(); +*/ + diff --git a/sca-cpp/trunk/modules/js/htdocs/xmlutil.js b/sca-cpp/trunk/modules/js/htdocs/xmlutil.js index 29240dff9c..c8878bf2af 100644 --- a/sca-cpp/trunk/modules/js/htdocs/xmlutil.js +++ b/sca-cpp/trunk/modules/js/htdocs/xmlutil.js @@ -22,18 +22,6 @@ */ /** - * Convert a DOM node list to a regular list. - */ -function nodeList(n) { - var l = new Array(); - if (isNull(n)) - return l; - for (var i = 0; i < n.length; i++) - l[i] = n[i]; - return l; -} - -/** * Append a list of nodes to a parent node. */ function appendNodes(nodes, p) { @@ -41,7 +29,7 @@ function appendNodes(nodes, p) { return p; p.appendChild(car(nodes)); return appendNodes(cdr(nodes), p); -}; +} /** * Return the child attributes of an element. @@ -61,31 +49,29 @@ function childElements(e) { * Return the child text nodes of an element. */ function childText(e) { - function trim(s) { - return s.replace(/^\s*/, '').replace(/\s*$/, ''); - } - return filter(function(n) { return n.nodeType == 3 && trim(n.nodeValue) != ''; }, nodeList(e.childNodes)); + return filter(function(n) { return n.nodeType == 3 && n.nodeValue.trim().length != 0; }, nodeList(e.childNodes)); } /** * Read a list of XML attributes. */ -function readAttributes(p, a) { +function readAttributes(a) { if (isNull(a)) return a; var x = car(a); - return cons(mklist(attribute, "'" + x.nodeName, x.nodeValue), readAttributes(p, cdr(a))); + return cons(mklist(attribute, "'" + x.name, x.value), readAttributes(cdr(a))); } /** * Read an XML element. */ function readElement(e, childf) { - var l = append(append(mklist(element, "'" + e.nodeName), readAttributes(e, childf(e))), readElements(childElements(e), childf)); + var l = append(append(mklist(element, "'" + e.nodeName), readAttributes(childf(e))), readElements(childElements(e), childf)); var t = childText(e); if (isNull(t)) return l; - return append(l, mklist(car(t).nodeValue)); + var tv = reduce(function(a, n) { return a + n.nodeValue; }, '', t); + return append(l, mklist(tv)); } /** @@ -109,10 +95,10 @@ function isXML(l) { /** * Parse a list of strings representing an XML document. */ +var xmlParser = new DOMParser(); function parseXML(l) { var s = writeStrings(l); - var p = new DOMParser(); - return p.parseFromString(s, "text/xml"); + return xmlParser.parseFromString(s, "text/xml"); } /** @@ -121,7 +107,7 @@ function parseXML(l) { function readXMLDocument(doc) { var root = childElements(doc); if (isNull(root)) - return mklist(); + return nil; return mklist(readElement(car(root), childAttributes)); } @@ -129,29 +115,7 @@ function readXMLDocument(doc) { * Read a list of values from an XHTML element. */ function readXHTMLElement(xhtml) { - // Special XHTML attribute filtering on IE - function ieChildAttributes(e) { - var a = filter(function(n) { - // Filter out empty and internal DOM attributes - if (n.nodeType != 2 || isNull(n.nodeValue) || n.nodeValue == '') - return false; - if (n.nodeName == 'contentEditable' || n.nodeName == 'maxLength' || n.nodeName == 'loop' || n.nodeName == 'start') - return false; - return true; - }, nodeList(e.attributes)); - - if (e.style.cssText == '') - return a; - - // Add style attribute - var sa = new Object(); - sa.nodeName = 'style'; - sa.nodeValue = e.style.cssText; - return cons(sa, a); - } - - var childf = (typeof(XMLSerializer) != 'undefined')? childAttributes : ieChildAttributes; - return mklist(readElement(xhtml, childf)); + return mklist(readElement(xhtml, childAttributes)); } /** @@ -164,10 +128,9 @@ function readXML(l) { /** * Return a list of strings representing an XML document. */ +var xmlSerializer = new XMLSerializer(); function writeXMLDocument(doc) { - if (typeof(XMLSerializer) != 'undefined') - return mklist(new XMLSerializer().serializeToString(doc)); - return mklist(doc.xml); + return mklist(xmlSerializer.serializeToString(doc)); } /** @@ -185,7 +148,7 @@ function writeList(l, node, doc) { var token = car(l); if (isTaggedList(token, attribute)) { - if (isIE()) { + if (isMSIE()) { var aname = attributeName(token).substring(1); if (aname != 'xmlns') node.setAttribute(aname, '' + attributeValue(token)); @@ -207,7 +170,7 @@ function writeList(l, node, doc) { } var ns = xmlns(elementChildren(tok)); - if (isIE()) + if (isMSIE()) return doc.createElementNS(ns != null? ns : node.namespaceURI, elementName(tok).substring(1)); if (ns == null) return doc.createElement(elementName(tok).substring(1)); @@ -251,6 +214,6 @@ function writeXML(l, xmlTag) { writeList(l, doc, doc); if (!xmlTag) return writeXMLDocument(doc); - return mklist('<?xml version="1.0" encoding="UTF-8"?>\n' + writeXMLDocument(doc) + '\n'); + return mklist('<?xml version="1.0" encoding="UTF-8"?>\n' + car(writeXMLDocument(doc)) + '\n'); } |