diff options
55 files changed, 491 insertions, 291 deletions
diff --git a/sca-cpp/trunk/hosting/server/apps.py b/sca-cpp/trunk/hosting/server/apps.py index 20c38cb3c5..e61ee5eb9d 100644 --- a/sca-cpp/trunk/hosting/server/apps.py +++ b/sca-cpp/trunk/hosting/server/apps.py @@ -25,7 +25,7 @@ def appid(id): return ("apps", car(id), "app.info") # Put an app into the apps db -def put(id, app, user, cache, dashboard, store, composites, pages, icons): +def put(id, app, user, cache, db, dashboard, store, composites, pages, icons): debug('apps.py::put::id', id) debug('apps.py::put::app', app) @@ -68,7 +68,7 @@ def put(id, app, user, cache, dashboard, store, composites, pages, icons): return False # Clone app - appentry = mkentry(title(app), car(id), user.get(()), now(), content(app)) + appentry = mkentry(title(capp), car(id), user.get(()), now(), content(capp)) debug('apps.py::put::appentry', appentry) cache.put(appid(id), appentry) composites.put(id, composites.get((eid,))) @@ -78,10 +78,19 @@ def put(id, app, user, cache, dashboard, store, composites, pages, icons): return True # Get an app from the apps db -def get(id, user, cache, dashboard, store, composites, pages, icons): +def get(id, user, cache, db, dashboard, store, composites, pages, icons): debug('apps.py::get::id', id) + + # Return the newest apps if isNull(id): - return (("'feed", ("'title", "Apps"), ("'id", "apps")),) + newentries = db.get((("'regex", '("apps" .* "app.info")'), ("'rank", "(regexp_matches(value, '(.*\(updated )([^\)]+)(\).*)'))[2]::timestamp"), ("'limit", 25))) + flatentries = tuple(map(lambda v: car(v), () if isNull(newentries) else newentries)) + def sortkey(e): + return updated((e,)) + sortedentries = tuple(sorted(flatentries, key = sortkey, reverse = True))[0:25] + newapps = ((("'feed", ("'title", "Apps"), ("'id", 'apps')) + sortedentries),) + debug('apps.py::get::newapps', newapps) + return newapps # Get the requested app app = cache.get(appid(id)) @@ -94,7 +103,7 @@ def get(id, user, cache, dashboard, store, composites, pages, icons): return app # Delete an app from the apps db -def delete(id, user, cache, dashboard, store, composites, pages, icons): +def delete(id, user, cache, db, dashboard, store, composites, pages, icons): debug('apps.py::delete::id', id) # Get the requested app diff --git a/sca-cpp/trunk/hosting/server/composites.py b/sca-cpp/trunk/hosting/server/composites.py index d0276ab5ee..581d202671 100644 --- a/sca-cpp/trunk/hosting/server/composites.py +++ b/sca-cpp/trunk/hosting/server/composites.py @@ -43,7 +43,12 @@ def put(id, comp, user, cache, apps): # Update the composite in the composite db compentry = mkentry(title(app), car(id), user.get(()), now(), content(comp)) debug('composites.py::put::compentry', compentry) - return cache.put(compid(id), compentry) + rc = cache.put(compid(id), compentry) + if rc == False: + return False + + # Update the app's updated date + return apps.put(id, app) # Get a composite from the composite db def get(id, user, cache, apps): @@ -88,5 +93,10 @@ def delete(id, user, cache, apps): return False # Delete the composite - return cache.delete(compid(id)) + rc = cache.delete(compid(id)) + if rc == False: + return False + + # Update the app's updated date + return apps.put(id, app) diff --git a/sca-cpp/trunk/hosting/server/data/apps/nearme/app.info b/sca-cpp/trunk/hosting/server/data/apps/nearme/app.info index 07777a07b0..9669bd85f0 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/nearme/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/nearme/app.info @@ -1 +1 @@ -((entry (title "nearme") (id "nearme") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "nearme") (id "nearme") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/nearme2/app.info b/sca-cpp/trunk/hosting/server/data/apps/nearme2/app.info index e637ebab14..0b7f3f3e7a 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/nearme2/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/nearme2/app.info @@ -1 +1 @@ -((entry (title "nearme2") (id "nearme2") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "nearme2") (id "nearme2") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/new/app.info b/sca-cpp/trunk/hosting/server/data/apps/new/app.info index 04ab8b8571..3b5a1e748d 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/new/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/new/app.info @@ -1 +1 @@ -((entry (title "An empty app template") (id "new") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "A new app") (id "new") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "A new app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/ourphotos/app.info b/sca-cpp/trunk/hosting/server/data/apps/ourphotos/app.info index afc57e86da..7fd5c86dc8 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/ourphotos/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/ourphotos/app.info @@ -1 +1 @@ -((entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/shoppingcart/app.info b/sca-cpp/trunk/hosting/server/data/apps/shoppingcart/app.info index 3b77112bff..c23fa1dbe5 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/shoppingcart/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/shoppingcart/app.info @@ -1 +1 @@ -((entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/slice/app.info b/sca-cpp/trunk/hosting/server/data/apps/slice/app.info index 76685cd580..02b7744464 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/slice/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/slice/app.info @@ -1 +1 @@ -((entry (title "Slice") (id "slice") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Slice") (id "slice") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/test/app.info b/sca-cpp/trunk/hosting/server/data/apps/test/app.info index b6ea414f7a..90e394831e 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/test/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/test/app.info @@ -1 +1 @@ -((entry (title "An empty test app") (id "test") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "An empty test app") (id "test") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testanimation/app.info b/sca-cpp/trunk/hosting/server/data/apps/testanimation/app.info index a6759e4df8..9d3c35bc0e 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testanimation/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testanimation/app.info @@ -1 +1 @@ -((entry (title "Test animation components") (id "testanimation") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test animation components") (id "testanimation") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testdb/app.info b/sca-cpp/trunk/hosting/server/data/apps/testdb/app.info index 3f5b3deadc..df9d884bfb 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testdb/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testdb/app.info @@ -1 +1 @@ -((entry (title "Test database components") (id "testdb") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test database components") (id "testdb") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testevents/app.info b/sca-cpp/trunk/hosting/server/data/apps/testevents/app.info index 20191d663c..788c083d77 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testevents/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testevents/app.info @@ -1 +1 @@ -((entry (title "Test event components") (id "testevents") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test event components") (id "testevents") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testhttp/app.info b/sca-cpp/trunk/hosting/server/data/apps/testhttp/app.info index ef2afff46f..50f315e6f0 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testhttp/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testhttp/app.info @@ -1 +1 @@ -((entry (title "Test HTTP components") (id "testhttp") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test HTTP components") (id "testhttp") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testlogic/app.info b/sca-cpp/trunk/hosting/server/data/apps/testlogic/app.info index b4d3d9d492..7475616ec4 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testlogic/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testlogic/app.info @@ -1 +1 @@ -((entry (title "Test logic components") (id "testlogic") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test logic components") (id "testlogic") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testsearch/app.info b/sca-cpp/trunk/hosting/server/data/apps/testsearch/app.info index 6c959dc3c4..baf16599e1 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testsearch/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testsearch/app.info @@ -1 +1 @@ -((entry (title "Test search components") (id "testsearch") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test search components") (id "testsearch") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testsms/app.info b/sca-cpp/trunk/hosting/server/data/apps/testsms/app.info index ef2afff46f..50f315e6f0 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testsms/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testsms/app.info @@ -1 +1 @@ -((entry (title "Test HTTP components") (id "testhttp") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test HTTP components") (id "testhttp") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testsocial/app.info b/sca-cpp/trunk/hosting/server/data/apps/testsocial/app.info index 16190d4fe8..401a9a4a9b 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testsocial/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testsocial/app.info @@ -1 +1 @@ -((entry (title "Test social components") (id "testsocial") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test social components") (id "testsocial") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testtext/app.info b/sca-cpp/trunk/hosting/server/data/apps/testtext/app.info index e717015880..4277aed6df 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testtext/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testtext/app.info @@ -1 +1 @@ -((entry (title "Test text processing components") (id "testtext") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test text processing components") (id "testtext") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testurl/app.info b/sca-cpp/trunk/hosting/server/data/apps/testurl/app.info index 37d89b57e0..3b2d48fd43 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testurl/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testurl/app.info @@ -1 +1 @@ -((entry (title "Test URL components") (id "testurl") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test URL components") (id "testurl") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testvalues/app.info b/sca-cpp/trunk/hosting/server/data/apps/testvalues/app.info index 42ed01b53d..97c95917e3 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testvalues/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testvalues/app.info @@ -1 +1 @@ -((entry (title "Test values and lists") (id "testvalues") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test values and lists") (id "testvalues") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testwidgets/app.info b/sca-cpp/trunk/hosting/server/data/apps/testwidgets/app.info index 3d8e7be195..3d0f35c15a 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testwidgets/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testwidgets/app.info @@ -1 +1 @@ -((entry (title "Test widgets") (id "testwidgets") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test widgets") (id "testwidgets") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testwidgets2/app.info b/sca-cpp/trunk/hosting/server/data/apps/testwidgets2/app.info index 2ba25712f9..e5e2e47bb8 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testwidgets2/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testwidgets2/app.info @@ -1 +1 @@ -((entry (title "Test more widgets") (id "testwidgets2") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test more widgets") (id "testwidgets2") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/testwidgets3/app.info b/sca-cpp/trunk/hosting/server/data/apps/testwidgets3/app.info index 3d01141f07..432d560b99 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/testwidgets3/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/testwidgets3/app.info @@ -1 +1 @@ -((entry (title "Test HTML generator components") (id "testwidgets3") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "Test HTML generator components") (id "testwidgets3") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/apps/twsms/app.info b/sca-cpp/trunk/hosting/server/data/apps/twsms/app.info index d870caf3e2..f1fe2b8c45 100644 --- a/sca-cpp/trunk/hosting/server/data/apps/twsms/app.info +++ b/sca-cpp/trunk/hosting/server/data/apps/twsms/app.info @@ -1 +1 @@ -((entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "Jan 01, 2012") (content (info (description "Sample app"))))) +((entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00") (content (info (description "Sample app"))))) diff --git a/sca-cpp/trunk/hosting/server/data/store/all/store.apps b/sca-cpp/trunk/hosting/server/data/store/all/store.apps index cb12aa05c7..14b9390c7f 100644 --- a/sca-cpp/trunk/hosting/server/data/store/all/store.apps +++ b/sca-cpp/trunk/hosting/server/data/store/all/store.apps @@ -1 +1 @@ -((feed (title "App Store") (id "all") (entry (title "Check my public social data") (id "me360") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Where are my friends") (id "nearme") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Where are my friends") (id "nearme2") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Slice") (id "slice") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "An empty test app") (id "test") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test values and lists") (id "testvalues") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test social components") (id "testsocial") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test URL components") (id "testurl") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test logic components") (id "testlogic") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test text processing components") (id "testtext") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test HTTP components") (id "testhttp") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test SMS API") (id "testsms") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test widgets") (id "testwidgets") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test more widgets") (id "testwidgets2") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test event components") (id "testevents") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test search components") (id "testsearch") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test database components") (id "testdb") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test HTML generator components") (id "testwidgets3") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Test animation components") (id "testanimation") (author "admin@example.com") (updated "Jan 01, 2012")))) +((feed (title "App Store") (id "all") (entry (title "Check my public social data") (id "me360") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Where are my friends") (id "nearme") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Where are my friends") (id "nearme2") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Slice") (id "slice") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "An empty test app") (id "test") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test values and lists") (id "testvalues") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test social components") (id "testsocial") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test URL components") (id "testurl") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test logic components") (id "testlogic") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test text processing components") (id "testtext") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test HTTP components") (id "testhttp") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test SMS API") (id "testsms") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test widgets") (id "testwidgets") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test more widgets") (id "testwidgets2") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test event components") (id "testevents") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test search components") (id "testsearch") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test database components") (id "testdb") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test HTML generator components") (id "testwidgets3") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Test animation components") (id "testanimation") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")))) diff --git a/sca-cpp/trunk/hosting/server/data/store/featured/store.apps b/sca-cpp/trunk/hosting/server/data/store/featured/store.apps index adfcf5e10d..e196ddc759 100644 --- a/sca-cpp/trunk/hosting/server/data/store/featured/store.apps +++ b/sca-cpp/trunk/hosting/server/data/store/featured/store.apps @@ -1 +1 @@ -((feed (title "App Store") (id "featured") (entry (title "Check my public social data") (id "me360") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Where are my friends") (id "nearme") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Where are my friends") (id "nearme2") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Slice") (id "slice") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "Jan 01, 2012")))) +((feed (title "App Store") (id "featured") (entry (title "Check my public social data") (id "me360") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Where are my friends") (id "nearme") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Where are my friends") (id "nearme2") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Slice") (id "slice") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")))) diff --git a/sca-cpp/trunk/hosting/server/data/store/new/store.apps b/sca-cpp/trunk/hosting/server/data/store/new/store.apps index b444d7f73c..b874c6e667 100644 --- a/sca-cpp/trunk/hosting/server/data/store/new/store.apps +++ b/sca-cpp/trunk/hosting/server/data/store/new/store.apps @@ -1 +1 @@ -((feed (title "App Store") (id "new") (entry (title "Check my public social data") (id "me360") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Where are my friends") (id "nearme") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Where are my friends") (id "nearme2") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Slice") (id "slice") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "Jan 01, 2012")))) +((feed (title "App Store") (id "new") (entry (title "Check my public social data") (id "me360") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Where are my friends") (id "nearme") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Where are my friends") (id "nearme2") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Slice") (id "slice") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")))) diff --git a/sca-cpp/trunk/hosting/server/data/store/top/store.apps b/sca-cpp/trunk/hosting/server/data/store/top/store.apps index 63a7b34d46..5202823b10 100644 --- a/sca-cpp/trunk/hosting/server/data/store/top/store.apps +++ b/sca-cpp/trunk/hosting/server/data/store/top/store.apps @@ -1 +1 @@ -((feed (title "App Store") (id "top") (entry (title "Check my public social data") (id "me360") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Where are my friends") (id "nearme") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Where are my friends") (id "nearme2") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "Slice") (id "slice") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "Jan 01, 2012")) (entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "Jan 01, 2012")))) +((feed (title "App Store") (id "top") (entry (title "Check my public social data") (id "me360") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Where are my friends") (id "nearme") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Where are my friends") (id "nearme2") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Our photos of an event") (id "ourphotos") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "Slice") (id "slice") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "My online store") (id "shoppingcart") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")) (entry (title "SMS send service") (id "twsms") (author "admin@example.com") (updated "2012-01-01T00:00:00+00:00")))) diff --git a/sca-cpp/trunk/hosting/server/htdocs/account/index.html b/sca-cpp/trunk/hosting/server/htdocs/account/index.html index 9357a89dd6..c16dde4b53 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/account/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/account/index.html @@ -28,7 +28,7 @@ <tr><tr><td class="label">Email:</td></tr> <tr><td><input type="text" id="userEmail" class="readentry" size="30" readonly="readonly" placeholder="Your email address" style="width: 300px;"/></td></tr> <tr><tr><td class="label">Picture:</td></tr> -<tr><td><img id="userPicture" style="width: 50px; height: 50px; vertical-align: top;"/><input id="uploadPicture" type="button" class="lightbutton" value="Upload"/><input id="uploadFile" type="file" accept="image/*" style="display:none;"/><span id="refreshingPicture" class="refreshing" style="display:none;"/></td></tr> +<tr><td><img id="userPicture" style="width: 50px; height: 50px; vertical-align: top;"/><input id="uploadPicture" type="button" class="lightbutton" value="Upload"/><input id="uploadFile" type="file" accept="image/*" style="visibility: hidden;"/><span id="refreshingPicture" class="refreshing" style="display:none;"/></td></tr> <tr><tr><td class="label">Name:</td></tr> <tr><td><input type="text" id="userFullname" class="flatentry" size="30" placeholder="Your name" style="width: 300px;"/></td></tr> <tr><tr><td class="label">Bio:</td></tr> @@ -86,7 +86,7 @@ TODO Disabled for now (function layout() { document.title = config.windowtitle() + ' - Account'; $('viewhead').innerHTML = '<span class="cmenu">' + username + '</span>' + - '<input type="button" class="redbutton plusminus" style="position: absolute; top: 4px; left: 5px;" id="deleteUser" value="-" title="Delete your account" disabled="true"/>'; + '<input type="button" class="redbutton plusminus" style="position: absolute; top: 4px; left: 2px;" id="deleteUser" value="-" title="Delete your account" disabled="true"/>'; if (!ui.isMobile()) $('viewform').className = 'viewform flatscrollbars'; $('userName').value = username; @@ -133,7 +133,7 @@ var savedpicxml = ''; var acct = cadr(assoc("'content", acctentry)); var email = assoc("'email", acct); - $('userEmail').value = isNull(email) || isNull(cdr(email))? '' : cadr(email); + $('userEmail').value = isNull(email) || isNull(cdr(email))? (username.indexOf('@') != -1? username : '') : cadr(email); var desc = assoc("'description", acct); $('userDescription').innerHTML = isNull(desc) || isNull(cdr(desc))? '' : cadr(desc); @@ -354,7 +354,7 @@ var lastkeyup = null; $('userFullname').onkeyup = $('userDescription').onkeyup = function() { var t = new Date().getTime(); lastkeyup = t; - ui.delay(function() { + ui.async(function() { return t == lastkeyup? onaccountchange() : true; }, 2000); }; @@ -395,7 +395,7 @@ function readpic(files) { showstatus('Loaded'); // Now upload it - ui.delay(function() { + ui.async(function() { var picentry = mklist("'entry", mklist("'title", username), mklist("'id", username), mklist("'author", username), mklist("'content", mklist("'picture", mklist("'image", url)))); var entryxml = car(atom.writeATOMEntry(valuesToElements(mklist(picentry)))); if (savedpicxml == entryxml) { @@ -429,7 +429,7 @@ function emailpicture() { // Open the email app var mailto = safeb64encode('p/' + username + '/' + token); - ui.navigate('mailto:' + mailto + '@' + topdomainname(window.location.hostname) + '?subject=Email to upload&body=Paste picture here', '_self'); + ui.navigate('mailto:' + mailto + '@' + topdomainname(window.location.hostname) + '?subject=Uploading picture&body=Paste picture here', '_self'); // Refresh app icon refreshingpic = true; @@ -440,11 +440,12 @@ function emailpicture() { /** * Handle picture upload events. */ -$('uploadPicture').onclick = function() { - if (ui.isMobile()) - return emailpicture(); - return $('uploadFile').click(); -}; +ui.onclick($('uploadPicture'), function(e) { + debug('uploadPicture.onclick()'); + if (ui.isMobile() && ((ui.isWebkit() && ui.browserVersion() < 6.0) || (ui.isAndroid() && ui.browserVersion() < 2.2))) + return ui.delay(function() { return emailpicture(); }); + return ui.delay(function() { return $('uploadFile').click(); }); +}); $('uploadFile').onchange = function(e) { return readpic(e.target.files); }; diff --git a/sca-cpp/trunk/hosting/server/htdocs/app/index.html b/sca-cpp/trunk/hosting/server/htdocs/app/index.html index 9ff3a72b0f..108a35ee09 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/app/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/app/index.html @@ -28,11 +28,9 @@ <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="viewport" content="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-precomposed" href="/public/touchicon.png"/> <base href="/"/> <script type="text/javascript"> @@ -311,7 +309,7 @@ function setwidgetvalue(e, dv) { // Define the stylesheet if (s != '') { - var esheet = ui.elementByID(contentdiv, 'style_' + e.id); + var esheet = ui.elementByID(document, 'style_' + e.id); if (isNull(esheet)) { var nesheet = document.createElement('style'); nesheet.id = 'style_' + e.id; @@ -434,7 +432,7 @@ function updatepage(l) { return e; } - map(updatewidget, filter(function(e) { return !isNull(e.id) && e.id.substring(0, 5) != 'page:'; }, nodeList(ui.elementByID(contentdiv, 'page').childNodes))); + map(updatewidget, filter(function(e) { return !isNull(e.id) && e.id.substring(0, 5) != 'page:'; }, nodeList(ui.elementByID(document, 'page').childNodes))); return true; } @@ -464,18 +462,19 @@ function bindwidgethandler(e, appname) { if (e.className == 'button') { var b = car(childElements(e)); b.name = e.id; - b.onclick = function() { return buttonClickHandler(b.value, appname); }; + ui.onclick(b, function(e) { + return buttonClickHandler(b.value, appname); + }); return e; } if (e.className == 'link') { var l = car(childElements(e)); var hr = l.href; if (hr.substring(0, 5) == 'link:' && hr.indexOf('://') == -1) { - var f = function(e) { + ui.onclick(l, function(e) { e.preventDefault(); return buttonClickHandler(hr.substring(5), appname); - }; - l.ontouchstart = l.onclick = f; + }); l.href = 'javascript:void()'; } return e; @@ -609,7 +608,7 @@ function getappdata(appname, page, compos) { } // Setup the widgets - map(setupwidget, filter(function(e) { return !isNull(e.id); }, nodeList(ui.elementByID(contentdiv, 'page').childNodes))); + map(setupwidget, filter(function(e) { return !isNull(e.id); }, nodeList(ui.elementByID(document, 'page').childNodes))); // Get the app components var comps = scdl.components(compos); @@ -720,7 +719,7 @@ function compquery() { return append(nodeList(n.childNodes), reduce(append, mklist(), map(childrenList, nodeList(n.childNodes)))); } - var args = map(queryarg, filter(function(e) { return !isNull(e.id) && !isNull(inputvalue(e)); }, childrenList(ui.elementByID(contentdiv, 'page')))); + var args = map(queryarg, filter(function(e) { return !isNull(e.id) && !isNull(inputvalue(e)); }, childrenList(ui.elementByID(document, 'page')))); // Append current location properties if known if (!isNull(geoposition)) { diff --git a/sca-cpp/trunk/hosting/server/htdocs/clone/index.html b/sca-cpp/trunk/hosting/server/htdocs/clone/index.html index e9de1be1fb..208aea94b8 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/clone/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/clone/index.html @@ -164,9 +164,9 @@ $('cloneAppForm').onsubmit = function() { /** * Cancel cloning an app. */ -$('cloneAppCancelButton').onclick = function() { +ui.onclick($('cloneAppCancelButton'), function(e) { history.back(); -}; +}); })(); </script> diff --git a/sca-cpp/trunk/hosting/server/htdocs/create/index.html b/sca-cpp/trunk/hosting/server/htdocs/create/index.html index 3fc26b8515..daae21202d 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/create/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/create/index.html @@ -72,6 +72,7 @@ function saveapp(name, entryxml) { apps.put(name, savedappxml, function(e) { if (e) { if (e.code && e.code == 404) { + alert('name taken'); errorstatus('App name is taken, please pick another name'); workingstatus(false); return false; @@ -115,6 +116,7 @@ $('createAppForm').onsubmit = function() { // Check reserved app names var reserved = mklist('account', 'app', 'cache', 'clone', 'create', 'delete', 'graph', 'home', 'login', 'new', 'page', 'proxy', 'public', 'private', 'info', 'store'); if (!isNull(assoc(name, map(function(r) { return mklist(r, r); }, reserved)))) { + alert('invalid name'); errorstatus('App name is taken, please pick another name'); return false; } @@ -129,9 +131,9 @@ $('createAppForm').onsubmit = function() { /** * Cancel creating an app. */ -$('createAppCancelButton').onclick = function() { +ui.onclick($('createAppCancelButton'), function(e) { history.back(); -}; +}); /** * Show the status. diff --git a/sca-cpp/trunk/hosting/server/htdocs/delete/index.html b/sca-cpp/trunk/hosting/server/htdocs/delete/index.html index 3855a09e3c..d578842e7b 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/delete/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/delete/index.html @@ -138,9 +138,9 @@ $('deleteAppForm').onsubmit = function() { /** * Cancel cloning an app. */ -$('deleteAppCancelButton').onclick = function() { +ui.onclick($('deleteAppCancelButton'), function(e) { history.back(); -}; +}); })(); </script> diff --git a/sca-cpp/trunk/hosting/server/htdocs/graph/index.html b/sca-cpp/trunk/hosting/server/htdocs/graph/index.html index 557f427e38..d239c3c021 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/graph/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/graph/index.html @@ -2055,7 +2055,7 @@ function showdata(gcomp) { return displaydata(t, '100%'); }); - ui.async(function hidegraphdiv() { + ui.delay(function hidegraphdiv() { graphdiv.style.display = 'none' }); return true; @@ -2071,7 +2071,7 @@ function showgraph(gcomp) { graphdiv.style.display = 'block' gvisible = true; graph.compselect(gcomp, true, atitle, cvalue, ccopy, cdelete); - ui.async(function hideplaydiv() { + ui.delay(function hideplaydiv() { pdiv.style.display = 'none'; pdiv.innerHTML = ''; }); diff --git a/sca-cpp/trunk/hosting/server/htdocs/home/index.html b/sca-cpp/trunk/hosting/server/htdocs/home/index.html index b5240bfd11..c586e54349 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/home/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/home/index.html @@ -32,7 +32,7 @@ <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+ or IE 9+</div> +<div class="note">Requires Safari 6+, Chrome 24+, Firefox 18+ or IE 10+</div> <br/> </div> @@ -51,9 +51,9 @@ $('viewcontent').className = 'viewcontent flatscrollbars'; })(); -$('getstarted').onclick = function() { +ui.onclick($('getstarted'), function(e) { return ui.navigate('/#view=store', '_view'); -}; +}); /** * Display animation. diff --git a/sca-cpp/trunk/hosting/server/htdocs/index.html b/sca-cpp/trunk/hosting/server/htdocs/index.html index 7722f96e3f..a77c59508f 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/index.html @@ -28,11 +28,9 @@ <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="viewport" content="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-precomposed" href="/public/touchicon.png"/> <base href="/"/> <script type="text/javascript"> @@ -174,6 +172,11 @@ var storecat = 'top'; var storeidx = 0; /** + * The current search query. + */ +var searchquery = ''; + +/** * Populate cache with app resources. */ var appresources = [ @@ -329,19 +332,18 @@ 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('menusearch', 'Search', '/#view=search', '_view', view == 'search')), + ui.menu('menusearch', 'Search', '/#view=search&q=' + searchquery, '_view', view == 'search')), (isNull(appname) || appname == 'undefined')? mklist() : mklist( - 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('menuinfo', 'Info', '/#view=info&app=' + appname, '_view', view == 'info'), + ui.menu('menupage', 'Edit', '/#view=page&app=' + appname, '_view', view == 'page'), 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) */ )), - (isNull(appname) || appname == 'undefined')? mklist( + (true || isNull(appname) || appname == 'undefined')? mklist( ui.menufunc('menusignout', 'Sign out', 'return logout();', false), ui.menu('menuaccount', 'Account', '/#view=account', '_view', view == 'account')) : mklist()); @@ -380,12 +382,16 @@ function showview(url) { var uri = '/' + view + '/'; var idx = isNull(params['idx'])? 0 : parseInt(params['idx']); - // Track store category view + // Track store category if (view == 'store') { storecat = isNull(params['category'])? 'top' : params['category']; storeidx = idx; } + // Track search query + if (view == 'search') + searchquery = isNull(params['q'])? '' : params['q']; + // Determine the transition to use var vtransition = uri == viewuri? (idx >= viewidx? 'left' : 'right') : viewtransition(viewuri, uri); @@ -407,7 +413,7 @@ function showview(url) { // Prepare current view for transition out var ovdiv = viewdiv; if (!isNull(ovdiv)) { - ovdiv.skipNode = true; + ui.removeElementIDs(ovdiv); ovdiv.className = 'viewunloading3dm'; } @@ -416,7 +422,6 @@ function showview(url) { var vdoc = appcache.get(uri); vdiv.innerHTML = vdoc; $('viewcontainer').appendChild(vdiv); - map(ui.evalScript, ui.innerScripts(vdiv)); ui.async(function mtransitionview() { // Transition the old view out @@ -425,20 +430,23 @@ function showview(url) { // Transition the new view in vdiv.className = 'viewloaded3dm'; + + ui.async(function mtransitioneval() { + map(ui.evalScript, ui.innerScripts(vdiv)); + }); }); } else { // Prepare current view for transition out var ovdiv = viewdiv; if (!isNull(ovdiv)) - ovdiv.skipNode = true; + ui.removeElementIDs(ovdiv); // Load the requested doc into the view var vdiv = mkviewdiv('viewloading3d'); var vdoc = appcache.get(uri); vdiv.innerHTML = vdoc; $('viewcontainer').appendChild(vdiv); - map(ui.evalScript, ui.innerScripts(vdiv)); ui.async(function transitionview() { // Transition the new view in @@ -447,6 +455,10 @@ function showview(url) { // Transition the old view out if (!isNull(ovdiv)) ovdiv.parentNode.removeChild(ovdiv); + + ui.async(function mtransitioneval() { + map(ui.evalScript, ui.innerScripts(vdiv)); + }); }); } @@ -622,7 +634,7 @@ document.body.onorientationchange = function(e) { //debug('appcache iframe loaded'); }; - ui.delay(function() { + ui.async(function() { $('installer').innerHTML = '<iframe src="/cache/" class="installer"></iframe>'; }); @@ -639,10 +651,10 @@ document.body.onorientationchange = function(e) { } //debug('cache-manifest changed, reloading'); - ui.delay(function() { + ui.async(function() { workingstatus(true); showstatus('Updating'); - ui.delay(function() { + ui.async(function() { workingstatus(true); showstatus('Updating'); map(function(res) { diff --git a/sca-cpp/trunk/hosting/server/htdocs/info/index.html b/sca-cpp/trunk/hosting/server/htdocs/info/index.html index 3038d37cf2..5143808523 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/info/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/info/index.html @@ -26,7 +26,7 @@ <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><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="visibility: hidden;"/><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> @@ -55,12 +55,11 @@ var appname = ui.fragmentParams(location)['app']; */ (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>'; + $('viewhead').innerHTML = '<span id="appname" class="cmenu">' + appname + + '<input type="button" class="redbutton plusminus" style="position: absolute; top: 4px; left: 2px;" id="deleteApp" value="-" title="Delete this app" disabled="true"/>' + + '<input type="button" class="bluebutton" id="editApp" style="position: absolute; top: 4px; right: 72px;" value="Edit" title="Edit this app" disabled="true"/>' + + '<input type="button" class="greenbutton plusminus" id="runApp" style="position: absolute; top: 4px; right: 37px;" value=">" title="Run this app"/>' + + '<input type="button" class="bluebutton" style="position: absolute; top: 4px; right: 2px; font-size: 16px;" id="cloneApp" value="C" title="' + config.clone() + ' this app"/>'; if (!ui.isMobile()) $('viewform').className = 'viewform flatscrollbars'; $('appURL').value = window.location.hostname + '/' + appname + '/'; @@ -133,9 +132,13 @@ var savediconxml; $('appDescription').className = 'flatentry'; $('uploadIcon').style.display = 'inline'; $('deleteApp').disabled = false; - $('deleteApp').onclick = function() { + $('editApp').disabled = false; + ui.onclick($('editApp'), function(e) { + return ui.navigate('/#view=page&app=' + appname, '_view'); + }); + ui.onclick($('deleteApp'), function(e) { return ui.navigate('/#view=delete&app=' + appname, '_view'); - } + }); onlinestatus(); } else { showstatus('Read only'); @@ -360,7 +363,7 @@ var lastkeyup = null; $('appDescription').onkeyup = function() { var t = new Date().getTime(); lastkeyup = t; - ui.delay(function() { + ui.async(function() { return t == lastkeyup? onappchange() : true; }, 2000); }; @@ -376,16 +379,16 @@ $('appForm').onsubmit = function() { /** * Handle Clone button event. */ -$('cloneApp').onclick = function() { +ui.onclick($('cloneApp'), function(e) { return ui.navigate('/#view=clone&app=' + appname, '_view'); -}; +}); /** * Handle Run button event. */ -$('runApp').onclick = function() { +ui.onclick($('runApp'), function(e) { return ui.navigate('/' + appname + '/', '_blank'); -}; +}); /** * Read and upload icon file. @@ -417,7 +420,7 @@ function uploadicon(files) { showstatus('Loaded'); // Now upload it - ui.delay(function() { + ui.async(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) { @@ -451,7 +454,7 @@ function emailicon() { // 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'); + ui.navigate('mailto:' + mailto + '@' + topdomainname(window.location.hostname) + '?subject=Uploading icon&body=Paste icon here', '_self'); // Refresh app icon refreshingicon = true; @@ -462,11 +465,11 @@ function emailicon() { /** * Handle icon upload events. */ -$('uploadIcon').onclick = function() { - if (ui.isMobile()) - return emailicon(); - return $('uploadFile').click(); -}; +ui.onclick($('uploadIcon'), function(e) { + if (ui.isMobile() && ((ui.isWebkit() && ui.browserVersion() < 6.0) || (ui.isAndroid() && ui.browserVersion() < 2.2))) + return ui.delay(function() { return emailicon(); }); + return ui.delay(function() { return $('uploadFile').click(); }); +}); $('uploadFile').onchange = function(e) { return uploadicon(e.target.files); }; @@ -484,9 +487,9 @@ $('appIcon').ondrop = function(e) { /** * Handle rate button event. */ -$('rateApp').onclick = function() { +ui.onclick($('rateApp'), function(e) { return ui.navigate('/#view=rate&app=' + appname, '_view'); -}; +}); })(); </script> diff --git a/sca-cpp/trunk/hosting/server/htdocs/login/index.html b/sca-cpp/trunk/hosting/server/htdocs/login/index.html index 93d47d3f28..10e7b34d04 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/login/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/login/index.html @@ -28,11 +28,9 @@ <script src="http://www.example.com:9998/target/target-script-min.js#anonymous"></script> --> <title>Sign in</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="viewport" content="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-precomposed" href="/public/touchicon.png"/> <base href="/login/"/> <script type="text/javascript"> @@ -137,7 +135,7 @@ ui.includeCSS(appcache.get('/ui-min.css')); <tr><td><span id="loginprompt" style="font-size: 16px;"></span></tr></td> <tr><td><input type="text" class="flatentry" name="httpd_username" value="" placeholder="Username or email"/></td></tr> <tr><td><input type="password" class="flatentry" name="httpd_password" value="" placeholder="Password"/></td></tr> -<tr><td><input type="submit" class="bluebutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px" value="Sign in"/></td></tr> +<tr><td><input type="submit" class="bluebutton" style="font-size: 16px; line-height: 16px;" value="Sign in"/></td></tr> </table> <input type="hidden" name="httpd_location" value="/"/> </form> @@ -146,7 +144,7 @@ ui.includeCSS(appcache.get('/ui-min.css')); <form name="facebookOAuth2Form" style="width: 100%;"> <table style="width: 100%;"> <tr><td><span style="font-size: 16px;">Sign in with your <span style="font-weight: bold;">Facebook</span> account</span></td></tr> -<tr><td><input type="button" id="facebookOAuth2Signin" value="Sign in" class="bluebutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px"/></td></tr> +<tr><td><input type="button" id="facebookOAuth2Signin" value="Sign in" class="bluebutton" style="font-size: 16px;"/></td></tr> </table> </form> <br/> @@ -154,7 +152,7 @@ ui.includeCSS(appcache.get('/ui-min.css')); <form name="googleOAuth2Form" style="width: 100%;"> <table style="width: 100%;"> <tr><td><span style="font-size: 16px;">Sign in with your <span style="font-weight: bold;" >Google</span> account</span></td></tr> -<tr><td><input type="button" id="googleOAuth2Signin" value="Sign in" class="bluebutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px"/></td></tr> +<tr><td><input type="button" id="googleOAuth2Signin" value="Sign in" class="bluebutton" style="font-size: 16px;"/></td></tr> </table> </form> <br/> @@ -194,7 +192,7 @@ try { $('loginprompt').innerHTML = config.loginprompt(); document.title = config.windowtitle() + ' - Sign in'; $('viewhead').innerHTML = '<span class="bcmenu">' + config.pagetitle() + '</span>' + - '<span class="rmenu"><input type="button" id="signUp" class="redbutton" style="font-size: 16px; line-height: 16px; padding: 6px; height: 32px" title="' + config.signuptitle() + '" value="Sign up"/></span>'; + '<input type="button" id="signUp" class="redbutton" style="position: absolute; top: 4px; right: 2px; font-size: 16px;" title="' + config.signuptitle() + '" value="Sign up"/>'; if (!ui.isMobile()) $('viewcontent').className = 'viewcontent flatscrollbars'; $('status').className = ui.isMobile()? 'status3dm' : 'status3d'; @@ -337,13 +335,13 @@ function withgoogle() { return parms; } -$('facebookOAuth2Signin').onclick = function() { +ui.onclick($('facebookOAuth2Signin'), function(e) { return submitoauth2signin(withfacebook); -}; +}); -$('googleOAuth2Signin').onclick = function() { +ui.onclick($('googleOAuth2Signin'), function(e) { return submitoauth2signin(withgoogle); -}; +}); /** * Signin with a username and password. @@ -356,9 +354,9 @@ $('formSignin').onsubmit = function submitformsignin() { /** * Signup. */ -$('signUp').onclick = function submitsignup() { +ui.onclick($('signUp'), function submitsignup(e) { ui.navigate('/public/notyet/', '_self'); -}; +}); /** * Handle orientation change. @@ -442,7 +440,7 @@ var appresources = [ //debug('appcache iframe loaded'); }; - ui.delay(function() { + ui.async(function() { $('installer').innerHTML = '<iframe src="/public/cache/" class="installer"></iframe>'; }); @@ -459,10 +457,10 @@ var appresources = [ } //debug('cache-manifest changed, reloading'); - ui.delay(function() { + ui.async(function() { workingstatus(true); showstatus('Updating'); - ui.delay(function() { + ui.async(function() { workingstatus(true); showstatus('Updating'); map(function(res) { diff --git a/sca-cpp/trunk/hosting/server/htdocs/page/index.html b/sca-cpp/trunk/hosting/server/htdocs/page/index.html index ca89ed34db..3834640dbc 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/page/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/page/index.html @@ -95,11 +95,12 @@ var appname = ui.fragmentParams(location)['app']; document.title = config.windowtitle() + ' - Page - ' + appname; $('viewhead').innerHTML = '<span id="appTitle" class="cmenu">' + appname + '</span>' + - '<input type="button" id="deleteWidgetButton" title="Delete a Widget" 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="widgetValue" type="text" value="" class="flatentry" title="Widget value" autocapitalize="off" placeholder="Value" style="position: absolute; left: 0px; top: 4px; width: 100%; display: none;" readonly="readonly"/></span>' + - '<input type="button" id="playPageButton" title="View page" class="greenbutton plusminus" style="position: absolute; top: 4px; right: 75px;" value=">"/>' + - '<input type="button" id="copyWidgetButton" title="Copy a Widget" class="bluebutton" style="position: absolute; top: 4px; right: 40px; font-size: 16px;" disabled="true" value="C"/>' + - '<input type="button" id="addWidgetButton" title="Add a Widget" class="bluebutton plusminus" style="position: absolute; top: 4px; right: 5px;" disabled="true" value="+"/>'; + '<input type="button" id="deleteWidgetButton" title="Delete a widget" class="redbutton plusminus" style="position: absolute; top: 4px; left: 2px;" disabled="true" value="-"/>' + + '<span style="position: absolute; top: 0px; left: 37px; right: 110px; padding: 0px; background: transparent;"><input id="widgetValue" type="text" value="" class="flatentry" title="Widget value" autocapitalize="off" placeholder="Value" style="position: absolute; left: 0px; top: 4px; width: 100%; display: none;" readonly="readonly"/></span>' + + '<input type="button" id="playPageButton" title="View page" class="greenbutton plusminus" style="position: absolute; top: 4px; right: 72px;" value=">"/>' + + '<input type="button" id="copyWidgetButton" title="Copy a widget" class="bluebutton" style="position: absolute; top: 4px; right: 37px; font-size: 16px;" disabled="true" value="C"/>' + + '<input type="button" id="addWidgetButton" title="Add a widget" class="bluebutton plusminus" style="position: absolute; top: 4px; right: 2px;" disabled="true" value="+"/>'; + //'<input type="button" id="appInfoButton" title="View app info" class="bluebutton" style="position: absolute; top: 4px; right: 2px; font-size: 16px;" value="i"/>'; if (ui.isMobile()) { $('palettecontainer').className = 'palettecontainer3dm'; @@ -606,7 +607,7 @@ function showpalette() { $('paletteview').className = 'paletteloading3dm'; $('paletteview').style.display = 'block'; $('paletteview').visible = true; - ui.async(function transitionview() { + ui.delay(function transitionview() { $('paletteview').className = 'paletteloaded3dm'; }); } else { @@ -624,7 +625,7 @@ function hidepalette() { if (ui.isMobile()) { $('paletteview').className = 'paletteunloading3dm'; $('paletteview').visible = false; - ui.async(function transitionview() { + ui.delay(function transitionview() { $('paletteview').className = 'paletteunloaded3dm'; }); } else { @@ -675,7 +676,7 @@ function mkeditor() { return save(newxml); // Autosave other changes after 1 second - ui.delay(function autosave() { + ui.async(function autosave() { if (savedxhtml == newxml) { showstatus('Saved'); return false; @@ -806,14 +807,6 @@ function mkeditor() { moved = false; return onmousedown(e); }; - $('pagediv').addEventListener('touchstart', function(e) { - //debug('ontouchstart'); - mdown = true; - moveX = e.touches[0].clientX; - moveY = e.touches[0].clientY; - moved = false; - return onmousedown(e); - }, false); $('palettecontent').ontouchstart = function(e) { //debug('ontouchstart'); mdown = true; @@ -977,24 +970,6 @@ function mkeditor() { return true; } - /* - if (!ui.isMobile()) { - $('pagediv').onclick = function(e) { - //debug('onclick'); - moveX = e.clientX; - moveY = e.clientY; - return onclick(e); - }; - } else { - window.onclick = function(e) { - //debug('onclick'); - moveX = e.touches[0].clientX; - moveY = e.touches[0].clientY; - return onclick(e); - }; - } - */ - /** * Handle field on change events. */ @@ -1009,16 +984,16 @@ function mkeditor() { }; // Handle add widget event. - $('addWidgetButton').onclick = function() { + ui.onclick($('addWidgetButton'), function(e) { // Show / hide the palette if ($('paletteview').visible) return hidepalette(); return showpalette(); - }; + }); // Handle delete event. - $('deleteWidgetButton').onclick = function() { + ui.onclick($('deleteWidgetButton'), function(e) { if (selected == null) return false; @@ -1035,10 +1010,10 @@ function mkeditor() { // Trigger page change event onpagechange(true); return false; - }; + }); // Handle copy event. - $('copyWidgetButton').onclick = function() { + ui.onclick($('copyWidgetButton'), function(e) { if (selected == null) return false; if (selected.id.substring(0, 8) == 'palette:') @@ -1068,18 +1043,18 @@ function mkeditor() { // Trigger page change event onpagechange(true); return false; - }; + }); /** - * Handle play page button event. - */ - $('playPageButton').onclick = function() { + * Handle play page button event. + */ + ui.onclick($('playPageButton'), function(e) { // Show / hide the page play frame if ($('playdiv').visible) return showeditor(); return showplaying(); - } + }); // Show the editor showeditor(); @@ -1234,6 +1209,15 @@ function save(newxml) { }; /** + * Handle app info button event. + */ +/* Disabled for now. +ui.onclick($('appInfoButton'), function(e) { + return ui.navigate('/#view=info&app=' + appname, '_view'); +}); +*/ + +/** * Initialize the page editor. */ mkeditor(); diff --git a/sca-cpp/trunk/hosting/server/htdocs/proxy/public/oops/index.html b/sca-cpp/trunk/hosting/server/htdocs/proxy/public/oops/index.html index f7cdab9bf2..6d3b8b21aa 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/proxy/public/oops/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/proxy/public/oops/index.html @@ -28,11 +28,9 @@ <script src="http://www.example.com:9998/target/target-script-min.js#anonymous"></script> --> <title>Oops</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="viewport" content="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-precomposed" href="/proxy/public/touchicon.png"/> <base href="/proxy/public/oops/"/> <script type="text/javascript"> @@ -305,7 +303,7 @@ var appresources = [ //debug('appcache iframe loaded'); }; - ui.delay(function() { + ui.async(function() { $('installer').innerHTML = '<iframe src="/proxy/public/cache/" class="installer"></iframe>'; }); @@ -322,9 +320,9 @@ var appresources = [ } //debug('cache-manifest changed, reloading'); - ui.delay(function() { + ui.async(function() { showstatus('Updating'); - ui.delay(function() { + ui.async(function() { map(function(res) { appcache.remove(res[0]); appcache.get(res[0], 'remote'); diff --git a/sca-cpp/trunk/hosting/server/htdocs/public/notauth/index.html b/sca-cpp/trunk/hosting/server/htdocs/public/notauth/index.html index cf5f3465d8..2cfd72e5b1 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/public/notauth/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/public/notauth/index.html @@ -28,11 +28,9 @@ <script src="http://www.example.com:9998/target/target-script-min.js#anonymous"></script> --> <title>Sorry</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="viewport" content="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-precomposed" href="/public/touchicon.png"/> <base href="/public/notauth/"/> <script type="text/javascript"> @@ -304,7 +302,7 @@ var appresources = [ //debug('appcache iframe loaded'); }; - ui.delay(function() { + ui.async(function() { $('installer').innerHTML = '<iframe src="/public/cache/" class="installer"></iframe>'; }); @@ -321,9 +319,9 @@ var appresources = [ } //debug('cache-manifest changed, reloading'); - ui.delay(function() { + ui.async(function() { showstatus('Updating'); - ui.delay(function() { + ui.async(function() { map(function(res) { appcache.remove(res[0]); appcache.get(res[0], 'remote'); diff --git a/sca-cpp/trunk/hosting/server/htdocs/public/notfound/index.html b/sca-cpp/trunk/hosting/server/htdocs/public/notfound/index.html index ba82ecb897..728319daf3 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/public/notfound/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/public/notfound/index.html @@ -28,11 +28,9 @@ <script src="http://www.example.com:9998/target/target-script-min.js#anonymous"></script> --> <title>Page not found</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="viewport" content="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-precomposed" href="/public/touchicon.png"/> <base href="/public/notfound/"/> <script type="text/javascript"> @@ -305,7 +303,7 @@ var appresources = [ //debug('appcache iframe loaded'); }; - ui.delay(function() { + ui.async(function() { $('installer').innerHTML = '<iframe src="/public/cache/" class="installer"></iframe>'; }); @@ -322,9 +320,9 @@ var appresources = [ } //debug('cache-manifest changed, reloading'); - ui.delay(function() { + ui.async(function() { showstatus('Updating'); - ui.delay(function() { + ui.async(function() { map(function(res) { appcache.remove(res[0]); appcache.get(res[0], 'remote'); diff --git a/sca-cpp/trunk/hosting/server/htdocs/public/notyet/index.html b/sca-cpp/trunk/hosting/server/htdocs/public/notyet/index.html index 0597d10942..02d8f846cf 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/public/notyet/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/public/notyet/index.html @@ -28,11 +28,9 @@ <script src="http://www.example.com:9998/target/target-script-min.js#anonymous"></script> --> <title>Page not found</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="viewport" content="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-precomposed" href="/public/touchicon.png"/> <base href="/public/notyet/"/> <script type="text/javascript"> @@ -305,7 +303,7 @@ var appresources = [ //debug('appcache iframe loaded'); }; - ui.delay(function() { + ui.async(function() { $('installer').innerHTML = '<iframe src="/public/cache/" class="installer"></iframe>'; }); @@ -322,9 +320,9 @@ var appresources = [ } //debug('cache-manifest changed, reloading'); - ui.delay(function() { + ui.async(function() { showstatus('Updating'); - ui.delay(function() { + ui.async(function() { map(function(res) { appcache.remove(res[0]); appcache.get(res[0], 'remote'); diff --git a/sca-cpp/trunk/hosting/server/htdocs/public/oops/index.html b/sca-cpp/trunk/hosting/server/htdocs/public/oops/index.html index 788435289f..ba9f563a5f 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/public/oops/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/public/oops/index.html @@ -28,11 +28,9 @@ <script src="http://www.example.com:9998/target/target-script-min.js#anonymous"></script> --> <title>Oops</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="viewport" content="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-precomposed" href="/public/touchicon.png"/> <base href="/public/oops/"/> <script type="text/javascript"> @@ -304,7 +302,7 @@ var appresources = [ //debug('appcache iframe loaded'); }; - ui.delay(function() { + ui.async(function() { $('installer').innerHTML = '<iframe src="/public/cache/" class="installer"></iframe>'; }); @@ -321,9 +319,9 @@ var appresources = [ } //debug('cache-manifest changed, reloading'); - ui.delay(function() { + ui.async(function() { showstatus('Updating'); - ui.delay(function() { + ui.async(function() { map(function(res) { appcache.remove(res[0]); appcache.get(res[0], 'remote'); diff --git a/sca-cpp/trunk/hosting/server/htdocs/rate/index.html b/sca-cpp/trunk/hosting/server/htdocs/rate/index.html index 90d45bd3ea..f5211ca23c 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/rate/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/rate/index.html @@ -82,14 +82,14 @@ var reviews = sca.reference(editorComp, "reviews"); * Initialize the rate buttons. */ var rateAppButtons = [ - [$('rateApp1'), 1, function() { return onclickrating(1); }, 'Don\'t like it'], - [$('rateApp2'), 2, function() { return onclickrating(2); }, 'It\'s ok'], - [$('rateApp3'), 3, function() { return onclickrating(3); }, 'It\'s good'], - [$('rateApp4'), 4, function() { return onclickrating(4); }, 'It\'s great'] + [$('rateApp1'), 1, function(e) { return onclickrating(1); }, 'Don\'t like it'], + [$('rateApp2'), 2, function(e) { return onclickrating(2); }, 'It\'s ok'], + [$('rateApp3'), 3, function(e) { return onclickrating(3); }, 'It\'s good'], + [$('rateApp4'), 4, function(e) { return onclickrating(4); }, 'It\'s great'] ]; (function initRateAppButtons() { map(function(b) { - b[0].onclick = b[2]; + ui.onclick(b[0], b[2]); }, rateAppButtons); })(); @@ -180,9 +180,9 @@ function onclickrating(r) { /** * Navigate back. */ -$('rateAppDoneButton').onclick = function() { +ui.onclick($('rateAppDoneButton'), function(e) { history.back(); -}; +}); })(); </script> diff --git a/sca-cpp/trunk/hosting/server/htdocs/search/index.html b/sca-cpp/trunk/hosting/server/htdocs/search/index.html index d46b0528c4..d50b492640 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/search/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/search/index.html @@ -38,8 +38,8 @@ $('viewcontent').className = 'viewcontent flatscrollbars'; $('viewhead').innerHTML = '<form id="searchForm">' + - '<span style="position: absolute; top: 0px; left: 5px; right: 70px; padding: 0px; background: transparent;"><input type="text" id="searchQuery" value="" class="flatentry" title="Search" autocapitalize="off" placeholder="Search for apps" style="position: absolute; left: 0px; top: 4px; width: 100%;"></span>' + - '<input type="submit" id="searchButton" title="Search" class="bluebutton search" style="position: absolute; top: 4px; right: 5px; width: 60px; background-position: center center; background-repeat: no-repeat; background-image: url(\'' + ui.b64png(appcache.get('/public/search.b64')) + '\');" value=" "/>' + + '<span style="position: absolute; top: 0px; left: 2px; right: 70px; padding: 0px; background: transparent;"><input type="text" id="searchQuery" value="" class="flatentry" title="Search" autocapitalize="off" placeholder="Search for apps" style="position: absolute; left: 0px; top: 4px; width: 100%;"></span>' + + '<input type="submit" id="searchButton" title="Search" class="bluebutton search" style="position: absolute; top: 4px; right: 2px; width: 60px; background-position: center center; background-repeat: no-repeat; background-image: url(\'' + ui.b64png(appcache.get('/public/search.b64')) + '\');" value=" "/>' + '</form>'; $('viewcontent').appendChild(ui.declareCSS( @@ -50,6 +50,11 @@ })(); /** + * Get the requested search query. + */ +var query = ui.fragmentParams(location)['q']; + +/** * Initialize service references. */ var editorComp = sca.component("Editor"); @@ -186,10 +191,16 @@ $('searchForm').onsubmit = function() { return false; if (ui.isMobile()) $('searchQuery').blur(); - getapps($('searchQuery').value.trim()); + //getapps($('searchQuery').value.trim()); + ui.navigate('/#view=search&q=' + $('searchQuery').value.trim(), '_view'); return false; }; +if(query && query != '') { + $('searchQuery').value = query; + getapps(query); +} + })(); </script> diff --git a/sca-cpp/trunk/hosting/server/htdocs/store/index.html b/sca-cpp/trunk/hosting/server/htdocs/store/index.html index 57920ede2e..b64e3de1ba 100644 --- a/sca-cpp/trunk/hosting/server/htdocs/store/index.html +++ b/sca-cpp/trunk/hosting/server/htdocs/store/index.html @@ -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 catmenu() { 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. diff --git a/sca-cpp/trunk/hosting/server/icons.py b/sca-cpp/trunk/hosting/server/icons.py index d9fbcab448..a7d63348b3 100644 --- a/sca-cpp/trunk/hosting/server/icons.py +++ b/sca-cpp/trunk/hosting/server/icons.py @@ -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) diff --git a/sca-cpp/trunk/hosting/server/pages.py b/sca-cpp/trunk/hosting/server/pages.py index 3d353279ba..cb6a33621a 100644 --- a/sca-cpp/trunk/hosting/server/pages.py +++ b/sca-cpp/trunk/hosting/server/pages.py @@ -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) diff --git a/sca-cpp/trunk/hosting/server/ratings.py b/sca-cpp/trunk/hosting/server/ratings.py index d36dcad45e..f1edeeecb6 100644 --- a/sca-cpp/trunk/hosting/server/ratings.py +++ b/sca-cpp/trunk/hosting/server/ratings.py @@ -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 diff --git a/sca-cpp/trunk/hosting/server/server.composite b/sca-cpp/trunk/hosting/server/server.composite index b3b95fb6b2..51234a20bb 100644 --- a/sca-cpp/trunk/hosting/server/server.composite +++ b/sca-cpp/trunk/hosting/server/server.composite @@ -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"/> diff --git a/sca-cpp/trunk/hosting/server/store.py b/sca-cpp/trunk/hosting/server/store.py index aac233f877..732e699e84 100644 --- a/sca-cpp/trunk/hosting/server/store.py +++ b/sca-cpp/trunk/hosting/server/store.py @@ -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): diff --git a/sca-cpp/trunk/hosting/server/test.py b/sca-cpp/trunk/hosting/server/test.py index 5670ec2ea9..0e95c45518 100755 --- a/sca-cpp/trunk/hosting/server/test.py +++ b/sca-cpp/trunk/hosting/server/test.py @@ -98,7 +98,7 @@ def testPages(): # Put and get a page cache1 = mkcache('cache', {}) page1updated = (("'entry", ("'title", 'app1'), ("'id", 'app1'), ("'author", 'jdoe@example.com'), ("'updated", '2012-01-01T00:00:00+00:00'), ("'content",)),) - assert pages.put(('app1',), page1, mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == True + assert pages.put(('app1',), page1, mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id, app = None: app1 if app is None else True)) == True assert pages.get(('app1',), mkref('user', lambda id: 'jdoe@example.com'), 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: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == page1updated # Delete a page - assert pages.delete(('app1',), mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == True + assert pages.delete(('app1',), mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id, app = None: app1 if app is None else True)) == True assert pages.get(('app1',), mkref('user', lambda id: 'jdoe@example.com'), 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", 'jdoe@example.com'), ("'updated", '2012-01-01T00:00:00+00:00'), ("'content", ("'icon", ("'image", img50)))),) - assert icons.put(('app1',), icon1, mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == True + assert icons.put(('app1',), icon1, mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id, app = None: app1 if app is None else True)) == True assert icons.get(('app1',), mkref('user', lambda id: 'jdoe@example.com'), 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", 'jdoe@example.com'), ("'updated", '2012-01-01T00:00:00+00:00'), ("'content", ("'icon", ("'image", img50), ("'token", '1234')))),) - assert icons.put(('app1',), icon1oktoken, mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == True + assert icons.put(('app1',), icon1oktoken, mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id, app = None: app1 if app is None else True)) == True assert icons.get(('app1',), mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == icon1updated # Delete a icon - assert icons.delete(('app1',), mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == True + assert icons.delete(('app1',), mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id, app = None: app1 if app is None else True)) == True assert icons.get(('app1',), mkref('user', lambda id: 'jdoe@example.com'), 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", 'jdoe@example.com'), ("'updated", '2012-01-01T00:00:00+00:00'), ("'content",)),) - assert composites.put(('app1',), composite1, mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == True + assert composites.put(('app1',), composite1, mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id, app = None: app1 if app is None else True)) == True assert composites.get(('app1',), mkref('user', lambda id: 'jdoe@example.com'), 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: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == composite1updated # Delete a composite - assert composites.delete(('app1',), mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == True + assert composites.delete(('app1',), mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id, app = None: app1 if app is None else True)) == True assert composites.get(('app1',), mkref('user', lambda id: 'jdoe@example.com'), cache1, mkref('apps', lambda id: app1)) == defcompositefromapp return True def testApps(): # Get default app - assert apps.get(('app1',), mkref('user', lambda id: 'jdoe@example.com'), 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: 'jdoe@example.com'), 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", 'jdoe@example.com'), ("'updated", '2012-01-01T00:00:00+00:00'), ("'content", ("'info", ("'description", '')))),) - assert apps.get(('app1',), mkref('user', lambda id: 'jdoe@example.com'), 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: 'jdoe@example.com'), 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: 'jdoe@example.com'), 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: 'jdoe@example.com'), 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: 'jdoe@example.com'), 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: 'jdoe@example.com'), 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", 'jane@example.com'), ("'updated", '2012-01-03T00:00:00+00:00'), ("'content",)),) - assert apps.put(('app1',), app1, mkref('user', lambda id: 'jane@example.com'), 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: 'jane@example.com'), 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: 'jane@example.com'), 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: 'jane@example.com'), 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: 'jane@example.com'), 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: 'jane@example.com'), 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: 'jane@example.com'), 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: 'jane@example.com'), 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: 'jdoe@example.com'), 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: 'jdoe@example.com'), 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: 'jdoe@example.com'), 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: 'jdoe@example.com'), 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(): diff --git a/sca-cpp/trunk/modules/js/htdocs/component.js b/sca-cpp/trunk/modules/js/htdocs/component.js index a34ebfac92..0a8ec5f5d5 100644 --- a/sca-cpp/trunk/modules/js/htdocs/component.js +++ b/sca-cpp/trunk/modules/js/htdocs/component.js @@ -184,43 +184,113 @@ HTTPBindingClient.jsonResult = function(http) { }; /** - * 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); + + // 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); + } + } + } - // Run the first request in the queue - var req = HTTPBindingClient.queuedRequests.shift(); - HTTPBindingClient.runningRequests++; - setTimeout(function runAsyncRequest() { + // 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 = function(req) { // 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 = function(req) { // 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 = function(id, cb, mode) { 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 = function(id, cb, mode) { // 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 = function(id, cb, mode) { } 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 = function(id, cb, mode) { // Send the request http.send(null); return true; - }); + }, true); } // Call synchronously and return the result or exception @@ -477,7 +545,8 @@ HTTPBindingClient.prototype.get = function(id, cb, mode) { 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 = function (entry, cb) { // 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 = function (entry, cb) { // Send the request http.send(entry); return true; - }); + }, false); } // Call synchronously @@ -562,8 +630,7 @@ HTTPBindingClient.prototype.put = function(id, entry, cb, mode) { // 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 = function(id, entry, cb, mode) { // Send the request http.send(entry); return true; - }); + }, false); } // Call synchronously @@ -640,8 +707,7 @@ HTTPBindingClient.prototype.del = function(id, cb, mode) { // 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 = function(id, cb, mode) { // Send the request http.send(null); return true; - }); + }, false); } // Call synchronously diff --git a/sca-cpp/trunk/modules/js/htdocs/ui.js b/sca-cpp/trunk/modules/js/htdocs/ui.js index 3aa9e1052a..2bd21f6ed4 100644 --- a/sca-cpp/trunk/modules/js/htdocs/ui.js +++ b/sca-cpp/trunk/modules/js/htdocs/ui.js @@ -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, hilight) { 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) |