You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cordova.apache.org by br...@apache.org on 2013/06/25 20:58:02 UTC

[4/9] git commit: Restyle to use Topcoat, popup notifications, and better UX.

Restyle to use Topcoat, popup notifications, and better UX.


Project: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/repo
Commit: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/commit/d871da2a
Tree: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/tree/d871da2a
Diff: http://git-wip-us.apache.org/repos/asf/cordova-app-harness/diff/d871da2a

Branch: refs/heads/master
Commit: d871da2aca9297d6545b10e576e119d66f72a550
Parents: 9b881f4
Author: Braden Shepherdson <br...@gmail.com>
Authored: Wed Jun 19 16:02:16 2013 -0400
Committer: Braden Shepherdson <br...@gmail.com>
Committed: Thu Jun 20 10:43:56 2013 -0400

----------------------------------------------------------------------
 www/cdvah_index.html                 |  16 ++++-
 www/cdvah_js/AddCtrl.js              |  18 +++---
 www/cdvah_js/ListCtrl.js             |  22 ++++---
 www/cdvah_js/Notify.js               |  40 +++++++++++++
 www/cdvah_js/app.js                  |   2 +-
 www/cdvah_views/add.html             |  15 ++---
 www/cdvah_views/list.html            |  27 +++++----
 www/css/style.css                    |  30 ++++++++++
 www/css/topcoat-mobile-light.min.css |   1 +
 www/font/LICENSE.txt                 |  93 ++++++++++++++++++++++++++++++
 www/font/SourceSansPro-Light.otf     | Bin 0 -> 98972 bytes
 www/font/SourceSansPro-Regular.otf   | Bin 0 -> 101820 bytes
 www/font/SourceSansPro-Semibold.otf  | Bin 0 -> 101772 bytes
 13 files changed, 226 insertions(+), 38 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_index.html
----------------------------------------------------------------------
diff --git a/www/cdvah_index.html b/www/cdvah_index.html
index 8850f80..64787aa 100644
--- a/www/cdvah_index.html
+++ b/www/cdvah_index.html
@@ -16,7 +16,19 @@
         <script type="text/javascript" src="cdvah_js/CdvhPackageHandler.js"></script>
         <script type="text/javascript" src="cdvah_js/ListCtrl.js"></script>
         <script type="text/javascript" src="cdvah_js/AddCtrl.js"></script>
+        <script type="text/javascript" src="cdvah_js/Notify.js"></script>
+        <link rel="stylesheet" type="text/css" href="css/topcoat-mobile-light.min.css" />
+        <link rel="stylesheet" type="text/css" href="css/style.css" />
     </head>
-    <body ng-app="CordovaAppHarness" ng-view>
+    <body ng-app="CordovaAppHarness">
+        <div class="topcoat-navigation-bar">
+            <div class="topcoat-navigation-bar__item center full">
+                <h1 class="topcoat-navigation-bar__title">{{ appTitle }}</h1>
+            </div>
+        </div>
+
+        <cdvah-notify></cdvah-notify>
+
+        <div ng-view></div>
     </body>
