You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by js...@apache.org on 2013/01/03 08:41:56 UTC

svn commit: r1428193 [2/8] - in /tuscany/sca-cpp/trunk: etc/ hosting/server/ hosting/server/data/apps/me360/ hosting/server/data/apps/nearme/ hosting/server/data/apps/nearme2/ hosting/server/data/apps/new/ hosting/server/data/apps/ourphotos/ hosting/se...

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/clone/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/clone/index.html?rev=1428193&r1=1428192&r2=1428193&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/clone/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/clone/index.html Thu Jan  3 07:41:53 2013
@@ -19,29 +19,24 @@
 -->
 <div id="bodydiv" class="body">
 
-<div class="viewform">
+<div id="viewform" class="viewform">
 
 <form id="cloneAppForm">
 <table style="width: 100%;">
-<tr><td><b>New App Name:</b></td></tr>
-<tr><td><input type="text" id="appName" class="flatentry" size="15" autocapitalize="off" placeholder="Your app name"/></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Icon:</b></td></tr>
-<tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Title:</b></td></tr>
-<tr><td><input type="text" id="appTitle" class="flatentry" size="30" placeholder="Enter the title of your app" style="width: 300px;"/></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
-<tr><td><textarea id="appDescription" class="flatentry" cols="40" rows="3" placeholder="Enter a short description of your app" style="width: 300px;"></textarea></td></tr>
-<tr><td>
-<input id="cloneAppOKButton" type="submit" class="graybutton bluebutton" style="font-weight: bold;" value="Clone" title="Clone the app"/>
+<tr><td class="label">New URL:</td></tr>
+<tr><td><span id="hostname" class="readentry"></span><input type="text" id="appName" class="flatentry" size="18" autocapitalize="off" placeholder="New app name"/></td></tr>
+<tr><td style="padding-top: 20px;">
+<input id="cloneAppOKButton" type="submit" class="bluebutton" style="font-weight: bold;" value="Clone" title="Clone this app"/>
 <input id="cloneAppCancelButton" type="button" class="graybutton" value="Cancel"/>
 </td></tr>
 </table>
 </form>
+<br/>
 
 </div>
 
 <script type="text/javascript">
