diff options
Diffstat (limited to 'sca-cpp/trunk')
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"/> <span id="appDomain"></span></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><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"/> <span id="appDomain"></span></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><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;">></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;">></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 = '<'; + if (isNil(gcomp)) + return true; + cvalue.value = complink(appname, gcomp.id); + cplay.innerHTML = '<'; 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 = '>'; - var rdiv = $('dataDiv'); - rdiv.style.visibility = 'hidden'; - rdiv.innerHTML = ''; + cplay.innerHTML = '>'; + 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)? '<< insert diagram here >>' : 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;">></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;">></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 = '<'; + 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 = '>'; + 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); } |