-</html>
\ No newline at end of file
+</html>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_js/AddCtrl.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/AddCtrl.js b/www/cdvah_js/AddCtrl.js
index 4fc52a4..394531c 100644
--- a/www/cdvah_js/AddCtrl.js
+++ b/www/cdvah_js/AddCtrl.js
@@ -1,7 +1,9 @@
 (function(){
     "use strict";
     /* global myApp */
-    myApp.controller("AddCtrl", ["$scope", "AppsService", function ($scope, AppsService) {
+    myApp.controller("AddCtrl", ["notifier", "$rootScope", "$scope", "$location", "AppsService", function (notifier, $rootScope, $scope, $location, AppsService) {
+
+        $rootScope.appTitle = 'Add App';
 
         $scope.appData = {
             appName : "",
@@ -14,13 +16,13 @@
             var serviceCall;
             if($scope.appData.appSource === "pattern") {
                 if(!$scope.appData.appSourcePattern) {
-                    alert("Url of package not specified");
+                    notifier.error('Url of package not specified');
                     return;
                 }
                 serviceCall = AppsService.addAppFromPattern($scope.appData.appName, $scope.appData.appSourcePattern);
             } else if($scope.appData.appSource === "serve") {
                 if(!$scope.appData.appSourceServe) {
-                    alert("Url of config file not specified");
+                    notifier.error('Url of config file not specified');
                     return;
                 }
                 serviceCall = AppsService.addAppFromServe($scope.appData.appName, $scope.appData.appSourceServe);
@@ -28,15 +30,15 @@
 
             if(serviceCall){
                 serviceCall.then(function() {
-                    alert("Successfully installed");
+                    console.log('successfully installed');
+                    notifier.success('Successfully installed');
                 }, function(error) {
                     console.error(error);
-                    alert("Unable to add application because: \n" + error);
+                    notifier.error('Unable to add application because: ' + error.message);
                 });
             } else {
-                alert("Add application error: Unrecognized application source - " + $scope.appData.appSource);
+                notifier.error('Error adding application: Unrecognized application source: ' + $scope.appData.appSource);
             }
         };
     }]);
-
-})();
\ No newline at end of file
+})();

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_js/ListCtrl.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/ListCtrl.js b/www/cdvah_js/ListCtrl.js
index 938b5b2..3940554 100644
--- a/www/cdvah_js/ListCtrl.js
+++ b/www/cdvah_js/ListCtrl.js
@@ -1,9 +1,10 @@
 (function(){
     "use strict";
     /* global myApp */
-    myApp.controller("ListCtrl", [ "$scope", "$routeParams", "AppsService", function ($scope, $routeParams, AppsService) {
+    myApp.controller("ListCtrl", [ "notifier", "$rootScope", "$scope", "$location", "$routeParams", "AppsService", function (notifier, $rootScope, $scope, $location, $routeParams, AppsService) {
 
         $scope.appsList = [];
+        $rootScope.appTitle = 'Cordova App Harness';
 
         function clearAppBundleAliases(){
             var deferred = Q.defer();
@@ -33,7 +34,7 @@
                     .then(AppsService.launchApp, function(e){
                         e = e || {};
                         console.error("Error launching last run app: " + e);
-                        alert("Error launching last run app. Please try again.");
+                        notifier.error("Error launching last run app. Please try again.");
                     });
                 }
                 else if($routeParams.updateLastLaunched) {
@@ -50,7 +51,7 @@
                     }, function(e){
                         e = e || {};
                         console.error("Error updating last run app: " + e);
-                        alert("Error updating last run app. Please try again.");
+                        notifier.error("Error updating last run app. Please try again.");
                     });
                 }
                 else {
@@ -79,7 +80,7 @@
             }, function(error){
                 var str = "There was an error retrieving the apps list";
                 console.error(str + ": " + error);
-                alert(str);
+                notifier.error(str);
             });
         };
 
@@ -87,17 +88,18 @@
             return AppsService.launchApp(app)
             .then(null, function(error){
                 console.error("Error during loading of app " + app + ": " + error);
-                alert("Something went wrong during the loading of the app. Please try again." + error);
+                notifier.error("Something went wrong during the loading of the app. Please try again." + error);
             });
         };
 
         $scope.updateApp = function(app) {
             return AppsService.updateApp(app)
             .then(function(){
-                alert("Updated successfully");
+                notifier.success("Updated successfully");
+                console.log('successfully updated');
             }, function(error){
                 console.error("Error during updating of app " + app + ": " + error);
-                alert("Something went wrong during the updating of the app. Please try again.");
+                notifier.error("Something went wrong during the updating of the app. Please try again.");
             });
         };
 
@@ -107,11 +109,13 @@
                 return AppsService.uninstallApp(app)
                 .then(function() { $scope.loadAppsList(true); }, function(error){
                     console.error("Error during uninstall of app " + app + ": " + error);
-                    alert("Something went wrong during the uninstall of the app. Please try again.");
+                    notifier.error("Something went wrong during the uninstall of the app. Please try again.");
                 });
             }
         };
 
         document.addEventListener("deviceready", initialise, false);
     }]);
