diff options
Diffstat (limited to 'sca-cpp/trunk')
54 files changed, 4238 insertions, 3693 deletions
diff --git a/sca-cpp/trunk/.gitignore b/sca-cpp/trunk/.gitignore index c2b43cc804..93663ee63c 100644 --- a/sca-cpp/trunk/.gitignore +++ b/sca-cpp/trunk/.gitignore @@ -59,6 +59,7 @@ config.status *config.js all.js intro*.png +intro*.b64 depcomp install-sh ltmain.sh diff --git a/sca-cpp/trunk/modules/edit/Makefile.am b/sca-cpp/trunk/modules/edit/Makefile.am index c749415425..55eca3ed7e 100644 --- a/sca-cpp/trunk/modules/edit/Makefile.am +++ b/sca-cpp/trunk/modules/edit/Makefile.am @@ -20,7 +20,7 @@ if WANT_PYTHON moddir = $(prefix)/modules/edit dist_mod_SCRIPTS = start stop ssl-start mkapplinks -nobase_dist_mod_DATA = edit.composite *.py htdocs/*.html htdocs/*.js htdocs/*.cmf htdocs/*.ico htdocs/*.png htdocs/*.txt htdocs/account/*.html htdocs/create/*.html htdocs/clone/*.html htdocs/data/*.html htdocs/app/*.html htdocs/store/*.html htdocs/stats/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html htdocs/public/*.html htdocs/public/*.png palettes/*/palette.composite apps/*/app.composite apps/*/app.stats apps/*/htdocs/app.html dashboards/*/user.apps store/*/store.apps -EXTRA_DIST = edit.composite *.py htdocs/*.html htdocs/*.js htdocs/*.cmf htdocs/*.ico htdocs/*.png htdocs/*.txt htdocs/account/*.html htdocs/create/*.html htdocs/clone/*.html htdocs/data/*.html htdocs/app/*.html htdocs/store/*.html htdocs/stats/*.html htdocs/graph/*.html htdocs/graph/*.js htdocs/page/*.html htdocs/page/*.js htdocs/login/*.html htdocs/logout/*.html htdocs/public/*.html htdocs/public/*.png palettes/*/palette.composite apps/*/app.composite apps/*/app.stats apps/*/htdocs/app.html dashboards/*/user.apps store/*/store.apps +nobase_dist_mod_DATA = edit.composite *.py htdocs/*.html htdocs/*.js htdocs/*.cmf htdocs/*.ico htdocs/home/*.png htdocs/home/*.b64 htdocs/*.txt htdocs/account/*.html htdocs/create/*.html htdocs/clone/*.html htdocs/app/*.html htdocs/store/*.html htdocs/stats/*.html htdocs/graph/*.html htdocs/home/*.html htdocs/page/*.html htdocs/login/*.html htdocs/logout/*.html htdocs/notauth/*.html htdocs/notfound/*.html htdocs/oops/*.html htdocs/public/*.html htdocs/public/*.png htdocs/public/*.b64 palettes/*/palette.composite apps/*/app.composite apps/*/app.stats apps/*/htdocs/app.html dashboards/*/user.apps store/*/store.apps +EXTRA_DIST = edit.composite *.py htdocs/*.html htdocs/*.js htdocs/*.cmf htdocs/*.ico htdocs/home/*.png htdocs/home/*.b64 htdocs/*.txt htdocs/account/*.html htdocs/create/*.html htdocs/clone/*.html htdocs/app/*.html htdocs/store/*.html htdocs/stats/*.html htdocs/graph/*.html htdocs/home/*.html htdocs/page/*.html htdocs/login/*.html htdocs/logout/*.html htdocs/notauth/*.html htdocs/notfound/*.html htdocs/oops/*.html htdocs/public/*.html htdocs/public/*.png htdocs/public/*.b64 palettes/*/palette.composite apps/*/app.composite apps/*/app.stats apps/*/htdocs/app.html dashboards/*/user.apps store/*/store.apps endif diff --git a/sca-cpp/trunk/modules/edit/accounts.py b/sca-cpp/trunk/modules/edit/accounts.py index 6c37fc5d32..600134c054 100644 --- a/sca-cpp/trunk/modules/edit/accounts.py +++ b/sca-cpp/trunk/modules/edit/accounts.py @@ -22,7 +22,7 @@ from util import * def accountid(user): return ("'" + user.id(), "'user.account") -# Get the user's account +# Get the current user's account def get(id, user, cache): account = cache.get(accountid(user)) if isNil(account): diff --git a/sca-cpp/trunk/modules/edit/htdocs/account/index.html b/sca-cpp/trunk/modules/edit/htdocs/account/index.html index ef1deb0527..7fef6c1d13 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/account/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/account/index.html @@ -17,26 +17,8 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> -<head> -<title>Account</title> -<meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> <div id="bodydiv" class="bodydiv"> -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menu"></div> - <table style="width: 100%;"> <tr> <td><h2><span id="h1"></span><span id="userNameHeader"></span></h2></td> @@ -53,7 +35,7 @@ <form id="userForm"> <table style="width: 100%;"> <tr><tr><td><b>Photo:</b></td></tr> -<tr><td><img src="/public/app.png" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> +<tr><td><img id="userimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> <tr><tr><td style="padding-top: 6px;"><b>Name:</b></td></tr> <tr><td><input type="text" id="userTitle" size="30" placeholder="Enter your name" style="width: 300px;"/></td></tr> <tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr> @@ -97,29 +79,22 @@ </form> <script type="text/javascript"> -ui.initbody(); // Init service references var editWidget = sca.component("EditWidget"); var user= sca.defun(sca.reference(editWidget, "user"), "id"); var accounts = sca.reference(editWidget, "accounts"); -// Get the user name -var username = ''; -try { - username = user.id() -} catch(e) {} - // Set page titles -document.title = windowtitle(window.location.hostname) + ' - Account - ' + username; -$('userNameHeader').innerHTML = username; +document.title = ui.windowtitle(location.hostname) + ' - Account'; -// Load the menu bar -displaymenu(); +// Set images +$('userimg').src = ui.b64img(appcache.get('/public/user.b64')); /** * The current account entry and corresponding saved XML content. */ +var username; var accountentry; var savedaccountentryxml = ''; @@ -134,7 +109,9 @@ function getaccount(name) { return false; accountentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name)); + username = cadr(assoc("'id", cdr(accountentry))); var title = cadr(assoc("'title", cdr(accountentry))); + $('userNameHeader').innerHTML = username; $('userTitle').value = title; var content = cadr(assoc("'content", cdr(accountentry))); @@ -170,6 +147,8 @@ function getaccount(name) { * Save the user's account. */ function save(entryxml) { + if (isNil(username)) + return false; $('saveStatus').innerHTML = 'Saving'; savedaccountentryxml = entryxml; accounts.put(username, savedaccountentryxml, function(e) { @@ -228,14 +207,8 @@ $('userForm').onsubmit = function() { }; // Get the user's account -getaccount(username); -</script> +getaccount(); -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> +</script> </div> -</body> -</html> - diff --git a/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf b/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf index 1d9464bea6..4f3358edef 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf +++ b/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf @@ -1,25 +1,17 @@ CACHE MANIFEST -# Common resources -/all-min.js -/ui-min.css +# Version 5 # App resources / -/data/index.html /favicon.ico -/footconfig.js -/frame.html -/headconfig.js -/public/app.png +/notauth/ +/notfound/ +/notyet/ +/oops/ /public/iframe.html /public/img.png -/public/notauth.html -/public/notfound.html -/public/notyet.html -/public/oops.html /public/touchicon.png -/robots.txt NETWORK: * diff --git a/sca-cpp/trunk/modules/edit/htdocs/app/frame.html b/sca-cpp/trunk/modules/edit/htdocs/app/frame.html deleted file mode 100644 index 3509e1e190..0000000000 --- a/sca-cpp/trunk/modules/edit/htdocs/app/frame.html +++ /dev/null @@ -1,31 +0,0 @@ -<!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-manifest.cmf"> -<head> -<title></title> -<meta name="viewport" content="width=device-width, user-scalable=no, initial-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="stylesheet" type="text/css" href="/ui-min.css"/> -</head> -<body> -</body> -</html> - diff --git a/sca-cpp/trunk/modules/edit/htdocs/app/index.html b/sca-cpp/trunk/modules/edit/htdocs/app/index.html index f62cc5d0eb..cb89cd0ced 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/app/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/app/index.html @@ -23,36 +23,77 @@ <meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> +<base href="/"/> <script type="text/javascript"> -document.title = window.location.hostname.split('.')[0]; + +window.appcache = {}; + +/** + * Get and cache a resource. + */ +appcache.get = function(uri) { + var h = uri.indexOf('#'); + var u = h == -1? uri : uri.substring(0, h); + + // Get resource from local storage first + var item = localStorage.getItem(u); + if (item != null && item != '') + return item; + + // Get resource from network + var http = new XMLHttpRequest(); + http.open("GET", u, false); + http.send(null); + if (http.status == 200) { + if (http.getResponseHeader("X-Login") != null) { + if (log) log('http err', u, 'X-Login'); + return null; + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + if (log) log('http err', u, 'No-Content'); + return null; + } + localStorage.setItem(u, http.responseText); + return http.responseText; + } + if (log) log('http err', u, http.status, http.statusText); + return null; +}; + +// Load Javascript and CSS +(function() { + var bootjs = document.createElement('script'); + bootjs.type = 'text/javascript'; + bootjs.text = appcache.get('/all-min.js'); + document.head.appendChild(bootjs); + document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css'))); +})(); + </script> -<link rel="apple-touch-icon" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> </head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> -<div id="bodydiv" class="bodydiv"> +<body class="delayed" onload="onload();"> +<div id="mainbodydiv" class="mainbodydiv"> <div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="app"> -<iframe id="appframe" style="position: relative; height: 5000px; width: 100%;" scrolling="no" frameborder="0" src="/frame.html"></iframe> +<script type="text/javascript"> +(function() { +$('headdiv').appendChild(ui.declareScript(appcache.get('/headconfig.js'))); +})(); +</script> </div> -<div id="appbuffer" style="visibility: hidden"> +<div id="content"> </div> <script type="text/javascript"> -ui.initbody(); + +// Set the document title +document.title = location.hostname.split('.')[0]; /** - * The main app div. + * The main page div. */ -var appdiv = $('app'); -var appframe = $('appframe'); -var appbody; +var contentdiv = $('content'); /** * Start, stop, timer, animation and location components. @@ -64,6 +105,59 @@ var animationcomp = sca.httpclient('animation', '/animation'); var locationcomp = sca.httpclient('location', '/location'); /** + * Pre-fetch app resources. + */ +var appresources = [ + ['/all-min.js'], + ['/app.html'], + ['/ui-min.css'], + ['/footconfig.js'], + ['/headconfig.js'], +]; + +/** + * Handle application cache events. + */ +applicationCache.addEventListener('checking', function(e) { + //log('appcache checking', e); +}, false); +applicationCache.addEventListener('error', function(e) { + //log('appcache error', e); +}, false); +applicationCache.addEventListener('noupdate', function(e) { + //log('appcache noupdate', e); +}, false); +applicationCache.addEventListener('downloading', function(e) { + //log('appcache downloading', e); +}, false); +applicationCache.addEventListener('progress', function(e) { + //log('appcache progress', e); +}, false); +applicationCache.addEventListener('updateready', function(e) { + //log('appcache updateready', e); + applicationCache.swapCache(); + //log('appcache swapped', e); +}, false); +applicationCache.addEventListener('cached', function(e) { + //log('appcache cached', e); + map(function(res) { + appcache.get(res[0]); + }, appresources); +}, false); + +/** + * Handle network offline/online events. + */ +window.addEventListener('offline', function(e) { + //log('going offline'); +}, false); +window.addEventListener('online', function(e) { + //log('going online'); +}, false); + +//log(navigator.onLine? 'online' : 'offline'); + +/** * Find a named value in a tree of elements. The value name is given * as a list of ids. */ @@ -172,12 +266,12 @@ function setwidgetvalue(e, dv) { // Define the stylesheet if (s != '') { - var esheet = appframe.contentDocument.getElementById('style_' + e.id); + var esheet = contentdiv.getElementById('style_' + e.id); if (isNil(esheet)) { var nesheet = document.createElement('style'); nesheet.id = 'style_' + e.id; nesheet.type = 'text/css'; - appframe.contentDocument.getElementsByTagName('head')[0].appendChild(nesheet); + contentdiv.getElementsByTagName('head')[0].appendChild(nesheet); nesheet.innerHTML = s; } else { esheet.innerHTML = s; @@ -294,7 +388,7 @@ function updatepage(l) { return e; } - map(updatewidget, filter(function(e) { return !isNil(e.id) && e.id.substring(0, 5) != 'page:'; }, nodeList(ui.elementByID(appbody, 'page').childNodes))); + map(updatewidget, filter(function(e) { return !isNil(e.id) && e.id.substring(0, 5) != 'page:'; }, nodeList(ui.elementByID(contentdiv, 'page').childNodes))); return true; } @@ -474,16 +568,10 @@ function getpagedata() { } // Get the component app data - var doc = getdoc(startcomp, 'start', window.location.search); - - // Prepare app HTML page - appbody = appframe.contentDocument.body; - var appbufferbody = $('appbufferframe').contentDocument.body; - appbody.innerHTML = appbufferbody.innerHTML; - appbufferbody.innerHTML = ''; + var doc = getdoc(startcomp, 'start', location.search); // Setup the widgets - map(setupwidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID(appbody, 'page').childNodes))); + map(setupwidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID(contentdiv, 'page').childNodes))); // Display data on the page displaypage(doc); @@ -513,7 +601,7 @@ function compquery() { return append(nodeList(n.childNodes), reduce(append, mklist(), map(childrenList, nodeList(n.childNodes)))); } - var args = map(queryarg, filter(function(e) { return !isNil(e.id) && !isNil(inputvalue(e)); }, childrenList(ui.elementByID(appbody, 'page')))); + var args = map(queryarg, filter(function(e) { return !isNil(e.id) && !isNil(inputvalue(e)); }, childrenList(ui.elementByID(contentdiv, 'page')))); // Append current location properties if known if (!isNil(geoposition)) { @@ -677,12 +765,35 @@ function setupLocationHandler() { return true; } -// Load the app frame -$('appbuffer').innerHTML = '<iframe id="appbufferframe" style="position: relative; height: 5000px; width: 100%;" scrolling="no" frameborder="0" src="app.html" onload="getpagedata()"></iframe>'; +// Load the app page +var appcontent = appcache.get('/app.html'); +contentdiv.innerHTML = appcontent; + +// Merge in the app data +getpagedata(); + +/** + * Document load post processing. + */ +function onload() { + //log('onload'); + + // Show the page + document.body.style.visibility = 'visible'; + + // Scroll to the top and hide the address bar + window.scrollTo(0, 0); + return true; +} + </script> <div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> +<script type="text/javascript"> +(function() { +$('footdiv').appendChild(ui.declareScript(appcache.get('/footconfig.js'))); +})(); +</script> </div> </div> diff --git a/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf b/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf index 8e6e666844..4f3358edef 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf +++ b/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf @@ -1,39 +1,17 @@ CACHE MANIFEST -# Version 2 - -# Common resources -/all-min.js -/ui-min.css +# Version 5 # App resources / -/account/ -/app/ -/clone/ -/data/ -/create/ /favicon.ico -/footconfig.js -/graph/graph.js -/graph/ -/headconfig.js -/home.png -/menu.js -/page/ -/page/page.js -/public/app.png -/public/grid72.png +/notauth/ +/notfound/ +/notyet/ +/oops/ /public/iframe.html /public/img.png -/public/notauth.html -/public/notfound.html -/public/notyet.html -/public/oops.html /public/touchicon.png -/robots.txt -/stats/ -/store/ NETWORK: * diff --git a/sca-cpp/trunk/modules/edit/htdocs/clone/index.html b/sca-cpp/trunk/modules/edit/htdocs/clone/index.html index 29ebe1ce06..38b4edefa8 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/clone/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/clone/index.html @@ -17,26 +17,8 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> -<head> -<title></title> -<meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> <div id="bodydiv" class="bodydiv"> -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menu"></div> - <table style="width: 100%;"> <tr> <td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td> @@ -54,7 +36,7 @@ <tr><td><b>New App Name:</b></td></tr> <tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/> <span id="appDomain"></span></td></tr> <tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr> -<tr><td><img src="/public/app.png" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> +<tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> <tr><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr> <tr><td><input type="checkbox" value="shared"/><span>Shared</span></td></tr> <tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr> @@ -69,20 +51,17 @@ </form> <script type="text/javascript"> -ui.initbody(); // Get the app name -var appname = ui.fragmentParams()['app']; -if (isNil(appname)) - window.open('/', '_self'); +var appname = ui.fragmentParams(location)['app']; /** * Return the link to an app. */ function applink(appname) { - var protocol = window.location.protocol; - var host = window.location.hostname; - var port = ':' + window.location.port; + var protocol = location.protocol; + var host = location.hostname; + var port = ':' + location.port; if (port == ':80' || port == ':443' || port == ':') port = ''; var link = protocol + '//' + appname + '.' + host + port + '/'; @@ -91,17 +70,17 @@ function applink(appname) { // Set page titles var tclone = isNil(config.clone)? 'Clone' : config.clone; -document.title = windowtitle(window.location.hostname) + ' - ' + tclone + ' - ' + appname; +document.title = ui.windowtitle(location.hostname) + ' - ' + tclone + ' - ' + appname; $('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>'; $('th').innerHTML = tclone + ' this App'; $('cloneAppOKButton').value = tclone; $('cloneAppOKButton').title = tclone + ' this app'; -// Load the menu bar -displaymenu(); +// Set images +$('appimg').src = ui.b64img(appcache.get('/public/app.b64')); // Init form -$('appDomain').innerHTML = '.' + window.location.hostname; +$('appDomain').innerHTML = '.' + location.hostname; // Init service references var editWidget = sca.component("EditWidget"); @@ -152,7 +131,7 @@ $('cloneAppForm').onsubmit = function() { return false; // Open it in the page editor - ui.navigate('/page/#app=' + name, '_self'); + ui.navigate('/#view=page&app=' + name, '_view'); return false; }); return false; @@ -162,18 +141,12 @@ $('cloneAppForm').onsubmit = function() { * Cancel cloning an app. */ $('cloneAppCancelButton').onclick = function() { - ui.navigate('/stats/#app=' + appname, '_self'); + history.back(); }; // Get the current app getapp(appname); -</script> -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> +</script> </div> -</body> -</html> - diff --git a/sca-cpp/trunk/modules/edit/htdocs/create/index.html b/sca-cpp/trunk/modules/edit/htdocs/create/index.html index 575016aeb8..35c7733c38 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/create/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/create/index.html @@ -17,26 +17,8 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> -<head> -<title>Create App</title> -<meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> <div id="bodydiv" class="bodydiv"> -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menu"></div> - <table style="width: 100%;"> <tr><td><h2><span id="h1"></span></h2></td></tr> </table> @@ -52,7 +34,7 @@ <tr><td><b>App Name:</b></td></tr> <tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/> <span id="appDomain"></span></td></tr> <tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr> -<tr><td><img src="/public/app.png" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> +<tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> <tr><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr> <tr><td><input type="checkbox" value="shared"/><span>Shared</span></td></tr> <tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr> @@ -67,17 +49,16 @@ </form> <script type="text/javascript"> -ui.initbody(); // Set page titles -document.title = windowtitle(window.location.hostname) + ' - Create App'; -$('h1').innerHTML = hometitle(window.location.hostname); +document.title = ui.windowtitle(location.hostname) + ' - Create App'; +$('h1').innerHTML = ui.hometitle(location.hostname); -// Load the menu bar -displaymenu(); +// Set images +$('appimg').src = ui.b64img(appcache.get('/public/app.b64')); // Init form -$('appDomain').innerHTML = '.' + window.location.hostname; +$('appDomain').innerHTML = '.' + location.hostname; // Init service references var editWidget = sca.component("EditWidget"); @@ -101,7 +82,7 @@ $('createAppForm').onsubmit = function() { return false; // Open it in the page editor - ui.navigate('/page/#app=' + name, '_self'); + ui.navigate('/#view=page&app=' + name, '_view'); return false; }); return false; @@ -111,15 +92,9 @@ $('createAppForm').onsubmit = function() { * Cancel creating an app. */ $('createAppCancelButton').onclick = function() { - return ui.navigate('/store/', '_self'); + history.back(); }; -</script> -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> +</script> </div> -</body> -</html> - diff --git a/sca-cpp/trunk/modules/edit/htdocs/data/index.html b/sca-cpp/trunk/modules/edit/htdocs/data/index.html deleted file mode 100644 index 23b8668ce4..0000000000 --- a/sca-cpp/trunk/modules/edit/htdocs/data/index.html +++ /dev/null @@ -1,105 +0,0 @@ -<!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-manifest.cmf"> -<head> -<title>View</title> -<script type="text/javascript"> -var cn = window.location.search.substring(1).split('=')[1]; -document.title = 'View - ' + window.location.hostname.split('.')[0] + '/' + cn; -</script> -<meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"> -<script type="text/javascript" src="/all-min.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> - -<div id="bodydiv" style="position: absolute; top: 0px; left: 0px; right: 0px;"> -<div id="compLinkHeader" style="margin-top: 4px; margin-bottom: 4px;"></div> -<div id="datadiv" style="position: relative; left: 0px; right: 0px;"> -</div> - -<script type="text/javascript"> -ui.initbody(); - -// Get the component name -var cname = ui.fragmentParams()['component']; - -/** - * The current component. - */ -var comp = sca.component(cname); - -/** - * Display an HTML element. - */ -function display(e) { - $('datadiv').innerHTML = e; - return true; -} - -/** - * Convert data to an HTML table. - */ -function datatable(e) { - return ui.datatable(e); -} - -/** - * Wrap a document in an HTML table. - */ -function mkdoctable(doc) { - var tr = '<tr><td class="datatdl">' + 'value' + '</td>' + '<td class="datatdr">' + doc + '</td></tr>'; - return '<table class="datatable ' + (window.name == 'previewFrame'? ' databg' : '') + '" style="width: 100%;">' + tr + '</table>'; -} - -/** - * Get and display the contents of the current component. - */ -function getdata() { - return comp.getnocache('', function(doc) { - - // Stop now if we didn't the doc - if (doc == null) - return false; - - if (json.isJSON(mklist(doc))) - return display(datatable(json.readJSON(mklist(doc)))); - - if (atom.isATOMEntry(mklist(doc))) - return display(datatable(atom.readATOMEntry(mklist(doc)))); - - if (atom.isATOMFeed(mklist(doc))) - return display(datatable(atom.readATOMFeed(mklist(doc)))); - - return display(mkdoctable('<iframe style="width: 100%; height: 5000px;" scrolling="no" frameborder="0" src="' + comp.uri + '"/>')); - }); -} - -getdata(); -</script> - -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> -</body> -</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js deleted file mode 100644 index d459a4b021..0000000000 --- a/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js +++ /dev/null @@ -1,1778 +0,0 @@ -/* - * 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. - */ - -/** - * SVG composite rendering functions. - */ - -var graph = {}; - -/** - * Basic colors - */ -graph.colors = {}; -graph.colors.black = '#000000'; -graph.colors.blue = '#0000ff'; -graph.colors.cyan = '#00ffff'; -graph.colors.gray = '#808080' -graph.colors.lightgray = '#dcdcdc' -graph.colors.green = '#00ff00'; -graph.colors.magenta = '#ff00ff'; -graph.colors.orange = '#ffa500'; -graph.colors.pink = '#ffc0cb'; -graph.colors.purple = '#800080'; -graph.colors.red = '#ff0000'; -graph.colors.white = '#ffffff'; -graph.colors.yellow = '#ffff00'; -graph.colors.link = '#598edd'; - -graph.colors.orange1 = '#ffd666'; -graph.colors.green1 = '#bbe082'; -graph.colors.blue1 = '#66dbdf'; -graph.colors.yellow1 = '#fdf57a'; -graph.colors.cyan1 = '#e6eafb'; -graph.colors.lightgray1 = '#eaeaea' -graph.colors.pink1 = '#ffd9e0'; -graph.colors.red1 = '#d03f41'; -graph.colors.white1 = '#ffffff'; - -graph.colors.orange2 = '#ffbb00'; -graph.colors.green2 = '#96d333'; -//graph.colors.blue2 = '#0d7cc1'; -graph.colors.blue2 = '#00c3c9'; -graph.colors.red2 = '#d03f41'; -graph.colors.yellow2 = '#fcee21'; -graph.colors.magenta2 = '#c0688a'; -graph.colors.cyan2 = '#d5dcf9'; -graph.colors.lightgray2 = '#dcdcdc' -graph.colors.pink2 = '#ffc0cb'; -graph.colors.white2 = '#ffffff'; - -graph.colors.orange3 = '#ffc700'; -graph.colors.green3 = '#92e120'; -graph.colors.blue3 = '#008fd1'; -graph.colors.yellow3 = '#fdf400'; -graph.colors.cyan3 = '#b4d3fd'; -graph.colors.lightgray3 = '#e3e3e3' -graph.colors.pink3 = '#da749b'; -graph.colors.red3 = '#ed3f48'; -graph.colors.white3 = '#ffffff'; - -/** - * Default positions and sizes. - */ -var palcx = 2500; -var proxcx = 20; -var proxcy = 20; -var buttoncx = 55; -var buttoncy = 23; -var curvsz = 4; -var tabsz = 2; -var titlex = 4; -var titley = 11; -var titlesp = 3; -var titlew = ui.isMobile()? -2 : 0; - -/** - * SVG rendering functions. - */ - -graph.svgns='http://www.w3.org/2000/svg'; - -/** - * Make an SVG graph. - */ -graph.mkgraph = function(cdiv, pos, cvalue, cadd, ccopy, cdelete) { - - // Create a div element to host the graph - var div = document.createElement('div'); - div.id = 'svgdiv'; - div.style.position = 'absolute'; - div.style.left = ui.pixpos(pos.xpos() + cdiv.offsetLeft); - div.style.top = ui.pixpos(pos.ypos() + cdiv.offsetTop); - //div.style.overflow = 'hidden'; - cdiv.appendChild(div); - - // Create SVG element - var svg = document.createElementNS(graph.svgns, 'svg'); - svg.style.height = ui.pixpos(5000); - svg.style.width = ui.pixpos(5000); - div.appendChild(svg); - - // Track element dragging and selection - graph.dragging = null; - graph.dragged = false; - graph.moverenderer = null; - graph.selected = null; - cvalue.disabled = true; - ccopy.disabled = true; - cdelete.disabled = true; - - /** - * Find the first draggable element in a hierarchy of elements. - */ - function draggable(n) { - if (n == div || n == svg || n == null) - return null; - if (n.nodeName == 'g' && !isNil(n.id) && n.id != '') - return n; - return draggable(n.parentNode); - } - - /** - * Handle a mouse down or touch start event. - */ - function onmousedown(e) { - - // Remember mouse or touch position - var pos = typeof e.touches != "undefined" ? e.touches[0] : e; - graph.downX = pos.screenX; - graph.downY = pos.screenY; - graph.moveX = pos.screenX; - graph.moveY = pos.screenY; - - // Engage the click component selection right away - // on mouse controlled devices - if (typeof e.touches == 'undefined') - onclick(e); - - // Find and remember draggable component - var dragging = draggable(e.target); - if (dragging == null || dragging != graph.selected) - return true; - graph.dragging = dragging; - graph.dragged = false; - - // Remember current drag position - graph.dragX = pos.screenX; - graph.dragY = pos.screenY; - - e.preventDefault(); - return true; - }; - - if (!ui.isMobile()) { - div.onmousedown = function(e) { - //log('onmousedown'); - var suspend = svg.suspendRedraw(10); - var r = onmousedown(e); - svg.unsuspendRedraw(suspend); - return r; - } - } else { - div.ontouchstart = function(e) { - //log('ontouchstart'); - - // Clear current move renderer if it's running - if (!isNil(graph.moverenderer)) { - clearInterval(graph.moverenderer); - graph.moverenderer = null; - } - - var suspend = svg.suspendRedraw(10); - var r = onmousedown(e); - svg.unsuspendRedraw(suspend); - return r; - } - } - - /** - * Handle a mouse up or touch end event. - */ - function onmouseup(e) { - - // Engage the click component selection now on touch devices - if (ui.isMobile()) { - if (!graph.dragged && graph.moveX == graph.downX && graph.moveY == graph.downY) - return onclick(e); - } - - // Stop here if the component was not dragged - if (graph.dragging == null) - return true; - if (!graph.dragged) { - graph.dragging = null; - return true; - } - - if (graph.dragging.parentNode == svg && graph.dragging.id.substring(0, 8) != 'palette:') { - - // Add new dragged component to the composite - if (isNil(graph.dragging.compos)) { - var compos = scdl.composite(svg.compos); - setElement(compos, graph.sortcompos(graph.addcomps(mklist(graph.dragging.comp), compos))); - graph.dragging.compos = svg.compos; - } - - // Update component position - setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.abspos(graph.dragging, svg))); - - // Wire component to neighboring reference - if (!isNil(graph.dragging.svcpos)) { - var compos = scdl.composite(svg.compos); - setElement(compos, graph.sortcompos(graph.clonerefs(graph.wire(graph.dragging, compos, svg)))); - } - - // Snap top level component position to grid - if (graph.dragging.parentNode == svg) { - var gpos = graph.relpos(graph.dragging); - setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.mkpath().pos(graph.gridsnap(gpos.xpos()), graph.gridsnap(gpos.ypos())))); - } - } - - // Forget current dragged component - graph.dragging = null; - graph.dragged = false; - - // Refresh the composite - //log('onmouseup refresh'); - var nodes = graph.refresh(svg); - - // Reselected the previously selected component - if (!isNil(graph.selected)) { - graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes); - graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); - - // Trigger component select event - svg.oncompselect(graph.selected); - } - - // Trigger composite change event - svg.oncomposchange(false); - return true; - }; - - if (!ui.isMobile()) { - div.onmouseup = function(e) { - //log('onmouseup'); - var suspend = svg.suspendRedraw(10); - var r = onmouseup(e); - svg.unsuspendRedraw(suspend); - return r; - } - } else { - div.ontouchend = function(e) { - //log('ontouchend'); - - // Clear current move renderer if it's running - if (!isNil(graph.moverenderer)) { - clearInterval(graph.moverenderer); - graph.moverenderer = null; - } - - var suspend = svg.suspendRedraw(10); - var r = onmouseup(e); - svg.unsuspendRedraw(suspend); - return r; - } - } - - /** - * Handle a mouse or touch click event. - */ - function onclick(e) { - //log('onclick logic'); - - // Find selected component - var selected = draggable(e.target); - if (selected == null) { - if (graph.selected != null) { - - // Reset current selection - graph.compselect(graph.selected, false, cvalue, ccopy, cdelete); - graph.selected = null; - - // Trigger component select event - svg.oncompselect(null); - } - - // Dismiss the palette - if (e.target == div || e.target == svg && ui.numpos(div.style.left) != (palcx * -1)) - div.style.left = ui.pixpos(palcx * -1); - - return true; - } - - // Ignore multiple click events - if (selected == graph.selected) - return true; - if (selected.id.substring(0, 8) == 'palette:' && ui.numpos(div.style.left) != 0) - return true; - - // Deselect previously selected component - graph.compselect(graph.selected, false, cvalue, ccopy, cdelete); - - // Clone component from the palette - if (selected.id.substring(0, 8) == 'palette:') { - var compos = scdl.composite(svg.compos); - var comp = graph.clonepalette(selected, compos, svg); - setElement(compos, graph.sortcompos(graph.addcomps(mklist(comp), compos))); - - // Move into the editing area and hide the palette - div.style.left = ui.pixpos(palcx * -1); - - // Refresh the composite - //log('onclick refresh'); - var nodes = graph.refresh(svg); - - // Reselect the previously selected component - graph.selected = graph.findcompnode(scdl.name(comp), nodes); - graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); - - // Trigger component select event - svg.oncompselect(graph.selected); - - // Trigger composite change event - svg.oncomposchange(true); - - } else { - graph.selected = selected; - - // Select the component - graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); - - // Trigger component select event - svg.oncompselect(graph.selected); - } - - //log('comp selected'); - - if (e.preventDefault) - e.preventDefault(); - else - e.returnValue = false; - return true; - } - - if (!ui.isMobile()) { - div.onclick = function(e) { - //log('div onclick'); - var suspend = svg.suspendRedraw(10); - var r = onclick(e); - svg.unsuspendRedraw(suspend); - return r; - } - svg.onclick = function(e) { - //log('svg onclick'); - var suspend = svg.suspendRedraw(10); - var r = onclick(e); - svg.unsuspendRedraw(suspend); - return r; - } - } - - /** - * Handle a mouse or touch move event. - */ - function onmousemove(e) { - if (graph.dragging == null) - return true; - - // Ignore duplicate mouse move events - if (graph.moveX == graph.dragX && graph.moveY == graph.dragY) - return true; - - // Remember that the component was dragged - graph.dragged = true; - - // Cut wire to component - if (graph.dragging.parentNode != svg) { - var compos = scdl.composite(svg.compos); - setElement(compos, graph.sortcompos(graph.cutwire(graph.dragging, compos, svg))); - - // Bring component to the top - graph.bringtotop(graph.dragging, svg); - } - - // Calculate new position of dragged element - var gpos = graph.relpos(graph.dragging); - var newX = gpos.xpos() + (graph.moveX - graph.dragX); - var newY = gpos.ypos() + (graph.moveY - graph.dragY); - if (newX >= palcx) - graph.dragX = graph.moveX - else - newX = palcx; - if (newY >= 0) - graph.dragY = graph.moveY; - else - newY = 0; - - // Detach child elements to speedup rendering - graph.compoutline(graph.dragging, true); - - // Move the dragged element - graph.move(graph.dragging, graph.mkpath().pos(newX, newY)); - - return false; - }; - - if (!ui.isMobile()) { - window.onmousemove = function(e) { - //log('onmousemove'); - - // Remember mouse position - graph.moveX = e.screenX; - graph.moveY = e.screenY; - - var suspend = svg.suspendRedraw(10); - var r = onmousemove(e); - svg.unsuspendRedraw(suspend); - return r; - } - } else { - div.ontouchmove = function(e) { - //log('ontouchmove'); - - // Remember touch position - var pos = e.touches[0]; - if (graph.moveX == pos.screenX && graph.moveY == pos.screenY) - return true; - graph.moveX = pos.screenX; - graph.moveY = pos.screenY; - if (graph.moveX == graph.dragX && graph.moveY == graph.dragY) - return true; - - // Start async move renderer - if (graph.moverenderer == null) { - graph.moverenderer = setInterval(function() { - var suspend = svg.suspendRedraw(10); - onmousemove(e); - svg.unsuspendRedraw(suspend); - }, 10); - } - return true; - } - } - - /** - * Handle field on change events. - */ - function onvaluechange() { - if (graph.selected == null) - return false; - if (g.parentNode.style.visibility == 'hidden') - return false; - - // Change component name and refactor references to it - function changename() { - var compos = scdl.composite(svg.compos); - cvalue.value = graph.ucid(cvalue.value, compos, false); - graph.selected.id = cvalue.value; - setElement(compos, graph.sortcompos(graph.renamecomp(graph.selected.comp, compos, cvalue.value))); - - // Refresh the composite - //log('onchangename refresh'); - var nodes = graph.refresh(svg); - - // Reselected the previously selected component - graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes); - graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); - - // Trigger component select event - svg.oncompselect(graph.selected); - - // Trigger composite change event - svg.oncomposchange(true); - return false; - } - - // Change the component property value - function changeprop() { - graph.setproperty(graph.selected.comp, cvalue.value); - cvalue.value = graph.property(graph.selected.comp); - cvalue.disabled = !graph.hasproperty(graph.selected.comp); - - // Refresh the composite - //log('onchangeprop refresh'); - var nodes = graph.refresh(svg); - - // Reselected the previously selected component - graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes); - graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); - - // Trigger component select event - svg.oncompselect(graph.selected); - - // Trigger composite change event - svg.oncomposchange(true); - return false; - } - - return graph.hasproperty(graph.selected.comp)? changeprop() : changename(); - }; - - cvalue.onchange = function() { - var suspend = svg.suspendRedraw(10); - var r = onvaluechange(); - svg.unsuspendRedraw(suspend); - return r; - } - - // Handle delete event - function ondeleteclick() { - if (graph.selected == null) - return false; - if (graph.selected.id.substring(0, 8) != 'palette:') { - - // Remove selected component - var compos = scdl.composite(svg.compos); - if (isNil(graph.selected.compos)) - setElement(compos, graph.sortcompos(graph.cutwire(graph.selected, compos, svg))); - setElement(compos, graph.sortcompos(graph.clonerefs(graph.gcollect(graph.removecomp(graph.selected.comp, compos))))); - - // Reset current selection - graph.compselect(graph.selected, false, cvalue, ccopy, cdelete); - graph.selected = null; - - // Refresh the composite - //log('ondelete refresh'); - graph.refresh(svg); - - // Trigger component select event - svg.oncompselect(null); - - // Trigger composite change event - svg.oncomposchange(true); - } - return false; - }; - - cdelete.onclick = function() { - var suspend = svg.suspendRedraw(10); - var r = ondeleteclick(); - svg.unsuspendRedraw(suspend); - return r; - }; - - // Handle copy event - function oncopyclick() { - if (graph.selected == null) - return false; - if (graph.selected.id.substring(0, 8) == 'palette:') - return false; - - // Clone the selected component - var compos = scdl.composite(svg.compos); - var comps = graph.clonecomp(graph.selected, compos, svg); - setElement(compos, graph.sortcompos(graph.addcomps(comps, compos))); - - // Refresh the composite - //log('onclick refresh'); - var nodes = graph.refresh(svg); - - // Select the component clone - graph.selected = graph.findcompnode(scdl.name(car(comps)), nodes); - graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); - - // Trigger component select event - svg.oncompselect(graph.selected); - - // Trigger composite change event - svg.oncomposchange(true); - - return false; - }; - - ccopy.onclick = function() { - var suspend = svg.suspendRedraw(10); - var r = oncopyclick(); - svg.unsuspendRedraw(suspend); - return r; - }; - - // Handle add event - cadd.onclick = function() { - - // Show the palette - div.style.left = ui.pixpos(0); - return false; - }; - - // Create a hidden SVG element to help compute the width - // of component and reference titles - graph.svgtitles = document.createElementNS(graph.svgns, 'svg'); - graph.svgtitles.style.visibility = 'hidden'; - graph.svgtitles.style.height = ui.pixpos(0); - graph.svgtitles.style.width = ui.pixpos(0); - div.appendChild(graph.svgtitles); - - return svg; -}; - -/** - * Point class. - */ -graph.Point = function(x, y) { - this.x = x; - this.y = y; -}; -graph.Point.prototype.xpos = function() { - return this.x; -}; -graph.Point.prototype.ypos = function() { - return this.y; -}; - -graph.mkpoint = function(x, y) { - return new graph.Point(x, y); -}; - -/** - * Path class. - */ -graph.Path = function() { - this.path = ''; - this.x = 0; - this.y = 0; -} -graph.Path.prototype.pos = function(x, y) { - this.x = x; - this.y = y; - return this; -}; -graph.Path.prototype.xpos = function() { - return this.x; -}; -graph.Path.prototype.ypos = function() { - return this.y; -}; -graph.Path.prototype.rmove = function(x, y) { - return this.move(this.x + x, this.y + y); -}; -graph.Path.prototype.rline = function(x, y) { - return this.line(this.x + x, this.y + y); -}; -graph.Path.prototype.rcurve = function(x1, y1, x, y) { - return this.curve(this.x + x1, this.y + y1, this.x + x1 + x, this.y + y1 + y); -}; -graph.Path.prototype.str = function() { - return this.path; -}; -graph.Path.prototype.clone = function() { - return graph.mkpath().pos(this.xpos(), this.ypos()); -}; -graph.Path.prototype.move = function(x, y) { - this.path += 'M' + x + ',' + y + ' '; - return this.pos(x, y); -}; -graph.Path.prototype.line = function(x, y) { - this.path += 'L' + x + ',' + y + ' '; - return this.pos(x, y); -}; -graph.Path.prototype.curve = function(x1, y1, x, y) { - this.path += 'Q' + x1 + ',' + y1 + ' ' + x + ',' + y + ' '; - return this.pos(x, y); -}; -graph.Path.prototype.end = function() { - this.path += 'Z'; - return this; -}; - -graph.mkpath = function() { - return new graph.Path(); -}; - -/** - * Return an element representing a title. - */ -graph.mktitle = function(t, x, y) { - var title = document.createElementNS(graph.svgns, 'text'); - title.setAttribute('x', x); - title.setAttribute('y', y); - title.setAttribute('class', 'svgtitle'); - title.setAttribute('pointer-events', 'none'); - title.appendChild(document.createTextNode(t)); - graph.svgtitles.appendChild(title); - return title; -}; - -/** - * Return an element representing the title of a component. - */ -graph.comptitle = function(comp) { - return memo(comp, 'title', function() { - var ct = graph.title(comp); - var pt = graph.propertytitle(comp); - if (ct == '' && pt == '') - return null; - return graph.mktitle((ct != '' && pt != '')? ct + ' ' + pt : ct + pt, titlex, titley); - }); -}; - -/** - * Return the width of the title of a component. - */ -graph.comptitlewidth = function(comp) { - var title = graph.comptitle(comp); - if (isNil(title)) - return 0; - return title.getBBox().width + titlew; -}; - -/** - * Draw a component shape selection. - */ -graph.compselect = function(g, s, cvalue, ccopy, cdelete) { - if (isNil(g) || !s) { - cvalue.value = ''; - cvalue.disabled = true; - ccopy.disabled = true; - cdelete.disabled = true; - if (isNil(g)) - return true; - g.shape.setAttribute('stroke', graph.colors.gray); - g.shape.setAttribute('stroke-width', '1'); - return true; - } - - cvalue.value = graph.hasproperty(g.comp)? graph.property(g.comp) : g.id; - cvalue.disabled = false; - ccopy.disabled = false; - cdelete.disabled = false; - - g.shape.setAttribute('stroke', graph.colors.link); - g.shape.setAttribute('stroke-width', '2'); - g.parentNode.appendChild(g); - return true; -}; - -/** - * Draw a palette shape selection. - */ -graph.paletteselect = function(g, s) { - if (isNil(g)) - return true; - if (!s) { - g.shape.setAttribute('stroke', graph.colors.gray); - g.shape.setAttribute('stroke-width', '1'); - return true; - } - - g.shape.setAttribute('stroke', graph.colors.link); - g.shape.setAttribute('stroke-width', '2'); - g.parentNode.appendChild(g); - return true; -}; - -/** - * Draw a component outline for faster rendering. - */ -graph.compoutline = function(g, s) { - if (s == (isNil(g.outlined)? false : g.outlined)) - return true; - g.outlined = s; - - if (s) { - g.shape.setAttribute('fill', 'none'); - if (!isNil(g.title)) - g.removeChild(g.title); - } else { - g.shape.setAttribute('fill', graph.color(g.comp)); - if (!isNil(g.title)) - g.appendChild(g.title); - } - - map(function(r) { - var n = caddr(r); - if (isNil(n)) - return r; - graph.compoutline(n, s); - return r; - }, g.refpos); - return true; -}; - -/** - * Return a node representing a component. - */ -graph.compnode = function(comp, cassoc, pos, parentg) { - - // Make the component title element - var title = graph.comptitle(comp); - - // Compute the path of the component shape - var path = graph.comppath(comp, cassoc); - - // Create the main component shape - var shape = document.createElementNS(graph.svgns, 'path'); - shape.setAttribute('d', path.str()); - shape.setAttribute('fill', graph.color(comp)); - //shape.setAttribute('fill-opacity', '0.6'); - shape.setAttribute('stroke', graph.colors.gray); - shape.setAttribute('stroke-width', '1'); - shape.setAttribute('pointer-events', 'visible'); - - // Create an svg group and add the shape and title to it - var g = document.createElementNS(graph.svgns, 'g'); - g.comp = comp; - g.id = scdl.name(comp); - g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')'); - g.pos = pos.clone(); - g.appendChild(shape); - g.shape = shape; - if (!isNil(title)) { - g.appendChild(title); - g.title = title; - } - - // Store the the positions of the services and references - g.refpos = reverse(path.refpos); - g.svcpos = reverse(path.svcpos); - - // Handle onclick events - g.onclick = parentg.onclick; - - return g; -}; - -/** - * Find the node representing a component. - */ -graph.findcompnode = function(name, nodes) { - if (isNil(nodes)) - return null; - if (isNil(car(nodes).comp)) - return graph.findcompnode(name, cdr(nodes)); - if (name == scdl.name(car(nodes).comp)) - return car(nodes); - var node = graph.findcompnode(name, nodeList(car(nodes).childNodes)); - if (!isNil(node)) - return node; - return graph.findcompnode(name, cdr(nodes)); -} - -/** - * Return a graphical group. - */ -graph.mkgroup = function(pos) { - var g = document.createElementNS(graph.svgns, 'g'); - g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')'); - g.pos = pos.clone(); - return g; -}; - -/** - * Return a node representing a button. - */ -graph.mkbutton = function(t, pos) { - - // Make the button title - var title = graph.mktitle(t, titlex, titley); - - // Compute the path of the button shape - var path = graph.buttonpath().str(); - - // Create the main button shape - var shape = document.createElementNS(graph.svgns, 'path'); - shape.setAttribute('d', path); - shape.setAttribute('fill', graph.colors.lightgray1); - //shape.setAttribute('fill-opacity', '0.6'); - shape.setAttribute('stroke', graph.colors.gray); - shape.setAttribute('stroke-width', '1'); - shape.setAttribute('pointer-events', 'visible'); - - // Create a group and add the button shape to it - var g = document.createElementNS(graph.svgns, 'g'); - g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')'); - g.pos = pos.clone(); - g.appendChild(shape); - g.appendChild(title); - - // Store the button shape in the group - g.shape = shape; - - return g; -}; - -/** - * Return the relative position of a node. - */ -graph.relpos = function(e) { - var pmatrix = e.parentNode != null? e.parentNode.getCTM() : null; - var matrix = e.getCTM(); - var curX = pmatrix != null? (Number(matrix.e) - Number(pmatrix.e)): Number(matrix.e); - var curY = pmatrix != null? (Number(matrix.f) - Number(pmatrix.f)): Number(matrix.f); - return graph.mkpath().pos(curX, curY); -}; - -/** - * Move a node. - */ -graph.move = function(e, pos) { - e.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')'); - e.pos = pos.clone(); -}; - -/** - * Return the absolute position of a component node. - */ -graph.abspos = function(e, g) { - if (e == g) - return graph.mkpath(); - var gpos = graph.relpos(e); - var pgpos = graph.abspos(e.parentNode, g); - return graph.mkpath().pos(gpos.xpos() + pgpos.xpos(), gpos.ypos() + pgpos.ypos()); -}; - -/** - * Bring a component node to the top. - */ -graph.bringtotop = function(n, g) { - if (n == g) - return null; - graph.move(n, graph.abspos(n, g)); - g.appendChild(n); -} - -/** - * Return the title of a SCDL element. - */ -graph.title = function(e) { - var t = scdl.title(e); - if (t != null) { - if (t == 'gt') - return '>' - if (t == 'lt') - return '<'; - if (t.indexOf('{propval}') != -1) - return ''; - if (t.indexOf('{compname}') == -1) - return t; - return t.replace('{compname}', scdl.name(e)); - } - return scdl.name(e); -}; - -/** - * Return the property value of a SCDL component. - */ -graph.property = function(e) { - var p = scdl.properties(e); - if (isNil(p)) - return ''; - if (scdl.visible(car(p)) == 'false') - return ''; - var pv = scdl.propertyValue(car(p)); - return pv; -}; - -/** - * Return the title of a property of a SCDL component. - */ -graph.propertytitle = function(e) { - var pv = graph.property(e); - var t = scdl.title(e); - if (t.indexOf('{propval}') == -1) - return pv; - return t[0] == ' '? t.substr(1).replace('{propval}', pv) : t.replace('{propval}', pv); -}; - -/** - * Return true if a SCDL component has a property. - */ -graph.hasproperty = function(e) { - var p = scdl.properties(e); - if (isNil(p)) - return false; - if (scdl.visible(car(p)) == 'false') - return false; - return true; -}; - -/** - * Change the property value of a SCDL component. - */ -graph.setproperty = function(e, value) { - var p = scdl.properties(e); - if (isNil(p)) - return ''; - if (scdl.visible(car(p)) == 'false') - return ''; - var name = scdl.name(car(p)); - setElement(car(p), mklist(element, "'property", mklist(attribute, "'name", name != null? name : "property"), value)); - return value; -}; - -/** - * Return the color of a SCDL component. - */ -graph.color = function(comp) { - return memo(comp, 'color', function() { - var c = scdl.color(comp); - return c == null? graph.colors.blue1 : graph.colors[c]; - }); -}; - -/** - * Return the services on the left side of a component. - */ -graph.lsvcs = function(comp) { - return memo(comp, 'lsvcs', function() { - var svcs = scdl.services(comp); - if (isNil(svcs)) - return mklist(mklist("'element","'service","'attribute","'name",scdl.name(comp))); - var l = filter(function(s) { - var a = scdl.align(s); - var v = scdl.visible(s); - return (a == null || a == 'left') && v != 'false'; - }, svcs); - if (isNil(l)) - return mklist(); - return mklist(car(l)); - }); -}; - -/** - * Return the references on the right side of a component. - */ -graph.rrefs = function(comp) { - return memo(comp, 'rrefs', function() { - return filter(function(r) { - var a = scdl.align(r); - var v = scdl.visible(r); - return (a == null || a == 'right') && v != 'false'; - }, scdl.references(comp)); - }); -}; - -/** - * Return the height of a reference on the right side of a component. - */ -graph.rrefheight = function(ref, cassoc) { - return memo(ref, 'rheight', function() { - var target = assoc(scdl.target(ref), cassoc); - if (isNil(target)) - return tabsz * 8; - return graph.compclosureheight(cadr(target), cassoc); - }); -}; - -/** - * Return the total height of the references on the right side of a component. - */ -graph.rrefsheight = function(refs, cassoc) { - if (isNil(refs)) - return 0; - return graph.rrefheight(car(refs), cassoc) + graph.rrefsheight(cdr(refs), cassoc); -}; - -/** - * Return the height of a component node. - */ -graph.compheight = function(comp, cassoc) { - return memo(comp, 'height', function() { - var lsvcs = graph.lsvcs(comp); - var lsvcsh = Math.max(1, length(lsvcs)) * (tabsz * 8) + (tabsz * 4); - var rrefs = graph.rrefs(comp); - var rrefsh = graph.rrefsheight(rrefs, cassoc) + (tabsz * 2); - return Math.max(lsvcsh, rrefsh); - }); -}; - -/** - * Return the height of a component and the components wired to its bottom side. - */ -graph.compclosureheight = function(comp, cassoc) { - return memo(comp, 'closureheight', function() { - return graph.compheight(comp, cassoc); - }); -}; - -/** - * Return the max width of the references on the right side of a component. - */ -graph.rrefswidth = function(refs, cassoc) { - if (isNil(refs)) - return 0; - return Math.max(graph.rrefwidth(car(refs), cassoc), graph.rrefswidth(cdr(refs), cassoc)); -}; - -/** - * Return the width of a component. - */ -graph.compwidth = function(comp, cassoc) { - return memo(comp, 'width', function() { - var ctw = graph.comptitlewidth(comp); - var rrefsw = (isNil(graph.rrefs(comp))? 0 : (tabsz * 4)); - var twidth = (titlex * 2) + ctw + rrefsw; - var width = Math.max(twidth, (tabsz * 8) + (tabsz * 4)); - return width; - }); -}; - -/** - * Return a path representing a reference positioned to the right of a component. - */ -graph.rrefpath = function(ref, cassoc, path, maxheight) { - var height = graph.rrefheight(ref, cassoc); - - // Record reference position in the path - var xpos = path.xpos(); - var ypos = path.ypos(); - path.refpos = cons(mklist(ref, graph.mkpath().pos(xpos, ypos + (tabsz * 5))), path.refpos); - - // Compute the reference path - return path.rline(0,tabsz * 2).rcurve(0,tabsz,-tabsz,0).rcurve(-tabsz,0,0,-tabsz/2.0).rcurve(0,-tabsz/2.0,-tabsz,0).rcurve(-tabsz,0,0,tabsz/2.0).rline(0,tabsz * 3).rcurve(0,tabsz/2.0,tabsz,0).rcurve(tabsz,0,0,-tabsz/2.0).rcurve(0,-tabsz/2.0,tabsz,0).rcurve(tabsz,0,0,tabsz).line(path.xpos(), Math.min(ypos + height, maxheight)); -}; - -/** - * Return a path representing a service positioned to the left of a component. - */ -graph.lsvcpath = function(svc, cassoc, path, minheight) { - var height = tabsz * 8; - - // Record service position in the path - var xpos = path.xpos(); - var ypos = path.ypos(); - path.svcpos = cons(mklist(svc, graph.mkpath().pos(xpos, ypos - (tabsz * 6))), path.svcpos); - - // Compute the service path - return path.rline(0, -(tabsz * 2)).rcurve(0,-tabsz,-tabsz,0).rcurve(-tabsz,0,0,tabsz/2.0).rcurve(0,tabsz/2.0,-tabsz,0).rcurve(-tabsz,0,0,-tabsz/2.0).rline(0,-(tabsz * 3)).rcurve(0,-tabsz/2.0,tabsz,0).rcurve(tabsz,0,0,tabsz/2.0).rcurve(0,tabsz/2.0,tabsz,0).rcurve(tabsz,0,0,-tabsz).line(path.xpos(), Math.max(ypos - height, minheight)); -}; - -/** - * Return a path representing a component node. - */ -graph.comppath = function(comp, cassoc) { - - // Calculate the width and height of the component node - var width = graph.compwidth(comp, cassoc); - var height = graph.compheight(comp, cassoc); - - /** - * Apply a path rendering function to a list of services or references. - */ - function renderpath(x, f, cassoc, path, height) { - if (isNil(x)) - return path; - return renderpath(cdr(x), f, cassoc, f(car(x), cassoc, path, height), height); - } - - var path = graph.mkpath().move(curvsz,0); - - // Store the positions of services and references in the path - path.refpos = mklist(); - path.svcpos = mklist(); - - // Render the references on the right side of the component - var rrefs = graph.rrefs(comp); - path = path.line(width - curvsz,path.ypos()).rcurve(curvsz,0,0,curvsz); - path = renderpath(rrefs, graph.rrefpath, cassoc, path, height - curvsz); - - // Render the references on the bottom side of the component - var boffset = curvsz; - path = path.line(path.xpos(),height - curvsz).rcurve(0,curvsz,curvsz * -1,0).line(boffset, path.ypos()); - - // Render the services on the left side of the component - var lsvcs = graph.lsvcs(comp); - var loffset = curvsz + (length(lsvcs) * (tabsz * 8)); - path = path.line(curvsz,path.ypos()).rcurve(curvsz * -1,0,0,curvsz * -1).line(path.xpos(), loffset); - path = renderpath(lsvcs, graph.lsvcpath, cassoc, path, curvsz); - - // Close the component node path - path = path.line(0,curvsz).rcurve(0,curvsz * -1,curvsz,0); - - return path.end(); -}; - -/** - * Return the position of a component. - */ -graph.comppos = function(comp, pos) { - var x = scdl.x(comp); - var y = scdl.y(comp); - return graph.mkpath().pos(x != null? Number(x) + palcx : pos.xpos(), y != null? Number(y) : pos.ypos()); -}; - -/** - * Return a path representing a button node. - */ -graph.buttonpath = function(t) { - var path = graph.mkpath().move(curvsz,0); - path = path.line(buttoncx - curvsz,path.ypos()).rcurve(curvsz,0,0,curvsz); - path = path.line(path.xpos(),buttoncy - curvsz).rcurve(0,curvsz,-curvsz,0).line(curvsz, path.ypos()); - path = path.line(curvsz,path.ypos()).rcurve(-curvsz,0,0,-curvsz).line(path.xpos(), curvsz); - path = path.line(0,curvsz).rcurve(0,-curvsz,curvsz,0); - return path.end(); -}; - -/** - * Render a SCDL composite into a list of component nodes. - */ -graph.composite = function(compos, pos, aspalette, g) { - var name = scdl.name(scdl.composite(compos)); - var comps = scdl.components(compos); - var cassoc = scdl.nameToElementAssoc(comps); - var proms = scdl.promotions(compos); - - // Unmemoize any memoized info about components and their references. - map(function(c) { - unmemo(c); - map(function(r) { - unmemo(r); - }, scdl.references(c)); - }, comps); - - /** - * Render a component. - */ - function rendercomp(comp, cassoc, pos) { - - /** - * Render the references on the right side of a component. - */ - function renderrrefs(refs, cassoc, pos, gcomp) { - - /** - * Render a reference on the right side of a component. - */ - function renderrref(ref, cassoc, pos, gcomp) { - var target = assoc(scdl.target(ref), cassoc); - if (isNil(target)) - return null; - - // Render the component target of the reference - return rendercomp(cadr(target), cassoc, pos); - } - - /** - * Move the rendering cursor down below a reference. - */ - function rendermove(ref, cassoc, pos) { - return pos.clone().rmove(0, graph.rrefheight(ref, cassoc)); - } - - if (isNil(refs)) - return mklist(); - - // Return list of (ref, comp rendering) pairs - var grefcomp = renderrref(car(refs), cassoc, pos, gcomp); - return cons(mklist(car(refs), grefcomp), renderrrefs(cdr(refs), cassoc, rendermove(car(refs), cassoc, pos), gcomp)); - } - - // Compute the component shape - var gcomp = graph.compnode(comp, cassoc, pos, g); - - // Render the components wired to the component references - var rrefs = graph.rrefs(comp); - var rpos = graph.mkpath().rmove(graph.compwidth(comp, cassoc), 0); - var grrefs = renderrrefs(rrefs, cassoc, rpos, gcomp); - - // Store list of (ref, pos, component rendering) triplets in the component - function refposgcomp(refpos, grefs) { - if (isNil(refpos)) - return mklist(); - - // Append component rendering to component - var gref = cadr(car(grefs)); - if (gref != null) - gcomp.appendChild(gref); - return cons(mklist(car(car(refpos)), cadr(car(refpos)), gref), refposgcomp(cdr(refpos), cdr(grefs))); - } - - gcomp.refpos = refposgcomp(gcomp.refpos, grrefs); - - return gcomp; - } - - /** - * Render a list of promoted service components. - */ - function renderproms(svcs, cassoc, pos) { - - /** - * Return the component promoted by a service. - */ - function promcomp(svc, cassoc) { - var c = assoc(scdl.promote(svc), cassoc); - if (isNil(c)) - return mklist(); - return cadr(c); - } - - /** - * Move the rendering cursor down below a component. - */ - function rendermove(comp, cassoc, pos) { - return pos.clone().rmove(0, graph.compclosureheight(comp, cassoc) + Math.max((tabsz * 2), 8)); - } - - if (isNil(svcs)) - return mklist(); - - // Render the first promoted component in the list - // then recurse to render the rest of the list - var comp = promcomp(car(svcs), cassoc); - if (isNil(comp)) - return renderproms(cdr(svcs), cassoc, rendermove(car(svcs), cassoc, pos)); - - var cpos = graph.comppos(comp, pos); - return cons(rendercomp(comp, cassoc, cpos), renderproms(cdr(svcs), cassoc, rendermove(comp, cassoc, cpos))); - } - - // Render the promoted service components - var rproms = renderproms(proms, cassoc, pos.clone().rmove(tabsz * 4, tabsz * 4)); - - if (aspalette) { - - // Prefix ids of palette component elements with 'palette:' and - // move them to the palette area - return map(function(r) { - r.id = 'palette:' + r.id; - var gpos = r.pos; - graph.move(r, graph.mkpath().pos(gpos.xpos() - palcx, gpos.ypos())); - return r; - }, rproms); - - } else { - - // Link app component elements to the containing composite - return map(function(r) { r.compos = compos; return r; }, rproms); - } -}; - -/** - * Return a component unique id. - */ -graph.ucid = function(prefix, compos1, compos2, clone) { - - // Build an assoc list keyed by component name - var comps = map(function(c) { return mklist(scdl.name(c), c); }, append(namedElementChildren("'component", compos1), namedElementChildren("'component", compos2))); - - if (!clone && isNil(assoc(prefix, comps))) - return prefix; - - /** - * Find a free component id. - */ - function ucid(p, id) { - if (isNil(assoc(p + id, comps))) - return p + id; - return ucid(p, id + 1); - } - - /** - * Remove trailing digits from a prefix. - */ - function untrail(p) { - if (p.length < 2 || p[p.length - 1] < '0' || p[p.length - 1] > '9') - return p; - return untrail(p.substring(0, p.length - 1)); - } - - return ucid(prefix == ''? 'comp' : (clone? untrail(prefix) : prefix), 1); -}; - -/** - * Clone a palette component node. - */ -graph.clonepalette = function(e, compos, g) { - - // Clone the SCDL component and give it a unique name - var wcomp = append(mklist(element, "'component", mklist(attribute, "'name", graph.ucid(scdl.name(e.comp), compos, compos, true))), - filter(function(c) { return !(isAttribute(c) && attributeName(c) == "'name")}, elementChildren(e.comp))); - var x = '<composite>' + writeXML(mklist(wcomp), false) + '</composite>'; - var rcompos = scdl.composite(readXML(mklist(x))); - var comp = car(scdl.components(mklist(rcompos))); - - // Update component position - setElement(comp, graph.movecomp(comp, graph.abspos(e, g).rmove(palcx, 0))); - - return comp; -}; - -/** - * Move a SCDL component to the given position. - */ -graph.movecomp = function(comp, pos) { - if (isNil(pos)) - return append(mklist(element, "'component"), - filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'x" || attributeName(e) == "'y")); }, elementChildren(comp))); - return append(mklist(element, "'component", mklist(attribute, "'x", '' + (pos.xpos() - palcx)), mklist(attribute, "'y", '' + pos.ypos())), - filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'x" || attributeName(e) == "'y")); }, elementChildren(comp))); -}; - -/** - * Align a pos along a 10pixel grid. - */ -graph.gridsnap = function(x) { - return Math.round(x / 10) * 10; -} - -/** - * Clone a component node and all the components it references. - */ -graph.clonecomp = function(e, compos, g) { - - // Write the component and the components it references to XML - function collectcomp(e) { - function collectrefs(refpos) { - if (isNil(refpos)) - return mklist(); - var r = car(refpos); - var n = caddr(r); - if (isNil(n)) - return collectrefs(cdr(refpos)); - return append(collectcomp(n), collectrefs(cdr(refpos))); - } - - return cons(e.comp, collectrefs(e.refpos)); - } - - var allcomps = collectcomp(e); - var ls = map(function(e) { return writeXML(mklist(e), false); }, allcomps); - var x = '<composite>' + writeStrings(ls) + '</composite>'; - - // Read them back from XML to clone them - var rcompos = scdl.composite(readXML(mklist(x))); - var comps = scdl.components(mklist(rcompos)); - - // Give them new unique names - map(function(e) { - - // Rename each component - var oname = scdl.name(e); - var name = graph.ucid(oname, compos, rcompos, true); - setElement(e, append(mklist(element, "'component", mklist(attribute, "'name", name)), - filter(function(c) { return !(isAttribute(c) && attributeName(c) == "'name")}, elementChildren(e)))); - - // Refactor references to the component - map(function(c) { return graph.refactorrefs(scdl.references(c), oname, name); }, comps); - }, comps); - - // Update the top component position - var comp = car(comps); - setElement(comp, graph.movecomp(comp, graph.abspos(e, g).rmove(10, 10))); - - return comps; -}; - -/** - * Sort elements of a composite. - */ -graph.sortcompos = function(compos) { - return append(mklist(element, "'composite"), elementChildren(compos).sort(function(a, b) { - - // Sort attributes, place them at the top - var aa = isAttribute(a); - var ba = isAttribute(b); - if (aa && !ba) return -1; - if (!aa && ba) return 1; - if (aa && ba) { - var aan = attributeName(a); - var ban = attributeName(b); - if (aan < ban) return -1; - if (aan > ban) return 1; - return 0; - } - - // Sort elements, place services before components - var aen = elementName(a); - var ben = elementName(b); - if (aen == "'service" && ben == "'component") return -1; - if (aen == "'component" && ben == "'service") return 1; - var an = scdl.name(a); - var bn = scdl.name(b); - if (an < bn) return -1; - if (an > bn) return 1; - return 0; - })); -} - -/** - * Add a list of components to a SCDL composite. The first - * component in the list is a promoted component. - */ -graph.addcomps = function(comps, compos) { - var comp = car(comps); - var name = scdl.name(comp); - var prom = mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name)); - return append(mklist(element, "'composite"), append(elementChildren(compos), cons(prom, comps))); -}; - -/** - * Remove a component from a SCDL composite. - */ -graph.removecomp = function(comp, compos) { - var name = scdl.name(comp); - return append(mklist(element, "'composite"), - filter(function(c) { return !(isElement(c) && scdl.name(c) == name); }, elementChildren(compos))); -}; - -/** - * Garbage collect components not referenced or promoted. - */ -graph.gcollect = function(compos) { - - // List the promoted components - var proms = map(function(s) { return mklist(scdl.promote(s), true); }, scdl.promotions(mklist(compos))); - - // List the referenced components - var refs = reduce(function(a, comp) { - return append(a, - map(function(ref) { return mklist(scdl.target(ref), true); }, filter(function(ref) { return scdl.target(ref) != null; }, scdl.references(comp)))); - }, mklist(), scdl.components(mklist(compos))); - - // Filter out the unused components - var used = append(proms, refs); - return append(mklist(element, "'composite"), - filter(function(c) { return !(isElement(c) && elementName(c) == "'component" && isNil(assoc(scdl.name(c), used))); }, elementChildren(compos))); -} - -/** - * Clone and cleanup clonable references. - */ -graph.clonerefs = function(compos) { - return append(mklist(element, "'composite"), - map(function(c) { - if (elementName(c) != "'component") - return c; - - // If the references are clonable - var refs = scdl.references(c); - if (isNil(refs)) - return c; - if (scdl.clonable(car(refs)) != 'true') - return c; - - // Filter out the unwired references and add a fresh unwired - // reference at the end of the list - var cc = append( - filter(function(e) { return !(elementName(e) == "'reference" && scdl.target(e) == null); }, elementChildren(c)), - mklist(mklist(element, "'reference", mklist(attribute, "'name", scdl.name(car(refs))), mklist(attribute, "'clonable", "true")))); - return append(mklist(element, "'component"), cc); - - }, elementChildren(compos))); -} - -/** - * Refactor references to a component. - */ -graph.refactorrefs = function(refs, oname, nname) { - if (isNil(refs)) - return true; - var ref = car(refs); - if (scdl.target(ref) != oname) - return graph.refactorrefs(cdr(refs), oname, nname); - - // Change the reference's target attribute - setElement(ref, append(mklist(element, "'reference"), - append(filter(function(e) { return !(isAttribute(e) && attributeName(e) == "'target"); }, elementChildren(ref)), - mklist(mklist(attribute, "'target", nname))))); - - return graph.refactorrefs(cdr(refs), oname, nname); -}; - -/** - * Rename a component. - */ -graph.renamecomp = function(comp, compos, name) { - - // Refactor all the references to the renamed component - var oname = scdl.name(comp); - map(function(c) { return graph.refactorrefs(scdl.references(c), oname, name); }, namedElementChildren("'component", compos)); - - // Rename the SCDL promoted service and component - var proms = filter(function(s) { return scdl.name(s) == oname }, scdl.services(compos)); - if (!isNil(proms)) - setElement(car(proms), mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name))); - setElement(comp, append(mklist(element, "'component"), - cons(mklist(attribute, "'name", name), - filter(function(e) { return !(isAttribute(e) && attributeName(e) == "'name"); }, elementChildren(comp))))); - - return append(mklist(element, "'composite"), elementChildren(compos)); -}; - -/** - * Cut the wire to a component node and make that node a - * top level component node. - */ -graph.cutwire = function(node, compos, g) { - - /** - * Find the reference wired to a node and cut its wire. - */ - function cutref(refs, node) { - if (isNil(refs)) - return true; - var ref = car(refs); - if (caddr(ref) == node) { - setlist(ref, mklist(car(ref), cadr(ref), null)); - setElement(car(ref), - append(mklist(element, "'reference"), - filter(function(e) { return !(isAttribute(e) && attributeName(e) == "'target"); }, elementChildren(car(ref))))); - } - return cutref(cdr(refs), node); - } - - // Cut any reference wire, if found - cutref(node.parentNode.refpos, node); - - // Make the component node a top level node. - node.compos = g.compos; - - // Update the SCDL composite, add a promote element for - // that component - var comp = node.comp; - var name = scdl.name(comp); - var prom = mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name)); - return append(mklist(element, "'composite"), - append(mklist(prom), filter(function(c) { return !(isElement(c) && elementName(c) == "'service" && scdl.name(c) == name); }, elementChildren(compos)))); -} - -/** - * Wire a component to the closest neighbor reference. - */ -graph.wire = function(n, compos, g) { - - // Compute position of the component's service node - var spos = cadr(car(n.svcpos)); - var aspos = graph.abspos(n, g).rmove(spos.xpos(), spos.ypos()); - - /** - * Find closest unwired reference node among all the references - * of all the components. - */ - function closecomprefs(nodes, spos, cref) { - - /** - * Find the closest unwired reference node among all the - * references of a node. - */ - function closerefs(npos, refs, spos, cref) { - if (isNil(refs)) - return cref; - var fdist = cadddr(cref); - var ref = car(refs); - - // Skip wired reference - if (!isNil(filter(function(n) { return isAttribute(n) && attributeName(n) == "'target"; }, car(ref)))) - return closerefs(npos, cdr(refs), spos, cref); - - // Compute distance between service node and reference node - var rpos = cadr(ref).clone().rmove(npos.xpos(), npos.ypos()); - var dx = Math.pow(rpos.xpos() - spos.xpos(), 2); - var dy = Math.pow(rpos.ypos() - spos.ypos(), 2); - - // Check for proximity threshold - var rdist = (dx < (proxcx * proxcx) && dy < (proxcy * proxcy))? Math.sqrt(dx + dy) : 25000000; - - // Go through all the references in the component - return closerefs(npos, cdr(refs), spos, fdist < rdist? cref : mklist(car(ref), cadr(ref), caddr(ref), rdist)); - } - - if (isNil(nodes)) - return cref; - - // Skip non-component nodes - var node = car(nodes); - if (isNil(node.comp)) - return closecomprefs(cdr(nodes), spos, cref); - - // Compute the component absolute position - var npos = graph.abspos(node, g); - - // Go through all the components and their references - return closecomprefs(append(nodeList(node.childNodes), cdr(nodes)), spos, closerefs(npos, node.refpos, spos, cref)); - } - - // Find closest reference node - var cref = closecomprefs(nodeList(g.childNodes), aspos, mklist(null, graph.mkpath(), null, 25000000)); - if (car(cref) == null) - return compos; - if (cadddr(cref) == 25000000) - return compos; - - // Wire component to that reference, un-promote it, and - // update the SCDL reference and composite - setElement(n.comp, graph.movecomp(graph.dragging.comp, null)); - n.compos = null; - setElement(car(cref), append(mklist(element, "'reference", mklist(attribute, "'target", scdl.name(n.comp))), elementChildren(car(cref)))); - var name = scdl.name(n.comp); - return append(mklist(element, "'composite"), - filter(function(c) { return !(isElement(c) && elementName(c) == "'service" && scdl.name(c) == name); }, elementChildren(compos))); -} - -/** - * Display a list of graphical nodes. - */ -graph.display = function(nodes, g, svg) { - var suspend = svg.suspendRedraw(10); - - // Append the nodes to the graphical canvas - appendNodes(nodes, g); - - svg.unsuspendRedraw(suspend); - return nodes; -}; - -/** - * Hide a graph. - */ -graph.hide = function(g) { - - // Remove nodes from the graph - map(function(n) { if (!isNil(n.comp) && n.id.substr(0, 8) != 'palette:') { g.removeChild(n); } return n; }, nodeList(g.childNodes)); - return g; -}; - -/** - * Refresh a graph. - */ -graph.refresh = function(g) { - //log('refresh'); - - // Remove existing nodes from the graph - map(function(n) { if (!isNil(n.comp) && n.id.substr(0, 8) != 'palette:') { g.removeChild(n); } return n; }, nodeList(g.childNodes)); - - // Redisplay the composite associated with the graph - var nodes = graph.composite(g.compos, graph.mkpath().pos(palcx,0), false, g); - appendNodes(nodes, g); - return nodes; -}; - -/** - * Display and enable editing of a composite and the graphical - * nodes that represent it. - */ -graph.edit = function(appname, compos, nodes, onchange, onselect, g) { - var suspend = g.suspendRedraw(10); - - // Store the appname and composite in the graphical canvas - g.appname = appname; - g.compos = compos; - - // Sort the composite elements now to allow for change detection later - var scompos = scdl.composite(g.compos); - setElement(scompos, graph.sortcompos(scompos)); - - // Store event listeners - g.oncomposchange = onchange; - g.oncompselect = onselect; - - // Remove existing nodes from the graph - map(function(n) { if (!isNil(n.comp) && n.id.substr(0, 8) != 'palette:') { g.removeChild(n); } return n; }, nodeList(g.childNodes)); - - // Display the composite nodes - appendNodes(nodes, g); - - g.unsuspendRedraw(suspend); - return nodes; -}; - diff --git a/sca-cpp/trunk/modules/edit/htdocs/graph/index.html b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html index 6e93548814..730506c9a1 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/graph/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html @@ -17,33 +17,8 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> -<head> -<title></title> -<meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -<script type="text/javascript" src="graph.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> <div id="bodydiv" class="bodydiv" style="overflow: visible;"> -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menubackground" style="position: absolute; top: 0px; left: 0px; z-index: -1; width: 2500px;"> -<table cellpadding="0" cellspacing="0" width="100%" class="tbar"><tr><td class="dtbar"> -<table border="0" cellspacing="0" cellpadding="0"><tr><td class="ltbar"><span class="tbarsmenu">> </span></td></tr></table> -</td></tr></table> -</div> - -<div id="menu"></div> - <table style="width: 100%;"> <tr> <td><h2><span id="appNameHeader"></span></h2></td> @@ -59,10 +34,6 @@ <table id="compValueTable" style="width: 100%;"> <tr> -<td class="thr thl" style="padding-left: 2px; padding-right: 2px; vertical-align: top; width: 100%"> -<input id="compValue" type="text" value="" title="Component value" autocapitalize="off" placeholder="Value" style="position: relative; width: 100%;"/> -</td> - <td class="thl thr" style="text-align: right; padding-right: 2px; vertical-align: top;"> <span id="deleteCompButton" title="Delete a component" class="graybutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; text-align: center; margin-left: 0px; margin-right: 0px;">-</span> @@ -72,36 +43,38 @@ <span id="playCompButton" title="View component value" class="graybutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; text-align: center; margin-left: 0px; margin-right: 0px;">></span> </td> + +<td class="thl thr" style="padding-left: 2px; padding-right: 2px; vertical-align: top; width: 100%"> +<input id="compValue" type="text" value="" title="Component value" autocapitalize="off" placeholder="Value" style="position: relative; visibility: hidden; width: 100%;"/> +</td> </tr> </table> <div id="contentdiv" style="margin-top: 4px; width: 2500px;"> -<div id="playdiv" style="position:relative; top: 0x; left: 0px; right: 0px; width: 2500px; height: 5000px; visibility: hidden"> +<div id="playdiv" style="position: relative; top: 0x; left: 0px; right: 0px; width: 2500px; height: 5000px; visibility: hidden"> </div> </div> <script type="text/javascript"> -ui.initbody(); // Get the app name -var appname = ui.fragmentParams()['app']; +var appname = ui.fragmentParams(location)['app']; var ispalette = false; if (isNil(appname)) { appname = ui.fragmentParams()['palette']; - if (isNil(appname)) - window.open('/', '_self'); // Edit a palette instead of a regular app - ispalette = true; + if (!isNil(appname)) + ispalette = true; } /** * Return the link to an app. */ function applink(appname) { - var protocol = window.location.protocol; - var host = window.location.hostname; - var port = ':' + window.location.port; + var protocol = location.protocol; + var host = location.hostname; + var port = ':' + location.port; if (port == ':80' || port == ':443' || port == ':') port = ''; var link = protocol + '//' + appname + '.' + host + port + '/'; @@ -109,12 +82,9 @@ function applink(appname) { } // Set page titles -document.title = windowtitle(window.location.hostname) + ' - ' + (isNil(config.compose)? 'Composition' : config.compose) + ' - ' + appname; +document.title = ui.windowtitle(location.hostname) + ' - ' + (isNil(config.compose)? 'Composition' : config.compose) + ' - ' + appname; $('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>'; -// Load the menu bar -displaymenu(); - /** * Component value field, add, delete and play buttons. */ @@ -125,10 +95,6 @@ var ccopy = $('copyCompButton'); var cplay = $('playCompButton'); // Position background divs -var mbackground = $('menubackground'); -var menudiv = $('menu'); -mbackground.style.top = ui.pixpos(menudiv.offsetTop); - var cvbackground = $('compValueBackground'); var cvtable = $('compValueTable'); cvbackground.style.top = ui.pixpos(cvtable.offsetTop); @@ -154,6 +120,1764 @@ var composites = sca.reference(editWidget, ispalette? "palettes" : "composites") //rconsole = sca.defun(sca.reference(editWidget, "log"), "log"); /** + * SVG composite rendering functions. + */ +var graph = {}; + +/** + * Basic colors + */ +graph.colors = {}; +graph.colors.black = '#000000'; +graph.colors.blue = '#0000ff'; +graph.colors.cyan = '#00ffff'; +graph.colors.gray = '#808080' +graph.colors.lightgray = '#dcdcdc' +graph.colors.green = '#00ff00'; +graph.colors.magenta = '#ff00ff'; +graph.colors.orange = '#ffa500'; +graph.colors.pink = '#ffc0cb'; +graph.colors.purple = '#800080'; +graph.colors.red = '#ff0000'; +graph.colors.white = '#ffffff'; +graph.colors.yellow = '#ffff00'; +graph.colors.link = '#598edd'; + +graph.colors.orange1 = '#ffd666'; +graph.colors.green1 = '#bbe082'; +graph.colors.blue1 = '#66dbdf'; +graph.colors.yellow1 = '#fdf57a'; +graph.colors.cyan1 = '#e6eafb'; +graph.colors.lightgray1 = '#eaeaea' +graph.colors.pink1 = '#ffd9e0'; +graph.colors.red1 = '#d03f41'; +graph.colors.white1 = '#ffffff'; + +graph.colors.orange2 = '#ffbb00'; +graph.colors.green2 = '#96d333'; +//graph.colors.blue2 = '#0d7cc1'; +graph.colors.blue2 = '#00c3c9'; +graph.colors.red2 = '#d03f41'; +graph.colors.yellow2 = '#fcee21'; +graph.colors.magenta2 = '#c0688a'; +graph.colors.cyan2 = '#d5dcf9'; +graph.colors.lightgray2 = '#dcdcdc' +graph.colors.pink2 = '#ffc0cb'; +graph.colors.white2 = '#ffffff'; + +graph.colors.orange3 = '#ffc700'; +graph.colors.green3 = '#92e120'; +graph.colors.blue3 = '#008fd1'; +graph.colors.yellow3 = '#fdf400'; +graph.colors.cyan3 = '#b4d3fd'; +graph.colors.lightgray3 = '#e3e3e3' +graph.colors.pink3 = '#da749b'; +graph.colors.red3 = '#ed3f48'; +graph.colors.white3 = '#ffffff'; + +/** + * Default positions and sizes. + */ +graph.palcx = 2500; +graph.proxcx = 20; +graph.proxcy = 20; +graph.buttoncx = 55; +graph.buttoncy = 23; +graph.curvsz = 4; +graph.tabsz = 2; +graph.titlex = 4; +graph.titley = 11; +graph.titlew = ui.isMobile()? -2 : 0; + +/** + * SVG rendering functions. + */ + +graph.svgns='http://www.w3.org/2000/svg'; + +/** + * Make an SVG graph. + */ +graph.mkgraph = function(cdiv, pos, cvalue, cadd, ccopy, cdelete) { + + // Create a div element to host the graph + var div = document.createElement('div'); + div.id = 'svgdiv'; + div.style.position = 'absolute'; + div.style.left = ui.pixpos(pos.xpos() + cdiv.offsetLeft); + div.style.top = ui.pixpos(pos.ypos() + cdiv.offsetTop); + cdiv.appendChild(div); + + // Create SVG element + var svg = document.createElementNS(graph.svgns, 'svg'); + svg.style.height = ui.pixpos(5000); + svg.style.width = ui.pixpos(5000); + div.appendChild(svg); + + // Track element dragging and selection + graph.dragging = null; + graph.dragged = false; + graph.moverenderer = null; + graph.selected = null; + cvalue.disabled = true; + cvalue.style.visibility = 'hidden'; + ccopy.disabled = true; + cdelete.disabled = true; + + /** + * Find the first draggable element in a hierarchy of elements. + */ + function draggable(n) { + if (n == div || n == svg || n == null) + return null; + if (n.nodeName == 'g' && !isNil(n.id) && n.id != '') + return n; + return draggable(n.parentNode); + } + + /** + * Handle a mouse down or touch start event. + */ + function onmousedown(e) { + + // Remember mouse or touch position + var pos = typeof e.touches != "undefined" ? e.touches[0] : e; + graph.downX = pos.screenX; + graph.downY = pos.screenY; + graph.moveX = pos.screenX; + graph.moveY = pos.screenY; + + // Engage the click component selection right away + // on mouse controlled devices + if (typeof e.touches == 'undefined') + onclick(e); + + // Find and remember draggable component + var dragging = draggable(e.target); + if (dragging == null || dragging != graph.selected) + return true; + graph.dragging = dragging; + graph.dragged = false; + + // Remember current drag position + graph.dragX = pos.screenX; + graph.dragY = pos.screenY; + + e.preventDefault(); + return true; + }; + + if (!ui.isMobile()) { + div.onmousedown = function(e) { + //log('onmousedown'); + var suspend = svg.suspendRedraw(10); + var r = onmousedown(e); + svg.unsuspendRedraw(suspend); + return r; + } + } else { + div.ontouchstart = function(e) { + //log('ontouchstart'); + + // Clear current move renderer if it's running + if (!isNil(graph.moverenderer)) { + clearInterval(graph.moverenderer); + graph.moverenderer = null; + } + + var suspend = svg.suspendRedraw(10); + var r = onmousedown(e); + svg.unsuspendRedraw(suspend); + return r; + } + } + + /** + * Handle a mouse up or touch end event. + */ + function onmouseup(e) { + + // Engage the click component selection now on touch devices + if (ui.isMobile()) { + if (!graph.dragged && graph.moveX == graph.downX && graph.moveY == graph.downY) + return onclick(e); + } + + // Stop here if the component was not dragged + if (graph.dragging == null) + return true; + if (!graph.dragged) { + graph.dragging = null; + return true; + } + + if (graph.dragging.parentNode == svg && graph.dragging.id.substring(0, 8) != 'palette:') { + + // Add new dragged component to the composite + if (isNil(graph.dragging.compos)) { + var compos = scdl.composite(svg.compos); + setElement(compos, graph.sortcompos(graph.addcomps(mklist(graph.dragging.comp), compos))); + graph.dragging.compos = svg.compos; + } + + // Update component position + setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.abspos(graph.dragging, svg))); + + // Wire component to neighboring reference + if (!isNil(graph.dragging.svcpos)) { + var compos = scdl.composite(svg.compos); + setElement(compos, graph.sortcompos(graph.clonerefs(graph.wire(graph.dragging, compos, svg)))); + } + + // Snap top level component position to grid + if (graph.dragging.parentNode == svg) { + var gpos = graph.relpos(graph.dragging); + setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.mkpath().pos(graph.gridsnap(gpos.xpos()), graph.gridsnap(gpos.ypos())))); + } + } + + // Forget current dragged component + graph.dragging = null; + graph.dragged = false; + + // Refresh the composite + //log('onmouseup refresh'); + var nodes = graph.refresh(svg); + + // Reselected the previously selected component + if (!isNil(graph.selected)) { + graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes); + graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); + + // Trigger component select event + svg.oncompselect(graph.selected); + } + + // Trigger composite change event + svg.oncomposchange(false); + return true; + }; + + if (!ui.isMobile()) { + div.onmouseup = function(e) { + //log('onmouseup'); + var suspend = svg.suspendRedraw(10); + var r = onmouseup(e); + svg.unsuspendRedraw(suspend); + return r; + } + } else { + div.ontouchend = function(e) { + //log('ontouchend'); + + // Clear current move renderer if it's running + if (!isNil(graph.moverenderer)) { + clearInterval(graph.moverenderer); + graph.moverenderer = null; + } + + var suspend = svg.suspendRedraw(10); + var r = onmouseup(e); + svg.unsuspendRedraw(suspend); + return r; + } + } + + /** + * Handle a mouse or touch click event. + */ + function onclick(e) { + //log('onclick logic'); + + // Find selected component + var selected = draggable(e.target); + if (selected == null) { + if (graph.selected != null) { + + // Reset current selection + graph.compselect(graph.selected, false, cvalue, ccopy, cdelete); + graph.selected = null; + + // Trigger component select event + svg.oncompselect(null); + } + + // Dismiss the palette + if (e.target == div || e.target == svg && ui.numpos(div.style.left) != (graph.palcx * -1)) + div.style.left = ui.pixpos(graph.palcx * -1); + + return true; + } + + // Ignore multiple click events + if (selected == graph.selected) + return true; + if (selected.id.substring(0, 8) == 'palette:' && ui.numpos(div.style.left) != 0) + return true; + + // Deselect previously selected component + graph.compselect(graph.selected, false, cvalue, ccopy, cdelete); + + // Clone component from the palette + if (selected.id.substring(0, 8) == 'palette:') { + var compos = scdl.composite(svg.compos); + var comp = graph.clonepalette(selected, compos, svg); + setElement(compos, graph.sortcompos(graph.addcomps(mklist(comp), compos))); + + // Move into the editing area and hide the palette + div.style.left = ui.pixpos(graph.palcx * -1); + + // Refresh the composite + //log('onclick refresh'); + var nodes = graph.refresh(svg); + + // Reselect the previously selected component + graph.selected = graph.findcompnode(scdl.name(comp), nodes); + graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); + + // Trigger component select event + svg.oncompselect(graph.selected); + + // Trigger composite change event + svg.oncomposchange(true); + + } else { + graph.selected = selected; + + // Select the component + graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); + + // Trigger component select event + svg.oncompselect(graph.selected); + } + + //log('comp selected'); + + e.preventDefault(); + return true; + } + + if (!ui.isMobile()) { + div.onclick = function(e) { + //log('div onclick'); + var suspend = svg.suspendRedraw(10); + var r = onclick(e); + svg.unsuspendRedraw(suspend); + return r; + } + svg.onclick = function(e) { + //log('svg onclick'); + var suspend = svg.suspendRedraw(10); + var r = onclick(e); + svg.unsuspendRedraw(suspend); + return r; + } + } + + /** + * Handle a mouse or touch move event. + */ + function onmousemove(e) { + if (graph.dragging == null) + return true; + + // Ignore duplicate mouse move events + if (graph.moveX == graph.dragX && graph.moveY == graph.dragY) + return true; + + // Remember that the component was dragged + graph.dragged = true; + + // Cut wire to component + if (graph.dragging.parentNode != svg) { + var compos = scdl.composite(svg.compos); + setElement(compos, graph.sortcompos(graph.cutwire(graph.dragging, compos, svg))); + + // Bring component to the top + graph.bringtotop(graph.dragging, svg); + } + + // Calculate new position of dragged element + var gpos = graph.relpos(graph.dragging); + var newX = gpos.xpos() + (graph.moveX - graph.dragX); + var newY = gpos.ypos() + (graph.moveY - graph.dragY); + if (newX >= graph.palcx) + graph.dragX = graph.moveX + else + newX = graph.palcx; + if (newY >= 0) + graph.dragY = graph.moveY; + else + newY = 0; + + // Detach child elements to speedup rendering + graph.compoutline(graph.dragging, true); + + // Move the dragged element + graph.move(graph.dragging, graph.mkpath().pos(newX, newY)); + + return false; + }; + + if (!ui.isMobile()) { + window.onmousemove = function(e) { + //log('onmousemove'); + + // Remember mouse position + graph.moveX = e.screenX; + graph.moveY = e.screenY; + + var suspend = svg.suspendRedraw(10); + var r = onmousemove(e); + svg.unsuspendRedraw(suspend); + return r; + } + } else { + div.ontouchmove = function(e) { + //log('ontouchmove'); + + // Remember touch position + var pos = e.touches[0]; + if (graph.moveX == pos.screenX && graph.moveY == pos.screenY) + return true; + graph.moveX = pos.screenX; + graph.moveY = pos.screenY; + if (graph.moveX == graph.dragX && graph.moveY == graph.dragY) + return true; + + // Start async move renderer + if (graph.moverenderer == null) { + graph.moverenderer = setInterval(function() { + var suspend = svg.suspendRedraw(10); + onmousemove(e); + svg.unsuspendRedraw(suspend); + }, 10); + } + return true; + } + } + + /** + * Handle field on change events. + */ + function onvaluechange() { + if (graph.selected == null) + return false; + if (g.parentNode.style.visibility == 'hidden') + return false; + + // Change component name and refactor references to it + function changename() { + var compos = scdl.composite(svg.compos); + cvalue.value = graph.ucid(cvalue.value, compos, false); + graph.selected.id = cvalue.value; + setElement(compos, graph.sortcompos(graph.renamecomp(graph.selected.comp, compos, cvalue.value))); + + // Refresh the composite + //log('onchangename refresh'); + var nodes = graph.refresh(svg); + + // Reselected the previously selected component + graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes); + graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); + + // Trigger component select event + svg.oncompselect(graph.selected); + + // Trigger composite change event + svg.oncomposchange(true); + return false; + } + + // Change the component property value + function changeprop() { + graph.setproperty(graph.selected.comp, cvalue.value); + var hasprop = graph.hasproperty(graph.selected.comp); + cvalue.disabled = hasprop? false : true; + cvalue.style.visibility = hasprop? 'visible' : 'hidden'; + cvalue.value = graph.property(graph.selected.comp); + + // Refresh the composite + //log('onchangeprop refresh'); + var nodes = graph.refresh(svg); + + // Reselected the previously selected component + graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes); + graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); + + // Trigger component select event + svg.oncompselect(graph.selected); + + // Trigger composite change event + svg.oncomposchange(true); + return false; + } + + return graph.hasproperty(graph.selected.comp)? changeprop() : changename(); + }; + + cvalue.onchange = function() { + var suspend = svg.suspendRedraw(10); + var r = onvaluechange(); + svg.unsuspendRedraw(suspend); + return r; + } + + // Handle delete event + function ondeleteclick() { + if (graph.selected == null) + return false; + if (graph.selected.id.substring(0, 8) != 'palette:') { + + // Remove selected component + var compos = scdl.composite(svg.compos); + if (isNil(graph.selected.compos)) + setElement(compos, graph.sortcompos(graph.cutwire(graph.selected, compos, svg))); + setElement(compos, graph.sortcompos(graph.clonerefs(graph.gcollect(graph.removecomp(graph.selected.comp, compos))))); + + // Reset current selection + graph.compselect(graph.selected, false, cvalue, ccopy, cdelete); + graph.selected = null; + + // Refresh the composite + //log('ondelete refresh'); + graph.refresh(svg); + + // Trigger component select event + svg.oncompselect(null); + + // Trigger composite change event + svg.oncomposchange(true); + } + return false; + }; + + cdelete.onclick = function() { + var suspend = svg.suspendRedraw(10); + var r = ondeleteclick(); + svg.unsuspendRedraw(suspend); + return r; + }; + + // Handle copy event + function oncopyclick() { + if (graph.selected == null) + return false; + if (graph.selected.id.substring(0, 8) == 'palette:') + return false; + + // Clone the selected component + var compos = scdl.composite(svg.compos); + var comps = graph.clonecomp(graph.selected, compos, svg); + setElement(compos, graph.sortcompos(graph.addcomps(comps, compos))); + + // Refresh the composite + //log('onclick refresh'); + var nodes = graph.refresh(svg); + + // Select the component clone + graph.selected = graph.findcompnode(scdl.name(car(comps)), nodes); + graph.compselect(graph.selected, true, cvalue, ccopy, cdelete); + + // Trigger component select event + svg.oncompselect(graph.selected); + + // Trigger composite change event + svg.oncomposchange(true); + + return false; + }; + + ccopy.onclick = function() { + var suspend = svg.suspendRedraw(10); + var r = oncopyclick(); + svg.unsuspendRedraw(suspend); + return r; + }; + + // Handle add event + cadd.onclick = function() { + + // Show the palette + div.style.left = ui.pixpos(0); + return false; + }; + + // Create a hidden SVG element to help compute the width + // of component and reference titles + graph.svgtitles = document.createElementNS(graph.svgns, 'svg'); + graph.svgtitles.style.visibility = 'hidden'; + graph.svgtitles.style.height = ui.pixpos(0); + graph.svgtitles.style.width = ui.pixpos(0); + div.appendChild(graph.svgtitles); + + return svg; +}; + +/** + * Point class. + */ +graph.Point = function(x, y) { + this.x = x; + this.y = y; +}; +graph.Point.prototype.xpos = function() { + return this.x; +}; +graph.Point.prototype.ypos = function() { + return this.y; +}; + +graph.mkpoint = function(x, y) { + return new graph.Point(x, y); +}; + +/** + * Path class. + */ +graph.Path = function() { + this.path = ''; + this.x = 0; + this.y = 0; +} +graph.Path.prototype.pos = function(x, y) { + this.x = x; + this.y = y; + return this; +}; +graph.Path.prototype.xpos = function() { + return this.x; +}; +graph.Path.prototype.ypos = function() { + return this.y; +}; +graph.Path.prototype.rmove = function(x, y) { + return this.move(this.x + x, this.y + y); +}; +graph.Path.prototype.rline = function(x, y) { + return this.line(this.x + x, this.y + y); +}; +graph.Path.prototype.rcurve = function(x1, y1, x, y) { + return this.curve(this.x + x1, this.y + y1, this.x + x1 + x, this.y + y1 + y); +}; +graph.Path.prototype.str = function() { + return this.path; +}; +graph.Path.prototype.clone = function() { + return graph.mkpath().pos(this.xpos(), this.ypos()); +}; +graph.Path.prototype.move = function(x, y) { + this.path += 'M' + x + ',' + y + ' '; + return this.pos(x, y); +}; +graph.Path.prototype.line = function(x, y) { + this.path += 'L' + x + ',' + y + ' '; + return this.pos(x, y); +}; +graph.Path.prototype.curve = function(x1, y1, x, y) { + this.path += 'Q' + x1 + ',' + y1 + ' ' + x + ',' + y + ' '; + return this.pos(x, y); +}; +graph.Path.prototype.end = function() { + this.path += 'Z'; + return this; +}; + +graph.mkpath = function() { + return new graph.Path(); +}; + +/** + * Return an element representing a title. + */ +graph.mktitle = function(t, x, y) { + var title = document.createElementNS(graph.svgns, 'text'); + title.setAttribute('x', x); + title.setAttribute('y', y); + title.setAttribute('class', 'svgtitle'); + title.setAttribute('pointer-events', 'none'); + title.appendChild(document.createTextNode(t)); + graph.svgtitles.appendChild(title); + return title; +}; + +/** + * Return an element representing the title of a component. + */ +graph.comptitle = function(comp) { + return memo(comp, 'title', function() { + var ct = graph.title(comp); + var pt = graph.propertytitle(comp); + if (ct == '' && pt == '') + return null; + return graph.mktitle((ct != '' && pt != '')? ct + ' ' + pt : ct + pt, graph.titlex, graph.titley); + }); +}; + +/** + * Return the width of the title of a component. + */ +graph.comptitlewidth = function(comp) { + var title = graph.comptitle(comp); + if (isNil(title)) + return 0; + return title.getBBox().width + graph.titlew; +}; + +/** + * Draw a component shape selection. + */ +graph.compselect = function(g, s, cvalue, ccopy, cdelete) { + if (isNil(g) || !s) { + cvalue.value = ''; + cvalue.disabled = true; + cvalue.style.visibility = 'hidden'; + ccopy.disabled = true; + cdelete.disabled = true; + if (isNil(g)) + return true; + g.shape.setAttribute('stroke', graph.colors.gray); + g.shape.setAttribute('stroke-width', '1'); + return true; + } + + cvalue.value = graph.hasproperty(g.comp)? graph.property(g.comp) : g.id; + cvalue.disabled = false; + cvalue.style.visibility = 'visible'; + ccopy.disabled = false; + cdelete.disabled = false; + + g.shape.setAttribute('stroke', graph.colors.link); + g.shape.setAttribute('stroke-width', '2'); + g.parentNode.appendChild(g); + return true; +}; + +/** + * Draw a palette shape selection. + */ +graph.paletteselect = function(g, s) { + if (isNil(g)) + return true; + if (!s) { + g.shape.setAttribute('stroke', graph.colors.gray); + g.shape.setAttribute('stroke-width', '1'); + return true; + } + + g.shape.setAttribute('stroke', graph.colors.link); + g.shape.setAttribute('stroke-width', '2'); + g.parentNode.appendChild(g); + return true; +}; + +/** + * Draw a component outline for faster rendering. + */ +graph.compoutline = function(g, s) { + if (s == (isNil(g.outlined)? false : g.outlined)) + return true; + g.outlined = s; + + if (s) { + g.shape.setAttribute('fill', 'none'); + if (!isNil(g.title)) + g.removeChild(g.title); + } else { + g.shape.setAttribute('fill', graph.color(g.comp)); + if (!isNil(g.title)) + g.appendChild(g.title); + } + + map(function(r) { + var n = caddr(r); + if (isNil(n)) + return r; + graph.compoutline(n, s); + return r; + }, g.refpos); + return true; +}; + +/** + * Return a node representing a component. + */ +graph.compnode = function(comp, cassoc, pos, parentg) { + + // Make the component title element + var title = graph.comptitle(comp); + + // Compute the path of the component shape + var path = graph.comppath(comp, cassoc); + + // Create the main component shape + var shape = document.createElementNS(graph.svgns, 'path'); + shape.setAttribute('d', path.str()); + shape.setAttribute('fill', graph.color(comp)); + //shape.setAttribute('fill-opacity', '0.6'); + shape.setAttribute('stroke', graph.colors.gray); + shape.setAttribute('stroke-width', '1'); + shape.setAttribute('pointer-events', 'visible'); + + // Create an svg group and add the shape and title to it + var g = document.createElementNS(graph.svgns, 'g'); + g.comp = comp; + g.id = scdl.name(comp); + g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')'); + g.pos = pos.clone(); + g.appendChild(shape); + g.shape = shape; + if (!isNil(title)) { + g.appendChild(title); + g.title = title; + } + + // Store the the positions of the services and references + g.refpos = reverse(path.refpos); + g.svcpos = reverse(path.svcpos); + + // Handle onclick events + g.onclick = parentg.onclick; + + return g; +}; + +/** + * Find the node representing a component. + */ +graph.findcompnode = function(name, nodes) { + if (isNil(nodes)) + return null; + if (isNil(car(nodes).comp)) + return graph.findcompnode(name, cdr(nodes)); + if (name == scdl.name(car(nodes).comp)) + return car(nodes); + var node = graph.findcompnode(name, nodeList(car(nodes).childNodes)); + if (!isNil(node)) + return node; + return graph.findcompnode(name, cdr(nodes)); +} + +/** + * Return a graphical group. + */ +graph.mkgroup = function(pos) { + var g = document.createElementNS(graph.svgns, 'g'); + g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')'); + g.pos = pos.clone(); + return g; +}; + +/** + * Return a node representing a button. + */ +graph.mkbutton = function(t, pos) { + + // Make the button title + var title = graph.mktitle(t, graph.titlex, graph.titley); + + // Compute the path of the button shape + var path = graph.buttonpath().str(); + + // Create the main button shape + var shape = document.createElementNS(graph.svgns, 'path'); + shape.setAttribute('d', path); + shape.setAttribute('fill', graph.colors.lightgray1); + //shape.setAttribute('fill-opacity', '0.6'); + shape.setAttribute('stroke', graph.colors.gray); + shape.setAttribute('stroke-width', '1'); + shape.setAttribute('pointer-events', 'visible'); + + // Create a group and add the button shape to it + var g = document.createElementNS(graph.svgns, 'g'); + g.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')'); + g.pos = pos.clone(); + g.appendChild(shape); + g.appendChild(title); + + // Store the button shape in the group + g.shape = shape; + + return g; +}; + +/** + * Return the relative position of a node. + */ +graph.relpos = function(e) { + var pmatrix = e.parentNode != null? e.parentNode.getCTM() : null; + var matrix = e.getCTM(); + var curX = pmatrix != null? (Number(matrix.e) - Number(pmatrix.e)): Number(matrix.e); + var curY = pmatrix != null? (Number(matrix.f) - Number(pmatrix.f)): Number(matrix.f); + return graph.mkpath().pos(curX, curY); +}; + +/** + * Move a node. + */ +graph.move = function(e, pos) { + e.setAttribute('transform', 'translate(' + pos.xpos() + ',' + pos.ypos() + ')'); + e.pos = pos.clone(); +}; + +/** + * Return the absolute position of a component node. + */ +graph.abspos = function(e, g) { + if (e == g) + return graph.mkpath(); + var gpos = graph.relpos(e); + var pgpos = graph.abspos(e.parentNode, g); + return graph.mkpath().pos(gpos.xpos() + pgpos.xpos(), gpos.ypos() + pgpos.ypos()); +}; + +/** + * Bring a component node to the top. + */ +graph.bringtotop = function(n, g) { + if (n == g) + return null; + graph.move(n, graph.abspos(n, g)); + g.appendChild(n); +} + +/** + * Return the title of a SCDL element. + */ +graph.title = function(e) { + var t = scdl.title(e); + if (t != null) { + if (t == 'gt') + return '>' + if (t == 'lt') + return '<'; + if (t.indexOf('{propval}') != -1) + return ''; + if (t.indexOf('{compname}') == -1) + return t; + return t.replace('{compname}', scdl.name(e)); + } + return scdl.name(e); +}; + +/** + * Return the property value of a SCDL component. + */ +graph.property = function(e) { + var p = scdl.properties(e); + if (isNil(p)) + return ''; + if (scdl.visible(car(p)) == 'false') + return ''; + var pv = scdl.propertyValue(car(p)); + return pv; +}; + +/** + * Return the title of a property of a SCDL component. + */ +graph.propertytitle = function(e) { + var pv = graph.property(e); + var t = scdl.title(e); + if (t.indexOf('{propval}') == -1) + return pv; + return t[0] == ' '? t.substr(1).replace('{propval}', pv) : t.replace('{propval}', pv); +}; + +/** + * Return true if a SCDL component has a property. + */ +graph.hasproperty = function(e) { + var p = scdl.properties(e); + if (isNil(p)) + return false; + if (scdl.visible(car(p)) == 'false') + return false; + return true; +}; + +/** + * Change the property value of a SCDL component. + */ +graph.setproperty = function(e, value) { + var p = scdl.properties(e); + if (isNil(p)) + return ''; + if (scdl.visible(car(p)) == 'false') + return ''; + var name = scdl.name(car(p)); + setElement(car(p), mklist(element, "'property", mklist(attribute, "'name", name != null? name : "property"), value)); + return value; +}; + +/** + * Return the color of a SCDL component. + */ +graph.color = function(comp) { + return memo(comp, 'color', function() { + var c = scdl.color(comp); + return c == null? graph.colors.blue1 : graph.colors[c]; + }); +}; + +/** + * Return the services on the left side of a component. + */ +graph.lsvcs = function(comp) { + return memo(comp, 'lsvcs', function() { + var svcs = scdl.services(comp); + if (isNil(svcs)) + return mklist(mklist("'element","'service","'attribute","'name",scdl.name(comp))); + var l = filter(function(s) { + var a = scdl.align(s); + var v = scdl.visible(s); + return (a == null || a == 'left') && v != 'false'; + }, svcs); + if (isNil(l)) + return mklist(); + return mklist(car(l)); + }); +}; + +/** + * Return the references on the right side of a component. + */ +graph.rrefs = function(comp) { + return memo(comp, 'rrefs', function() { + return filter(function(r) { + var a = scdl.align(r); + var v = scdl.visible(r); + return (a == null || a == 'right') && v != 'false'; + }, scdl.references(comp)); + }); +}; + +/** + * Return the height of a reference on the right side of a component. + */ +graph.rrefheight = function(ref, cassoc) { + return memo(ref, 'rheight', function() { + var target = assoc(scdl.target(ref), cassoc); + if (isNil(target)) + return graph.tabsz * 8; + return graph.compclosureheight(cadr(target), cassoc); + }); +}; + +/** + * Return the total height of the references on the right side of a component. + */ +graph.rrefsheight = function(refs, cassoc) { + if (isNil(refs)) + return 0; + return graph.rrefheight(car(refs), cassoc) + graph.rrefsheight(cdr(refs), cassoc); +}; + +/** + * Return the height of a component node. + */ +graph.compheight = function(comp, cassoc) { + return memo(comp, 'height', function() { + var lsvcs = graph.lsvcs(comp); + var lsvcsh = Math.max(1, length(lsvcs)) * (graph.tabsz * 8) + (graph.tabsz * 4); + var rrefs = graph.rrefs(comp); + var rrefsh = graph.rrefsheight(rrefs, cassoc) + (graph.tabsz * 2); + return Math.max(lsvcsh, rrefsh); + }); +}; + +/** + * Return the height of a component and the components wired to its bottom side. + */ +graph.compclosureheight = function(comp, cassoc) { + return memo(comp, 'closureheight', function() { + return graph.compheight(comp, cassoc); + }); +}; + +/** + * Return the max width of the references on the right side of a component. + */ +graph.rrefswidth = function(refs, cassoc) { + if (isNil(refs)) + return 0; + return Math.max(graph.rrefwidth(car(refs), cassoc), graph.rrefswidth(cdr(refs), cassoc)); +}; + +/** + * Return the width of a component. + */ +graph.compwidth = function(comp, cassoc) { + return memo(comp, 'width', function() { + var ctw = graph.comptitlewidth(comp); + var rrefsw = (isNil(graph.rrefs(comp))? 0 : (graph.tabsz * 4)); + var twidth = (graph.titlex * 2) + ctw + rrefsw; + var width = Math.max(twidth, (graph.tabsz * 8) + (graph.tabsz * 4)); + return width; + }); +}; + +/** + * Return a path representing a reference positioned to the right of a component. + */ +graph.rrefpath = function(ref, cassoc, path, maxheight) { + var height = graph.rrefheight(ref, cassoc); + + // Record reference position in the path + var xpos = path.xpos(); + var ypos = path.ypos(); + path.refpos = cons(mklist(ref, graph.mkpath().pos(xpos, ypos + (graph.tabsz * 5))), path.refpos); + + // Compute the reference path + return path.rline(0,graph.tabsz * 2).rcurve(0,graph.tabsz,-graph.tabsz,0).rcurve(-graph.tabsz,0,0,-graph.tabsz/2.0).rcurve(0,-graph.tabsz/2.0,-graph.tabsz,0).rcurve(-graph.tabsz,0,0,graph.tabsz/2.0).rline(0,graph.tabsz * 3).rcurve(0,graph.tabsz/2.0,graph.tabsz,0).rcurve(graph.tabsz,0,0,-graph.tabsz/2.0).rcurve(0,-graph.tabsz/2.0,graph.tabsz,0).rcurve(graph.tabsz,0,0,graph.tabsz).line(path.xpos(), Math.min(ypos + height, maxheight)); +}; + +/** + * Return a path representing a service positioned to the left of a component. + */ +graph.lsvcpath = function(svc, cassoc, path, minheight) { + var height = graph.tabsz * 8; + + // Record service position in the path + var xpos = path.xpos(); + var ypos = path.ypos(); + path.svcpos = cons(mklist(svc, graph.mkpath().pos(xpos, ypos - (graph.tabsz * 6))), path.svcpos); + + // Compute the service path + return path.rline(0, -(graph.tabsz * 2)).rcurve(0,-graph.tabsz,-graph.tabsz,0).rcurve(-graph.tabsz,0,0,graph.tabsz/2.0).rcurve(0,graph.tabsz/2.0,-graph.tabsz,0).rcurve(-graph.tabsz,0,0,-graph.tabsz/2.0).rline(0,-(graph.tabsz * 3)).rcurve(0,-graph.tabsz/2.0,graph.tabsz,0).rcurve(graph.tabsz,0,0,graph.tabsz/2.0).rcurve(0,graph.tabsz/2.0,graph.tabsz,0).rcurve(graph.tabsz,0,0,-graph.tabsz).line(path.xpos(), Math.max(ypos - height, minheight)); +}; + +/** + * Return a path representing a component node. + */ +graph.comppath = function(comp, cassoc) { + + // Calculate the width and height of the component node + var width = graph.compwidth(comp, cassoc); + var height = graph.compheight(comp, cassoc); + + /** + * Apply a path rendering function to a list of services or references. + */ + function renderpath(x, f, cassoc, path, height) { + if (isNil(x)) + return path; + return renderpath(cdr(x), f, cassoc, f(car(x), cassoc, path, height), height); + } + + var path = graph.mkpath().move(graph.curvsz,0); + + // Store the positions of services and references in the path + path.refpos = mklist(); + path.svcpos = mklist(); + + // Render the references on the right side of the component + var rrefs = graph.rrefs(comp); + path = path.line(width - graph.curvsz,path.ypos()).rcurve(graph.curvsz,0,0,graph.curvsz); + path = renderpath(rrefs, graph.rrefpath, cassoc, path, height - graph.curvsz); + + // Render the references on the bottom side of the component + var boffset = graph.curvsz; + path = path.line(path.xpos(),height - graph.curvsz).rcurve(0,graph.curvsz,graph.curvsz * -1,0).line(boffset, path.ypos()); + + // Render the services on the left side of the component + var lsvcs = graph.lsvcs(comp); + var loffset = graph.curvsz + (length(lsvcs) * (graph.tabsz * 8)); + path = path.line(graph.curvsz,path.ypos()).rcurve(graph.curvsz * -1,0,0,graph.curvsz * -1).line(path.xpos(), loffset); + path = renderpath(lsvcs, graph.lsvcpath, cassoc, path, graph.curvsz); + + // Close the component node path + path = path.line(0,graph.curvsz).rcurve(0,graph.curvsz * -1,graph.curvsz,0); + + return path.end(); +}; + +/** + * Return the position of a component. + */ +graph.comppos = function(comp, pos) { + var x = scdl.x(comp); + var y = scdl.y(comp); + return graph.mkpath().pos(x != null? Number(x) + graph.palcx : pos.xpos(), y != null? Number(y) : pos.ypos()); +}; + +/** + * Return a path representing a button node. + */ +graph.buttonpath = function(t) { + var path = graph.mkpath().move(graph.curvsz,0); + path = path.line(graph.buttoncx - graph.curvsz,path.ypos()).rcurve(graph.curvsz,0,0,graph.curvsz); + path = path.line(path.xpos(),graph.buttoncy - graph.curvsz).rcurve(0,graph.curvsz,-graph.curvsz,0).line(graph.curvsz, path.ypos()); + path = path.line(graph.curvsz,path.ypos()).rcurve(-graph.curvsz,0,0,-graph.curvsz).line(path.xpos(), graph.curvsz); + path = path.line(0,graph.curvsz).rcurve(0,-graph.curvsz,graph.curvsz,0); + return path.end(); +}; + +/** + * Render a SCDL composite into a list of component nodes. + */ +graph.composite = function(compos, pos, aspalette, g) { + var name = scdl.name(scdl.composite(compos)); + var comps = scdl.components(compos); + var cassoc = scdl.nameToElementAssoc(comps); + var proms = scdl.promotions(compos); + + // Unmemoize any memoized info about components and their references. + map(function(c) { + unmemo(c); + map(function(r) { + unmemo(r); + }, scdl.references(c)); + }, comps); + + /** + * Render a component. + */ + function rendercomp(comp, cassoc, pos) { + + /** + * Render the references on the right side of a component. + */ + function renderrrefs(refs, cassoc, pos, gcomp) { + + /** + * Render a reference on the right side of a component. + */ + function renderrref(ref, cassoc, pos, gcomp) { + var target = assoc(scdl.target(ref), cassoc); + if (isNil(target)) + return null; + + // Render the component target of the reference + return rendercomp(cadr(target), cassoc, pos); + } + + /** + * Move the rendering cursor down below a reference. + */ + function rendermove(ref, cassoc, pos) { + return pos.clone().rmove(0, graph.rrefheight(ref, cassoc)); + } + + if (isNil(refs)) + return mklist(); + + // Return list of (ref, comp rendering) pairs + var grefcomp = renderrref(car(refs), cassoc, pos, gcomp); + return cons(mklist(car(refs), grefcomp), renderrrefs(cdr(refs), cassoc, rendermove(car(refs), cassoc, pos), gcomp)); + } + + // Compute the component shape + var gcomp = graph.compnode(comp, cassoc, pos, g); + + // Render the components wired to the component references + var rrefs = graph.rrefs(comp); + var rpos = graph.mkpath().rmove(graph.compwidth(comp, cassoc), 0); + var grrefs = renderrrefs(rrefs, cassoc, rpos, gcomp); + + // Store list of (ref, pos, component rendering) triplets in the component + function refposgcomp(refpos, grefs) { + if (isNil(refpos)) + return mklist(); + + // Append component rendering to component + var gref = cadr(car(grefs)); + if (gref != null) + gcomp.appendChild(gref); + return cons(mklist(car(car(refpos)), cadr(car(refpos)), gref), refposgcomp(cdr(refpos), cdr(grefs))); + } + + gcomp.refpos = refposgcomp(gcomp.refpos, grrefs); + + return gcomp; + } + + /** + * Render a list of promoted service components. + */ + function renderproms(svcs, cassoc, pos) { + + /** + * Return the component promoted by a service. + */ + function promcomp(svc, cassoc) { + var c = assoc(scdl.promote(svc), cassoc); + if (isNil(c)) + return mklist(); + return cadr(c); + } + + /** + * Move the rendering cursor down below a component. + */ + function rendermove(comp, cassoc, pos) { + return pos.clone().rmove(0, graph.compclosureheight(comp, cassoc) + Math.max((graph.tabsz * 2), 8)); + } + + if (isNil(svcs)) + return mklist(); + + // Render the first promoted component in the list + // then recurse to render the rest of the list + var comp = promcomp(car(svcs), cassoc); + if (isNil(comp)) + return renderproms(cdr(svcs), cassoc, rendermove(car(svcs), cassoc, pos)); + + var cpos = graph.comppos(comp, pos); + return cons(rendercomp(comp, cassoc, cpos), renderproms(cdr(svcs), cassoc, rendermove(comp, cassoc, cpos))); + } + + // Render the promoted service components + var rproms = renderproms(proms, cassoc, pos.clone().rmove(graph.tabsz * 4, graph.tabsz * 4)); + + if (aspalette) { + + // Prefix ids of palette component elements with 'palette:' and + // move them to the palette area + return map(function(r) { + r.id = 'palette:' + r.id; + var gpos = r.pos; + graph.move(r, graph.mkpath().pos(gpos.xpos() - graph.palcx, gpos.ypos())); + return r; + }, rproms); + + } else { + + // Link app component elements to the containing composite + return map(function(r) { r.compos = compos; return r; }, rproms); + } +}; + +/** + * Return a component unique id. + */ +graph.ucid = function(prefix, compos1, compos2, clone) { + + // Build an assoc list keyed by component name + var comps = map(function(c) { return mklist(scdl.name(c), c); }, append(namedElementChildren("'component", compos1), namedElementChildren("'component", compos2))); + + if (!clone && isNil(assoc(prefix, comps))) + return prefix; + + /** + * Find a free component id. + */ + function ucid(p, id) { + if (isNil(assoc(p + id, comps))) + return p + id; + return ucid(p, id + 1); + } + + /** + * Remove trailing digits from a prefix. + */ + function untrail(p) { + if (p.length < 2 || p[p.length - 1] < '0' || p[p.length - 1] > '9') + return p; + return untrail(p.substring(0, p.length - 1)); + } + + return ucid(prefix == ''? 'comp' : (clone? untrail(prefix) : prefix), 1); +}; + +/** + * Clone a palette component node. + */ +graph.clonepalette = function(e, compos, g) { + + // Clone the SCDL component and give it a unique name + var wcomp = append(mklist(element, "'component", mklist(attribute, "'name", graph.ucid(scdl.name(e.comp), compos, compos, true))), + filter(function(c) { return !(isAttribute(c) && attributeName(c) == "'name")}, elementChildren(e.comp))); + var x = '<composite>' + writeXML(mklist(wcomp), false) + '</composite>'; + var rcompos = scdl.composite(readXML(mklist(x))); + var comp = car(scdl.components(mklist(rcompos))); + + // Update component position + setElement(comp, graph.movecomp(comp, graph.abspos(e, g).rmove(graph.palcx, 0))); + + return comp; +}; + +/** + * Move a SCDL component to the given position. + */ +graph.movecomp = function(comp, pos) { + if (isNil(pos)) + return append(mklist(element, "'component"), + filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'x" || attributeName(e) == "'y")); }, elementChildren(comp))); + return append(mklist(element, "'component", mklist(attribute, "'x", '' + (pos.xpos() - graph.palcx)), mklist(attribute, "'y", '' + pos.ypos())), + filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'x" || attributeName(e) == "'y")); }, elementChildren(comp))); +}; + +/** + * Align a pos along a 10pixel grid. + */ +graph.gridsnap = function(x) { + return Math.round(x / 10) * 10; +} + +/** + * Clone a component node and all the components it references. + */ +graph.clonecomp = function(e, compos, g) { + + // Write the component and the components it references to XML + function collectcomp(e) { + function collectrefs(refpos) { + if (isNil(refpos)) + return mklist(); + var r = car(refpos); + var n = caddr(r); + if (isNil(n)) + return collectrefs(cdr(refpos)); + return append(collectcomp(n), collectrefs(cdr(refpos))); + } + + return cons(e.comp, collectrefs(e.refpos)); + } + + var allcomps = collectcomp(e); + var ls = map(function(e) { return writeXML(mklist(e), false); }, allcomps); + var x = '<composite>' + writeStrings(ls) + '</composite>'; + + // Read them back from XML to clone them + var rcompos = scdl.composite(readXML(mklist(x))); + var comps = scdl.components(mklist(rcompos)); + + // Give them new unique names + map(function(e) { + + // Rename each component + var oname = scdl.name(e); + var name = graph.ucid(oname, compos, rcompos, true); + setElement(e, append(mklist(element, "'component", mklist(attribute, "'name", name)), + filter(function(c) { return !(isAttribute(c) && attributeName(c) == "'name")}, elementChildren(e)))); + + // Refactor references to the component + map(function(c) { return graph.refactorrefs(scdl.references(c), oname, name); }, comps); + }, comps); + + // Update the top component position + var comp = car(comps); + setElement(comp, graph.movecomp(comp, graph.abspos(e, g).rmove(10, 10))); + + return comps; +}; + +/** + * Sort elements of a composite. + */ +graph.sortcompos = function(compos) { + return append(mklist(element, "'composite"), elementChildren(compos).sort(function(a, b) { + + // Sort attributes, place them at the top + var aa = isAttribute(a); + var ba = isAttribute(b); + if (aa && !ba) return -1; + if (!aa && ba) return 1; + if (aa && ba) { + var aan = attributeName(a); + var ban = attributeName(b); + if (aan < ban) return -1; + if (aan > ban) return 1; + return 0; + } + + // Sort elements, place services before components + var aen = elementName(a); + var ben = elementName(b); + if (aen == "'service" && ben == "'component") return -1; + if (aen == "'component" && ben == "'service") return 1; + var an = scdl.name(a); + var bn = scdl.name(b); + if (an < bn) return -1; + if (an > bn) return 1; + return 0; + })); +} + +/** + * Add a list of components to a SCDL composite. The first + * component in the list is a promoted component. + */ +graph.addcomps = function(comps, compos) { + var comp = car(comps); + var name = scdl.name(comp); + var prom = mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name)); + return append(mklist(element, "'composite"), append(elementChildren(compos), cons(prom, comps))); +}; + +/** + * Remove a component from a SCDL composite. + */ +graph.removecomp = function(comp, compos) { + var name = scdl.name(comp); + return append(mklist(element, "'composite"), + filter(function(c) { return !(isElement(c) && scdl.name(c) == name); }, elementChildren(compos))); +}; + +/** + * Garbage collect components not referenced or promoted. + */ +graph.gcollect = function(compos) { + + // List the promoted components + var proms = map(function(s) { return mklist(scdl.promote(s), true); }, scdl.promotions(mklist(compos))); + + // List the referenced components + var refs = reduce(function(a, comp) { + return append(a, + map(function(ref) { return mklist(scdl.target(ref), true); }, filter(function(ref) { return scdl.target(ref) != null; }, scdl.references(comp)))); + }, mklist(), scdl.components(mklist(compos))); + + // Filter out the unused components + var used = append(proms, refs); + return append(mklist(element, "'composite"), + filter(function(c) { return !(isElement(c) && elementName(c) == "'component" && isNil(assoc(scdl.name(c), used))); }, elementChildren(compos))); +} + +/** + * Clone and cleanup clonable references. + */ +graph.clonerefs = function(compos) { + return append(mklist(element, "'composite"), + map(function(c) { + if (elementName(c) != "'component") + return c; + + // If the references are clonable + var refs = scdl.references(c); + if (isNil(refs)) + return c; + if (scdl.clonable(car(refs)) != 'true') + return c; + + // Filter out the unwired references and add a fresh unwired + // reference at the end of the list + var cc = append( + filter(function(e) { return !(elementName(e) == "'reference" && scdl.target(e) == null); }, elementChildren(c)), + mklist(mklist(element, "'reference", mklist(attribute, "'name", scdl.name(car(refs))), mklist(attribute, "'clonable", "true")))); + return append(mklist(element, "'component"), cc); + + }, elementChildren(compos))); +} + +/** + * Refactor references to a component. + */ +graph.refactorrefs = function(refs, oname, nname) { + if (isNil(refs)) + return true; + var ref = car(refs); + if (scdl.target(ref) != oname) + return graph.refactorrefs(cdr(refs), oname, nname); + + // Change the reference's target attribute + setElement(ref, append(mklist(element, "'reference"), + append(filter(function(e) { return !(isAttribute(e) && attributeName(e) == "'target"); }, elementChildren(ref)), + mklist(mklist(attribute, "'target", nname))))); + + return graph.refactorrefs(cdr(refs), oname, nname); +}; + +/** + * Rename a component. + */ +graph.renamecomp = function(comp, compos, name) { + + // Refactor all the references to the renamed component + var oname = scdl.name(comp); + map(function(c) { return graph.refactorrefs(scdl.references(c), oname, name); }, namedElementChildren("'component", compos)); + + // Rename the SCDL promoted service and component + var proms = filter(function(s) { return scdl.name(s) == oname }, scdl.services(compos)); + if (!isNil(proms)) + setElement(car(proms), mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name))); + setElement(comp, append(mklist(element, "'component"), + cons(mklist(attribute, "'name", name), + filter(function(e) { return !(isAttribute(e) && attributeName(e) == "'name"); }, elementChildren(comp))))); + + return append(mklist(element, "'composite"), elementChildren(compos)); +}; + +/** + * Cut the wire to a component node and make that node a + * top level component node. + */ +graph.cutwire = function(node, compos, g) { + + /** + * Find the reference wired to a node and cut its wire. + */ + function cutref(refs, node) { + if (isNil(refs)) + return true; + var ref = car(refs); + if (caddr(ref) == node) { + setlist(ref, mklist(car(ref), cadr(ref), null)); + setElement(car(ref), + append(mklist(element, "'reference"), + filter(function(e) { return !(isAttribute(e) && attributeName(e) == "'target"); }, elementChildren(car(ref))))); + } + return cutref(cdr(refs), node); + } + + // Cut any reference wire, if found + cutref(node.parentNode.refpos, node); + + // Make the component node a top level node. + node.compos = g.compos; + + // Update the SCDL composite, add a promote element for + // that component + var comp = node.comp; + var name = scdl.name(comp); + var prom = mklist(element, "'service", mklist(attribute, "'name", name), mklist(attribute, "'promote", name)); + return append(mklist(element, "'composite"), + append(mklist(prom), filter(function(c) { return !(isElement(c) && elementName(c) == "'service" && scdl.name(c) == name); }, elementChildren(compos)))); +} + +/** + * Wire a component to the closest neighbor reference. + */ +graph.wire = function(n, compos, g) { + + // Compute position of the component's service node + var spos = cadr(car(n.svcpos)); + var aspos = graph.abspos(n, g).rmove(spos.xpos(), spos.ypos()); + + /** + * Find closest unwired reference node among all the references + * of all the components. + */ + function closecomprefs(nodes, spos, cref) { + + /** + * Find the closest unwired reference node among all the + * references of a node. + */ + function closerefs(npos, refs, spos, cref) { + if (isNil(refs)) + return cref; + var fdist = cadddr(cref); + var ref = car(refs); + + // Skip wired reference + if (!isNil(filter(function(n) { return isAttribute(n) && attributeName(n) == "'target"; }, car(ref)))) + return closerefs(npos, cdr(refs), spos, cref); + + // Compute distance between service node and reference node + var rpos = cadr(ref).clone().rmove(npos.xpos(), npos.ypos()); + var dx = Math.pow(rpos.xpos() - spos.xpos(), 2); + var dy = Math.pow(rpos.ypos() - spos.ypos(), 2); + + // Check for proximity threshold + var rdist = (dx < (graph.proxcx * graph.proxcx) && dy < (graph.proxcy * graph.proxcy))? Math.sqrt(dx + dy) : 25000000; + + // Go through all the references in the component + return closerefs(npos, cdr(refs), spos, fdist < rdist? cref : mklist(car(ref), cadr(ref), caddr(ref), rdist)); + } + + if (isNil(nodes)) + return cref; + + // Skip non-component nodes + var node = car(nodes); + if (isNil(node.comp)) + return closecomprefs(cdr(nodes), spos, cref); + + // Compute the component absolute position + var npos = graph.abspos(node, g); + + // Go through all the components and their references + return closecomprefs(append(nodeList(node.childNodes), cdr(nodes)), spos, closerefs(npos, node.refpos, spos, cref)); + } + + // Find closest reference node + var cref = closecomprefs(nodeList(g.childNodes), aspos, mklist(null, graph.mkpath(), null, 25000000)); + if (car(cref) == null) + return compos; + if (cadddr(cref) == 25000000) + return compos; + + // Wire component to that reference, un-promote it, and + // update the SCDL reference and composite + setElement(n.comp, graph.movecomp(graph.dragging.comp, null)); + n.compos = null; + setElement(car(cref), append(mklist(element, "'reference", mklist(attribute, "'target", scdl.name(n.comp))), elementChildren(car(cref)))); + var name = scdl.name(n.comp); + return append(mklist(element, "'composite"), + filter(function(c) { return !(isElement(c) && elementName(c) == "'service" && scdl.name(c) == name); }, elementChildren(compos))); +} + +/** + * Display a list of graphical nodes. + */ +graph.display = function(nodes, g, svg) { + var suspend = svg.suspendRedraw(10); + + // Append the nodes to the graphical canvas + appendNodes(nodes, g); + + svg.unsuspendRedraw(suspend); + return nodes; +}; + +/** + * Hide a graph. + */ +graph.hide = function(g) { + + // Remove nodes from the graph + map(function(n) { if (!isNil(n.comp) && n.id.substr(0, 8) != 'palette:') { g.removeChild(n); } return n; }, nodeList(g.childNodes)); + return g; +}; + +/** + * Refresh a graph. + */ +graph.refresh = function(g) { + //log('refresh'); + + // Remove existing nodes from the graph + map(function(n) { if (!isNil(n.comp) && n.id.substr(0, 8) != 'palette:') { g.removeChild(n); } return n; }, nodeList(g.childNodes)); + + // Redisplay the composite associated with the graph + var nodes = graph.composite(g.compos, graph.mkpath().pos(graph.palcx,0), false, g); + appendNodes(nodes, g); + return nodes; +}; + +/** + * Display and enable editing of a composite and the graphical + * nodes that represent it. + */ +graph.edit = function(appname, compos, nodes, onchange, onselect, g) { + var suspend = g.suspendRedraw(10); + + // Store the appname and composite in the graphical canvas + g.appname = appname; + g.compos = compos; + + // Sort the composite elements now to allow for change detection later + var scompos = scdl.composite(g.compos); + setElement(scompos, graph.sortcompos(scompos)); + + // Store event listeners + g.oncomposchange = onchange; + g.oncompselect = onselect; + + // Remove existing nodes from the graph + map(function(n) { if (!isNil(n.comp) && n.id.substr(0, 8) != 'palette:') { g.removeChild(n); } return n; }, nodeList(g.childNodes)); + + // Display the composite nodes + appendNodes(nodes, g); + + g.unsuspendRedraw(suspend); + return nodes; +}; + +/** * Track the current app composite and corresponding saved XML content. */ var savedcomposxml = ''; @@ -216,7 +1940,7 @@ function getapp(name, g) { } // Display the composite - graph.edit(name, composite, graph.composite(composite, graph.mkpath().move(palcx,0), false, g), oncomposchange, oncompselect, g); + graph.edit(name, composite, graph.composite(composite, graph.mkpath().move(graph.palcx,0), false, g), oncomposchange, oncompselect, g); // Track the saved composite XML savedcomposxml = car(writeXML(composite, false)); @@ -319,29 +2043,14 @@ function oncomposchange(prop) { } /** - * Return the link to a component value. - */ -function compdatalink(appname, cname) { - if (cname == '' || isNil(cname)) - return ''; - var protocol = window.location.protocol; - var host = window.location.hostname; - var port = ':' + window.location.port; - if (port == ':80' || port == ':443' || port == ':') - port = ''; - var link = protocol + '//' + appname + '.' + host + port + '/data/#component=' + cname; - return link; -} - -/** * Return the link to a component. */ function complink(appname, cname) { if (cname == '' || isNil(cname)) return ''; - var protocol = window.location.protocol; - var host = window.location.hostname; - var port = ':' + window.location.port; + var protocol = location.protocol; + var host = location.hostname; + var port = ':' + location.port; if (port == ':80' || port == ':443' || port == ':') port = ''; var link = protocol + '//' + appname + '.' + host + port + '/c/' + cname; @@ -355,16 +2064,14 @@ function oncompselect(gsel) { if (gsel == gcomp) return true; gcomp = gsel; - var cname = isNil(gsel)? '' : gsel.id; - var link = compdatalink(appname, cname); function updateButton(b, v) { b.style.color = v? '#000000' : '#808080'; } - updateButton(cdelete, link != ''); - updateButton(ccopy, link != ''); - updateButton(cplay, link != ''); + updateButton(cdelete, !isNil(gsel)); + updateButton(ccopy, !isNil(gsel)); + updateButton(cplay, !isNil(gsel)); return true; } @@ -376,14 +2083,47 @@ function showdata(gcomp) { return true; if (isNil(gcomp)) return true; - cvalue.value = complink(appname, gcomp.id); + var clink = complink(appname, gcomp.id); + cvalue.value = clink; cplay.innerHTML = '<'; - gdiv.style.visibility = 'hidden' gvisible = false; - pdiv.style.visibility = 'visible'; pdiv.innerHTML = ''; - pdiv.innerHTML = '<iframe id="dataFrame" style="position: relative; height: 5000px; width: 2500px; border: 0px;" scrolling="no" frameborder="0" src="' + - compdatalink(appname, gcomp.id) + '"></iframe>'; + pdiv.style.visibility = 'visible'; + + // Get the component result data + var comp = sca.component(gcomp.id, appname); + comp.getnocache('', function(doc) { + function displaydata(t, w) { + pdiv.style.width = w; + pdiv.innerHTML = t; + return true; + } + + // Stop now if we didn't get the doc + if (doc == null) + return displaydata('No content', '2500px'); + + // Format data table + if (json.isJSON(mklist(doc))) + return displaydata(ui.datatable(json.readJSON(mklist(doc))), '2500px'); + + if (atom.isATOMEntry(mklist(doc))) + return displaydata(ui.datatable(atom.readATOMEntry(mklist(doc))), '2500px'); + + if (atom.isATOMFeed(mklist(doc))) + return display(ui.datatable(atom.readATOMFeed(mklist(doc))), '2500px'); + + // Insert the doc as is in an iframe + var t = '<table class="datatable" style="width: 100%;">' + + '<tr><td class="datatdltop">' + 'value' + '</td>' + '<td class="datatdr">' + + '<iframe style="width: 100%; height: 5000px;" scrolling="no" frameborder="0" src="' + clink + '"/>' + + '</td></tr></table>' + return displaydata(t, '100%'); + }); + + setTimeout(function() { + gdiv.style.visibility = 'hidden' + }, 0); return true; } @@ -394,11 +2134,13 @@ function showgraph(gcomp) { if (gvisible) return true; cplay.innerHTML = '>'; - pdiv.style.visibility = 'hidden'; - pdiv.innerHTML = ''; gdiv.style.visibility = 'visible' gvisible = true; graph.compselect(gcomp, true, cvalue, ccopy, cdelete); + setTimeout(function() { + pdiv.style.visibility = 'hidden'; + pdiv.innerHTML = ''; + }, 0); return true; } @@ -437,13 +2179,7 @@ installpalette('python', pos.rmove(0, 28), g, bg, spalette, gpalettes); // Get and display the current app getapp(appname, g); -</script> -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> +</script> </div> -</body> -</html> - diff --git a/sca-cpp/trunk/modules/edit/htdocs/home/home.b64 b/sca-cpp/trunk/modules/edit/htdocs/home/home.b64 new file mode 100644 index 0000000000..9131135881 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/home/home.b64 @@ -0,0 +1 @@ +iVBORw0KGgoAAAANSUhEUgAAAaoAAACRCAIAAAAdJ2t7AAAgAElEQVR42u2d+1NT1/r/99/AD2f68ZfjOOOFGXFwhoLScqgow2E+IAylGUqDCAlBwFgU6yUwMkVyKnKGD7anSvVrcWwZLziVFioUiQJCzIWQkHATwrXCEVQUBP1Uz6d+n7XXTtgJm5ug3J5n3tMuHtfaa+2tefE8a629wrxGQ0NDW5HG4CNAQ0ND/KGhoaEh/tDQ0NAQf2hoaGiIPzQ0NDTEHxoaGhriDw0NDQ3xh4aGhob4Q0NDQ0P8oaGhoSH+0NDQ0BB/aGhoaMsSfy9fvhwbGxsdHX2G9tYMHi88ZHjUS+75L92R4/NchPe4iPA3MNyhsV4pbzz1q/mr4oZM1FsSPN5yS6763qX23obBwcHnz5/T5/981DrQ90NfV9b9zmP3O1MXpWBgWX09F/vvG/kjb3nyNK/5nsJg3KczJGnrUDMUPC5FnfGMpVnf3ePwL2GoZbAxr1+r6Ffv669NWtqCW4AbaTjT36Xn3+Piwl/rv6tKzEpk07sUPHBjR3l/f//w8PDTxxX3O9MWK/UmKq2v9wYdeUnv/b1IvbkJHuD1e230eQ73lPSr9y556glwcG9/y3V6j4sLfxD32dlXYs4sa838rS2zvF2JekuCxwsPGR41PHaIAXu67va0HaVk6e9Kfdyf+nQgdXhwMQoGBsODQQIBIQa8025NUOu4j7HOkGC0JDQ0JZibUTMVPC6jBR4dEBBiwJ62O73VCZQXD9RJT/QJI4aEZ/VLW3ALcCNwO4SAXXog4NxjwPnEH+S8lH1lrcrb9zMr+5SodyB41PDASRbccrqj+SCwD8jyn1HF/40tdsEgYaiQBWdr66TVtcC+RKNF1tYpa+9CvYnaOuEBQhZsvZvdeUsK7HuiT/yzSfa6efkIbgduimTB/f2QBS8W/L18+bK88RSN+5B9C0DAhv9pb063Nqfc7zy6JNhnJ2CP9cT+O2pJVU2Ctg7ZN3cCKrQG6+39nSpJf03CMmOfnYAPdIp+1ua4EjJv+BsbG6NrHZCOTftxVdXHfRYXVNCB5JpEPYcPy33/UXts5k1KGr5qbzoE+BvoPbyQRBved/6gd5Hl4Myb3O84JquqAfzJ6oz2j7G4MNd1x1aXLYnhjXPCgbT2qvvu9IjGhWk+hew3GHYLujgGXUhrCmhhjlfepzV0qGSAv4d3x5HxoibCqpHOFjRv1uod6EmdnOIPsLMo8Dc6Okoz39/apsdfaVkQw7x3ug1JN4naktYwTHxZ2izwZ84E9oEe3j+0kPgbiHVjmBO1B2bepL87TcLiT2ow2T7DdV4Mw6yP9ErLnSMOYorSGWZDqGlhmk+u8Rv8+HomlKCLmKJjtDDHi+/VGYB9oMd2chnDQxgm43L07CjzZq3eiUYMCRR/gJ1Fgb9nz55R/JW3T/9ZLVXBg3X9vgfKx1U9yDvH0BgeSE/yhwwjnw3+fjUrKf4e9S1Y9PfHMER/8fBXm/tG+Iurb7B9hitdGca7pHXuoIkpUTKMf3hLl6ylXfqGzbeGzT/+BG4wpgQ4uCVsHvBXT/E3pI3jeGEhIDtVJJkdZd6s1TvRs3oOf4CdRYm/nuTPXN+L/+kwG8vIw13fi81PIeWOZCjv/3//Db/8wuXvM6z5p+4uZT/DxVVR/q7U9568IBk85bVRH7q6xx50rmkXW8E1PM6dVvjsX0kq1n+xIGQzw9haRRWzzis/cc41YR8Ee7/32dkUwU6dVFT2qb1CfL58ik5nPn7BTq9c5Ya3OeA9+O+BOeOvqSjwI9tD+Czzk0djijHLJyEb132+dyN1HsmP/WMSJzR/VP/JZ5zvL7lF8f/H1dz4Zdpm2zUjnrI1u37lOvoo6C/w3zNzwV9jhZttzGszSsEjOq9cZfccOhfNfsijik6vXU99W30uVtJPfnTZOZtzg/f5Chu/GNfdodTrkVMsdW6+wSuvVDaJk4e/xoDPQyFe26lt57NGojq3er2/m+367uz1WefWtSFbSdc5Fc6XdbxBScXp/1ofE25ywN/EG5kD/mIKgrnukrNF4BkqCRCvow6XU2fBIy2Vr2Y83Q16Qhbrtx4Ms/rnil1OrRB/s4r+vkwLYxhxFHChuPjv5CmGicq5tHfN/xSFEI/rBzmq5K//5QtFueqYqn43ZHyb5R9frP+COuN/UrBxIhipmZPzAYGC6tiEQBIu5Xtad/js2R1QjL16uLyKOINPxF6p/+J0PukdEsnSKhEUPkyNKtDJD8cRvnyYkSTYqQNe2VZr4j6+qEvJOUEG8FnBF4Kdznz8gjXLecOTB5A2U0R/5R3KYvNxUHnHpPgbqw+Ei8i+juyyJqmv+jFsTvpUR5zMRm916z59wd+g+OWv+wSdf1gj4FP60cGgJmtSVb43aX4zmavJeN7Uxd/M8ySk0x0cqyf3GJL5SVurNDeI/PEU0d+zh4r+LiIoTBL9tUZcIsxyO1EgqmqUlLH8yiiIrK0JzTsCZa8ik0x7wQU+u7uzRVWVgYf8ye+VqnZpLXGu2pMtqq3ZmZNIal6qo/hj1ifuLKukTo+LdZKyXMbWPCgjlmDrfI2gkwseG03+u8ll/EpMQuEhuX5olSbsm/3s9TWck4n1zUjfnvfVhMve4t9gTAnkvFtCefgTvJHJYLfH0pKoM4CgMFn013eZ/BuTpQdaaySvKgM3Mcw2mW9LZWR1Nvn9nfVD1GvNTvJXuCtgsIL8y9umCHVqhfibdfJ7rQAen3tBn/L0wTXsv4b3L5Iy4eDPLBT+UU9rHv4MUHU25fsTEA6tOalLKzYriptT4r3Ha57k1XSaESt1qHD8yzDSqrTti6+vJhX3KMvb0q6UfbqGRcnZjDWMa1Ax1zAZfrdtzkgS7LScd33SivG9wv14/B9i+CwG/STU6XczHr9gp9+Sjv7ODa9DPkXya7yX3dZ0GFSt/+pK1fFfjMcF8ffHQFLVr7GPhhVjAwe6asPcWCpRft2wUvQcuRrBMBEhA0JO3dcQIfz1RuuBR93Jj/oSTvxtYs19R1ik6rP/CmR4RAH3WDpF8nu9qTCxuhr0490Ckz6t15omnPy2lK625YZSU83Oi8XRLV0Skymy6DRwwbvIFJ4ByIuN5BCgCTiRG65tZ51bA6tM0dq66LpKry2A5NxdLIkCamnNdj8Y3I7snWkQlyXamrcHwP2uTxd0itnmq7Yw7JXbJ8mOmUDb9f1DeJ1WEWeY0GVjeDdop569IHgjEiH2Fel/vKdKBF29dfbzctVejW7a5NecDj2vKq2IHqqJGtJEZMGvsGC/FxASXvbmgr1g3yFMfudh7q85Dj7QaSo5/MqLL4iCv9LDZUlQDi84zDJrzVlu6ePYYW9mTUbSxX+9z/DNFVLUj39yrHnAVRh/XzdzP17McSWM6zmcdtCdfzE5Bx3fIq7hl1N0ys+vv4cLMjtsrej1Q34S6vTMjMcv2OmZE/yOvpx4p/a4D8BHSQcFwB8InALJ7/C+H9M28vux46+qz5Yd561jNvp3Cznv5m92GORGxi0i6D6p+Vf9AK158MxGgj8TAeXfHnCMO0SdgnEfgI+SDgqAPxAJBifir7F4FYs5FoUav89D+QMBvygHPOkxjiwQ5UQ6DHg94xKSzfJrfO1CdMKfkA7+y+yPauc7laFCTjEXx7H9CoVgFH876xyuH8nGjGHsok240GVjeDc4EX+CNxIjFPcB+CjpoAD4A4FTAH/GsG0AsmtkEaMl29Xh4uuYTcG+I2yOzEbzTJ6dd7xWiL83WPo4dhhCadf3yCpHxzESIrGf9dPNSif8HfAmgRgbZ31gi7OUV8piTxanlDjWlAvj7z07iU7G0UAMLuX6D9UXpZAb9sg3s8n192x4ZeNLSjgzaacq5+hvHH8n5YwNf86dfjvj8Qt2mseP/iZf+oCEl2Kut/0g6KdqJeAPnDcbTzjhz/Q1BGXrinRJTx8DCqUfAf50B1n8/cVOuht77TGds7OWxHSeXTZ4ddVG3qhMeOyIv9yNE6K/yZc+IOGlmJPUakF3dUrAHzjbO76aAn/hGRA9+QeU1MQ0kqiQ+Esa2ZBqv5gDgcl/T6T3xRrWaQ8JuyKLCgILK6PZyTsb/tjojIv+xpEUuAcQoxR0Unru1JoCSfLrH1oniL8NdvyRalz0xy2YhAlddmr8Cd7IxHWbRNsK7/0qotSbNwB/4FTo1YL4o1wzKKBnt24bR7qvBZVejngFhW/t4YK71eLcCvH3Jiu/V/LJbBcTEALpZAENeegM4AT8QSDGTX4djLrSnFbwEwmv1qTuKZ0R/pg14pCC5rTv88k03GdXD7Oke//r+mPlbV98KSepd/C/klX1UWRVQS76vipJzrL4w0k6dbz+x+yU3O6iNu76kKcLdjrz8U9S82N2vjKuqO3wyVT3yeb++FHeo74vDMZMIGCxJtPSZPd/weGPUGlzlfXg2EDS1YN/JfM4+fE0+nOLDWzrO2C6Sqb5jtjm/pyc3Ixe2iddfQfabrIVMqOfCuHvqS6InWSMejCw70bmxsnm/vhRnsTQkKP+BQhobMg8pb/BYdEghD/CgsidtY0SU43/Hm4xQaIi83Rr0y5EmUyhOWRCzU/VSifvVn9+LrLORCfXXA5d56bhQpQRdaZwdurQnczNZZOah0jz8DwyYef6TeUkThZkjWRIa8l1cmOEoj+XCHr9/bbrj+NP8LKyKfEneCNTL3EMaSW3b2cBARVVN+/U/NPmt5FLHwogE6f4t1TGvCghs8Ah8oBuTbT1Bx8ob0oJ5SYEFWGAPPK3Lgt85dgK8fdGG1/MsRB5+eeQ1VJV7ad03YBdT4CPuisffx+ydQoKgtbYfgdtjhNd65lQczL82ScuMmLLybbq2GD7dcS+wRDvx0WR0En16Yes88O4Hf5kMIcFO3UizkV28YS/dCvY6azGL9jpRXYVhQ2RXdn5ymNT4+/50BFa5guc3NyfNVJm6+KjWG8ZcGnvJxzp/sb5ZdmRY2MKQSdcoa3I375G+dHekN+HFWP1QLp1TskvyZcLbI03rmMnGQ9Ojb+4pnsc8ngCpw1/pWttdJDWFtiztVURia7rGWb3OfBHnE+3/6W429Zzwelir7w7V9wCKMmm+SP3XDOu0poiFoW21eQLMZM42eb+FGRRl47Q9RAB/G2xXT+tQOLYSrgv3g2ylXew+OMKgjcyNf7+1xRHy3yB08aL6HyRCyUdWds9673JdvFtu/z6LFGnIO1d50FDwr6zHtx6iGMrxN+87fub8oWHL4ub00o7js+wPreFsEOpaksrdXiN5Hip43WuFPw9+GAUN6/XkbSZv4oybadchWk7nc34BWuyTtWMN7gM9H7BZx/86AidI0/7Djx9fMTuYUm3zvRY8cfAAZIUT+60TSAeeuR4hcnf9yA1/5jxBhep3shnH/w4+WaO9pg6U0zjhJWHltZo8LcIOSdUFrgCV7Nreue0+wobu6SmKVvN8rJT3MhkG1we3pXy2Qc/Or/CYZS8Gt/TJxnSRI8Yp3+jw6EV4u+t42+WmvkLJKpaEZt9+x448Xc2BnQ/3fzWO513TVzigHAPEl6QPe6bQk9rIer9i3pgeue8a+ISB4kBDSQRHo/7lpre2mshb7K9GcI9SHhBvLhveQrxZ4OaOelAxqdXZvb6cJEqNl7+QbD4/dgTn15sPv5uOl1U+PujO/ZMdljX4+mdiL8ZvRSsLfZJOx3ZiPhD/C0E/laanPB3r+PET9VKkMGYKZT8LiI54e+0peKuTgnKUf8yXfKLmh5/Wn1u6s0boNu3swSTX8Qf4m9Z4Q/CPbrxBQQFp6WPxYw/CPfoxhcQFJyXPlCzxB+Ee3TjCwgKE5Y+EH+Iv+WCP7rtGfA3cF9B2XftLpHTxpdFiD+67Rnwt9dYT9nXalaAnDe+oGaGP7rtGfA3oNtL2SevvANy3vhiU8u3XjKRu6rC5tdEFKZ7HZW5HZX7VJdxu1teaUSFCq+ju9wyFP5WvdMhCJF5MtfklMAReuxK2c58pW9Bth+R0rf0WhRbTdqS75chc0uWef18TQyewWuB49XYmgVnw8lyikZUoPBI3uV2NMXXUClB/KGmV7H5eLX+KyBgV9uRu+YTFH/gXAwnvkyDvy7Fj3cLgIBJavUVwyWKP/L+r8CJL6jplagzXL11FgjYVZVYWPM9xV8iOe9+wlsflFYl/nS/C/cihz5M7PD+B5NfFPPaGC5z8Nm2QLOqTmGPnvD0oW/FsTuo+W9WhQL7VCkOzrxr0YYUF8bZvIb0Th2tUtVIEX+oaVTewWW7fAm/9LbI9OyhgiKPL+GX3lAz0B5LC0UeX8IvvTVLDNnj74BS/HXnsns6Pb2sGnHhLsKsbSmhfflste0+3TXhR9lTYbJs5/2NFPlw7T192OhPwh4J43JU4Zuv9Dml8Cq8LH5dE8QS1qWwRGxQrqVM7Lvsf0rhk5fuk690t20sFY1cYzfNbvfuM0b/vIvwMSNfjPhDTa9fjA7sm+zIg0WoXqsD+yY98gA1w/xXo+Ozb9IjD/Shm3iBFsWf9ay3ePvqjG8jyeY+Fm0hirChsrBCpU9pCaSiUnrgFYc/S0Syvf12Fn+WCJaPLoVFkd0VYro3cDCfbJneJAsYaZYOloVVXw7v5p0W86LIlzaH4JHiL4Q9WkYjJ/BNZkeC+EPNKAac9sCrRRsDTnfgFWp2MeC0B169NoqydnkZasT5wbzkd1xRp7YTv1hpO9dPHyajBwJ6eg2yHhVLKLHcI8TGr9eandscste11ZVSg2I137VN5NM3njtHZbG4/LmCJrli9kdmk+cqFs2uZj3O/aHmbz/gUhHi723vB7QpJm/7BPxZxHnBztN8L0r8tjF0wm71zyUxQ9fYtFfk/6o5gkzYbfd9QWYS/QBbm7Z7qK6F5rG5MxPsp09fSyfysnIDTolWsZFgEA0M6YFam2SBNiLT4JFh1nEdlVZIEH8oxB/qbeEv3wl/RhHHIMbNoHFGTB+byTIiv9Pbac7rniXj6CaT+VqNvMoadsrP0+d2+mrKQfbEBDY89PQe4nWdV8StL7ewM4MhKTvJLCT7ljGzK/AV4g+F+EO9E/yxJx0QQnnYWdbCrpAcZafhhi57sX/qnes5YeWWcSk55yP2dJGlh5G9MmV+tGYnPTOVIq8mcJO9bAwnq8zrPPpsg6FpMk236cyjbUUF8YdC/KHecvJrzR0/93QTGwOGpIdxC7KMi0zmSldLknMjXuijhzTRQ/qYkcqgEHZCsFsvfUGRxzAyuQf95hByXpZFRLezbAt2E3sy9nPzuYlCHuAGKVsZl2S5RwjbXJwdgckvCvGHemvRX7Btf1+zpHCX83a8EBLKSTW8LTLJ6TtfOH71pdi+8tssNed62BeUxba90C8qgrhlE7igzH+Qt2mGrvPaJDVke4x3LQ8Ywm3PKMQf6q3hb+ZfcRnDHoc1k5oSNjB02rEsHSFOyZs2R/yhEH+ohcIfvvOL+EP8If4Qf4g/xB/iD/GH+EP8If4Qf4i/RY+/DpVsmePPKEf8oRB/qAn409dbb+8H/D3WLNsTT0caFBR/o6OjiD8U4g9lOwhLb7xXcxLwN6hettHfk9bvKP7GxsYQfyjEH4pTQr25sb68QyX5vTr+z6ZlyL4/m+Mf9Bgo/l6+fIn4QyH+UDb8mZubmpqaNRd6q/c80ScuMwIC+550lVD2DQ4OzpFaiD/EH+JvueGvs7PTbDZ3NFf3N5x5oFM8qZOPGBKe1S9lGeUjDQrIee1xH9jz588RfyjEH8oBf4CGtrY2q9Xav3xteHh47tRC/CH+EH/LEH80NwRbfuCDm5p73If4Q/wtFvzJEH/zJ7mlhb8n7uXLl2NjY6Ojo8+WuMEtwI3Mca0D8Yf4W1z6d3fa/jtq8k3nBhPCa+5SNLXOy5bglWCIP8TfAutBT+pJtZZEf/p6hNfc9V1bB+IP8Yf4Wxp61JdaXm8E/MWrtbK2TuTXXBTf3mXo/R3xh/hD/C0NDQ+mNjU1XdDp96i1iUYLEnAu7Cvp6bUvESD+EH+IvyWAP7pPrbql9YylWaEz7NMa9upA9StR+vpEvTGh3pxgbnZWvRn+CCo4Nflcb0ytN55paFS33rPabHBwcJEsLyD+UIi/qfBH96mVmy3Z2rr9d9R0IXgFCm58f7X6pFpbXm+EiBh+K9A4rqftjvVutvX2fnqUy7TqqZT11ybNWup9/VpFf8OZ/i79PG4uQfyhEH/T4O+HBktctVpaXStZqexz0gWdHiJi+K3QbfqhYwbI43RL2lu9503Y58DBvf0t1+drazHiD4X4mwp/d9qtZOmjVpOkrUvQ1snqjFKDKa6+YQWK3Li+Pl6t3aPWVre03mso77wV11sVD/q9On5QHfdYIx3Sxk3UE51suC5+ju+WjRgSnugTHqhZAnbp5+XFMsQfCvE3Ff4g56X4w6UPTm2d8CjOWJoh54WADiKyd3l4AXQE3ZEseD6OFUD8oRB/U218odueceOLEwEVWgM9uLS/JuEdH9wC3T3QKeblUCnEHwrxN9W2Z+6lN962Z4m2MqKufWpASGuuuu8+FtHoXH8mbedR4sJc1x1bXbYkht3ixiOtKbAPbC7apzXQtY6Hd8fB9KImwjr7Y5zfoNWTOvm8HCmK+EMh/qZ66Y1O9o+/9NZYupphPAqneQcupiSTYdaHmhzrz6zt/KnOi4FRRHql5X58nRtPTNExbmBz/dYOA13QGD+23hgewjAZl6Nnh783ajViSJiXA+URfyjE32xOfGkhCPMuaZ0pKfj1Z9t2rqp0ndAdy+UtYfOAvwnf2WYhIDtVJJnl15a/Sav5+jY1xB8K8Tdz/DX6wYeVNbd/fu++foPXJQ3xm0rd1m/wyKtkQ7wKKPucy/mv9THhJl79nGJeuQJqRpedW7ueOjZ4nyceierc6vVb14ZsBZcrW4dLmYnf3213KK3tnlMsnVA5qui0/WpeeaVkGFxvzNqMUknFaXY8DvibOIA54C+mIJjrLjlbBJ6hkgDxOupwOXUWPNJS+WrG092gJ/yyfuvBMKt/rtjl1Arxh/hD/C2Mnj1U9HcRQWGy6E9cmE1wk3EhQttAcBZxDkgUXXiEfIJDciUQXhWlM8zWoMuQY26BHJNXv5VfltZecGGYVXuyRbU1O3MSwe91qS6mRMmiINY3I92/xMQL2Vj/+sTQKk3YN/uh6HFRw6+8Pe8rgpnd2aKqyqCMWILI87ciLpEKbicKRFWNMSXceOz4ExzAZLDbY2lJ1BlAUJgs+uu77AsXkaUHWmskryoDNzHMNplvS2VkdbY7+LN+iHqt2Un4vytgsCIA/r9NEerUCvGH+EP8LYyuNxUmVleDfrxbYNKn9VrTpk1+xeeBGqER7V2hn29lSRQpImXCwV32IGuS5Dc8wx8oGVhlitbWRddVem2hrQiwAqomziQSf2At/bHdP8S5clgaDCAxkqvfHhABrEyP4XVnp569IDgAiRD7ivQ/3lMlgq7eOvt5uWqvRjdt8mtOh55XlVZED9VEDWkisjwZJtjvBYSEl725YC/YdwiTX8Qf4m+RxH0APko6KAD+QCQYnIi/xuJVwJQiNjSruwoBlF9JKSRyXufPrWUY36JiKLud14znmPz6vLIoJ5Lh23rGJSRbTIjmH9YojL+dddyPohP+QLdIXuVw8DD7o9r5FZQxvO4m4k9wADFCcR+Aj5IOCoA/EDgF8GcM2wYgu0YWMVqyXR0uvo7ZFOw7wubIeZ7EkWfnHa8V4g/xh/hbiDm+LgX3RletFnRXpwT8gbO94ytB/Plw6wmNvjsAHBsAQ+GNjf7c1J5/aF2XE/64+rwyG6/F2uK1rsiigsDCymhCtK0T1yVY/G2w4y9wtz364yqzVxvHX+AeZlr8CQ5AOvGbeW0rvPeriFJv3gD8gVOhVwvij3LNoICe3bpttOq+FlR6OeIVFL51txHR3WpxboX4Q/wh/hZ4iUNiaMhR/wIENDZkntLf4LBosOHPdB0+2WsPnRbVNhJq5JGJNmaHEtLGCBpP0RlAO/749XllSVku1F39+bnIOhOdpHM5dD1mKvwxLhHKiDpTeB6Z+3Pn5v64yjElZFZx9aELUSaugus3lbIp8Sc4gKmXOIa0ktu3s4CAiqqbd2r+afPbyKUPBZCJU/xbKmNelPiRJyEP6NZEW3/wgfKmlFBuQlARBsgjvylkga8cWyH+EH+IvwXGX1zTvYkv+YPTRgSTb8SGcVhoCwjRTpSSrc6q0+yaQw1Zqy0DHu1g2cSv79A24ny6iy0WWrU7V9xCW/lPir8tXGXXtAJJu3NlUd4Re6659tCFGHab4Vob/uzjYUFJByYwgKnx97+muIkHGYDTRqXofJELJR1Z2z3rvcl28W27/PosUacg7V3nQUPCvrMe3HqIYyvEH+IP8bfAG1ykeiOfffCjExQkja3S2WwT4dd3aNvSGl1nimlsn24TtZLNr7ukJqg8xR5DerXZ7OCbbgBOc3wP70r57IMfnV/hMEpeje/pkwxpokeM07/R4dAK8Yf4Q/wt7PZmEgMaSCLMi/sWTOxmmg1zf1VjXrY3Q7gHCS+IF/e9ayH+EH+Iv5WCP6m22CftdGQj4g/xh/hD/L1l/J22VNzVKUE56l8Ek9+VIyf8afW5qTdvgG7fzhJMfhF/iD/U0l76oBtfQFCYsPSxcvEH4R7d+AKCwoSlD8Qf4g+1NPFHtz0D/vYa6yn7Ws0KkPPGl5WHP7rtGfA3oNtL2SevvANy2vjyqjI0S+aWkR70AvGH+EMtrW3PP94tAAImqdVXDJco/sj7vxPf+lhhStQZrt46CwTsqkosrPme4i+R/a47pznBkWte7C4XryHEH+IPtbReeqPI40v4pbcVpj2WFoo8voRferNEGX7YqSkRz4Rfr4zSV4g/xB/ib5Go1+rAvkmPPFiB+a9Gx2ffZEcevKgIlG1fLZYHjFDA1YRliVZz255FXoYabpFk8Jq/7SCsVafyIxB/iCESqGQAAAU2SURBVD/E35I58GrFxoDTHng1co283MZ4+pDkVx8mpojzXCv25F5FMesBkf70BECZzJ2+IX1qtqdDI/4Qf4i/BTvtGTUZ/oo4/EH0Z80lZ61uEvnRU14K2dfaxMpwAzkIiwlJIcsj3ex7b/QgLMQf4g/xh/hbJvgzp68lZxpkc7lti5L8GKIIo37Hs7C8hxB/iD/EH+Jv2eCPnve3aVcAu74hLZWtIvhLDzco2OhPsXPEIukrCsrP9lddi3iF+EP8If4Qf8sGf69rgjZxix7uR0Wr2OJqjcZ+2vOqLKVvMjsnOKuDXhB/iD/EH+JvMeLvRQn51g5muw9d+R0qsq/wQobrqirjjvNr+dbLnviG7PIbxJVfxB/iD/G3pPH3Si9WKdmvlvN0mMt7oY8e0kw4x9QSM8ODsBB/iD/EH+JvsePPkMIdnLpJFoTv/CL+UIi/lYS/XO/kXW5HU/y6jXjkAeIPhfhbYXN/eOIL4g+F+Fsp+OtQyRYMf0Y54g/xh/hD/C0Q/vT11tv7AX+PNQtw4ulIg4Lib3R0FPGH+EP8If7e7UFYeuO9mpOAv0H1AkR/T1q/o/gbGxtD/CH+EH+Iv3eqhHpzY315h0rye3X8n03vlH1/Nsc/6DFQ/L18+RLxh/hD/CH+3i3+zM1NTU3Nmgu91Xue6BPfGQGBfU+6Sij7BgcHXy9fQ/wh/hB/ixd/nZ2dZrO5o7m6v+HMA53iSZ18xJDwrP7tyCgfaVBAzmuP+8CeP3+O+EP8If4QfwuAPwBQW1ub1WrtXwgbHh5+vawN8Yf4Q/wtavzRDBTsXYIPulvecR/iD/G3WPAnQ/wJSW5p4e+8e/ny5djY2Ojo6LO3ZnBx6GIZr3Ug/hB/i0v/7k7bf0dNvuncYELk8aVoal32G48Rf6gVjb8HPakn1VoS/enrEXl8fdfWgfhD/KGWM/4e9aWW1xsBf/FqraytE6lHFd/eZej9HfGH+EMtZ/wND6Y2NTVd0On3qLWJRgsSkLKvpKfXvhCB+EP8oZYt/ujutuqW1jOWZkV9g9zUmNDQlGBuXmmSW1oUza2Q89rjvmW/8w7xh1rp+FvY3W2L2Zb9zjvEHwrxtzC72xazrZCdd4g/1Pzgr73p0NLEX/o73t22mG2l7bxD/KHmA38WZXtzOuDv4f1DSwt/TwdO4gQ/GuIPNRf8ZbY2fgv4e9CzxPA3NFCA+END/KHeXKUtmY3mW+1NKb3th/8zumTY95/R1Af9DYg/NMQf6s0Fj52cDWe51N125HF/6pIgILBv6OFN3N2GhvhDzRV/3Nlw7eq+nov/7sl63H/s6UDq8OAiVPrw4EnIee1xH+5uQ0P8oeaEv6W7ew53t6Eh/lBzxd+S2z2Hu9vQlgn+fjV/hfhbKFVYs5bQ7jnc3Ya2rPAH/6DLG08B/n5ry0QYLYA6vsYFBDS0hcEf/DJX37sE+CtrRfwtgOp6ChF/aGgLgz9IZNp7G0rMyhJz5u37SMB3rY7fzYg/NLSFwR/Y4OCgsaMcCFjWqkQCvks191Xi7jk0tIXE3/Pnz+HjBzEgZME3m0/9du/Eb21kJQT1NlRhzars/AZyXnvch7vn0NAWDH9gw8PDeFQR7p5DQ1uJ+KMxIJ7ahrvn0NBWIv6orfBT23D3HBraysUfGhoaGuIPDQ0NDfGHhoaGhvhDQ0NDQ/yhoaGhIf7Q0NDQEH9oaGhoiD80NDQ0xB8aGhoa4g8NDQ0N8YeGhoaG+ENDQ0ND/KGhoaEh/tDQ0NAQf2hoaGiIPzQ0tJVs/x8Xr6boMQqPwwAAAABJRU5ErkJggg==
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/edit/htdocs/home.png b/sca-cpp/trunk/modules/edit/htdocs/home/home.png Binary files differindex 8f5a0b0d86..8f5a0b0d86 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/home.png +++ b/sca-cpp/trunk/modules/edit/htdocs/home/home.png diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/oops.html b/sca-cpp/trunk/modules/edit/htdocs/home/index.html index e85c40c172..686bc67d4a 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/public/oops.html +++ b/sca-cpp/trunk/modules/edit/htdocs/home/index.html @@ -17,48 +17,47 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> -<head> -<title>Oops</title> -<meta name="viewport" content="width=device-width user-scalable=no initial-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="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> <div id="bodydiv" class="bodydiv"> -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menu"></div> - <table style="width: 100%;"> <tr><td><h2><span id="h1"></span></h2></td></tr> </table> <div style="margin-left: auto; margin-right: auto; text-align: center;"> -<div class="hd2">Oops, something went wrong...</div> + +<div id="maintitle" style="font-size: 150%;"></div> + +<div id="maindiagram"><div id="diagram" style="width: 320px; height: 280px; padding: 0px; margin: 0px auto;"></div></div> + +<input type="button" class="greenbutton" style="font-size: 150%; font-weight: bold; font-style: italic; padding: 10px;" id="getstarted" title="Get Started" value="Get Started"/> + +<br/><br/> +<div>Requires Safari 5+, Chrome 11+, Firefox 4+, IE 9+</div> + </div> <script type="text/javascript"> -ui.initbody(); -// Set page title -$('h1').innerHTML = hometitle(window.location.hostname); +// Set page titles +document.title = ui.windowtitle(location.hostname); +$('h1').innerHTML = ui.hometitle(location.hostname); + +$('maintitle').innerHTML = isNil(config.maintitle)? 'Simple App Builder' : config.maintitle; +$('getstarted').onclick = function() { + return ui.navigate('/#view=store', '_view'); +}; + +// Display the main diagram +var diagram = $('diagram'); +diagram.style.background = 'url(\'' + ui.b64img(appcache.get('/home/home.b64')) + '\')'; +var bgpos = 0; +setInterval(function() { + bgpos = bgpos -280; + if (bgpos == -2800) + bgpos = 0; + diagram.style.backgroundPosition = '0px ' + ui.pixpos(bgpos); +}, 2000); -// Load the menu bar -if (!issubdomain(window.location.hostname)) - displaymenu(); </script> -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> - </div> -</body> -</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/index.html b/sca-cpp/trunk/modules/edit/htdocs/index.html index 3bc871d47b..bba70baa61 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/index.html @@ -19,78 +19,417 @@ --> <html manifest="/cache-manifest.cmf"> <head> -<title>Home</title> +<title></title> <meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> +<base href="/"/> +<script type="text/javascript"> + +window.appcache = {}; + +/** + * Get and cache a resource. + */ +appcache.get = function(uri) { + var h = uri.indexOf('#'); + var u = h == -1? uri : uri.substring(0, h); + + // Get resource from local storage first + var item = localStorage.getItem(u); + if (item != null && item != '') + return item; + + // Get resource from network + var http = new XMLHttpRequest(); + http.open("GET", u, false); + http.send(null); + if (http.status == 200) { + if (http.getResponseHeader("X-Login") != null) { + if (log) log('http err', u, 'X-Login'); + return null; + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + if (log) log('http err', u, 'No-Content'); + return null; + } + localStorage.setItem(u, http.responseText); + return http.responseText; + } + if (log) log('http err', u, http.status, http.statusText); + return null; +}; + +// Load Javascript and CSS +(function() { + var bootjs = document.createElement('script'); + bootjs.type = 'text/javascript'; + bootjs.text = appcache.get('/all-min.js'); + document.head.appendChild(bootjs); + document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css'))); +})(); + +</script> </head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> -<div id="bodydiv" class="bodydiv"> +<body class="delayed" onload="onload();"> +<div id="mainbodydiv" class="mainbodydiv" style="overflow: visible;"> <div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> +<script type="text/javascript"> +(function() { +$('headdiv').appendChild(ui.declareScript(appcache.get('/headconfig.js'))); +})(); +</script> +</div> + +<div id="menubackground" style="position: absolute; top: 0px; left: 0px; z-index: -1; width: 100%; visibility: hidden;"> +<table cellpadding="0" cellspacing="0" width="100%" class="tbar"><tr><td class="dtbar"> +<table border="0" cellspacing="0" cellpadding="0"><tr><td class="ltbar"><span class="tbarsmenu">> </span></td></tr></table> +</td></tr></table> </div> <div id="menu"></div> -<table style="width: 100%;"> -<tr><td><h2><span id="h1"></span></h2></td></tr> -</table> +<div id="content" class="bodydiv" style="overflow: visible;"> +<div id="viewcontainer"></div> +</div> + +<script type="text/javascript"> -<div style="margin-left: auto; margin-right: auto; text-align: center;"> +// Set page titles +document.title = ui.windowtitle(location.hostname); -<div id="maintitle" style="font-size: 150%;"></div> +// Init div variables +var bdiv = $('mainbodydiv'); +var mdiv = $('menu'); +var cdiv = $('content'); +var mbgdiv = $('menubackground'); +mbgdiv.style.top = ui.pixpos(mdiv.offsetTop); +var vcontainer = $('viewcontainer'); +vcontainer.className = ui.isMobile()? 'viewcontainer3dm' : 'viewcontainer3d'; -<div id="maindiagram"><div id="diagram" style="width: 320px; height: 280px; background: url(home.png); padding: 0px; margin: 0px auto;"></div></div> +/** + * Pre-fetch app resources. + */ +var appresources = [ + ['/all-min.js'], + ['/ui-min.css'], + ['/account/', 'flip'], + ['/clone/', 'flip'], + ['/create/', 'flip'], + ['/footconfig.js'], + ['/graph/', 'flip'], + ['/headconfig.js'], + ['/home/', 'right'], + ['/home/home.b64'], + ['/page/', 'flip'], + ['/public/app.b64'], + ['/public/grid72.b64'], + ['/public/iframe.html'], + ['/public/img.b64'], + ['/public/user.b64'], + ['/stats/', 'flip'], + ['/store/', 'left'] +]; -<input type="button" class="greenbutton" style="font-size: 150%; font-weight: bold; font-style: italic; padding: 10px;" id="getstarted" title="Get Started" value="Get Started"/> +/** + * Handle application cache events. + */ +applicationCache.addEventListener('checking', function(e) { + //log('appcache checking', e); +}, false); +applicationCache.addEventListener('error', function(e) { + //log('appcache error', e); +}, false); +applicationCache.addEventListener('noupdate', function(e) { + //log('appcache noupdate', e); +}, false); +applicationCache.addEventListener('downloading', function(e) { + //log('appcache downloading', e); +}, false); +applicationCache.addEventListener('progress', function(e) { + //log('appcache progress', e); +}, false); +applicationCache.addEventListener('updateready', function(e) { + //log('appcache updateready', e); + applicationCache.swapCache(); + //log('appcache swapped', e); +}, false); +applicationCache.addEventListener('cached', function(e) { + //log('appcache cached', e); + map(function(res) { + appcache.get(res[0]); + }, appresources); +}, false); -<br/><br/> -<div>Requires Safari 5+, Chrome 11+, Firefox 4+, IE 9+</div> +/** + * Handle network offline/online events. + */ +window.addEventListener('offline', function(e) { + //log('going offline'); +}, false); +window.addEventListener('online', function(e) { + //log('going online'); +}, false); -</div> +//log(navigator.onLine? 'online' : 'offline'); -<script type="text/javascript"> +/** + * Handle view transitions. + */ -// On mobile devices, redirect to the last visited page -if (ui.isMobile() && (document.referrer == null || document.referrer == '')) { - var last = ui.lastvisited(); - if (!isNil(last) && last != document.location) - window.open(last, '_self'); +// Keep track of the current view url and uri +var viewurl = ''; +var viewuri = ''; +var viewidx = ''; +var viewdiv; + +/** + * Record which transitions should be applied to each resource. + */ +var apptransitions = {}; +map(function(res) { + if (res.length > 1) + apptransitions[res[0]] = res[1]; +}, appresources); + +/** + * Return the transition that should be applied to a resource. + */ +function viewtransition(uri) { + var t = apptransitions[uri]; + return isNil(t)? 'left' : t; } -// Init and display this page -ui.initbody(); +/** + * Create a new view div. + */ +function mkviewdiv(cname) { + var vdiv = document.createElement('div'); + vdiv.className = cname; + if (!ui.isMobile()) + return vdiv; -// Set page titles -document.title = windowtitle(window.location.hostname); -$('h1').innerHTML = hometitle(window.location.hostname); + // Handle view transition end + function viewdivtransitionend(e) { + if (e.target.className == 'leftviewunloaded3dm' || e.target.className == 'rightviewunloaded3dm' || e.target.className == 'flipviewunloaded3dm') + e.target.parentNode.removeChild(e.target); + } + vdiv.addEventListener('webkitTransitionEnd', viewdivtransitionend, false); + vdiv.addEventListener('transitionend', viewdivtransitionend, false); + return vdiv; +} + +/** + * Return the last visited location. + */ +function lastvisited() { + var loc = localStorage.getItem('ui.lastvisited') + if (!isNil(loc)) + return loc; + return '' + location; +} + +/** + * Build and show the menu bar. + */ +function showmenu(mdiv, view, appname) { + mdiv.innerHTML = ui.menubar( + append(mklist(ui.menu('Home', '/', '_view', view == 'home'), ui.menu('Store', '/#view=store', '_view', view === 'store')), + (isNil(appname) || appname == 'undefined')? + mklist() : + mklist( + ui.menu('Stats', '/#view=stats&app=' + appname, '_view', view == 'stats'), + ui.menu('Page', '/#view=page&app=' + appname, '_view', view == 'page'), + ui.menu(isNil(config.compose)? 'Composition' : config.compose, '/#view=graph&app=' + appname, '_view', view == 'graph'))), + mklist(ui.menu('Account', '/#view=account', '_view', view == 'account'), ui.menu('Sign out', '/logout/', '_self', false))); +} + +/** + * Show a view. + */ +function showview(url) { + //log('showview', url); + + // Save last visited location + localStorage.setItem('ui.lastvisited', url); + + // Determine the view to show + var params = ui.fragmentParams(url); + var view = isNil(params['view'])? 'home' : params['view'];; + var uri = '/' + view + '/'; + var idx = isNil(params['idx'])? '1' : params['idx']; -// Display the menu bar -displaymenu(); + // Determine the transition to use + var vt = viewtransition(uri); + var ovt = viewtransition(viewuri); + var vtransition; + if (ovt == 'flip') + vtransition = 'flip'; + else if (uri == viewuri && (vt == 'left' || vt == 'right')) + vtransition = idx >= viewidx? 'left' : 'right'; + else + vtransition = vt; -$('maintitle').innerHTML = isNil(config.maintitle)? 'Simple App Builder' : config.maintitle; -$('getstarted').onclick = function() { - return ui.navigate('/store/', '_self'); + // Track current view url and uri + viewurl = url; + viewuri = uri; + viewidx = idx; + + // Show the menu bar + var appname = params['app']; + showmenu(mdiv, view, appname); + cdiv.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); + + // Scroll to the top and hide the address bar + window.scrollTo(0, 0); + + // Compute the viewport size + var iswide = view == 'graph' || view == 'page'; + var vwidth = iswide? '2500px' : '100%'; + mbgdiv.style.visibility = iswide? 'visible' : 'hidden'; + mbgdiv.style.width = vwidth; + + // Start to unload the front view and create a new view + if (ui.isMobile()) { + // Prepare current view for transition out + var ovdiv = viewdiv; + if (!isNil(ovdiv)) { + ovdiv.skipNode = true; + ovdiv.className = 'viewunloading3dm'; + } + + // Load the requested doc into a new view + var vdiv = mkviewdiv(vtransition + 'viewloading3dm'); + vcontainer.appendChild(vdiv); + var vdoc = appcache.get(uri); + vdiv.innerHTML = vdoc; + map(ui.evalScript, ui.innerScripts(vdiv)); + + // Show the document + if (document.body.style.visibility != 'visible') + document.body.style.visibility = 'visible'; + + setTimeout(function() { + // Transition the old view out + if (!isNil(ovdiv)) + ovdiv.className = vtransition + 'viewunloaded3dm'; + + // Transition the new view in + vdiv.className = 'viewloaded3dm'; + }, 0); + } else { + // Prepare current view for transition out + var ovdiv = viewdiv; + if (!isNil(ovdiv)) + ovdiv.skipNode = true; + + // Load the requested doc into the view + var vdiv = mkviewdiv('viewloading3d'); + vcontainer.appendChild(vdiv); + var vdoc = appcache.get(uri); + vdiv.innerHTML = vdoc; + map(ui.evalScript, ui.innerScripts(vdiv)); + + // Show the document + if (document.body.style.visibility != 'visible') + document.body.style.visibility = 'visible'; + + setTimeout(function() { + // Transition the new view in + vdiv.className = 'viewloaded3d'; + + // Transition the old view out + if (!isNil(ovdiv)) + ovdiv.parentNode.removeChild(ovdiv); + }, 0); + } + + // Track the current visible view + viewdiv = vdiv; + + return true; +} + +/** + * Handle navigations. + */ +window.onnavigate = function(url) { + //log('onnavigate', url); + + // Add url to the history + if (url != ui.pathandparams(location)) { + history.pushState(null, null, url); + var f = ui.fragment(url); + if (f != '' && f != location.hash) { + location.hash = f; + //log('hash', f); + } + //log('pushstate', history.length); + } + + // Show the specified view + if (url == viewurl) + return true; + return showview(url); }; -// Display the main diagram -var diagram = $('diagram'); -var bgpos = 0; -setInterval(function() { - bgpos = bgpos -280; - if (bgpos == -2800) - bgpos = 0; - diagram.style.backgroundPosition = '0px ' + ui.pixpos(bgpos); -}, 2000); +/** + * Handle history. + */ +window.addEventListener('popstate', function(e) { + //log('popstate', history.length); + var furl = ui.fragment(location); + var url = location.pathname + (furl == ''? '' : '#' + furl); + + // Show the current view + if (url == viewurl) + return true; + return showview(url); + +}, false); + +window.addEventListener('hashchange', function(e) { + //log('onhashchange'); + var furl = ui.fragment(location); + var url = location.pathname + (furl == ''? '' : '#' + furl); + + // Show the current view + if (url == viewurl) + return true; + return showview(url); + +}, false); + +/** + * Document load post processing. + */ +function onload() { + //log('onload', history.length); + var furl = ui.fragment(location); + url = location.pathname + (furl == ''? '' : '#' + furl); + + // Show the current view + if (url == viewurl) + return true; + return showview(url); +} + +// Show the last visited view +//if (ui.isMobile() && (document.referrer == null || document.referrer == '')) { + //log('show lastvisited'); + //showview(lastvisited()); +//} else + //showview('/'); + </script> <div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> +<script type="text/javascript"> +(function() { +$('footdiv').appendChild(ui.declareScript(appcache.get('/footconfig.js'))); +})(); +</script> </div> </div> diff --git a/sca-cpp/trunk/modules/edit/htdocs/login/index.html b/sca-cpp/trunk/modules/edit/htdocs/login/index.html index e51a6ac2ae..2968e9ee2e 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/login/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/login/index.html @@ -17,17 +17,17 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> +<html> <head> <title>Sign in</title> <meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> +<base href="/login/"/> <link rel="stylesheet" type="text/css" href="/ui-min.css"/> <script type="text/javascript" src="/all-min.js"></script> </head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> +<body class="delayed" onload="onload();"> <div id="bodydiv" class="bodydiv"> <h1>Sign in</h1> @@ -44,8 +44,6 @@ </form> <script type="text/javascript"> -ui.initbody(); - function queryParams() { qp = new Array(); qs = window.location.search.substring(1).split('&'); @@ -71,11 +69,22 @@ function oauthReferrer() { } function submitSignin() { - var reset = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';domain=.' + domainname(window.location.hostname) + ';path=/;secure=TRUE'; + var reset = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';domain=.' + domainname(window.location.hostname) + ';path=/'; document.cookie = reset; document.formSignin.httpd_location.value = oauthReferrer(); document.formSignin.submit(); } + +function onload() { + // Show the page + document.body.style.visibility = 'visible'; + + // Scroll to the top and hide the address bar + window.scrollTo(0, 1); + window.scrollTo(0, 0); + return true; +} + </script> </div> diff --git a/sca-cpp/trunk/modules/edit/htdocs/logout/index.html b/sca-cpp/trunk/modules/edit/htdocs/logout/index.html index c1f7a57408..bce50815a7 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/logout/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/logout/index.html @@ -17,17 +17,17 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> +<html> <head> <title>Sign out</title> <meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> +<base href="/logout/"/> <link rel="stylesheet" type="text/css" href="/ui-min.css"/> <script type="text/javascript" src="/all-min.js"></script> </head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> +<body class="delayed" onload="onload();"> <div id="bodydiv" class="bodydiv"> <h1>Sign out</h1> @@ -37,16 +37,25 @@ </form> <script type="text/javascript"> -ui.initbody(); - function submitSignout() { // Clear session cookie and local storage - var reset = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/; secure; version=1'; + var reset = 'TuscanyOpenAuth=; expires=' + new Date(1970,01,01).toGMTString() + '; domain=.' + domainname(window.location.hostname) + '; path=/'; document.cookie = reset; localStorage.clear(); document.signout.submit(); return true; } + +function onload() { + // Show the page + document.body.style.visibility = 'visible'; + + // Scroll to the top and hide the address bar + window.scrollTo(0, 1); + window.scrollTo(0, 0); + return true; +} + </script> </div> diff --git a/sca-cpp/trunk/modules/edit/htdocs/menu.js b/sca-cpp/trunk/modules/edit/htdocs/menu.js deleted file mode 100644 index 42f18534bc..0000000000 --- a/sca-cpp/trunk/modules/edit/htdocs/menu.js +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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. - */ - -var editWidget = sca.component("EditWidget"); -var user= sca.defun(sca.reference(editWidget, "user"), "id"); - -/** - * Display the current signed in user. - */ -function userMenu() { - function UserMenu() { - this.content = function() { - var u = user.id() - return '<span>' + u + '</span>'; - }; - } - return new UserMenu(); -} - -/** - * Display the menu bar. - */ -function displaymenu() { - var mdiv = $('menu'); - var name = ui.fragmentParams()['app']; - - mdiv.innerHTML = ui.menubar( - append(mklist(ui.menu('Home', '/'), ui.menu('Store', '/store/')), - (isNil(name) || name == 'undefined')? - mklist() : - mklist( - ui.menu('Stats', '/stats/#app=' + name), - ui.menu('Page', '/page/#app=' + name), - ui.menu(isNil(config.compose)? 'Composition' : config.compose, '/graph/#app=' + name))), - mklist(ui.menu('Account', '/account/'), ui.menu('Sign out', '/logout/'))); -} - diff --git a/sca-cpp/trunk/modules/edit/htdocs/notauth/index.html b/sca-cpp/trunk/modules/edit/htdocs/notauth/index.html new file mode 100644 index 0000000000..4b6eb7e3f0 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/notauth/index.html @@ -0,0 +1,143 @@ +<!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> +<head> +<title>Sorry</title> +<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, target-densitydpi=devicedpi"/> +<meta name="apple-mobile-web-app-capable" content="yes"/> +<meta name="apple-mobile-web-app-status-bar-style" content="black"/> +<base href="/notauth/"/> +<script type="text/javascript"> + +window.appcache = {}; + +/** + * Get and cache a resource. + */ +appcache.get = function(uri) { + var h = uri.indexOf('#'); + var u = h == -1? uri : uri.substring(0, h); + + // Get resource from local storage first + var item = localStorage.getItem(u); + if (item != null && item != '') + return item; + + // Get resource from network + var http = new XMLHttpRequest(); + http.open("GET", u, false); + http.send(null); + if (http.status == 200) { + if (http.getResponseHeader("X-Login") != null) { + if (log) log('http err', u, 'X-Login'); + return null; + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + if (log) log('http err', u, 'No-Content'); + return null; + } + localStorage.setItem(u, http.responseText); + return http.responseText; + } + if (log) log('http err', u, http.status, http.statusText); + return null; +}; + +// Load Javascript and CSS +(function() { + var bootjs = document.createElement('script'); + bootjs.type = 'text/javascript'; + bootjs.text = appcache.get('/all-min.js'); + document.head.appendChild(bootjs); + document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css'))); +})(); + +</script> +</head> +<body class="delayed" onload="onload();"> +<div id="bodydiv" class="mainbodydiv"> + +<div id="headdiv" class="hsection"> +<script type="text/javascript"> +(function() { +$('headdiv').appendChild(ui.declareScript(appcache.get('/headconfig.js'))); +})(); +</script> +</div> + +<div id="menu"></div> + +<div id="content" class="viewloaded3d"> + +<table style="width: 100%;"> +<tr><td><h2><span id="h1"></span></h2></td></tr> +</table> + +<div style="margin-left: auto; margin-right: auto; text-align: center;"> +<div class="hd2">Sorry, you're not authorized to view this page.</div> +</div> + +</div> + +<script type="text/javascript"> + +// Set page title +$('h1').innerHTML = ui.hometitle(location.hostname); + +// Init div variables +var mdiv = $('menu'); +var cdiv = $('content'); + +/** + * Build and show the menu bar. + */ +function showmenu(mdiv) { + mdiv.innerHTML = ui.menubar( + mklist(ui.menu('Home', '/', '_view', false), ui.menu('Store', '/#view=store', '_view', false)), + mklist(ui.menu('Account', '/#view=account', '_view', false), ui.menu('Sign out', '/logout/', '_self', false))); +} + +showmenu($('menu')); +cdiv.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); + +/** + * Load post processing. + */ +function onload() { + // Show the page + document.body.style.visibility = 'visible'; + + // Scroll to the top and hide the address bar + window.scrollTo(0, 0); + return true; +} + +</script> + +<div id="footdiv" class="fsection"> +<script type="text/javascript"> +(function() { +$('footdiv').appendChild(ui.declareScript(appcache.get('/footconfig.js'))); +})(); +</script> +</div> + +</div> +</body> +</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/notfound/index.html b/sca-cpp/trunk/modules/edit/htdocs/notfound/index.html new file mode 100644 index 0000000000..4d11a1a7dc --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/notfound/index.html @@ -0,0 +1,144 @@ +<!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> +<head> +<title>Page not found</title> +<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, target-densitydpi=devicedpi"/> +<meta name="apple-mobile-web-app-capable" content="yes"/> +<meta name="apple-mobile-web-app-status-bar-style" content="black"/> +<base href="/notfound/"/> +<script type="text/javascript"> + +window.appcache = {}; + +/** + * Get and cache a resource. + */ +appcache.get = function(uri) { + var h = uri.indexOf('#'); + var u = h == -1? uri : uri.substring(0, h); + + // Get resource from local storage first + var item = localStorage.getItem(u); + if (item != null && item != '') + return item; + + // Get resource from network + var http = new XMLHttpRequest(); + http.open("GET", u, false); + http.send(null); + if (http.status == 200) { + if (http.getResponseHeader("X-Login") != null) { + if (log) log('http err', u, 'X-Login'); + return null; + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + if (log) log('http err', u, 'No-Content'); + return null; + } + localStorage.setItem(u, http.responseText); + return http.responseText; + } + if (log) log('http err', u, http.status, http.statusText); + return null; +}; + +// Load Javascript and CSS +(function() { + var bootjs = document.createElement('script'); + bootjs.type = 'text/javascript'; + bootjs.text = appcache.get('/all-min.js'); + document.head.appendChild(bootjs); + document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css'))); +})(); + +</script> +</head> +<body class="delayed" onload="onload();"> +<div id="bodydiv" class="mainbodydiv"> + +<div id="headdiv" class="hsection"> +<script type="text/javascript"> +(function() { +$('headdiv').appendChild(ui.declareScript(appcache.get('/headconfig.js'))); +})(); +</script> +</div> + +<div id="menu"></div> + +<div id="content" class="viewloaded3d"> + +<table style="width: 100%;"> +<tr><td><h2><span id="h1"></span></h2></td></tr> +</table> + +<div style="margin-left: auto; margin-right: auto; text-align: center;"> +<div class="hd2">Sorry, that page was not found.</div> +<div>You may have clicked an expired link or mistyped the address.</div> +</div> + +</div> + +<script type="text/javascript"> + +// Set page title +$('h1').innerHTML = ui.hometitle(location.hostname); + +// Init div variables +var mdiv = $('menu'); +var cdiv = $('content'); + +/** + * Build and show the menu bar. + */ +function showmenu(mdiv) { + mdiv.innerHTML = ui.menubar( + mklist(ui.menu('Home', '/', '_view', false), ui.menu('Store', '/#view=store', '_view', false)), + mklist(ui.menu('Account', '/#view=account', '_view', false), ui.menu('Sign out', '/logout/', '_self', false))); +} + +showmenu(mdiv); +div.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); + +/** + * Load post processing. + */ +function onload() { + // Show the page + document.body.style.visibility = 'visible'; + + // Scroll to the top and hide the address bar + window.scrollTo(0, 0); + return true; +} + +</script> + +<div id="footdiv" class="fsection"> +<script type="text/javascript"> +(function() { +$('footdiv').appendChild(ui.declareScript(appcache.get('/footconfig.js'))); +})(); +</script> +</div> + +</div> +</body> +</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/notyet/index.html b/sca-cpp/trunk/modules/edit/htdocs/notyet/index.html new file mode 100644 index 0000000000..2f9f7751d1 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/notyet/index.html @@ -0,0 +1,144 @@ +<!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> +<head> +<title>Page not found</title> +<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, target-densitydpi=devicedpi"/> +<meta name="apple-mobile-web-app-capable" content="yes"/> +<meta name="apple-mobile-web-app-status-bar-style" content="black"/> +<base href="/notyet/"/> +<script type="text/javascript"> + +window.appcache = {}; + +/** + * Get and cache a resource. + */ +appcache.get = function(uri) { + var h = uri.indexOf('#'); + var u = h == -1? uri : uri.substring(0, h); + + // Get resource from local storage first + var item = localStorage.getItem(u); + if (item != null && item != '') + return item; + + // Get resource from network + var http = new XMLHttpRequest(); + http.open("GET", u, false); + http.send(null); + if (http.status == 200) { + if (http.getResponseHeader("X-Login") != null) { + if (log) log('http err', u, 'X-Login'); + return null; + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + if (log) log('http err', u, 'No-Content'); + return null; + } + localStorage.setItem(u, http.responseText); + return http.responseText; + } + if (log) log('http err', u, http.status, http.statusText); + return null; +}; + +// Load Javascript and CSS +(function() { + var bootjs = document.createElement('script'); + bootjs.type = 'text/javascript'; + bootjs.text = appcache.get('/all-min.js'); + document.head.appendChild(bootjs); + document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css'))); +})(); + +</script> +</head> +<body class="delayed" onload="onload();"> +<div id="bodydiv" class="mainbodydiv"> + +<div id="headdiv" class="hsection"> +<script type="text/javascript"> +(function() { +$('headdiv').appendChild(ui.declareScript(appcache.get('/headconfig.js'))); +})(); +</script> +</div> + +<div id="menu"></div> + +<div id="content" class="viewloaded3d"> + +<table style="width: 100%;"> +<tr><td><h2><span id="h1"></span></h2></td></tr> +</table> + +<div style="margin-left: auto; margin-right: auto; text-align: center;"> +<div class="hd2">Sorry, that page is still under construction.</div> +<div>Please check back later.</div> +</div> + +</div> + +<script type="text/javascript"> + +// Set page title +$('h1').innerHTML = ui.hometitle(location.hostname); + +// Init div variables +var mdiv = $('menu'); +var cdiv = $('content'); + +/** + * Build and show the menu bar. + */ +function showmenu(mdiv) { + mdiv.innerHTML = ui.menubar( + mklist(ui.menu('Home', '/', '_view', false), ui.menu('Store', '/#view=store', '_view', false)), + mklist(ui.menu('Account', '/#view=account', '_view', false), ui.menu('Sign out', '/logout/', '_self', false))); +} + +showmenu($('menu')); +cdiv.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); + +/** + * Load post processing. + */ +function onload() { + // Show the page + document.body.style.visibility = 'visible'; + + // Scroll to the top and hide the address bar + window.scrollTo(0, 0); + return true; +} + +</script> + +<div id="footdiv" class="fsection"> +<script type="text/javascript"> +(function() { +$('footdiv').appendChild(ui.declareScript(appcache.get('/footconfig.js'))); +})(); +</script> +</div> + +</div> +</body> +</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/oops/index.html b/sca-cpp/trunk/modules/edit/htdocs/oops/index.html new file mode 100644 index 0000000000..70fe3994a2 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/oops/index.html @@ -0,0 +1,143 @@ +<!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> +<head> +<title>Oops</title> +<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, target-densitydpi=devicedpi"/> +<meta name="apple-mobile-web-app-capable" content="yes"/> +<meta name="apple-mobile-web-app-status-bar-style" content="black"/> +<base href="/oops/"/> +<script type="text/javascript"> + +window.appcache = {}; + +/** + * Get and cache a resource. + */ +appcache.get = function(uri) { + var h = uri.indexOf('#'); + var u = h == -1? uri : uri.substring(0, h); + + // Get resource from local storage first + var item = localStorage.getItem(u); + if (item != null && item != '') + return item; + + // Get resource from network + var http = new XMLHttpRequest(); + http.open("GET", u, false); + http.send(null); + if (http.status == 200) { + if (http.getResponseHeader("X-Login") != null) { + if (log) log('http err', u, 'X-Login'); + return null; + } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) { + if (log) log('http err', u, 'No-Content'); + return null; + } + localStorage.setItem(u, http.responseText); + return http.responseText; + } + if (log) log('http err', u, http.status, http.statusText); + return null; +}; + +// Load Javascript and CSS +(function() { + var bootjs = document.createElement('script'); + bootjs.type = 'text/javascript'; + bootjs.text = appcache.get('/all-min.js'); + document.head.appendChild(bootjs); + document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css'))); +})(); + +</script> +</head> +<body class="delayed" onload="onload();"> +<div id="bodydiv" class="mainbodydiv"> + +<div id="headdiv" class="hsection"> +<script type="text/javascript"> +(function() { +$('headdiv').appendChild(ui.declareScript(appcache.get('/headconfig.js'))); +})(); +</script> +</div> + +<div id="menu"></div> + +<div id="content" class="viewloaded3d"> + +<table style="width: 100%;"> +<tr><td><h2><span id="h1"></span></h2></td></tr> +</table> + +<div style="margin-left: auto; margin-right: auto; text-align: center;"> +<div class="hd2">Oops, something went wrong...</div> +</div> + +</div> + +<script type="text/javascript"> + +// Set page title +$('h1').innerHTML = ui.hometitle(location.hostname); + +// Init div variables +var mdiv = $('menu'); +var cdiv = $('content'); + +/** + * Build and show the menu bar. + */ +function showmenu(mdiv) { + mdiv.innerHTML = ui.menubar( + mklist(ui.menu('Home', '/', '_view', false), ui.menu('Store', '/#view=store', '_view', false)), + mklist(ui.menu('Account', '/#view=account', '_view', false), ui.menu('Sign out', '/logout/', '_self', false))); +} + +showmenu($('menu')); +cdiv.style.top = ui.pixpos(mdiv.offsetTop + mdiv.offsetHeight); + +/** + * Load post processing. + */ +function onload() { + // Show the page + document.body.style.visibility = 'visible'; + + // Scroll to the top and hide the address bar + window.scrollTo(0, 0); + return true; +} + +</script> + +<div id="footdiv" class="fsection"> +<script type="text/javascript"> +(function() { +$('footdiv').appendChild(ui.declareScript(appcache.get('/footconfig.js'))); +})(); +</script> +</div> + +</div> +</body> +</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/index.html b/sca-cpp/trunk/modules/edit/htdocs/page/index.html index ca2619e07b..dd33f34ac2 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/page/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/page/index.html @@ -17,33 +17,8 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> -<head> -<title>Page</title> -<meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -<script type="text/javascript" src="page.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> <div id="bodydiv" class="bodydiv" style="overflow: visible;"> -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menubackground" style="position: absolute; top: 0px; left: 0px; z-index: -1; width: 2500px;"> -<table cellpadding="0" cellspacing="0" width="100%" class="tbar"><tr><td class="dtbar"> -<table border="0" cellspacing="0" cellpadding="0"><tr><td class="ltbar"><span class="tbarsmenu"> </span></td></tr></table> -</td></tr></table> -</div> - -<div id="menu"></div> - <table style="width: 100%;"> <tr> <td><h2><span id="appNameHeader"></span></h2></td> @@ -59,10 +34,6 @@ <table id="widgetValueTable" style="width: 100%;"> <tr> -<td class="thr thl" style="padding-left: 2px; padding-right: 2px; vertical-align: top; width: 100%;"> -<input id="widgetValue" type="text" value="" title="Widget value" autocapitalize="off" placeholder="Value" style="position: relative; width: 100%;"/> -</td> - <td class="thl thr" style="text-align: right; padding-right: 2px; vertical-align: top;"> <span id="deleteWidgetButton" title="Delete a Widget" class="graybutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; text-align: center; margin-left: 0px; margin-right: 0px;">-</span> @@ -72,13 +43,17 @@ <span id="playPageButton" title="View page" class="graybutton" style="font-weight: bold; font-size: 16px; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; middle; text-align: center; margin-left: 0px; margin-right: 0px;">></span> </td> + +<td class="thl thr" style="padding-left: 2px; padding-right: 2px; vertical-align: top; width: 100%;"> +<input id="widgetValue" type="text" value="" title="Widget value" autocapitalize="off" placeholder="Value" style="position: relative; visibility: hidden; width: 100%;"/> +</td> </tr> </table> -<div id="contentdiv" style="margin-top: 4px; width: 2500px"> +<div id="contentdiv" style="margin-top: 4px; width: 2500px;"> <div id="editdiv" style="visibility: visible; position: relative; top: 0px; left: -2500px; width: 2500px; height: 5000px;"> -<div style="position: relative; left: 2500px; top: 0px; right: 0px; height: 5000px; border:1px; border-style: solid; border-color: #a2bae7; background: url(/public/grid72.png);"></div> +<div style="position: relative; left: 2500px; top: 0px; right: 0px; height: 5000px; border:1px; border-style: solid; border-color: #a2bae7;"><span id="editgrid"></span></div> <div class="guide" style="position: absolute; left: 2500px; top: 0px; width: 320px; height: 460px;"></div> <div class="guide" style="position: absolute; left: 2500px; top: 0px; width: 480px; height: 300px;"></div> <div class="guide" style="position: absolute; left: 2500px; top: 0px; width: 768px; height: 911px;"></div> @@ -101,7 +76,7 @@ <span class="link" id="palette:link" style="position: absolute; left: 0px; top: 340px;"><a href="/"><span>link</span></a></span> <span class="text" id="palette:text" style="position: absolute; left: 0px; top: 370px;"><span>text</span></span> <span class="iframe fakeframe" id="palette:iframe" style="position: absolute; left: 0px; top: 400px; width: 200px;"><a href="/public/iframe.html"><span class="fakeframe"><span>frame ...</span></span></a></span> -<span class="img" id="palette:img" style="position: absolute; left: 0px; top: 430px;"><img src="/public/img.png"/></span> +<span class="img" id="palette:img" style="position: absolute; left: 0px; top: 430px;"><img id="imgimg"/></span> </div> <div id="playdiv" style="visibility: hidden; position: absolute; top: 0px; left: 0px; width: 2500px; height: 5000px;"> @@ -112,20 +87,17 @@ <div id="buffer" style="visibility: hidden; width: 0px; height: 0px"></div> <script type="text/javascript"> -ui.initbody(); // Get the app name -var appname = ui.fragmentParams()['app']; -if (isNil(appname)) - window.open('/', '_self'); +var appname = ui.fragmentParams(location)['app']; /** * Return the link to an app. */ function applink(appname) { - var protocol = window.location.protocol; - var host = window.location.hostname; - var port = ':' + window.location.port; + var protocol = location.protocol; + var host = location.hostname; + var port = ':' + location.port; if (port == ':80' || port == ':443' || port == ':') port = ''; var link = protocol + '//' + appname + '.' + host + port + '/'; @@ -133,12 +105,9 @@ function applink(appname) { } // Set page titles -document.title = windowtitle(window.location.hostname) + ' - Page - ' + appname; +document.title = ui.windowtitle(location.hostname) + ' - Page - ' + appname; $('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>'; -// Load the menu bar -displaymenu(); - /** * Page editor area, widget value field, add, delete and play page buttons. */ @@ -152,6 +121,10 @@ var wdelete = $('deleteWidgetButton'); var wcopy = $('copyWidgetButton'); var pplay = $('playPageButton'); +// Set images +$('editgrid').parentNode.style.background = 'url(\'' + ui.b64img(appcache.get('/public/grid72.b64')) + '\')'; +$('imgimg').src = ui.b64img(appcache.get('/public/img.b64')); + // Position edit and play divs inside the content div ediv.style.position = 'absolute'; ediv.style.top = cdiv.offsetTop + 'px'; @@ -159,10 +132,6 @@ pdiv.style.position = 'absolute'; pdiv.style.top = cdiv.offsetTop + 'px'; // Position background divs -var mbackground = $('menubackground'); -var menudiv = $('menu'); -mbackground.style.top = ui.pixpos(menudiv.offsetTop); - var wvbackground = $('widgetValueBackground'); var wvtable = $('widgetValueTable'); wvbackground.style.top = ui.pixpos(wvtable.offsetTop); @@ -184,6 +153,569 @@ var editWidget = sca.component("EditWidget"); var pages = sca.reference(editWidget, "pages"); /** + * Page editing functions. + */ +var page = {}; + +/** + * Default positions and sizes. + */ +page.palcx = 2500; + +/** + * Init a page editor. Works with all browsers except IE. + */ +page.edit = function(elem, wvalue, wadd, wcopy, wdelete, onchange, onselect) { + + // Track element dragging and selection + page.dragging = null; + page.selected = null; + wvalue.disabled = true; + wvalue.style.visibility = 'hidden'; + wcopy.disabled = true; + wdelete.disabled = true; + + // Trigger widget select and page change events + page.onpagechange = onchange; + page.onwidgetselect = onselect; + + /** + * Handle a mouse down event. + */ + elem.onmousedown = function(e) { + + // On mouse controlled devices, engage the click component selection + // logic right away + if (typeof e.touches == 'undefined') + elem.onclick(e); + + // Find a draggable element + var dragging = page.draggable(e.target, elem); + if (dragging == null || dragging != page.selected) + return true; + page.dragging = dragging; + + // Remember mouse position + var pos = typeof e.touches != "undefined"? e.touches[0] : e; + page.dragX = pos.screenX; + page.dragY = pos.screenY; + + if (e.preventDefault) + e.preventDefault(); + else + e.returnValue = false; + return true; + }; + + // Support touch devices + elem.ontouchstart = elem.onmousedown; + + /** + * Handle a mouse up event. + */ + elem.onmouseup = function(e) { + if (page.dragging == null) + return true; + + // Snap to grid + var newX = page.gridsnap(ui.numpos(page.dragging.style.left)); + var newY = page.gridsnap(ui.numpos(page.dragging.style.top)); + page.dragging.style.left = ui.pixpos(newX); + page.dragging.style.top = ui.pixpos(newY); + page.dragging.cover.style.left = ui.pixpos(newX); + page.dragging.cover.style.top = ui.pixpos(newY); + + // Fixup widget style + page.fixupwidget(page.dragging); + + // Forget dragged element + page.dragging = null; + + // Trigger page change event + page.onpagechange(false); + return true; + }; + + // Support touch devices + elem.ontouchend = elem.onmouseup; + + /** + * Handle a mouse move event. + */ + window.onmousemove = function(e) { + if (page.dragging == null) + return true; + + // Get the mouse position + var pos = typeof e.touches != "undefined"? e.touches[0] : e; + if (pos.screenX == page.dragX && pos.screenY == page.dragY) + return true; + + // Compute position of dragged element + var curX = ui.numpos(page.dragging.style.left); + var curY = ui.numpos(page.dragging.style.top); + var newX = curX + (pos.screenX - page.dragX); + var newY = curY + (pos.screenY - page.dragY); + if (newX >= page.palcx) + page.dragX = pos.screenX; + else + newX = page.palcx; + if (newY >= 0) + page.dragY = pos.screenY; + else + newY = 0; + + // Move the dragged element + page.dragging.style.left = ui.pixpos(newX); + page.dragging.style.top = ui.pixpos(newY); + page.dragging.cover.style.left = ui.pixpos(newX); + page.dragging.cover.style.top = ui.pixpos(newY); + return true; + }; + + // Support touch devices + elem.ontouchmove = window.onmousemove; + + /** + * Handle a mouse click event. + */ + elem.onclick = function(e) { + + // Find selected element + var selected = page.draggable(e.target, elem); + if (selected == null) { + if (page.selected != null) { + + // Reset current selection + page.widgetselect(page.selected, false, wvalue, wcopy, wdelete); + page.selected = null; + + // Trigger widget select event + page.onwidgetselect(null); + } + + // Dismiss the palette + if (ui.numpos(elem.style.left) != (page.palcx * -1)) + elem.style.left = ui.pixpos(page.palcx * -1); + + return true; + } + + // Deselect the previously selected element + page.widgetselect(page.selected, false, wvalue, wcopy, wdelete); + + // Clone element dragged from palette + if (selected.id.substring(0, 8) == 'palette:') { + page.selected = page.clone(selected); + + // Move into the editing area and hide the palette + page.selected.style.left = ui.pixpos(ui.numpos(page.selected.style.left) + page.palcx); + page.selected.cover.style.left = ui.pixpos(ui.numpos(page.selected.cover.style.left) + page.palcx); + elem.style.left = ui.pixpos(page.palcx * -1); + + // Bring it to the top + page.bringtotop(page.selected); + + // Trigger page change event + page.onpagechange(true); + + } else { + + // Bring selected element to the top + page.selected = selected; + page.bringtotop(page.selected); + } + + // Select the element + page.widgetselect(page.selected, true, wvalue, wcopy, wdelete); + + // Trigger widget select event + page.onwidgetselect(page.selected); + + return true; + }; + + /** + * Handle field on change events. + */ + wvalue.onchange = wvalue.onblur = function() { + if (page.selected == null) + return false; + page.settext(page.selected, wvalue.value); + page.selected.cover.style.width = ui.pixpos(page.selected.clientWidth + 4); + page.selected.cover.style.height = ui.pixpos(page.selected.clientHeight + 4); + + // Trigger page change event + page.onpagechange(true); + return false; + }; + + // Handle add widget event. + wadd.onclick = function() { + + // Show the palette + elem.style.left = ui.pixpos(0); + return false; + }; + + // Handle delete event. + wdelete.onclick = function() { + if (page.selected == null) + return false; + + // Reset current selection + page.widgetselect(page.selected, false, wvalue, wcopy, wdelete); + + // Remove selected widget + page.selected.parentNode.removeChild(page.selected); + page.selected.cover.parentNode.removeChild(page.selected.cover); + page.selected = null; + + // Trigger widget select event + page.onwidgetselect(null); + + // Trigger page change event + page.onpagechange(true); + return false; + }; + + // Handle copy event. + wcopy.onclick = function() { + if (page.selected == null) + return false; + if (page.selected.id.substring(0, 8) == 'palette:') + return false; + + // Reset current selection + page.widgetselect(page.selected, false, wvalue, wcopy, wdelete); + + // Clone selected widget + page.selected = page.clone(page.selected); + + // Move 10 pixels down right + page.selected.style.left = ui.pixpos(ui.numpos(page.selected.style.left) + 10); + page.selected.style.top = ui.pixpos(ui.numpos(page.selected.style.top) + 10); + page.selected.cover.style.left = ui.pixpos(ui.numpos(page.selected.cover.style.left) + 10); + page.selected.cover.style.top = ui.pixpos(ui.numpos(page.selected.cover.style.top) + 10); + + // Bring it to the top + page.bringtotop(page.selected); + + // Select the element + page.widgetselect(page.selected, true, wvalue, wcopy, wdelete); + + // Trigger widget select event + page.onwidgetselect(page.selected); + + // Trigger page change event + page.onpagechange(true); + return false; + }; + + // Cover child elements with span elements to prevent + // any input events to reach them + map(page.cover, nodeList(elem.childNodes)); + + return elem; +}; + +/** + * Return the text of a widget. + */ +page.text = function(e) { + function formula(e) { + var f = e.id; + if (f.substring(0, 5) != 'page:') + return '=' + f; + return ''; + } + + function constant(e, f) { + if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') { + var t = car(childElements(e)).innerHTML; + return t == f? '' : t; + } + if (e.className == 'button' || e.className == 'checkbox') { + var t = car(childElements(e)).value; + return t == f? '' : t; + } + if (e.className == 'entry' || e.className == 'password') { + var t = car(childElements(e)).defaultValue; + return t == f? '' : t; + } + if (e.className == 'select') { + var t = car(childElements(car(childElements(e)))).value; + return t == f? '' : t; + } + if (e.className == 'link') { + var lhr = car(childElements(e)).href; + var hr = lhr.substring(0, 5) == 'link:'? lhr.substring(5) : ''; + var t = car(childElements(car(childElements(e)))).innerHTML; + return t == f? hr : (t == hr? hr : (t == ''? hr : hr + ',' + t)); + } + if (e.className == 'img') { + var src = car(childElements(e)).src; + return src == location.href? '' : src; + } + if (e.className == 'iframe') { + var hr = car(childElements(e)).href; + return hr == location.href? '' : hr; + } + if (e.className == 'list') + return ''; + if (e.className == 'table') + return ''; + return ''; + } + + var f = formula(e); + var c = constant(e, f); + return f == ''? c : (c == ''? f : f + ',' + c); +}; + +/** + * Return true if a widget has editable text. + */ +page.hastext = function(e) { + if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') + return true; + if (e.className == 'button' || e.className == 'checkbox') + return true; + if (e.className == 'entry' || e.className == 'password') + return true; + if (e.className == 'select') + return false; + if (e.className == 'link') + return true; + if (e.className == 'img') + return true; + if (e.className == 'iframe') + return true; + if (e.className == 'list') + return false; + if (e.className == 'table') + return false; + return false; +}; + +/** + * Set the text of a widget. + */ +page.settext = function(e, t) { + function formula(t) { + if (t.length > 1 && t.substring(0, 1) == '=') + return car(t.split(',')); + return ''; + } + + function constant(t) { + return t.length > 1 && t.substring(0, 1) == '='? cdr(t.split(',')) : t.split(','); + } + + var f = formula(t); + var c = constant(t); + + e.id = f != ''? f.substring(1) : ('page:' + e.className); + + if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') { + car(childElements(e)).innerHTML = isNil(c)? f : car(c); + return t; + } + if (e.className == 'button' || e.className == 'entry' || e.className == 'password') { + car(childElements(e)).defaultValue = isNil(c)? f : car(c); + return t; + } + if (e.className == 'checkbox') { + car(childElements(e)).value = isNil(c)? f : car(c); + map(function(n) { if (n.nodeName == "SPAN") n.innerHTML = isNil(c)? f : car(c); return n; }, nodeList(e.childNodes)); + return t; + } + if (e.className == 'select') { + var ce = car(childElements(car(childElements(e)))); + ce.value = isNil(c)? f : car(c); + ce.innerHTML = isNil(c)? f : car(c); + return t; + } + if (e.className == 'list') { + e.innerHTML = '<table class="datatable" style="width: 100%;;"><tr><td class="datatd">' + (isNil(c)? f : car(c)) + '</td></tr><tr><td class="datatd">...</td></tr></table>'; + return t; + } + if (e.className == 'table') { + e.innerHTML = '<table class="datatable" style="width: 100%;"><tr><td class="datatdl">' + (isNil(c)? f : car(c)) + '</td><td class="datatdr">...</td></tr><tr><td class="datatdl">...</td><td class="datatdr">...</td></tr></table>'; + return t; + } + if (e.className == 'link') { + var ce = car(childElements(e)); + ce.href = isNil(c)? 'link:/index.html' : ('link:' + car(c)); + car(childElements(ce)).innerHTML = isNil(c)? (f != ''? f : '/index.html') : isNil(cdr(c))? (f != ''? f : car(c)) : cadr(c); + return t; + } + if (e.className == 'img') { + car(childElements(e)).src = isNil(c)? '/public/img.png' : car(c); + return t; + } + if (e.className == 'iframe') { + car(childElements(e)).href = isNil(c)? '/public/iframe.html' : car(c); + return t; + } + return ''; +}; + +/** + * Initial fixup of a widget. + */ +page.fixupwidget = function(e) { + if (e.className == 'iframe') { + var f = car(childElements(e)); + //e.innerHTML = '<iframe src="' + f.href + '" frameborder="no" scrolling="no"></iframe>'; + return e; + } + if (e.className == 'section') { + e.style.width = '100%'; + return e; + } + if (e.className == 'list') { + e.style.width = '100%'; + car(childElements(e)).style.width = '100%'; + return e; + } + if (e.className == 'table') { + e.style.width = '100%'; + car(childElements(e)).style.width = '100%'; + return e; + } + if (e.className == 'img') { + var i = car(childElements(e)); + if (i.src != '' && i.src.substring(0, 5) == 'data:') + i.src = '/public/img.png'; + return e; + } + return e; +} + +/** + * Find a draggable element in a hierarchy of elements. + */ +page.draggable = function(n, e) { + if (n == e) + return null; + if (n.id != '') + return n; + if (n.covered) + return n.covered; + return page.draggable(n.parentNode, e); +} + +/** + * Align a pos along a 9pixel grid. + */ +page.gridsnap = function(x) { + return Math.round(x / 9) * 9; +} + +/** + * Bring an element and its parent to the top. + */ +page.bringtotop = function(n) { + n.parentNode.appendChild(n); + n.cover.parentNode.appendChild(n.cover); +} + +/** + * Draw widget selection. + */ +page.widgetselect = function(n, s, wvalue, wcopy, wdelete) { + if (isNil(n) || !s) { + // Clear the widget value field + wvalue.value = ''; + wvalue.disabled = true; + wvalue.style.visibility = 'hidden'; + wcopy.disabled = true; + wdelete.disabled = true; + + // Clear the widget outline + if (!isNil(n)) + n.cover.style.borderWidth = '0px'; + return true; + } + + // Update the widget value field + wvalue.value = page.text(n); + wvalue.disabled = false; + wvalue.style.visibility = 'visible'; + wcopy.disabled = false; + wdelete.disabled = false; + + // Outline the widget + n.cover.style.borderWidth = '2px'; + return true; +}; + +/** + * Cover a page element with a <span> element to prevent + * any input events to reach it. + */ +page.cover = function(e) { + if (e.id == '' || isNil(e.style)) + return e; + var cover = document.createElement('div'); + cover.style.position = 'absolute'; + cover.style.left = ui.pixpos(ui.numpos(e.style.left) - 2); + cover.style.top = ui.pixpos(ui.numpos(e.style.top) - 2); + cover.style.width = ui.pixpos(e.clientWidth + 4); + cover.style.height = ui.pixpos(e.clientHeight + 4); + cover.style.visibility = 'inherit'; + cover.style.borderStyle = 'solid'; + cover.style.borderWidth = '0px'; + cover.style.borderColor = '#598edd'; + cover.style.padding = '0px'; + cover.style.margin = '0px'; + cover.covered = e; + e.cover = cover; + e.parentNode.appendChild(cover); + return e; +} + +/** + * Clone a palette element. + */ +page.clone = function(e) { + + /** + * Clone an element's HTML. + */ + function mkclone(e) { + var ne = document.createElement('span'); + + // Skip the palette: prefix + ne.id = 'page:' + e.id.substr(8); + + // Copy the class and HTML content + ne.className = e.className; + ne.innerHTML = e.innerHTML; + + // Fixup the widget style + page.fixupwidget(ne); + + return ne; + } + + /** + * Clone an element's position. + */ + function posclone(ne, e) { + ne.style.position = 'absolute'; + ne.style.left = ui.pixpos(ui.numpos(e.style.left)); + ne.style.top = ui.pixpos(ui.numpos(e.style.top)); + e.parentNode.appendChild(ne); + page.cover(ne); + return ne; + } + + return posclone(mkclone(e), e); +}; + +/** * Return the page in an ATOM entry. */ function atompage(doc) { @@ -373,35 +905,19 @@ function onpagechange(prop) { } /** - * Return the link to a component value. - */ -function compvaluelink(appname, cname) { - if (cname == '' || isNil(cname)) - return ''; - var protocol = window.location.protocol; - var host = window.location.hostname; - var port = ':' + window.location.port; - if (port == ':80' || port == ':443' || port == ':') - port = ''; - var link = protocol + '//' + appname + '.' + host + port + '/data/#component=' + cname; - return link; -} - -/** * Handle a widget select event. */ function onwidgetselect(w) { if (w == widget) return true; widget = w; - var link = compvaluelink(appname, isNil(w)? '' : w.id); function updateButton(b, v) { b.style.color = v? '#000000' : '#808080'; } - updateButton(wdelete, link != ''); - updateButton(wcopy, link != ''); + updateButton(wdelete, !isNil(w)); + updateButton(wcopy, !isNil(w)); return true; } @@ -415,12 +931,14 @@ function playpage() { page.selected = null; wvalue.value = applink(appname); pplay.innerHTML = '<'; - ediv.style.visibility = 'hidden' evisible = false; pdiv.style.visibility = 'visible'; pdiv.innerHTML = ''; pdiv.innerHTML = '<iframe id="playappframe" style="position: relative; height: 5000px; width: 2500px; border: 0px;" scrolling="no" frameborder="0" src="' + applink(appname) + '"></iframe>'; + setTimeout(function() { + ediv.style.visibility = 'hidden' + }, 0); return true; } @@ -431,12 +949,14 @@ function showedit() { if (evisible) return true; pplay.innerHTML = '>'; - pdiv.style.visibility = 'hidden'; - pdiv.innerHTML = ''; ediv.style.visibility = 'visible' evisible = true; page.widgetselect(widget, true, wvalue, wcopy, wdelete); page.selected = widget; + setTimeout(function() { + pdiv.style.visibility = 'hidden'; + pdiv.innerHTML = ''; + }, 0); return true; } @@ -454,13 +974,7 @@ page.edit(ediv, wvalue, wadd, wcopy, wdelete, onpagechange, onwidgetselect); // Get and display the current app page getpage(appname, ediv); -</script> -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> +</script> </div> -</body> -</html> - diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/page.js b/sca-cpp/trunk/modules/edit/htdocs/page/page.js deleted file mode 100644 index 2fd88c0c6b..0000000000 --- a/sca-cpp/trunk/modules/edit/htdocs/page/page.js +++ /dev/null @@ -1,573 +0,0 @@ -/* - * 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. - */ - -/** - * Page editing functions. - */ -var page = {}; - -/** - * Default positions and sizes. - */ -var palcx = 2500; - -/** - * Init a page editor. Works with all browsers except IE. - */ -page.edit = function(elem, wvalue, wadd, wcopy, wdelete, onchange, onselect) { - - // Track element dragging and selection - page.dragging = null; - page.selected = null; - wvalue.disabled = true; - wcopy.disabled = true; - wdelete.disabled = true; - - // Trigger widget select and page change events - page.onpagechange = onchange; - page.onwidgetselect = onselect; - - /** - * Handle a mouse down event. - */ - elem.onmousedown = function(e) { - - // On mouse controlled devices, engage the click component selection - // logic right away - if (typeof e.touches == 'undefined') - elem.onclick(e); - - // Find a draggable element - var dragging = page.draggable(e.target, elem); - if (dragging == null || dragging != page.selected) - return true; - page.dragging = dragging; - - // Remember mouse position - var pos = typeof e.touches != "undefined"? e.touches[0] : e; - page.dragX = pos.screenX; - page.dragY = pos.screenY; - - if (e.preventDefault) - e.preventDefault(); - else - e.returnValue = false; - return true; - }; - - // Support touch devices - elem.ontouchstart = elem.onmousedown; - - /** - * Handle a mouse up event. - */ - elem.onmouseup = function(e) { - if (page.dragging == null) - return true; - - // Snap to grid - var newX = page.gridsnap(ui.numpos(page.dragging.style.left)); - var newY = page.gridsnap(ui.numpos(page.dragging.style.top)); - page.dragging.style.left = ui.pixpos(newX); - page.dragging.style.top = ui.pixpos(newY); - page.dragging.cover.style.left = ui.pixpos(newX); - page.dragging.cover.style.top = ui.pixpos(newY); - - // Fixup widget style - page.fixupwidget(page.dragging); - - // Forget dragged element - page.dragging = null; - - // Trigger page change event - page.onpagechange(false); - return true; - }; - - // Support touch devices - elem.ontouchend = elem.onmouseup; - - /** - * Handle a mouse move event. - */ - window.onmousemove = function(e) { - if (page.dragging == null) - return true; - - // Get the mouse position - var pos = typeof e.touches != "undefined"? e.touches[0] : e; - if (pos.screenX == page.dragX && pos.screenY == page.dragY) - return true; - - // Compute position of dragged element - var curX = ui.numpos(page.dragging.style.left); - var curY = ui.numpos(page.dragging.style.top); - var newX = curX + (pos.screenX - page.dragX); - var newY = curY + (pos.screenY - page.dragY); - if (newX >= palcx) - page.dragX = pos.screenX; - else - newX = palcx; - if (newY >= 0) - page.dragY = pos.screenY; - else - newY = 0; - - // Move the dragged element - page.dragging.style.left = ui.pixpos(newX); - page.dragging.style.top = ui.pixpos(newY); - page.dragging.cover.style.left = ui.pixpos(newX); - page.dragging.cover.style.top = ui.pixpos(newY); - return true; - }; - - // Support touch devices - elem.ontouchmove = window.onmousemove; - - /** - * Handle a mouse click event. - */ - elem.onclick = function(e) { - - // Find selected element - var selected = page.draggable(e.target, elem); - if (selected == null) { - if (page.selected != null) { - - // Reset current selection - page.widgetselect(page.selected, false, wvalue, wcopy, wdelete); - page.selected = null; - - // Trigger widget select event - page.onwidgetselect(null); - } - - // Dismiss the palette - if (ui.numpos(elem.style.left) != (palcx * -1)) - elem.style.left = ui.pixpos(palcx * -1); - - return true; - } - - // Deselect the previously selected element - page.widgetselect(page.selected, false, wvalue, wcopy, wdelete); - - // Clone element dragged from palette - if (selected.id.substring(0, 8) == 'palette:') { - page.selected = page.clone(selected); - - // Move into the editing area and hide the palette - page.selected.style.left = ui.pixpos(ui.numpos(page.selected.style.left) + palcx); - page.selected.cover.style.left = ui.pixpos(ui.numpos(page.selected.cover.style.left) + palcx); - elem.style.left = ui.pixpos(palcx * -1); - - // Bring it to the top - page.bringtotop(page.selected); - - // Trigger page change event - page.onpagechange(true); - - } else { - - // Bring selected element to the top - page.selected = selected; - page.bringtotop(page.selected); - } - - // Select the element - page.widgetselect(page.selected, true, wvalue, wcopy, wdelete); - - // Trigger widget select event - page.onwidgetselect(page.selected); - - return true; - }; - - /** - * Handle field on change events. - */ - wvalue.onchange = wvalue.onblur = function() { - if (page.selected == null) - return false; - page.settext(page.selected, wvalue.value); - page.selected.cover.style.width = ui.pixpos(page.selected.clientWidth + 4); - page.selected.cover.style.height = ui.pixpos(page.selected.clientHeight + 4); - - // Trigger page change event - page.onpagechange(true); - return false; - }; - - // Handle add widget event. - wadd.onclick = function() { - - // Show the palette - elem.style.left = ui.pixpos(0); - return false; - }; - - // Handle delete event. - wdelete.onclick = function() { - if (page.selected == null) - return false; - - // Reset current selection - page.widgetselect(page.selected, false, wvalue, wcopy, wdelete); - - // Remove selected widget - page.selected.parentNode.removeChild(page.selected); - page.selected.cover.parentNode.removeChild(page.selected.cover); - page.selected = null; - - // Trigger widget select event - page.onwidgetselect(null); - - // Trigger page change event - page.onpagechange(true); - return false; - }; - - // Handle copy event. - wcopy.onclick = function() { - if (page.selected == null) - return false; - if (page.selected.id.substring(0, 8) == 'palette:') - return false; - - // Reset current selection - page.widgetselect(page.selected, false, wvalue, wcopy, wdelete); - - // Clone selected widget - page.selected = page.clone(page.selected); - - // Move 10 pixels down right - page.selected.style.left = ui.pixpos(ui.numpos(page.selected.style.left) + 10); - page.selected.style.top = ui.pixpos(ui.numpos(page.selected.style.top) + 10); - page.selected.cover.style.left = ui.pixpos(ui.numpos(page.selected.cover.style.left) + 10); - page.selected.cover.style.top = ui.pixpos(ui.numpos(page.selected.cover.style.top) + 10); - - // Bring it to the top - page.bringtotop(page.selected); - - // Select the element - page.widgetselect(page.selected, true, wvalue, wcopy, wdelete); - - // Trigger widget select event - page.onwidgetselect(page.selected); - - // Trigger page change event - page.onpagechange(true); - return false; - }; - - // Cover child elements with span elements to prevent - // any input events to reach them - map(page.cover, nodeList(elem.childNodes)); - - return elem; -}; - -/** - * Return the text of a widget. - */ -page.text = function(e) { - function formula(e) { - var f = e.id; - if (f.substring(0, 5) != 'page:') - return '=' + f; - return ''; - } - - function constant(e, f) { - if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') { - var t = car(childElements(e)).innerHTML; - return t == f? '' : t; - } - if (e.className == 'button' || e.className == 'checkbox') { - var t = car(childElements(e)).value; - return t == f? '' : t; - } - if (e.className == 'entry' || e.className == 'password') { - var t = car(childElements(e)).defaultValue; - return t == f? '' : t; - } - if (e.className == 'select') { - var t = car(childElements(car(childElements(e)))).value; - return t == f? '' : t; - } - if (e.className == 'link') { - var lhr = car(childElements(e)).href; - var hr = lhr.substring(0, 5) == 'link:'? lhr.substring(5) : ''; - var t = car(childElements(car(childElements(e)))).innerHTML; - return t == f? hr : (t == hr? hr : (t == ''? hr : hr + ',' + t)); - } - if (e.className == 'img') { - var src = car(childElements(e)).src; - return src == window.location.href? '' : src; - } - if (e.className == 'iframe') { - var hr = car(childElements(e)).href; - return hr == window.location.href? '' : hr; - } - if (e.className == 'list') - return ''; - if (e.className == 'table') - return ''; - return ''; - } - - var f = formula(e); - var c = constant(e, f); - return f == ''? c : (c == ''? f : f + ',' + c); -}; - -/** - * Return true if a widget has editable text. - */ -page.hastext = function(e) { - if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') - return true; - if (e.className == 'button' || e.className == 'checkbox') - return true; - if (e.className == 'entry' || e.className == 'password') - return true; - if (e.className == 'select') - return false; - if (e.className == 'link') - return true; - if (e.className == 'img') - return true; - if (e.className == 'iframe') - return true; - if (e.className == 'list') - return false; - if (e.className == 'table') - return false; - return false; -}; - -/** - * Set the text of a widget. - */ -page.settext = function(e, t) { - function formula(t) { - if (t.length > 1 && t.substring(0, 1) == '=') - return car(t.split(',')); - return ''; - } - - function constant(t) { - return t.length > 1 && t.substring(0, 1) == '='? cdr(t.split(',')) : t.split(','); - } - - var f = formula(t); - var c = constant(t); - - e.id = f != ''? f.substring(1) : ('page:' + e.className); - - if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') { - car(childElements(e)).innerHTML = isNil(c)? f : car(c); - return t; - } - if (e.className == 'button' || e.className == 'entry' || e.className == 'password') { - car(childElements(e)).defaultValue = isNil(c)? f : car(c); - return t; - } - if (e.className == 'checkbox') { - car(childElements(e)).value = isNil(c)? f : car(c); - map(function(n) { if (n.nodeName == "SPAN") n.innerHTML = isNil(c)? f : car(c); return n; }, nodeList(e.childNodes)); - return t; - } - if (e.className == 'select') { - var ce = car(childElements(car(childElements(e)))); - ce.value = isNil(c)? f : car(c); - ce.innerHTML = isNil(c)? f : car(c); - return t; - } - if (e.className == 'list') { - e.innerHTML = '<table class="datatable" style="width: 100%;;"><tr><td class="datatd">' + (isNil(c)? f : car(c)) + '</td></tr><tr><td class="datatd">...</td></tr></table>'; - return t; - } - if (e.className == 'table') { - e.innerHTML = '<table class="datatable" style="width: 100%;"><tr><td class="datatdl">' + (isNil(c)? f : car(c)) + '</td><td class="datatdr">...</td></tr><tr><td class="datatdl">...</td><td class="datatdr">...</td></tr></table>'; - return t; - } - if (e.className == 'link') { - var ce = car(childElements(e)); - ce.href = isNil(c)? 'link:/index.html' : ('link:' + car(c)); - car(childElements(ce)).innerHTML = isNil(c)? (f != ''? f : '/index.html') : isNil(cdr(c))? (f != ''? f : car(c)) : cadr(c); - return t; - } - if (e.className == 'img') { - car(childElements(e)).src = isNil(c)? '/public/img.png' : car(c); - return t; - } - if (e.className == 'iframe') { - car(childElements(e)).href = isNil(c)? '/public/iframe.html' : car(c); - return t; - } - return ''; -}; - -/** - * Initial fixup of a widget. - */ -page.fixupwidget = function(e) { - if (e.className == 'iframe') { - var f = car(childElements(e)); - //e.innerHTML = '<iframe src="' + f.href + '" frameborder="no" scrolling="no"></iframe>'; - return e; - } - if (e.className == 'section') { - e.style.width = '100%'; - return e; - } - if (e.className == 'list') { - e.style.width = '100%'; - car(childElements(e)).style.width = '100%'; - return e; - } - if (e.className == 'table') { - e.style.width = '100%'; - car(childElements(e)).style.width = '100%'; - return e; - } - return e; -} - -/** - * Find a draggable element in a hierarchy of elements. - */ -page.draggable = function(n, e) { - if (n == e) - return null; - if (n.id != '') - return n; - if (n.covered) - return n.covered; - return page.draggable(n.parentNode, e); -} - -/** - * Align a pos along a 9pixel grid. - */ -page.gridsnap = function(x) { - return Math.round(x / 9) * 9; -} - -/** - * Bring an element and its parent to the top. - */ -page.bringtotop = function(n) { - n.parentNode.appendChild(n); - n.cover.parentNode.appendChild(n.cover); -} - -/** - * Draw widget selection. - */ -page.widgetselect = function(n, s, wvalue, wcopy, wdelete) { - if (isNil(n) || !s) { - // Clear the widget value field - wvalue.value = ''; - wvalue.disabled = true; - wcopy.disabled = true; - wdelete.disabled = true; - - // Clear the widget outline - if (!isNil(n)) - n.cover.style.borderWidth = '0px'; - return true; - } - - // Update the widget value field - wvalue.value = page.text(n); - wvalue.disabled = false; - wcopy.disabled = false; - wdelete.disabled = false; - - // Outline the widget - n.cover.style.borderWidth = '2px'; - return true; -}; - -/** - * Cover a page element with a <span> element to prevent - * any input events to reach it. - */ -page.cover = function(e) { - if (e.id == '' || isNil(e.style)) - return e; - var cover = document.createElement('div'); - cover.style.position = 'absolute'; - cover.style.left = ui.pixpos(ui.numpos(e.style.left) - 2); - cover.style.top = ui.pixpos(ui.numpos(e.style.top) - 2); - cover.style.width = ui.pixpos(e.clientWidth + 4); - cover.style.height = ui.pixpos(e.clientHeight + 4); - cover.style.visibility = 'inherit'; - cover.style.borderStyle = 'solid'; - cover.style.borderWidth = '0px'; - cover.style.borderColor = '#598edd'; - cover.style.padding = '0px'; - cover.style.margin = '0px'; - cover.covered = e; - e.cover = cover; - e.parentNode.appendChild(cover); - return e; -} - -/** - * Clone a palette element. - */ -page.clone = function(e) { - - /** - * Clone an element's HTML. - */ - function mkclone(e) { - var ne = document.createElement('span'); - - // Skip the palette: prefix - ne.id = 'page:' + e.id.substr(8); - - // Copy the class and HTML content - ne.className = e.className; - ne.innerHTML = e.innerHTML; - - // Fixup the widget style - page.fixupwidget(ne); - - return ne; - } - - /** - * Clone an element's position. - */ - function posclone(ne, e) { - ne.style.position = 'absolute'; - ne.style.left = ui.pixpos(ui.numpos(e.style.left)); - ne.style.top = ui.pixpos(ui.numpos(e.style.top)); - e.parentNode.appendChild(ne); - page.cover(ne); - return ne; - } - - return posclone(mkclone(e), e); -}; - diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/app.b64 b/sca-cpp/trunk/modules/edit/htdocs/public/app.b64 new file mode 100644 index 0000000000..7ed235aa14 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/public/app.b64 @@ -0,0 +1 @@ +iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAABGdBTUEAALGPC/xhBQAAAAxQTFRFyN+N+dR1/PCI////6HjE5gAAADJJREFUKM9j+I8EPjBQifeBAQSY6coLBYN6inhaq0Bg6SDn/f//akB466ExTS6P2ukMAKumzarJO/66AAAAAElFTkSuQmCC
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/delete.b64 b/sca-cpp/trunk/modules/edit/htdocs/public/delete.b64 new file mode 100644 index 0000000000..c8137d7ab4 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/public/delete.b64 @@ -0,0 +1 @@ +iVBORw0KGgoAAAANSUhEUgAAABkAAAAZCAYAAADE6YVjAAAAAXNSR0IArs4c6QAAAAZiS0dEANAAPwBBXloXjQAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sEFhQaKzNh4PgAAAMKSURBVEjHxZZPTBNBFMa/maVbWjcUi0YiIHIoNBADTUgsqCWgUUFjwkk5CXLUBKIc9KIXjx64oMSDoiggGC8koImCGDWYkADRIiQQgikWCq0WoXW33R0PpYjSLeWP8btN3sv85s17894QrKNeIBng8gFmJSDZgGIAqJeBjQCkH5AHioGZaHsQNUMP+ByKYB0ByVjvIAxsUkHcrRJI9pggXYBWB1pLQUqxQSlg3X4o9WWAqArpAhL04JoIYMQmxQCPD3JlGbCwBtIFaPXgWrcC+AtUEY6Ihg060NrtACyf3KgDrQ2v6e8kbzwH0URBSnvA56xAKIJ1kRzNbS2ZNhYssjodVj41VbPaxqemaqxOh9XGgkXmtpbMyKDQvqQXSKbg2iKGzfPE0v8uV7BYDIuDg95B66FhJkmM8DyxfHifK+TlGRaHhryDBwuHmSSxyBUnn6Ohh6aSQElin86U26XZWVGwWAxZD5tMAGBufmAS8vIMkssl2s+Uj6gBQuLySS/oTQpyONr9GmxHhAMvnltovJZ+73vjTiyyJSmipHw8WTrkfd33Y52385arAr1EAF00R3HqixRwu38mnT61O35/uh4AJq7Ujc0/affEUGsCDfWi9TXX3uEOeDwBABCnp/3OO42uGPuAgQLUG4urueVRlsZo1ACANiVFZ7rTkBFjMXtpqJtGV9q1q3uNJ47vlpd88kTt5VEWCLLk6gtpeyrP74qheY5wlaB6AhSqOSUUFOzIun8vh8RxZKKmZvRrw20X0WjkxCKbceexo0Z3Z+d8wDUXVIeQdgrIA6rFl5DAmVsfZ1MtT+faO5zOxrtzADB1/Ybj28tX85wgxOU8e5pN9XqqHos8QIuBGQY2GTEPD5tM8en79P7x8aWxqurx1bbPZytGRYfDrzOZBHPzA5PanCkGZki4d3GQG7DNksFdLIFkpwBQAsmugHVvJ0AB6w5PypW79EOpZ4BnOwAM8Pih1P/R6gGgDBB9kCu3Clo1GcU1kGXQgg9yxWavTgHrXp6IC///t/Iv/l2/AGa0Qa2X0eC0AAAAAElFTkSuQmCC
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/grid72.b64 b/sca-cpp/trunk/modules/edit/htdocs/public/grid72.b64 new file mode 100644 index 0000000000..34be13e5ca --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/public/grid72.b64 @@ -0,0 +1 @@ +iVBORw0KGgoAAAANSUhEUgAAAEgAAABIAgMAAAAog1vUAAAABGdBTUEAALGPC/xhBQAAAAlQTFRFwuD84/T+////fj9v9QAAACxJREFUOMtjWLUqa9WsVctWrYQxVjAMCqFQdBDCMOrUUaeOOnXUqYPPqZgAABmg/C7pJC7lAAAAAElFTkSuQmCC
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/iframe.html b/sca-cpp/trunk/modules/edit/htdocs/public/iframe.html index a9a9efc4b3..e2b862dbaa 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/public/iframe.html +++ b/sca-cpp/trunk/modules/edit/htdocs/public/iframe.html @@ -17,13 +17,8 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> +<html> <head> -<title>frame</title> -<meta name="viewport" content="width=device-width user-scalable=no initial-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="stylesheet" type="text/css" href="/ui-min.css"/> </head> <body style="margin:3px; padding: 0px; background-color: #dcdcdc;"> diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/img.b64 b/sca-cpp/trunk/modules/edit/htdocs/public/img.b64 new file mode 100644 index 0000000000..97dae687a0 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/public/img.b64 @@ -0,0 +1 @@ +iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAMAAABEpIrGAAAABGdBTUEAALGPC/xhBQAAAIRQTFRFwdt/w9yEw9+MxN2GxN6NxN+Oxd2Mxd6Nxt6Lx96Lx96Nx9+NyN6MyN+MyN+N8u2I8+2I+NBq+NFr+NFt+NFu+NJz+NN0+dR1+dR3+dZw+dh4+9Fy+9Nz++5++++B+++F/NNz/PCH/PCI/PGW/PKc/fKd/vzp/vzq/v7+/v/z/9Jx////nQZfHwAAAIxJREFUOMtj0CYAGKiiQANdUAPdBAZmFMCIYQUzHwrgpKECblYwYEJ2LYoCHi0FMBCEAmF0E3hkxFGABJICXnYWFhY2aVE4EENTwCWgCARKCCCFoUAJFQw9BYycnBz8eBSA04cqPhNAQIX+CiSFhIRE8CiQ10ROMNgUqKNnHGU5FCCrhqZAg7Z5Ey8AALiBh6brcmloAAAAAElFTkSuQmCC
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/notauth.html b/sca-cpp/trunk/modules/edit/htdocs/public/notauth.html deleted file mode 100644 index 44e68da5de..0000000000 --- a/sca-cpp/trunk/modules/edit/htdocs/public/notauth.html +++ /dev/null @@ -1,79 +0,0 @@ -<!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-manifest.cmf"> -<head> -<title>Sorry</title> -<meta name="viewport" content="width=device-width user-scalable=no initial-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="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> -<div id="bodydiv" class="bodydiv"> - -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menu"></div> - -<table style="width: 100%;"> -<tr><td><h2><span id="h1"></span></h2></td></tr> -</table> - -<div style="margin-left: auto; margin-right: auto; text-align: center;"> -<div class="hd2">Sorry, you're not authorized to view this page.</div> -</div> - -<form name="signout" action="/public/notauth.html" method="GET"> -</form> - -<script type="text/javascript"> -ui.initbody(); - -// Set page title -$('h1').innerHTML = hometitle(window.location.hostname); - -// Load the menu bar -if (!issubdomain(window.location.hostname)) - displaymenu(); - -// Sign out -if (window.top.location.pathname != '/public/notauth.html') { - function submitSignout() { - var reset = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';domain=.' + domainname(window.location.hostname) + ';path=/;secure=TRUE'; - document.cookie = reset; - document.signout.submit(); - return true; - } - - submitSignout(); -} -</script> - -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> - -</div> -</body> -</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/notfound.html b/sca-cpp/trunk/modules/edit/htdocs/public/notfound.html deleted file mode 100644 index c71f4aa0ef..0000000000 --- a/sca-cpp/trunk/modules/edit/htdocs/public/notfound.html +++ /dev/null @@ -1,65 +0,0 @@ -<!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-manifest.cmf"> -<head> -<title>Page not found</title> -<meta name="viewport" content="width=device-width user-scalable=no initial-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="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -</head> -<body class="delayed"> -<div id="bodydiv" class="bodydiv" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> - -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menu"></div> - -<table style="width: 100%;"> -<tr><td><h2><span id="h1"></span></h2></td></tr> -</table> - -<div style="margin-left: auto; margin-right: auto; text-align: center;"> -<div class="hd2">Sorry, that page was not found.</div> -<div>You may have clicked an expired link or mistyped the address.</div> -</div> - -<script type="text/javascript"> -ui.initbody(); - -// Set page title -$('h1').innerHTML = hometitle(window.location.hostname); - -// Load the menu bar -if (!issubdomain(window.location.hostname)) - displaymenu(); -</script> - -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> - -</div> -</body> -</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/notyet.html b/sca-cpp/trunk/modules/edit/htdocs/public/notyet.html deleted file mode 100644 index 591d8be991..0000000000 --- a/sca-cpp/trunk/modules/edit/htdocs/public/notyet.html +++ /dev/null @@ -1,64 +0,0 @@ -<!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-manifest.cmf"> -<head> -<title>Page not found</title> -<meta name="viewport" content="width=device-width user-scalable=no initial-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="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> -<div id="bodydiv" class="bodydiv"> - -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> -<div id="menu"></div> - -<table style="width: 100%;"> -<tr><td><h2><span id="h1"></span></h2></td></tr> -</table> - -<div style="margin-left: auto; margin-right: auto; text-align: center;"> -<div class="hd2">Sorry, that page is still under construction.</div> -<div>Please check back later.</div> -</div> - -<script type="text/javascript"> -ui.initbody(); - -// Set page title -$('h1').innerHTML = hometitle(window.location.hostname); - -// Load the menu bar -if (!issubdomain(window.location.hostname)) - displaymenu(); -</script> - -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> - -</div> -</body> -</html> diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/touchicon.b64 b/sca-cpp/trunk/modules/edit/htdocs/public/touchicon.b64 new file mode 100644 index 0000000000..2239f6ae0f --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/public/touchicon.b64 @@ -0,0 +1 @@ +iVBORw0KGgoAAAANSUhEUgAAADkAAAA5CAIAAAADehTSAAAAAXNSR0IArs4c6QAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sDGxMkCJXGmL8AAAHwSURBVGje7ZpNbhNBEIXf625sCzA/QUhkg8SGiGxZcpDcgRux5hLkEjkE7BAS9gIyk+muxyZIsSeOG09bsXHX0p4pfVNdP8/loSTsiTnsj1XWyrrMutVSG+ic/ftNqe1mIMtSjsPUu9EQJ6H/UdvNLr59cgwFWaM1p8dnLx6dFGYF6RhIXzLVGIChB3VX8Fg0DWrPqqyHxTq4MUnKKEEBoNvIN4uxiqTkofUXpgZKsqtMx3Djpb45lNWAxxbfXf6wtdH9+vkKBLLGrFLz4M1HTk+K5gAIgBCVcaTI1gOK/acazqqbw2PdYzE7tdyh9AFJTL0zNDIJMInAZpKPzBzmIZuUnjoa9QQkOBHAyWbigYDaTslybg/59f7Q4+003pqwhqcbqjLH9H2OXw0Ksl6XsWB/a39lhf1rz8vOnKoHKmtlrayVtbLuuc6SFK1Z2hEZkBwAv1us4zA9PT7rDX3v9dPiOeBxT/uY0A+qd6Pbl2Sax/kXDN9LlcrXO3Rk9k/QWluVtbIe2O5toBGwFum3bLH/pEso7RarrPNHH/D8JbBIpsjJqx2Lq3Xu2Xv61yvXJzf6/b3nK2Htyu8WB9P/XltF/wfVllgFxet9azGL+bjMD5IUYbPSMktwT8hRSdalkizcufKcs77vUlkr61bsD5lbwtgOKPT2AAAAAElFTkSuQmCC
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/user.b64 b/sca-cpp/trunk/modules/edit/htdocs/public/user.b64 new file mode 100644 index 0000000000..7ed235aa14 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/public/user.b64 @@ -0,0 +1 @@ +iVBORw0KGgoAAAANSUhEUgAAADIAAAAyAgMAAABjUWAiAAAABGdBTUEAALGPC/xhBQAAAAxQTFRFyN+N+dR1/PCI////6HjE5gAAADJJREFUKM9j+I8EPjBQifeBAQSY6coLBYN6inhaq0Bg6SDn/f//akB466ExTS6P2ukMAKumzarJO/66AAAAAElFTkSuQmCC
\ No newline at end of file diff --git a/sca-cpp/trunk/modules/edit/htdocs/public/user.png b/sca-cpp/trunk/modules/edit/htdocs/public/user.png Binary files differnew file mode 100644 index 0000000000..1f73274b76 --- /dev/null +++ b/sca-cpp/trunk/modules/edit/htdocs/public/user.png diff --git a/sca-cpp/trunk/modules/edit/htdocs/stats/index.html b/sca-cpp/trunk/modules/edit/htdocs/stats/index.html index b7dd4648c6..9fa463e822 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/stats/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/stats/index.html @@ -17,26 +17,8 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> -<head> -<title>Stats</title> -<meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> <div id="bodydiv" class="bodydiv"> -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menu"></div> - <table style="width: 100%;"> <tr> <td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td> @@ -57,7 +39,7 @@ <form id="appForm"> <table style="width: 100%;"> <tr><tr><td><b>App Icon:</b></td></tr> -<tr><td><img src="/public/app.png" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> +<tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr> <tr><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr> <tr><td><input type="checkbox" value="shared"/><span>Shared</span></td></tr> <tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr> @@ -70,20 +52,17 @@ </form> <script type="text/javascript"> -ui.initbody(); // Get the app name -var appname = ui.fragmentParams()['app']; -if (isNil(appname)) - window.open('/', '_self'); +var appname = ui.fragmentParams(location)['app']; /** * Return the link to an app. */ function applink(appname) { - var protocol = window.location.protocol; - var host = window.location.hostname; - var port = ':' + window.location.port; + var protocol = location.protocol; + var host = location.hostname; + var port = ':' + location.port; if (port == ':80' || port == ':443' || port == ':') port = ''; var link = protocol + '//' + appname + '.' + host + port + '/'; @@ -91,14 +70,14 @@ function applink(appname) { } // Set page titles -document.title = windowtitle(window.location.hostname) + ' - Stats - ' + appname; +document.title = ui.windowtitle(location.hostname) + ' - Stats - ' + appname; $('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>'; var tclone = isNil(config.clone)? 'Clone' : config.clone; $('cloneApp').value = tclone; $('cloneApp').title = tclone + ' this app'; -// Load the menu bar -displaymenu(); +// Set images +$('appimg').src = ui.b64img(appcache.get('/public/app.b64')); // Init service references var editWidget = sca.component("EditWidget"); @@ -176,18 +155,12 @@ $('appForm').onsubmit = function() { * Handle Clone button event. */ $('cloneApp').onclick = function() { - return ui.navigate('/clone/#app=' + appname, '_self'); + return ui.navigate('/#view=clone&app=' + appname, '_view'); } // Get the current app getapp(appname); -</script> -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> +</script> </div> -</body> -</html> - diff --git a/sca-cpp/trunk/modules/edit/htdocs/store/index.html b/sca-cpp/trunk/modules/edit/htdocs/store/index.html index e63dbdb834..1a04b406ac 100644 --- a/sca-cpp/trunk/modules/edit/htdocs/store/index.html +++ b/sca-cpp/trunk/modules/edit/htdocs/store/index.html @@ -17,26 +17,8 @@ * specific language governing permissions and limitations * under the License. --> -<html manifest="/cache-manifest.cmf"> -<head> -<title>Store</title> -<meta name="viewport" content="width=device-width, user-scalable=no, initial-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" href="/public/touchicon.png"/> -<link rel="stylesheet" type="text/css" href="/ui-min.css"/> -<script type="text/javascript" src="/all-min.js"></script> -<script type="text/javascript" src="/menu.js"></script> -</head> -<body class="delayed" onload="ui.onload();" onbeforeunload="ui.onbeforeunload();"> <div id="bodydiv" class="bodydiv"> -<div id="headdiv" class="hsection"> -<script type="text/javascript" src="/headconfig.js"></script> -</div> - -<div id="menu"></div> - <table style="width: 100%;"> <tr><td><h2><span id="h1"></span></h2></td></tr> </table> @@ -46,17 +28,13 @@ <div id="apps"></div> <script type="text/javascript"> -ui.initbody(); // Set page titles -document.title = windowtitle(window.location.hostname) + ' - Store'; -$('h1').innerHTML = hometitle(window.location.hostname); - -// Display the menu bar -displaymenu(); +document.title = ui.windowtitle(location.hostname) + ' - Store'; +$('h1').innerHTML = ui.hometitle(location.hostname); // Get the store category -var category = ui.fragmentParams()['category']; +var category = ui.fragmentParams(location)['category']; if (isNil(category)) category = 'myapps'; @@ -64,18 +42,18 @@ if (isNil(category)) * Build store menu bar */ function catmenu() { - function catmenuitem(name, cat) { + function catmenuitem(name, cat, idx) { var c = cat == category? 'smenu' : 'amenu'; return '<th class="thl thr" style="width: 10px; padding-top: 4px; padding-bottom: 4px; padding-right: 6px;">' - + ui.ahref('/store/#category=' + cat, '_reload', '<span class="' + c + '">' + name + '</span>') + '</th>'; + + ui.ahref('/#view=store&category=' + cat + '&idx=' + idx, '_view', '<span class="' + c + '">' + name + '</span>') + '</th>'; } var m = '<table style="width: 100%; margin-bottom: 2px;"><tr>'; - m += catmenuitem('My Apps', 'myapps'); - m += catmenuitem('New', 'new'); - m += catmenuitem('Top', 'top'); - m += catmenuitem('Featured', 'featured'); - m += catmenuitem('All', 'all'); + m += catmenuitem('My Apps', 'myapps', '1'); + m += catmenuitem('New', 'new', '2'); + m += catmenuitem('Top', 'top', '3'); + m += catmenuitem('Featured', 'featured', '4'); + m += catmenuitem('All', 'all', '5'); if (category == 'myapps') { m += '<th class="thl thr" style="width: 100%; padding-top: 0px; padding-bottom: 0px; padding-right: 0px; text-align: right;">'; m += '<input type="button" class="graybutton" id="createApp" title="Create a new app" style="font-weight: bold; margin-top: 0px; margin-bottom: 0px; height: 24px;" Value="New App"/>'; @@ -100,9 +78,9 @@ var dashboards = sca.reference(editWidget, "dashboards"); * Return the link to an app. */ function applink(appname) { - var protocol = window.location.protocol; - var host = window.location.hostname; - var port = ':' + window.location.port; + var protocol = location.protocol; + var host = location.hostname; + var port = ':' + location.port; if (port == ':80' || port == ':443' || port == ':') port = ''; var link = protocol + '//' + appname + '.' + host + port + '/'; @@ -113,14 +91,14 @@ function applink(appname) { * Edit an app. */ function editApp(appname) { - return ui.navigate('/page/#app=' + appname, '_self'); + return ui.navigate('/#view=page&app=' + appname, '_view'); } /** * View an app. */ function viewApp(appname) { - return ui.navigate('/stats/#app=' + appname, '_self'); + return ui.navigate('/#view=stats&app=' + appname, '_view'); } /** @@ -128,7 +106,7 @@ function viewApp(appname) { */ if (category == 'myapps') { $('createApp').onclick = function() { - return ui.navigate('/create/', '_self'); + return ui.navigate('/#view=create', '_view'); } } @@ -136,6 +114,7 @@ if (category == 'myapps') { * Get and display list of apps. */ function getapps(category) { + //log('category', category); function display(doc) { // Stop now if we didn't get the apps @@ -147,6 +126,8 @@ function getapps(category) { var aentries = assoc("'entry", cdr(feed)); var entries = isNil(aentries)? mklist() : isList(car(cadr(aentries)))? cadr(aentries) : mklist(cdr(aentries)); + var appimg = ui.b64img(appcache.get('/public/app.b64')); + function displayentries(entries) { if (isNil(entries)) return apps; @@ -159,7 +140,7 @@ function getapps(category) { apps += '<div class="box" style="width: 150px; display: inline-block; border: 1px; border-style: solid; border-color: #dcdcdc; border-collapse: collapse; margin: 2px; padding: 2px; vertical-align: top;">' apps += '<table><tr>'; apps += '<td>'; - apps += '<div>' + ui.ahref('/stats/#app=' + name, '_self', '<img src="/public/app.png" width="50" height="50" style="height: 50px; width: 50px; vertical-align: top; margin: 0px; padding: 0px;"></img>') + '</div>'; + apps += '<div>' + ui.ahref('/#view=stats&app=' + name, '_view', '<img src="' + appimg + '" width="50" height="50" style="height: 50px; width: 50px; vertical-align: top; margin: 0px; padding: 0px;"></img>') + '</div>'; apps += '</td>'; apps += '<td class="tdw">'; apps += '<div style="font-weight: bold">' + ui.ahref(applink(name), '_blank', name) + '</div>'; @@ -186,13 +167,7 @@ function getapps(category) { // Get and display the list of apps getapps(category); -</script> -<div id="footdiv" class="fsection"> -<script type="text/javascript" src="/footconfig.js"></script> -</div> +</script> </div> -</body> -</html> - diff --git a/sca-cpp/trunk/modules/edit/ssl-start b/sca-cpp/trunk/modules/edit/ssl-start index 576fa39463..050de3e83c 100755 --- a/sca-cpp/trunk/modules/edit/ssl-start +++ b/sca-cpp/trunk/modules/edit/ssl-start @@ -51,18 +51,18 @@ jsprefix=`echo "import os; print os.path.realpath('$here/../js')" | python` # Configure error pages cat >>tmp/conf/svhost-ssl.conf <<EOF # Error pages -ErrorDocument 404 /public/notfound.html -ErrorDocument 401 /public/notauth.html -ErrorDocument 500 /public/oops.html +ErrorDocument 404 /notfound/ +ErrorDocument 401 /notauth/ +ErrorDocument 500 /oops/ EOF # Configure app home pages cat >>tmp/conf/dvhost-ssl.conf <<EOF # App error pages -ErrorDocument 404 /public/notfound.html -ErrorDocument 401 /public/notauth.html -ErrorDocument 500 /public/oops.html +ErrorDocument 404 /notfound/ +ErrorDocument 401 /notauth/ +ErrorDocument 500 /oops/ # Redirect www to main home page RewriteEngine on @@ -101,7 +101,8 @@ EOF # Configure main aliases cat >>tmp/conf/httpd.conf <<EOF -Alias /home.png $here/htdocs/home.png +Alias /home/home.png $here/htdocs/home/home.png +Alias /home/home.b64 $here/htdocs/home/home.b64 EOF @@ -120,7 +121,10 @@ Alias /headconfig.js $here/htdocs/headconfig.js Alias /index.html $here/htdocs/app/index.html Alias /login $here/htdocs/login Alias /logout $here/htdocs/logout -Alias /menu.js $here/htdocs/menu.js +Alias /notauth $here/htdocs/notauth +Alias /notfound $here/htdocs/notfound +Alias /notyet $here/htdocs/notyet +Alias /oops $here/htdocs/oops Alias /public $here/htdocs/public Alias /robots.txt $here/htdocs/robots.txt diff --git a/sca-cpp/trunk/modules/edit/start b/sca-cpp/trunk/modules/edit/start index 6125ba02bf..b9fe5953d6 100755 --- a/sca-cpp/trunk/modules/edit/start +++ b/sca-cpp/trunk/modules/edit/start @@ -35,18 +35,18 @@ jsprefix=`echo "import os; print os.path.realpath('$here/../js')" | python` # Configure error pages cat >>tmp/conf/svhost.conf <<EOF # Error pages -ErrorDocument 404 /public/notfound.html -ErrorDocument 401 /public/notauth.html -ErrorDocument 500 /public/oops.html +ErrorDocument 404 /notfound/ +ErrorDocument 401 /notauth/ +ErrorDocument 500 /oops/ EOF # Configure app home pages cat >>tmp/conf/dvhost.conf <<EOF # App error pages -ErrorDocument 404 /public/notfound.html -ErrorDocument 401 /public/notauth.html -ErrorDocument 500 /public/oops.html +ErrorDocument 404 /notfound/ +ErrorDocument 401 /notauth/ +ErrorDocument 500 /oops/ # Redirect www to main home page RewriteEngine on @@ -70,6 +70,14 @@ SCAVirtualComposite app.composite EOF +# Configure main aliases +cat >>tmp/conf/httpd.conf <<EOF + +Alias /home/home.png $here/htdocs/home/home.png +Alias /home/home.b64 $here/htdocs/home/home.b64 + +EOF + # Create app links and sub-directories if needed ./mkapplinks @@ -85,7 +93,10 @@ Alias /headconfig.js $here/htdocs/headconfig.js Alias /index.html $here/htdocs/app/index.html Alias /login $here/htdocs/login Alias /logout $here/htdocs/logout -Alias /menu.js $here/htdocs/menu.js +Alias /notauth $here/htdocs/notauth +Alias /notfound $here/htdocs/notfound +Alias /notyet $here/htdocs/notyet +Alias /oops $here/htdocs/oops Alias /public $here/htdocs/public Alias /robots.txt $here/htdocs/robots.txt diff --git a/sca-cpp/trunk/modules/http/conf/mime.types b/sca-cpp/trunk/modules/http/conf/mime.types index c0dba0ef86..430aa95f0f 100644 --- a/sca-cpp/trunk/modules/http/conf/mime.types +++ b/sca-cpp/trunk/modules/http/conf/mime.types @@ -546,7 +546,7 @@ text/directory text/enriched text/html html htm text/parityfec -text/plain asc txt +text/plain asc txt b64 text/prs.lines.tag text/rfc822-headers text/richtext rtx diff --git a/sca-cpp/trunk/modules/http/httpd-conf b/sca-cpp/trunk/modules/http/httpd-conf index 44f3cc8586..d672b2dce5 100755 --- a/sca-cpp/trunk/modules/http/httpd-conf +++ b/sca-cpp/trunk/modules/http/httpd-conf @@ -284,6 +284,11 @@ cat >$root/conf/vhost.conf <<EOF # Virtual host configuration UseCanonicalName Off +# Enable HTTP reverse proxy +ProxyRequests Off +ProxyPreserveHost Off +ProxyStatus On + EOF cat >$root/conf/svhost.conf <<EOF diff --git a/sca-cpp/trunk/modules/http/httpd-ssl-conf b/sca-cpp/trunk/modules/http/httpd-ssl-conf index 77a4898e74..9de67ff716 100755 --- a/sca-cpp/trunk/modules/http/httpd-ssl-conf +++ b/sca-cpp/trunk/modules/http/httpd-ssl-conf @@ -129,6 +129,18 @@ SSLRequire %{SSL_CIPHER_USEKEYSIZE} >= 128 LogFormat "[%{%a %b %d %H:%M:%S %Y}t] [sslaccess] %h %l %u %{SSL_PROTOCOL}x %{SSL_CIPHER}x \"%r\" %>s %b \"%{Referer}i\" \"%{User-agent}i\" \"%{SSL_CLIENT_I_DN}x\" \"%{SSL_CLIENT_S_DN}x\" \"%{cookie}n\" %A %V %D %I %O" sslcombined CustomLog $root/logs/ssl_access_log sslcombined +# Enable HTTPS reverse proxy +ProxyRequests Off +ProxyPreserveHost Off +ProxyStatus On +SSLProxyEngine on +SSLProxyCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL + +# Verify server certificates +SSLProxyVerify require +SSLProxyVerifyDepth 1 +SSLProxyCheckPeerCN Off + EOF proxycert="server" @@ -144,8 +156,12 @@ Include conf/vhost-ssl.conf # Declare SSL certificates used in this virtual host SSLCACertificateFile "$root/cert/ca.crt" SSLCertificateChainFile "$root/cert/ca.crt" -SSLCertificateFile "$root/cert/server.crt" -SSLCertificateKeyFile "$root/cert/server.key" +SSLCertificateFile "$root/cert/vhost.crt" +SSLCertificateKeyFile "$root/cert/vhost.key" + +# Declare proxy SSL client certificates +SSLProxyCACertificateFile "$root/cert/ca.crt" +SSLProxyMachineCertificateFile "$root/cert/$proxycert.pem" EOF diff --git a/sca-cpp/trunk/modules/http/mod-openauth.cpp b/sca-cpp/trunk/modules/http/mod-openauth.cpp index 9fd6579265..c2791b5402 100644 --- a/sca-cpp/trunk/modules/http/mod-openauth.cpp +++ b/sca-cpp/trunk/modules/http/mod-openauth.cpp @@ -199,6 +199,7 @@ static int checkAuthn(request_rec *r) { if (!dc.enabled) return DECLINED; const char* atype = ap_auth_type(r); + debug(atype, "modopenauth::checkAuthn::auth_type"); if (atype == NULL || strcasecmp(atype, "Open")) return DECLINED; diff --git a/sca-cpp/trunk/modules/http/proxy-conf b/sca-cpp/trunk/modules/http/proxy-conf index 8bca7cd2de..9094996b4b 100755 --- a/sca-cpp/trunk/modules/http/proxy-conf +++ b/sca-cpp/trunk/modules/http/proxy-conf @@ -24,11 +24,6 @@ root=`echo "import os; print os.path.realpath('$1')" | python` cat >>$root/conf/vhost.conf <<EOF # Generated by: proxy-conf $* -# Enable HTTP reverse proxy -ProxyRequests Off -ProxyPreserveHost On -ProxyStatus On - # Enable load balancing ProxyPass / balancer://cluster/ diff --git a/sca-cpp/trunk/modules/http/proxy-ssl-conf b/sca-cpp/trunk/modules/http/proxy-ssl-conf index af8fce8179..6897a0ff47 100755 --- a/sca-cpp/trunk/modules/http/proxy-ssl-conf +++ b/sca-cpp/trunk/modules/http/proxy-ssl-conf @@ -24,17 +24,6 @@ root=`echo "import os; print os.path.realpath('$1')" | python` cat >>$root/conf/vhost-ssl.conf <<EOF # Generated by: proxy-ssl-conf $* -# Enable HTTPS reverse proxy -ProxyRequests Off -ProxyPreserveHost On -ProxyStatus On -SSLProxyEngine on -SSLProxyCipherSuite ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP:+eNULL - -# Verify server certificates -SSLProxyVerify require -SSLProxyVerifyDepth 1 - # Enable load balancing ProxyPass /balancer-manager ! ProxyPass / balancer://sslcluster/ @@ -63,7 +52,6 @@ EOF cat >>$root/conf/dvhost-ssl.conf <<EOF # Generated by: proxy-ssl-conf $* - # Declare proxy SSL client certificates SSLProxyCACertificateFile "$root/cert/ca.crt" SSLProxyMachineCertificateFile "$root/cert/proxy.pem" diff --git a/sca-cpp/trunk/modules/js/htdocs/all-min.js b/sca-cpp/trunk/modules/js/htdocs/all-min.js index 921abf170e..b214be0ad8 100644 --- a/sca-cpp/trunk/modules/js/htdocs/all-min.js +++ b/sca-cpp/trunk/modules/js/htdocs/all-min.js @@ -1,3 +1,21 @@ +/* + * 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. + */ 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];} @@ -66,10 +84,6 @@ function properties(o){var a=new Array();for(p in o) a.push(p);return a;} function domainname(host){var h=reverse(host.split('.'));return reverse(mklist(car(h),cadr(h))).join('.');} function issubdomain(host){return host.split('.').length>2;} -function hometitle(host){if(!isNil(config.hometitle)) -return config.hometitle;var h=reverse(host.split('.'));var d=isNil(cdr(h))?car(h):cadr(h);return d.substr(0,1).toUpperCase()+d.substr(1);} -function windowtitle(host){if(!isNil(config.windowtitle)) -return config.windowtitle;var h=reverse(host.split('.'));var d=isNil(cdr(h))?car(h):cadr(h);return d.substr(0,1).toUpperCase()+d.substr(1);} function format(){var i=0;var s='';for(a in arguments){s=i==0?arguments[a]:s.replace('{'+a+'}',arguments[a]);i++;} return s;} function setcar(l,v){l[0]=v;return l;} @@ -231,56 +245,34 @@ return t;return bindingsTarget(scdl.bindings(l));} var turi=targetURI();if(isNil(turi)) return turi;return car(tokens(turi));};scdl.properties=function(l){return namedElementChildren("'property",l);};scdl.propertyValue=function(l){if(!elementHasValue(l)) return'';return elementValue(l);};scdl.nameToElementAssoc=function(l){if(isNil(l)) -return l;return cons(mklist(scdl.name(car(l)),car(l)),scdl.nameToElementAssoc(cdr(l)));};var ui={};ui.ahref=function(loc,target,html){if(target=='_blank') -return'<a href="'+loc+'" target="_blank">'+html+'</a>';return'<a href="javascript:void(0)" onclick="ui.navigate(\''+loc+'\', \''+target+'\');">'+html+'</a>';};ui.menu=function(name,href,target){function Menu(n,h,t){this.name=n;this.href=h;this.target=isNil(t)?'_parent':t;this.content=function(){function complete(uri){var h=uri.indexOf('#');if(h!=-1) -return complete(uri.substr(0,h));var q=uri.indexOf('?');if(q!=-1) -return complete(uri.substr(0,q));if(uri.match('.*\.html$')) -return uri;if(uri.match('.*/$')) -return uri+'index.html';return uri+'/index.html';} -if(complete(this.href)!=complete(window.top.location.pathname)) -return ui.ahref(this.href,this.target,'<span class="tbaramenu">'+this.name+'</span>');return ui.ahref(this.href,this.target,'<span class="tbarsmenu">'+this.name+'</span>');};} -return new Menu(name,href,target);};ui.menubar=function(left,right){var bar='<table cellpadding="0" cellspacing="0" width="100%" class="tbar"><tr>'+'<td class="dtbar"><table border="0" cellspacing="0" cellpadding="0"><tr>';for(i in left) -bar=bar+'<td class="ltbar">'+left[i].content()+'</td>' -bar=bar+'</tr></table></td>'+'<td class="dtbar"><table border="0" cellpadding="0" cellspacing="0" align="right"><tr>';for(i in right) -bar=bar+'<td class="'+(i==0?'dtbar':'rtbar')+'">'+right[i].content()+'</td>' -bar=bar+'</tr></table></td></tr></table>';return bar;};ui.selectSuggestion=function(node,value){for(;;){node=node.parentNode;if(node.tagName.toLowerCase()=='div') -break;} -node.selectSuggestion(value);};ui.hilightSuggestion=function(node,over){if(over) -node.className='suggestHilighted';node.className='suggestItem';};ui.suggest=function(input,suggestFunction){input.suggest=suggestFunction;input.selectSuggestion=function(value){this.hideSuggestDiv();this.value=value;} -input.hideSuggestDiv=function(){if(this.suggestDiv!=null){this.suggestDiv.style.visibility='hidden';}} -input.showSuggestDiv=function(){if(this.suggestDiv==null){this.suggestDiv=document.createElement('div');this.suggestDiv.input=this;this.suggestDiv.className='suggest';input.parentNode.insertBefore(this.suggestDiv,input);this.suggestDiv.style.visibility='hidden';this.suggestDiv.style.zIndex='99';this.suggestDiv.selectSuggestion=function(value){this.input.selectSuggestion(value);}} -var values=this.suggest();var items='';for(var i=0;i<values.length;i++){if(values[i].indexOf(this.value)==-1) -continue;if(items.length==0) -items+='<table class="suggestTable">';items+='<tr><td class="suggestItem" '+'onmouseover="ui.hilightSuggestion(this, true)" onmouseout="ui.hilightSuggestion(this, false)" '+'onmousedown="ui.selectSuggestion(this, \''+values[i]+'\')">'+values[i]+'</td></tr>';} -if(items.length!=0) -items+='</table>';this.suggestDiv.innerHTML=items;if(items.length!=0){var node=input;var left=0;var top=0;for(;;){left+=node.offsetLeft;top+=node.offsetTop;node=node.offsetParent;if(node.tagName.toLowerCase()=='body') -break;} -this.suggestDiv.style.left=left;this.suggestDiv.style.top=top+input.offsetHeight;this.suggestDiv.style.visibility='visible';}else -this.suggestDiv.style.visibility='hidden';} -input.onkeydown=function(event){this.showSuggestDiv();};input.onkeyup=function(event){this.showSuggestDiv();};input.onmousedown=function(event){this.showSuggestDiv();};input.onblur=function(event){setTimeout(function(){input.hideSuggestDiv();},50);};};ui.elementByID=function(node,id){for(var i in node.childNodes){var child=node.childNodes[i];if(child.id==id) +return l;return cons(mklist(scdl.name(car(l)),car(l)),scdl.nameToElementAssoc(cdr(l)));};var ui={};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;};function $(id){if(id==document){if(!isNil(document.widget)) -return document.widget;return document;} -return ui.elementByID($(document),id);};ui.queryParams=function(){var qp=new Array();var qs=window.location.search.substring(1).split('&');for(var i=0;i<qs.length;i++){var e=qs[i].indexOf('=');if(e>0) +return null;};function $(id){if(id==document) +return document;return ui.elementByID($(document),id);};ui.query=function(url){var u=''+url;var q=u.indexOf('?');return q>=0?u.substring(q+1):'';};ui.fragment=function(url){var u=''+url;var h=u.indexOf('#');return h>=0?u.substring(h+1):'';};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):'';};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;};ui.fragmentParams=function(){var qp=new Array();var qs=window.location.hash.substring(1).split('&');for(var i=0;i<qs.length;i++){var e=qs[i].indexOf('=');if(e>0) +return qp;};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;};ui.mobiledetected=false;ui.mobile=false;ui.isMobile=function(){if(ui.mobiledetected) +return qp;};ui.b64img=function(b64){return'data:image/png;base64,'+b64;};ui.declareCSS=function(s){var e=document.createElement('style');e.type='text/css';e.textContent=s;return e;};ui.declareScript=function(s){var e=document.createElement('script');e.type='text/javascript';e.text=s;return e;};ui.innerScripts=function(e){return map(function(s){return s.text;},nodeList(e.getElementsByTagName('script')));};ui.evalScript=function(s){return eval('(function() {\n'+s+'\n})();');};ui.includeScript=function(s){log('include',s);return eval(s);};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;};ui.pagetransitions=false;ui.initbody=function(){if(ui.isMobile()){if(ui.pagetransitions){var bdiv=$('bodydiv');if(!isNil(bdiv)){bdiv.className='bodydivloading';}} -document.body.onorientationchange=ui.onorientationchange;} -return true;} -ui.onorientationchange=function(){window.open(window.location,'_self');return true;} -ui.onload=function(){var path=document.location.pathname;if(path.indexOf('/login/')!=0&&path.indexOf('/logout/')!=0) -localStorage.setItem('ui.lastvisited',''+document.location);document.body.style.visibility='visible';if(ui.pagetransitions&&ui.isMobile()){setTimeout(function(){var bdiv=$('bodydiv');if(!isNil(bdiv)){function transitionend(e){bdiv.removeEventListener('webkitTransitionEnd',transitionend,false);bdiv.removeEventListener('transitionend',transitionend,false);bdiv.className='bodydiv';};bdiv.addEventListener('webkitTransitionEnd',transitionend,false);bdiv.addEventListener('transitionend',transitionend,false);bdiv.className='bodydivloaded';}},0);} -return true;};ui.navigate=function(url,win){function opendoc(url,win){if(win=='_reload'){window.location=url;return window.location.reload();} -return window.open(url,win);} -if(ui.pagetransitions&&ui.isMobile()&&win!='_blank'){var bdiv=$('bodydiv');if(!isNil(bdiv)){function transitionend(e){bdiv.removeEventListener('webkitTransitionEnd',transitionend,false);bdiv.removeEventListener('transitionend',transitionend,false);return opendoc(url,win);};bdiv.addEventListener('webkitTransitionEnd',transitionend,false);bdiv.addEventListener('transitionend',transitionend,false);bdiv.className='bodydivunloaded';return true;}} -return opendoc(url,win);} -ui.onbeforeunload=function(){if(ui.pagetransitions&&ui.isMobile()){var bdiv=$('bodydiv');if(!isNil(bdiv)) -bdiv.className='bodydivunloaded';}};ui.lastvisited=function(){return localStorage.getItem('ui.lastvisited');} -ui.numpos=function(p){return p==''?0:Number(p.substr(0,p.length-2));};ui.pixpos=function(p){return p+'px';};ui.datatable=function(l){function indent(i){if(i==0) +ui.mobile=true;ui.mobiledetected=true;return ui.mobile;};ui.hometitle=function(host){if(!isNil(window.top.config.hometitle)) +return window.top.config.hometitle;var h=reverse(host.split('.'));var d=isNil(cdr(h))?car(h):cadr(h);return d.substr(0,1).toUpperCase()+d.substr(1);};ui.windowtitle=function(host){if(!isNil(window.top.config.windowtitle)) +return window.top.config.windowtitle;var h=reverse(host.split('.'));var d=isNil(cdr(h))?car(h):cadr(h);return d.substr(0,1).toUpperCase()+d.substr(1);};ui.numpos=function(p){return p==''?0:Number(p.substr(0,p.length-2));};ui.pixpos=function(p){return p+'px';};ui.onorientationchange=function(){window.location.reload();return true;} +ui.navigate=function(url,win){log('navigate',url,win);if(win=='_blank') +return window.top.open(url,win);if(win=='_self') +return window.top.open(url,win);if(win=='_reload'){window.top.location=url;return window.top.location.reload();} +if(win=='_view'){if(!window.top.onnavigate) +return window.top.open(url,'_self');return window.top.onnavigate(url);} +return window.top.open(url,win);} +ui.ahref=function(loc,target,html){if(target=='_blank') +return'<a href="'+loc+'" target="_blank">'+html+'</a>';return'<a href="javascript:void(0)" onclick="ui.navigate(\''+loc+'\', \''+target+'\');">'+html+'</a>';};ui.menu=function(name,href,target,hilight){function Menu(){this.content=function(){if(hilight) +return ui.ahref(href,target,'<span class="tbarsmenu">'+name+'</span>');return ui.ahref(href,target,'<span class="tbaramenu">'+name+'</span>');};} +return new Menu();};ui.menubar=function(left,right){var bar='<table cellpadding="0" cellspacing="0" width="100%" class="tbar"><tr>'+'<td class="dtbar"><table border="0" cellspacing="0" cellpadding="0"><tr>';for(i in left) +bar=bar+'<td class="ltbar">'+left[i].content()+'</td>' +bar=bar+'</tr></table></td>'+'<td class="dtbar"><table border="0" cellpadding="0" cellspacing="0" align="right"><tr>';for(i in right) +bar=bar+'<td class="'+(i==0?'dtbar':'rtbar')+'">'+right[i].content()+'</td>' +bar=bar+'</tr></table></td></tr></table>';return bar;};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);if(!isList(e)) @@ -296,7 +288,21 @@ return rows(expandElementValues("'value",l),i);if(elementHasValue(e)){var v=elem return rows(expandElementValues(elementName(e),v),i)+rows(cdr(l),i);} 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>';} -var JSONClient={};JSONClient.escapeJSONChar=function(c){if(c=="\""||c=="\\")return"\\"+c;if(c=="\b")return"\\b";if(c=="\f")return"\\f";if(c=="\n")return"\\n";if(c=="\r")return"\\r";if(c=="\t")return"\\t";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;};JSONClient.escapeJSONString=function(s){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) +ui.selectSuggestion=function(node,value){for(;;){node=node.parentNode;if(node.tagName.toLowerCase()=='div') +break;} +node.selectSuggestion(value);};ui.hilightSuggestion=function(node,over){if(over) +node.className='suggestHilighted';node.className='suggestItem';};ui.suggest=function(input,suggestFunction){input.suggest=suggestFunction;input.selectSuggestion=function(value){this.hideSuggestDiv();this.value=value;} +input.hideSuggestDiv=function(){if(this.suggestDiv!=null){this.suggestDiv.style.visibility='hidden';}} +input.showSuggestDiv=function(){if(this.suggestDiv==null){this.suggestDiv=document.createElement('div');this.suggestDiv.input=this;this.suggestDiv.className='suggest';input.parentNode.insertBefore(this.suggestDiv,input);this.suggestDiv.style.visibility='hidden';this.suggestDiv.style.zIndex='99';this.suggestDiv.selectSuggestion=function(value){this.input.selectSuggestion(value);}} +var values=this.suggest();var items='';for(var i=0;i<values.length;i++){if(values[i].indexOf(this.value)==-1) +continue;if(items.length==0) +items+='<table class="suggestTable">';items+='<tr><td class="suggestItem" '+'onmouseover="ui.hilightSuggestion(this, true)" onmouseout="ui.hilightSuggestion(this, false)" '+'onmousedown="ui.selectSuggestion(this, \''+values[i]+'\')">'+values[i]+'</td></tr>';} +if(items.length!=0) +items+='</table>';this.suggestDiv.innerHTML=items;if(items.length!=0){var node=input;var left=0;var top=0;for(;;){left+=node.offsetLeft;top+=node.offsetTop;node=node.offsetParent;if(node.tagName.toLowerCase()=='body') +break;} +this.suggestDiv.style.left=left;this.suggestDiv.style.top=top+input.offsetHeight;this.suggestDiv.style.visibility='visible';}else +this.suggestDiv.style.visibility='hidden';} +input.onkeydown=function(event){this.showSuggestDiv();};input.onkeyup=function(event){this.showSuggestDiv();};input.onmousedown=function(event){this.showSuggestDiv();};input.onblur=function(event){setTimeout(function(){input.hideSuggestDiv();},50);};};var JSONClient={};JSONClient.escapeJSONChar=function(c){if(c=="\""||c=="\\")return"\\"+c;if(c=="\b")return"\\b";if(c=="\f")return"\\f";if(c=="\n")return"\\n";if(c=="\r")return"\\r";if(c=="\t")return"\\t";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;};JSONClient.escapeJSONString=function(s){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("")+"\"";};JSONClient.toJSON=function(o){if(o==null) return"null";if(o.constructor==String) @@ -308,7 +314,7 @@ 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");else v.push(JSONClient.escapeJSONString(attr)+": "+JSONClient.toJSON(o[attr]));} -return"{"+v.join(", ")+"}";};function HTTPBindingClient(name,uri){this.name=name;this.uri=uri;this.apply=this.createApplyMethod();} +return"{"+v.join(", ")+"}";};function HTTPBindingClient(name,uri,domain){this.name=name;this.domain=domain;this.uri=uri;this.apply=this.createApplyMethod();} HTTPBindingClient.jsonrpcID=1;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;};HTTPBindingClient.makeJSONRequest=function(methodName,args,cb){var req={};req.id=HTTPBindingClient.jsonrpcID++;if(cb) @@ -320,14 +326,14 @@ HTTPBindingClient.charset=httpCharset(http);var obj;eval("obj = "+http.responseT throw new HTTPBindingClient.Exception(obj.error.code,obj.error.msg);var res=obj.result;return res;};HTTPBindingClient.prototype.jsonApply=function(req){var http=HTTPBindingClient.getHTTPRequest();var hascb=req.cb?true:false;http.open("POST",this.uri,hascb);http.setRequestHeader("Content-Type","application/json-rpc");if(hascb){http.onreadystatechange=function(){if(http.readyState==4){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){}}};http.send(req.data);return req.id;} http.send(req.data);if(http.status==200) -return HTTPBindingClient.jsonResult(http);throw new HTTPBindingClient.Exception(http.status,http.statusText);};HTTPBindingClient.prototype.get=function(id,cb){var u=this.uri+'/'+id;var hascb=cb?true:false;var item=localStorage.getItem(u);if(item!=null&&item!=''){if(!hascb) +return HTTPBindingClient.jsonResult(http);throw new HTTPBindingClient.Exception(http.status,http.statusText);};HTTPBindingClient.prototype.get=function(id,cb){var u=id?(this.uri?this.uri+'/'+id:id):this.uri;var hascb=cb?true:false;var item=localStorage.getItem(u);if(item!=null&&item!=''){if(!hascb) return item;try{cb(item);}catch(cbe){}} var http=HTTPBindingClient.getHTTPRequest();http.open("GET",u,hascb);if(hascb){http.onreadystatechange=function(){if(http.readyState==4){if(http.status==200){if(http.getResponseHeader("X-Login")!=null){try{cb(null,new HTTPBindingClient.Exception(403,'X-Login'));}catch(cbe){}}else if(http.responseText==''||http.getResponseHeader("Content-Type")==null){try{cb(null,new HTTPBindingClient.Exception(403,'No-Content'));}catch(cbe){}}else{if(item==null||http.responseText!=item){if(http.responseText!=null){localStorage.setItem(u,http.responseText);} try{cb(http.responseText);}catch(cbe){}}}} else{if(item==null){try{cb(null,new HTTPBindingClient.Exception(http.status,http.statusText));}catch(cbe){}}}}};http.send(null);return true;} http.send(null);if(http.status==200){if(http.getResponseHeader("X-Login")!=null){throw new HTTPBindingClient.Exception(403,'X-Login');}else if(http.responseText==''||http.getResponseHeader("Content-Type")==null){throw new HTTPBindingClient.Exception(403,'No-Content');} return http.responseText;} -throw new HTTPBindingClient.Exception(http.status,http.statusText);};HTTPBindingClient.prototype.getnocache=function(id,cb){var u=this.uri+'/'+id;var hascb=cb?true:false;var http=HTTPBindingClient.getHTTPRequest();http.open("GET",u,hascb);if(hascb){http.onreadystatechange=function(){if(http.readyState==4){if(http.status==200){if(http.getResponseHeader("X-Login")!=null){try{return cb(null,new HTTPBindingClient.Exception(403,'X-Login'));}catch(cbe){}}else if(http.responseText==''||http.getResponseHeader("Content-Type")==null){try{return cb(null,new HTTPBindingClient.Exception(403,'No-Content'));}catch(cbe){}}else{try{cb(http.responseText);}catch(cbe){}}}else{try{cb(null,new HTTPBindingClient.Exception(http.status,http.statusText));}catch(cbe){}}}};http.send(null);return true;} +throw new HTTPBindingClient.Exception(http.status,http.statusText);};HTTPBindingClient.prototype.getnocache=function(id,cb){var u=id?(this.uri?this.uri+'/'+id:id):this.uri;var hascb=cb?true:false;var http=HTTPBindingClient.getHTTPRequest();http.open("GET",u,hascb);if(hascb){http.onreadystatechange=function(){if(http.readyState==4){if(http.status==200){if(http.getResponseHeader("X-Login")!=null){try{return cb(null,new HTTPBindingClient.Exception(403,'X-Login'));}catch(cbe){}}else if(http.responseText==''||http.getResponseHeader("Content-Type")==null){try{return cb(null,new HTTPBindingClient.Exception(403,'No-Content'));}catch(cbe){}}else{try{cb(http.responseText);}catch(cbe){}}}else{try{cb(null,new HTTPBindingClient.Exception(http.status,http.statusText));}catch(cbe){}}}};http.send(null);return true;} http.send(null);if(http.status==200){if(http.getResponseHeader("X-Login")!=null){throw new HTTPBindingClient.Exception(403,'X-Login');}else if(http.responseText==''||http.getResponseHeader("Content-Type")==null){throw new HTTPBindingClient.Exception(403,'No-Content');} return http.responseText;} throw new HTTPBindingClient.Exception(http.status,http.statusText);};HTTPBindingClient.prototype.post=function(entry,cb){var http=HTTPBindingClient.getHTTPRequest();var hascb=cb?true:false;http.open("POST",this.uri,hascb);http.setRequestHeader("Content-Type","application/atom+xml");if(hascb){http.onreadystatechange=function(){if(http.readyState==4){if(http.status==201){try{cb(http.responseText);}catch(cbe){}} @@ -341,7 +347,9 @@ http.send(null);if(http.status==200) return true;throw new HTTPBindingClient.Exception(http.status,http.statusText);};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;};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();try{HTTPBindingClient.httpFactory=function(){return new XMLHttpRequest();};return HTTPBindingClient.httpFactory();}catch(e){} for(var i=0;i<HTTPBindingClient.msxmlNames.length;i++){try{HTTPBindingClient.httpFactory=function(){return new ActiveXObject(HTTPBindingClient.msxmlNames[i]);};return HTTPBindingClient.httpFactory();}catch(e){}} -HTTPBindingClient.httpFactory=null;throw new HTTPBindingClient.Exception(0,"Can't create XMLHttpRequest object");};var sca={};sca.httpclient=function(name,uri){return new HTTPBindingClient(name,uri);};sca.component=function(name){return new HTTPBindingClient(name,'/components/'+name);};sca.reference=function(comp,rname){return new HTTPBindingClient(comp.name+'/'+rname,"/references/"+comp.name+"/"+rname);};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++) +HTTPBindingClient.httpFactory=null;throw new HTTPBindingClient.Exception(0,"Can't create XMLHttpRequest object");};var sca={};sca.httpclient=function(name,uri,domain){return new HTTPBindingClient(name,uri,domain);};sca.component=function(name,domain){if(!domain) +return new HTTPBindingClient(name,'/c/'+name,domain);return new HTTPBindingClient(name,'/a/'+domain+'/c/'+name,domain);};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,'/a/'+comp.domain+'/r/'+comp.name+'/'+rname,comp.domain);};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;};
\ No newline at end of file +return ref;}; diff --git a/sca-cpp/trunk/modules/js/htdocs/component.js b/sca-cpp/trunk/modules/js/htdocs/component.js index 742e7be930..95cad7cf4f 100644 --- a/sca-cpp/trunk/modules/js/htdocs/component.js +++ b/sca-cpp/trunk/modules/js/htdocs/component.js @@ -102,8 +102,9 @@ JSONClient.toJSON = function(o) { /** * Construct an HTTPBindingClient. */ -function HTTPBindingClient(name, uri) { +function HTTPBindingClient(name, uri, domain) { this.name = name; + this.domain = domain; this.uri = uri; this.apply = this.createApplyMethod(); } @@ -230,10 +231,10 @@ HTTPBindingClient.prototype.jsonApply = function(req) { /** - * REST ATOMPub GET method. + * REST GET method. */ HTTPBindingClient.prototype.get = function(id, cb) { - var u = this.uri + '/' + id; + var u = id? (this.uri? this.uri + '/' + id : id) : this.uri; var hascb = cb? true : false; // Get from local storage first @@ -321,10 +322,10 @@ HTTPBindingClient.prototype.get = function(id, cb) { }; /** - * REST ATOMPub GET method, does not use the local cache. + * REST GET method, does not use the local cache. */ HTTPBindingClient.prototype.getnocache = function(id, cb) { - var u = this.uri + '/' + id; + var u = id? (this.uri? this.uri + '/' + id : id) : this.uri; var hascb = cb? true : false; // Connect to the service @@ -386,7 +387,7 @@ HTTPBindingClient.prototype.getnocache = function(id, cb) { }; /** - * REST ATOMPub POST method. + * REST POST method. */ HTTPBindingClient.prototype.post = function (entry, cb) { @@ -426,7 +427,7 @@ HTTPBindingClient.prototype.post = function (entry, cb) { }; /** - * REST ATOMPub PUT method. + * REST PUT method. */ HTTPBindingClient.prototype.put = function (id, entry, cb) { var u = this.uri + '/' + id; @@ -470,7 +471,7 @@ HTTPBindingClient.prototype.put = function (id, entry, cb) { }; /** - * REST ATOMPub DELETE method. + * REST DELETE method. */ HTTPBindingClient.prototype.del = function (id, cb) { var u = this.uri + '/' + id; @@ -569,22 +570,26 @@ var sca = {}; /** * Return an HTTP client proxy. */ -sca.httpclient = function(name, uri) { - return new HTTPBindingClient(name, uri); +sca.httpclient = function(name, uri, domain) { + return new HTTPBindingClient(name, uri, domain); }; /** * Return a component proxy. */ -sca.component = function(name) { - return new HTTPBindingClient(name, '/components/' + name); +sca.component = function(name, domain) { + if (!domain) + return new HTTPBindingClient(name, '/c/' + name, domain); + return new HTTPBindingClient(name, '/a/' + domain + '/c/' + name, domain); }; /** * Return a reference proxy. */ sca.reference = function(comp, rname) { - return new HTTPBindingClient(comp.name + '/' + rname, "/references/" + comp.name + "/" + rname); + if (!comp.domain) + return new HTTPBindingClient(comp.name + '/' + rname, '/r/' + comp.name + '/' + rname, comp.domain); + return new HTTPBindingClient(comp.name + '/' + rname, '/a/' + comp.domain + '/r/' + comp.name + '/' + rname, comp.domain); }; /** diff --git a/sca-cpp/trunk/modules/js/htdocs/ui-min.css b/sca-cpp/trunk/modules/js/htdocs/ui-min.css index c8798583c6..d8d8863c17 100644 --- a/sca-cpp/trunk/modules/js/htdocs/ui-min.css +++ b/sca-cpp/trunk/modules/js/htdocs/ui-min.css @@ -1,10 +1,38 @@ -body{margin-top:0px;margin-bottom:2px;margin-left:2px;margin-right:2px;font-family:"Helvetica Neue", Helvetica;font-style:normal;font-variant:normal;font-size:13px;-webkit-text-size-adjust:none;-webkit-touch-callout:none;-webkit-user-select:none;} +/* + * 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:"Helvetica Neue", Helvetica;font-style:normal;font-variant:normal;font-size:13px;-webkit-text-size-adjust:none;-webkit-touch-callout:none;-webkit-tap-highlight-color:rgba(0,0,0,0);-webkit-user-select:none;} .delayed{visibility:hidden;} .devicewidth{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:hidden;} +.mainbodydiv{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:hidden;} .bodydiv{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:hidden;} -.bodydivloading{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:hidden;-webkit-transform:translate(100%, 0px);-webkit-backface-visibility:hidden;-moz-transform:translate(100%, 0px);-ms-transform:translate(100%, 0px);transform:translate(100%, 0px);} -.bodydivloaded{-webkit-transition:-webkit-transform 0.4s linear;-moz-transition:-moz-transform 0.4s linear;-ms-transition:-ms-transform 0.4s linear;transition:transform 0.4s linear;position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:hidden;-webkit-transform:translate3d(0px, 0px, 0px);-webkit-backface-visibility:hidden;-moz-transform:translate(0px, 0px);-ms-transform:translate(0px, 0px);transform:translate(0px, 0px);} -.bodydivunloaded{-webkit-transition:-webkit-transform 0.4s linear;-moz-transition:-moz-transform 0.4s linear;-ms-transition:-ms-transform 0.4s linear;transition:transform 0.4s linear;position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:hidden;-webkit-transform:translate3d(-100%, 0px, 0px);-webkit-backface-visibility:hidden;-moz-transform:translate(-100%, 0px);-ms-transform:translate(-100%, 0px);transform:translate(-100%, 0px);} +.viewcontainer3dm{-webkit-perspective:1000;} +.viewcontainer3d{} +.leftviewloading3dm{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;-webkit-transform:translate3d(100%, 0px, 0) rotateY(0deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(100%, 0px);-ms-transform:translate(100%, 0px);transform:translate(100%, 0px);} +.rightviewloading3dm{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;-webkit-transform:translate3d(-100%, 0px, 0) rotateY(0deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(-100%, 0px);-ms-transform:translate(-100%, 0px);transform:translate(-100%, 0px);} +.flipviewloading3dm{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;-webkit-transform:translate3d(0px, 0px, 0) rotateY(180deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(100%, 0px);-ms-transform:translate(100%, 0px);transform:translate(100%, 0px);} +.viewloading3d{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;visibility:hidden;-webkit-transform:translate3d(100%, 0px, 0) rotateY(0deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(100%, 0px);-ms-transform:translate(100%, 0px);transform:translate(100%, 0px);} +.viewloaded3dm{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;-webkit-transition:-webkit-transform 0.5s ease-in-out;-moz-transition:-moz-transform 0.5s ease-in-out;-ms-transition:-ms-transform 0.5s ease-in-out;transition:transform 0.5s ease-in-out;-webkit-transform:translate3d(0px, 0px, 0) rotateY(0deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(0px, 0px);-ms-transform:translate(0px, 0px);transform:translate(0px, 0px);} +.viewloaded3d{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;-webkit-transform:translate3d(0px, 0px, 0) rotateY(0deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(0px, 0px);-ms-transform:translate(0px, 0px);transform:translate(0px, 0px);} +.viewunloading3dm{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;-webkit-transform:translate3d(0px, 0px, 0) rotateY(0deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(0px, 0px);-ms-transform:translate(0px, 0px);transform:translate(0px, 0px);} +.leftviewunloaded3dm{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;-webkit-transition:-webkit-transform 0.5s ease-in-out;-moz-transition:-moz-transform 0.5s ease-in-out;-ms-transition:-ms-transform 0.5s ease-in-out;transition:transform 0.5s ease-in-out;-webkit-transform:translate3d(-100%, 0px, 0px) rotateY(0deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(-100%, 0px);-ms-transform:translate(-100%, 0px);transform:translate(-100%, 0px);} +.rightviewunloaded3dm{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;-webkit-transition:-webkit-transform 0.5s ease-in-out;-moz-transition:-moz-transform 0.5s ease-in-out;-ms-transition:-ms-transform 0.5s ease-in-out;transition:transform 0.5s ease-in-out;-webkit-transform:translate3d(100%, 0px, 0) rotateY(0deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(100%, 0px);-ms-transform:translate(100%, 0px);transform:translate(100%, 0px);} +.flipviewunloaded3dm{position:absolute;top:0px;left:0px;width:100%;height:5000px;overflow:visible;-webkit-transition:-webkit-transform 0.5s ease-in-out;-moz-transition:-moz-transform 0.5s ease-in-out;-ms-transition:-ms-transform 0.5s ease-in-out;transition:transform 0.5s ease-in-out;-webkit-transform:translate3d(0px, 0px, 0) rotateY(-180deg);-webkit-backface-visibility:hidden;background-color:#ffffff;-moz-transform:translate(0px, 0px);-ms-transform:translate(0px, 0px);transform:translate(0px, 0px);} table{border:0px;border-collapse:collapse;border-color:#a2bae7;border-style:solid;font-family:"Helvetica Neue", Helvetica;font-style:normal;font-variant:normal;font-size:13px;overflow:visible;} .trb{border-bottom:1px;border-bottom-style:solid;border-color:#dcdcdc;} th{font-weight:bold;background-color:#d4e6fc;color:#000000;height:18px;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:#a2bae7;border-bottom-color:#d1d3d4;border-left-color:#a2bae7;border-right-color:#a2bae7;overflow:hidden;} @@ -21,6 +49,7 @@ td{padding-left:2px;padding-top:2px;padding-right:8px;white-space:nowrap;vertica .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);} @@ -51,10 +80,10 @@ img{border:0px;} .ltbar{padding-left:2px;padding-right:6px;padding-top:3px;padding-bottom:4px;white-space:nowrap;vertical-align:middle;} .dtbar{padding-left:0px;padding-right:0px;padding-top:3px;padding-bottom:4px;white-space:nowrap;vertical-align:middle;text-align:right;} .rtbar{padding-left:6px;padding-right:2px;padding-top:3px;padding-bottom:4px;white-space:nowrap;vertical-align:middle;text-align:right;} -.tbaramenu{color:#cccccc;text-decoration:none;white-space:nowrap;} -.tbarsmenu{font-weight:bold;color:#ffffff;text-decoration:none;white-space:nowrap;} +.tbaramenu{color:#cccccc;text-decoration:none;white-space:nowrap;vertical-align:middle;} +.tbarsmenu{font-weight:bold;color:#ffffff;text-decoration:none;white-space:nowrap;vertical-align:middle;} .suggest{background-color:#d4e6fc;color:#598edd;border-top:1px;border-bottom:1px;border-left:1px;border-right:1px;border-style:solid;border-top-color:#a2bae7;border-bottom-color:#d1d3d4;border-left-color:#d1d3d4;border-right-color:#d1d3d4;position:absolute;overflow:auto;overflow-x:hidden;padding:0px;margin:0px;cursor:default;} .suggestTable{border:0px;border-collapse:separate;padding-left:5px;padding-right:5px;padding-top:2px;padding-bottom:2px;margin:0px;} .suggestItem{padding-left:2px;padding-top:0px;padding-bottom:0px;padding-right:2px;vertical-align:middle;background-color:#d4e6fc;color:#598edd;} .suggestHilighted{padding-left:2px;padding-top:0px;padding-bottom:0px;padding-right:2px;vertical-align:middle;background-color:#598edd;color:#d4e6fc;} -.svgtitle{margin:0px;padding:0px;font-family:"Helvetica Neue", Helvetica;font-style:normal;font-variant:normal;font-size:10px;cursor:default;}
\ No newline at end of file +.svgtitle{margin:0px;padding:0px;font-family:"Helvetica Neue", Helvetica;font-style:normal;font-variant:normal;font-size:10px;cursor:default;} diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.css b/sca-cpp/trunk/modules/js/htdocs/ui.css index b4c27a54e8..42d89b8087 100644 --- a/sca-cpp/trunk/modules/js/htdocs/ui.css +++ b/sca-cpp/trunk/modules/js/htdocs/ui.css @@ -22,6 +22,7 @@ margin-top: 0px; margin-bottom: 2px; margin-left: 2px; margin-right: 2px; font-family: "Helvetica Neue", Helvetica; font-style: normal; font-variant: normal; font-size: 13px; -webkit-text-size-adjust: none; -webkit-touch-callout: none; +-webkit-tap-highlight-color: rgba(0,0,0,0); -webkit-user-select: none; } @@ -33,42 +34,128 @@ visibility: hidden; position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; } -.bodydiv { +.mainbodydiv { position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; } -.bodydivloading { +.bodydiv { position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; --webkit-transform: translate(100%, 0px); -webkit-backface-visibility: hidden; +} + +.viewcontainer3dm { +-webkit-perspective: 1000; +} + +.viewcontainer3d { +} + +.leftviewloading3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-transform: translate3d(100%, 0px, 0) rotateY(0deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; -moz-transform: translate(100%, 0px); -ms-transform: translate(100%, 0px); transform: translate(100%, 0px); } -.bodydivloaded { --webkit-transition: -webkit-transform 0.4s linear; --moz-transition: -moz-transform 0.4s linear; --ms-transition: -ms-transform 0.4s linear; -transition: transform 0.4s linear; -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; --webkit-transform: translate3d(0px, 0px, 0px); -webkit-backface-visibility: hidden; +.rightviewloading3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-transform: translate3d(-100%, 0px, 0) rotateY(0deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; +-moz-transform: translate(-100%, 0px); +-ms-transform: translate(-100%, 0px); +transform: translate(-100%, 0px); +} + +.flipviewloading3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-transform: translate3d(0px, 0px, 0) rotateY(180deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; +-moz-transform: translate(100%, 0px); +-ms-transform: translate(100%, 0px); +transform: translate(100%, 0px); +} + +.viewloading3d { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +visibility: hidden; +-webkit-transform: translate3d(100%, 0px, 0) rotateY(0deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; +-moz-transform: translate(100%, 0px); +-ms-transform: translate(100%, 0px); +transform: translate(100%, 0px); +} + +.viewloaded3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-transition: -webkit-transform 0.5s ease-in-out; +-moz-transition: -moz-transform 0.5s ease-in-out; +-ms-transition: -ms-transform 0.5s ease-in-out; +transition: transform 0.5s ease-in-out; +-webkit-transform: translate3d(0px, 0px, 0) rotateY(0deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; -moz-transform: translate(0px, 0px); -ms-transform: translate(0px, 0px); transform: translate(0px, 0px); } -.bodydivunloaded { --webkit-transition: -webkit-transform 0.4s linear; --moz-transition: -moz-transform 0.4s linear; --ms-transition: -ms-transform 0.4s linear; -transition: transform 0.4s linear; -position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: hidden; --webkit-transform: translate3d(-100%, 0px, 0px); -webkit-backface-visibility: hidden; +.viewloaded3d { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-transform: translate3d(0px, 0px, 0) rotateY(0deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; +-moz-transform: translate(0px, 0px); +-ms-transform: translate(0px, 0px); +transform: translate(0px, 0px); +} + +.viewunloading3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-transform: translate3d(0px, 0px, 0) rotateY(0deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; +-moz-transform: translate(0px, 0px); +-ms-transform: translate(0px, 0px); +transform: translate(0px, 0px); +} + +.leftviewunloaded3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-transition: -webkit-transform 0.5s ease-in-out; +-moz-transition: -moz-transform 0.5s ease-in-out; +-ms-transition: -ms-transform 0.5s ease-in-out; +transition: transform 0.5s ease-in-out; +-webkit-transform: translate3d(-100%, 0px, 0px) rotateY(0deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; -moz-transform: translate(-100%, 0px); -ms-transform: translate(-100%, 0px); transform: translate(-100%, 0px); } +.rightviewunloaded3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-transition: -webkit-transform 0.5s ease-in-out; +-moz-transition: -moz-transform 0.5s ease-in-out; +-ms-transition: -ms-transform 0.5s ease-in-out; +transition: transform 0.5s ease-in-out; +-webkit-transform: translate3d(100%, 0px, 0) rotateY(0deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; +-moz-transform: translate(100%, 0px); +-ms-transform: translate(100%, 0px); +transform: translate(100%, 0px); +} + +.flipviewunloaded3dm { +position: absolute; top: 0px; left: 0px; width: 100%; height: 5000px; overflow: visible; +-webkit-transition: -webkit-transform 0.5s ease-in-out; +-moz-transition: -moz-transform 0.5s ease-in-out; +-ms-transition: -ms-transform 0.5s ease-in-out; +transition: transform 0.5s ease-in-out; +-webkit-transform: translate3d(0px, 0px, 0) rotateY(-180deg); +-webkit-backface-visibility: hidden; background-color: #ffffff; +-moz-transform: translate(0px, 0px); +-ms-transform: translate(0px, 0px); +transform: translate(0px, 0px); +} + table { border: 0px; border-collapse: collapse; border-color: #a2bae7; border-style: solid; font-family: "Helvetica Neue", Helvetica; font-style: normal; font-variant: normal; font-size: 13px; @@ -143,6 +230,10 @@ border-top: 1px; border-bottom: 1px; border-style: solid; border-color: #dcdcdc; 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; } @@ -335,11 +426,11 @@ padding-left: 6px; padding-right: 2px; padding-top: 3px; padding-bottom: 4px; wh } .tbaramenu { -color: #cccccc; text-decoration: none; white-space: nowrap; +color: #cccccc; text-decoration: none; white-space: nowrap; vertical-align: middle; } .tbarsmenu { -font-weight: bold; color: #ffffff; text-decoration: none; white-space: nowrap; +font-weight: bold; color: #ffffff; text-decoration: none; white-space: nowrap; vertical-align: middle; } .suggest { diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.js b/sca-cpp/trunk/modules/js/htdocs/ui.js index 7c079e3089..d8628f6dd0 100644 --- a/sca-cpp/trunk/modules/js/htdocs/ui.js +++ b/sca-cpp/trunk/modules/js/htdocs/ui.js @@ -24,167 +24,11 @@ var ui = {}; /** - * Build a portable <a href> tag. - */ -ui.ahref = function(loc, target, html) { - if (target == '_blank') - return '<a href="' + loc + '" target="_blank">' + html + '</a>'; - return '<a href="javascript:void(0)" onclick="ui.navigate(\'' + loc + '\', \'' + target + '\');">' + html + '</a>'; -}; - -/** - * Build a menu bar. - */ -ui.menu = function(name, href, target) { - function Menu(n, h, t) { - this.name = n; - this.href = h; - this.target = isNil(t)? '_parent' : t; - - this.content = function() { - function complete(uri) { - var h = uri.indexOf('#'); - if (h != -1) - return complete(uri.substr(0, h)); - var q = uri.indexOf('?'); - if (q != -1) - return complete(uri.substr(0, q)); - if (uri.match('.*\.html$')) - return uri; - if (uri.match('.*/$')) - return uri + 'index.html'; - return uri + '/index.html'; - } - - if (complete(this.href) != complete(window.top.location.pathname)) - return ui.ahref(this.href, this.target, '<span class="tbaramenu">' + this.name + '</span>'); - return ui.ahref(this.href, this.target, '<span class="tbarsmenu">' + this.name + '</span>'); - }; - } - return new Menu(name, href, target); -}; - -ui.menubar = function(left, right) { - var bar = '<table cellpadding="0" cellspacing="0" width="100%" class="tbar"><tr>' + - '<td class="dtbar"><table border="0" cellspacing="0" cellpadding="0"><tr>'; - for (i in left) - bar = bar + '<td class="ltbar">' + left[i].content() + '</td>' - - bar = bar + '</tr></table></td>' + - '<td class="dtbar"><table border="0" cellpadding="0" cellspacing="0" align="right"><tr>'; - for (i in right) - bar = bar + '<td class="' + (i == 0? 'dtbar' : 'rtbar') + '">' + right[i].content() + '</td>' - - bar = bar + '</tr></table></td></tr></table>'; - return bar; -}; - -/** - * Autocomplete / suggest support for input fields - * To use it declare a 'suggest' function as follows: - * function suggestItems() { - * return new Array('abc', 'def', 'ghi'); - * } - * then hook it to an input field as follows: - * suggest(document.yourForm.yourInputField, suggestItems); - */ -ui.selectSuggestion = function(node, value) { - for (;;) { - node = node.parentNode; - if (node.tagName.toLowerCase() == 'div') - break; - } - node.selectSuggestion(value); -}; - -ui.hilightSuggestion = function(node, over) { - if (over) - node.className = 'suggestHilighted'; - node.className = 'suggestItem'; -}; - -ui.suggest = function(input, suggestFunction) { - input.suggest = suggestFunction; - - input.selectSuggestion = function(value) { - this.hideSuggestDiv(); - this.value = value; - } - - input.hideSuggestDiv = function() { - if (this.suggestDiv != null) { - this.suggestDiv.style.visibility = 'hidden'; - } - } - - input.showSuggestDiv = function() { - if (this.suggestDiv == null) { - this.suggestDiv = document.createElement('div'); - this.suggestDiv.input = this; - this.suggestDiv.className = 'suggest'; - input.parentNode.insertBefore(this.suggestDiv, input); - this.suggestDiv.style.visibility = 'hidden'; - this.suggestDiv.style.zIndex = '99'; - - this.suggestDiv.selectSuggestion = function(value) { - this.input.selectSuggestion(value); - } - } - - var values = this.suggest(); - var items = ''; - for (var i = 0; i < values.length; i++) { - if (values[i].indexOf(this.value) == -1) - continue; - if (items.length == 0) - items += '<table class="suggestTable">'; - items += '<tr><td class="suggestItem" ' + - 'onmouseover="ui.hilightSuggestion(this, true)" onmouseout="ui.hilightSuggestion(this, false)" ' + - 'onmousedown="ui.selectSuggestion(this, \'' + values[i] + '\')">' + values[i] + '</td></tr>'; - } - if (items.length != 0) - items += '</table>'; - this.suggestDiv.innerHTML = items; - - if (items.length != 0) { - var node = input; - var left = 0; - var top = 0; - for (;;) { - left += node.offsetLeft; - top += node.offsetTop; - node = node.offsetParent; - if (node.tagName.toLowerCase() == 'body') - break; - } - this.suggestDiv.style.left = left; - this.suggestDiv.style.top = top + input.offsetHeight; - this.suggestDiv.style.visibility = 'visible'; - } else - this.suggestDiv.style.visibility = 'hidden'; - } - - input.onkeydown = function(event) { - this.showSuggestDiv(); - }; - - input.onkeyup = function(event) { - this.showSuggestDiv(); - }; - - input.onmousedown = function(event) { - this.showSuggestDiv(); - }; - - input.onblur = function(event) { - setTimeout(function() { input.hideSuggestDiv(); }, 50); - }; -}; - -/** * 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) @@ -200,20 +44,46 @@ ui.elementByID = function(node, id) { * Return the current document, or a child element with the given id. */ function $(id) { - if (id == document) { - if (!isNil(document.widget)) - return document.widget; + if (id == document) return document; - } return ui.elementByID($(document), id); }; /** - * Return a dictionary of the query parameters. + * 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.queryParams = function() { +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 = window.location.search.substring(1).split('&'); + var qs = ui.query(url).split('&'); for (var i = 0; i < qs.length; i++) { var e = qs[i].indexOf('='); if (e > 0) @@ -223,11 +93,11 @@ ui.queryParams = function() { }; /** - * Return a dictionary of the fragment parameters. + * Return a dictionary of fragment parameters in a URL. */ -ui.fragmentParams = function() { +ui.fragmentParams = function(url) { var qp = new Array(); - var qs = window.location.hash.substring(1).split('&'); + var qs = ui.fragment(url).split('&'); for (var i = 0; i < qs.length; i++) { var e = qs[i].indexOf('='); if (e > 0) @@ -237,6 +107,55 @@ ui.fragmentParams = function() { }; /** + * 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; @@ -252,145 +171,117 @@ ui.isMobile = function() { }; /** - * Initialize a document's body. + * Convert a host name to a home page title. */ -ui.pagetransitions = false; +ui.hometitle = function(host) { + if (!isNil(window.top.config.hometitle)) + return window.top.config.hometitle; + var h = reverse(host.split('.')); + var d = isNil(cdr(h))? car(h) : cadr(h); + return d.substr(0, 1).toUpperCase() + d.substr(1); +}; -ui.initbody = function() { - if (ui.isMobile()) { - //log('init', window.location); +/** + * Convert a host name to a window title. + */ +ui.windowtitle = function(host) { + if (!isNil(window.top.config.windowtitle)) + return window.top.config.windowtitle; + var h = reverse(host.split('.')); + var d = isNil(cdr(h))? car(h) : cadr(h); + return d.substr(0, 1).toUpperCase() + d.substr(1); +}; - // Position the main body div off screen - if (ui.pagetransitions) { - var bdiv = $('bodydiv'); - if (!isNil(bdiv)) { - bdiv.className = 'bodydivloading'; - } - } +/** + * Convert a CSS position to a numeric position. + */ +ui.numpos = function(p) { + return p == ''? 0 : Number(p.substr(0, p.length - 2)); +}; - // Install orientation handler - document.body.onorientationchange = ui.onorientationchange; - } - return true; -} +/** + * Convert a numeric position to a CSS pixel position. + */ +ui.pixpos = function(p) { + return p + 'px'; +}; /** * Reload the current document when orientation changes. */ ui.onorientationchange = function() { - window.open(window.location, '_self'); + window.location.reload(); return true; } /** - * Post process a document after it's loaded. - */ -ui.onload = function() { - - // Save the current page location in local storage - // (except for login and logout pages) - var path = document.location.pathname; - if (path.indexOf('/login/') != 0 && path.indexOf('/logout/') != 0) - localStorage.setItem('ui.lastvisited', '' + document.location); - - // Make the document body visible - //log('visible', $('bodydiv').className); - document.body.style.visibility = 'visible'; - - if (ui.pagetransitions && ui.isMobile()) { - //log('onload', window.location); - - // Slide the main body div in - setTimeout(function() { - var bdiv = $('bodydiv'); - if (!isNil(bdiv)) { - function transitionend(e) { - bdiv.removeEventListener('webkitTransitionEnd', transitionend, false); - bdiv.removeEventListener('transitionend', transitionend, false); - bdiv.className = 'bodydiv'; - //log('loadtransitionend', window.location); - }; - bdiv.addEventListener('webkitTransitionEnd', transitionend, false); - bdiv.addEventListener('transitionend', transitionend, false); - //log('loadtransitionstart', window.location); - bdiv.className = 'bodydivloaded'; - } - }, 0); - } - return true; -}; - -/** * Navigate to a new document. */ ui.navigate = function(url, win) { + log('navigate', url, win); - function opendoc(url, win) { - if (win == '_reload') { - window.location = url; - return window.location.reload(); - } - return window.open(url, win); + // Open a new window + if (win == '_blank') + return window.top.open(url, win); + + // Open a new document in the current window + if (win == '_self') + return window.top.open(url, win); + + // Reload the current window + if (win == '_reload') { + window.top.location = url; + return window.top.location.reload(); } - if (ui.pagetransitions && ui.isMobile() && win != '_blank') { - - // Slide the main body div out, then open the new document - var bdiv = $('bodydiv'); - if (!isNil(bdiv)) { - function transitionend(e) { - bdiv.removeEventListener('webkitTransitionEnd', transitionend, false); - bdiv.removeEventListener('transitionend', transitionend, false); - //log('navigatetransitionend', window.location); - return opendoc(url, win); - }; - bdiv.addEventListener('webkitTransitionEnd', transitionend, false); - bdiv.addEventListener('transitionend', transitionend, false); - //log('navigatetransitionstart', window.location); - bdiv.className = 'bodydivunloaded'; - return true; - } + // Let the current top window handle the navigation + if (win == '_view') { + if (!window.top.onnavigate) + return window.top.open(url, '_self'); + return window.top.onnavigate(url); } - return opendoc(url, win); + return window.top.open(url, win); } /** - * Pre process a document just before it's unloaded. + * Build a portable <a href> tag. */ -ui.onbeforeunload = function() { +ui.ahref = function(loc, target, html) { + if (target == '_blank') + return '<a href="' + loc + '" target="_blank">' + html + '</a>'; + return '<a href="javascript:void(0)" onclick="ui.navigate(\'' + loc + '\', \'' + target + '\');">' + html + '</a>'; +}; - if (ui.pagetransitions && ui.isMobile()) { - - // Slide the main body div out - var bdiv = $('bodydiv'); - if (!isNil(bdiv)) - bdiv.className = 'bodydivunloaded'; +/** + * Build a menu bar. + */ +ui.menu = function(name, href, target, hilight) { + function Menu() { + this.content = function() { + if (hilight) + return ui.ahref(href, target, '<span class="tbarsmenu">' + name + '</span>'); + return ui.ahref(href, target, '<span class="tbaramenu">' + name + '</span>'); + }; } + return new Menu(); }; +ui.menubar = function(left, right) { + var bar = '<table cellpadding="0" cellspacing="0" width="100%" class="tbar"><tr>' + + '<td class="dtbar"><table border="0" cellspacing="0" cellpadding="0"><tr>'; + for (i in left) + bar = bar + '<td class="ltbar">' + left[i].content() + '</td>' -/** - * Return the last visited page. - */ -ui.lastvisited = function() { - return localStorage.getItem('ui.lastvisited'); -} - -/** - * Convert a CSS position to a numeric position. - */ -ui.numpos = function(p) { - return p == ''? 0 : Number(p.substr(0, p.length - 2)); -}; + bar = bar + '</tr></table></td>' + + '<td class="dtbar"><table border="0" cellpadding="0" cellspacing="0" align="right"><tr>'; + for (i in right) + bar = bar + '<td class="' + (i == 0? 'dtbar' : 'rtbar') + '">' + right[i].content() + '</td>' -/** - * Convert a numeric position to a CSS pixel position. - */ -ui.pixpos = function(p) { - return p + 'px'; + bar = bar + '</tr></table></td></tr></table>'; + return bar; }; - + /** * Convert a list of elements to an HTML table. */ @@ -473,3 +364,105 @@ ui.datalist = function(l) { return '<table class="datatable ' + (window.name == 'dataFrame'? ' databg' : '') + '" style="width: 100%;">' + rows(l, 0) + '</table>'; } +/** + * Autocomplete / suggest support for input fields + * To use it declare a 'suggest' function as follows: + * function suggestItems() { + * return new Array('abc', 'def', 'ghi'); + * } + * then hook it to an input field as follows: + * suggest(document.yourForm.yourInputField, suggestItems); + */ +ui.selectSuggestion = function(node, value) { + for (;;) { + node = node.parentNode; + if (node.tagName.toLowerCase() == 'div') + break; + } + node.selectSuggestion(value); +}; + +ui.hilightSuggestion = function(node, over) { + if (over) + node.className = 'suggestHilighted'; + node.className = 'suggestItem'; +}; + +ui.suggest = function(input, suggestFunction) { + input.suggest = suggestFunction; + + input.selectSuggestion = function(value) { + this.hideSuggestDiv(); + this.value = value; + } + + input.hideSuggestDiv = function() { + if (this.suggestDiv != null) { + this.suggestDiv.style.visibility = 'hidden'; + } + } + + input.showSuggestDiv = function() { + if (this.suggestDiv == null) { + this.suggestDiv = document.createElement('div'); + this.suggestDiv.input = this; + this.suggestDiv.className = 'suggest'; + input.parentNode.insertBefore(this.suggestDiv, input); + this.suggestDiv.style.visibility = 'hidden'; + this.suggestDiv.style.zIndex = '99'; + + this.suggestDiv.selectSuggestion = function(value) { + this.input.selectSuggestion(value); + } + } + + var values = this.suggest(); + var items = ''; + for (var i = 0; i < values.length; i++) { + if (values[i].indexOf(this.value) == -1) + continue; + if (items.length == 0) + items += '<table class="suggestTable">'; + items += '<tr><td class="suggestItem" ' + + 'onmouseover="ui.hilightSuggestion(this, true)" onmouseout="ui.hilightSuggestion(this, false)" ' + + 'onmousedown="ui.selectSuggestion(this, \'' + values[i] + '\')">' + values[i] + '</td></tr>'; + } + if (items.length != 0) + items += '</table>'; + this.suggestDiv.innerHTML = items; + + if (items.length != 0) { + var node = input; + var left = 0; + var top = 0; + for (;;) { + left += node.offsetLeft; + top += node.offsetTop; + node = node.offsetParent; + if (node.tagName.toLowerCase() == 'body') + break; + } + this.suggestDiv.style.left = left; + this.suggestDiv.style.top = top + input.offsetHeight; + this.suggestDiv.style.visibility = 'visible'; + } else + this.suggestDiv.style.visibility = 'hidden'; + } + + input.onkeydown = function(event) { + this.showSuggestDiv(); + }; + + input.onkeyup = function(event) { + this.showSuggestDiv(); + }; + + input.onmousedown = function(event) { + this.showSuggestDiv(); + }; + + input.onblur = function(event) { + setTimeout(function() { input.hideSuggestDiv(); }, 50); + }; +}; + diff --git a/sca-cpp/trunk/modules/js/htdocs/util.js b/sca-cpp/trunk/modules/js/htdocs/util.js index fd7005e9c7..86e17c4f60 100644 --- a/sca-cpp/trunk/modules/js/htdocs/util.js +++ b/sca-cpp/trunk/modules/js/htdocs/util.js @@ -327,28 +327,6 @@ function issubdomain(host) { } /** - * Convert a host name to a home page title. - */ -function hometitle(host) { - if (!isNil(config.hometitle)) - return config.hometitle; - var h = reverse(host.split('.')); - var d = isNil(cdr(h))? car(h) : cadr(h); - return d.substr(0, 1).toUpperCase() + d.substr(1); -} - -/** - * Convert a host name to a window title. - */ -function windowtitle(host) { - if (!isNil(config.windowtitle)) - return config.windowtitle; - var h = reverse(host.split('.')); - var d = isNil(cdr(h))? car(h) : cadr(h); - return d.substr(0, 1).toUpperCase() + d.substr(1); -} - -/** * Format a string like Python format. */ function format() { diff --git a/sca-cpp/trunk/modules/server/mod-wiring.cpp b/sca-cpp/trunk/modules/server/mod-wiring.cpp index e56cee1d8c..cb2f44c729 100644 --- a/sca-cpp/trunk/modules/server/mod-wiring.cpp +++ b/sca-cpp/trunk/modules/server/mod-wiring.cpp @@ -186,6 +186,38 @@ int translateService(const ServerConf& sc, request_rec *r) { } /** + * Route an /apps/app-name/... request to the target app domain. + */ +int translateDomain(request_rec *r) { + httpdDebugRequest(r, "modwiring::translateDomain::input"); + debug(r->uri, "modwiring::translateDomain::uri"); + + // Extract the requested app name + const list<value> apath(pathValues(r->uri)); + if (isNil(cdr(apath))) + return HTTP_NOT_FOUND; + + // Compute the target uri in the target app domain + ostringstream turi; + turi << httpd::scheme(r) << "://" << string(cadr(apath)) << "." << httpd::hostName(r) << ":" << httpd::port(r) << string(path(cddr(apath))) << (r->args != NULL? string("?") + r->args : string("")); + debug(str(turi), "modwiring::translateDomain::appuri"); + + // Route to an absolute target URI using mod_proxy or an HTTP client redirect + if (useModProxy) { + r->filename = apr_pstrdup(r->pool, c_str(string("proxy:") + str(turi))); + debug(r->filename, "modwiring::translateDomain::filename"); + r->proxyreq = PROXYREQ_REVERSE; + r->handler = "proxy-server"; + apr_table_setn(r->notes, "proxy-nocanon", "1"); + return OK; + } + + debug(str(turi), "modwiring::translateDomain::location"); + r->handler = "mod_tuscany_wiring"; + return httpd::externalRedirect(str(turi), r); +} + +/** * Read the components declared in a composite. */ const failable<list<value> > readComponents(const string& path) { @@ -315,6 +347,10 @@ int translate(request_rec *r) { // Create a scoped memory pool gc_scoped_pool pool(r->pool); + // Translate an app domain request + if (!strncmp(r->uri, "/apps/", 6) || !strncmp(r->uri, "/a/", 3)) + return translateDomain(r); + // Get the server configuration const ServerConf& sc = httpd::serverConf<ServerConf>(r, &mod_tuscany_wiring); |