summaryrefslogtreecommitdiffstats
path: root/sca-cpp/trunk
diff options
context:
space:
mode:
Diffstat (limited to 'sca-cpp/trunk')
-rw-r--r--sca-cpp/trunk/.gitignore1
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf25
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf.off25
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/app/index.html60
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf57
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/clone/index.html22
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/create/index.html15
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/data/index.html10
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/graph/graph.js370
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/graph/index.html164
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/index.html24
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/login/index.html12
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/logout/index.html10
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/page/index.html173
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/page/page.js237
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/stats/index.html28
-rw-r--r--sca-cpp/trunk/modules/edit/htdocs/store/index.html24
17 files changed, 800 insertions, 457 deletions
diff --git a/sca-cpp/trunk/.gitignore b/sca-cpp/trunk/.gitignore
index 1f6ae3e985..5f4c10c77b 100644
--- a/sca-cpp/trunk/.gitignore
+++ b/sca-cpp/trunk/.gitignore
@@ -57,6 +57,7 @@ config.sub
config.status
config.js
all.js
+intro*.png
depcomp
install-sh
ltmain.sh
diff --git a/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf b/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf
deleted file mode 100644
index 460f0b6bbd..0000000000
--- a/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf
+++ /dev/null
@@ -1,25 +0,0 @@
-CACHE MANIFEST
-
-# Common resources
-all-min.js
-config.js
-ui-min.css
-
-# App resources
-app.html
-data/index.html
-favicon.ico
-index.html
-public/app.png
-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/cache-manifest.cmf.off b/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf.off
new file mode 100644
index 0000000000..bd44d87aa1
--- /dev/null
+++ b/sca-cpp/trunk/modules/edit/htdocs/app/cache-manifest.cmf.off
@@ -0,0 +1,25 @@
+CACHE MANIFEST
+
+# Common resources
+/all-min.js
+/config.js
+/ui-min.css
+
+# App resources
+/
+/app.html
+/data/index.html
+/favicon.ico
+/public/app.png
+/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/index.html b/sca-cpp/trunk/modules/edit/htdocs/app/index.html
index fe7edd44b9..99a523362f 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/app/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/app/index.html
@@ -17,7 +17,7 @@
* specific language governing permissions and limitations
* under the License.
-->
-<html manifest="/cache-manifest.cmf">
+<html>
<head>
<title>App</title>
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0"/>
@@ -37,20 +37,25 @@ document.title = window.location.hostname.split('.')[0];
<div id="app"></div>
-<span id="appFrame"></span>
+<span id="appbuffer"></span>
+<span id="appebuffer"></span>
</div>
<script type="text/javascript">
-if (ui.isIE()) $('bodydiv').style.right = -20;
/**
- * Start, stop, timer and geolocation components.
+ * The main app div.
+ */
+var appdiv = $('app');
+
+/**
+ * Start, stop, timer and location components.
*/
var startcomp = sca.httpclient('start', '/start');
var stopcomp = sca.httpclient('stop', '/stop');
var timercomp = sca.httpclient('timer', '/timer');
-var geolocationcomp = sca.httpclient('geolocation', '/geolocation');
+var locationcomp = sca.httpclient('location', '/location');
/**
* Find a named value in a tree of elements.
@@ -146,13 +151,13 @@ function setwidgetvalue(e, dv) {
return t;
}
if (e.className == 'list') {
- var t = ui.datalist(mklist(dv));
- car(childElements(e)).innerHTML = t;
+ var t = ui.datalist(isNil(dv)? mklist() : mklist(dv));
+ e.innerHTML = t;
return t;
}
if (e.className == 'table') {
- var t = ui.datatable(mklist(dv));
- car(childElements(e)).innerHTML = t;
+ var t = ui.datatable(isNil(dv)? mklist() : mklist(dv));
+ e.innerHTML = t;
return t;
}
if (e.className == 'link') {
@@ -190,7 +195,7 @@ function displaydata(l) {
return e;
}
- map(updatewidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID($('app'), 'page').childNodes)));
+ map(updatewidget, filter(function(e) { return !isNil(e.id) && e.id.substring(0, 5) != 'page:'; }, nodeList(ui.elementByID(appdiv, 'page').childNodes)));
return true;
}
@@ -219,10 +224,11 @@ function displaydoc(doc) {
function bindwidgethandler(e) {
if (e.className == 'button') {
var b = car(childElements(e));
- b.onclick = function() { return buttonClickHandler(e.id); };
+ b.name = e.id;
+ b.onclick = function() { return buttonClickHandler(b.value); };
return e;
}
- if (e.className == 'button' || e.className == 'entry' || e.className == 'password' || e.className == 'checkbox') {
+ if (e.className == 'entry' || e.className == 'password' || e.className == 'checkbox') {
car(childElements(e)).name = e.id;
return e;
}
@@ -263,6 +269,15 @@ function fixupwidget(e) {
}
/**
+ * Set initial value of a widget.
+ */
+function initwidget(e) {
+ if (!isNil(e.id) && e.id.substring(0, 5) != 'page:')
+ setwidgetvalue(e, mklist());
+ return e;
+}
+
+/**
* Get app data from the main app page component.
*/
function getpagedata() {
@@ -291,6 +306,7 @@ function getpagedata() {
// Initial setup of a widget
function setupwidget(e) {
+ initwidget(e);
fixupwidget(e);
bindwidgethandler(e);
}
@@ -298,17 +314,24 @@ function getpagedata() {
// Get the component app data
var doc = startcomp.get(window.location.search);
try {
- $('app').innerHTML = $('appFrame').contentDocument.body.innerHTML;
+ var appFrame = $('appFrame');
+ if (!isNil(appFrame.contentDocument.body)) {
+ appdiv.innerHTML = appFrame.contentDocument.body.innerHTML;
+ } else {
+ $('appebuffer').appendChild(appFrame.contentDocument.documentElement);
+ appdiv.innerHTML = appebuffer.innerHTML;
+ appebuffer.innerHTML = '';
+ }
// Initial setup of the widgets
- map(setupwidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID($('app'), 'page').childNodes)));
+ map(setupwidget, filter(function(e) { return !isNil(e.id); }, nodeList(ui.elementByID(appdiv, 'page').childNodes)));
// Display data on the page
displaypage(doc);
// Get and eval the optional timer and location watch setup scripts
evalcompinit(timercomp.get('setup'));
- evalcompinit(geolocationcomp.get('setup'));
+ evalcompinit(locationcomp.get('setup'));
return true;
} catch(e) {
@@ -339,7 +362,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($('app'), 'page'))));
+ var args = map(queryarg, filter(function(e) { return !isNil(e.id) && !isNil(inputvalue(e)); }, childrenList(ui.elementByID(appdiv, 'page'))));
// Append current location properties if known
if (!isNil(geoposition)) {
@@ -378,6 +401,7 @@ function intervalHandler() {
* Setup an interval timer.
*/
function setupIntervalHandler(msec) {
+ intervalHandler();
try {
return setInterval(intervalHandler, msec);
} catch(e) {
@@ -394,7 +418,7 @@ var geoposition = null;
function locationHandler(pos) {
try {
geoposition = pos;
- return getcompdata(geolocationcomp, compquery());
+ return getcompdata(locationcomp, compquery());
} catch(e) {
locationErrorHandler(e);
}
@@ -431,7 +455,7 @@ function setupLocationHandler() {
}
// Load the app frame
-$('app').innerHTML = '<iframe id="appFrame" class="widgetFrame" src="app.html" onload="getpagedata()"></iframe>';
+$('appbuffer').innerHTML = '<iframe id="appFrame" class="widgetframe" src="app.html" onload="getpagedata()"></iframe>';
</script>
</body>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf b/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf
index d734f1f2c7..3f331a4e5d 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf
+++ b/sca-cpp/trunk/modules/edit/htdocs/cache-manifest.cmf
@@ -1,36 +1,37 @@
CACHE MANIFEST
# Common resources
-all-min.js
-config.js
-ui-min.css
+/all-min.js
+/config.js
+/ui-min.css
# App resources
-app/index.html
-clone/index.html
-data/index.html
-create/index.html
-data/index.html
-favicon.ico
-graph/graph.js
-graph/index.html
-home.png
-index.html
-menu.js
-page/index.html
-page/page.js
-public/app.png
-public/grid72.png
-public/iframe.html
-public/img.png
-public/notauth.html
-public/notfound.html
-public/notyet.html
-public/oops.html
-public/touchicon.png
-robots.txt
-stats/index.html
-store/index.html
+/
+/account/
+/app/
+/clone/
+/data/
+/create/
+/data/
+/favicon.ico
+/graph/graph.js
+/graph/
+/home.png
+/menu.js
+/page/
+/page/page.js
+/public/app.png
+/public/grid72.png
+/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 a68943b072..8613992806 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/clone/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/clone/index.html
@@ -36,7 +36,7 @@
<table style="width: 100%;">
<tr>
-<td><h1><span id="h1"></span><span id="appNameHeader"></span></h1></td>
+<td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td>
</tr>
</table>
@@ -49,7 +49,7 @@
<form id="cloneAppForm" style="position: absolute; top: 90px; left: 0px;">
<table style="width: 100%;">
<tr><td><b>New App Name:</b></td></tr>
-<tr><td><input type="text" id="appName" size="15" placeholder="Your app name"/>&nbsp;<span id="appDomain"></span></td></tr>
+<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/>&nbsp;<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><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr>
@@ -89,11 +89,11 @@ function applink(appname) {
// Set page titles
var tclone = isNil(config.clone)? 'Clone' : config.clone;
document.title = windowtitle(window.location.hostname) + ' - ' + tclone + ' - ' + appname;
-$('h1').innerHTML = hometitle(window.location.hostname);
-$('appNameHeader').innerHTML = ' - <a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>';
+//$('h1').innerHTML = hometitle(window.location.hostname);
+$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '.' + window.location.hostname + '</a>';
$('th').innerHTML = tclone + ' this App';
$('cloneAppOKButton').value = tclone;
-$('cloneAppOKButton').title = tclone + ' the app';
+$('cloneAppOKButton').title = tclone + ' this app';
// Load the menu bar
displaymenu();
@@ -106,7 +106,7 @@ ui.showbody();
// Init service references
var editWidget = sca.component("EditWidget");
-var dashboard = sca.reference(editWidget, "dashboard");
+var dashboards = sca.reference(editWidget, "dashboards");
var apps = sca.reference(editWidget, "apps");
/**
@@ -138,11 +138,15 @@ $('cloneAppForm').onsubmit = function() {
var name = $('appName').value;
if (name == '')
return false;
+
+ // Clone the app
var title = $('appTitle').value;
var app = mklist(mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", appname)));
var entry = atom.writeATOMEntry(valuesToElements(app));
- dashboard.put(name, car(entry));
- window.open('/store/', '_self');
+ dashboards.put(name, car(entry));
+
+ // Open it in the page editor
+ window.open('/page/?app=' + name, '_self');
return false;
};
@@ -150,7 +154,7 @@ $('cloneAppForm').onsubmit = function() {
* Cancel cloning an app.
*/
$('cloneAppCancelButton').onclick = function() {
- return window.open('/store/', '_self');
+ window.open('/stats/?app=' + appname, '_self');
};
// Get the current app
diff --git a/sca-cpp/trunk/modules/edit/htdocs/create/index.html b/sca-cpp/trunk/modules/edit/htdocs/create/index.html
index 9452275a83..0195473ca5 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/create/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/create/index.html
@@ -47,7 +47,7 @@
<form id="createAppForm" style="position: absolute; top: 90px; left: 0px;">
<table style="width: 100%;">
<tr><td><b>App Name:</b></td></tr>
-<tr><td><input type="text" id="appName" size="15" placeholder="Your app name"/>&nbsp;<span id="appDomain"></span></td></tr>
+<tr><td><input type="text" id="appName" size="15" autocapitalize="off" placeholder="Your app name"/>&nbsp;<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><tr><td style="padding-top: 6px;"><b>Sharing:</b></td></tr>
@@ -81,7 +81,8 @@ ui.showbody();
// Init service references
var editWidget = sca.component("EditWidget");
-var dashboard = sca.reference(editWidget, "dashboard");
+var dashboards = sca.reference(editWidget, "dashboards");
+var apps = sca.reference(editWidget, "apps");
/**
* Create an app.
@@ -90,11 +91,15 @@ $('createAppForm').onsubmit = function() {
var name = $('appName').value;
if (name == '')
return false;
+
+ // Clone the '.new' app template
var title = $('appTitle').value;
- var app = mklist(mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", name)));
+ var app = mklist(mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", 'new')));
var entry = atom.writeATOMEntry(valuesToElements(app));
- dashboard.put(name, car(entry));
- window.open('/store/', '_self');
+ dashboards.put(name, car(entry));
+
+ // Open it in the page editor
+ window.open('/page/?app=' + name, '_self');
return false;
};
diff --git a/sca-cpp/trunk/modules/edit/htdocs/data/index.html b/sca-cpp/trunk/modules/edit/htdocs/data/index.html
index 1f078f7b87..6a9ee416c2 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/data/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/data/index.html
@@ -35,23 +35,25 @@ document.title = 'View - ' + window.location.hostname.split('.')[0] + '/' + cn;
<body class="delayed" onorientationchange="ui.reload();">
<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">
-if (ui.isIE()) $('bodydiv').style.right = -20;
+
+// Get the component name
+var cname = ui.queryParams()['component'];
/**
* The current component.
*/
-var cname = ui.queryParams()['component'];
var comp = sca.component(cname);
/**
* Display an HTML element.
*/
function display(e) {
- $('bodydiv').innerHTML = e;
+ $('datadiv').innerHTML = e;
ui.showbody();
return true;
diff --git a/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
index 2de6a40d6c..139d4600f9 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
+++ b/sca-cpp/trunk/modules/edit/htdocs/graph/graph.js
@@ -41,6 +41,8 @@ graph.colors.red = '#ff0000';
graph.colors.white = '#ffffff';
graph.colors.yellow = '#ffff00';
+graph.colors.link = '#598edd';
+
graph.colors.orange1 = '#ffbb00';
graph.colors.green1 = '#96d333';
graph.colors.blue1 = '#00c3c9';
@@ -54,7 +56,6 @@ graph.colors.lightgray1 = '#dcdcdc'
* Default positions and sizes.
*/
var palcx = 2500;
-var trashcx = 2480;
var proxcx = 20;
var proxcy = 20;
var buttoncx = 65;
@@ -150,53 +151,22 @@ graph.mkgraph = function(pos, cvalue, cadd, cdelete) {
*/
div.onmousedown = function(e) {
- // Find draggable component
- graph.dragging = draggable(e.target);
- graph.selected = graph.dragging;
- if (graph.dragging == null) {
+ // On mouse controlled devices, engage the click component selection
+ // logic right away
+ if (typeof e.touches == 'undefined')
+ div.onclick(e);
- // Reset current selection
- cvalue.value = '';
- cvalue.disabled = true;
- cdelete.disabled = true;
-
- // Trigger component select event
- svg.oncompselect('');
+ // Find draggable component
+ var dragging = draggable(e.target);
+ if (dragging == null || dragging != graph.selected)
return true;
- }
-
- // Clone component from the palette
- var compos = scdl.composite(svg.compos);
- if (graph.dragging.id.substring(0, 8) == 'palette:') {
- graph.dragging = graph.clonepalette(graph.dragging, compos);
- graph.selected = graph.dragging;
-
- // Move into the editing area and hide the palette
- var gpos = graph.relpos(graph.dragging);
- graph.move(graph.dragging, graph.mkpath().move(gpos.xpos() + palcx, gpos.ypos()));
- div.style.left = ui.pixpos(palcx * -1);
- }
-
- // Cut wire to component
- if (graph.dragging.parentNode != svg)
- setElement(compos, graph.sortcompos(graph.cutwire(graph.dragging, compos, svg)));
-
- // Bring component to the top
- graph.bringtotop(graph.dragging, svg);
+ graph.dragging = dragging;
// Remember current mouse position
var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
graph.dragX = pos.screenX;
graph.dragY = pos.screenY;
- // Update the component name and property value fields
- cvalue.value = graph.hasproperty(graph.selected.comp)? graph.property(graph.selected.comp) : graph.selected.id;
- cvalue.disabled = false;
- cdelete.disabled = false;
-
- // Trigger component select event
- svg.oncompselect(graph.selected.id);
-
if (e.preventDefault)
e.preventDefault();
else
@@ -216,45 +186,28 @@ graph.mkgraph = function(pos, cvalue, cadd, cdelete) {
if (graph.dragging.parentNode == svg && graph.dragging.id.substring(0, 8) != 'palette:') {
var gpos = graph.relpos(graph.dragging);
- if (gpos.xpos() >= trashcx) {
-
- // If component close enough to editing area, move it there
- if (gpos.xpos() < palcx)
- graph.move(graph.dragging, graph.mkpath().move(palcx, gpos.ypos()));
-
- // Add new dragged component to the composite
- if (isNil(graph.dragging.compos)) {
- var compos = scdl.composite(svg.compos);
- setElement(compos, graph.sortcompos(graph.addcomp(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))));
- }
-
- } else {
+ // Add new dragged component to the composite
+ if (isNil(graph.dragging.compos)) {
+ var compos = scdl.composite(svg.compos);
+ setElement(compos, graph.sortcompos(graph.addcomp(graph.dragging.comp, compos)));
+ graph.dragging.compos = svg.compos;
+ }
- // Discard component dragged out of composite
- svg.removeChild(graph.dragging);
- if (!isNil(graph.dragging.compos)) {
- var compos = scdl.composite(svg.compos);
- setElement(compos, graph.sortcompos(graph.clonerefs(graph.gcollect(graph.removecomp(graph.dragging.comp, compos)))));
- }
+ // Update component position
+ setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.abspos(graph.dragging, svg)));
- // Reset current selection
- graph.selected = null;
- cvalue.value = '';
- cvalue.disabled = true;
- cdelete.disabled = true;
+ // 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))));
+ }
- // Trigger component select event
- svg.oncompselect('');
+ // Snap top level component position to grid
+ if (graph.dragging.parentNode == svg) {
+ var gpos = graph.relpos(graph.dragging);
+ graph.move(graph.dragging, graph.mkpath().move(graph.gridsnap(gpos.xpos()), graph.gridsnap(gpos.ypos())));
+ setElement(graph.dragging.comp, graph.movecomp(graph.dragging.comp, graph.abspos(graph.dragging, svg)));
}
}
@@ -262,7 +215,14 @@ graph.mkgraph = function(pos, cvalue, cadd, cdelete) {
graph.dragging = null;
// Refresh the composite
- graph.refresh(svg);
+ 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, cdelete);
+
+ // Trigger component select event
+ svg.oncompselect(graph.selected);
// Trigger composite change event
svg.oncomposchange(false);
@@ -273,13 +233,79 @@ graph.mkgraph = function(pos, cvalue, cadd, cdelete) {
div.ontouchend = div.onmouseup;
// Handle a mouse click event.
- div.onclick = function(e) {
- if (graph.dragging == null && (e.target == div || e.target == svg)) {
+ div.onclick = svg.onclick = function(e) {
+
+ // Find selected component
+ var selected = draggable(e.target);
+ if (selected == null) {
+ if (graph.selected != null) {
+
+ // Reset current selection
+ graph.compselect(graph.selected, false, cvalue, cdelete);
+ graph.selected = null;
+
+ // Trigger component select event
+ svg.oncompselect(null);
+ }
// Dismiss the palette
- if (ui.numpos(div.style.left) != (palcx * -1))
+ 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, cdelete);
+
+ // Clone component from the palette
+ if (selected.id.substring(0, 8) == 'palette:') {
+ var compos = scdl.composite(svg.compos);
+ graph.selected = graph.clonepalette(selected, compos, svg);
+ setElement(compos, graph.sortcompos(graph.addcomp(graph.selected.comp, compos)));
+ graph.selected.compos = svg.compos;
+
+ // Move into the editing area and hide the palette
+ var gpos = graph.relpos(graph.selected);
+ graph.move(graph.selected, graph.mkpath().move(gpos.xpos() + palcx, gpos.ypos()));
+ div.style.left = ui.pixpos(palcx * -1);
+
+ // Update component position
+ setElement(graph.selected.comp, graph.movecomp(graph.selected.comp, graph.abspos(graph.selected, svg)));
+
+ // Refresh the composite
+ var nodes = graph.refresh(svg);
+
+ // Reselect the previously selected component
+ graph.selected = graph.findcompnode(scdl.name(graph.selected.comp), nodes);
+ graph.compselect(graph.selected, true, cvalue, 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, cdelete);
+
+ // Trigger component select event
+ svg.oncompselect(graph.selected);
+ }
+
+ if (e.preventDefault)
+ e.preventDefault();
+ else
+ e.returnValue = false;
return true;
}
@@ -290,15 +316,28 @@ graph.mkgraph = function(pos, cvalue, cadd, cdelete) {
if (graph.dragging == null)
return true;
+ // Get the mouse position
+ var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
+ if (pos.screenX == graph.dragX && pos.screenY == graph.dragY)
+ return 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 pos = typeof e.touches != "undefined" ? e.touches[0] : e;
var newX = gpos.xpos() + (pos.screenX - graph.dragX);
var newY = gpos.ypos() + (pos.screenY - graph.dragY);
- if (newX >= 0)
+ if (newX >= palcx)
graph.dragX = pos.screenX;
else
- newX = 0;
+ newX = palcx;
if (newY >= 0)
graph.dragY = pos.screenY;
else
@@ -319,19 +358,25 @@ graph.mkgraph = function(pos, cvalue, cadd, cdelete) {
cvalue.onchange = function() {
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);
+ 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)));
- // Trigger component select event
- svg.oncompselect(graph.selected.id);
-
// Refresh the composite
- graph.refresh(svg);
+ 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, cdelete);
+
+ // Trigger component select event
+ svg.oncompselect(graph.selected);
// Trigger composite change event
svg.oncomposchange(true);
@@ -345,7 +390,14 @@ graph.mkgraph = function(pos, cvalue, cadd, cdelete) {
cvalue.disabled = !graph.hasproperty(graph.selected.comp);
// Refresh the composite
- graph.refresh(svg);
+ 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, cdelete);
+
+ // Trigger component select event
+ svg.oncompselect(graph.selected);
// Trigger composite change event
svg.oncomposchange(true);
@@ -359,23 +411,23 @@ graph.mkgraph = function(pos, cvalue, cadd, cdelete) {
cdelete.onclick = function() {
if (graph.selected == null)
return false;
- if (graph.selected.id.substring(0, 8) != 'palette:' && !isNil(graph.selected.compos)) {
+ 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, cdelete);
graph.selected = null;
- cvalue.value = '';
- cvalue.disabled = true;
- cdelete.disabled = true;
// Refresh the composite
graph.refresh(svg);
// Trigger component select event
- svg.oncompselect('');
+ svg.oncompselect(null);
// Trigger composite change event
svg.oncomposchange(true);
@@ -512,9 +564,40 @@ graph.proptitlewidth = function(comp) {
};
/**
+ * Draw a component shape selection.
+ */
+graph.compselect = function(g, s, cvalue, cdelete) {
+ if (isNil(g) || !s) {
+ if (!isNil(cvalue)) {
+ cvalue.value = '';
+ cvalue.disabled = true;
+ }
+ if (!isNil(cdelete))
+ cdelete.disabled = true;
+ if (isNil(g))
+ return true;
+ g.contour.setAttribute('stroke', graph.colors.gray);
+ g.contour.setAttribute('stroke-opacity', '0.20');
+ return true;
+ }
+
+ if (!isNil(cvalue)) {
+ cvalue.value = graph.hasproperty(g.comp)? graph.property(g.comp) : g.id;
+ cvalue.disabled = false;
+ }
+ if (!isNil(cdelete))
+ cdelete.disabled = false;
+
+ g.contour.setAttribute('stroke', graph.colors.link);
+ g.contour.setAttribute('stroke-opacity', '0.80');
+ g.parentNode.appendChild(g);
+ return true;
+};
+
+/**
* Return a node representing a component.
*/
-graph.compnode = function(comp, cassoc, pos) {
+graph.compnode = function(comp, cassoc, pos, parentg) {
// Make the component and property title elements
var title = graph.comptitle(comp);
@@ -554,10 +637,32 @@ graph.compnode = function(comp, cassoc, pos) {
g.refpos = reverse(path.refpos);
g.svcpos = reverse(path.svcpos);
+ // Store the contour in the component shape
+ g.contour = contour;
+
+ // 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) {
@@ -598,6 +703,10 @@ graph.mkbutton = function(t, pos) {
g.appendChild(shape);
g.appendChild(contour);
g.appendChild(title);
+
+ // Store the contour in the button shape
+ g.contour = contour;
+
return g;
};
@@ -605,7 +714,7 @@ graph.mkbutton = function(t, pos) {
* Return the relative position of a node.
*/
graph.relpos = function(e) {
- var pmatrix = e.parentNode.getCTM();
+ 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);
@@ -1048,12 +1157,20 @@ graph.buttonpath = function(t) {
/**
* Render a SCDL composite into a list of component nodes.
*/
-graph.composite = function(compos, pos) {
+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.
*/
@@ -1124,7 +1241,7 @@ graph.composite = function(compos, pos) {
}
// Compute the component shape
- var gcomp = graph.compnode(comp, cassoc, pos);
+ var gcomp = graph.compnode(comp, cassoc, pos, g);
// Render the components wired to the component references
var rrefs = graph.rrefs(comp);
@@ -1201,10 +1318,17 @@ graph.composite = function(compos, pos) {
// Render the promoted service components
var rproms = renderproms(proms, cassoc, pos.clone().rmove(tabsz * 4, tabsz * 4));
- if (name == 'palette') {
+ 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 = graph.relpos(r);
+ graph.move(r, graph.mkpath().move(gpos.xpos() - palcx, gpos.ypos()));
+ return r;
+ }, rproms);
- // Prefix ids of palette component elements with 'palette:'
- return map(function(r) { r.id = 'palette:' + r.id; return r; }, rproms);
} else {
// Link app component elements to the containing composite
@@ -1215,11 +1339,14 @@ graph.composite = function(compos, pos) {
/**
* Return a component unique id.
*/
-graph.ucid = function(prefix, compos) {
+graph.ucid = function(prefix, compos, clone) {
// Build an assoc list keyed by component name
var comps = map(function(c) { return mklist(scdl.name(c), c); }, namedElementChildren("'component", compos));
+ if (!clone && isNil(assoc(prefix, comps)))
+ return prefix;
+
/**
* Find a free component id.
*/
@@ -1229,26 +1356,23 @@ graph.ucid = function(prefix, compos) {
return ucid(p, id + 1);
}
- if (isNil(assoc(prefix, comps)))
- return prefix;
-
- return ucid(prefix == ''? 'comp' : prefix, 2);
+ return ucid(prefix == ''? 'comp' : prefix, 1);
};
/**
* Clone a palette component node.
*/
-graph.clonepalette = function(e, compos) {
+graph.clonepalette = function(e, compos, g) {
- // Clone the SCDL component and give it a unique name
- var comp = append(mklist(element, "'component", mklist(attribute, "'name", graph.ucid(scdl.name(e.comp), compos))),
+ // 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, true))),
filter(function(c) { return !(isAttribute(c) && attributeName(c) == "'name")}, elementChildren(e.comp)));
- var x = '<composite xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1">' + writeXML(mklist(comp), false) + '</composite>';
- var compos = readXML(mklist(x));
- comp = car(scdl.components(compos));
+ var x = '<composite>' + writeXML(mklist(wcomp), false) + '</composite>';
+ var rcompos = readXML(mklist(x));
+ var comp = car(scdl.components(rcompos));
// Make a component node
- var gcomp = graph.compnode(comp, mklist(), graph.mkpath());
+ var gcomp = graph.compnode(comp, mklist(), graph.mkpath(), g);
graph.move(gcomp, graph.relpos(e));
e.parentNode.appendChild(gcomp);
@@ -1261,12 +1385,19 @@ graph.clonepalette = function(e, compos) {
graph.movecomp = function(comp, pos) {
if (isNil(pos))
return append(mklist(element, "'component"),
- filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'t:x" || attributeName(e) == "'t:y")); }, elementChildren(comp)));
- return append(mklist(element, "'component", mklist(attribute, "'t:x", '' + (pos.xpos() - palcx)), mklist(attribute, "'t:y", '' + pos.ypos())),
- filter(function(e) { return !(isAttribute(e) && (attributeName(e) == "'t:x" || attributeName(e) == "'t:y")); }, elementChildren(comp)));
+ 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;
+}
+
+/**
* Sort elements of a composite.
*/
graph.sortcompos = function(compos) {
@@ -1356,7 +1487,7 @@ graph.clonerefs = function(compos) {
// 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, "'t:clonable", "true"))));
+ mklist(mklist(element, "'reference", mklist(attribute, "'name", scdl.name(car(refs))), mklist(attribute, "'clonable", "true"))));
return append(mklist(element, "'component"), cc);
}, elementChildren(compos)));
@@ -1535,10 +1666,11 @@ graph.hide = function(g) {
*/
graph.refresh = function(g) {
- // Remove nodes and redisplay the composite associated with the graph
+ // 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));
- graph.display(graph.composite(g.compos, graph.mkpath().move(palcx,0)), g);
- return g;
+
+ // Redisplay the composite associated with the graph
+ return graph.display(graph.composite(g.compos, graph.mkpath().move(palcx,0), false, g), g);
};
/**
diff --git a/sca-cpp/trunk/modules/edit/htdocs/graph/index.html b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
index 942433235c..626edf1c52 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/graph/index.html
@@ -37,32 +37,45 @@
<table style="width: 100%;">
<tr>
-<td><h1><span id="h1"></span><span id="appNameHeader"></span></h1></td>
-<td style="vertical-align: middle; text-align: right;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
+<td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td>
+<td style="vertical-align: middle; text-align: right; padding-right: 2px;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
</tr>
</table>
<table style="width: 100%;">
<tr>
-<th class="thr thl" style="padding-left: 2px; padding-right: 2px;">
-<input id="compValue" type="text" value="" title="Component value" placeholder="Name" style="position: relative; width: 170px;"/>
-<span id="deleteComponentButton" title="Delete a component" class="redbutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">-</span>
-<span id="addComponentButton" title="Add a component" class="greenbutton" style="font-weight: bold; font-size: 16px; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">+</span>
-<span id="playComponentButton" title="View component value" class="bluebutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">&gt;</span>
+<th class="thr thl" style="padding-left: 2px; padding-right: 2px; width: 100%">
+<input id="compValue" type="text" value="" title="Component value" autocapitalize="off" placeholder="Value" style="position: relative; width: 100%;"/>
+</th>
+
+<th class="thl thr" style="text-align: right; padding-right: 2px;">
+<span id="deleteCompButton" title="Delete a component" class="redbutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">-</span>
+
+<span id="addCompButton" title="Add a component" class="greenbutton" style="font-weight: bold; font-size: 16px; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">+</span>
+
+<span id="playCompButton" title="View component value" class="bluebutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">&gt;</span>
</th>
</tr>
</table>
-<div id="dataDiv" style="position:absolute; top: 95px; left: 0px; right: 0px; height: 5000px; visibility: hidden">
+<div id="playdiv" style="position:absolute; top: 95px; left: 0px; right: 0px; height: 5000px; visibility: hidden">
</div>
</div>
<script type="text/javascript">
+
// Get the app name
var appname = ui.queryParams()['app'];
-if (isNil(appname))
- window.open('/', '_self');
+var ispalette = false;
+if (isNil(appname)) {
+ appname = ui.queryParams()['palette'];
+ if (isNil(appname))
+ window.open('/', '_self');
+
+ // Edit a palette instead of a regular app
+ ispalette = true;
+}
/**
* Return the link to an app.
@@ -79,41 +92,65 @@ function applink(appname) {
// Set page titles
document.title = windowtitle(window.location.hostname) + ' - ' + (isNil(config.compose)? 'Composition' : config.compose) + ' - ' + appname;
-$('h1').innerHTML = hometitle(window.location.hostname);
-$('appNameHeader').innerHTML = ' - <a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>';
+//$('h1').innerHTML = hometitle(window.location.hostname);
+$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '.' + window.location.hostname + '</a>';
// Load the menu bar
displaymenu();
+/**
+ * Component value field, add, delete and play buttons.
+ */
+var cvalue = $('compValue');
+var cadd = $('addCompButton');
+var cdelete = $('deleteCompButton');
+var cplay = $('playCompButton');
+
+/**
+ * Adjust field size.
+ */
+function resizeFields() {
+ cvalue.style.width = '0px';
+ cvalue.style.width = ui.pixpos(cvalue.parentNode.clientWidth - 18);
+ return true;
+}
+
+resizeFields();
+window.onresize = resizeFields;
+
// Show the page
ui.showbody();
// Init componnent references
var editWidget = sca.component("EditWidget");
var palettes = sca.reference(editWidget, "palettes");
-var composites = sca.reference(editWidget, "composites");
+var composites = sca.reference(editWidget, ispalette? "palettes" : "composites");
// Setup remote log
//rconsole = sca.defun(sca.reference(editWidget, "log"), "log");
/**
- * The current app composite, corresponding saved XML content and component name.
+ * Track the current app composite and corresponding saved XML content.
*/
var savedcomposxml = '';
var composite;
-var compname = '';
/**
- * Track the composition graph and whether it's visible or not.
+ * Track the composition graph, whether it's visible or not and the selected component.
*/
var g;
var gdiv;
var bg;
var gvisible = true;
+var gcomp = null;
+var pdiv = $('playdiv');
-// Track the palettes
+/**
+ * Track the palettes.
+ */
var gpalettes = new Array();
var spalette = 'control';
+var bpalette = null;
/**
* Return the composite in an ATOM entry.
@@ -139,11 +176,13 @@ function getapp(name, g) {
if (isNil(composite)) {
// Create a default empty composite if necessary
- var x = '<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" xmlns:t="http://tuscany.apache.org/xmlns/sca/1.1"' +
+ var x = '<composite xmlns="http://docs.oasis-open.org/ns/opencsa/sca/200912" ' +
'targetNamespace="http://app" name="app"></composite>';
composite = readXML(mklist(x));
}
- graph.edit(name, composite, graph.composite(composite, graph.mkpath().move(palcx,0)), oncomposchange, oncompselect, g);
+
+ // Display the composite
+ graph.edit(name, composite, graph.composite(composite, graph.mkpath().move(palcx,0), false, g), oncomposchange, oncompselect, g);
// Track the saved composite XML
savedcomposxml = car(writeXML(composite, false));
@@ -161,7 +200,7 @@ function displaypalette(name, g, palette, gpalettes) {
// Get the palette from the server
var doc = palettes.get(name);
- gpalettes[name] = graph.composite(atomcomposite(doc), graph.mkpath().move(80,0));
+ gpalettes[name] = graph.composite(atomcomposite(doc), graph.mkpath().move(2580,0), true, g);
}
graph.display(gpalettes[name], g);
return true;
@@ -177,7 +216,10 @@ function installpalette(name, pos, g, bg, palette, gpalettes) {
b.onclick = function(e) {
// Swap the selected palette
+ graph.compselect(bpalette, false);
displaypalette(spalette, bg, palette, gpalettes);
+ bpalette = b;
+ graph.compselect(b, true, null, null);
spalette = name;
return displaypalette(spalette, g, palette, gpalettes);
};
@@ -190,7 +232,10 @@ function installpalette(name, pos, g, bg, palette, gpalettes) {
}
// Display the selected palette
- return displaypalette(name, g, palette, gpalettes);
+ graph.compselect(b, true, null, null);
+ displaypalette(name, g, palette, gpalettes);
+
+ return b;
}
/**
@@ -202,8 +247,9 @@ function save(savexml) {
var entry = '<entry xmlns="http://www.w3.org/2005/Atom">' +
'<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml">' +
savedcomposxml + '</content></entry>';
- composites.put(appname, entry);
- $('saveStatus').innerHTML = 'Saved';
+ composites.put(appname, entry, function(r) {
+ $('saveStatus').innerHTML = 'Saved';
+ });
return true;
}
@@ -220,15 +266,14 @@ function oncomposchange(prop) {
if (prop)
return save(newxml);
- // Autosave other changes after 3 seconds
+ // Autosave other changes after 1 second
$('saveStatus').innerHTML = 'Modified';
setTimeout(function() {
- var savexml = car(writeXML(composite, false));
- if (savedcomposxml == savexml) {
+ if (savedcomposxml == newxml) {
$('saveStatus').innerHTML = 'Saved';
return false;
}
- return save(savexml);
+ return save(newxml);
}, 1000);
return true;
}
@@ -236,7 +281,7 @@ function oncomposchange(prop) {
/**
* Return the link to a component value.
*/
-function compvaluelink(appname, cname) {
+function compdatalink(appname, cname) {
if (cname == '' || isNil(cname))
return '';
var protocol = window.location.protocol;
@@ -249,9 +294,9 @@ function compvaluelink(appname, cname) {
}
/**
- * Return the link to a component raw data.
+ * Return the link to a component.
*/
-function compdebuglink(appname, cname) {
+function complink(appname, cname) {
if (cname == '' || isNil(cname))
return '';
var protocol = window.location.protocol;
@@ -259,78 +304,81 @@ function compdebuglink(appname, cname) {
var port = ':' + window.location.port;
if (port == ':80' || port == ':443' || port == ':')
port = '';
- var link = protocol + '//' + appname + '.' + host + port + '/components/' + cname;
+ var link = protocol + '//' + appname + '.' + host + port + '/c/' + cname;
return link;
}
/**
* Handle a component select event.
*/
-function oncompselect(cname) {
- if (cname == compname)
+function oncompselect(gsel) {
+ if (gsel == gcomp)
return true;
- compname = cname;
- var link = compvaluelink(appname, cname);
+ gcomp = gsel;
+ var cname = isNil(gsel)? '' : gsel.id;
+ var link = compdatalink(appname, cname);
function updateButton(b, v) {
b.style.color = v? '#000000' : '#808080';
}
- updateButton($('deleteComponentButton'), link != '');
- updateButton($('playComponentButton'), link != '');
+ updateButton(cdelete, link != '');
+ updateButton(cplay, link != '');
return true;
}
/**
* Show the result data of a component.
*/
-function showdata(cname) {
+function showdata(gcomp) {
if (!gvisible)
return true;
- gvisible = false;
- $('playComponentButton').innerHTML = '&lt;';
+ if (isNil(gcomp))
+ return true;
+ cvalue.value = complink(appname, gcomp.id);
+ cplay.innerHTML = '&lt;';
gdiv.style.visibility = 'hidden'
- var rdiv = $('dataDiv');
- rdiv.style.visibility = 'visible';
- rdiv.innerHTML = '<iframe id="dataFrame" style="position: relative; height: 5000px; width: 100%; border: 0px;" scrolling="no" frameborder="0" src="' +
- compvaluelink(appname, cname) + '"></iframe>';
+ gvisible = false;
+ pdiv.style.visibility = 'visible';
+ pdiv.innerHTML = '<iframe id="dataFrame" style="position: relative; height: 5000px; width: 100%; border: 0px;" scrolling="no" frameborder="0" src="' +
+ compdatalink(appname, gcomp.id) + '"></iframe>';
return true;
}
/**
* Show the composition graph.
*/
-function showgraph() {
+function showgraph(gcomp) {
if (gvisible)
return true;
- gvisible = true;
- $('playComponentButton').innerHTML = '&gt;';
- var rdiv = $('dataDiv');
- rdiv.style.visibility = 'hidden';
- rdiv.innerHTML = '';
+ cplay.innerHTML = '&gt;';
+ pdiv.style.visibility = 'hidden';
+ pdiv.innerHTML = '';
gdiv.style.visibility = 'visible'
+ gvisible = true;
+ graph.compselect(gcomp, true, cvalue, cdelete);
return true;
}
/**
- * Play the current component.
+ * Handle play component button event.
*/
-$('playComponentButton').onclick = function() {
- if (compname == '')
+cplay.onclick = function() {
+ if (gcomp == null)
return false;
if (!gvisible)
- return showgraph();
- return showdata(compname);
+ return showgraph(gcomp);
+ return showdata(gcomp);
}
// Create editor graph area
-g = graph.mkgraph(graph.mkpath().move(-2500,95), $('compValue'), $('addComponentButton'), $('deleteComponentButton'));
+g = graph.mkgraph(graph.mkpath().move(-2500,95), cvalue, cadd, cdelete);
gdiv = g.parentNode;
bg = graph.mkgroup(graph.mkpath());
// Install the palettes
-var pos = graph.mkpath();
-installpalette('control', pos.rmove(5,0), g, bg, spalette, gpalettes);
+var pos = graph.mkpath().move(0, 0);
+bpalette = installpalette('control', pos.rmove(5,0), g, bg, spalette, gpalettes);
installpalette('values', pos.rmove(0,35), g, bg, spalette, gpalettes);
installpalette('lists', pos.rmove(0, 35), g, bg, spalette, gpalettes);
installpalette('transform', pos.rmove(0, 35), g, bg, spalette, gpalettes);
diff --git a/sca-cpp/trunk/modules/edit/htdocs/index.html b/sca-cpp/trunk/modules/edit/htdocs/index.html
index 68aa6f7f7b..612dd5868c 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/index.html
@@ -37,20 +37,18 @@
<table style="width: 100%;">
<tr><td><h1><span id="h1"></span></h1></td></tr>
</table>
-<br/>
<div style="margin-left: auto; margin-right: auto; text-align: center;">
-<h1><span id="maintitle"><span></h1>
-<br/><br/><br/><br/>
+<div id="maintitle" style="font-size: 150%;"></div>
-<div id="maindiagram"></div>
-<br/><br/><br/><br/>
+<div id="maindiagram"><div id="diagram" style="width: 320px; height: 280px; background: url(home.png); padding: 0px; margin: 0px auto;"></div></div>
+<br/>
<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/><br/>
-<div>Safari, Chrome, Firefox only for now.</div>
+<br/><br/>
+<div>Requires Safari 5+, Chrome 11+, Firefox 4+, IE 9+</div>
</div>
@@ -65,13 +63,23 @@ $('h1').innerHTML = hometitle(window.location.hostname);
displaymenu();
$('maintitle').innerHTML = isNil(config.maintitle)? 'Simple App Builder' : config.maintitle;
-$('maindiagram').innerHTML = isNil(config.maindiagram)? '&lt;&lt insert diagram here &gt;&gt;' : config.maindiagram;
$('getstarted').onclick = function() {
return window.open('/store/', '_self');
};
+// 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);
+
// Show the page
ui.showbody();
+
</script>
</body>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/login/index.html b/sca-cpp/trunk/modules/edit/htdocs/login/index.html
index 618a9eed7a..22df9ce7ef 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/login/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/login/index.html
@@ -27,13 +27,15 @@
<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
<script type="text/javascript" src="/all-min.js"></script>
</head>
-<body onorientationchange="ui.reload();">
+<body class="delayed" onorientationchange="ui.reload();">
+<div id="bodydiv" class="devicewidth">
+
<h1>Sign in</h1>
<form name="formSignin" onsubmit="submitSignin();" method="POST" action="/login/dologin/">
<table border="0">
<tr><td><b>Username:</b></td></tr>
-<tr><td><input type="text" id="httpd_username" name="httpd_username" value="" size="15" placeholder="Enter your user name" style="width: 300px;"/></td></tr>
+<tr><td><input type="text" id="httpd_username" name="httpd_username" value="" size="15" autocapitalize="off" placeholder="Enter your user name" style="width: 300px;"/></td></tr>
<tr><td><b>Password:</b></td></tr>
<tr><td><input type="password" name="httpd_password" value="" size="15" placeholder="Enter your password" style="width: 300px;"/></td></tr>
<tr><td><input type="submit" value="Sign in" class="greenbutton" style="font-weight: bold;"/></td><td></td></tr>
@@ -41,7 +43,13 @@
<input type="hidden" name="httpd_location" value="/"/>
</form>
+</div>
+
<script type="text/javascript">
+
+// Show the page
+ui.showbody();
+
function queryParams() {
qp = new Array();
qs = window.location.search.substring(1).split('&');
diff --git a/sca-cpp/trunk/modules/edit/htdocs/logout/index.html b/sca-cpp/trunk/modules/edit/htdocs/logout/index.html
index 7c326463cf..ee07c9bf15 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/logout/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/logout/index.html
@@ -27,14 +27,22 @@
<link rel="stylesheet" type="text/css" href="/ui-min.css"/>
<script type="text/javascript" src="/all-min.js"></script>
</head>
-<body onorientationchange="ui.reload();">
+<body class="delayed" onorientationchange="ui.reload();">
+<div id="bodydiv" class="devicewidth">
+
<h1>Sign out</h1>
<form name="signout" onsubmit="submitSignout();" action="/" method="GET">
<input type="submit" id="signOut" value="Sign out" class="greenbutton" style="font-weight: bold"/>
</form>
+</div>
+
<script type="text/javascript">
+
+// Show the page
+ui.showbody();
+
function submitSignout() {
var reset = 'TuscanyOpenAuth=;expires=' + new Date(1970,01,01).toGMTString() + ';domain=.' + domainname(window.location.hostname) + ';path=/;secure=TRUE';
document.cookie = reset;
diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/index.html b/sca-cpp/trunk/modules/edit/htdocs/page/index.html
index b498e8d77c..678491f220 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/page/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/page/index.html
@@ -37,26 +37,28 @@
<table style="width: 100%;">
<tr>
-<td><h1><span id="h1"></span><span id="appNameHeader"></span></h1></td>
-<td style="vertical-align: middle; text-align: right;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
+<td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td>
+<td style="vertical-align: middle; text-align: right; padding-right: 2px;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
</tr>
</table>
<table style="width: 100%;">
<tr>
-<th class="thr thl" style="padding-left: 2px; padding-right: 2px;">
-<input id="widgetName" type="text" value="" title="Widget name" placeholder="Name" style="position: relative; width: 65px;"/>
-<input id="widgetText" type="text" value="" title="Widget text" placeholder="Text" style="position: relative; width: 120px;"/>
+<th class="thr thl" style="padding-left: 2px; padding-right: 2px; width: 100%;">
+<input id="widgetValue" type="text" value="" title="Widget value" autocapitalize="off" placeholder="Value" style="position: relative; width: 100%;"/>
+</th>
+
+<th class="thl thr" style="text-align: right; padding-right: 2px;">
<span id="deleteWidgetButton" title="Delete a Widget" class="redbutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">-</span>
+
<span id="addWidgetButton" title="Add a Widget" class="greenbutton" style="font-weight: bold; font-size: 16px; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">+</span>
-<!--
-<span id="playWidgetButton" title="View" class="bluebutton" style="font-weight: bold; font-size: 16px; color: #808080; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">&gt;</span>
--->
+
+<span id="playPageButton" title="View page" class="bluebutton" style="font-weight: bold; font-size: 16px; display: inline-block; width: 24px; height: 20px; padding-top: 0px; padding-bottom: 0px; vertical-align: middle; text-align: center; margin-left: 0px; margin-right: 0px;">&gt;</span>
</th>
</tr>
</table>
-<div id="page" style="position: absolute; top: 95px; left: -2500px; right: 0px; height: 5000px;">
+<div id="editdiv" style="position: absolute; top: 95px; left: -2500px; right: 0px; height: 5000px;">
<div style="position: absolute; left: 2500px; top: 0px; right: 0px; height: 5000px; border:1px; border-style: solid; border-color: #a2bae7; background: url(/public/grid72.png);"></div>
<div class="guide" style="position: absolute; left: 2500px; top: 0px; width: 320px; height: 460px;"></div>
@@ -85,6 +87,8 @@
</div>
+<div id="playdiv" style="visibility: hidden; position: absolute; top: 95px; left: 0px; right: 0px; height: 5000px;"></div>
+
<div id="buffer" style="visibility: hidden; position: absolute; top: 0px; left: 0px; width: 0px; height: 0px"></div>
</div>
@@ -111,12 +115,35 @@ function applink(appname) {
// Set page titles
document.title = windowtitle(window.location.hostname) + ' - Page - ' + appname;
-$('h1').innerHTML = hometitle(window.location.hostname);
-$('appNameHeader').innerHTML = ' - <a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>';
+//$('h1').innerHTML = hometitle(window.location.hostname);
+$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '.' + window.location.hostname + '</a>';
// Load the menu bar
displaymenu();
+/**
+ * Page editor area, widget value field, add, delete and play page buttons.
+ */
+var ediv = $('editdiv');
+var evisible = true;
+var pdiv = $('playdiv');
+var wvalue = $('widgetValue');
+var wadd = $('addWidgetButton');
+var wdelete = $('deleteWidgetButton');
+var pplay = $('playPageButton');
+
+/**
+ * Adjust fields sizes.
+ */
+function resizeFields() {
+ wvalue.style.width = '0px';
+ wvalue.style.width = ui.pixpos(wvalue.parentNode.clientWidth - 18);
+ return true;
+}
+
+resizeFields();
+window.onresize = resizeFields;
+
// Show the page
ui.showbody();
@@ -138,15 +165,19 @@ function atompage(doc) {
}
/**
- * Track the current widget and page saved XHTML content.
+ * Track the current page saved XHTML content.
*/
-var widgetname = '';
var savedpagexhtml = '';
/**
+ * Track the current widget.
+ */
+var widget = null;
+
+/**
* Get and display an app page.
*/
-function getpage(name, edit) {
+function getpage(name, ediv) {
if (isNil(name))
return false;
return pages.get(name, function(doc) {
@@ -157,19 +188,19 @@ function getpage(name, edit) {
// Create a default empty page if necessary
if (isNil(el))
- buffer.innerHTML = '<DIV id="page">\n</DIV>\n';
+ buffer.innerHTML = '<div id="page"></div>';
else
buffer.innerHTML = writeStrings(writeXML(atompage(doc), false));
// Append page nodes to editor
map(function(e) {
- edit.appendChild(e);
+ ediv.appendChild(e);
if (!isNil(e.style))
e.style.left = ui.pixpos(ui.numpos(e.style.left) + 2500);
return page.cover(e);
}, nodeList(buffer.childNodes[0].childNodes));
- savedpagexhtml = pagexhtml();
+ savedpagexhtml = pagexhtml(ediv);
return true;
});
}
@@ -177,22 +208,28 @@ function getpage(name, edit) {
/**
* Handle add widget button click event.
*/
-$('addWidgetButton').onclick = function(e) {
+wadd.onclick = function(e) {
// Show the widget palette
- $('page').style.left = ui.pixpos(0);
+ ediv.style.left = ui.pixpos(0);
};
/**
* Return the current page XHTML content.
*/
-function pagexhtml() {
+function pagexhtml(ediv) {
// Copy page DOM to hidden buffer
- var edit = $('page');
var buffer = $('buffer');
- buffer.innerHTML = '<DIV id="page">\n</DIV>\n'
+ buffer.innerHTML = '<div id="page"></div>'
var div = buffer.childNodes[0];
- div.innerHTML = edit.innerHTML;
+
+ // Capture the nodes inside the page div
+ div.innerHTML = ediv.innerHTML;
+ var nodes = nodeList(div.childNodes);
+ map(function(e) {
+ div.removeChild(e);
+ return e;
+ }, nodes);
// Filter out palette and editor artifacts, which are not
// part of the page, as well as nodes positioned out the
@@ -204,7 +241,7 @@ function pagexhtml() {
if (x < 0 || ui.numpos(e.style.top) < 0)
return false;
return true;
- }, nodeList(div.childNodes));
+ }, nodes);
// Reposition nodes
map(function(e) {
@@ -226,8 +263,7 @@ function pagexhtml() {
return 0;
});
- // Append them back to the div in order
- div.innerHTML = '';
+ // Append the sorted nodes back to the div in order
map(function(e) {
div.appendChild(e);
return e;
@@ -242,20 +278,20 @@ function pagexhtml() {
/**
* Save the current page.
*/
-function save() {
+function save(newxml) {
$('saveStatus').innerHTML = 'Saving';
// Get the current page XHTML content
- savedpagexhtml = pagexhtml();
+ savedpagexhtml = newxml;
// Update the page ATOM entry
var entry = '<entry xmlns="http://www.w3.org/2005/Atom">' +
'<title type="text">' + appname + '</title><id>' + appname + '</id><content type="application/xml">' +
- savedpagexhtml + '</content></entry>';
+ newxml + '</content></entry>';
- pages.put(appname, entry);
- if (savedpagexhtml == pagexhtml())
+ pages.put(appname, entry, function(r) {
$('saveStatus').innerHTML = 'Saved';
+ });
return true;
};
@@ -263,19 +299,22 @@ function save() {
* Handle a page change event
*/
function onpagechange(prop) {
- if (savedpagexhtml == pagexhtml())
+ var newxml = pagexhtml(ediv);
+ if (savedpagexhtml == newxml)
return false;
$('saveStatus').innerHTML = 'Modified';
// Save property changes right away
if (prop)
- return save();
+ return save(newxml);
- // Autosave other changes after 3 seconds
+ // Autosave other changes after 1 second
setTimeout(function() {
- if (savedpagexhtml == pagexhtml())
+ if (savedpagexhtml == newxml) {
+ $('saveStatus').innerHTML = 'Saved';
return false;
- return save();
+ }
+ return save(newxml);
}, 1000);
return true;
}
@@ -298,40 +337,68 @@ function compvaluelink(appname, cname) {
/**
* Handle a widget select event.
*/
-function onwidgetselect(wname) {
- if (wname == widgetname)
+function onwidgetselect(w) {
+ if (w == widget)
return true;
- widgetname = wname;
- var link = compvaluelink(appname, wname);
+ widget = w;
+ var link = compvaluelink(appname, isNil(w)? '' : w.id);
function updateButton(b, v) {
b.style.color = v? '#000000' : '#808080';
}
- updateButton($('deleteWidgetButton'), link != '');
- //updateButton($('playWidgetButton'), link != '');
+ updateButton(wdelete, link != '');
+ return true;
+}
+/**
+ * Play page in a frame.
+ */
+function playpage() {
+ if (!evisible)
+ return true;
+ page.widgetselect(widget, false, wvalue, wdelete);
+ page.selected = null;
+ wvalue.value = applink(appname);
+ pplay.innerHTML = '&lt;';
+ ediv.style.visibility = 'hidden'
+ evisible = false;
+ pdiv.style.visibility = 'visible';
+ pdiv.innerHTML = '<iframe id="appFrame" style="position: relative; height: 5000px; width: 100%; border: 0px;" scrolling="no" frameborder="0" src="' +
+ applink(appname) + '"></iframe>';
+ return true;
+}
+
+/**
+ * Show the page editor.
+ */
+function showedit() {
+ if (evisible)
+ return true;
+ pplay.innerHTML = '&gt;';
+ pdiv.style.visibility = 'hidden';
+ pdiv.innerHTML = '';
+ ediv.style.visibility = 'visible'
+ evisible = true;
+ page.widgetselect(widget, true, wvalue, wdelete);
+ page.selected = widget;
return true;
}
/**
- * Play the component associated with the current widget.
+ * Handle play page button event.
*/
-/*
-$('playWidgetButton').onclick = function() {
- var link = compvaluelink(appname, widgetname);
- if (link == '')
- return;
- return window.open(link, '_' + appname + '_' + widgetname);
+pplay.onclick = function() {
+ if (!evisible)
+ return showedit();
+ return playpage();
}
-*/
// Initialize the page editor
-var edit = $('page');
-page.edit(edit, $('widgetName'), $('widgetText'), $('addWidgetButton'), $('deleteWidgetButton'), onpagechange, onwidgetselect);
+page.edit(ediv, wvalue, wadd, wdelete, onpagechange, onwidgetselect);
// Get and display the current app page
-getpage(appname, edit);
+getpage(appname, ediv);
</script>
</body>
diff --git a/sca-cpp/trunk/modules/edit/htdocs/page/page.js b/sca-cpp/trunk/modules/edit/htdocs/page/page.js
index 09617d9720..707788cc64 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/page/page.js
+++ b/sca-cpp/trunk/modules/edit/htdocs/page/page.js
@@ -26,18 +26,16 @@ var page = {};
* Default positions and sizes.
*/
var palcx = 2500;
-var trashcx = 2480;
/**
* Init a page editor. Works with all browsers except IE.
*/
-page.edit = function(elem, wname, wtext, wadd, wdelete, onchange, onselect) {
+page.edit = function(elem, wvalue, wadd, wdelete, onchange, onselect) {
// Track element dragging and selection
page.dragging = null;
page.selected = null;
- wname.disabled = true;
- wtext.disabled = true;
+ wvalue.disabled = true;
wdelete.disabled = true;
// Trigger widget select and page change events
@@ -49,59 +47,22 @@ page.edit = function(elem, wname, wtext, wadd, wdelete, onchange, onselect) {
*/
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
- page.dragging = page.draggable(e.target, elem);
- page.selected = page.dragging;
- if (page.dragging == null) {
-
- // Reset current selection
- wname.value = '';
- wname.disabled = true;
- wtext.value = '';
- wtext.disabled = true;
- wdelete.disabled = true;
-
- // Trigger widget select event
- page.onwidgetselect('');
+ var dragging = page.draggable(e.target, elem);
+ if (dragging == null || dragging != page.selected)
return true;
- }
-
- // Clone element dragged from palette
- if (page.dragging.id.substring(0, 8) == 'palette:') {
- page.dragging = page.clone(page.dragging);
- page.selected = page.dragging;
-
- // Move into the editing area and hide the palette
- page.selected.style.left = ui.pixpos(ui.numpos(page.selected.style.left) + palcx);
- elem.style.left = ui.pixpos(palcx * -1);
-
- // Bring it to the top
- page.bringtotop(page.dragging);
-
- // Trigger page change event
- page.onpagechange(true);
-
- } else {
-
- // Bring it to the top
- page.bringtotop(page.dragging);
- }
+ page.dragging = dragging;
// Remember mouse position
var pos = typeof e.touches != "undefined" ? e.touches[0] : e;
page.dragX = pos.screenX;
page.dragY = pos.screenY;
- // Update the widget name and text fields
- wname.value = page.selected.id;
- wname.disabled = false;
- wtext.value = page.text(page.selected);
- wtext.disabled = !page.hastext(page.selected);
- wdelete.disabled = false;
-
- // Trigger widget select event
- page.onwidgetselect(page.selected.id);
-
if (e.preventDefault)
e.preventDefault();
else
@@ -130,29 +91,6 @@ page.edit = function(elem, wname, wtext, wadd, wdelete, onchange, onselect) {
// Fixup widget style
page.fixupwidget(page.dragging);
- // Discard element dragged out of page area
- if (ui.numpos(page.dragging.style.left) < palcx && page.dragging.id.substring(0, 8) != 'palette:') {
- if (ui.numpos(page.dragging.style.left) >= trashcx) {
-
- // Unless it's close enough to page area, then move it there
- page.dragging.style.left = ui.pixpos(palcx);
- page.dragging.cover.style.left = ui.pixpos(palcx);
- } else {
- page.dragging.parentNode.removeChild(page.dragging);
-
- // Reset current selection
- page.selected = null;
- wname.value = '';
- wname.disabled = true;
- wtext.value = '';
- wtext.disabled = true;
- wdelete.disabled = true;
-
- // Trigger widget select event
- page.onwidgetselect('');
- }
- }
-
// Forget dragged element
page.dragging = null;
@@ -171,16 +109,20 @@ page.edit = function(elem, wname, wtext, wadd, wdelete, onchange, onselect) {
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 pos = typeof e.touches != "undefined" ? e.touches[0] : e;
var newX = curX + (pos.screenX - page.dragX);
var newY = curY + (pos.screenY - page.dragY);
- if (newX >= 0)
+ if (newX >= palcx)
page.dragX = pos.screenX;
else
- newX = 0;
+ newX = palcx;
if (newY >= 0)
page.dragY = pos.screenY;
else
@@ -201,32 +143,70 @@ page.edit = function(elem, wname, wtext, wadd, wdelete, onchange, onselect) {
* Handle a mouse click event.
*/
elem.onclick = function(e) {
- if (page.dragging == null) {
+
+ // 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, 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, 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, wdelete);
+
+ // Trigger widget select event
+ page.onwidgetselect(page.selected);
+
return true;
};
/**
* Handle field on change events.
*/
- wname.onchange = wname.onblur = function() {
- if (page.selected == null)
- return false;
- page.selected.id = wname.value;
-
- // Trigger page change event
- page.onpagechange(true);
- return false;
- };
-
- wtext.onchange = wtext.onblur = function() {
+ wvalue.onchange = wvalue.onblur = function() {
if (page.selected == null)
return false;
- page.settext(page.selected, wtext.value);
+ 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);
@@ -246,19 +226,16 @@ page.edit = function(elem, wname, wtext, wadd, wdelete, onchange, onselect) {
if (page.selected == null)
return false;
+ // Reset current selection
+ page.widgetselect(page.selected, false, wvalue, wdelete);
+
// Remove selected widget
page.selected.parentNode.removeChild(page.selected);
-
- // Reset current selection
+ page.selected.cover.parentNode.removeChild(page.selected.cover);
page.selected = null;
- wname.value = '';
- wname.disabled = true;
- wtext.value = '';
- wtext.disabled = true;
- wdelete.disabled = true;
// Trigger widget select event
- page.onwidgetselect('');
+ page.onwidgetselect(null);
// Trigger page change event
page.onpagechange(true);
@@ -276,6 +253,11 @@ page.edit = function(elem, wname, wtext, wadd, wdelete, onchange, onselect) {
* Return the text of a widget.
*/
page.text = function(e) {
+ var formula = e.id;
+ if (formula.substring(0, 5) != 'page:') {
+ return '=' + formula;
+ }
+
if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section')
return car(childElements(e)).innerHTML;
if (e.className == 'button' || e.className == 'checkbox')
@@ -331,6 +313,9 @@ page.hastext = function(e) {
* Set the text of a widget.
*/
page.settext = function(e, t) {
+ var formula = t.length > 1 && t.substring(0, 1) == '=';
+ e.id = formula? t.substring(1) : 'page:' + e.className;
+
if (e.className == 'h1' || e.className == 'h2' || e.className == 'text' || e.className == 'section') {
car(childElements(e)).innerHTML = t;
return t;
@@ -351,10 +336,12 @@ page.settext = function(e, t) {
return t;
}
if (e.className == 'list') {
+ e.innerHTML = '<table class="datatable" style="width: 100%;;"><tr><td class="datatd">' + t + '</td></tr><tr><td class="datatd">...</td></tr></table>';
return '';
}
if (e.className == 'table') {
- return '';
+ e.innerHTML = '<table class="datatable" style="width: 100%;"><tr><td class="datatdl">' + t + '</td><td class="datatdr">...</td></tr><tr><td class="datatdl">...</td><td class="datatdr">...</td></tr></table>';
+ return t;
}
if (e.className == 'link') {
var l = t.split(',');
@@ -364,11 +351,11 @@ page.settext = function(e, t) {
return t;
}
if (e.className == 'img') {
- car(childElements(e)).src = t;
+ car(childElements(e)).src = formula? '/public/img.png' : t;
return t;
}
if (e.className == 'iframe') {
- car(childElements(e)).href = t;
+ car(childElements(e)).href = formula? '/public/iframe.html' : t;
return t;
}
return '';
@@ -388,10 +375,12 @@ page.fixupwidget = function(e) {
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;
}
@@ -427,19 +416,51 @@ page.bringtotop = function(n) {
}
/**
+ * Draw widget selection.
+ */
+page.widgetselect = function(n, s, wvalue, wdelete) {
+ if (isNil(n) || !s) {
+ // Clear the widget value field
+ wvalue.value = '';
+ wvalue.disabled = true;
+ wdelete.disabled = true;
+
+ // Clear the widget outline
+ if (!isNil(n))
+ n.cover.style.borderWidth = '0px';
+ }
+ if (isNil(n))
+ return true;
+
+ // Update the widget value field
+ wvalue.value = page.text(n);
+ wvalue.disabled = false;
+ wdelete.disabled = false;
+
+ // Outline the widget
+ n.cover.style.borderWidth = s? '2px' : '0px';
+ 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('span');
+ var cover = document.createElement('div');
cover.style.position = 'absolute';
- cover.style.left = ui.pixpos(ui.numpos(e.style.left) - 5);
- cover.style.top = ui.pixpos(ui.numpos(e.style.top) - 5);
- cover.style.width = e.clientWidth + 10;
- cover.style.height = e.clientHeight + 10;
- cover.style.visibility = 'visible';
+ 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);
@@ -458,11 +479,15 @@ page.clone = function(e) {
var ne = document.createElement('span');
// Skip the palette: prefix
- ne.id = e.id.substr(8);
+ 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;
}
diff --git a/sca-cpp/trunk/modules/edit/htdocs/stats/index.html b/sca-cpp/trunk/modules/edit/htdocs/stats/index.html
index 737bb0bef4..b676b4b38c 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/stats/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/stats/index.html
@@ -36,14 +36,18 @@
<table style="width: 100%;">
<tr>
-<td><h1><span id="h1"></span><span id="appNameHeader"></span></h1></td>
+<td><h2><span id="h1"></span><span id="appNameHeader"></span></h2></td>
<td style="vertical-align: middle; text-align: right;"><span id="saveStatus" style="font-weight: bold; color: #808080;">Saved</span></td>
</tr>
</table>
<table style="width: 100%;">
<tr>
-<th class="thl thr" style="padding-top: 4px; padding-bottom: 4px;">Stats</th>
+<th class="thl thr" style="padding-top: 4px; padding-bottom: 4px; padding-left: 2px; padding-right: 2px; ">Stats</th>
+
+<th class="thl thr" style="width: 100%; text-align: right; padding-right: 2px; padding-top: 0px; padding-bottom: 0px;">
+<input type="button" class="greenbutton" style="font-weight: bold; margin-top: 0px; margin-bottom: 0px; height: 24px;" id="cloneApp" value="Clone" title="Clone this app"/>
+</th>
</tr>
</table>
@@ -85,8 +89,11 @@ function applink(appname) {
// Set page titles
document.title = windowtitle(window.location.hostname) + ' - Stats - ' + appname;
-$('h1').innerHTML = hometitle(window.location.hostname);
-$('appNameHeader').innerHTML = ' - <a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '</a>';
+//$('h1').innerHTML = hometitle(window.location.hostname);
+$('appNameHeader').innerHTML = '<a href=\"' + applink(appname) + '\" target=\"' + '_blank' + '\">' + appname + '.' + window.location.hostname + '</a>';
+var tclone = isNil(config.clone)? 'Clone' : config.clone;
+$('cloneApp').value = tclone;
+$('cloneApp').title = tclone + ' this app';
// Load the menu bar
displaymenu();
@@ -96,7 +103,7 @@ ui.showbody();
// Init service references
var editWidget = sca.component("EditWidget");
-var dashboard = sca.reference(editWidget, "dashboard");
+var dashboards = sca.reference(editWidget, "dashboards");
/**
* The current app entry and corresponding saved XML content.
@@ -110,7 +117,7 @@ var savedappentryxml = '';
function getapp(name) {
if (isNil(name))
return false;
- return dashboard.get(name, function(doc) {
+ return dashboards.get(name, function(doc) {
appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
var title = cadr(assoc("'title", cdr(appentry)));
$('appTitle').value = title;
@@ -127,7 +134,7 @@ function getapp(name) {
function save(entryxml) {
$('saveStatus').innerHTML = 'Saving';
savedappentryxml = entryxml;
- dashboard.put(appname, savedappentryxml);
+ dashboards.put(appname, savedappentryxml);
$('saveStatus').innerHTML = 'Saved';
return true;
}
@@ -156,6 +163,13 @@ $('appForm').onsubmit = function() {
return false;
};
+/**
+ * Handle Clone button event.
+ */
+$('cloneApp').onclick = function() {
+ return window.open('/clone/?app=' + appname, '_self');
+}
+
// Get the current app
getapp(appname);
diff --git a/sca-cpp/trunk/modules/edit/htdocs/store/index.html b/sca-cpp/trunk/modules/edit/htdocs/store/index.html
index 3c79f6c780..1d96781801 100644
--- a/sca-cpp/trunk/modules/edit/htdocs/store/index.html
+++ b/sca-cpp/trunk/modules/edit/htdocs/store/index.html
@@ -94,7 +94,7 @@ ui.showbody();
*/
var editWidget = sca.component("EditWidget");
var store = sca.reference(editWidget, "store");
-var dashboard = sca.reference(editWidget, "dashboard");
+var dashboards = sca.reference(editWidget, "dashboards");
/**
* Return the link to an app.
@@ -117,6 +117,13 @@ function editApp(appname) {
}
/**
+ * View an app.
+ */
+function viewApp(appname) {
+ return window.open('/stats/?app=' + appname, '_self');
+}
+
+/**
* Create an app.
*/
if (category == 'myapps') {
@@ -126,13 +133,6 @@ if (category == 'myapps') {
}
/**
- * Clone an app.
- */
-function cloneApp(appname) {
- return window.open('/clone/?app=' + appname, '_self');
-}
-
-/**
* Get and display list of apps.
*/
function getapps(category) {
@@ -150,10 +150,7 @@ function getapps(category) {
apps += '<div class="box" style="width: 285px; display: inline-block; border: 1px; border-style: solid; border-color: #dcdcdc; border-collapse: collapse; margin: 5px; padding: 10px; vertical-align: top;">'
apps += '<table><tr>';
apps += '<td>';
- apps += '<div>' + ui.ahref(applink(name), '_blank', '<img src="/public/app.png" width="50" height="50" style="height: 50px; width: 50px; vertical-align: top; margin-right: 10px; margin-bottom: 5px;"></img>') + '</div>';
- apps += '<div><input type="button" class="greenbutton" id="cloneApp" value="' + clone + '" title="' + clone + ' this app" onclick="cloneApp(\'' + name + '\');"></div>';
- if (category == 'myapps')
- apps += '<div><input type="button" id="editApp" class="bluebutton" value="Edit" title="Edit this app" onclick="editApp(\'' + name + '\');"></div>';
+ 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-right: 10px; margin-bottom: 5px;"></img>') + '</div>';
apps += '</td>';
apps += '<td class="tdw">';
apps += '<div style="font-weight: bold">' + ui.ahref(applink(name), '_blank', name) + '</div>';
@@ -164,7 +161,6 @@ function getapps(category) {
apps += '<div>Feb 4, 2011</div>';
apps += '<br/>';
apps += '<div>' + title + '</div>';
- apps += '<br/>';
apps += '</td>';
apps += '</tr></table>';
apps += '</div>';
@@ -174,7 +170,7 @@ function getapps(category) {
}
if (category == 'myapps')
- return dashboard.get('', display);
+ return dashboards.get('', display);
return store.get(category, display);
}