hosting/server/htdocs/app/index.html (854 lines of code) (raw):

<!DOCTYPE html> <!-- * 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. --> <html manifest="cache/cache-manifest.cmf"> <head> <!-- Firebug inspector --> <!-- <script type="text/javascript" src="https://getfirebug.com/releases/lite/1.3/firebug-lite.js"></script> --> <!-- Weinre inspector --> <!-- <script src="http://www.example.com:9998/target/target-script-min.js#anonymous"></script> --> <title></title> <meta name="viewport" content="user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"/> <meta name="apple-mobile-web-app-capable" content="yes"/> <meta name="apple-mobile-web-app-status-bar-style" content="black"/> <link rel="apple-touch-icon-precomposed" href="/public/touchicon.png"/> <base href="/"/> <script type="text/javascript"> try { (function apphead() { window.appcache = {}; /** * Get and cache a resource. */ appcache.get = function(uri, mode) { var h = uri.indexOf('#'); var u = h == -1? uri : uri.substring(0, h); // Get resource from local storage first var ls = window.lstorage || localStorage; var item = null; try { item = ls.getItem('ui.r.' + u); } catch(e) {} if (item != null && item != '') return item; // Get resource from network var http = new XMLHttpRequest(); http.open("GET", mode == 'remote'? (u + '?t=' + new Date().getTime() + '&r=' + Math.random()) : u, false); http.setRequestHeader("Accept", "*/*"); if (mode == 'remote') http.setRequestHeader("If-Modified-Since", "Thu, 1 Jan 1970 00:00:00 GMT"); http.send(null); if (http.status == 200) { if (http.getResponseHeader("X-Login") != null) { if (window.debug) debug('http error', u, 'X-Login'); // Redirect to login page if not signed in document.location = '/login/'; return null; } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { if (window.debug) debug('http error', u, 'No-Content'); return null; } try { ls.setItem('ui.r.' + u, http.responseText); } catch(e) {} return http.responseText; } if (window.debug) debug('http error', u, http.status, http.statusText); // Redirect to login page if not signed in if (http.status == 403) document.location = '/login/'; return null; }; })(); /** * Load Javascript and CSS. */ (function appboot() { var bootjs = document.createElement('script'); bootjs.type = 'text/javascript'; bootjs.text = 'try {\n' + appcache.get('/all-min.js') + '\n' + appcache.get('/config-min.js') + '\n} catch(e) { console.log(e.stack); throw e; }\n'; var head = document.getElementsByTagName('head')[0]; head.appendChild(bootjs); head.appendChild(ui.declareCSS(appcache.get('/ui-min.css'))); })(); } catch(e) { if (window.debug) debug(e.stack); throw e; } </script> </head> <body class="delayed"> <div id="content"> </div> <script type="text/javascript"> try { (function appbody() { /** * Get the app name */ var appname = location.pathname.split('/')[1]; /** * Set page title. */ document.title = appname; /** * The main page div. */ var contentdiv = $('content'); /** * The main app composite and page definitions. */ var appcomposite = null; var apppage = null; /** * Initialize the app HTTP clients. */ var appComp = sca.component('App'); var pagecomp = sca.reference(appComp, 'pages'); var composcomp = sca.reference(appComp, 'composites'); var startcomp = sca.httpclient('start', '/' + appname + '/start'); var stopcomp = sca.httpclient('stop', '/' + appname + '/stop'); var timercomp = sca.httpclient('timer', '/' + appname + '/timer'); var animationcomp = sca.httpclient('animation', '/' + appname + '/animation'); var locationcomp = sca.httpclient('location', '/' + appname + '/location'); /** * Pre-fetch app resources. */ var appresources = [ ['/all-min.js'], ['/ui-min.css'], ['/config-min.js'], ['/public/config-min.js'] ]; /** * Handle application cache events. */ applicationCache.addEventListener('checking', function(e) { //debug('appcache checking', e); }, false); applicationCache.addEventListener('error', function(e) { //debug('appcache error', e); }, false); applicationCache.addEventListener('noupdate', function(e) { //debug('appcache noupdate', e); }, false); applicationCache.addEventListener('downloading', function(e) { //debug('appcache downloading', e); }, false); applicationCache.addEventListener('progress', function(e) { //debug('appcache progress', e); }, false); applicationCache.addEventListener('updateready', function(e) { //debug('appcache updateready', e); try { applicationCache.swapCache(); } catch(e) {} //debug('appcache swapped', e); }, false); applicationCache.addEventListener('cached', function(e) { //debug('appcache cached', e); map(function(res) { appcache.get(res[0], 'remote'); }, appresources); }, false); /** * Handle network offline/online events. */ window.addEventListener('offline', function(e) { //debug('going offline'); }, false); window.addEventListener('online', function(e) { //debug('going online'); }, false); //debug(navigator.onLine? 'online' : 'offline'); /** * Find a named value in a tree of elements. The value name is given * as a list of ids. */ function namedvalue(l, id) { if (isNull(l)) return null; var e = car(l); // Element matches id segment if (car(id) == elementName(e)) { // Found element matching the whole id path if (isNull(cdr(id))) return e; // Search for next id segments in child elements if (!elementHasValue(e)) { var v = namedvalue(elementChildren(e), cdr(id)); if (v != null) return v; } } // Search for id through the whole element tree if (!elementHasValue(e)) { var v = namedvalue(elementChildren(e), id); if (v != null) return v; } return namedvalue(cdr(l), id); } /** * Return the value of an input element. */ function inputvalue(e) { if (e.className == 'entry' || e.className == 'password') { return car(childElements(e)).value; } if (e.className == 'button') { return car(childElements(e)).value; } if (e.className == 'checkbox') { if (!car(childElements(e)).checked) return null; return car(childElements(e)).value; } if (e.className == 'select') { return car(childElements(car(childElements(e)))).value; } return null; }; /** * Set a value into a widget. */ function setwidgetvalue(e, dv) { var htattrs = namedElementChild("'htattrs", dv); function attr(ce) { return mklist(elementName(ce) == "'htstyle"? 'style' : elementName(ce).substring(1), elementHasValue(ce)? elementValue(ce) : elementChildren(ce)); } function vattr(dv) { return (elementHasValue(dv) && !isNull(elementValue(dv)))? mklist(mklist('value', isNull(elementValue(dv))? '' : elementValue(dv))) : mklist(); } function sattr(dv) { var s = namedElementChild("'htstyle", dv); return isNull(s)? mklist() : mklist(mklist('style', elementHasValue(s)? elementValue(s) : elementChildren(s))) } var attrs = append(append(isNull(htattrs)? mklist() : map(attr, elementChildren(htattrs)), vattr(dv)), sattr(dv)); // Set the attributes of the widget function setattrs(vsetter, attrs, ce) { return map(function(a) { if (car(a) == 'value') return vsetter(a, ce); if (car(a) == 'style') { // Split a style property between a style attribute // and a stylesheet definition in the document's head function prop(s) { if (s == ';') return ''; var i = s.indexOf('<style>'); if (i == -1) return s; var j = s.indexOf('</style>'); return s.substring(0, i) + prop(s.substring(j + 8)); } function sheet(s) { var i = s.indexOf('<style>'); if (i == -1) return ''; var j = s.indexOf('</style>'); return s.substring(i + 7, j) + sheet(s.substring(j + 8)); } var st = cadr(a).replace(new RegExp('{id}', 'g'), e.id); var p = prop(st); var s = sheet(st); // Define the stylesheet if (s != '') { var esheet = ui.elementByID(document, 'style_' + e.id); if (isNull(esheet)) { var nesheet = document.createElement('style'); nesheet.id = 'style_' + e.id; nesheet.type = 'text/css'; var head = document.getElementsByTagName('head')[0]; head.appendChild(nesheet); nesheet.innerHTML = s; } else { esheet.innerHTML = s; } } var aname = ce.style.webkitAnimationName; // Set the style attribute ce.setAttribute('style', p); // Restart current animation if necessary if (!isNull(aname) && ce.style.webkitAnimationName == aname) { ce.style.webkitAnimationName = ''; ui.async(function restartanimation() { ce.style.webkitAnimationName = aname; }); } return a; } ce.setAttribute(car(a), cadr(a)); return a; }, attrs); } if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') { var ce = car(childElements(e)); return setattrs(function(a, ce) { ce.innerHTML = cadr(a); }, attrs, ce); } if (e.className == 'entry' || e.className == 'password') { var ce = car(childElements(e)); return setattrs(function(a, ce) { ce.defaultValue = cadr(a); }, attrs, ce); } if (e.className == 'button') { var ce = car(childElements(e)); return setattrs(function(a, ce) { ce.value = cadr(a); }, attrs, ce); } if (e.className == 'checkbox') { var ce = car(childElements(e)); function setcheckvalue(a, ce) { var v = cadr(a); ce.value = v; map(function(n) { if (n.nodeName == "SPAN") n.innerHTML = v; return n; }, nodeList(e.childNodes)); return true; } return setattrs(setcheckvalue, attrs, ce); } if (e.className == 'select') { var ce = car(childElements(car(childElements(e)))); function setselectvalue(a, ce) { var v = cadr(a); ce.value = v; ce.innerHTML = v; return true; } return setattrs(setselectvalue, attrs, ce); } if (e.className == 'list') { var dl = ui.datalist(isNull(dv)? mklist() : mklist(dv)); e.innerHTML = dl; return dl; } if (e.className == 'table') { var dl = ui.datatable(isNull(dv)? mklist() : mklist(dv)); e.innerHTML = dl; return dl; } if (e.className == 'link') { var ce = car(childElements(e)); function setlinkvalue(a, ce) { var v = cadr(a); if (isList(v)) { ce.href = car(v); ce.innerHTML = cadr(v); return true; } ce.href = v; ce.innerHTML = v; return true; } return setattrs(setlinkvalue, attrs, ce); } if (e.className == 'img') { var ce = car(childElements(e)); return setattrs(function(a, ce) { ce.setAttribute('src', cadr(a)); }, attrs, ce); } if (e.className == 'iframe') { var ce = car(childElements(e)); return setattrs(function(a, ce) { ce.setAttribute('src', cadr(a)); }, attrs, ce); } return ''; }; /** * Update the app page with the given app data. */ function updatepage(l) { if (isNull(l)) return true; // Update the widgets values function updatewidget(e) { var dv = namedvalue(l, map(function(t) { return "'" + t; }, e.id.split('.'))); if (dv == null || isNull(dv)) return e; setwidgetvalue(e, dv); return e; } map(updatewidget, filter(function(e) { return !isNull(e.id) && e.id.substring(0, 5) != 'page:'; }, nodeList(ui.elementByID(document, 'page').childNodes))); return true; } /** * Convert a document to application data. */ function docdata(doc) { if (isNull(doc)) return null; if (json.isJSON(mklist(doc))) return json.readJSON(mklist(doc)); if (atom.isATOMEntry(mklist(doc))) return atom.readATOMEntry(mklist(doc)); if (atom.isATOMFeed(mklist(doc))) return atom.readATOMFeed(mklist(doc)); return doc; } /** * Bind a handler to a widget. */ function bindwidgethandler(e, appname) { if (e.className == 'button') { var b = car(childElements(e)); b.name = e.id; ui.onclick(b, function(e) { return buttonClickHandler(b.value, appname); }); return e; } if (e.className == 'link') { var l = car(childElements(e)); var hr = l.href; if (hr.substring(0, 5) == 'link:' && hr.indexOf('://') == -1) { ui.onclick(l, function(e) { e.preventDefault(); return buttonClickHandler(hr.substring(5), appname); }); l.href = 'javascript:void()'; } return e; } if (e.className == 'entry' || e.className == 'password' || e.className == 'checkbox') { car(childElements(e)).name = e.id; return e; } if (e.className == 'select') { var ce = car(childElements(car(childElements(e)))); ce.name = e.id; return e; } return e; } /** * Initial fixup of a widget. */ function fixupwidget(e) { if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') { if (e.className == 'section') e.style.width = '100%'; var ce = car(childElements(e)); if (ce.innerHTML == '=' + e.id) ce.innerHTML = ''; return e; } if (e.className == 'entry' || e.className == 'password') { var ce = car(childElements(e)); if (ce.defaultValue == '=' + e.id) ce.defaultValue = ''; return e; } if (e.className == 'button') { var ce = car(childElements(e)); if (ce.value == '=' + e.id) ce.value = ''; return e; } if (e.className == 'checkbox') { var ce = car(childElements(e)); if (ce.value == '=' + e.id) { ce.value = ''; map(function(n) { if (n.nodeName == "SPAN") n.innerHTML = ''; return n; }, nodeList(e.childNodes)); } return e; } if (e.className == 'select') { var ce = car(childElements(car(childElements(e)))); if (ce.value == '=' + e.id) { ce.value = ''; ce.innerHTML = ''; } return e; } if (e.className == 'list') { car(childElements(e)).innerHTML = ''; e.style.width = '100%'; car(childElements(e)).style.width = '100%'; return e; } if (e.className == 'table') { car(childElements(e)).innerHTML = ''; e.style.width = '100%'; car(childElements(e)).style.width = '100%'; return e; } if (e.className == 'link') { var ce = car(childElements(e)); if (ce.innerHTML == '=' + e.id) ce.innerHTML = ''; return e; } if (e.className == 'img') { var ce = car(childElements(e)); return e; } if (e.className == 'iframe') { var ce = car(childElements(e)); e.innerHTML = '<iframe src="' + ce.href + '" frameborder="no" scrolling="no"></iframe>'; return e; } return e; } /** * Set initial value of a widget. */ function initwidget(e) { if (!isNull(e.id) && e.id.substring(0, 5) != 'page:') setwidgetvalue(e, mklist()); return e; } /** * Return the component bound to a uri. */ function isbound(uri, comps) { return !isNull(filter(function(comp) { return !isNull(filter(function(svc) { return !isNull(filter(function(b) { return uri == scdl.uri(b); }, scdl.bindings(svc))); }, scdl.services(comp))); }, comps)); } /** * Get app data from the main app page component. */ function getappdata(appname, page, compos) { try { // Eval a component init script function evalcompinit(doc) { if (isNull(doc)) return true; var js = car(json.readJSON(mklist(doc))); if (!elementHasValue(js)) return true; eval(elementValue(js)); return true; } // Initial setup of a widget function setupwidget(e) { initwidget(e); fixupwidget(e); bindwidgethandler(e, appname); } // Setup the widgets map(setupwidget, filter(function(e) { return !isNull(e.id); }, nodeList(ui.elementByID(document, 'page').childNodes))); // Get the app components var comps = scdl.components(compos); // Get the component app data if (isbound("start", comps)) { startcomp.get(location.search, function(doc, e) { if (isNull(doc)) { debug('error on get(start, ' + location.search + ')', e); return false; } // Display data on the page updatepage(docdata(doc)); }); } // Get and eval the optional timer, animation and location watch setup scripts if (isbound("timer", comps)) { timercomp.get('setup', function(doc, e) { if (isNull(doc)) { debug('error on get(timer, setup)', e); return false; } // Evaluate the component init expression return evalcompinit(doc); }); } if (isbound("animation", comps)) { animationcomp.get('setup', function(doc, e) { if (isNull(doc)) { debug('error on get(animation, setup)', e); return false; } // Evaluate the component init expression return evalcompinit(doc); }); } if (isbound("location", comps)) { locationcomp.get('setup', function(doc, e) { if (isNull(doc)) { debug('error on get(location, setup)', e); return false; } // Evaluate the component init expression return evalcompinit(doc); }); } return true; } catch(e) { debug('error in getappdata()', e); return true; } } /** * Return the page in an ATOM entry. */ function atompage(doc) { var entry = atom.readATOMEntry(mklist(doc)); if (isNull(entry)) return mklist(); var content = namedElementChild("'content", car(entry)); if (content == null) return mklist(); return elementChildren(content); } /** * Get the app page. */ function getapppage(appname, compos) { pagecomp.get(appname, function(doc, e) { //debug('page get'); if (isNull(doc)) { debug('error in getapppage', e); return false; } // Set the app HTML page into the content div var page = atompage(doc); contentdiv.innerHTML = writeStrings(writeXML(page, false)); apppage = page; // Merge in the app data if (!isNull(appcomposite)) getappdata(appname, apppage, appcomposite); }); } /** * Build a query string from the values of the page's input fields. */ function compquery() { function queryarg(e) { return e.id + '=' + inputvalue(e); } function childrenList(n) { return append(nodeList(n.childNodes), reduce(append, mklist(), map(childrenList, nodeList(n.childNodes)))); } var args = map(queryarg, filter(function(e) { return !isNull(e.id) && !isNull(inputvalue(e)); }, childrenList(ui.elementByID(document, 'page')))); // Append current location properties if known if (!isNull(geoposition)) { var g = geoposition; args = append(args, mklist('latitude=' + g.coords.latitude, 'longitude=' + g.coords.longitude, 'altitude=' + g.coords.altitude, 'accuracy=' + g.coords.accuracy, 'altitudeAccuracy=' + g.coords.altitudeAccuracy, 'heading=' + g.coords.heading, 'speed=' + g.coords.speed)); } return '?' + args.join('&'); } /** * Handle a button click event. */ function buttonClickHandler(id, appname) { try { var uri = compquery(); return sca.component(id, appname).get(uri, function(doc, e) { if (isNull(doc)) { debug('error on get(button, ' + uri + ')', e); return false; } // Inject data into the page updatepage(docdata(doc)); }); } catch(e) { debug('error in buttonClickHandler()', e); return true; } } /** * Handle a timer interval event. */ function intervalHandler() { try { var uri = compquery(); return timercomp.get(uri, function(doc, e) { if (isNull(doc)) { debug('error on get(timer, ' + uri + ')', e); return false; } // Inject data into the page updatepage(docdata(doc)); }); } catch(e) { debug('error in intervalHandler()', e); return true; } } /** * Setup an interval timer. */ function setupIntervalHandler(msec) { intervalHandler(); try { return setInterval(intervalHandler, msec); } catch(e) { debug('error in setupIntervalHandler()', e); return true; } } /** * Handle an animation event. */ var animationData = null; var gettingAnimationData = false; var currentAnimationData = null; var animationLoop = 0; var currentAnimationLoop = 0; function animationHandler() { try { function applyAnimation() { // Update page with current animation data updatepage(car(currentAnimationData)); // End of animation? if (isNull(cdr(currentAnimationData))) { if (currentAnimationLoop == -1) { // Repeat current animation forever currentAnimationData = animationData; return true; } currentAnimationLoop = currentAnimationLoop - 1; if (currentAnimationLoop <= 0) { // Get next animation data currentAnimationData = null; animationData = null; return true; } // Repeat animation currentAnimationData = animationData; return true; } // Move to the next animation frame currentAnimationData = cdr(currentAnimationData); return true; } // Get new animation data if necessary if (isNull(animationData)) { if (gettingAnimationData) return true; var uri = compquery(); return animationcomp.get(uri, function(doc, e) { if (isNull(doc)) { debug('error on get(animation, ' + uri + ')', e); return false; } // Apply the new animation currentAnimationData = docdata(doc); currentAnimationLoop = animationLoop; gettingAnimationData = false; applyAnimation(); }); } // Apply the current animation return applyAnimation(); } catch(e) { debug('error in animationHandler()', e); return true; } } /** * Setup an animation. */ function setupAnimationHandler(msec, loop) { animationLoop = loop; animationHandler(); try { return setInterval(animationHandler, msec); } catch(e) { debug('error in setupAnimationHandler()', e); return true; } } /** * Handle a location watch event. */ var locationWatch = null; var geoposition = null; function locationHandler(pos) { try { geoposition = pos; var uri = compquery(); return locationcomp.get(uri, function(doc, e) { if (isNull(doc)) { debug('error on get(location, ' + uri + ')', e); return false; } // Inject data into the page updatepage(docdata(doc)); }); } catch(e) { return locationErrorHandler(e); } } function locationErrorHandler(e) { debug('location error', e); if (!isNull(locationWatch)) { try { navigator.geolocation.clearWatch(locationWatch); } catch(e) {} locationWatch = null; } return true; } /** * Setup a location watch handler. */ function setupLocationHandler() { function installLocationHandler() { if (!isNull(locationWatch)) return true; try { locationWatch = navigator.geolocation.watchPosition(locationHandler, locationErrorHandler); } catch(e) { debug('error in installLocationHandler()', e); } return true; } installLocationHandler(); setInterval(installLocationHandler, 10000); return true; } /** * Handle orientation change. */ document.body.onorientationchange = function(e) { //debug('onorientationchange'); ui.onorientationchange(e); return true; }; /** * Return the composite in an ATOM entry. */ function atomcomposite(doc) { var entry = atom.readATOMEntry(mklist(doc)); if (isNull(entry)) return mklist(); var content = namedElementChild("'content", car(entry)); if (content == null) return mklist(); return elementChildren(content); } /** * Get the app composite. */ function getappcomposite(appname) { return composcomp.get(appname, function(doc, e) { //debug('page get'); if (isNull(doc)) { debug('error in getappcomposite', e); return false; } var compos = atomcomposite(doc); if (isNull(compos)) { // Create a default empty composite if necessary var x = '<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" ' + 'targetNamespace="http://app" name="app"></composite>'; compos = readXML(mklist(x)); } appcomposite = compos; // Merge in the app data if (!isNull(apppage)) getappdata(appname, apppage, appcomposite); }); } /** * Initialize the document. */ window.onload = function() { //debug('onload'); ui.onload(); // Initialize the app composite getappcomposite(appname); // Initialize the app page getapppage(appname); return true; }; })(); } catch(e) { debug(e.stack); throw e; } </script> </body> </html>