Added new loading modal window. Phase 1.
Phase 2 will include metadata, currently it needs to be rewritten to allow it.
Also removed some redundant loading animations.
Change-Id: I1dce75460a0d61d14ec1de43b250b1cb27801c65
diff --git a/client/catalog/css/cubeLoader.css b/client/catalog/css/cubeLoader.css
deleted file mode 100644
index 008b846..0000000
--- a/client/catalog/css/cubeLoader.css
+++ /dev/null
@@ -1,61 +0,0 @@
-.sk-cube-grid {
- width: 40px;
- height: 40px;
- margin: 100px auto;
-}
-
-.sk-cube-grid .sk-cube {
- width: 33%;
- height: 33%;
- background-color: #333;
- float: left;
- -webkit-animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
- animation: sk-cubeGridScaleDelay 1.3s infinite ease-in-out;
-}
-.sk-cube-grid .sk-cube1 {
- -webkit-animation-delay: 0.2s;
- animation-delay: 0.2s; }
-.sk-cube-grid .sk-cube2 {
- -webkit-animation-delay: 0.3s;
- animation-delay: 0.3s; }
-.sk-cube-grid .sk-cube3 {
- -webkit-animation-delay: 0.4s;
- animation-delay: 0.4s; }
-.sk-cube-grid .sk-cube4 {
- -webkit-animation-delay: 0.1s;
- animation-delay: 0.1s; }
-.sk-cube-grid .sk-cube5 {
- -webkit-animation-delay: 0.2s;
- animation-delay: 0.2s; }
-.sk-cube-grid .sk-cube6 {
- -webkit-animation-delay: 0.3s;
- animation-delay: 0.3s; }
-.sk-cube-grid .sk-cube7 {
- -webkit-animation-delay: 0s;
- animation-delay: 0s; }
-.sk-cube-grid .sk-cube8 {
- -webkit-animation-delay: 0.1s;
- animation-delay: 0.1s; }
-.sk-cube-grid .sk-cube9 {
- -webkit-animation-delay: 0.2s;
- animation-delay: 0.2s; }
-
-@-webkit-keyframes sk-cubeGridScaleDelay {
- 0%, 70%, 100% {
- -webkit-transform: scale3D(1, 1, 1);
- transform: scale3D(1, 1, 1);
- } 35% {
- -webkit-transform: scale3D(0, 0, 1);
- transform: scale3D(0, 0, 1);
- }
-}
-
-@keyframes sk-cubeGridScaleDelay {
- 0%, 70%, 100% {
- -webkit-transform: scale3D(1, 1, 1);
- transform: scale3D(1, 1, 1);
- } 35% {
- -webkit-transform: scale3D(0, 0, 1);
- transform: scale3D(0, 0, 1);
- }
-}
diff --git a/client/catalog/css/style.css b/client/catalog/css/style.css
index 0146b6e..d8be5c1 100644
--- a/client/catalog/css/style.css
+++ b/client/catalog/css/style.css
@@ -8,8 +8,6 @@
background-attachment: fixed;
}
-body#body {}
-
.sidebar {
height: 100%;
max-height: 100%;
@@ -170,7 +168,7 @@
content: "[=]"
}
-#popup {
+.popup {
top: 0;
left: 0;
position: fixed;
@@ -183,23 +181,15 @@
pointer-events: none;
}
-#popup > * {
+.popup > * {
display: none;
pointer-events: auto;
}
-.modal-open, #request {
+.modal-open, #request, #loading {
padding-right: 0 !important;
}
-.sk-cube-grid {
- display: none;
-}
-
-table:empty ~ .sk-cube-grid {
- display: block;
-}
-
#requestForm {
max-width: 500px;
/* min-height: 300px; */
@@ -267,3 +257,11 @@
#direct-download-list:empty:before {
content: "No names in the selection are available for direct download...";
}
+
+#loading.loading #cancel-text {
+ display: none;
+}
+
+#loading.cancelled #loading-text {
+ display: none;
+}
diff --git a/client/catalog/index.html b/client/catalog/index.html
index 78c0e73..774b28e 100644
--- a/client/catalog/index.html
+++ b/client/catalog/index.html
@@ -24,31 +24,22 @@
<!-- Styles -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css">
-<link rel="stylesheet" href="css/cubeLoader.css">
<link rel="stylesheet" href="css/theme.min.css">
<link rel="stylesheet" href="css/style.css">
<!-- Scripts -->
-<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.3/jquery.min.js">
-</script>
-<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-scrollTo/2.1.2/jquery.scrollTo.min.js">
-</script>
-<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js">
-</script>
-<script src="https://cdnjs.cloudflare.com/ajax/libs/async/1.5.2/async.min.js">
-</script>
-<script src="../ndn-js/build/ndn.min.js">
-</script>
-<script src="js/autocomplete.js">
-</script>
-<script src="js/treeExplorer.js">
-</script>
-<script src="js/catalog.js">
-</script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
+<script src="https://cdnjs.cloudflare.com/ajax/libs/async/2.0.1/async.min.js"></script>
+<script src="../ndn-js/build/ndn.min.js"></script>
+<script src="js/autocomplete.js"></script>
+<script src="js/treeExplorer.js"></script>
+<script src="js/loading-overlay.js"></script>
+<script src="js/catalog.js"></script>
</head>
-<body id="body">
+<body>
<div id="templates">
<div class="row" id="timeTemplate">
@@ -120,7 +111,7 @@
<div class="panel panel-info tab-pane fade in active" id="filterSearch">
<div class="panel-heading">Filter Search</div>
<div class="panel-body">
- <div>
+ <div class="well">
<div id="filters"></div>
<button id="searchButton" class="btn btn-primary right-fix">Search</button>
</div>
@@ -191,17 +182,6 @@
<div class="navbar-text navbar-right">(Page <span class="pageNumber">0</span>) <span class="pageLength">0</span>/<span class="totalResults">0</span> Results</div>
</nav>
<table id="resultTable" class="table"></table>
- <div class="sk-cube-grid">
- <div class="sk-cube sk-cube1"></div>
- <div class="sk-cube sk-cube2"></div>
- <div class="sk-cube sk-cube3"></div>
- <div class="sk-cube sk-cube4"></div>
- <div class="sk-cube sk-cube5"></div>
- <div class="sk-cube sk-cube6"></div>
- <div class="sk-cube sk-cube7"></div>
- <div class="sk-cube sk-cube8"></div>
- <div class="sk-cube sk-cube9"></div>
- </div>
<nav class="navbar navbar-inverse col-md-12 resultMenu">
<ul class="nav navbar-nav navbar-left">
<li><a href="#" class="requestSelectedButton">Request Selected</a></li>
@@ -235,7 +215,7 @@
</div>
- <div id="popup">
+ <div class="popup">
<div id="request" class="panel panel-primary">
<div class="panel-heading">Confirmation</div>
<div class="panel-body">
@@ -283,6 +263,28 @@
</div>
</div>
+ <div class="popup">
+ <div id="loading" class="panel panel-primary loading">
+ <div class="panel-heading">Loading</div>
+ <div class="panel-body">
+ <span id="loading-text">Please wait while we finish loading your request.</span>
+ <span id="cancel-text">Your request has been cancelled.</span>
+ <div class="row">
+ <div class="col-sm-12">
+ <div class="progress">
+ <div class="progress-bar progress-bar-striped active" style="width:100%;">Loading...</div>
+ </div>
+ </div>
+ </div>
+ <div class="row">
+ <div class="col-sm-12">
+ <button id="loading-cancel" class="btn btn-danger pull-right">Cancel</button>
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+
</body>
</html>
diff --git a/client/catalog/js/catalog.js b/client/catalog/js/catalog.js
index 5203fdc..2dfb368 100644
--- a/client/catalog/js/catalog.js
+++ b/client/catalog/js/catalog.js
@@ -377,9 +377,9 @@
} else if (resultIndex === 1) {
this.resultMenu.find('.previous').removeClass('disabled');
}
- $.scrollTo("#results", 500, {
- interrupt: true
- });
+ $('body').animate({
+ scrollTop: $("#results").offset().top
+ }, 500);
}
Atmos.prototype.getResults = function(index) {
@@ -455,19 +455,29 @@
interest.setInterestLifetimeMilliseconds(500);
interest.setMustBeFresh(true);
const face = this.face;
- async.retry(4, function(done) {
- face.expressInterest(interest, function(interest, data) {
- done();
- success(interest, data);
- }, function(interest) {
- done("Interest timed out 4 times.", interest);
+ var cancelled = false;
+ var attempt = 0;
+ openLoadingOverlay(function(update){
+ async.retry(4, function(done) {
+ face.expressInterest(interest, function(interest, data) {
+ update(true, attempt, attempt);
+ done();
+ success(interest, data);
+ }, function(interest) {
+ update(false, attempt++, attempt);
+ done("Timeout", interest);
+ });
+ }, function(err, interest) {
+ update(true, attempt, attempt);
+ if (err) {
+ console.log(err, interest);
+ failure(interest);
+ }
});
- }, function(err, interest) {
- if (err) {
- console.log(err, interest);
- failure(interest);
- }
+ }, function(){
+ cancelled = true;
});
+
}
/**
@@ -673,7 +683,8 @@
var item = $('<li><a href="#">' + name + '</a></li>');
sub.append(item);
- item.click(function() {
+ item.find('a').click(function(e) {
+ e.preventDefault();
//Click on the side menu filters
if (item.hasClass('active')) {
//Does the filter already exist?
@@ -685,7 +696,7 @@
var filter = $('<span class="label label-default"></span>');
filter.text(category + ':' + name);
scope.filters.append(filter);
- filter.click(function() {
+ filter.click(function(e) {
//Click on a filter
filter.remove();
item.removeClass('active');
@@ -694,7 +705,8 @@
});
});
//Toggle the menus. (Only respond when the immediate tab is clicked.)
- e.find('> a').click(function() {
+ e.find('> a').click(function(e) {
+ e.preventDefault();
scope.categories.find('.subnav').slideUp();
var t = $(this).siblings('.subnav');
if (!t.is(':visible')) {
diff --git a/client/catalog/js/loading-overlay.js b/client/catalog/js/loading-overlay.js
new file mode 100644
index 0000000..849524d
--- /dev/null
+++ b/client/catalog/js/loading-overlay.js
@@ -0,0 +1,78 @@
+/**
+ * This function allows the app to pass in a callback function for updating the progress and a function to call if the progress it cancelled.
+ * @param func - A function accepting two functions as parameters, the first will be called with one parameter (which is a callback function
+ * for progress updates) when the overlay is ready.
+ * @param cancel - A function to call if the overlay is cancelled.
+ *
+ * Example:
+ * openLoadingOverlay(function(update){
+ * //Begin progress, call update if progress is in chunks, otherwise ignore.
+ * }, function(){
+ * //Cancelled
+ * });
+ */
+var openLoadingOverlay = (function(){
+ "use strict";
+
+ var isOpen = false;
+
+ return function(func, cancel){
+
+ var overlay = $('#loading');
+ var progress = overlay.find('.progress-bar');
+ var cancelButton = overlay.find('#loading-cancel');
+
+ if (isOpen){
+ console.warn("Two overlays are not permitted at the same time. The second will have dummy callbacks");
+ func(function(){});
+ return;
+ }
+
+ isOpen = true;
+
+ var update = function(done, current, total){
+ if (current && total){
+ progress.text(current + '/' + total)
+ .animate({
+ width: Math.round(current/total) + '%'
+ },
+ 200,
+ 'linear',
+ function(){
+ if (done){
+ reset();
+ }
+ }
+ );
+ } else {
+ if (done){
+ reset();
+ }
+ }
+ };
+
+ var reset = function(){
+ overlay.modal('hide');
+ progress.text('Loading...').css('width', '100%');
+ overlay.removeClass('cancelled').addClass('loading');
+ cancelButton.removeClass('disabled');
+ };
+
+ cancelButton.one('click', function(){
+
+ cancelButton.addClass('disabled');
+ overlay.addClass('cancelled').removeClass('loading');
+
+ setTimeout(reset, 2000);
+ progress.text('Cancelling...').css('width', 0).animate({
+ width: '100%'
+ }, 2000);
+
+ });
+
+ overlay.modal('show');
+
+ func(update);
+
+ };
+})();