-})();
\ No newline at end of file
+})();
+
+

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_js/Notify.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/Notify.js b/www/cdvah_js/Notify.js
new file mode 100644
index 0000000..921d15d
--- /dev/null
+++ b/www/cdvah_js/Notify.js
@@ -0,0 +1,40 @@
+(function() {
+    "use strict";
+    /* global myApp */
+    myApp.directive("cdvahNotify", [ "$rootScope", "$timeout", function($rootScope, $timeout) {
+        return {
+            scope: {},
+            restrict: 'E',
+            template: '<div class="notification-container" ng-show="showNotify"><div class="notification" ng-class="notification.css">{{ notification.message }}</div></div>',
+            replace: true,
+            link: function(scope, element, attrs) {
+                $rootScope.$watch('notification', function(newValue) {
+                    scope.showNotify = !!newValue;
+                    if (newValue) {
+                        scope.notification = {};
+                        scope.notification.message = newValue.message;
+                        scope.notification.css = 'notification-' + newValue.type;
+
+                        $timeout(function() {
+                            $rootScope.notification = undefined;
+                        }, 5000);
+                    }
+                });
+            }
+        };
+    }]);
+
+    myApp.factory('notifier', ['$rootScope', function($rootScope) {
+        return {
+            success: function(msg) {
+                $rootScope.notification = { message: msg, type: 'success' };
+                $rootScope.$apply();
+            },
+            error: function(msg) {
+                $rootScope.notification = { message: msg, type: 'error' };
+                $rootScope.$apply();
+            }
+        };
+    }]);
+})();
+

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_js/app.js
----------------------------------------------------------------------
diff --git a/www/cdvah_js/app.js b/www/cdvah_js/app.js
index a2d5488..105a10b 100644
--- a/www/cdvah_js/app.js
+++ b/www/cdvah_js/app.js
@@ -8,4 +8,4 @@ myApp.config(["$routeProvider", function($routeProvider){
         templateUrl: "cdvah_views/add.html",
         controller: "AddCtrl"
     });
-}]);
\ No newline at end of file
+}]);

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_views/add.html
----------------------------------------------------------------------
diff --git a/www/cdvah_views/add.html b/www/cdvah_views/add.html
index edb4dfb..a9eaaf4 100644
--- a/www/cdvah_views/add.html
+++ b/www/cdvah_views/add.html
@@ -1,6 +1,6 @@
 <form name="addForm" ng-controller="AddCtrl">
     <label for="inputAppName">Enter the App Name</label><br />
-    <input type="text" name="appName" ng-model="appData.appName" ng-pattern="/^[\w ]*$/" ng-maxlength="64" required />
+    <input class="topcoat-text-input" type="text" name="appName" ng-model="appData.appName" ng-pattern="/^[\w ]*$/" ng-maxlength="64" required />
     <span ng-show="addForm.appName.$error.required">Required</span>
     <span ng-show="addForm.appName.$error.pattern">Invalid characters used</span>
     <span ng-show="addForm.appName.$error.maxlength">Too long</span>
@@ -8,16 +8,17 @@
 
     <input type="radio" ng-model="appData.appSource" name="appSource" value="pattern" ng-checked="appData.appSource=='pattern'" />
         <label for="inputAppPattern">Enter the URL to a file</label><br />
-        <input id="inputAppPattern" type="text" name="appSourcePattern" ng-model="appData.appSourcePattern" ng-disabled="appData.appSource!='pattern'" ng-required="appData.appSource=='pattern'" autocorrect="off" autocapitalize="off" />
+        <input class="topcoat-text-input" id="inputAppPattern" type="text" name="appSourcePattern" ng-model="appData.appSourcePattern" ng-disabled="appData.appSource!='pattern'" ng-required="appData.appSource=='pattern'" autocorrect="off" autocapitalize="off" />
         <span ng-show="addForm.appSourcePattern.$error.required">Required</span>
         <br />
     <input type="radio" ng-model="appData.appSource" name="appSource" value="serve" ng-checked="appData.appSource=='serve'" />
         <label for="inputAppServe">Enter the URL to the server hosting the app</label><br />
