Modified: tuscany/sca-cpp/trunk/hosting/server/htdocs/store/index.html
URL: 
http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/htdocs/store/index.html?rev=1444660&r1=1444659&r2=1444660&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/htdocs/store/index.html (original)
+++ tuscany/sca-cpp/trunk/hosting/server/htdocs/store/index.html Mon Feb 11 
05:48:20 2013
@@ -50,8 +50,7 @@
 var categories = [
     ['Featured', 'featured', 1],
     ['Top', 'top', 2],
-    //['New', 'new', 3],
-    //['Search', 'all', 4],
+    ['New', 'new', 3],
     ['My Apps', 'myapps', 5]
 ];
 
@@ -83,7 +82,7 @@ $('viewhead').innerHTML = (function catm
 
     var m = '';
     map(function(c) { m += catmenuitem(car(c), cadr(c), caddr(c)); }, 
categories);
-    m += '<span class="rmenu"><input type="button" class="bluebutton" 
id="createApp" title="Create a new app" Value="Create"/></span>';
+    m += '<input type="button" class="bluebutton" id="createApp" 
style="position: absolute; top: 4px; right: 2px;" title="Create a new app" 
Value="Create"/>';
     return m;
 })();
 
@@ -113,9 +112,9 @@ function viewapp(appname) {
 /**
  * Create an app.
  */
-$('createApp').onclick = function() {
+ui.onclick($('createApp'), function(e) {
     return ui.navigate('/#view=create', '_view');
-};
+});
 
 /**
  * Get and display an app icon.

Modified: tuscany/sca-cpp/trunk/hosting/server/icons.py
URL: 
http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/icons.py?rev=1444660&r1=1444659&r2=1444660&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/icons.py (original)
+++ tuscany/sca-cpp/trunk/hosting/server/icons.py Mon Feb 11 05:48:20 2013
@@ -105,12 +105,22 @@ def put(id, icon, user, cache, apps):
         debug('icons.py::put::img', img)
         iconentry = mkentry(title(app), car(id), author(app), now(), ("'icon", 
("'image", img)))
         debug('icons.py::put::iconentry', iconentry)
-        return cache.put(iconid(id), iconentry)
+        rc = cache.put(iconid(id), iconentry)
+        if rc == False:
+            return False
+
+        # Update the app's updated date
+        return apps.put(id, app)
 
     # Put default empty icon
     iconentry = mkentry(title(app), car(id), author(app), now(), ())
     debug('icons.py::put::iconentry', iconentry)
-    return cache.put(iconid(id), iconentry)
+    rc = cache.put(iconid(id), iconentry)
+    if rc == False:
+        return False
+
+    # Update the app's updated date
+    return apps.put(id, app)
 
 # Get an icon
 def get(id, user, cache, apps):
@@ -171,5 +181,10 @@ def delete(id, user, cache, apps):
         return False
 
     # Delete the icon
-    return cache.delete(iconid(id))
+    rc = cache.delete(iconid(id))
+    if rc == False:
+        return False
+
+    # Update the app's updated date
+    return apps.put(id, app)
 

Modified: tuscany/sca-cpp/trunk/hosting/server/pages.py
URL: 
http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/pages.py?rev=1444660&r1=1444659&r2=1444660&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/pages.py (original)
+++ tuscany/sca-cpp/trunk/hosting/server/pages.py Mon Feb 11 05:48:20 2013
@@ -43,7 +43,12 @@ def put(id, page, user, cache, apps):
     # Update the page in the page db
     pageentry = mkentry(title(app), car(id), user.get(()), now(), 
content(page))
     debug('pages.py::put::pageentry', pageentry)
-    return cache.put(pageid(id), pageentry)
+    rc = cache.put(pageid(id), pageentry)
+    if rc == False:
+        return False
+
+    # Update the app's updated date
+    return apps.put(id, app)
 
 # Get a page from the page db
 def get(id, user, cache, apps):
@@ -90,5 +95,10 @@ def delete(id, user, cache, apps):
         return False
 
     # Delete the page
-    return cache.delete(pageid(id))
+    rc = cache.delete(pageid(id))
+    if rc == False:
+        return False
+
+    # Update the app's updated date
+    return apps.put(id, app)
 

Modified: tuscany/sca-cpp/trunk/hosting/server/ratings.py
URL: 
http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/ratings.py?rev=1444660&r1=1444659&r2=1444660&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/ratings.py (original)
+++ tuscany/sca-cpp/trunk/hosting/server/ratings.py Mon Feb 11 05:48:20 2013
@@ -110,9 +110,9 @@ def get(id, user, cache, db, apps):
     if isNull(id):
         topentries = db.get((("'regex", '("ratings" .* "app.ratings")'), 
("'rank", "(regexp_matches(value, '(.*\(rating )([^\)]+)(\).*)'))[2]::float"), 
("'limit", 25)))
         flatentries = tuple(map(lambda v: car(v), () if isNull(topentries) 
else topentries))
-        def rating(e):
+        def sortkey(e):
             return cadr(assoc("'rating", assoc("'ratings", assoc("'content", 
e))))
-        sortedentries = tuple(sorted(flatentries, key = rating, reverse = 
True))
+        sortedentries = tuple(sorted(flatentries, key = sortkey, reverse = 
True))[0:25]
         topratings = ((("'feed", ("'title", "Ratings"), ("'id", 'ratings')) + 
sortedentries),)
         debug('ratings.py::get::topratings', topratings)
         return topratings

Modified: tuscany/sca-cpp/trunk/hosting/server/server.composite
URL: 
http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/server.composite?rev=1444660&r1=1444659&r2=1444660&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/server.composite (original)
+++ tuscany/sca-cpp/trunk/hosting/server/server.composite Mon Feb 11 05:48:20 
2013
@@ -105,6 +105,7 @@
         <implementation.python script="apps.py"/>
         <reference name="user" target="User"/>
         <reference name="cache" target="Cache"/>
+        <reference name="db" target="Database"/>
         <reference name="dashboard" target="Dashboards"/>
         <reference name="store" target="AppStore"/>
         <reference name="composites" target="Composites"/>

Modified: tuscany/sca-cpp/trunk/hosting/server/store.py
URL: 
http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/store.py?rev=1444660&r1=1444659&r2=1444660&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/store.py (original)
+++ tuscany/sca-cpp/trunk/hosting/server/store.py Mon Feb 11 05:48:20 2013
@@ -102,6 +102,14 @@ def get(id, user, cache, apps, ratings):
         debug('store.py::get::store', topstore)
         return topstore
 
+    # Collect the newest apps
+    if tag == 'new':
+        newapps = apps.get(()) 
+        newapps = mergeapps(cdddr(car(newapps)), apps, ratings)
+        newstore = ((("'feed", ("'title", 'App Store'), ("'id", tag)) + 
newapps),)
+        debug('store.py::get::store', newstore)
+        return newstore
+
     # Collect the featured apps
     appid = cdr(id)
     def findapp(appid, store):

Modified: tuscany/sca-cpp/trunk/hosting/server/test.py
URL: 
http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/hosting/server/test.py?rev=1444660&r1=1444659&r2=1444660&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/hosting/server/test.py (original)
+++ tuscany/sca-cpp/trunk/hosting/server/test.py Mon Feb 11 05:48:20 2013
@@ -98,7 +98,7 @@ def testPages():
     # Put and get a page
     cache1 = mkcache('cache', {})
     page1updated = (("'entry", ("'title", 'app1'), ("'id", 'app1'), 
("'author", '[email protected]'), ("'updated", '2012-01-01T00:00:00+00:00'), 
("'content",)),)
-    assert pages.put(('app1',), page1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == True
+    assert pages.put(('app1',), page1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id, app = None: app1 if app 
is None else True)) == True
     assert pages.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('apps', lambda id: app1)) == page1updated
     
     # Reject put from user other than the author
@@ -113,7 +113,7 @@ def testPages():
     assert pages.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('apps', lambda id: app1)) == page1updated
 
     # Delete a page
-    assert pages.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == True
+    assert pages.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id, app = None: app1 if app 
is None else True)) == True
     assert pages.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('apps', lambda id: app1)) == defpagefromapp
     return True
 
@@ -137,7 +137,7 @@ def testIcons():
     # Put and get a icon
     cache1 = mkcache('cache', {})
     icon1updated = (("'entry", ("'title", 'app1'), ("'id", 'app1'), 
("'author", '[email protected]'), ("'updated", '2012-01-01T00:00:00+00:00'), 
("'content", ("'icon", ("'image", img50)))),)
-    assert icons.put(('app1',), icon1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == True
+    assert icons.put(('app1',), icon1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id, app = None: app1 if app 
is None else True)) == True
     assert icons.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('apps', lambda id: app1)) == icon1updated
     
     # Reject put from user other than the author
@@ -164,11 +164,11 @@ def testIcons():
 
     # Upload with valid token
     icon1oktoken = (("'entry", ("'title", 'app1'), ("'id", 'app1'), 
("'author", '[email protected]'), ("'updated", '2012-01-01T00:00:00+00:00'), 
("'content", ("'icon", ("'image", img50), ("'token", '1234')))),)
-    assert icons.put(('app1',), icon1oktoken, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == True
+    assert icons.put(('app1',), icon1oktoken, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id, app = None: app1 if app 
is None else True)) == True
     assert icons.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('apps', lambda id: app1)) == icon1updated
 
     # Delete a icon
-    assert icons.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == True
+    assert icons.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id, app = None: app1 if app 
is None else True)) == True
     assert icons.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('apps', lambda id: app1)) == deficonfromapp
     return True
 
@@ -187,7 +187,7 @@ def testComposites():
     # Put and get a composite
     cache1 = mkcache('cache', {})
     composite1updated = (("'entry", ("'title", 'app1'), ("'id", 'app1'), 
("'author", '[email protected]'), ("'updated", '2012-01-01T00:00:00+00:00'), 
("'content",)),)
-    assert composites.put(('app1',), composite1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == True
+    assert composites.put(('app1',), composite1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id, app = None: app1 if app 
is None else True)) == True
     assert composites.get(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == 
composite1updated
     
     # Reject put from user other than the author
@@ -202,36 +202,36 @@ def testComposites():
     assert composites.get(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == 
composite1updated
 
     # Delete a composite
-    assert composites.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == True
+    assert composites.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id, app = None: app1 if app 
is None else True)) == True
     assert composites.get(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('apps', lambda id: app1)) == 
defcompositefromapp
     return True
 
 def testApps():
     # Get default app
-    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
mkcache('cache', {}), mkref('dashboard', lambda id: None), mkref('store', 
lambda id: None), mkref('composites', lambda id: None), mkref('pages', lambda 
id: None), mkref('icons', lambda id: None)) is None
+    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
mkcache('cache', {}), mkref('db', lambda id: None), mkref('dashboard', lambda 
id: None), mkref('store', lambda id: None), mkref('composites', lambda id: 
None), mkref('pages', lambda id: None), mkref('icons', lambda id: None)) is None
 
     # Get an app
     app1 = (("'entry", ("'title", 'app1'), ("'id", 'app1'), ("'author", 
'[email protected]'), ("'updated", '2012-01-01T00:00:00+00:00'), ("'content", 
("'info", ("'description", '')))),)
-    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
mkcache('cache', {('apps', 'app1', 'app.info') : app1}), mkref('dashboard', 
lambda id: None), mkref('store', lambda id: None), mkref('composites', lambda 
id: None), mkref('pages', lambda id: None), mkref('icons', lambda id: None)) == 
app1
+    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
mkcache('cache', {('apps', 'app1', 'app.info') : app1}), mkref('db', lambda id: 
None), mkref('dashboard', lambda id: None), mkref('store', lambda id: None), 
mkref('composites', lambda id: None), mkref('pages', lambda id: None), 
mkref('icons', lambda id: None)) == app1
 
     # Put and get an app
     cache1 = mkcache('cache', {})
-    assert apps.put(('app1',), app1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('dashboard', lambda id, app: True), 
mkref('store', lambda id, app: True), mkref('composites', lambda id, app: 
True), mkref('pages', lambda id, app: True), mkref('icons', lambda id, app: 
True)) == True
-    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('dashboard', lambda id: None), mkref('store', lambda id: None), 
mkref('composites', lambda id: None), mkref('pages', lambda id: None), 
mkref('icons', lambda id: None)) == app1
+    assert apps.put(('app1',), app1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('db', lambda id: None), mkref('dashboard', 
lambda id, app: True), mkref('store', lambda id, app: True), 
mkref('composites', lambda id, app: True), mkref('pages', lambda id, app: 
True), mkref('icons', lambda id, app: True)) == True
+    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('db', lambda id: None), mkref('dashboard', lambda id: None), 
mkref('store', lambda id: None), mkref('composites', lambda id: None), 
mkref('pages', lambda id: None), mkref('icons', lambda id: None)) == app1
     return True
     
     # Reject put from user other than the author
     app1otherauthor = (("'entry", ("'title", 'app1'), ("'id", 'app1'), 
("'author", '[email protected]'), ("'updated", '2012-01-03T00:00:00+00:00'), 
("'content",)),)
-    assert apps.put(('app1',), app1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('dashboard', lambda id, app: True), 
mkref('store', lambda id, app: True), mkref('composites', lambda id, app: 
True), mkref('pages', lambda id, app: True), mkref('icons', lambda id, app: 
True)) == false
-    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('dashboard', lambda id: None), mkref('store', lambda id: None), 
mkref('composites', lambda id: None), mkref('pages', lambda id: None), 
mkref('icons', lambda id: None)) == app1
+    assert apps.put(('app1',), app1, mkref('user', lambda id: 
'[email protected]'), cache1, mkref('db', lambda id: None), mkref('dashboard', 
lambda id, app: True), mkref('store', lambda id, app: True), 
mkref('composites', lambda id, app: True), mkref('pages', lambda id, app: 
True), mkref('icons', lambda id, app: True)) == false
+    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('db', lambda id: None), mkref('dashboard', lambda id: None), 
mkref('store', lambda id: None), mkref('composites', lambda id: None), 
mkref('pages', lambda id: None), mkref('icons', lambda id: None)) == app1
 
     # Reject delete from user other than the author
-    assert apps.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('dashboard', lambda id: None), 
mkref('store', lambda id: None), mkref('composites', lambda id: None), 
mkref('pages', lambda id: None), mkref('icons', lambda id: None)) == False
-    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('dashboard', lambda id: None), mkref('store', lambda id: None), 
mkref('composites', lambda id: None), mkref('pages', lambda id: None), 
mkref('icons', lambda id: None)) == app1
+    assert apps.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('db', lambda id: None), mkref('dashboard', 
lambda id: None), mkref('store', lambda id: None), mkref('composites', lambda 
id: None), mkref('pages', lambda id: None), mkref('icons', lambda id: None)) == 
False
+    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
cache1, mkref('db', lambda id: None), mkref('dashboard', lambda id: None), 
mkref('store', lambda id: None), mkref('composites', lambda id: None), 
mkref('pages', lambda id: None), mkref('icons', lambda id: None)) == app1
 
     # Delete an app
-    assert apps.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('dashboard', lambda id: None), 
mkref('store', lambda id: None), mkref('composites', lambda id: None), 
mkref('pages', lambda id: None), mkref('icons', lambda id: None)) == True
-    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
mkcache('cache', {}), mkref('dashboard', lambda id: None), mkref('store', 
lambda id: None), mkref('composites', lambda id: None), mkref('pages', lambda 
id: None), mkref('icons', lambda id: None)) is None
+    assert apps.delete(('app1',), mkref('user', lambda id: 
'[email protected]'), cache1, mkref('db', lambda id: None), mkref('dashboard', 
lambda id: None), mkref('store', lambda id: None), mkref('composites', lambda 
id: None), mkref('pages', lambda id: None), mkref('icons', lambda id: None)) == 
True
+    assert apps.get(('app1',), mkref('user', lambda id: '[email protected]'), 
mkcache('cache', {}), mkref('db', lambda id: None), mkref('dashboard', lambda 
id: None), mkref('store', lambda id: None), mkref('composites', lambda id: 
None), mkref('pages', lambda id: None), mkref('icons', lambda id: None)) is None
     return True
 
 def testStore():

Modified: tuscany/sca-cpp/trunk/modules/js/htdocs/component.js
URL: 
http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/js/htdocs/component.js?rev=1444660&r1=1444659&r2=1444660&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/js/htdocs/component.js (original)
+++ tuscany/sca-cpp/trunk/modules/js/htdocs/component.js Mon Feb 11 05:48:20 
2013
@@ -184,43 +184,113 @@ HTTPBindingClient.jsonResult = function(
 };
 
 /**
- * Schedule async requests, and limit to 4 concurrent running requests.
+ * Schedule async requests, limiting the number of concurrent running requests.
  */
 HTTPBindingClient.queuedRequests = new Array();
-HTTPBindingClient.runningRequests = 0;
-HTTPBindingClient.scheduleAsyncRequest = function(f) {
+HTTPBindingClient.runningRequests = new Array();
+HTTPBindingClient.concurrentRequests = 2;
+
+HTTPBindingClient.scheduleAsyncRequest = function(f, cancelable) {
+    //debug('schedule async request, running ' + 
HTTPBindingClient.runningRequests.length + ' queued ' + 
HTTPBindingClient.queuedRequests.length);
+
     // Queue the request function
-    HTTPBindingClient.queuedRequests.push(f);
+    var req = new Object();
+    req.f = f;
+    req.cancelable = cancelable;
+    req.canceled = false;
+    HTTPBindingClient.queuedRequests.push(req);
+
+    // Execute any requests in the queue
+    setTimeout(function() {
+        HTTPBindingClient.runAsyncRequests(true);
+    }, 0);
+    return true;
+};
 
-    // Execute requests in the queue
-    (function runAsyncRequests() {
-        // Stop now if we already have enough requests running or there's no 
request in the queue
-        //debug('runAsyncRequests', 'running', 
HTTPBindingClient.runningRequests, 'queued', 
HTTPBindingClient.queuedRequests.length);
-        if(HTTPBindingClient.runningRequests >= 4 || 
HTTPBindingClient.queuedRequests.length == 0)
+HTTPBindingClient.forgetRequest = function(req) {
+    req.http = null;
+
+    // Remove a request from the list of running requests
+    for (i in HTTPBindingClient.runningRequests) {
+        if (HTTPBindingClient.runningRequests[i] == req) {
+            HTTPBindingClient.runningRequests.splice(i, 1);
+            //debug('forget async request, running ' + 
HTTPBindingClient.runningRequests.length + ' queued ' + 
HTTPBindingClient.queuedRequests.length);
             return true;
+        }
+    }
+    return false;
+};
+
+HTTPBindingClient.cancelRequests = function() {
+    //debug('cancel async requests, running ' + 
HTTPBindingClient.runningRequests.length + ' queued ' + 
HTTPBindingClient.queuedRequests.length);
 
-        // Run the first request in the queue
-        var req = HTTPBindingClient.queuedRequests.shift();
-        HTTPBindingClient.runningRequests++;
-        setTimeout(function runAsyncRequest() {
+    // Cancel any cancelable in flight HTTP requests
+    for (i in HTTPBindingClient.queuedRequests) {
+        var req = HTTPBindingClient.queuedRequests[i];
+        if (req.cancelable)
+            req.canceled = true;
+    }
+    for (i in HTTPBindingClient.runningRequests) {
+        var req = HTTPBindingClient.runningRequests[i];
+        if (req.cancelable) {
+            req.canceled = true;
+            if (req.http) {
+                req.http.abort();
+                req.http = null;
+                //debug('abort async request, running ' + 
HTTPBindingClient.runningRequests.length + ' queued ' + 
HTTPBindingClient.queuedRequests.length);
+            }
+        }
+    }
+
+    // Flush the queue
+    setTimeout(function() {
+        HTTPBindingClient.runAsyncRequests(true);
+    }, 0);
+}
+
+HTTPBindingClient.runAsyncRequests = function(fromui) {
+    // Stop now if we already have enough requests running or there's no 
request in the queue
+    if(HTTPBindingClient.runningRequests.length >= 
HTTPBindingClient.concurrentRequests || HTTPBindingClient.queuedRequests.length 
== 0)
+        return true;
+
+    // Run the first request in the queue
+    var req = HTTPBindingClient.queuedRequests.shift();
+    if (!req.canceled) {
+        HTTPBindingClient.runningRequests.push(req);
+        //debug('run async request, running ' + 
HTTPBindingClient.runningRequests.length + ' queued ' + 
HTTPBindingClient.queuedRequests.length);
+        var runAsyncRequest = function() {
+            if (req.canceled) {
+                HTTPBindingClient.forgetRequest(req);
+                //debug('canceled timed async request, running ' + 
HTTPBindingClient.runningRequests.length + ' queued ' + 
HTTPBindingClient.queuedRequests.length);
+                return false;
+            }
             try {
-                return req(function asyncRequestDone() {
+                req.http = new XMLHttpRequest();
+                return req.f(req.http, function asyncRequestDone() {
                     // Execute any requests left in the queue
-                    HTTPBindingClient.runningRequests--;
-                    runAsyncRequests();
+                    HTTPBindingClient.forgetRequest(req);
+                    //debug('done async request, running ' + 
HTTPBindingClient.runningRequests.length + ' queued ' + 
HTTPBindingClient.queuedRequests.length);
+                    HTTPBindingClient.runAsyncRequests(false);
                     return true;
                 });
             } catch(e) {
                 // Execute any requests left in the queue
-                HTTPBindingClient.runningRequests--;
-                runAsyncRequests();
+                HTTPBindingClient.forgetRequest(req);
+                //debug('err async request, running ' + 
HTTPBindingClient.runningRequests.length + ' queued ' + 
HTTPBindingClient.queuedRequests.length);
+                HTTPBindingClient.runAsyncRequests(false);
             }
-        }, 0);
+            return false;
+        };
+        if (false)
+            setTimeout(runAsyncRequest, 0);
+        else
+            runAsyncRequest();
+    } else {
+        //debug('canceled queued async request, running ' + 
HTTPBindingClient.runningRequests.length + ' queued ' + 
HTTPBindingClient.queuedRequests.length);
+    }
 
