diff options
author | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2013-08-26 03:04:34 +0000 |
---|---|---|
committer | jsdelfino <jsdelfino@13f79535-47bb-0310-9956-ffa450edef68> | 2013-08-26 03:04:34 +0000 |
commit | 2e5abd585874b18d5e94067ca7704a1966df3226 (patch) | |
tree | f82d228586a2b36a6b6135709bef51a99de73a68 /sca-cpp/trunk/modules/js/htdocs/util.js | |
parent | 1976d3e16febbd0339f330650ee0817f9fbe2637 (diff) |
Refactor base Javascript and CSS utilities and support server-side aggregation of HTML and Javascript.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1517415 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-cpp/trunk/modules/js/htdocs/util.js')
-rw-r--r-- | sca-cpp/trunk/modules/js/htdocs/util.js | 576 |
1 files changed, 364 insertions, 212 deletions
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,235 +24,320 @@ /** * 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]; - return a; +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 { - var s = ''; - for (i = 0; i < arguments.length; i++) { - s = s + writeValue(arguments[i]); - if (i < arguments.length) - s = s + ' '; +function error() { + var s = ''; + 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) {} - } - try { - console.log(s); - } catch (e) {} - } 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; +} + +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. */ var config; -if (isNull(config)) +if(isNull(config)) config = {}; /** - * Simple assert function. + * Assertion. */ -function AssertException() { -} - -AssertException.prototype.toString = function () { - return 'AssertException'; -}; - function assert(exp) { - if (!exp) - throw new AssertException(); + if(!exp) + 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); } /** @@ -260,22 +345,22 @@ function writeStrings(l) { */ function writeValue(v) { function writePrimitive(p) { - if (isSymbol(p)) + if(isSymbol(p)) return '' + p.substring(1); - if (isString(p)) + if(isString(p)) return '"' + p + '"'; return '' + p; } function writeList(l) { - if (isNull(l)) + if(l == nil) return ''; return ' ' + writeValue(car(l)) + writeList(cdr(l)); } - if (!isList(v)) + if(!isList(v)) return writePrimitive(v); - if (isNull(v)) + if(v == nil) return '()'; return '(' + writeValue(car(v)) + writeList(cdr(v)) + ')'; } @@ -284,11 +369,11 @@ 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(); } - if (key in obj.memo) + if(key in obj.memo) return obj.memo[key]; return obj.memo[key] = f(); } @@ -297,18 +382,19 @@ function memo(obj, key, f) { * Un-memoize stored results. */ function unmemo(obj, prefix) { - if (!prefix) { + if(!prefix) { obj.memo = {}; return true; } - if (!('memo' in obj)) { + if(typeof obj.memo == 'undefined') { obj.memo = {}; return true; } - for (key in obj.memo) { - if (key.substring(0, prefix.length) == prefix) + for(var key in obj.memo) { + if(key.substring(0, prefix.length) == prefix) delete obj.memo[key]; } + return true; } /** @@ -321,115 +407,112 @@ lstorage.enabled = true; * Get a key. */ lstorage.key = function(i) { - if (!lstorage.enabled) - return null; - try { - return localStorage.key(i); - } catch(e) { - return null; - } + if(!lstorage.enabled) + return undefined; + return localStorage.key(i); }; /** * Return the number of keys. */ lstorage.length = function() { - if (!lstorage.enabled) - return 0; - try { - return localStorage.length; - } catch(e) { + if(!lstorage.enabled) return 0; - } + return localStorage.length; }; /** * Get an item. */ lstorage.getItem = function(k) { - if (!lstorage.enabled) - return null; - try { - return localStorage.getItem(k); - } catch(e) { - return null; - } + if(!lstorage.enabled) + return undefined; + return localStorage.getItem(k); }; /** * Set an item. */ lstorage.setItem = function(k, v) { - if (!lstorage.enabled) - return null; - try { + if(!lstorage.enabled) + return v; + if (localStorage.getItem(k) != v) return localStorage.setItem(k, v); - } catch(e) { - return null; - } + else + return v; }; /** * Remove an item. */ lstorage.removeItem = function(k) { - if (!lstorage.enabled) - return null; - try { - return localStorage.removeItem(k); - } catch(e) { - return null; - } + if(!lstorage.enabled) + return undefined; + return localStorage.removeItem(k); }; /** * 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)); + if(ds != -1) + 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('.'); + if(s != -1) + 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,10 +532,10 @@ 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) + if(!match) return new Date(); return new Date(Date.UTC(match[1], parseInt(match[2]) - 1, match[3], match[9]? parseInt(match[4]) + parseInt(match[10]) * (match[9] == '+'? 1 : -1) : match[4], @@ -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))); } @@ -478,7 +561,7 @@ function safeb64decode(s) { * Return a uuid4. */ function uuid4() { - if (window.crypto && window.crypto.getRandomValues) { + if(window.crypto && window.crypto.getRandomValues) { var b = new Uint16Array(8); window.crypto.getRandomValues(b); function s4(n) { @@ -497,9 +580,9 @@ 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) + for(var i = 0; i < x.length; i += 2) a += String.fromCharCode(parseInt(x.substr(i, 2), 16)); return a; } @@ -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)) - return a; - a.push(car(b)); - return setappend(a, cdr(b)); +function setcdr(a, b) { + a.cdr = b; + return a; } /** - * 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; +})(); +*/ + |