-        <input id="inputAppServe" type="text" name="appSourceServe" ng-model="appData.appSourceServe" ng-disabled="appData.appSource!='serve'" ng-pattern="/.*\/config.xml(\?.*|#.*)?$/" ng-required="appData.appSource=='serve'" autocorrect="off" autocapitalize="off" />
+        <input class="topcoat-text-input" id="inputAppServe" type="text" name="appSourceServe" ng-model="appData.appSourceServe" ng-disabled="appData.appSource!='serve'" ng-pattern="/.*\/config.xml(\?.*|#.*)?$/" ng-required="appData.appSource=='serve'" autocorrect="off" autocapitalize="off" />
         <span ng-show="addForm.appSourceServe.$error.required">Required</span>
         <span ng-show="addForm.appSourceServe.$error.pattern">Url must point to a config.xml file</span>
         <br />
-    <button ng-click="addApp()" ng-disabled="!(addForm.$valid)">Add</button>
-    <br />
-    <a href="#/">Back To Main Menu</a>
-</form>
\ No newline at end of file
+    <div class="buttons">
+        <button class="topcoat-button--cta" ng-click="addApp()" ng-disabled="!(addForm.$valid)">Add</button>
+        <a href="#/"><button class="topcoat-button" ng-click="back()">Back</button></a>
+    </div>
+</form>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/cdvah_views/list.html
----------------------------------------------------------------------
diff --git a/www/cdvah_views/list.html b/www/cdvah_views/list.html
index b563845..bc69941 100644
--- a/www/cdvah_views/list.html
+++ b/www/cdvah_views/list.html
@@ -1,12 +1,17 @@
-<ul>
-	<li ng-repeat="app in appsList"> 
-        <p>{{app.Name}}</p>
-        <p>Installed on: {{app.Installed}}</p>
-        <button ng-click="launchApp(app.Name)">Launch</button>
-		<button ng-click="updateApp(app.Name)" ng-disabled="app.Source==='serve'">Update</button>
-		<button ng-click="removeApp(app.Name)">Remove</button>
-	</li>
-</ul>
-<button ng-click="loadAppsList()">Reload Apps List</button>
+<div class="topcoat-list__container">
+    <h3 class="topcoat-list__header">Installed Apps</h3>
+    <ul class="topcoat-list">
+        <li class="topcoat-list__item" ng-repeat="app in appsList">
+            <p>{{app.Name}}</p>
+            <p>Installed on: {{app.Installed}}</p>
+            <button ng-click="launchApp(app.Name)">Launch</button>
+            <button ng-click="updateApp(app.Name)" ng-disabled="app.Source==='serve'">Update</button>
+            <button ng-click="removeApp(app.Name)">Remove</button>
+        </li>
+    </ul>
+</div>
 <br />