-        // Execute any requests left in the queue
-        runAsyncRequests();
-    })();
-    return true;
+    // Execute any requests left in the queue
+    HTTPBindingClient.runAsyncRequests(fromui);
 };
 
 /**
@@ -339,8 +409,7 @@ HTTPBindingClient.prototype.jsonApply = 
     // Call asynchronously with a callback
     if(hascb) {
         var u = this.uri;
-        return HTTPBindingClient.scheduleAsyncRequest(function 
jsonApplyRequest(done) {
-            var http = new XMLHttpRequest();
+        return HTTPBindingClient.scheduleAsyncRequest(function 
jsonApplyRequest(http, done) {
             http.open("POST", u, true);
             http.setRequestHeader("Accept", "*/*");
             http.setRequestHeader("Content-Type", "application/json-rpc");
@@ -371,7 +440,7 @@ HTTPBindingClient.prototype.jsonApply = 
             // Send the request
             http.send(req.data);
             return req.id;
-        });
+        }, false);
     }
 
     // Call synchronously and return the result or exception
@@ -402,16 +471,15 @@ HTTPBindingClient.prototype.get = functi
                 return item;
 
             // Pass local result to callback
-            try {
+            setTimeout(function() {
                 cb(item);
-            } catch (cbe) {}
+            }, 0);
         }
     }
 
     // Call asynchronously with a callback
     if(hascb) {
-        return HTTPBindingClient.scheduleAsyncRequest(function 
getRequest(done) {
-            var http = new XMLHttpRequest();
+        return HTTPBindingClient.scheduleAsyncRequest(function 
getRequest(http, done) {
             http.open("GET", u, true);
             http.setRequestHeader("Accept", "*/*");
             http.onreadystatechange = function() {
@@ -420,7 +488,8 @@ HTTPBindingClient.prototype.get = functi
                     // Pass result if different from local result
                     if(http.status == 200) {
                         var xl = http.getResponseHeader("X-Login");
-                        if(xl != null && xl != '') {
+                        var ct = http.getResponseHeader("Content-Type");
+                        if(xl != null && xl != '' && ct != null && 
ct.indexOf('text/html') == 0) {
                             // Detect redirect to a login page
                             try {
                                 var le = new HTTPBindingClient.Exception(403, 
'X-Login');
@@ -431,7 +500,6 @@ HTTPBindingClient.prototype.get = functi
                             } catch(cbe) {}
 
                         }
-                        var ct = http.getResponseHeader("Content-Type");
                         if(http.responseText == '' || ct == null || ct == '') {
                             // Report empty response
                             try {
@@ -467,7 +535,7 @@ HTTPBindingClient.prototype.get = functi
             // Send the request
             http.send(null);
             return true;
-        });
+        }, true);
     }
 
     // Call synchronously and return the result or exception
@@ -477,7 +545,8 @@ HTTPBindingClient.prototype.get = functi
     http.send(null);
     if(http.status == 200) {
         var xl = http.getResponseHeader("X-Login");
-        if(xl != null && xl != '') {
+        var ct = http.getResponseHeader("Content-Type");
+        if(xl != null && xl != '' && ct != null && ct.indexOf('text/html') == 
0) {
             // Detect redirect to a login page
             var le = new HTTPBindingClient.Exception(403, 'X-Login');
             if(window.onloginredirect)
@@ -504,8 +573,7 @@ HTTPBindingClient.prototype.post = funct
     // Call asynchronously with a callback
     if(hascb) {
         var u = this.uri;
-        return HTTPBindingClient.scheduleAsyncRequest(function 
postRequest(done) {
-            var http = new XMLHttpRequest();
+        return HTTPBindingClient.scheduleAsyncRequest(function 
postRequest(http, done) {
             http.open("POST", u, true);
             http.setRequestHeader("Accept", "*/*");
             http.setRequestHeader("Content-Type", "application/atom+xml");
@@ -529,7 +597,7 @@ HTTPBindingClient.prototype.post = funct
             // Send the request
             http.send(entry);
             return true;
-        });
+        }, false);
     }
 
     // Call synchronously
@@ -562,8 +630,7 @@ HTTPBindingClient.prototype.put = functi
 
     // Call asynchronously with a callback
     if(hascb) {
-        return HTTPBindingClient.scheduleAsyncRequest(function 
putRequest(done) {
-            var http = new XMLHttpRequest();
+        return HTTPBindingClient.scheduleAsyncRequest(function 
putRequest(http, done) {
             http.open("PUT", u, true);
             http.setRequestHeader("Accept", "*/*");
             http.setRequestHeader("Content-Type", "application/atom+xml");
@@ -599,7 +666,7 @@ HTTPBindingClient.prototype.put = functi
             // Send the request
             http.send(entry);
             return true;
-        });
+        }, false);
     }
 
     // Call synchronously
@@ -640,8 +707,7 @@ HTTPBindingClient.prototype.del = functi
 
     // Call asynchronously with a callback
     if(hascb) {
-        return HTTPBindingClient.scheduleAsyncRequest(function 
delRequest(done) {
-            var http = new XMLHttpRequest();
+        return HTTPBindingClient.scheduleAsyncRequest(function 
delRequest(http, done) {
             http.open("DELETE", u, true);        
             http.setRequestHeader("Accept", "*/*");
             http.onreadystatechange = function() {
@@ -665,7 +731,7 @@ HTTPBindingClient.prototype.del = functi
             // Send the request
             http.send(null);
             return true;
-        });
+        }, false);
     }
 
     // Call synchronously

Modified: tuscany/sca-cpp/trunk/modules/js/htdocs/ui.js
URL: 
http://svn.apache.org/viewvc/tuscany/sca-cpp/trunk/modules/js/htdocs/ui.js?rev=1444660&r1=1444659&r2=1444660&view=diff
==============================================================================
--- tuscany/sca-cpp/trunk/modules/js/htdocs/ui.js (original)
+++ tuscany/sca-cpp/trunk/modules/js/htdocs/ui.js Mon Feb 11 05:48:20 2013
@@ -29,6 +29,8 @@ var ui = {};
 ui.elementByID = function(node, id) {
     if (node.skipNode == true)
         return null;
+    if (node == document)
+        return document.getElementById(id);
     for (var i in node.childNodes) {
         var child = node.childNodes[i];
         if (isNull(child))
@@ -43,6 +45,21 @@ ui.elementByID = function(node, id) {
 };
 
 /**
+ * Remove ids in a tree of elements.
+ */
+ui.removeElementIDs = function(node) {
+    if (!isNull(node.id))
+        node.id = null;
+    for (var i in node.childNodes) {
+        var child = node.childNodes[i];
+        if (isNull(child))
+            continue;
+        ui.removeElementIDs(child);
+    }
+    return true;
+};
+
+/**
  * Return the current document, or a child element with the given id.
  */
 function $(id) {
@@ -229,6 +246,20 @@ ui.webkitVersion = function() {
 };
 
 /**
+ * Return the Safari version.
+ */
+ui.browserVersion = function() {
+    return Number(navigator.userAgent.replace(/.*Version\/(\d+\.\d+).*/, 
'$1'));
+};
+
+/**
+ * Return true if the client is Android based.
+ */
+ui.isAndroid = function() {
+    return navigator.userAgent.match(/Android/i);
+};
+
+/**
  * Return true if the client is Firefox.
  */
 ui.isFirefox = function() {
@@ -273,16 +304,11 @@ ui.msieVersion = function() {
 /**
  * Run a UI rendering function asynchronously.
  */
-ui.asyncFrame = null;
-ui.async = function(f) {
-    if (isNull(ui.asyncFrame))
-        // Use requestAnimationFrame when available, fallback to setTimeout
-        ui.asyncFrame = window.requestAnimationFrame || 
window.webkitRequestAnimationFrame ||
-            window.mozRequestAnimationFrame || window.oRequestAnimationFrame 
|| window.msRequestAnimationFrame ||
-            function(f) {
-                return window.setTimeout(f, 16);
-            };
-    return ui.asyncFrame.call(window, f);
+ui.async = function(f, t) {
+    window.setTimeout(function() {
+        return f();
+    }, isNull(t)? 0 : t);
+    return true;
 };
 
 /**
@@ -290,10 +316,10 @@ ui.async = function(f) {
  */
 ui.delayed = {}
 ui.delay = function(f, t) {
-    var id =  window.setTimeout(function() {
+    var id = window.setTimeout(function() {
         delete ui.delayed[id];
         return f();
-    }, isNull(t)? 16 : t);
+    }, isNull(t)? 0 : t);
     ui.delayed[id] = id;
     return id;
 };
@@ -443,6 +469,9 @@ ui.navigate = function(url, win) {
             window.ontouchmove = null;
         }
 
+        // Cancel any cancelable HTTP requests
+        HTTPBindingClient.cancelRequests();
+
         // Cleanup memoized element lookups
         ui.unmemo$();
 
@@ -460,12 +489,65 @@ ui.navigate = function(url, win) {
 }
 
 /**
+ * Bind a click handler to a widget.
+ */
+ui.ontouchstart = function(widget, e) {
+    //debug('ontouchstart');
+    widget.down = true;
+    widget.moved = false;
+    var t = e.touches[0];
+    widget.moveX = t.clientX;
+    widget.moveY = t.clientY;
+};
+
+ui.ontouchmove = function(widget, e) {
+    //debug('ontouchmove');
+    var t = e.touches[0];
+    if (t.clientX != widget.moveX) {
+        widget.moveX = t.clientX;
+        widget.moved = true;
+    }
+    if (t.clientY != widget.moveY) {
+        widget.moveY = t.clientY;
+        widget.moved = true;
+    }
+};
+
+ui.ontouchend = function(widget, e) {
+    //debug('ontouchend');
+    widget.down = false;
+    if (!widget.moved) {
+        e.preventDefault();
+        return widget.onclick(e);
+    }
+};
+
+ui.onclick = function(widget, handler) {
+    if (ui.isMobile()) {
+        widget.ontouchstart = function(e) {
+            return ui.ontouchstart(widget, e);
+        };
+        widget.ontouchmove = function(e) {
+            return ui.ontouchmove(widget, e);
+        };
+        widget.ontouchend = function(e) {
+            return ui.ontouchend(widget, e);
+        };
+    }
+    widget.onclick = function(e) {
+        //debug('onclick');
+        return handler(e);
+    };
+    return widget;
+};
+
+/**
  * Build a portable <a href> tag.
  */
 ui.href = function(id, loc, target, html) {
     if (target == '_blank')
         return '<a id="' + id + '" href="' + loc + '" target="_blank">' + html 
+ '</a>';
-    return '<a id="' + id + '" href="' + loc + '" onclick="return 
ui.navigate(\'' + loc + '\', \'' + target + '\');">' + html + '</a>';
+    return '<a id="' + id + '" href="' + loc + '" ' + (ui.isMobile()? 
'ontouchstart="return ui.ontouchstart(this, event);" ontouchmove="return 
ui.ontouchmove(this, event);" ontouchend="return ui.ontouchend(this, event);" ' 
: '') + 'onclick="return ui.navigate(\'' + loc + '\', \'' + target + '\');">' + 
html + '</a>';
 };
 
 /**
@@ -489,7 +571,7 @@ ui.menufunc = function(id, name, fun, hi
     function Menu() {
         this.content = function() {
             function href(id, fun, html) {
-                return '<a id="' + id + '" href="/" onclick="' + fun + '">' + 
html + '</a>';
+                return '<a id="' + id + '" href="/" ' + (ui.isMobile()? 
'ontouchstart="return ui.ontouchstart(this, event);" ontouchmove="return 
ui.ontouchmove(this, event);" ontouchend="return ui.ontouchend(this, event);" ' 
: '') + 'onclick="' + fun + '">' + html + '</a>';
             }
 
             if (hilight == true)


Reply via email to