diff options
Diffstat (limited to 'sca-cpp/branches/lightweight-sca/modules/js/htdocs')
9 files changed, 3413 insertions, 0 deletions
diff --git a/sca-cpp/branches/lightweight-sca/modules/js/htdocs/atomutil.js b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/atomutil.js new file mode 100644 index 0000000000..068b5de2fd --- /dev/null +++ b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/atomutil.js @@ -0,0 +1,184 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * ATOM data conversion functions. + */ +var atom = {}; + +/** + * Convert a list of elements to a list of values representing an ATOM entry. + */ +atom.entryElementValues = function(e) { + var lt = filter(selector(mklist(element, "'title")), e); + var t = mklist(element, "'title", isNil(lt)? '' : elementValue(car(lt))); + + var li = filter(selector(mklist(element, "'id")), e); + var i = mklist(element, "'id", isNil(li)? '' : elementValue(car(li))); + + var la = filter(selector(mklist(element, "'author")), e); + var lan = isNil(la)? mklist() : filter(selector(mklist(element, "'name")), car(la)); + var lae = isNil(la)? mklist() : filter(selector(mklist(element, "'email")), car(la)); + var laa = isNil(lan)? lae : lan; + var a = isNil(laa)? mklist() : mklist(mklist(element, "'author", elementValue(car(laa)))); + + var lu = filter(selector(mklist(element, "'updated")), e); + var u = isNil(lu)? mklist() : mklist(mklist(element, "'updated", elementValue(car(lu)))); + + var lc = filter(selector(mklist(element, "'content")), e); + var c = isNil(lc)? mklist() : mklist(mklist(element, "'content", elementValue(car(lc)))); + + return append(append(append(mklist(element, "'entry", t, i), a), u), c); +}; + +/** + * Convert a list of elements to a list of values representing ATOM entries. + */ +atom.entriesElementValues = function(e) { + if (isNil(e)) + return e; + return cons(atom.entryElementValues(car(e)), atom.entriesElementValues(cdr(e))); +}; + +/** + * Return true if a list of strings represents an ATOM entry. + */ +atom.isATOMEntry = function(l) { + if (!isXML(l)) + return false; + return car(l).match('<entry') != null && car(l).match('<feed') == null && car(l).match('="http://www.w3.org/2005/Atom"') != null; +}; + +/** + * Convert a DOM Document to a list of values representing an ATOM entry. + */ +atom.readATOMEntryDocument = function(doc) { + var e = readXMLDocument(doc); + if (isNil(e)) + return mklist(); + return mklist(atom.entryElementValues(car(e))); +}; + +/** + * Convert a list of strings to a list of values representing an ATOM entry. + */ +atom.readATOMEntry = function(l) { + return atom.readATOMEntryDocument(parseXML(l)); +}; + +/** + * Return true if a list of strings represents an ATOM feed. + */ +atom.isATOMFeed = function(l) { + if (!isXML(l)) + return false; + return car(l).match('<feed') != null && car(l).match('="http://www.w3.org/2005/Atom"') != null; +}; + +/** + * Convert a DOM document to a list of values representing an ATOM feed. + */ +atom.readATOMFeedDocument = function(doc) { + var f = readXMLDocument(doc); + if (isNil(f)) + return mklist(); + var t = filter(selector(mklist(element, "'title")), car(f)); + var i = filter(selector(mklist(element, "'id")), car(f)); + var e = filter(selector(mklist(element, "'entry")), car(f)); + return mklist(append( + mklist(element, "'feed", mklist(element, "'title", elementValue(car(t))), mklist(element, "'id", elementValue(car(i)))), + atom.entriesElementValues(e))); +}; + +/** + * Convert a list of strings to a list of values representing an ATOM feed. + */ +atom.readATOMFeed = function(l) { + return atom.readATOMFeedDocument(parseXML(l)); +}; + +/** + * Convert a list of values representy an ATOM entry to a list of elements. + */ +atom.entryElement = function(l) { + var title = elementValue(namedElementChild("'title", l)); + var id = elementValue(namedElementChild("'id", l)); + var author = namedElementChild("'author", l); + var email = isNil(author)? false : (elementValue(author).indexOf('@') != -1); + var updated = namedElementChild("'updated", l); + var content = namedElementChild("'content", l); + var text = isNil(content)? false : elementHasValue(content); + return append(append(append(append( + mklist(element, "'entry", mklist(attribute, "'xmlns", "http://www.w3.org/2005/Atom"), + mklist(element, "'title", mklist(attribute, "'type", "text"), title), mklist(element, "'id", id)), + isNil(author)? mklist() : mklist(element, "'author", + (email? mklist(element, "'email", elementValue(author)) : mklist(element, "'name", elementValue(author))))), + isNil(updated)? mklist() : mklist(element, "'updated", elementValue(updated))), + isNil(content)? mklist() : + mklist(append(mklist(element, "'content", mklist(attribute, "'type", text? "text" : "application/xml")), + text? mklist(elementValue(content)) : elementChildren(content)))), + mklist(mklist(element, "'link", mklist(attribute, "'href", id)))); +}; + +/** + * Convert a list of values representing ATOM entries to a list of elements. + */ +atom.entriesElements = function(l) { + if (isNil(l)) + return l; + return cons(atom.entryElement(car(l)), atom.entriesElements(cdr(l))); +}; + +/** + * Convert a list of values representing an ATOM entry to an ATOM entry. + */ +atom.writeATOMEntry = function(ll) { + var l = isNil(ll)? ll : car(ll); + return writeXML(mklist(atom.entryElement(l)), true); +}; + +/** + * Convert a list of values representing an ATOM feed to an ATOM feed. + */ +atom.writeATOMFeed = function(ll) { + var l = isNil(ll)? ll : car(ll); + var lt = filter(selector(mklist(element, "'title")), l); + var t = isNil(lt)? '' : elementValue(car(lt)); + var li = filter(selector(mklist(element, "'id")), l); + var i = isNil(li)? '' : elementValue(car(li)); + var f = mklist(element, "'feed", mklist(attribute, "'xmlns", "http://www.w3.org/2005/Atom"), + mklist(element, "'title", mklist(attribute, "'type", "text"), car(l)), + mklist(element, "'id", cadr(l))); + + // Write ATOM entries + var le = filter(selector(mklist(element, "'entry")), l); + if (isNil(le)) + return writeXML(mklist(f), true); + + // Write a single ATOM entry element with a list of values + if (!isNil(le) && !isNil(car(le)) && isList(car(caddr(car(le))))) { + var fe = append(f, atom.entriesElements(caddr(car(le)))); + return writeXML(mklist(fe), true); + } + + // Write separate ATOM entry elements + var fe = append(f, atom.entriesElements(le)); + return writeXML(mklist(fe), true); +}; + diff --git a/sca-cpp/branches/lightweight-sca/modules/js/htdocs/component.js b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/component.js new file mode 100644 index 0000000000..c3799ef708 --- /dev/null +++ b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/component.js @@ -0,0 +1,637 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * 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"). + */ + +/** + * Client component wiring API, supporting JSON and ATOM bindings. + */ + +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) { + this.name = name; + this.domain = domain; + this.uri = uri; + this.apply = this.createApplyMethod(); +} + +/** + * JSON-RPC request counter. + */ +HTTPBindingClient.jsonrpcID = 1; + +/** + * HTTPBindingClient implementation + */ + +/** + * Generate client proxy apply method. + */ +HTTPBindingClient.prototype.createApplyMethod = function() { + var fn = function() { + var methodName = arguments[0]; + var args = []; + for(var i = 1; i < arguments.length; i++) + args.push(arguments[i]); + + var cb = null; + if (typeof args[args.length - 1] == "function") + cb = args.pop(); + + var req = HTTPBindingClient.makeJSONRequest(methodName, args, cb); + return fn.client.jsonApply(req); + }; + fn.client = this; + return fn; +}; + +/** + * Make a JSON-RPC request. + */ +HTTPBindingClient.makeJSONRequest = function(methodName, args, cb) { + var req = {}; + req.id = HTTPBindingClient.jsonrpcID++; + if (cb) + req.cb = cb; + var obj = {}; + obj.id = req.id; + obj.method = methodName; + obj.params = args; + req.data = JSONClient.toJSON(obj); + return req; +}; + +/** + * 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; +}; + +/** + * Apply a function remotely using JSON-RPC. + */ +HTTPBindingClient.prototype.jsonApply = function(req) { + // Connect to the service + var http = HTTPBindingClient.getHTTPRequest(); + var hascb = req.cb? true : false; + http.open("POST", this.uri, hascb); + http.setRequestHeader("Accept", "*/*"); + http.setRequestHeader("Content-Type", "application/json-rpc"); + + // Construct call back if we have one + if(hascb) { + http.onreadystatechange = function() { + if(http.readyState == 4) { + // Pass the result or exception + if(http.status == 200) { + var res = null; + try { + res = HTTPBindingClient.jsonResult(http); + try { + 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) {} + } + }; + + // Send the request + http.send(req.data); + return req.id; + } + + // Send the request and return the result or exception + http.send(req.data); + if (http.status == 200) + return HTTPBindingClient.jsonResult(http); + throw new HTTPBindingClient.Exception(http.status, http.statusText); +}; + + +/** + * REST GET method. + */ +HTTPBindingClient.prototype.get = function(id, cb) { + var u = id? (this.uri? this.uri + '/' + id : id) : this.uri; + var hascb = cb? true : false; + + // Get from local storage first + var ls = window.lstorage || localStorage; + var item = null; + try { item = ls.getItem(u); } catch(e) {} + //log('localStorage.getItem', u, item); + if (item != null && item != '') { + if (!hascb) + return item; + + // Pass local result to callback + try { + cb(item); + } catch (cbe) {} + } + + // Connect to the service + var http = HTTPBindingClient.getHTTPRequest(); + http.open("GET", u, hascb); + http.setRequestHeader("Accept", "*/*"); + + // Construct call back if we have one + if (hascb) { + http.onreadystatechange = function() { + //log('readystate', http.readyState, 'status', http.status, 'headers', http.getAllResponseHeaders()); + if (http.readyState == 4) { + // Pass result if different from local result + if (http.status == 200) { + + if (http.getResponseHeader("X-Login") != null) { + // Detect redirect to a login page + try { + var le = new HTTPBindingClient.Exception(403, 'X-Login'); + if (window.onloginredirect) + window.onloginredirect(le); + return cb(null, le); + } catch(cbe) {} + + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + // Report empty response + try { + return cb(null, new HTTPBindingClient.Exception(403, 'No-Content')); + } catch(cbe) {} + + } else { + if (item == null || http.responseText != item) { + // Store retrieved entry in local storage + if (http.responseText != null) { + //log('localStorage.setItem', u, http.responseText); + try { ls.setItem(u, http.responseText); } catch(e) {} + } + try { + return cb(http.responseText); + } catch(cbe) {} + } + } + } + else { + // Pass exception if we didn't have a local result + if (item == null) { + try { + return cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); + } catch(cbe) {} + } + } + } + }; + + // Send the request + http.send(null); + return true; + } + + // Send the request and return the result or exception + http.send(null); + if (http.status == 200) { + if (http.getResponseHeader("X-Login") != null) { + + // Detect redirect to a login page + var le = new HTTPBindingClient.Exception(403, 'X-Login'); + if (window.onloginredirect) + window.onloginredirect(le); + throw le; + + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + + // Report empty response + throw new HTTPBindingClient.Exception(403, 'No-Content'); + } + return http.responseText; + } + throw new HTTPBindingClient.Exception(http.status, http.statusText); +}; + +/** + * REST GET method, does not use the local cache. + */ +HTTPBindingClient.prototype.getnocache = function(id, cb) { + var u = id? (this.uri? this.uri + '/' + id : id) : this.uri; + var hascb = cb? true : false; + + // Connect to the service + var http = HTTPBindingClient.getHTTPRequest(); + http.open("GET", u, hascb); + http.setRequestHeader("Accept", "*/*"); + + // Construct call back if we have one + if (hascb) { + http.onreadystatechange = function() { + if (http.readyState == 4) { + if (http.status == 200) { + + if (http.getResponseHeader("X-Login") != null) { + // Detect redirect to a login page + try { + var le = new HTTPBindingClient.Exception(403, 'X-Login'); + if (window.onloginredirect) + window.onloginredirect(le); + return cb(null, le); + } catch(cbe) {} + + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + // Report empty response + try { + return cb(null, new HTTPBindingClient.Exception(403, 'No-Content')); + } catch(cbe) {} + + } else { + try { + return cb(http.responseText); + } catch(cbe) {} + } + } else { + try { + return cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); + } catch(cbe) {} + } + } + }; + + // Send the request + http.send(null); + return true; + } + + // Send the request and return the result or exception + http.send(null); + if (http.status == 200) { + if (http.getResponseHeader("X-Login") != null) { + + // Detect redirect to a login page + var le = new HTTPBindingClient.Exception(403, 'X-Login'); + if (window.onloginredirect) + window.onloginredirect(le); + throw le; + + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + + // Report empty response + throw new HTTPBindingClient.Exception(403, 'No-Content'); + } + return http.responseText; + } + throw new HTTPBindingClient.Exception(http.status, http.statusText); +}; + +/** + * REST POST method. + */ +HTTPBindingClient.prototype.post = function (entry, cb) { + + // Connect to the service + var http = HTTPBindingClient.getHTTPRequest(); + var hascb = cb? true : false; + http.open("POST", this.uri, hascb); + http.setRequestHeader("Accept", "*/*"); + http.setRequestHeader("Content-Type", "application/atom+xml"); + + // Construct call back if we have one + if (hascb) { + http.onreadystatechange = function() { + // Pass the result or exception + if (http.readyState == 4) { + if (http.status == 201) { + try { + cb(http.responseText); + } catch(cbe) {} + } + else { + try { + cb(null, new HTTPBindingClient.Exception(http.status, http.statusText)); + } catch(cbe) {} + } + } + }; + // Send the request + http.send(entry); + return true; + } + + // Send the request and return the result or exception + http.send(entry); + if (http.status == 201) + return http.responseText; + throw new HTTPBindingClient.Exception(http.status, http.statusText); +}; + +/** + * REST PUT method. + */ +HTTPBindingClient.prototype.put = function (id, entry, cb) { + var u = this.uri + '/' + id; + + // Update local storage + var ls = window.lstorage || localStorage; + try { ls.setItem(u, entry); } catch(e) {} + //log('localStorage.setItem', u, entry); + + // Connect to the service + var http = HTTPBindingClient.getHTTPRequest(); + var hascb = cb? true : false; + http.open("PUT", u, hascb); + http.setRequestHeader("Accept", "*/*"); + http.setRequestHeader("Content-Type", "application/atom+xml"); + + // Construct call back if we have one + if (hascb) { + http.onreadystatechange = function() { + if (http.readyState == 4) { + // Pass any exception + if (http.status == 200) { + try { + cb(); + } catch(cbe) {} + } else { + try { + cb(new HTTPBindingClient.Exception(http.status, http.statusText)); + } catch(cbe) {} + } + } + }; + // Send the request + http.send(entry); + return true; + } + + // Send the request and return any exception + http.send(entry); + if (http.status == 200) + return true; + throw new HTTPBindingClient.Exception(http.status, http.statusText); +}; + +/** + * REST DELETE method. + */ +HTTPBindingClient.prototype.del = function (id, cb) { + var u = this.uri + '/' + id; + + // Update local storage + var ls = window.lstorage || localStorage; + try { ls.removeItem(u); } catch(e) {} + //log('localStorage.removeItem', u); + + // Connect to the service + var http = HTTPBindingClient.getHTTPRequest(); + var hascb = cb? true : false; + http.open("DELETE", u, hascb); + http.setRequestHeader("Accept", "*/*"); + + // Construct call back if we have one + if (cb) { + http.onreadystatechange = function() { + if (http.readyState == 4) { + // Pass any exception + if (http.status == 200) { + try { + cb(); + } catch(cbe) {} + } + else { + try { + cb(new HTTPBindingClient.Exception(http.status, http.statusText)); + } catch(cbe) {} + } + } + }; + // Send the request + http.send(null); + return true; + } + + // Send the request and return any exception + http.send(null); + if (http.status == 200) + return true; + 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; +}; + +/** + * XMLHttpRequest wrapper. + */ +HTTPBindingClient.msxmlNames = [ "MSXML2.XMLHTTP.5.0", "MSXML2.XMLHTTP.4.0", "MSXML2.XMLHTTP.3.0", "MSXML2.XMLHTTP", "Microsoft.XMLHTTP" ]; + +HTTPBindingClient.getHTTPRequest = function() { + if (HTTPBindingClient.httpFactory) + return HTTPBindingClient.httpFactory(); + + // Mozilla XMLHttpRequest + try { + HTTPBindingClient.httpFactory = function() { + return new XMLHttpRequest(); + }; + return HTTPBindingClient.httpFactory(); + } catch(e) {} + + // Microsoft MSXML ActiveX + for (var i = 0; i < HTTPBindingClient.msxmlNames.length; i++) { + try { + HTTPBindingClient.httpFactory = function() { + return new ActiveXObject(HTTPBindingClient.msxmlNames[i]); + }; + return HTTPBindingClient.httpFactory(); + } catch (e) {} + } + + // Can't create XMLHttpRequest + HTTPBindingClient.httpFactory = null; + throw new HTTPBindingClient.Exception(0, "Can't create XMLHttpRequest object"); +}; + +/** + * Public API. + */ + +var sca = {}; + +/** + * Return an HTTP client proxy. + */ +sca.httpclient = function(name, uri, domain) { + return new HTTPBindingClient(name, uri, domain); +}; + +/** + * Return a component proxy. + */ +sca.component = function(name, domain) { + if (!domain) + return new HTTPBindingClient(name, '/c/' + name, domain); + return new HTTPBindingClient(name, '/' + domain + '/c/' + name, domain); +}; + +/** + * Return a reference proxy. + */ +sca.reference = function(comp, rname) { + if (!comp.domain) + return new HTTPBindingClient(comp.name + '/' + rname, '/r/' + comp.name + '/' + rname, comp.domain); + return new HTTPBindingClient(comp.name + '/' + rname, '/' + comp.domain + '/r/' + comp.name + '/' + rname, comp.domain); +}; + +/** + * Add proxy functions to a reference proxy. + */ +sca.defun = function(ref) { + function defapply(name) { + return function() { + var args = new Array(); + args[0] = name; + for (i = 0, n = arguments.length; i < n; i++) + args[i + 1] = arguments[i]; + return this.apply.apply(this, args); + }; + } + + for (f = 1; f < arguments.length; f++) { + var fn = arguments[f]; + ref[fn]= defapply(fn); + } + return ref; +}; + diff --git a/sca-cpp/branches/lightweight-sca/modules/js/htdocs/elemutil.js b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/elemutil.js new file mode 100644 index 0000000000..37d641f7b3 --- /dev/null +++ b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/elemutil.js @@ -0,0 +1,236 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Functions to help represent data as lists of elements and attributes. + */ + +var element = "'element" +var attribute = "'attribute" +var atsign = "'@" + +/** + * Return true if a value is an element. + */ +function isElement(v) { + return (!(!isList(v) || isNil(v) || car(v) != element)); +} + +/** + * Return true if a value is an attribute. + */ +function isAttribute(v) { + return (!(!isList(v) || isNil(v) || car(v) != attribute)); +} + +/** + * Return the name of an attribute. + */ +attributeName = cadr; + +/** + * Return the value of an attribute. + */ +attributeValue = caddr; + +/** + * Return the name of an element. + */ +elementName = cadr; + +/** + * Return true if an element has children. + */ +function elementHasChildren(l) { + return !isNil(cddr(l)); +} + +/** + * Return the children of an element. + */ +elementChildren = cddr; + +/** + * Return true if an element has a value. + */ +function elementHasValue(l) { + var r = reverse(l); + if (isSymbol(car(r))) + return false; + return (!(isList(car(r)) && !isNil(car(r)) && isSymbol(car(car(r))))) +} + +/** + * Return the value of an element. + */ +function elementValue(l) { + return car(reverse(l)); +} + +/** + * Convert an element to a value. + */ +function elementToValueIsList(v) { + if (!isList(v)) + return false; + return isNil(v) || !isSymbol(car(v)); +} + +function elementToValue(t) { + if (isTaggedList(t, attribute)) + return mklist(atsign + attributeName(t).substring(1), attributeValue(t)); + if (isTaggedList(t, element)) { + if (elementHasValue(t)) { + if (!elementToValueIsList(elementValue(t))) + return mklist(elementName(t), elementValue(t)); + return cons(elementName(t), mklist(elementsToValues(elementValue(t)))); + } + return cons(elementName(t), elementsToValues(elementChildren(t))); + } + if (!isList(t)) + return t; + return elementsToValues(t); +} + +/** + * Convert a list of elements to a list of values. + */ +function elementToValueIsSymbol(v) { + return (!(!isList(v)) || isNil(v) || !isSymbol(car(v))); +} + +function elementToValueGroupValues(v, l) { + if (isNil(l) || !elementToValueIsSymbol(v) || !elementToValueIsSymbol(car(l))) + return cons(v, l); + if (car(car(l)) != car(v)) + return cons(v, l); + if (!elementToValueIsList(cadr(car(l)))) { + var g = mklist(car(v), mklist(cdr(v), cdr(car(l)))); + return elementToValueGroupValues(g, cdr(l)); + } + var g = mklist(car(v), cons(cdr(v), cadr(car(l)))); + return elementToValueGroupValues(g, cdr(l)); +} + +function elementsToValues(e) { + if (isNil(e)) + return e; + return elementToValueGroupValues(elementToValue(car(e)), elementsToValues(cdr(e))); +} + +/** + * Convert a value to an element. + */ +function valueToElement(t) { + if (isList(t) && !isNil(t) && isSymbol(car(t))) { + var n = car(t); + var v = isNil(cdr(t))? mklist() : cadr(t); + if (!isList(v)) { + if (n.substring(0, 2) == atsign) + return mklist(attribute, "'" + n.substring(2), v); + return mklist(element, n, v); + } + if (isNil(v) || !isSymbol(car(v))) + return cons(element, cons(n, mklist(valuesToElements(v)))); + return cons(element, cons(n, valuesToElements(cdr(t)))); + } + if (!isList(t)) + return t; + return valuesToElements(t); +} + +/** + * Convert a list of values to a list of elements. + */ +function valuesToElements(l) { + if (isNil(l)) + return l; + return cons(valueToElement(car(l)), valuesToElements(cdr(l))); +} + +/** + * Return a selector lambda function which can be used to filter elements. + */ +function selector(s) { + function evalSelect(s, v) { + if (isNil(s)) + return true; + if (isNil(v)) + return false; + if (car(s) != car(v)) + return false; + return evalSelect(cdr(s), cdr(v)); + } + + return function(v) { return evalSelect(s, v); }; +} + +/** + * Return the attribute with the given name. + */ +function namedAttribute(name, l) { + return memo(l, name, function() { + var f = filter(function(v) { return isAttribute(v) && attributeName(v) == name; }, l); + if (isNil(f)) + return null; + return car(f); + }); +} + +/** + * Return the value of the attribute with the given name. + */ +function namedAttributeValue(name, l) { + var a = namedAttribute(name, l); + if (a == null) + return null + return attributeValue(a); +} + +/** + * Return child elements with the given name. + */ +function namedElementChildren(name, l) { + return memo(l, name, function() { + return filter(function(v) { return isElement(v) && elementName(v) == name; }, l); + }); +} + +/** + * Return the child element with the given name. + */ +function namedElementChild(name, l) { + var f = namedElementChildren(name, l); + if (isNil(f)) + return null; + return car(f); +} + +/** + * Side effect functions. Use with moderation. + */ + +/** + * Set the contents of an element. + */ +function setElement(l, e) { + setlist(l, e); + l.memo = {}; +} + diff --git a/sca-cpp/branches/lightweight-sca/modules/js/htdocs/jsonutil.js b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/jsonutil.js new file mode 100644 index 0000000000..8aa291bc89 --- /dev/null +++ b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/jsonutil.js @@ -0,0 +1,261 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * JSON data conversion functions. + */ +var json = {}; + +/** + * JSON exceptions. + */ +json.Exception = function(code, message) { + this.name = "JSONException"; + this.code = code; + this.message = message; +}; + +json.Exception.prototype = new Error(); + +json.Exception.prototype.toString = function() { + return this.name + ": " + this.message; +}; + +/** + * Return true if a list represents a JS array. + */ +json.isJSArray = function(l) { + if (isNil(l)) + return true; + var v = car(l); + if (isSymbol(v)) + return false; + if (isList(v)) + if (!isNil(v) && isSymbol(car(v))) + return false; + return true; +}; + +/** + * Converts JSON properties to values. + */ +json.jsPropertiesToValues = function(propertiesSoFar, o, i) { + if (isNil(i)) + return propertiesSoFar; + var p = car(i); + var jsv = o[p]; + 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 (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(v, propertiesSoFar), o, cdr(i)); +}; + +/** + * Converts a JSON val to a value. + */ +json.jsValToValue = function(jsv) { + if (jsv == null) + return null; + if (isList(jsv)) + return json.jsPropertiesToValues(mklist(), jsv, reverse(range(0, jsv.length))); + if (typeof jsv == 'object') + return json.jsPropertiesToValues(mklist(), jsv, reverse(properties(jsv))); + if (typeof jsv == 'string') + return '' + jsv; + return jsv; +} + +/** + * Return true if a list of strings contains a JSON document. + */ +json.isJSON = function(l) { + if (isNil(l)) + return false; + var s = car(l).slice(0, 1); + return s == "[" || s == "{"; +}; + +/** + * 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); +}; + +/** + * Convert a list of values to JSON array elements. + */ +json.valuesToJSElements = function(a, l, i) { + if (isNil(l)) + return a; + var pv = json.valueToJSVal(car(l)); + a[i] = pv + return json.valuesToJSElements(a, cdr(l), i + 1); +}; + +/** + * Convert a value to a JSON value. + */ +json.valueToJSVal = function(v) { + if (!isList(v)) + return v; + if (json.isJSArray(v)) + return json.valuesToJSElements(range(0, v.length), v, 0); + return json.valuesToJSProperties({}, v); +}; + +/** + * Convert a list of values to JSON properties. + */ +json.valuesToJSProperties = function(o, l) { + if (isNil(l)) + return o; + var token = car(l); + if (isTaggedList(token, attribute)) { + var pv = json.valueToJSVal(attributeValue(token)); + o['@' + attributeName(token).slice(1)] = pv; + } else if (isTaggedList(token, element)) { + if (elementHasValue(token)) { + var pv = json.valueToJSVal(elementValue(token)); + o[elementName(token).slice(1)] = pv; + } else { + var child = {}; + o[elementName(token).slice(1)] = child; + json.valuesToJSProperties(child, elementChildren(token)); + } + } + return json.valuesToJSProperties(o, cdr(l)); +}; + +/** + * Convert a list of values to a list of strings representing a JSON document. + */ +json.writeJSON = function(l) { + var jsv; + if (json.isJSArray(l)) + jsv = json.valuesToJSElements(range(0, l.length), l, 0); + else + jsv = json.valuesToJSProperties({}, l); + var s = json.toJSON(jsv); + return mklist(s); +} + +/** + * Convert a list + params to a JSON-RPC request. + */ +json.jsonRequest = function(id, func, params) { + var r = mklist(mklist("'id", id), mklist("'method", func), mklist("'params", params)); + return json.writeJSON(valuesToElements(r)); +}; + +/** + * Convert a value to a JSON-RPC result. + */ +json.jsonResult = function(id, val) { + return json.writeJSON(valuesToElements(mklist(mklist("'id", id), mklist("'result", val)))); +}; + +/** + * Convert a JSON-RPC result to a value. + */ +json.jsonResultValue = function(s) { + var jsres = json.readJSON(s); + var res = elementsToValues(jsres); + var val = cadr(assoc("'result", res)); + if (isList(val) && !json.isJSArray(val)) + return mklist(val); + 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/branches/lightweight-sca/modules/js/htdocs/scdl.js b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/scdl.js new file mode 100644 index 0000000000..50dab53e7c --- /dev/null +++ b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/scdl.js @@ -0,0 +1,250 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * SCDL parsing functions. + */ +var scdl = {}; + +/** + * Returns a composite element. + */ +scdl.composite = function(l) { + var cs = namedElementChildren("'composite", l); + if (isNil(cs)) + return cs; + return car(cs); +}; + +/** + * Returns a list of components in a composite. + */ +scdl.components = function(l) { + var cs = namedElementChildren("'composite", l); + if (isNil(cs)) + return cs; + return namedElementChildren("'component", car(cs)); +}; + +/** + * Returns a list of service promotions in a composite. + */ +scdl.promotions = function(l) { + var cs = namedElementChildren("'composite", l); + if (isNil(cs)) + return cs; + return namedElementChildren("'service", car(cs)); +}; + +/** + * Returns the target of a service promotion. + */ +scdl.promote = function(l) { + var puri = namedAttributeValue("'promote", l); + if (isNil(puri)) + return puri; + return car(tokens(puri)); +}; + +/** + * Returns the name of a component, componentType, service or reference. + */ +scdl.name = function(l) { + return namedAttributeValue("'name", l); +}; + +/** + * Returns the description of a component, componentType, service or reference. + */ +scdl.documentation = function(l) { + var d = namedElementChildren("'documentation", l); + if (isNil(d)) + return null; + if (!elementHasValue(car(d))) + return null; + var v = elementValue(car(d)); + return v; +}; + +/** + * Returns the title of a component or componentType. + */ +scdl.title = function(l) { + return namedAttributeValue("'title", l); +}; + +/** + * Returns the display style of a component, componentType, reference or property. + */ +scdl.style = function(l) { + return namedAttributeValue("'style", l); +}; + +/** + * Returns the color of a component or componentType. + */ +scdl.color = function(l) { + return namedAttributeValue("'color", l); +}; + +/** + * Returns the x position of a component. + */ +scdl.x = function(l) { + return namedAttributeValue("'x", l); +}; + +/** + * Returns the y position of a component. + */ +scdl.y = function(l) { + return namedAttributeValue("'y", l); +}; + +/** + * Returns the implementation of a component. + */ +scdl.implementation = function(l) { + function filterImplementation(v) { + return isElement(v) && cadr(v).match("implementation.") != null; + } + + var n = filter(filterImplementation, l); + if (isNil(n)) + return null; + return car(n); +}; + +/** + * Returns the type of a component or componentType implementation. + */ +scdl.implementationType = function(l) { + return elementName(l).substring(1); +}; + +/** + * Returns the URI of a service, reference or implementation. + */ +scdl.uri = function(l) { + return namedAttributeValue("'uri", l); +}; + +/** + * Returns the align attribute of a service or reference. + */ +scdl.align = function(l) { + return namedAttributeValue("'align", l); +}; + +/** + * Returns the visible attribute of a service or reference. + */ +scdl.visible = function(l) { + return namedAttributeValue("'visible", l); +}; + +/** + * Returns the clonable attribute of a reference. + */ +scdl.clonable = function(l) { + return namedAttributeValue("'clonable", l); +}; + +/** + * Returns a list of services in a component or componentType. + */ +scdl.services = function(l) { + return namedElementChildren("'service", l); +}; + +/** + * Returns a list of references in a component or componentType. + */ +scdl.references = function(l) { + return namedElementChildren("'reference", l); +}; + +/** + * Returns a list of bindings in a service or reference. + */ +scdl.bindings = function(l) { + function filterBinding(v) { + return isElement(v) && cadr(v).match("binding.") != null; + } + + return filter(filterBinding, l); +}; + +/** + * Returns the type of a binding. + */ +scdl.bindingType = function(l) { + return elementName(l).substring(1); +}; + +/** + * Returns the target of a reference. + */ +scdl.target = function(l) { + function targetURI() { + function bindingsTarget(l) { + if (isNil(l)) + return null; + var u = scdl.uri(car(l)); + if (!isNil(u)) + return u; + return bindingsTarget(cdr(l)); + } + + var t = namedAttributeValue("'target", l); + if (!isNil(t)) + return t; + return bindingsTarget(scdl.bindings(l)); + } + var turi = targetURI(); + if (isNil(turi)) + return turi; + return car(tokens(turi)); +}; + +/** + * Returns a list of properties in a component or componentType. + */ +scdl.properties = function(l) { + return namedElementChildren("'property", l); +}; + +/** + * Returns the value of a property. + */ +scdl.propertyValue = function(l) { + if (!elementHasValue(l)) + return ''; + return elementValue(l); +}; + +/** + * Convert a list of elements to a name -> element assoc list. + */ +scdl.nameToElementAssoc = function(l) { + if (isNil(l)) + return l; + return cons(mklist(scdl.name(car(l)), car(l)), scdl.nameToElementAssoc(cdr(l))); +}; + diff --git a/sca-cpp/branches/lightweight-sca/modules/js/htdocs/ui.css b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/ui.css new file mode 100644 index 0000000000..ddc21b2095 --- /dev/null +++ b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/ui.css @@ -0,0 +1,709 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +body { +margin-top: 0px; margin-bottom: 2px; margin-left: 2px; margin-right: 2px; +font-family: Arial; font-style: normal; font-variant: normal; font-size: 14px; +background-color: #ffffff; opacity: 1; +-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; +cursor: default; +-webkit-backface-visibility: hidden; +} + +.delayed { +visibility: hidden; +} + +.fixed { +position: fixed; +} + +.devicewidth { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +} + +.mainbody { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-backface-visibility: hidden; +} + +.viewcontainer3dm { +position: absolute; left: 0px; top: 35px; width: 100%; +-webkit-backface-visibility: hidden; +} + +.viewcontainer3d { +position: absolute; left: 0px; top: 35px; width: 100%; +-webkit-backface-visibility: hidden; +} + +.leftviewloading3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +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; +} + +.rightviewloading3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +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; +} + +.viewloading3d { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +visibility: hidden; 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; +} + +.viewloaded3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +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; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +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; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +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; +} + +.leftviewunloaded3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +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; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; +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; +} + +.body { +width: 100%; height: 5000px; overflow: visible; +-webkit-backface-visibility: hidden; +} + +.viewhead { +position: absolute; left: 0px; top: 35px; height: 35px; line-height: 35px; width: 100%; z-index: 8; +font-size: 110%; font-weight: bold; background-color: #f1f1f1; color: #000000; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; +border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; +overflow: hidden; +-webkit-backface-visibility: hidden; +} + +.viewheadbackground { +position: absolute; left: 0px; top: 35px; height: 35px; line-height: 35px; width: 2500px; z-index: 7; +background-color: #f1f1f1; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; +border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; +overflow: hidden; +-webkit-backface-visibility: hidden; +} + +.viewfoot { +position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 100%; z-index: 8; +font-size: 12px; background-color: #ffffff; color: #404040; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; +border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; +overflow: hidden; +-webkit-backface-visibility: hidden; +} + +.status { +position: absolute; left: 0px; bottom: 0px; height: 35px; line-height: 35px; width: 100%; z-index: 9; +font-size: 12px; background-color: #ffffff; color: #404040; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; +border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; +overflow: hidden; +-webkit-transform: translate(0px, 0px); +-moz-transform: translate(0px, 0px); +-ms-transform: translate(0px, 0px); +-o-transform: translate(0px, 0px); +transform: translate(0px, 0px); +-webkit-backface-visibility: hidden; +} + +.statusout3 { +position: absolute; left: 0px; bottom: 0px; height: 35px; line-height: 35px; width: 100%; z-index: 9; +font-size: 12px; background-color: #ffffff; color: #404040; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; +border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; +overflow: hidden; +-webkit-transition: -webkit-transform 0.4s ease-in-out 3s; +-moz-transition: -moz-transform 0.4s ease-in-out 3s; +-ms-transition: -ms-transform 0.4s ease-in-out 3s; +-o-transition: -o-transform 0.4s ease-in-out 3s; +transition: transform 0.4s ease-in-out 3s; +-webkit-transform: translate(0px, 35px); +-moz-transform: translate(0px, 35px); +-ms-transform: translate(0px, 35px); +-o-transform: translate(0px, 35px); +transform: translate(0px, 35px); +-webkit-backface-visibility: hidden; +} + +.statusout1 { +position: absolute; left: 0px; bottom: 0px; height: 35px; line-height: 35px; width: 100%; z-index: 9; +font-size: 12px; background-color: #ffffff; color: #404040; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; +border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; +overflow: hidden; +-webkit-transition: -webkit-transform 0.4s ease-in-out 1s; +-moz-transition: -moz-transform 0.4s ease-in-out 1s; +-ms-transition: -ms-transform 0.4s ease-in-out 1s; +-o-transition: -o-transform 0.4s ease-in-out 1s; +transition: transform 0.4s ease-in-out 1s; +-webkit-transform: translate(0px, 35px); +-moz-transform: translate(0px, 35px); +-ms-transform: translate(0px, 35px); +-o-transform: translate(0px, 35px); +transform: translate(0px, 35px); +-webkit-backface-visibility: hidden; +} + +.okstatus { +font-size: 110%; font-weight: bold; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none; +background-color: #f1f1f1; color: #000000; +width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right; +} + +.errorstatus { +font-size: 110%; font-weight: bold; padding-left: 6px; padding-right: 6px; white-space: nowrap; text-decoration: none; +background-color: #d14836; color: #ffffff; +width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right; +} + +.viewfootbackground { +position: absolute; left: 0px; bottom: 0px; height: 25px; line-height: 25px; width: 2500px; z-index: 7; +background-color: #ffffff; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; +border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #ffffff; +overflow: hidden; +-webkit-backface-visibility: hidden; +} + +.viewcontent { +position: absolute; left: 0px; top: 38px; width: 100%; +-webkit-backface-visibility: hidden; +} + +.viewform { +position: absolute; left: 0px; top: 40px; width: 100%; +} + +table { +border: 0px; border-collapse: collapse; border-color: #a2bae7; border-style: solid; +font-family: Arial; font-style: normal; font-variant: normal; font-size: 14px; +overflow: visible; +} + +.trb { +border-bottom: 1px; border-bottom-style: solid; border-color: #dcdcdc; +} + +th { +font-size: 110%; font-weight: bold; background-color: #f1f1f1; color: #000000; +text-align: left; padding-left: 2px; padding-right: 8px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; white-space: nowrap; +border-top: 1px; border-bottom: 1px; border-left: 1px; border-right: 1px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; border-left-color: #e5e5e5; border-right-color: #e5e5e5; +overflow: hidden; +} + +.section { +font-size: 110%; font-weight: bold; background-color: #f1f1f1; color: #000000; height: 30px; line-height: 30px; +text-align: left; padding-top: 0px; padding-bottom: 0px; padding-left: 2px; padding-right: 2px; white-space: nowrap; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #e5e5e5; border-bottom-color: #e5e5e5; border-left-color: #e5e5e5; border-right-color: #e5e5e5; +overflow: hidden; +} + +.hsection { +width: 100%; height: 0px; visibility: hidden; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-bottom-color: #000000; background-color: #ffffff; +padding-left: 2px; padding-right: 2px; padding-top: 0px; padding-bottom: 0px; margin-bottom: 0px; margin-left: auto; margin-right: auto; text-align: center; +} + +.fsection{ +width: 100%; height: 0px; visibility: hidden; +border-top: 0px; border-bottom: 0px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #a2bae7; +padding: 0px; margin-top: 0px; margin-left: auto; margin-right: auto; text-align: center; +} + +.bluetext { +color: #4787ed; +} + +.redtext { +color: #d14836; +} + +.mirror { +display: inline-block; +-webkit-transform: scaleX(-1); +-moz-transform: scaleX(-1); +-ms-transform: scaleX(-1); +-o-transform: scaleX(-1); +transform: scaleX(-1); +} + +.greentext { +color: #009900; +} + +.text { +padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; +} + +.link { +padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; +} + +.checkbox { +padding-top: 3px; padding-bottom: 4px; vertical-align: middle; white-space: nowrap; +} + +.thl { +border-left: 0px; +} + +.thr { +border-right: 0px; +} + +.ths { +padding: 0px; +} + +td { +padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: nowrap; vertical-align: middle; border: 0px; +} + +.tdl { +border-right: 1px; border-style: solid; border-color: #a2bae7; width: 10px; +} + +.tdr { +border-left: 1px; border-style: solid; border-color: #a2bae7; +} + +.tdw { +padding-left: 2px; padding-top: 2px; padding-right: 8px; white-space: normal; vertical-align: middle; +} + +.datatd { +border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; 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; +} + +.datatdltop { +border-right: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; width: 10px; vertical-align: top; +} + +.datatdr { +border-left: 1px; border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; vertical-align: middle; +} + +.datatable { +border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; +overflow: visible; +} + +.databg { +opacity: .6; +-ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=60)"; +filter: alpha(opacity=60); +} + +.guide { +border: 1px; border-style: solid; border-color: #c0c0c0; +} + +iframe { +border: 0px; margin: 0px; padding: 0px; +} + +.fakeframe { +padding: 3px; background-color: #dcdcdc; color: #000000; +} + +input { +vertical-align: middle; +font-family: Arial; font-style: normal; font-variant: normal; font-size: 15px; +outline: none; +-webkit-text-size-adjust: 100%; +} + +button { +vertical-align: middle; +font-family: Arial; font-style: normal; font-variant: normal; font-size: 15px; +outline: none; +-webkit-text-size-adjust: 100%; +} + +textarea { +font-family: Arial; font-style: normal; font-variant: normal; font-size: 15px; +outline: none; +overflow: auto; resize: none; +} + +.flatentry { +font-family: Arial; font-style: normal; font-variant: normal; font-size: 15px; +-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: 1px!important; padding: 3px 1px 3px 3px; +} + +.graphentry { +font-family: Arial; font-style: normal; font-variant: normal; font-size: 13px; +-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; +} + +.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; +} + +.editablesvg { +background-color: transparent; +font-family: inherit; font-style: inherit; font-variant: inherit; font-size: inherit; font-weight: inherit; +padding: 0px; margin: 0px; +overflow: auto; resize: none; +outline: none; -moz-outline-style: none; +-webkit-appearance: none; -webkit-text-size-adjust: 100%; +border: 0px; +} + +a:link { +color: #357ae8; text-decoration: none; white-space: nowrap; cursor: pointer; +} + +a:visited { +color: #357ae8; text-decoration: none; white-space: nowrap; cursor: pointer; +} + +.tbarmenu { +position: absolute; top: 0px; left: 0px; z-index: 10; width: 100%; margin: 0px; padding: 0px; border-collapse: separate; +height: 35px; line-height: 35px; background-color: #2c2c2c; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #2c2c2c; border-bottom-color: #2c2c2c; +-webkit-backface-visibility: hidden; +} + +.tbarbackground { +position: absolute; top: 0px; left: 0px; z-index: 9; width: 2500px; margin: 0px; padding: 0px; border-collapse: separate; +height: 35px; line-height: 35px; background-color: #2c2c2c; +border-top: 1px; border-bottom: 1px; border-left: 0px; border-right: 0px; border-style: solid; border-top-color: #2c2c2c; border-bottom-color: #2c2c2c; +overflow: hidden; +-webkit-backface-visibility: hidden; +} + +.tbarleft { +padding-left: 2px; padding-right: 6px; white-space: nowrap; float: left; +} + +.tbarright { +padding-left: 6px; padding-right: 2px; white-space: nowrap; float: right; +} + +.tbaramenu { +font-size: 110%; color: #cccccc; text-decoration: none; white-space: nowrap; +} + +.tbarsmenu { +font-size: 110%; font-weight: bold; color: #ffffff; text-decoration: none; white-space: nowrap; +} + +.amenu { +padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #808080; text-decoration: none; float: left; +} + +.smenu { +padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; float: left; +} + +.cmenu { +font-size: 18px; padding-left: 6px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; +width: 100%; margin-left: auto; margin-right: auto; text-align: center; float: right; +} + +.bcmenu { +font-size: 22px; padding-left: 2px; padding-right: 6px; white-space: nowrap; color: #000000; text-decoration: none; +} + +.rmenu { +padding-left: 2px; padding-right: 2px; white-space: nowrap; white-space: nowrap; float: right; +} + +h1 { +font-size: 150%; font-weight: bold; vertical-align: middle; margin-top: 5px; margin-bottom: 5px; margin-left: 2px; margin-right: 2px; white-space: nowrap; +} + +h2 { +font-size: 120%; font-weight: bold; vertical-align: middle; margin-top: 5px; margin-bottom: 5px; margin-left: 2px; margin-right: 2px; white-space: nowrap; +} + +.hd1 { +font-size: 150%; font-weight: bold; white-space: nowrap; +} + +.hd2 { +font-size: 120%; font-weight: bold; white-space: nowrap; +} + +img { +border: 0px; +} + +.plusminus { +font-size: 18px; font-family: "Courier New"; +} + +.imgbutton { +width: 142px; height: 64px; margin-left: 20px; margin-right: 20px; padding: 0px; border: 1px; cursor: pointer; +} + +.graybutton { +display: inline-block; text-align: center; color: #444; font-weight: bold; +padding-top: 0px; padding-bottom: 0px; padding-left: 4px; padding-right: 4px; +height: 28px; line-height: 28px; min-width: 30px; +-webkit-border-radius: 2px; -moz-border-radius: 2px; border-radius: 2px; +border: 1px solid gainsboro; background-color: whiteSmoke; +background-image: -webkit-gradient(linear,left top,left bottom,from(whiteSmoke),to(#f1f1f1)); +background-image: -webkit-linear-gradient(top,whiteSmoke,#f1f1f1); +background-image: -moz-linear-gradient(top,whiteSmoke,#f1f1f1); +background-image: -ms-linear-gradient(top,whiteSmoke,#f1f1f1); +background-image: -o-linear-gradient(top,whiteSmoke,#f1f1f1); +background-image: linear-gradient(top,whiteSmoke,#f1f1f1); +cursor: default; +} + +.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); +} + +.graybutton:active { +background-color: #f6f6f6; +background-image: -webkit-gradient(linear,left top,left bottom,from(#f6f6f6),to(#f1f1f1)); +background-image: -webkit-linear-gradient(top,#f6f6f6,#f1f1f1); +background-image: -moz-linear-gradient(top,#f6f6f6,#f1f1f1); +background-image: -ms-linear-gradient(top,#f6f6f6,#f1f1f1); +background-image: -o-linear-gradient(top,#f6f6f6,#f1f1f1); +background-image: linear-gradient(top,#f6f6f6,#f1f1f1); +-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1); +} + +.graybutton:disabled { +color: #c0c0c0; +} + +.bluebutton { +border: 1px solid #3079ed; color: white; 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:disabled { +color: #c0c0c0; +} + +.bluebutton:hover { +border: 1px solid #2f5bb7; color: white; 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:hover:disabled { +color: #c0c0c0; +} + +.redbutton { +border: 1px solid transparent; color: white; text-shadow: 0 1px rgba(0, 0, 0, 0.1); background-color: #d14836; +background-image: -webkit-gradient(linear,left top,left bottom,from(#dd4b39),to(#d14836)); +background-image: -webkit-linear-gradient(top,#dd4b39,#d14836); +background-image: -moz-linear-gradient(top,#dd4b39,#d14836); +background-image: -ms-linear-gradient(top,#dd4b39,#d14836); +background-image: -o-linear-gradient(top,#dd4b39,#d14836); +background-image: linear-gradient(top,#dd4b39,#d14836); +-webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); -moz-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); -ms-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); +-o-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.3); +} + +.redbutton:disabled { +color: #c0c0c0; +} + +.redbutton:hover { +border: 1px solid #b0281a; border-bottom-color: #af301f; color: white; background-color: #c53727; +background-image: -webkit-linear-gradient(top,#dd4b39,#c53727); +background-image: -moz-linear-gradient(top,#dd4b39,#c53727); +background-image: -ms-linear-gradient(top,#dd4b39,#c53727); +background-image: -o-linear-gradient(top,#dd4b39,#c53727); +background-image: linear-gradient(top,#dd4b39,#c53727); +-webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -moz-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); -ms-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); +-o-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2); +} + +.redbutton:hover:disabled { +color: #c0c0c0; +} + +.box { +width: 150px; display: inline-block; +border: 1px; border-style: solid; border-color: #dcdcdc; border-collapse: collapse; +white-space: nowrap; margin: 2px; padding: 2px; vertical-align: top; +} + +.appicon { +float: left; +height: 50px; width: 50px; vertical-align: top; margin: 0px; padding: 0px; +} + +.apptitle { +font-weight: bold; +} + +.note { +font-size: 12px; color: #808080; +} + +.pagediv { +position: absolute; display: block; overflow: visible; +-webkit-backface-visibility: hidden; +} + +.graphdiv { +position: absolute; display: block; overflow: visible; +-webkit-backface-visibility: hidden; +} + +.g { +position: absolute; display: block; overflow: visible; +-webkit-backface-visibility: hidden; +} + +.path { +position: absolute; background: transparent; display: block; overflow: visible; +visibility: visible; +-webkit-backface-visibility: hidden; +} + +.gtitle { +position: absolute; +margin: 4px; padding: 0px; line-height: 15px; vertical-align: middle; white-space: nowrap; +font-family: Arial; font-style: normal; font-variant: normal; font-size: 13px; cursor: default; +background: transparent; display: block; overflow: visible; +-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; +} + diff --git a/sca-cpp/branches/lightweight-sca/modules/js/htdocs/ui.js b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/ui.js new file mode 100644 index 0000000000..fb53598390 --- /dev/null +++ b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/ui.js @@ -0,0 +1,409 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * UI utility functions. + */ + +var ui = {}; + +/** + * Return a child element of a node with the given id. + */ +ui.elementByID = function(node, id) { + if (node.skipNode == true) + return null; + for (var i in node.childNodes) { + var child = node.childNodes[i]; + if (child.id == id) + return child; + var gchild = ui.elementByID(child, id); + if (gchild != null) + return gchild; + } + return null; +}; + +/** + * Return the current document, or a child element with the given id. + */ +function $(id) { + if (id == document) + return document; + return ui.elementByID($(document), id); +}; + +/** + * Return a list of elements with the given class name. + */ +ui.elementsByClassName = function(node, c) { + return nodeList(node.getElementsByClassName(c)); +}; + +/** + * Return the query string of a URL. + */ +ui.query = function(url) { + var u = '' + url; + var q = u.indexOf('?'); + return q >= 0? u.substring(q + 1) : ''; +}; + +/** + * Return the fragment part of a URL. + */ +ui.fragment = function(url) { + var u = '' + url; + var h = u.indexOf('#'); + return h >= 0? u.substring(h + 1) : ''; +}; + +/** + * Return the path and parameters of a URL. + */ +ui.pathandparams = function(url) { + var u = '' + url; + var ds = u.indexOf('//'); + var u2 = ds > 0? u.substring(ds + 2) : u; + var s = u2.indexOf('/'); + return s > 0? u2.substring(s) : ''; +}; + +/** + * Return a dictionary of query parameters in a URL. + */ +ui.queryParams = function(url) { + var qp = new Array(); + var qs = ui.query(url).split('&'); + for (var i = 0; i < qs.length; i++) { + var e = qs[i].indexOf('='); + if (e > 0) + qp[qs[i].substring(0, e)] = unescape(qs[i].substring(e + 1)); + } + return qp; +}; + +/** + * Return a dictionary of fragment parameters in a URL. + */ +ui.fragmentParams = function(url) { + var qp = new Array(); + var qs = ui.fragment(url).split('&'); + for (var i = 0; i < qs.length; i++) { + var e = qs[i].indexOf('='); + if (e > 0) + qp[qs[i].substring(0, e)] = unescape(qs[i].substring(e + 1)); + } + return qp; +}; + +/** + * Convert a base64-encoded image to a data URL. + */ +ui.b64img = function(b64) { + return 'data:image/png;base64,' + b64; +}; + +/** + * Declare a CSS stylesheet. + */ +ui.declareCSS = function(s) { + var e = document.createElement('style'); + e.type = 'text/css'; + e.textContent = s; + return e; +}; + +/** + * Declare a script. + */ +ui.declareScript = function(s) { + var e = document.createElement('script'); + e.type = 'text/javascript'; + e.text = s; + return e; +}; + +/** + * Return the scripts elements under a given element. + */ +ui.innerScripts = function(e) { + return map(function(s) { return s.text; }, nodeList(e.getElementsByTagName('script'))); +}; + +/** + * Evaluate a script. + */ +ui.evalScript = function(s) { + return eval('(function() {\n' + s + '\n})();'); +}; + +/** + * Include a script. + */ +ui.includeScript = function(s) { + //log('include', s); + return eval(s); +}; + +/** + * Return true if the client is a mobile device. + */ +ui.mobiledetected = false; +ui.mobile = false; +ui.isMobile = function() { + if (ui.mobiledetected) + return ui.mobile; + var ua = navigator.userAgent; + if (ua.match(/iPhone/i) || ua.match(/iPad/i) || ua.match(/Android/i) || ua.match(/Blackberry/i) || ua.match(/WebOs/i)) + ui.mobile = true; + ui.mobiledetected = true; + return ui.mobile; +}; + +/** + * Convert a CSS position to a numeric position. + */ +ui.numpos = function(p) { + return p == ''? 0 : Number(p.substr(0, p.length - 2)); +}; + +/** + * Convert a numeric position to a CSS pixel position. + */ +ui.pixpos = function(p) { + return p + 'px'; +}; + +/** + * Default orientation change behavior. + */ +ui.onorientationchange = function(e) { + + // Scroll to the top and hide the address bar + window.scrollTo(0, 0); + + // Change fixed position elements to absolute then back to fixed + // to make sure they're correctly layed out after the orientation + // change + map(function(e) { + e.style.position = 'absolute'; + return e; + }, ui.elementsByClassName(document, 'fixed')); + + setTimeout(function() { + map(function(e) { + e.style.position = 'fixed'; + return e; + }, ui.elementsByClassName(document, 'fixed')); + }, 0); + return true; +}; + +/** + * Default page load behavior. + */ +ui.onload = function() { + + // Scroll to the top and hide the address bar + window.scrollTo(0, 0); + + // Initialize fixed position elements only after the page is loaded, + // to workaround layout issues with fixed position on mobile devices + setTimeout(function() { + map(function(e) { + e.style.position = 'fixed'; + return e; + }, ui.elementsByClassName(document, 'fixed')); + }, 0); + return true; +}; + +/** + * Navigate to a new document. + */ +ui.navigate = function(url, win) { + //log('navigate', url, win); + + // Open a new window + if (win == '_blank') { + window.top.open(url, win); + return false; + } + + // Open a new document in the current window + if (win == '_self') { + window.top.open(url, win); + return false; + } + + // Reload the current window + if (win == '_reload') { + window.top.location = url; + window.top.location.reload(); + return false; + } + + // Let the current top window handle the navigation + if (win == '_view') { + if (!window.top.onnavigate) + return window.top.open(url, '_self'); + window.top.onnavigate(url); + return false; + } + + window.top.open(url, win); + return false; +} + +/** + * Build a portable <a href> tag. + */ +ui.href = function(id, loc, target, html) { + if (target == '_blank') + return '<a id="' + id + '" href="' + loc + '" target="_blank">' + html + '</a>'; + return '<a id="' + id + '" href="' + loc + '" onclick="return ui.navigate(\'' + loc + '\', \'' + target + '\');">' + html + '</a>'; +}; + +/** + * Build a menu bar. + */ +ui.menu = 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>'); + else if (hilight == false) + return ui.href(id, href, target, '<span class="tbaramenu">' + name + '</span>'); + else + return ui.href(id, href, target, '<span class="' + hilight + '">' + name + '</span>'); + }; + } + return new Menu(); +}; + +ui.menufunc = function(id, name, fun, hilight) { + function Menu() { + this.content = function() { + function href(id, fun, html) { + return '<a id="' + id + '" href="/" onclick="' + fun + '">' + html + '</a>'; + } + + if (hilight == true) + return href(id, fun, '<span class="tbarsmenu">' + name + '</span>'); + else if (hilight == false) + return href(id, fun, '<span class="tbaramenu">' + name + '</span>'); + else + return href(id, fun, '<span class="' + hilight + '">' + name + '</span>'); + }; + } + 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; +}; + +/** + * Convert a list of elements to an HTML table. + */ +ui.datatable = function(l) { + + function indent(i) { + if (i == 0) + return ''; + return ' ' + indent(i - 1); + } + + function rows(l, i) { + if (isNil(l)) + return ''; + var e = car(l); + + // Convert a list of simple values into a list of name value pairs + if (!isList(e)) + return rows(expandElementValues("'value", l), i); + + // Convert a list of complex values into a list of name value pairs + if (isList(car(e))) + return rows(expandElementValues("'value", l), i); + + // 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); + } + + 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 '<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) { + + function rows(l, i) { + if (isNil(l)) + return ''; + var e = car(l); + + // Convert a list of simple values into a list of name value pairs + if (!isList(e)) + return rows(expandElementValues("'value", l), i); + + // Convert a list of complex values into a list of name value pairs + if (isList(car(e))) + return rows(expandElementValues("'value", l), i); + + // 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); + } + + 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>'; +} + diff --git a/sca-cpp/branches/lightweight-sca/modules/js/htdocs/util.js b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/util.js new file mode 100644 index 0000000000..0f7de94289 --- /dev/null +++ b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/util.js @@ -0,0 +1,471 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * Simple utility functions. + */ + +/** + * Scheme-like lists. + */ +function cons(car, cdr) { + var a = new Array(); + a.push(car); + return a.concat(cdr); +} + +function car(l) { + return l[0]; +} + +function first(l) { + return l[0]; +} + +function cdr(l) { + return l.slice(1); +} + +function rest(l) { + return l.slice(1); +} + +function cadr(l) { + return l[1]; +} + +function cddr(l) { + return l.slice(2); +} + +function caddr(l) { + return l[2]; +} + +function cdddr(l) { + return l.slice(3); +} + +function cadddr(l) { + return l[3]; +} + +function append(a, b) { + return a.concat(b); +} + +function reverse(l) { + return l.slice(0).reverse(); +} + +function range(a, b) { + var l = new Array(); + for (var x = a; x < b; x++) + l.push(x); + return l; +} + +function isNil(v) { + return (v == null || typeof v == 'undefined' || (v.constructor == Array && v.length == 0)); +} + +function isSymbol(v) { + return (typeof v == 'string' && v.slice(0, 1) == "'"); +} + +function isString(v) { + return (typeof v == 'string' && v.slice(0, 1) != "'"); +} + +function isList(v) { + return (v != null && typeof v != 'undefined' && v.constructor == Array); +} + +function isTaggedList(v, t) { + return (isList(v) && !isNil(v) && 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 length(l) { + return l.length; +} + +/** + * Scheme-like associations. + */ +function assoc(k, l) { + if (isNil(l)) + return emptylist; + var n = l.length; + for(var i = 0; i < n; i++) { + if (k == car(l[i])) + return l[i]; + } + return emptylist; +} + +/** + * Map, filter and reduce functions. + */ +function map(f, l) { + if (isNil(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; +} + +function filter(f, l) { + if (isNil(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; +} + +function reduce(f, i, l) { + if (isNil(l)) + return i; + return reduce(f, f(i, car(l)), cdr(l)); +} + +/** + * Split a path into a list of segments. + */ +function tokens(path) { + return filter(function(s) { return length(s) != 0; }, path.split("/")); +} + +/** + * Debug log a value. + */ +var rconsole; + +function debug(v) { + try { + var s = ''; + for (i = 0; i < arguments.length; i++) { + s = s + writeValue(arguments[i]); + if (i < arguments.length) + s = s + ' '; + } + + if (rconsole) { + try { + rconsole.log(s); + } catch (e) {} + } + try { + console.log(s); + } catch (e) {} + } catch (e) {} + return true; +} + +/** + * Dump an object to the console. + */ +function dump(o) { + try { + for (f in o) { + try { + debug('dump ' + f + '=' + o[f]); + } catch (e) {} + } + } catch (e) {} + 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; +}; + +/** + * External build configuration. + */ +var config; +if (isNil(config)) + config = {}; + +/** + * Simple assert function. + */ +function AssertException() { +} + +AssertException.prototype.toString = function () { + return 'AssertException'; +}; + +function assert(exp) { + if (!exp) + throw new AssertException(); +} + +/** + * Write a list of strings. + */ +function writeStrings(l) { + if (isNil(l)) + return ''; + var s = ''; + var n = l.length; + for(var i = 0; i < n; i++) { + s = s + l[i]; + } + return s; +} + +/** + * Write a value using a Scheme-like syntax. + */ +function writeValue(v) { + function writePrimitive(p) { + if (isSymbol(p)) + return '' + p.substring(1); + if (isString(p)) + return '"' + p + '"'; + return '' + p; + } + + function writeList(l) { + if (isNil(l)) + return ''; + return ' ' + writeValue(car(l)) + writeList(cdr(l)); + } + + if (!isList(v)) + return writePrimitive(v); + if (isNil(v)) + return '()'; + return '(' + writeValue(car(v)) + writeList(cdr(v)) + ')'; +} + +/** + * Apply a function and memoize its result. + */ +function memo(obj, key, f) { + if (!('memo' in obj)) { + obj.memo = {}; + return obj.memo[key] = f(); + } + if (key in obj.memo) + return obj.memo[key]; + return obj.memo[key] = f(); +} + +/** + * Un-memoize stored results. + */ +function unmemo(obj) { + obj.memo = {}; + return true; +} + +/** + * Local storage. + */ +var lstorage = {}; +lstorage.enabled = true; + +/** + * Get an item. + */ +lstorage.getItem = function(k) { + if (!lstorage.enabled) + return null; + try { + return localStorage.getItem(k); + } catch(e) { + return null; + } +} + +/** + * Set an item. + */ +lstorage.setItem = function(k, v) { + if (!lstorage.enabled) + return null; + try { + return localStorage.setItem(k, v); + } catch(e) { + return null; + } +} + +/** + * Remove an item. + */ +lstorage.removeItem = function(k) { + if (!lstorage.enabled) + return null; + try { + 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; +} + +/** + * Convert a host name to a domain name. + */ +function domainname(host) { + var ds = host.indexOf('//'); + 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 = (!isNil(cddr(h)) && caddr(h) == 'www')? mklist(car(h), cadr(h), caddr(h)) : mklist(car(h), cadr(h)); + return reverse(d).join('.'); +} + +/** + * Return true if a host name is a subdomain. + */ +function issubdomain(host) { + return host.split('.').length > 2; +} + +/** + * Return true if the document cookie contains auth information. + */ +function hasauthcookie() { + return !isNil(document.cookie) && + (document.cookie.indexOf('TuscanyOpenAuth=') != -1 || + document.cookie.indexOf('TuscanyOAuth1=') != -1 || + document.cookie.indexOf('TuscanyOAuth2=') != -1 || + document.cookie.indexOf('TuscanyOpenIDAuth=') != -1); +} + +/** + * Clear auth information from the document cookie. + */ +function clearauthcookie() { + document.cookie = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth1=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOAuth2=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; + document.cookie = 'TuscanyOpenIDAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; + return true; +} + +/** + * Format a string like Python format. + */ +function format() { + var i = 0; + var s = ''; + for (a in arguments) { + s = i == 0? arguments[a] : s.replace('{' + a + '}', arguments[a]); + i++; + } + return s; +} + +/** + * Functions with side effects. Use with moderation. + */ + +/** + * Set the car of a list. + */ +function setcar(l, v) { + l[0] = v; + return l; +} + +/** + * Set the cadr of a list. + */ +function setcadr(l, v) { + l[1] = v; + return l; +} + +/** + * Set the caddr of a list. + */ +function setcaddr(l, v) { + l[2] = v; + return l; +} + +/** + * Append the elements of a list to a list. + */ +function setappend(a, b) { + if (isNil(b)) + return a; + a.push(car(b)); + return setappend(a, cdr(b)); +} + +/** + * Set the cdr of a list. + */ +function setcdr(a, b) { + a.length = 1; + return setappend(a, b); +} + +/** + * Set the contents of a list. + */ +function setlist(a, b) { + if (b == a) + return b; + a.length = 0; + return setappend(a, b); +} + diff --git a/sca-cpp/branches/lightweight-sca/modules/js/htdocs/xmlutil.js b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/xmlutil.js new file mode 100644 index 0000000000..4d943cce75 --- /dev/null +++ b/sca-cpp/branches/lightweight-sca/modules/js/htdocs/xmlutil.js @@ -0,0 +1,256 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * XML handling functions. + */ + +/** + * Convert a DOM node list to a regular list. + */ +function nodeList(n) { + var l = new Array(); + if (isNil(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) { + if (isNil(nodes)) + return p; + p.appendChild(car(nodes)); + return appendNodes(cdr(nodes), p); +}; + +/** + * Return the child attributes of an element. + */ +function childAttributes(e) { + return filter(function(n) { return n.nodeType == 2; }, nodeList(e.attributes)); +} + +/** + * Return the child elements of an element. + */ +function childElements(e) { + return filter(function(n) { return n.nodeType == 1; }, nodeList(e.childNodes)); +} + +/** + * 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)); +} + +/** + * Read a list of XML attributes. + */ +function readAttributes(p, a) { + if (isNil(a)) + return a; + var x = car(a); + return cons(mklist(attribute, "'" + x.nodeName, x.nodeValue), readAttributes(p, 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 t = childText(e); + if (isNil(t)) + return l; + return append(l, mklist(car(t).nodeValue)); +} + +/** + * Read a list of XML elements. + */ +function readElements(l, childf) { + if (isNil(l)) + return l; + return cons(readElement(car(l), childf), readElements(cdr(l), childf)); +} + +/** + * Return true if a list of strings contains an XML document. + */ +function isXML(l) { + if (isNil(l)) + return false; + return car(l).substring(0, 5) == '<?xml'; +} + +/** + * Parse a list of strings representing an XML document. + */ +function parseXML(l) { + var s = writeStrings(l); + var p = new DOMParser(); + return p.parseFromString(s, "text/xml"); +} + +/** + * Read a list of values from an XML document. + */ +function readXMLDocument(doc) { + var root = childElements(doc); + if (isNil(root)) + return mklist(); + return mklist(readElement(car(root), childAttributes)); +} + +/** + * 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 || isNil(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)); +} + +/** + * Read a list of values from a list of strings representing an XML document. + */ +function readXML(l) { + return readXMLDocument(parseXML(l)); +} + +/** + * Return a list of strings representing an XML document. + */ +function writeXMLDocument(doc) { + if (typeof(XMLSerializer) != 'undefined') + return mklist(new XMLSerializer().serializeToString(doc)); + return mklist(doc.xml); +} + +/** + * Write a list of XML element and attribute tokens. + */ +function expandElementValues(n, l) { + if (isNil(l)) + return l; + return cons(cons(element, cons(n, car(l))), expandElementValues(n, cdr(l))); +} + +function writeList(l, node, doc) { + if (isNil(l)) + return node; + + var token = car(l); + if (isTaggedList(token, attribute)) { + if (isIE()) { + var aname = attributeName(token).substring(1); + if (aname != 'xmlns') + node.setAttribute(aname, '' + attributeValue(token)); + } else + node.setAttribute(attributeName(token).substring(1), '' + attributeValue(token)); + + } else if (isTaggedList(token, element)) { + + function mkelem(tok, doc) { + function xmlns(l) { + if (isNil(l)) + return null; + var t = car(l); + if (isTaggedList(t, attribute)) { + if (attributeName(t).substring(1) == 'xmlns') + return attributeValue(t); + } + return xmlns(cdr(l)); + } + + var ns = xmlns(elementChildren(tok)); + if (isIE()) + return doc.createElementNS(ns != null? ns : node.namespaceURI, elementName(tok).substring(1)); + if (ns == null) + return doc.createElement(elementName(tok).substring(1)); + return doc.createElementNS(ns, elementName(tok).substring(1)); + } + + if (elementHasValue(token)) { + var v = elementValue(token); + if (isList(v)) { + var e = expandElementValues(elementName(token), v); + writeList(e, node, doc); + } else { + var child = mkelem(token, doc); + writeList(elementChildren(token), child, doc); + node.appendChild(child); + } + } else { + var child = mkelem(token, doc); + writeList(elementChildren(token), child, doc); + node.appendChild(child); + } + } else + node.appendChild(doc.createTextNode('' + token)); + + writeList(cdr(l), node, doc); + return node; +} + +/** + * Make a new XML document. + */ +function mkXMLDocument() { + return document.implementation.createDocument('', '', null); +} + +/** + * Convert a list of values to a list of strings representing an XML document. + */ +function writeXML(l, xmlTag) { + var doc = mkXMLDocument(); + writeList(l, doc, doc); + if (!xmlTag) + return writeXMLDocument(doc); + return mklist('<?xml version="1.0" encoding="UTF-8"?>\n' + writeXMLDocument(doc) + '\n'); +} + |