-(function() {
+(function clonebody() {
 
 /**
  * Get the app name.
@@ -49,20 +44,20 @@
 var appname = ui.fragmentParams(location)['app'];
 
 /**
- * Set page titles.
+ * Setup page layout.
  */
-document.title = config.windowtitle() + ' - ' + config.clone() + ' - ' + appname;
-$('viewhead').innerHTML = '<span class="smenu">' + config.clone() + ' ' + appname + '</span>';
-$('cloneAppOKButton').value = config.clone();
-$('cloneAppOKButton').title = config.clone() + ' this app';
-
-/**
- * Set images.
- */
-$('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
+(function layout() {
+    document.title = config.windowtitle() + ' - ' + config.clone() + ' - ' + appname;
+    $('viewhead').innerHTML = '<span class="smenu">' + config.clone() + ' ' + appname + '</span>';
+    if (!ui.isMobile())
+        $('viewform').className = 'viewform flatscrollbars';
+    $('hostname').innerHTML = window.location.hostname + '/';
+    $('cloneAppOKButton').value = config.clone();
+    $('cloneAppOKButton').title = config.clone() + ' this app';
+})();
 
 /**
- * Init service references.
+ * Initialize service references.
  */
 var editorComp = sca.component("Editor");
 var apps = sca.reference(editorComp, "apps");
@@ -71,50 +66,60 @@ var apps = sca.reference(editorComp, "ap
  * The current app entry and corresponding saved XML content.
  */
 var appentry;
-var savedappentryxml = '';
+var savedappxml = '';
 
 /**
- * Get and display an app.
+ * Get and display the requested app.
  */
-function getapp(name) {
-    if (isNil(name))
+(function getapp() {
+    if (isNil(appname))
         return false;
-    showStatus('Loading');
+    workingstatus(true);
+    showstatus('Loading');
 
-    return apps.get(name, function(doc) {
+    return apps.get(appname, function(doc) {
 
         // Stop now if we didn't get the app
         if (doc == null) {
-            showError('App not available');
+            errorstatus('Couldn\'t get the app info');
+            workingstatus(false);
             return false;
         }
-        showOnlineStatus();
 
-        appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
-        $('appTitle').value = cadr(assoc("'title", cdr(appentry)));
-        var content = cadr(assoc("'content", cdr(appentry)));
-        var description = assoc("'description", content);
-        $('appDescription').value = isNil(description) || isNil(cadr(description))? '' : cadr(description);
-        savedappentryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
+        appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", appname));
+        var content = cadr(assoc("'content", appentry));
+        savedappxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
+
+        onlinestatus();
+        workingstatus(false);
         return true;
     });
-}
+})();
 
 /**
  * Save an app.
  */
-function save(name, entryxml) {
-    showStatus('Saving');
-    savedappentryxml = entryxml;
-    apps.put(name, savedappentryxml, function(e) {
+function saveapp(name, entryxml) {
+    workingstatus(true);
+    showstatus('Saving');
+
+    savedappxml = entryxml;
+    apps.put(name, savedappxml, function(e) {
         if (e) {
-            showStatus('Local copy');
+            if (e.code && e.code == 404) {
+                errorstatus('App name is taken, please pick another name');
+                workingstatus(false);
+                return false;
+            }
+            showstatus('Local copy');
+            workingstatus(false);
             return false;
         }
-        showStatus('Saved');
+        showstatus('Saved');
+        workingstatus(false);
 
-        // Open it in the page editor
-        ui.navigate('/#view=page&app=' + name, '_view');
+        // Open the app in the page editor
+        ui.navigate('/#view=info&app=' + name, '_view');
         return false;
     });
     return false;
@@ -124,19 +129,36 @@ function save(name, entryxml) {
  * Clone an app.
  */
 $('cloneAppForm').onsubmit = function() {
+
+    // Validate app name
     var name = $('appName').value;
-    if (name == '') {
-        showError('Missing app name');
+    if (name.length < 3 || name.length > 10) {
+        errorstatus('App name must be between 3 and 10 characters');
+        return false;
+    }
+    name = name.toLowerCase();
+    var anum = name.split('').reduce(function(p, c, i, a) { return p && ((c >= 'a' && c <= 'z') || (c >= '0' && c<= '9')); }, true);
+    if (!anum) {
+        errorstatus('App name is taken, please pick another name');
+        return false;
+    }
+    if (name.charAt(0) < 'a' || name.charAt(0) > 'z') {
+        errorstatus('App name must start with a letter');
+        return false;
+    }
+
+    // Check reserved app names
+    var reserved = mklist('account', 'app', 'cache', 'clone', 'create', 'delete', 'graph', 'home', 'login', 'new', 'page', 'proxy', 'public', 'private', 'info', 'store');
+    if (!isNil(assoc(name, map(function(r) { return mklist(r, r); }, reserved)))) {
+        errorstatus('App name is taken, please pick another name');
         return false;
     }
-    showStatus('Saving');
 
     // Clone the app
-    var title = $('appTitle').value;
-    var description = $('appDescription').value;
-    appentry = mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", appname), mklist("'content", mklist("'stats", mklist("'description", description))));
+    showstatus('Modified');
+    appentry = mklist("'entry", mklist("'title", name), mklist("'id", appname), mklist("'author", username));
     var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
-    return save(name, entryxml);
+    return saveapp(name, entryxml);
 };
 
 /**
@@ -146,11 +168,6 @@ $('cloneAppCancelButton').onclick = func
     history.back();
 };
 
-/**
- * Get the current app.
- */
-getapp(appname);
-
 })();
 </script>
 

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/config.js
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/config.js?rev=1428193&r1=1428192&r2=1428193&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/config.js (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/config.js Thu Jan  3 07:41:53 2013
@@ -32,7 +32,7 @@ config.pagetitle = function() {
 };
 
 config.hometitle = function() {
-    return '<br/><span style="font-weight: bold;">Create SCA Composite Apps</span><br/><br/>';
+    return '<br/><span style="font-weight: bold;">Create SCA Apps</span><br/><br/>';
 };
 
 config.clone = function() {

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/create/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/create/index.html?rev=1428193&r1=1428192&r2=1428193&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/create/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/create/index.html Thu Jan  3 07:41:53 2013
@@ -19,43 +19,38 @@
 -->
 <div id="bodydiv" class="body">
 
-<div class="viewform">
+<div id="viewform" class="viewform">
 
 <form id="createAppForm">
 <table style="width: 100%;">
-<tr><td><b>App Name:</b></td></tr>
-<tr><td><input type="text" id="appName" class="flatentry" size="15" autocapitalize="off" placeholder="Your app name"/></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr>
-<tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr>
-<tr><td><input type="text" id="appTitle" class="flatentry" size="30" placeholder="Enter the title of your app" style="width: 300px;"/></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
-<tr><td><textarea id="appDescription" class="flatentry" cols="40" rows="3" placeholder="Enter a short description of your app" style="width: 300px;"></textarea></td></tr>
-<tr><td>
-<input id="createAppOKButton" type="submit" class="graybutton bluebutton" style="font-weight: bold;" value="Create" title="Create the app"/>
+<tr><td class="label">URL:</td></tr>
+<tr><td><span id="hostname" class="readentry"></span><input type="text" id="appName" class="flatentry" size="18" autocapitalize="off" placeholder="New app name"/></td></tr>
+<tr><td style="padding-top: 20px;">
+<input id="createAppOKButton" type="submit" class="bluebutton" style="font-weight: bold;" value="Create" title="Create the app"/>
 <input id="createAppCancelButton" type="button" class="graybutton" value="Cancel"/>
 </td></tr>
 </table>
 </form>
+<br/>
 
 </div>
 
 <script type="text/javascript">
-(function() {
+(function createbody() {
 
 /**
- * Set page titles.
+ * Setup page layout.
  */
-document.title = config.windowtitle() + ' - Create App';
-$('viewhead').innerHTML = '<span class="smenu">Create an App</span>';
-
-/**
- * Set images.
- */
-$('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
+(function layout() {
+    document.title = config.windowtitle() + ' - New App';
+    $('viewhead').innerHTML = '<span class="smenu">New App</span>';
+    if (!ui.isMobile())
+        $('viewform').className = 'viewform flatscrollbars';
+    $('hostname').innerHTML = window.location.hostname + '/';
+})();
 
 /**
- * Init service references.
+ * Initialize service references.
  */
 var editorComp = sca.component("Editor");
 var apps = sca.reference(editorComp, "apps");
@@ -64,23 +59,32 @@ var apps = sca.reference(editorComp, "ap
  * The current app entry and corresponding saved XML content.
  */
 var appentry;
-var savedappentryxml = '';
+var savedappxml = '';
 
 /**
  * Save an app.
  */
-function save(name, entryxml) {
-    showStatus('Saving');
-    savedappentryxml = entryxml;
-    apps.put(name, savedappentryxml, function(e) {
+function saveapp(name, entryxml) {
+    workingstatus(true);
+    showstatus('Saving');
+
+    savedappxml = entryxml;
+    apps.put(name, savedappxml, function(e) {
         if (e) {
-            showStatus('Local copy');
+            if (e.code && e.code == 404) {
+                errorstatus('App name is taken, please pick another name');
+                workingstatus(false);
+                return false;
+            }
+            showstatus('Local copy');
+            workingstatus(false);
             return false;
         }
-        showStatus('Saved');
+        showstatus('Saved');
+        workingstatus(false);
 
-        // Open it in the page editor
-        ui.navigate('/#view=page&app=' + name, '_view');
+        // Open the app in the page editor
+        ui.navigate('/#view=info&app=' + name, '_view');
         return false;
     });
     return false;
@@ -90,19 +94,36 @@ function save(name, entryxml) {
  * Create an app.
  */
 $('createAppForm').onsubmit = function() {
+
+    // Validate app name
     var name = $('appName').value;
-    if (name == '') {
-        showError('Missing app name');
+    if (name.length < 3 || name.length > 10) {
+        errorstatus('App name must be between 3 and 10 characters');
+        return false;
+    }
+    name = name.toLowerCase();
+    var anum = name.split('').reduce(function(p, c, i, a) { return p && ((c >= 'a' && c <= 'z') || (c >= '0' && c<= '9')); }, true);
+    if (!anum) {
+        errorstatus('App name can only use numbers and letters');
+        return false;
+    }
+    if (name.charAt(0) < 'a' || name.charAt(0) > 'z') {
+        errorstatus('App name must start with a letter');
+        return false;
+    }
+
+    // Check reserved app names
+    var reserved = mklist('account', 'app', 'cache', 'clone', 'create', 'delete', 'graph', 'home', 'login', 'new', 'page', 'proxy', 'public', 'private', 'info', 'store');
+    if (!isNil(assoc(name, map(function(r) { return mklist(r, r); }, reserved)))) {
+        errorstatus('App name is taken, please pick another name');
         return false;
     }
-    showStatus('Modified');
 
     // Clone the 'new' app template
-    var title = $('appTitle').value;
-    var description = $('appDescription').value;
-    appentry = mklist("'entry", mklist("'title", title != ''? title : name), mklist("'id", 'new'), mklist("'content", mklist("'stats", mklist("'description", description))));
+    showstatus('Modified');
+    appentry = mklist("'entry", mklist("'title", name), mklist("'id", 'new'), mklist("'author", username));
     var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
-    return save(name, entryxml);
+    return saveapp(name, entryxml);
 };
 
 /**
@@ -115,7 +136,7 @@ $('createAppCancelButton').onclick = fun
 /**
  * Show the status.
  */
-showOnlineStatus();
+onlinestatus();
 
 })();
 </script>

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/index.html?rev=1428193&r1=1428192&r2=1428193&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/delete/index.html Thu Jan  3 07:41:53 2013
@@ -19,31 +19,32 @@
 -->
 <div id="bodydiv" class="body">
 
-<div class="viewform">
+<div id="viewform" class="viewform">
 
 <form id="deleteAppForm">
 <table style="width: 100%;">
-<tr><tr><td style="padding-top: 6px;"><b>App Icon:</b></td></tr>
-<tr><td><img id="appimg" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>App Title:</b></td></tr>
-<tr><td><input type="text" id="appTitle" class="flatentry" size="30" readonly="readonly" style="width: 300px;"/></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Author:</b></td></tr>
-<tr><td><span id="appAuthor"></span></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Updated:</b></td></tr>
-<tr><td><span id="appUpdated"></span></td></tr>
-<tr><tr><td style="padding-top: 6px;"><b>Description:</b></td></tr>
-<tr><td><textarea id="appDescription" class="flatentry" cols="40" rows="3" readonly="readonly" style="width: 300px;"></textarea></td></tr>
+<tr><tr><td class="label">URL:</td></tr>
+<tr><td><input type="text" id="appURL" class="readentry" size="30" readonly="readonly" placeholder="App URL" style="width: 300px;"/></td></tr>
+<tr><tr><td class="label">Icon:</td></tr>
+<tr><td><img id="appIcon" style="width: 50px; height: 50px; vertical-align: top;"></td></tr>
+<tr><tr><td class="label">Author:</td></tr>
+<tr><td><img id="authorPhoto" style="width: 50px; height: 50px; vertical-align: middle;"><input type="text" id="appAuthor" class="readentry" size="30" readonly="readonly" placeholder="Author of the app" style="width: 248px;"/></td></tr>
+<tr><tr><td class="label">Updated:</td></tr>
+<tr><td><input type="text" id="appUpdated" class="readentry" size="30" readonly="readonly" placeholder="App update date" style="width: 300px;"/></td></tr>
+<tr><tr><td class="label">Description:</td></tr>
+<tr><td><textarea id="appDescription" class="readentry" cols="40" rows="3" readonly="readonly" placeholder="No description for this app" style="width: 300px;"></textarea></td></tr>
 <tr><td>
-<input id="deleteAppOKButton" type="submit" class="graybutton bluebutton" style="font-weight: bold;" value="Delete" title="Delete the app"/>
+<input id="deleteAppOKButton" type="submit" class="bluebutton" style="font-weight: bold;" value="Delete" title="Delete the app"/>
 <input id="deleteAppCancelButton" type="button" class="graybutton" value="Cancel"/>
 </td></tr>
 </table>
 </form>
+<br/>
 
 </div>
 
 <script type="text/javascript">
-(function() {
+(function deletebody() {
 
 /**
  * Get the app name.
@@ -51,18 +52,24 @@
 var appname = ui.fragmentParams(location)['app'];
 
 /**
- * Set page titles.
+ * Setup page layout.
  */
-document.title = config.windowtitle() + ' - ' + 'Delete' + ' - ' + appname;
-$('viewhead').innerHTML = '<span class="smenu">Delete ' + appname + '</span>';
+(function layout() {
+    document.title = config.windowtitle() + ' - ' + 'Delete' + ' - ' + appname;
+    $('viewhead').innerHTML = '<span class="smenu">Delete ' + appname + '</span>';
+    if (!ui.isMobile())
+        $('viewform').className = 'viewform flatscrollbars';
+    $('appURL').value = window.location.hostname + '/' + appname + '/';
+})();
 
 /**
  * Set images.
  */
-$('appimg').src = ui.b64img(appcache.get('/public/app.b64'));
+$('appIcon').src = ui.b64png(appcache.get('/public/app.b64'));
+$('authorPhoto').src = ui.b64png(appcache.get('/public/user.b64'));
 
 /**
- * Init service references.
+ * Initialize service references.
  */
 var editorComp = sca.component("Editor");
 var apps = sca.reference(editorComp, "apps");
@@ -73,49 +80,56 @@ var apps = sca.reference(editorComp, "ap
 var appentry;
 
 /**
- * Get and display an app.
+ * Get and display the requested app.
  */
-function getapp(name) {
-    if (isNil(name))
+(function getapp() {
+    if (isNil(appname))
         return false;
-    showStatus('Loading');
+    workingstatus(true);
+    showstatus('Loading');
 
-    return apps.get(name, function(doc) {
+    return apps.get(appname, function(doc) {
 
         // Stop now if we didn't get the app
         if (doc == null) {
-            showError('App not available');
+            errorstatus('Couldn\'t get the app info');
+            workingstatus(false);
             return false;
         }
-        showOnlineStatus();
 
-        appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", name));
-        $('appTitle').value = cadr(assoc("'title", cdr(appentry)));
-        $('appAuthor').innerHTML = cadr(assoc("'author", cdr(appentry)));
-        $('appUpdated').innerHTML = cadr(assoc("'updated", cdr(appentry)));
-        var content = cadr(assoc("'content", cdr(appentry)));
+        appentry = doc != null? car(elementsToValues(atom.readATOMEntry(mklist(doc)))) : mklist("'entry", mklist("'title", ''), mklist("'id", appname));
+        var author = cadr(assoc("'author", appentry));
+        $('appAuthor').value = author.split('@')[0];
+        $('appUpdated').value = xmldatetime(cadr(assoc("'updated", appentry))).toLocaleDateString();
+        var content = cadr(assoc("'content", appentry));
         var description = assoc("'description", content);
         $('appDescription').value = isNil(description) || isNil(cadr(description))? '' : cadr(description);
+
+        onlinestatus();
+        workingstatus(false);
         return true;
     });
-}
+})();
 
 /**
- * Delete an app.
+ * Delete the app.
  */
 $('deleteAppForm').onsubmit = function() {
-    showStatus('Deleting');
+    workingstatus(true);
+    showstatus('Deleting');
 
     // Delete the app
     apps.del(appname, function(e) {
         if (e) {
-            showStatus('Local copy');
+            showstatus('Local copy');
+            workingstatus(false);
             return false;
         }
-        showOnlineStatus();
+        onlinestatus();
+        workingstatus(false);
 
         // Return to the app store
-        ui.navigate('/#view=store', '_view');
+        ui.navigate('/#view=store&category=myapps&idx=5', '_view');
         return false;
     });
     return false;
@@ -128,11 +142,6 @@ $('deleteAppCancelButton').onclick = fun
     history.back();
 };
 
-/**
- * Get the current app.
- */
-getapp(appname);
-
 })();
 </script>
 

Added: tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon-16.xcf
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon-16.xcf?rev=1428193&view=auto
==============================================================================
Files tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon-16.xcf (added) and tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon-16.xcf Thu Jan  3 07:41:53 2013 differ

Added: tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon-32.xcf
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon-32.xcf?rev=1428193&view=auto
==============================================================================
Files tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon-32.xcf (added) and tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon-32.xcf Thu Jan  3 07:41:53 2013 differ

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon.ico
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon.ico?rev=1428193&r1=1428192&r2=1428193&view=diff
==============================================================================
Files tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon.ico (original) and tuscany/sca-cpp/trunk/hosting/server/htdocs/favicon.ico Thu Jan  3 07:41:53 2013 differ

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/graph/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/graph/index.html?rev=1428193&r1=1428192&r2=1428193&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/graph/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/graph/index.html Thu Jan  3 07:41:53 2013
@@ -19,13 +19,13 @@
 -->
 <div id="bodydiv" class="body">
 
-<div id="contentdiv" class="viewcontent" style="width: 2500px;">
-<div id="graphdiv" class="graphdiv" style="top: 0px; left: -2500px; width: 5000px; height: 5000px;"></div>
-<div id="playdiv" style="position: absolute; top: 0x; left: 0px; width: 2500px; height: 5000px; visibility: hidden"></div>
+<div id="viewcontent" class="viewcontent" style="width: 100%;">
+<div id="graphdiv" class="graphcontent" style="top: 0px; left: -2500px; width: 5000px; height: 5000px;"></div>
+<div id="playdiv" style="position: absolute; top: 0x; left: 0px; width: 2500px; height: 5000px; display: none"></div>
 </div>
 
 <script type="text/javascript">
-(function() {
+(function graphbody() {
 
 /**
  * Get the current app name.
@@ -49,11 +49,14 @@ document.title = config.windowtitle() + 
  * Set header div.
  */
 $('viewhead').innerHTML = '<span id="appTitle" class="cmenu">' + appname + '</span>' +
-'<input type="button" id="deleteCompButton" title="Delete a component" class="graybutton redbutton plusminus" style="position: absolute; top: 4px; left: 5px;" disabled="true" value="-"/>' +
-'<span style="position: absolute; top: 0px; left: 45px; right: 115px; padding: 0px; background: transparent;"><input id="compValue" type="text" value="" class="flatentry" title="Component value" autocapitalize="off" placeholder="Value" style="position: absolute; left: 0px; top: 4px; width: 100%; visibility: hidden;" readonly="readonly"/></span>' +
+'<input type="button" id="deleteCompButton" title="Delete a component" class="redbutton plusminus" style="position: absolute; top: 4px; left: 5px;" disabled="true" value="-"/>' +
+'<span style="position: absolute; top: 0px; left: 45px; right: 115px; padding: 0px; background: transparent;"><input id="compValue" type="text" value="" class="flatentry" title="Component value" autocapitalize="off" placeholder="Value" style="position: absolute; left: 0px; top: 4px; width: 100%; display: none;" readonly="readonly"/></span>' +
 '<input type="button" id="playCompButton" title="View component value" class="graybutton plusminus" style="position: absolute; top: 4px; right: 75px;" disabled="true" value="&gt;"/>' +
-'<input type="button" id="copyCompButton" title="Copy a component" class="graybutton bluebutton" style="position: absolute; top: 4px; right: 40px;" disabled="true" value="C"/>' +
-'<input type="button" id="addCompButton" title="Add a component" class="graybutton bluebutton plusminus" style="position: absolute; top: 4px; right: 5px;" disabled="true" value="+"/>';
+'<input type="button" id="copyCompButton" title="Copy a component" class="bluebutton" style="position: absolute; top: 4px; right: 40px;" disabled="true" value="C"/>' +
+'<input type="button" id="addCompButton" title="Add a component" class="bluebutton plusminus" style="position: absolute; top: 4px; right: 5px;" disabled="true" value="+"/>';
+
+if (!ui.isMobile())
+    $('viewcontent').className = 'viewcontent flatscrollbars';
 
 /**
  * Track the current app composite, author, and saved XML content.
@@ -159,8 +162,8 @@ graph.mkedit = function(graphdiv, pos, a
     graph.dragged = false;
     graph.selected = null;
     cvalue.readOnly = true;
-    cvalue.style.visibility = 'hidden';
-    atitle.style.visibility = 'visible';
+    cvalue.style.display = 'none';
+    atitle.style.display = 'block';
     ccopy.disabled = true;
     cdelete.disabled = true;
     cadd.disabled = !editable;
@@ -182,6 +185,54 @@ graph.mkedit = function(graphdiv, pos, a
     }
 
     /**
+     * Render component move animation.
+     */
+    function onmoveanimation() {
+        //debug('onmoveanimation');
+
+        // Stop animation if we're not dragging an element anymore
+        if (graph.dragging == null)
+            return true;
+
+        // Request the next animation frame
+        ui.animation(onmoveanimation);
+
+        // Nothing to do if the selected component has not moved
+        if (graph.moveX == graph.dragX && graph.moveY == graph.dragY)
+            return true;
+
+        // Remember that the selected component has been dragged
+        graph.dragged = true;
+
+        // Cut wire to the dragged component
+        if (graph.dragging.parentNode != graphdiv) {
+            var compos = scdl.composite(graphdiv.compos);
+            setElement(compos, graph.sortcompos(graph.cutwire(graph.dragging, compos, graphdiv)));
+
+            // Bring component to the top
+            graph.bringtotop(graph.dragging, graphdiv);
+        }
+
+        // Calculate new position of the dragged component
+        var gpos = graph.relpos(graph.dragging);
+        var newX = gpos.x + (graph.moveX - graph.dragX);
+        var newY = gpos.y + (graph.moveY - graph.dragY);
+        if (newX >= graph.palcx)
+            graph.dragX = graph.moveX
+        else
+            newX = graph.palcx;
+        if (newY >= 0)
+            graph.dragY = graph.moveY;
+        else
+            newY = 0;
+
+        // Move it
+        graph.move(graph.dragging, graph.mkpath().pos(newX, newY));
+
+        return false;
+    };
+
+    /**
      * Handle a mouse down or touch start event.
      */
     function onmousedown(e) {
@@ -209,6 +260,9 @@ graph.mkedit = function(graphdiv, pos, a
         graph.dragX = pos.screenX;
         graph.dragY = pos.screenY;
 
+        // Start move animation
+        ui.animation(onmoveanimation);
+
         e.preventDefault();
         return true;
     };
@@ -393,69 +447,28 @@ graph.mkedit = function(graphdiv, pos, a
     /**
      * Handle a mouse or touch move event.
      */
-    function onmousemove(e) {
-        if (graph.dragging == null)
-            return true;
-
-        // Ignore duplicate  mouse move events
-        if (graph.moveX == graph.dragX && graph.moveY == graph.dragY)
-            return true;
-
-        // Remember that the component was dragged
-        graph.dragged = true;
-
-        // Cut wire to component
-        if (graph.dragging.parentNode != graphdiv) {
-            var compos = scdl.composite(graphdiv.compos);
-            setElement(compos, graph.sortcompos(graph.cutwire(graph.dragging, compos, graphdiv)));
-
-            // Bring component to the top
-            graph.bringtotop(graph.dragging, graphdiv);
-        }
-
-        // Calculate new position of dragged element
-        var gpos = graph.relpos(graph.dragging);
-        var newX = gpos.x + (graph.moveX - graph.dragX);
-        var newY = gpos.y + (graph.moveY - graph.dragY);
-        if (newX >= graph.palcx)
-            graph.dragX = graph.moveX
-        else
-            newX = graph.palcx;
-        if (newY >= 0)
-            graph.dragY = graph.moveY;
-        else
-            newY = 0;
-
-        // Move the dragged element
-        graph.move(graph.dragging, graph.mkpath().pos(newX, newY));
-
-        return false;
-    };
-
     if (!ui.isMobile()) {
         window.onmousemove = function(e) {
             //debug('onmousemove');
 
-            // Remember mouse position
+            // Record mouse position
             graph.moveX = e.screenX;
             graph.moveY = e.screenY;
-
-            return onmousemove(e);
+            if (graph.dragging == null)
+                return true;
+            return false;
         }
     } else {
         graphdiv.ontouchmove = function(e) {
             //debug('ontouchmove');
             
-            // Remember touch position
+            // Record touch position
             var pos = e.touches[0];
-            if (graph.moveX == pos.screenX && graph.moveY == pos.screenY)
-                return true;
             graph.moveX = pos.screenX;
             graph.moveY = pos.screenY;
-            if (graph.moveX == graph.dragX && graph.moveY == graph.dragY)
+            if (graph.dragging == null)
                 return true;
-
-            return onmousemove(e);
+            return false;
         }
     }
 
@@ -465,7 +478,7 @@ graph.mkedit = function(graphdiv, pos, a
     function onvaluechange() {
         if (graph.selected == null)
             return false;
-        if (graphdiv.parentNode.style.visibility == 'hidden')
+        if (graphdiv.parentNode.style.display == 'none')
             return false;
 
         // Change component name and refactor references to it
@@ -496,8 +509,8 @@ graph.mkedit = function(graphdiv, pos, a
             graph.setproperty(graph.selected.comp, cvalue.value);
             var hasprop = graph.hasproperty(graph.selected.comp);
             cvalue.readOnly = (hasprop? false : true) || !editable;
-            cvalue.style.visibility = hasprop? 'visible' : 'hidden';
-            atitle.style.visibility = hasprop? 'hidden' : 'visible';
+            cvalue.style.display = hasprop? 'block' : 'none';
+            atitle.style.display = hasprop? 'none' : 'block';
             cvalue.value = graph.property(graph.selected.comp);
 
             // Refresh the composite
@@ -597,10 +610,11 @@ graph.mkedit = function(graphdiv, pos, a
         return false;
     };
 
-    // Create a hidden SVG element to help compute the width
-    // of component and reference titles
+    // Create a hidden element to help compute the width of
+    // component and reference titles
     graph.offtitles = document.createElement('span');
     graph.offtitles.style.visibility = 'hidden';
+    graph.offtitles.style.display = 'block';
     graph.offtitles.position = 'absolute';
     graph.offtitles.top = -500;
     graph.offtitles.width = 500;
@@ -792,8 +806,8 @@ graph.compselect = function(g, s, atitle
     if (isNil(g) || !s) {
         cvalue.value = '';
         cvalue.readOnly = true;
-        cvalue.style.visibility = 'hidden';
-        atitle.style.visibility = 'visible';
+        cvalue.style.display = 'none';
+        atitle.style.display = 'block';
         ccopy.disabled = true;
         cdelete.disabled = true;
         if (isNil(g))
@@ -806,8 +820,8 @@ graph.compselect = function(g, s, atitle
 
     cvalue.value = graph.hasproperty(g.comp)? graph.property(g.comp) : g.id;
     cvalue.readOnly = false || !editable;
-    cvalue.style.visibility = 'visible';
-    atitle.style.visibility = 'hidden';
+    cvalue.style.display = 'block';
+    atitle.style.display = 'none';
     ccopy.disabled = false || !editable;
     cdelete.disabled = false || !editable;
 
@@ -1817,13 +1831,15 @@ var bpalette = null;
 function getapp(name, g) {
     if (isNil(name))
         return false;
-    showStatus('Loading');
+    workingstatus(true);
+    showstatus('Loading');
 
     return composites.get(name, function(doc) {
 
         // Stop now if we didn't get a composite
         if (doc == null) {
-            showError('App not available');
+            errorstatus('Couldn\'t get the app info');
+            workingstatus(false);
             return false;
         }
 
@@ -1849,7 +1865,12 @@ function getapp(name, g) {
         author = elementValue(namedElementChild("'author", composentry));
         editable = author == username;
         cadd.disabled = !editable;
-        showStatus(editable? onlineStatus() : 'Read only');
+        if (editable)
+            onlinestatus();
+        else
+            showstatus('Read only');
+        
+        workingstatus(false);
         return true;
     });
 }
@@ -1912,17 +1933,21 @@ function installpalette(name, pos, g, bg
  * Save the current composite.
  */
 function save(savexml) {
-    showStatus('Saving');
+    workingstatus(true);
+    showstatus('Saving');
+
     savedcomposxml = savexml;
     var entry = '<?xml version="1.0" encoding="UTF-8"?>\n' + '<entry xmlns="http://www.w3.org/2005/Atom">' +
         '<title type="text">' + appname + '</title><id>' + appname + '</id><author><email>' + author + '</email></author>' +
         '<content type="application/xml">' + savedcomposxml + '</content></entry>';
     composites.put(appname, entry, function(e) {
         if (e) {
-            showStatus('Local copy');
+            showstatus('Local copy');
+            workingstatus(false);
             return false;
         }
-        showStatus('Saved');
+        showstatus('Saved');
+        workingstatus(false);
         return false;
     });
     return true;
@@ -1938,17 +1963,17 @@ function oncomposchange(prop) {
     var newxml = car(writeXML(composite, false));
     if (savedcomposxml == newxml)
         return false;
-    showStatus('Modified');
+    showstatus('Modified');
 
     // Save property changes right away
     if (prop)
         return save(newxml);
 
     // Autosave other changes after 1 second
-    showStatus('Modified');
-    setTimeout(function() {
+    showstatus('Modified');
+    ui.delay(function autosave() {
         if (savedcomposxml == newxml) {
-            showStatus('Saved');
+            showstatus('Saved');
             return false;
         }
         return save(newxml);
@@ -1997,7 +2022,7 @@ function showdata(gcomp) {
     cplay.value = '<';
     gvisible = false;
     pdiv.innerHTML = '';
-    pdiv.style.visibility = 'visible';
+    pdiv.style.display = 'block';
 
     // Get the component result data
     var comp = sca.component(gcomp.id, appname);
@@ -2030,9 +2055,9 @@ function showdata(gcomp) {
         return displaydata(t, '100%');
     });
 
-    setTimeout(function() {
-        graphdiv.style.visibility = 'hidden'
-    }, 0);
+    ui.async(function hidegraphdiv() {
+        graphdiv.style.display = 'none'
+    });
     return true;
 }
 
@@ -2043,13 +2068,13 @@ function showgraph(gcomp) {
     if (gvisible)
         return true;
     cplay.value = '>';
-    graphdiv.style.visibility = 'visible'
+    graphdiv.style.display = 'block'
     gvisible = true;
     graph.compselect(gcomp, true, atitle, cvalue, ccopy, cdelete);
-    setTimeout(function() {
-        pdiv.style.visibility = 'hidden';
+    ui.async(function hideplaydiv() {
+        pdiv.style.display = 'none';
         pdiv.innerHTML = '';
-    }, 0);
+    });
     return true;
 }
 

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/home/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/home/index.html?rev=1428193&r1=1428192&r2=1428193&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/home/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/home/index.html Thu Jan  3 07:41:53 2013
@@ -19,7 +19,7 @@
 -->
 <div id="bodydiv" class="body">
 
-<div class="viewcontent" style="margin-left: auto; margin-right: auto; text-align: center;">
+<div id="viewcontent" class="viewcontent" style="margin-left: auto; margin-right: auto; text-align: center;">
 
 <br/>
 <div id="hometitle" style="font-size: 28px;"></div>
@@ -29,22 +29,27 @@
 <div id="homeanimation" style="width: 320px; height: 280px; padding: 0px; margin: 0px auto;"></div>
 -->
 
-<input type="button" class="graybutton bluebutton" style="font-size: 21px; padding: 10px; height: 50px;" id="getstarted" title="Get Started" value="Get Started"/>
+<input type="button" class="bluebutton" style="font-size: 21px; padding: 10px; height: 50px;" id="getstarted" title="Get Started" value="Get Started"/>
 
 <br/><br/>
-<div class="note">Requires Safari 5+, Chrome 11+, Firefox 4+, IE 9+</div>
+<div class="note">Requires Safari 5+, Chrome 11+, Firefox 4+ or IE 9+</div>
+<br/>
 
 </div>
 
 <script type="text/javascript">
-(function() {
+(function homebody() {
 
 /**
- * Set page titles.
+ * Setup page layout.
  */
-document.title = config.windowtitle();
-$('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
-$('hometitle').innerHTML = config.hometitle();
+(function layout() {
+    document.title = config.windowtitle();
+    $('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>';
+    $('hometitle').innerHTML = config.hometitle();
+    if (!ui.isMobile())
+        $('viewcontent').className = 'viewcontent flatscrollbars';
+})();
 
 $('getstarted').onclick = function() {
     return ui.navigate('/#view=store', '_view');
@@ -53,22 +58,24 @@ $('getstarted').onclick = function() {
 /**
  * Display animation.
  */
-var anim = $('homeanimation');
-if (!isNil(anim)) {
-    anim.style.background = 'url(\'' + ui.b64img(appcache.get('/home/home.b64')) + '\')';
-    var bgpos = 0;
-    setInterval(function() {
-        bgpos = bgpos -280;
-        if (bgpos == -2800)
-            bgpos = 0;
-        anim.style.backgroundPosition = '0px ' + ui.pixpos(bgpos);
-    }, 2000);
-}
+(function homeanimation() {
+    var anim = $('homeanimation');
+    if (!isNil(anim)) {
+        anim.style.background = 'url(\'' + ui.b64png(appcache.get('/home/home.b64')) + '\')';
+        var bgpos = 0;
+        setInterval(function homeanimation() {
+            bgpos = bgpos -280;
+            if (bgpos == -2800)
+                bgpos = 0;
+            anim.style.backgroundPosition = '0px ' + ui.pixpos(bgpos);
+        }, 2000);
+    }
+})();
 
 /**
  * Show the status.
  */
-showOnlineStatus();
+onlinestatus();
 
 })();
 </script>

Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/index.html?rev=1428193&r1=1428192&r2=1428193&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/index.html Thu Jan  3 07:41:53 2013
@@ -17,50 +17,69 @@
  * specific language governing permissions and limitations
  * under the License.    
 -->
-<html manifest="/cache-manifest.cmf">
+<html>
 <head>
+<!-- Firebug inspector -->
+<!--
+<script type="text/javascript" src="https://getfirebug.com/releases/lite/1.3/firebug-lite.js"></script>
+-->
+<!-- Weinre inspector -->
+<!--
+<script src="http://www.example.com:9998/target/target-script-min.js#anonymous"></script>
+-->
 <title></title>
 <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0"/> 
+<!--
 <meta name="apple-mobile-web-app-capable" content="yes"/>
 <meta name="apple-mobile-web-app-status-bar-style" content="black"/>
-<link rel="apple-touch-icon" href="/public/touchicon.png"/>
+-->
+<link rel="apple-touch-icon-precomposed" href="/public/touchicon.png"/>
 <base href="/"/>
 <script type="text/javascript">
-(function() {
+try {
+
+(function roothead() {
 
 window.appcache = {};
 
 /**
  * Get and cache a resource.
  */
-appcache.get = function(uri) {
+appcache.get = function(uri, mode) {
     var h = uri.indexOf('#');
     var u = h == -1? uri : uri.substring(0, h);
 
     // Get resource from local storage first
     var ls = window.lstorage || localStorage;
-    var item = null;
-    try { item = ls.getItem(u); } catch(e) {}
-    if (item != null && item != '')
-        return item;
+    if (mode != 'remote') {
+        var item = null;
+        try { item = ls.getItem('ui.r.' + u); } catch(e) {}
+        if (item != null && item != '')
+            return item;
+        if (mode == 'local')
+            return null;
+    }
 
     // Get resource from network
     //if (window.debug) debug('appcache.get', u);
     var http = new XMLHttpRequest();
-    http.open("GET", u, false);
+    http.open("GET", mode == 'remote'? (u + '?t=' + new Date().getTime() + '&r=' + Math.random()) : u, false);
     http.setRequestHeader("Accept", "*/*");
     http.send(null);
     if (http.status == 200) {
-        if (http.getResponseHeader("X-Login") != null) {
+        var xl = http.getResponseHeader("X-Login");
+        if (xl != null && xl != '') {
             if (window.debug) debug('http error', u, 'X-Login');
             // Redirect to login page if not signed in
             document.location = '/login/';
             return null;
-        } else if (http.responseText == '' || http.getResponseHeader("Content-Type") == null) {
+        }
+        var ct = http.getResponseHeader("Content-Type");
+        if (http.responseText == '' || ct == null || ct == '') {
             if (window.debug) debug('http error', u, 'No-Content');
             return null;
         }
-        try { ls.setItem(u, http.responseText); } catch(e) {}
+        try { ls.setItem('ui.r.' + u, http.responseText); } catch(e) {}
         return http.responseText;
     }
     if (window.debug) debug('http error', u, http.status, http.statusText);
@@ -83,82 +102,68 @@ appcache.remove = function(uri) {
 /**
  * Load Javascript and CSS.
  */
-(function() {
+(function rootboot() {
 
-var bootjs = document.createElement('script');
-bootjs.type = 'text/javascript';
-bootjs.text = appcache.get('/all-min.js');
-document.head.appendChild(bootjs);
-document.head.appendChild(ui.declareCSS(appcache.get('/ui-min.css')));
+window.eval.call(window, 'try {\n' + appcache.get('/all-min.js') + '\n' + appcache.get('/config-min.js') + '\n} catch(e) { console.log(e.stack); throw e; }\n');
+ui.includeCSS(appcache.get('/ui-min.css'));
 
 // Disable cache for testing
 //lstorage.enabled = false;
 
 })();
 
-/**
- * Redirect to login page if not signed in.
- */
-(function() {
-
-if (document.location.protocol == 'https:' && !hasauthcookie())
-    document.location = '/login/';
-
-})();
+} catch(e) {
+    if (window.debug) debug(e.stack);
+    throw e;
+}
 </script>
 </head>
 <body class="delayed">
-<div id="mainbodydiv" class="mainbody">
 
-<div id="headdiv" class="hsection">
-<script type="text/javascript">
-(function() {
-
-$('headdiv').appendChild(ui.declareScript(appcache.get('/config-min.js')));
-
-})();
-</script>
+<div id="menucontainer" class="tbarmenu">
+<div id="menu"></div>
 </div>
 
-<div id="menubackground" class="tbarbackground fixed"></div>
-<div id="menu" class="tbarmenu fixed"></div>
+<div id="viewheadcontainer" class="viewhead">
+<div id="viewhead"></div>
+</div>
 
-<div id="viewheadbackground" class="viewheadbackground fixed"></div>
-<div id="viewhead" class="viewhead fixed"></div>
+<div id="working" class="working" style="display: none;"></div>
 
 <div id="viewcontainer"></div>
 
-<div id="viewfootbackground" class="viewfootbackground fixed"></div>
-<div id="viewfoot" class="viewfoot fixed"></div>
-<div id="status" class="status fixed" style="visibility: hidden;"></div>
+<div id="viewfootcontainer" class="viewfoot">
+<div id="viewfoot"></div>
+<div id="status"></div>
+</div>
+
+<div id="installer" class="installer"></div>
 
 <script type="text/javascript">
-(function() {
+try {
 
-/**
- * Init service references.
- */
-var editorComp = sca.component("Editor");
-var user= sca.defun(sca.reference(editorComp, "user"));
-var accounts = sca.reference(editorComp, "accounts");
+(function rootbody() {
 
 /**
- * Set page title.
+ * Setup page layout.
  */
-document.title = config.windowtitle();
+(function layout() {
+
+    document.title = config.windowtitle();
+    $('viewcontainer').className = ui.isMobile()? 'viewcontainer3dm' : 'viewcontainer3d';
+    $('status').className = ui.isMobile()? 'status3dm' : 'status3d';
+
+})();
 
 /**
- * Init div variables.
+ * Initialize service references.
  */
-var bdiv = $('mainbodydiv');
-var mdiv = $('menu'); 
-var hdiv = $('viewhead'); 
-var vcontainer = $('viewcontainer');
-vcontainer.className = ui.isMobile()? 'viewcontainer3dm' : 'viewcontainer3d';
-var fdiv = $('viewfoot'); 
+var editorComp = sca.component("Editor");
+var user = sca.defun(sca.reference(editorComp, "user"));
+var accounts = sca.reference(editorComp, "accounts");
 
 /**
- * The current user name and account entry.
+ * The current user name.
  */
 window.username = 'anonymous';
 
@@ -169,134 +174,95 @@ var storecat = 'top';
 var storeidx = 0;
 
 /**
- * Pre-fetch app resources.
+ * Populate cache with app resources.
  */
 var appresources = [
     ['/all-min.js'],
     ['/ui-min.css'],
     ['/account/', 9],
-    ['/clone/', 3],
-    ['/create/', 2],
-    ['/delete/', 3],
+    ['/clone/', 4],
+    ['/create/', 3],
+    ['/delete/', 4],
     ['/graph/', 5],
     ['/config-min.js'],
     ['/home/', 0],
-    ['/home/home.b64'],
     ['/page/', 4],
     ['/public/app.b64'],
     ['/public/config-min.js'],
-    ['/public/grid72.b64'],
-    ['/public/iframe-min.html'],
     ['/public/img.b64'],
+    ['/public/rate.b64'],
+    ['/public/ratings.b64'],
     ['/public/user.b64'],
-    ['/stats/', 2],
+    ['/rate/', 4],
+    ['/search/', 2],
+    ['/info/', 3],
     ['/store/', 1]
 ];
 
 /**
- * Show a status message.
+ * Init status message area.
  */
-window.showStatus = function(s, c) {
-    //debug('status', s);
-    var sdiv = $('status');
-    if (isNil(sdiv))
-        return s;
-    sdiv.innerHTML = '<span class="' + (c? c : 'okstatus') + '">' + s + '</span>';
-    sdiv.className = 'status fixed';
-    sdiv.style.visibility = 'visible';
+(function initstatus() {
+    if (isNil($('status')))
+        return;
+    $('status').style.display = 'none';
     
     function divtransitionend(e) {
-        e.target.style.visibility = 'hidden';
-        e.target.className = 'status fixed';
+        e.target.style.display = 'none';
+        e.target.className = ui.isMobile()? 'status3dm' : 'status3d';
+        e.target.error = false;
     }
-    if (!sdiv.addedTransitionEnd) {
-        sdiv.addEventListener('webkitTransitionEnd', divtransitionend, false);
-        sdiv.addEventListener('transitionend', divtransitionend, false);
-        sdiv.addedTransitionEnd = true;
-    }
-    sdiv.className = 'statusout3 fixed';
-    return s;
-}
+    $('status').addEventListener('webkitTransitionEnd', divtransitionend, false);
+    $('status').addEventListener('transitionend', divtransitionend, false);
+})();
 
 /**
- * Show an error message.
+ * Show a status message.
  */
-window.showError = function(s) {
-    //debug('error', s);
-    return showStatus(s, 'errorstatus');
-}
+window.showstatus = function(s, c) {
+    //debug('show status', s);
+    if (isNil($('status')) || $('status').error)
+        return s;
+    $('status').innerHTML = '<span class="' + (c? c : 'okstatus') + '">' + s + '</span>';
+    $('status').className = ui.isMobile()? 'status3dm' : 'status3d';
+    $('status').style.display = 'block';
+    $('status').error = c == 'errorstatus';
+    if ($('status').delay)
+        ui.cancelDelay($('status').delay);
+    $('status').delay = ui.delay(function hidestatus() {
+        $('status').className = ui.isMobile()? 'statusout3dm' : 'statusout3d';
+        $('status').error = false;
+    }, 3000);
+    return s;
+};
 
 /**
- * Show the online/offline status.
+ * Show an error message.
  */
-window.showOnlineStatus = function() {
-    return navigator.onLine? showStatus('Online') : showError('Offline');
-}
+window.errorstatus = function(s) {
+    //debug('error', s);
+    return showstatus(s, 'errorstatus');
+};
 
 /**
- * Handle application cache events.
+ * Show working status.
  */
-applicationCache.addEventListener('checking', function(e) {
-    //debug('appcache checking', e);
-    showStatus('Checking');
-}, false);
-applicationCache.addEventListener('error', function(e) {
-    //debug('appcache error', e);
-    showOnlineStatus();
-}, false);
-applicationCache.addEventListener('noupdate', function(e) {
-    //debug('appcache noupdate', e);
-    showOnlineStatus();
-}, false);
-applicationCache.addEventListener('downloading', function(e) {
-    //debug('appcache downloading', e);
-    showStatus('Updating');
-}, false);
-applicationCache.addEventListener('progress', function(e) {
-    //debug('appcache progress', e);
-    showStatus('Updating');
-}, false);
-applicationCache.addEventListener('updateready', function(e) {
-    //debug('appcache updateready', e);
-    try {
-        applicationCache.swapCache();
-    } catch(e) {}
-    showOnlineStatus();
-    //debug('appcache swapped', e);
-
-    // Update offline resources in local storage and reload the page
-    map(function(res) {
-        showStatus('Updating');
-        appcache.remove(res[0]);
-        appcache.get(res[0]);
-    }, append(appresources, config.appresources()));
-    window.location.reload();
-}, false);
-applicationCache.addEventListener('cached', function(e) {
-    //debug('appcache cached', e);
-    showOnlineStatus();
-
-    // Install offline resources in local storage
-    map(function(res) {
-        showStatus('Installing');
-        appcache.remove(res[0]);
-        appcache.get(res[0]);
-    }, append(appresources, config.appresources()));
-}, false);
+window.workingstatus = function(w, c) {
+    //debug('show working', w);
+    if (isNil($('working')))
+        return w;
+    if (!ui.isMobile())
+        $('working').style.top = ui.pixpos(Math.round(window.clientHeight / 2));
+    $('working').style.display = w? 'block' : 'none';
+    return w;
+};
 
 /**
- * Handle network offline/online events.
+ * Show the online/offline status.
  */
-window.addEventListener('offline', function(e) {
-    //debug('going offline');
-    showStatus('Offline');
-}, false);
-window.addEventListener('online', function(e) {
-    //debug('going online');
-    showStatus('Online');
-}, false);
-
-//debug(navigator.onLine? 'online' : 'offline');
+window.onlinestatus = function() {
+    return navigator.onLine? (ui.isMobile()? showstatus('Online') : showstatus('Online')) : errorstatus('Offline');
+};
 
 /**
  * Handle view transitions.
@@ -351,32 +317,36 @@ function mkviewdiv(cname) {
  * Return the last visited location.
  */
 function lastvisited() {
-    if (username != lstorage.getItem('ui.lastvisit.user'))
+    if (username != lstorage.getItem('ui.v.user'))
         return null;
-    return lstorage.getItem('ui.lastvisit.url');
+    return lstorage.getItem('ui.v.url');
 }
 
 /**
  * Build and show the menu bar.
  */
-function showmenu(mdiv, view, appname) {
-    mdiv.innerHTML = ui.menubar(
+function showmenu(view, appname) {
+     $('menu').innerHTML = ui.menubar(
         append(mklist(ui.menu('menuhome', 'Home', '/', '_view', view == 'home'),
-                    ui.menu('menustore', 'Store', '/#view=store&category=' + storecat + '&idx=' + storeidx, '_view', view === 'store')),
+                    ui.menu('menustore', 'Store', '/#view=store&category=' + storecat + '&idx=' + storeidx, '_view', view == 'store'),
+                    ui.menu('menusearch', 'Search', '/#view=search', '_view', view == 'search')),
                 (isNil(appname) || appname == 'undefined')?
                     mklist() :
                     mklist(
-                        ui.menu('menustats', 'Stats', '/#view=stats&app=' + appname, '_view', view == 'stats'),
-                        ui.menu('menupage', 'Page', '/#view=page&app=' + appname, '_view', view == 'page'),
+                        ui.menu('menuinfo', 'Info', '/#view=info&app=' + appname, '_view', view == 'info'),
+                        ui.menu('menupage', 'Edit', '/#view=page&app=' + appname, '_view', view == 'page')
+                        /* TODO disabled for now
+                        ,
                         ui.menu('menulogic', config.logic(), '/#view=graph&app=' + appname, '_view', view == 'graph'),
-                        ui.menu('menurun', '<span class="greentext" style="font-weight: bold">Run!</span>', '/' + appname + '/', '_blank', false))),
+                        ui.menu('menurun', '<span class="greentext" style="font-weight: bold">Run!</span>', '/' + appname + '/', '_blank', false)
+                        */
+                        )),
         (isNil(appname) || appname == 'undefined')? mklist(
-            hasauthcookie()? ui.menufunc('menusignout', 'Sign out', 'return logout();', false) : ui.menu('menusignin', 'Sign in', '/login/', '_self', false),
+            ui.menufunc('menusignout', 'Sign out', 'return logout();', false),
             ui.menu('menuaccount', 'Account', '/#view=account', '_view', view == 'account')) :
             mklist());
 
-    if (fdiv.innerHTML == '') 
-        fdiv.innerHTML = config.viewfoot();
+    $('viewfoot').innerHTML = config.viewfoot();
 }
 
 /**
@@ -390,7 +360,7 @@ function getaccount() {
         return false;
 
     var accountentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
-    username = cadr(assoc("'id", cdr(accountentry)));
+    username = cadr(assoc("'id", accountentry));
     return true;
 }
 
@@ -401,8 +371,8 @@ function showview(url) {
     //debug('showview', url);
 
     // Save last visited location
-    lstorage.setItem('ui.lastvisit.user', username);
-    lstorage.setItem('ui.lastvisit.url', url);
+    lstorage.setItem('ui.v.user', username);
+    lstorage.setItem('ui.v.url', url);
 
     // Determine the view to show
     var params = ui.fragmentParams(url);
@@ -426,10 +396,11 @@ function showview(url) {
 
     // Show the menu bar
     var appname = params['app'];
-    showmenu(mdiv, view, appname);
+    showmenu(view, appname);
 
-    // Scroll to the top and hide the address bar
-    window.scrollTo(0, 0);
+    // Make sure that the document is visible
+    if (document.body.style.display != 'block')
+        document.body.style.display = 'block';
 
     // Start to unload the front view and create a new view
     if (ui.isMobile()) {
@@ -444,21 +415,17 @@ function showview(url) {
         var vdiv = mkviewdiv(vtransition + 'viewloading3dm');
         var vdoc = appcache.get(uri);
         vdiv.innerHTML = vdoc;
-        vcontainer.appendChild(vdiv);
+        $('viewcontainer').appendChild(vdiv);
         map(ui.evalScript, ui.innerScripts(vdiv));
 
-        // Make sure the top document is visible
-        if (document.body.style.visibility != 'visible')
-            document.body.style.visibility = 'visible';
-
-        setTimeout(function() {
+        ui.async(function mtransitionview() {
             // Transition the old view out
             if (!isNil(ovdiv))
                 ovdiv.className = vtransition + 'viewunloaded3dm';
 
             // Transition the new view in
             vdiv.className = 'viewloaded3dm';
-        }, 100);
+        });
 
     } else {
         // Prepare current view for transition out
@@ -470,21 +437,17 @@ function showview(url) {
         var vdiv = mkviewdiv('viewloading3d');
         var vdoc = appcache.get(uri);
         vdiv.innerHTML = vdoc;
-        vcontainer.appendChild(vdiv);
+        $('viewcontainer').appendChild(vdiv);
         map(ui.evalScript, ui.innerScripts(vdiv));
 
-        // Make sure the top document is visible
-        if (document.body.style.visibility != 'visible')
-            document.body.style.visibility = 'visible';
-
-        setTimeout(function() {
+        ui.async(function transitionview() {
             // Transition the new view in
             vdiv.className = 'viewloaded3d';
 
             // Transition the old view out
             if (!isNil(ovdiv))
                 ovdiv.parentNode.removeChild(ovdiv);
-        }, 100);
+        });
     }
 
     // Track the current visible view
@@ -501,12 +464,14 @@ function updatelocation(url) {
 
     // Add url to the history if necessary
     if (url != ui.pathandparams(location)) {
-        history.pushState(null, null, url);
-        //debug('pushstate', history.length);
+        if (history.pushState) {
+            history.pushState(null, null, url);
+            //debug('pushstate', history.length);
+        }
 
         // Update the location hash if necessary
         var f = ui.fragment(url);
-        if (f != '' && f != location.hash) {
+        if (f != location.hash) {
             location.hash = f;
             //debug('hash', f);
         }
@@ -520,6 +485,10 @@ function updatelocation(url) {
 window.onnavigate = function(url) {
     //debug('onnavigate', url);
 
+    // Cleanup installer
+    if ($('installer').innerHTML != '')
+        $('installer').innerHTML = '';
+
     // Update the browser window location
     updatelocation(url);
 
@@ -541,12 +510,11 @@ window.onloginredirect = function(e) {
  */
 window.logout = function() {
     // Clear session cookie and user-specific local storage entries
-    clearauthcookie();
     lstorage.removeItem('/r/Editor/accounts');
     lstorage.removeItem('/r/Editor/dashboards');
-    document.location = '/login/';
+    document.location = '/logout/dologout/';
     return false;
-}
+};
 
 /**
  * Handle history.
@@ -555,10 +523,13 @@ window.addEventListener('popstate', func
     //debug('onpopstate', history.length);
     var furl = ui.fragment(location);
     var url = location.pathname + (furl == ''? '' : '#' + furl);
-
-    // Show the current view
     if (url == viewurl)
         return true;
+
+    // Cleanup element lookups memoized in current document
+    ui.unmemo$();
+
+    // Show the current view
     return showview(url);
 
 }, false);
@@ -567,10 +538,13 @@ window.addEventListener('hashchange', fu
     //debug('onhashchange');
     var furl = ui.fragment(location);
     var url = location.pathname + (furl == ''? '' : '#' + furl);
-
-    // Show the current view
     if (url == viewurl)
         return true;
+
+    // Cleanup element lookups memoized in current document
+    ui.unmemo$();
+
+    // Show the current view
     return showview(url);
 
 }, false);
@@ -580,18 +554,128 @@ window.addEventListener('hashchange', fu
  */
 document.body.onorientationchange = function(e) {
     //debug('onorientationchange');
-    ui.onorientationchange(e);
-
-    // Resize menu and view header
-    mdiv.style.width = ui.pixpos(document.documentElement.clientWidth);
-    hdiv.style.width = ui.pixpos(document.documentElement.clientWidth);
-    return true;
+    return ui.onorientationchange(e);
 };
 
 /**
+ * Install the application cache.
+ */
+(function installappcache() {
+    if (ui.isMobile()) {
+        // On mobile devices, trigger usage of an application cache manifest
+        window.onappcachechecking = function(e) {
+            //debug('appcache checking', e);
+            workingstatus(true);
+            showstatus('Checking');
+        };
+        window.onappcacheerror = function(e) {
+            //debug('appcache error', e);
+            onlinestatus();
+            workingstatus(false);
+        };
+        window.onappcachenoupdate = function(e) {
+            //debug('appcache noupdate', e);
+            onlinestatus();
+            workingstatus(false);
+        };
+        window.onappcachedownloading = function(e) {
+            //debug('appcache downloading', e);
+            workingstatus(true);
+            showstatus('Updating');
+        };
+        window.onappcacheprogress = function(e) {
+            //debug('appcache progress', e);
+            workingstatus(true);
+            showstatus('Updating');
+        };
+        window.onappcacheupdateready = function(e) {
+            //debug('appcache updateready', e);
+            try {
+                applicationCache.swapCache();
+            } catch(e) {}
+            onlinestatus();
+            workingstatus(false);
+            //debug('appcache swapped', e);
+
+            // Update offline resources in local storage and reload the page
+            map(function(res) {
+                showstatus('Updating');
+                appcache.remove(res[0]);
+                appcache.get(res[0], 'remote');
+            }, append(appresources, config.appresources()));
+            window.location.reload();
+        };
+        window.onappcachecached = function(e) {
+            //debug('appcache cached', e);
+            onlinestatus();
+            workingstatus(false);
+
+            // Install offline resources in local storage
+            map(function(res) {
+                showstatus('Installing');
+                appcache.remove(res[0]);
+                appcache.get(res[0], 'remote');
+            }, append(appresources, config.appresources()));
+        };
+
+        window.onloadappcache = function() {
+            //debug('appcache iframe loaded');
+        };
+
+        ui.delay(function() {
+            $('installer').innerHTML = '<iframe src="/cache/" class="installer"></iframe>';
+        });
+
+    } else {
+        // On non-mobile devices, check for cache-manifest changes ourselves.
+        workingstatus(true);
+        showstatus('Checking');
+        var lcmf = appcache.get('/cache/cache-manifest.cmf', 'local');
+        var rcmf = appcache.get('/cache/cache-manifest.cmf', 'remote');
+        if (lcmf == rcmf) {
+            onlinestatus();
+            workingstatus(false);
+            return true;
+        }
+
+        //debug('cache-manifest changed, reloading');
+        ui.delay(function() {
+            workingstatus(true);
+            showstatus('Updating');
+            ui.delay(function() {
+                workingstatus(true);
+                showstatus('Updating');
+                map(function(res) {
+                    appcache.remove(res[0]);
+                    appcache.get(res[0], 'remote');
+                }, append(appresources, config.appresources()));
+                if (!isNil(lcmf)) {
+                    //debug('reloading');
+                    window.location.reload();
+                }
+                onlinestatus();
+                workingstatus(false);
+            });
+        });
+    }
+})();
+
+/**
+ * Handle network offline/online events.
+ */
+window.addEventListener('offline', function(e) {
+    //debug('going offline');
+    showstatus('Offline');
+}, false);
+window.addEventListener('online', function(e) {
+    //debug('going online');
+    showstatus('Online');
+}, false);
+
+/**
  * Initialize the document.
  */
-function onload() {
+window.onload = function() {
     //debug('onload', history.length);
     ui.onload();
 
@@ -625,16 +709,15 @@ function onload() {
     if (url == viewurl)
         return true;
     return showview(url);
-}
-
-onload();
+};
 
 })();
-</script>
 
-<div id="footdiv" class="fsection">
-</div>
+} catch(e) {
+    debug(e.stack);
+    throw e;
+}
+</script>
 
-</div>
 </body>
 </html>

Added: tuscany/sca-cpp/trunk/hosting/server/htdocs/info/index.html
URL: http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/info/index.html?rev=1428193&view=auto
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/info/index.html (added)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/info/index.html Thu Jan  3 07:41:53 2013
@@ -0,0 +1,494 @@
+<!DOCTYPE html>
+<!--
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ * 
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.    
+-->
+<div id="bodydiv" class="body">
+
+<div id="viewform" class="viewform">
+
+<form id="appForm">
+<table style="width: 100%;">
+<tr><td class="label">URL:</td></tr>
+<tr><td><input type="text" id="appURL" class="readentry" size="30" readonly="readonly" placeholder="App URL" style="width: 300px;"/></td></tr>
+<tr><td class="label">Icon:</td></tr>
+<tr><td><img id="appIcon" style="width: 50px; height: 50px; vertical-align: top;"/><input id="uploadIcon" type="button" class="lightbutton" value="Upload" style="display:none;"/><input id="uploadFile" type="file" accept="image/*" style="display: none;"/><span id="refreshingIcon" class="refreshing" style="display:none;"/></td></tr>
+<tr><td class="label">Author:</td></tr>
+<tr><td><img id="authorPicture" style="width: 50px; height: 50px; vertical-align: middle;"/><input type="text" id="appAuthor" class="readentry" size="30" readonly="readonly" placeholder="Author of the app" style="width: 248px;"/></td></tr>
+<tr><td class="label">Rating:</td></tr>
+<tr><td><span id="appRating" class="ratings">&nbsp;</span><input id="rateApp" type="button" class="lightbutton" value="Rate this app"/></td></tr>
+<tr><td><input type="text" id="appRatings" class="readentry" size="20" readonly="readonly" placeholder="Number of ratings" style="font-size: 12px;"/></td></tr>
+<tr><td class="label">Updated:</td></tr>
+<tr><td><input type="text" id="appUpdated" class="readentry" size="30" readonly="readonly" placeholder="App update date" style="width: 300px;"/></td></tr>
+<tr><td class="label">Description:</td></tr>
+<tr><td><textarea id="appDescription" class="readentry" cols="40" rows="3" readonly="readonly" placeholder="Short description of the app" style="width: 300px;"></textarea></td></tr>
+</table>
+</form>
+<br/>
+
+</div>
+
+<script type="text/javascript">
+(function infobody() {
+
+/**
+ * Get the app name.
+ */
+var appname = ui.fragmentParams(location)['app'];
+
+/**
+ * Setup page layout.
+ */
+(function layout() {
+    document.title = config.windowtitle() + ' - Info - ' + appname;
+    $('viewhead').innerHTML = '<span id="appname" class="cmenu">' + appname + '</span>' +
+        '<input type="button" class="redbutton plusminus" style="position: absolute; top: 4px; left: 5px;" id="deleteApp" value="-" title="Delete this app" disabled="true"/>' +
+        '<span style="position: absolute; top: 0px; right: 5px;">' +
+        '<input type="button" class="greenbutton" id="runApp" value="Run" title="Run this app"/>' +
+        '<input type="button" class="bluebutton" id="cloneApp" value="'+ config.clone() +'" title="' + config.clone() + ' this app"/>' +
+        '</span>';
+    if (!ui.isMobile())
+        $('viewform').className = 'viewform flatscrollbars';
+    $('appURL').value = window.location.hostname + '/' + appname + '/';
+
+    $('viewform').appendChild(ui.declareCSS(
+        '.ratings { ' +
+        'background: url(\'' + ui.b64png(appcache.get('/public/ratings.b64')) + '\'); ' +
+        'vertical-align: middle; width: 50px; height: 14px; display: inline-block; ' +
+        ' }'));
+})();
+
+/**
+ * Set images.
+ */
+(function drawImages() {
+    $('appIcon').src = ui.b64png(appcache.get('/public/app.b64'));
+    $('authorPicture').src = ui.b64png(appcache.get('/public/user.b64'));
+})();
+
+/**
+ * Initialize service references.
+ */
+var editorComp = sca.component("Editor");
+var apps = sca.reference(editorComp, "apps");
+var icons = sca.reference(editorComp, "icons");
+var pictures = sca.reference(editorComp, "pictures");
+var ratings = sca.reference(editorComp, "ratings");
+
+/**
+ * The current app entry, author and saved XML content.
+ */
+var savedappxml = '';
+var author;
+var savediconxml;
+
+/**
+ * Get and display the requested app.
+ */
+(function getapp() {
+    if (isNil(appname))
+        return false;
+    workingstatus(true);
+    showstatus('Loading');
+
+    return apps.get(appname, function(doc) {
+
+        // Stop now if we didn't get the app
+        if (doc == null) {
+            errorstatus('Couldn\'t get the app info');
+            workingstatus(false);
+            return false;
+        }
+
+        var appentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
+        author = cadr(assoc("'author", appentry));
+        $('appAuthor').value = author.split('@')[0];
+        var updated = assoc("'updated", appentry);
+        $('appUpdated').value = isNil(updated)? '' : xmldatetime(cadr(updated)).toLocaleDateString();
+        var content = cadr(assoc("'content", appentry));
+        var description = assoc("'description", content);
+        $('appDescription').value = isNil(description) || isNil(cadr(description))? '' : cadr(description);
+        //var ratingy = -20 * (4 - Math.floor(Math.random() * 4));
+        //$('appRating').style.backgroundPosition = '0px ' + ratingy + 'px';
+        //$('appRatings').value = '';
+        savedappxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
+
+        // Enable author to edit and delete the app
+        if (username == author) {
+            $('appDescription').readOnly = false;
+            $('appDescription').className = 'flatentry';
+            $('uploadIcon').style.display = 'inline';
+            $('deleteApp').disabled = false;
+            $('deleteApp').onclick = function() {
+                return ui.navigate('/#view=delete&app=' + appname, '_view');
+            }
+            onlinestatus();
+        } else {
+            showstatus('Read only');
+        }
+        workingstatus(false);
+        return true;
+    });
+})();
+
+/**
+ * Get and display the author's picture.
+ */
+(function getpic(author) {
+    workingstatus(true);
+    showstatus('Loading');
+
+    return pictures.get(author, function(doc) {
+
+        // Stop now if we didn't get a picture
+        if (doc == null) {
+            errorstatus('Author picture not available');
+            workingstatus(false);
+            return false;
+        }
+
+        var picentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
+        var content = assoc("'content", picentry);
+        var picture = assoc("'picture", content);
+        var img = assoc("'image", picture);
+        if (!isNil(img))
+            $('authorPicture').src = cadr(img);
+
+        onlinestatus();
+        workingstatus(false);
+        return true;
+    });
+    return true;
+})();
+
+/**
+ * Get and display the app icon.
+ */
+(function geticon() {
+    if (isNil(appname))
+        return false;
+    workingstatus(true);
+    showstatus('Loading');
+
+    return icons.get(appname, function(doc) {
+        // Stop now if we didn't get an icon
+        if (doc == null) {
+            errorstatus('Icon not available');
+            workingstatus(false);
+            return false;
+        }
+
+        var iconentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
+        savediconxml = car(atom.writeATOMEntry(valuesToElements(mklist(iconentry))));
+        var content = assoc("'content", iconentry);
+        var icon = assoc("'icon", content);
+        var img = assoc("'image", icon);
+        if (!isNil(img))
+            $('appIcon').src = cadr(img);
+
+        onlinestatus();
+        workingstatus(false);
+        return true;
+    });
+    return true;
+})();
+
+/**
+ * Refresh icon.
+ */
+var refreshingicon = false;
+function refreshicon() {
+    if (isNil(appname))
+        return false;
+    if (!refreshingicon)
+        return false;
+    $('refreshingIcon').style.display = 'inline-block';
+    return icons.get(appname, function(doc) {
+        if (doc == null) {
+            errorstatus('Icon not available');
+            $('refreshingIcon').style.display = 'none';
+            refreshingicon = false;
+            return false;
+        }
+
+        var iconentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
+        var content = assoc("'content", iconentry);
+        var icon = assoc("'icon", content);
+        var token = assoc("'token", icon);
+
+        // Update icon
+        if (isNil(token)) {
+            var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(iconentry))));
+            savediconxml = entryxml;
+            var img = assoc("'image", icon);
+            if (!isNil(img))
+                $('appIcon').src = cadr(img);
+            $('refreshingIcon').style.display = 'none';
+            refreshingicon = false;
+            return true;
+        }
+
+        // Refresh in 2 secs
+        return ui.delay(refreshicon, 2000);
+    }, 'remote');
+    return true;
+}
+
+/**
+ * Get and display the app ratings.
+ */
+(function getratings() {
+    if (isNil(appname))
+        return false;
+    workingstatus(true);
+    showstatus('Loading');
+
+    return ratings.get(appname, function(doc) {
+        // Stop now if we didn't get an icon
+        if (doc == null) {
+            errorstatus('Ratings not available');
+            workingstatus(false);
+            return false;
+        }
+
+        var ratingsentry = car(elementsToValues(atom.readATOMEntry(mklist(doc))));
+        var aratings = assoc("'ratings", assoc("'content", ratingsentry));
+        var ar = assoc("'rating", aratings);
+        var ar1 = assoc("'rating1", aratings);
+        var ar2 = assoc("'rating2", aratings);
+        var ar3 = assoc("'rating3", aratings);
+        var ar4 = assoc("'rating4", aratings);
+        var rating = isNil(ar)? 0 : Number(cadr(ar));
+        var reviews = (isNil(ar1)? 0 : Number(cadr(ar1))) + (isNil(ar2)? 0 : Number(cadr(ar2))) + (isNil(ar3)? 0 : Number(cadr(ar3))) + (isNil(ar4)? 0 : Number(cadr(ar4)));
+
+        var ratingy = -20 * (4 - Math.floor(rating));
+        $('appRating').style.backgroundPosition = '0px ' + ratingy + 'px';
+        $('appRatings').value = reviews + (reviews > 1? ' ratings' : ' rating');
+
+        onlinestatus();
+        workingstatus(false);
+        return true;
+    });
+    return true;
+})();
+
+/**
+ * Save the current app.
+ */
+function saveapp(entryxml) {
+    workingstatus(true);
+    showstatus('Saving');
+    savedappxml = entryxml;
+    apps.put(appname, savedappxml, function(e) {
+        if (e) {
+            showstatus('Local copy');
+            workingstatus(false);
+            return false;
+        }
+
+        showstatus('Saved');
+        workingstatus(false);
+        return false;
+    });
+    return true;
+}
+
+/**
+ * Save the app icon.
+ */
+function saveicon(entryxml) {
+    workingstatus(true);
+    showstatus('Uploading');
+    savedappxml = entryxml;
+    icons.put(appname, savedappxml, function(e) {
+        if (e) {
+            showstatus('Local copy');
+            workingstatus(false);
+            return false;
+        }
+
+        showstatus('Uploaded');
+        workingstatus(false);
+        return true;
+    });
+    return true;
+}
+
+/**
+ * Handle a change event
+ */
+function onappchange() {
+    if (username != author)
+        return false;
+
+    // Validate user input
+    var description = $('appDescription').value;
+    if (description.length > 120) {
+        errorstatus('Description cannot be longer than 120 characters');
+        return false;
+    }
+
+    // Save the changes
+    var appentry = mklist("'entry", mklist("'title", appname), mklist("'id", appname), mklist("'content", mklist("'info", mklist("'description", description))));
+    var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(appentry))));
+    if (savedappxml == entryxml)
+        return false;
+    showstatus('Modified');
+    return saveapp(entryxml);
+}
+
+$('appDescription').onchange = onappchange;
+
+/**
+ * Handle a key event.
+ */
+var lastkeyup = null;
+$('appDescription').onkeyup = function() {
+    var t = new Date().getTime();
+    lastkeyup = t;
+    ui.delay(function() {
+            return t == lastkeyup? onappchange() : true;
+        }, 2000);
+};
+
+/**
+ * Handle a form submit event.
+ */
+$('appForm').onsubmit = function() {
+    onappchange();
+    return false;
+};
+
+/**
+ * Handle Clone button event.
+ */
+$('cloneApp').onclick = function() {
+    return ui.navigate('/#view=clone&app=' + appname, '_view');
+};
+
+/**
+ * Handle Run button event.
+ */
+$('runApp').onclick = function() {
+    return ui.navigate('/' + appname + '/', '_blank');
+};
+
+/**
+ * Read and upload icon file.
+ */
+function uploadicon(files) {
+    if (username != author)
+        return false;
+    if (!files || files.length == 0)
+        return false;
+    if (!files[0].type.match('image.*')) {
+        errorstatus('Please select an image');
+        return false;
+    }
+    workingstatus(true);
+    showstatus('Loading');
+
+    // Read the selected file into a 50x50 image
+    return ui.readimage(files[0],
+        function(e) {
+            errorstatus('Couldn\'t read the file');
+            workingstatus(false);
+        },
+        function(p) {
+            showstatus('Loading ' + p + '%');
+        },
+        function(url) {
+            // Update the app icon
+            $('appIcon').src = url;
+            showstatus('Loaded');
+
+            // Now upload it
+            ui.delay(function() {
+                var iconentry = mklist("'entry", mklist("'title", appname), mklist("'id", appname), mklist("'author", username), mklist("'content", mklist("'icon", mklist("'image", url))));
+                var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(iconentry))));
+                if (savediconxml == entryxml) {
+                    onlinestatus();
+                    workingstatus(false);
+                    return false;
+                }
+                return saveicon(entryxml);
+            });
+        }, 50, 50);
+}
+
+/**
+ * Upload an icon in an email.
+ */
+function emailicon() {
+
+    // Generate and put an icon email upload token
+    workingstatus(true);
+    showstatus('Uploading');
+    var token = uuid4();
+    var iconentry = mklist("'entry", mklist("'title", appname), mklist("'id", appname), mklist("'author", username), mklist("'content", mklist("'icon", mklist("'token", token))));
+    var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(iconentry))));
+    icons.put(appname, entryxml, function(e) {
+        if (e) {
+            showstatus('Local copy');
+            workingstatus(false);
+            return false;
+        }
+        workingstatus(false);
+
+        // Open the email app
+        var mailto = safeb64encode('i/' + appname + '/' + token);
+        ui.navigate('mailto:' + mailto + '@' + topdomainname(window.location.hostname) + '?subject=Email to upload&body=Paste icon here', '_self');
+
+        // Refresh app icon
+        refreshingicon = true;
+        return ui.delay(refreshicon, 500);
+    }, 'remote');
+}
+
+/**
+ * Handle icon upload events.
+ */
+$('uploadIcon').onclick = function() {
+    if (ui.isMobile())
+        return emailicon();
+    return $('uploadFile').click();
+};
+$('uploadFile').onchange = function(e) {
+    return uploadicon(e.target.files);
+};
+$('appIcon').ondrag = function(e) {
+    e.stopPropagation();
+    e.preventDefault();
+    e.dataTransfer.dropEffect = 'copy';
+};
+$('appIcon').ondrop = function(e) {
+    e.stopPropagation();
+    e.preventDefault();
+    return uploadicon(e.dataTransfer.files);
+};
+
+/**
+ * Handle rate button event.
+ */
+$('rateApp').onclick = function() {
+    return ui.navigate('/#view=rate&app=' + appname, '_view');
+};
+
+})();
+</script>
+
+</div>