-<a href="#/add">Add new App</a>
\ No newline at end of file
+<div class="buttons">
+    <a href="#/add"><button class="topcoat-button--cta">Add app</button></a>
+    <button class="topcoat-button" ng-click="loadAppsList()">Reload</button>
+</div>

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/css/style.css
----------------------------------------------------------------------
diff --git a/www/css/style.css b/www/css/style.css
new file mode 100644
index 0000000..d8554d1
--- /dev/null
+++ b/www/css/style.css
@@ -0,0 +1,30 @@
+.buttons {
+    margin: 15px;
+}
+
+.notification-container {
+    margin: 0;
+    padding: 0;
+
+    position: fixed;
+    bottom: 20px;
+    left: 0px;
+    right: 0px;
+    z-index: 3;
+}
+
+.notification {
+    border: 1px solid black;
+    border-radius: 10px;
+
+    margin: 0 20px;
+    padding: 10px 20px;
+}
+
+.notification-success {
+    background-color: #dff0d8;
+}
+
+.notification-error {
+    background-color: #f2dede;
+}

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/css/topcoat-mobile-light.min.css
----------------------------------------------------------------------
diff --git a/www/css/topcoat-mobile-light.min.css b/www/css/topcoat-mobile-light.min.css
new file mode 100644
index 0000000..1fa533a
--- /dev/null
+++ b/www/css/topcoat-mobile-light.min.css
@@ -0,0 +1 @@
+@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Regular.otf)}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Light.otf);font-weight:200}@font-face{font-family:"Source Sans";src:url(../font/SourceSansPro-Semibold.otf);font-weight:600}body{margin:0;padding:0;background:#dfe2e2;color:#000;font:16px "Source Sans",helvetica,arial,sans-serif;font-weight:200;text-rendering:optimizeLegibility}.topcoat-icon--menu-stack{background:url(../img/hamburger_dark.svg) no-repeat;-webkit-background-size:cover;-moz-background-size:cover;background-size:cover}.quarter{width:25%}.half{width:50%}.three-quarters{width:75%}.third{width:33.333%}.two-thirds{width:66.666%}.full{width:100%}.left{text-align:left}.center{text-align:center}.right{text-align:right}.reset-ui{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;
 vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden}.topcoat-button,.topcoat-button--quiet,.topcoat-button--large,.topcoat-button--large--quiet,.topcoat-button--cta,.topcoat-button--large--cta{position:relative;display:inline-block;vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;padding:0 1.25rem;font-size:16px;line-height:3rem;letter-spacing:1px;color:#454545;text
 -shadow:0 1px #fff;vertical-align:top;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px #fff;box-shadow:inset 0 1px #fff;border:1px solid #a5a8a8;-webkit-border-radius:6px;border-radius:6px}.topcoat-button:active,.topcoat-button.is-active,.topcoat-button--large:active,.topcoat-button--large.is-active{background-color:#d3d7d7;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button:disabled,.topcoat-button.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-button--quiet:active,.topcoat-button--quiet.is-active,.topcoat-button--large--quiet:active,.topcoat-button--large--quiet.is-active{color:#454545;text-shadow:0 1px #fff;background-color:#d3d7d7;border:1px solid #a5a8a8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-button--quiet:disabled,.topcoat-button--qu
 iet.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--large,.topcoat-button--large--quiet{font-size:1.3rem;line-height:4rem}.topcoat-button--large:disabled,.topcoat-button--large.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--large--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-button--large--quiet:disabled,.topcoat-button--large--quiet.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--cta,.topcoat-button--large--cta{border:1px solid #143250;background-color:#288edf;-webkit-box-shadow:inset 0 1px rgba(255,255,255,.36);box-shadow:inset 0 1px rgba(255,255,255,.36);color:#fff;font-weight:500;text-shadow:0 -1px rgba(0,0,0,.36)}.topcoat-button--cta:active,.topcoat-button--cta.is-active,.topcoat-button--large--cta:active,.topcoat-button--large--cta.is-active{background-color:#0380e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px 
 rgba(0,0,0,.12)}.topcoat-button--cta:disabled,.topcoat-button--cta.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-button--large--cta{font-size:1.3rem;line-height:4rem}.topcoat-button--large-cta:disabled,.topcoat-button--large--cta.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-icon-button,.topcoat-icon-button--quiet,.topcoat-icon-button--large,.topcoat-icon-button--large--quiet{position:relative;display:inline-block;vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;padding:0 .75rem;line-height:3rem;letter-spacing:1px;color:#454545;text-shadow:0 1px #ff
 f;vertical-align:baseline;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px #fff;box-shadow:inset 0 1px #fff;border:1px solid #a5a8a8;-webkit-border-radius:6px;border-radius:6px}.topcoat-icon-button:active,.topcoat-icon-button.is-active{background-color:#d3d7d7;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-icon-button:disabled,.topcoat-icon-button.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-icon-button--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-icon-button--quiet:active,.topcoat-icon-button--quiet.is-active,.topcoat-icon-button--large--quiet:active,.topcoat-icon-button--large--quiet.is-active{color:#454545;text-shadow:0 1px #fff;background-color:#d3d7d7;border:1px solid #a5a8a8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-icon-button--quiet:disabled,.topcoat-icon-button--quiet.is-disabled{opac
 ity:.3;cursor:default;pointer-events:none}.topcoat-icon-button--large,.topcoat-icon-button--large--quiet{width:4rem;height:4rem;line-height:4rem}.topcoat-icon-button--large:active,.topcoat-icon-button--large.is-active{background-color:#d3d7d7;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12)}.topcoat-icon-button--large:disabled,.topcoat-icon-button--large.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-icon-button--large--quiet{background:transparent;border:1px solid transparent;-webkit-box-shadow:none;box-shadow:none}.topcoat-icon-button--large--quiet:disabled,.topcoat-icon-button--large--quiet.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-icon,.topcoat-icon--large{position:relative;display:inline-block;vertical-align:top;overflow:hidden;width:1.5rem;height:1.5rem;vertical-align:middle}.topcoat-icon--large{width:2.5rem;height:2.5rem}.topcoat-list__container{padding:0;margin:0;font:inherit;color:inherit;back
 ground:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;overflow:auto;-webkit-overflow-scrolling:touch;border-top:1px solid #bcbfbf;border-bottom:1px solid #eff1f1;background-color:#dfe2e2}.topcoat-list__header{margin:0;padding:4px 20px;font-size:.9em;font-weight:400;background-color:#cccfcf;color:#656565;text-shadow:0 1px 0 rgba(255,255,255,.5);border-top:solid 1px rgba(255,255,255,.5);border-bottom:solid 1px rgba(255,255,255,.23)}.topcoat-list{padding:0;margin:0;list-style-type:none;border-top:1px solid #bcbfbf;color:#454545}.topcoat-list__item{margin:0;padding:0;padding:1.25rem;border-top:1px solid #eff1f1;border-bottom:1px solid #bcbfbf}.topcoat-list__item:first-child{border-top:1px solid rgba(0,0,0,.05)}.topcoat-navigation-bar{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;white-space:now
 rap;overflow:hidden;word-spacing:0;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;cursor:default;-webkit-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none;height:4rem;padding-left:1rem;padding-right:1rem;background:#e5e9e8;color:#000;-webkit-box-shadow:inset 0 -1 #b9bcbc,0 1px rgba(0,0,0,.95);box-shadow:inset 0 -1 #b9bcbc,0 1px rgba(0,0,0,.95)}.topcoat-navigation-bar__item{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;-webkit-background-clip:padding;-moz-background-clip:padding;background-clip:padding-box;position:relative;display:inline-block;vertical-align:top;padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;margin:var-margin;line-height:4rem;vertical-align:top}.topcoat-navigation-bar__title{padding:0;margin:0;font:inherit;color:inherit;background:transparent;border:0;-o-text-overflow:ellipsis;text-overflow:ellipsis;white-space:nowrap;overflow:hidden;font-size:1.
 3rem;font-weight:400;color:#000}.topcoat-search-input,.topcoat-search-input--large{vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0 1.25rem;-webkit-border-radius:6px;border-radius:6px;margin:5px;height:3rem;font:inherit;font-weight:200;outline:0;border:1px solid #a5a8a8;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12);color:#454545;-webkit-appearance:none;padding:0 0 0 2.7em;-webkit-border-radius:30px;border-radius:30px;background-image:url(../img/search.svg);background-position:1em center;background-repeat:no-repeat;-webkit-background-size:16px;-moz-background-size:16px;background-size:16px}.topcoat-search-input:focus,.topcoat-search-input--large:focus{background-color:#fff;color:var-color-focus}.topcoat-search-input::-webkit-search-cancel-button,.topcoat-search-input::-webkit-search-decoration{margin-right:5px}.topcoat-search-input:focus::-webkit-input-placehold
 er,.topcoat-search-input:focus::-webkit-input-placeholder{color:#c6c8c8}.topcoat-search-input:disabled,.topcoat-search-input.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-search-input--large{height:4rem;font-size:1.3rem;font-weight:200;padding-left:2.8em;-webkit-border-radius:40px;border-radius:40px;background-position:1.2em center;-webkit-background-size:1.3rem;-moz-background-size:1.3rem;background-size:1.3rem}.topcoat-search-input--large:disabled,.topcoat-search-input--large.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-text-input,.topcoat-text-input--large{vertical-align:top;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:0 1.25rem;-webkit-border-radius:6px;border-radius:6px;margin:5px;height:3rem;font:inherit;font-weight:200;outline:0;border:1px solid #a5a8a8;background-color:#e5e9e8;-webkit-box-shadow:inset 0 1px rgba(0,0,0,.12);box-shadow:inset 0 1px rgba(0,0,0,.12);color:#454545}.topcoat-text-in
 put:focus{background-color:#fff;color:#000}.topcoat-text-input:disabled,.topcoat-text-input.is-disabled{opacity:.3;cursor:default;pointer-events:none}.topcoat-text-input--large{height:4rem;font-size:1.3rem}.topcoat-text-input--large:focus{background-color:#fff;color:#000}.topcoat-text-input--large.is-disabled,.topcoat-text-input--large:disabled{opacity:.3;cursor:default;pointer-events:none}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/font/LICENSE.txt
----------------------------------------------------------------------
diff --git a/www/font/LICENSE.txt b/www/font/LICENSE.txt
new file mode 100644
index 0000000..d154618
--- /dev/null
+++ b/www/font/LICENSE.txt
@@ -0,0 +1,93 @@
+Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), with Reserved Font Name 'Source'. All Rights Reserved. Source is a trademark of Adobe Systems Incorporated in the United States and/or other countries.
+
+This Font Software is licensed under the SIL Open Font License, Version 1.1.
+
+This license is copied below, and is also available with a FAQ at: http://scripts.sil.org/OFL
+
+
+-----------------------------------------------------------
+SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
+-----------------------------------------------------------
+
+PREAMBLE
+The goals of the Open Font License (OFL) are to stimulate worldwide
+development of collaborative font projects, to support the font creation
+efforts of academic and linguistic communities, and to provide a free and
+open framework in which fonts may be shared and improved in partnership
+with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and
+redistributed freely as long as they are not sold by themselves. The
+fonts, including any derivative works, can be bundled, embedded, 
+redistributed and/or sold with any software provided that any reserved
+names are not used by derivative works. The fonts and derivatives,
+however, cannot be released under any other type of license. The
+requirement for fonts to remain under this license does not apply
+to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+"Font Software" refers to the set of files released by the Copyright
+Holder(s) under this license and clearly marked as such. This may
+include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the
+copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as
+distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting,
+or substituting -- in part or in whole -- any of the components of the
+Original Version, by changing formats or by porting the Font Software to a
+new environment.
+
+"Author" refers to any designer, engineer, programmer, technical
+writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of the Font Software, to use, study, copy, merge, embed, modify,
+redistribute, and sell modified and unmodified copies of the Font
+Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components,
+in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled,
+redistributed and/or sold with any software, provided that each copy
+contains the above copyright notice and this license. These can be
+included either as stand-alone text files, human-readable headers or
+in the appropriate machine-readable metadata fields within text or
+binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font
+Name(s) unless explicit written permission is granted by the corresponding
+Copyright Holder. This restriction only applies to the primary font name as
+presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
+Software shall not be used to promote, endorse or advertise any
+Modified Version, except to acknowledge the contribution(s) of the
+Copyright Holder(s) and the Author(s) or with their explicit written
+permission.
+
+5) The Font Software, modified or unmodified, in part or in whole,
+must be distributed entirely under this license, and must not be
+distributed under any other license. The requirement for fonts to
+remain under this license does not apply to any document created
+using the Font Software.
+
+TERMINATION
+This license becomes null and void if any of the above conditions are
+not met.
+
+DISCLAIMER
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
+OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
+COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
+INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
+DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
+OTHER DEALINGS IN THE FONT SOFTWARE.

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/font/SourceSansPro-Light.otf
----------------------------------------------------------------------
diff --git a/www/font/SourceSansPro-Light.otf b/www/font/SourceSansPro-Light.otf
new file mode 100644
index 0000000..9d8fb28
Binary files /dev/null and b/www/font/SourceSansPro-Light.otf differ

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/font/SourceSansPro-Regular.otf
----------------------------------------------------------------------
diff --git a/www/font/SourceSansPro-Regular.otf b/www/font/SourceSansPro-Regular.otf
new file mode 100644
index 0000000..7b6fa55
Binary files /dev/null and b/www/font/SourceSansPro-Regular.otf differ

http://git-wip-us.apache.org/repos/asf/cordova-app-harness/blob/d871da2a/www/font/SourceSansPro-Semibold.otf
----------------------------------------------------------------------
diff --git a/www/font/SourceSansPro-Semibold.otf b/www/font/SourceSansPro-Semibold.otf
new file mode 100644
index 0000000..6b39aa4
Binary files /dev/null and b/www/font/SourceSansPro-Semibold.otf differ