blob: 880ea4e3ef34a40fcb61e13b312ea79fbbfac619 [file] [log] [blame]
Tyler Scottcdfcde82015-09-14 16:13:29 -06001//Run when the document loads AND we have the config loaded.
Tyler Scott66a965d2016-02-29 15:41:33 -07002(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -06003 "use strict";
4 var config;
Tyler Scott384f37a2016-05-05 16:09:05 -06005 var conversions;
Tyler Scott7ae6be02016-06-22 15:29:26 -06006
7 Promise.all([new Promise(function(resolve, reject) {
8 $.ajax('config.json').done(function(data) {
Tyler Scott66a965d2016-02-29 15:41:33 -07009 config = data;
10 resolve();
11 }).fail(function() {
12 console.error("Failed to get config.");
13 ga('send', 'event', 'error', 'config');
14 reject();
15 });
Tyler Scott7ae6be02016-06-22 15:29:26 -060016 }), new Promise(function(resolve, reject) {
Tyler Scott66a965d2016-02-29 15:41:33 -070017 var timeout = setTimeout(function() {
18 console.error("Document never loaded? Something bad has happened!");
19 reject();
20 }, 10000);
21 $(function() {
22 clearTimeout(timeout);
23 resolve();
24 });
Tyler Scott7ae6be02016-06-22 15:29:26 -060025 }), new Promise(function(resolve, reject) {
Tyler Scott384f37a2016-05-05 16:09:05 -060026 $.getJSON('../conversions.json').done(function(data) {
27 conversions = data;
28 resolve();
Tyler Scott7ae6be02016-06-22 15:29:26 -060029 }).fail(function() {
Tyler Scott384f37a2016-05-05 16:09:05 -060030 console.error("Failed to get conversions.");
31 ga('send', 'event', 'error', 'config');
32 //reject(); We will continue anyways. We don't need this functionality.
33 conversions = {};
34 resolve();
35 });
Tyler Scott7ae6be02016-06-22 15:29:26 -060036 })]).then(function() {
Tyler Scott66a965d2016-02-29 15:41:33 -070037 var getParameterByName = function(name) {
38 name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
39 var regex = new RegExp("[\\?&]" + name + "=([^&#]*)");
40 var results = regex.exec(location.search);
Tyler Scott7ae6be02016-06-22 15:29:26 -060041 return results === null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
Tyler Scott66a965d2016-02-29 15:41:33 -070042 }
Tyler Scott2118a412015-10-29 15:17:05 -060043 //Overwrite config if present. Any failure will just cause this to be skipped.
Tyler Scott66a965d2016-02-29 15:41:33 -070044 try {
Tyler Scott2118a412015-10-29 15:17:05 -060045 var configParam = JSON.parse(getParameterByName('config'));
46 config = jQuery.extend(true, config, configParam);
Tyler Scott66a965d2016-02-29 15:41:33 -070047 } catch (e) {
Tyler Scott2118a412015-10-29 15:17:05 -060048 console.warn("Failure in config overwrite, skipping.", e);
49 }
Tyler Scott7ae6be02016-06-22 15:29:26 -060050 new Atmos(config,conversions);
Tyler Scott66a965d2016-02-29 15:41:33 -070051 }, function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -060052 console.error("Failed to initialize!");
53 ga('send', 'event', 'error', 'init');
54 });
Tyler Scottcdfcde82015-09-14 16:13:29 -060055
Tyler Scott7ae6be02016-06-22 15:29:26 -060056})();
Tyler Scott66a965d2016-02-29 15:41:33 -070057var Atmos = (function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -060058 "use strict";
Tyler Scottcdfcde82015-09-14 16:13:29 -060059 var closeButton = '<button type="button" class="close" data-dismiss="alert" aria-label="Close"><span aria-hidden="true">&times;</span></button>';
Tyler Scott66a965d2016-02-29 15:41:33 -070060 var guid = function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -060061 var d = new Date().getTime();
62 var uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
Tyler Scott66a965d2016-02-29 15:41:33 -070063 var r = (d + Math.random() * 16) % 16 | 0;
64 d = Math.floor(d / 16);
65 return (c == 'x' ? r : (r & 0x3 | 0x8)).toString(16);
Tyler Scottcdfcde82015-09-14 16:13:29 -060066 });
67 return uuid;
Tyler Scott66a965d2016-02-29 15:41:33 -070068 }
Tyler Scottcdfcde82015-09-14 16:13:29 -060069 /**
70 * Atmos
71 * @version 2.0
Tyler Scott66a965d2016-02-29 15:41:33 -070072
Tyler Scottcdfcde82015-09-14 16:13:29 -060073 * Configures an Atmos object. This manages the atmos interface.
Tyler Scott66a965d2016-02-29 15:41:33 -070074
Tyler Scottcdfcde82015-09-14 16:13:29 -060075 * @constructor
76 * @param {string} catalog - NDN path
77 * @param {Object} config - Object of configuration options for a Face.
78 */
Tyler Scott384f37a2016-05-05 16:09:05 -060079 var Atmos = function(config, conversions) {
Tyler Scottcdfcde82015-09-14 16:13:29 -060080 //Internal variables.
81 this.results = [];
82 this.resultCount = Infinity;
Tyler Scott66a965d2016-02-29 15:41:33 -070083 this.name = null ;
Tyler Scottcdfcde82015-09-14 16:13:29 -060084 this.page = 0;
85 this.resultsPerPage = 25;
86 this.retrievedSegments = 0;
87
88 //Config/init
89 this.config = config;
Tyler Scott384f37a2016-05-05 16:09:05 -060090 this.conversions = conversions;
Tyler Scottcdfcde82015-09-14 16:13:29 -060091
92 this.catalog = config['global']['catalogPrefix'];
Chengyu Fan7b978f82015-12-09 17:03:23 -070093 this.catalogPrefix = new Name(this.catalog);
Tyler Scottcdfcde82015-09-14 16:13:29 -060094 this.face = new Face(config['global']['faceConfig']);
95
96 //Easy access dom variables
97 this.categories = $('#side-menu');
98 this.resultTable = $('#resultTable');
99 this.filters = $('#filters');
100 this.searchInput = $('#search');
101 this.searchBar = $('#searchBar');
102 this.searchButton = $('#searchButton');
103 this.resultMenu = $('.resultMenu');
104 this.alerts = $('#alerts');
105 this.requestForm = $('#requestForm');
106
107 var scope = this;
Tyler Scott66a965d2016-02-29 15:41:33 -0700108 $('.requestSelectedButton').click(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600109 ga('send', 'event', 'button', 'click', 'request');
110 scope.request(scope.resultTable.find('.resultSelector:checked:not([disabled])').parent().parent());
111 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600112 this.filterSetup();
113
114 //Init autocomplete
Tyler Scott66a965d2016-02-29 15:41:33 -0700115 this.searchInput.autoComplete(function(field, callback) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600116 ga('send', 'event', 'search', 'autocomplete');
Tyler Scott66a965d2016-02-29 15:41:33 -0700117 scope.autoComplete(field, function(data) {
Tyler Scott94458992015-09-24 14:16:28 -0700118 var list = data.next;
119 var last = data.lastComponent === true;
Tyler Scott66a965d2016-02-29 15:41:33 -0700120 callback(list.map(function(element) {
121 return field + element + (last ? "/" : "");
122 //Don't add trailing slash for last component.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600123 }));
124 });
125 });
126
127 //Handle search
Tyler Scott66a965d2016-02-29 15:41:33 -0700128 this.searchBar.submit(function(e) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600129 ga('send', 'event', 'search', 'submit');
130 e.preventDefault();
Tyler Scott66a965d2016-02-29 15:41:33 -0700131 if (scope.searchInput.val().length === 0) {
132 if (!scope.searchBar.hasClass('has-error')) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600133 scope.searchBar.addClass('has-error').append('<span class="help-block">Search path is required!</span>');
134 }
135 return;
136 } else {
Tyler Scott66a965d2016-02-29 15:41:33 -0700137 scope.searchBar.removeClass('has-error').find('.help-block').fadeOut(function() {
138 $(this).remove()
139 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600140 }
141 scope.pathSearch();
142 });
143
Tyler Scott66a965d2016-02-29 15:41:33 -0700144 this.searchButton.click(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600145 console.log("Search Button Pressed");
146 ga('send', 'event', 'button', 'click', 'search');
147 scope.search();
148 });
149
150 //Result navigation handlers
Tyler Scott66a965d2016-02-29 15:41:33 -0700151 this.resultMenu.find('.next').click(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600152 ga('send', 'event', 'button', 'click', 'next');
Tyler Scott66a965d2016-02-29 15:41:33 -0700153 if (!$(this).hasClass('disabled')) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600154 scope.getResults(scope.page + 1);
155 }
156 });
Tyler Scott7ae6be02016-06-22 15:29:26 -0600157
Tyler Scott66a965d2016-02-29 15:41:33 -0700158 this.resultMenu.find('.previous').click(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600159 ga('send', 'event', 'button', 'click', 'previous');
Tyler Scott66a965d2016-02-29 15:41:33 -0700160 if (!$(this).hasClass('disabled')) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600161 scope.getResults(scope.page - 1);
162 }
163 });
Tyler Scott7ae6be02016-06-22 15:29:26 -0600164
Tyler Scott66a965d2016-02-29 15:41:33 -0700165 this.resultMenu.find('.clearResults').click(function() {
Tyler Scotte8dac702015-10-13 14:33:25 -0600166 ga('send', 'event', 'button', 'click', 'resultClear');
167 scope.clearResults();
Tyler Scott66a965d2016-02-29 15:41:33 -0700168 $('#results').fadeOut(function() {
Tyler Scotte8dac702015-10-13 14:33:25 -0600169 $(this).addClass('hidden');
170 });
171 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600172
173 //Change the number of results per page handler
Tyler Scott66a965d2016-02-29 15:41:33 -0700174 var rpps = $('.resultsPerPageSelector').click(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600175 var t = $(this);
Tyler Scott66a965d2016-02-29 15:41:33 -0700176 if (t.hasClass('active')) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600177 return;
178 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600179 rpps.find('.active').removeClass('active');
180 t.addClass('active');
181 scope.resultsPerPage = Number(t.text());
Tyler Scott66a965d2016-02-29 15:41:33 -0700182 scope.getResults(0);
183 //Force return to page 1;
Tyler Scottcdfcde82015-09-14 16:13:29 -0600184 });
185
186 //Init tree search
Tyler Scott66a965d2016-02-29 15:41:33 -0700187 $('#treeSearch div').treeExplorer(function(path, callback) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600188 console.log("Tree Explorer request", path);
189 ga('send', 'event', 'tree', 'request');
Tyler Scott66a965d2016-02-29 15:41:33 -0700190 scope.autoComplete(path, function(data) {
Tyler Scottb59e6de2015-09-18 14:46:30 -0600191 var list = data.next;
192 var last = (data.lastComponent === true);
Tyler Scottbb42ed22015-10-21 17:02:56 -0600193 if (last) {
194 console.log("Redirecting last element request to a search.");
195 scope.clearResults();
Tyler Scott66a965d2016-02-29 15:41:33 -0700196 scope.query(scope.catalog, {
197 '??': path
Tyler Scott7ae6be02016-06-22 15:29:26 -0600198 }, function(interest, data) {
Tyler Scottbb42ed22015-10-21 17:02:56 -0600199 console.log("Search response", interest, data);
Chengyu Fan7b978f82015-12-09 17:03:23 -0700200 scope.name = interest.getName();
Tyler Scottbb42ed22015-10-21 17:02:56 -0600201 scope.getResults(0);
Tyler Scott66a965d2016-02-29 15:41:33 -0700202 }, function(interest) {
Tyler Scottbb42ed22015-10-21 17:02:56 -0600203 console.warn("Failed to retrieve final component.", interest, path);
204 scope.createAlert("Failed to request final component. " + path + " See console for details.");
205 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700206 return;
207 //Don't call the callback
Tyler Scottbb42ed22015-10-21 17:02:56 -0600208 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600209 console.log("Autocomplete response", list);
Tyler Scott66a965d2016-02-29 15:41:33 -0700210 callback(list.map(function(element) {
211 return (path == "/" ? "/" : "") + element + "/";
Tyler Scottcdfcde82015-09-14 16:13:29 -0600212 }));
Chengyu Fan7b978f82015-12-09 17:03:23 -0700213 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600214 });
215
Tyler Scott66a965d2016-02-29 15:41:33 -0700216 $('#treeSearch').on('click', '.treeSearch', function() {
Tyler Scottb59e6de2015-09-18 14:46:30 -0600217 var t = $(this);
Tyler Scottb59e6de2015-09-18 14:46:30 -0600218 scope.clearResults();
Tyler Scottb59e6de2015-09-18 14:46:30 -0600219 var path = t.parent().parent().attr('id');
Tyler Scottbb42ed22015-10-21 17:02:56 -0600220 console.log("Tree search:", path);
Tyler Scott66a965d2016-02-29 15:41:33 -0700221 scope.query(scope.catalog, {
222 '??': path
Tyler Scott7ae6be02016-06-22 15:29:26 -0600223 }, function(interest, data) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700224 //Success
Tyler Scottb59e6de2015-09-18 14:46:30 -0600225 console.log("Tree search response", interest, data);
Chengyu Fan7b978f82015-12-09 17:03:23 -0700226 scope.name = interest.getName();
Tyler Scottb59e6de2015-09-18 14:46:30 -0600227 scope.getResults(0);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600228 }, function(interest) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700229 //Failure
Tyler Scottb59e6de2015-09-18 14:46:30 -0600230 console.warn("Request failed! Timeout", interest);
Tyler Scott66a965d2016-02-29 15:41:33 -0700231 scope.createAlert("Request timed out.\"" + interest.getName().toUri() + "\" See console for details.");
Tyler Scottb59e6de2015-09-18 14:46:30 -0600232 });
Tyler Scottb59e6de2015-09-18 14:46:30 -0600233 });
234
Tyler Scottcdfcde82015-09-14 16:13:29 -0600235 this.setupRequestForm();
Tyler Scott48f92cd2015-10-16 18:31:20 -0600236 this.resultTable.popover({
Tyler Scott66a965d2016-02-29 15:41:33 -0700237 selector: ".metaDataLink",
238 content: function() {
Tyler Scottf95a97c2016-06-21 12:09:22 -0600239 $('.metaDataLink').not(this).popover('destroy');
Tyler Scott48f92cd2015-10-16 18:31:20 -0600240 return scope.getMetaData(this);
241 },
242 title: "Metadata",
243 html: true,
244 trigger: 'click',
245 placement: 'bottom'
246 });
247
Tyler Scott66a965d2016-02-29 15:41:33 -0700248 this.resultTable.on('click', '.metaDataLink', function(e) {
Tyler Scott48f92cd2015-10-16 18:31:20 -0600249 //This prevents the page from scrolling when you click on a name.
250 e.preventDefault();
251 });
252
Tyler Scott66a965d2016-02-29 15:41:33 -0700253 this.resultTable.on('click', '.subsetButton', function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700254 var metaData = $(this).siblings('pre').text();
255 var exp = /netcdf ([\w-]+)/;
256 var match = exp.exec(metaData);
Tyler Scott66a965d2016-02-29 15:41:33 -0700257 var filename = match[0].replace(/netcdf /, '') + '.nc';
258 scope.request(null , filename);
Tyler Scottf355e452015-11-06 21:35:14 -0700259 });
260
Tyler Scottf95a97c2016-06-21 12:09:22 -0600261 //Allow the title to change the tab
Tyler Scott7ae6be02016-06-22 15:29:26 -0600262 $('#brand-title').click(function() {
Tyler Scottf95a97c2016-06-21 12:09:22 -0600263 //Correct active class on tabs.
Tyler Scott7ae6be02016-06-22 15:29:26 -0600264 $('#path-search-tab').removeClass('active');
265 $('#tree-search-tab').removeClass('active');
Tyler Scottf95a97c2016-06-21 12:09:22 -0600266 $('#search-tab').addClass('active');
267 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700268 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700269 Atmos.prototype.clearResults = function() {
270 this.results = [];
271 //Drop any old results.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600272 this.retrievedSegments = 0;
273 this.resultCount = Infinity;
274 this.page = 0;
275 this.resultTable.empty();
Tyler Scott66a965d2016-02-29 15:41:33 -0700276 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600277
Tyler Scott66a965d2016-02-29 15:41:33 -0700278 Atmos.prototype.pathSearch = function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600279 var value = this.searchInput.val();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600280 this.clearResults();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600281 var scope = this;
Tyler Scott66a965d2016-02-29 15:41:33 -0700282 this.query(this.catalog, {
283 "??": value
Tyler Scott7ae6be02016-06-22 15:29:26 -0600284 }, function(interest, data) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600285 console.log("Query response:", interest, data);
Tyler Scott66a965d2016-02-29 15:41:33 -0700286 scope.name = interest.getName();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600287 scope.getResults(0);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600288 }, function(interest) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600289 console.warn("Request failed! Timeout", interest);
290 scope.createAlert("Request timed out. \"" + interest.getName().toUri() + "\" See console for details.");
291 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700292 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600293
Tyler Scott66a965d2016-02-29 15:41:33 -0700294 Atmos.prototype.search = function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600295 var filters = this.getFilters();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600296 console.log("Search started!", this.searchInput.val(), filters);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600297 console.log("Initiating query");
Tyler Scottcdfcde82015-09-14 16:13:29 -0600298 this.clearResults();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600299 var scope = this;
Tyler Scott7ae6be02016-06-22 15:29:26 -0600300 this.query(this.catalog, filters, function(interest, data) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700301 //Response function
Tyler Scottcdfcde82015-09-14 16:13:29 -0600302 console.log("Query Response:", interest, data);
Chengyu Fan7b978f82015-12-09 17:03:23 -0700303 scope.name = interest.getName();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600304 scope.getResults(0);
Tyler Scott66a965d2016-02-29 15:41:33 -0700305 }, function(interest) {
306 //Timeout function
Tyler Scottd980a292015-10-13 15:16:34 -0600307 console.warn("Request failed after 3 attempts!", interest);
308 scope.createAlert("Request failed after 3 attempts. \"" + interest.getName().toUri() + "\" See console for details.");
Tyler Scottcdfcde82015-09-14 16:13:29 -0600309 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700310 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600311
Tyler Scott66a965d2016-02-29 15:41:33 -0700312 Atmos.prototype.autoComplete = function(field, callback) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600313 var scope = this;
Tyler Scott66a965d2016-02-29 15:41:33 -0700314 var result = {};
Tyler Scott66a965d2016-02-29 15:41:33 -0700315 const getAll = function(interest, data) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700316 if (data.getContent().length !== 0) {
317 var resp = JSON.parse(data.getContent().toString().replace(/[\n\0]/g, ""));
318 if (result.next) {
319 result.next = result.next.concat(resp.next);
320 } else {
321 result = resp;
Tyler Scottd61bf832015-11-30 16:36:17 -0700322 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700323 } else {
324 callback(result);
325 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700326 var name = data.getName();
327 var segment = name.components[name.getComponentCount() - 1];
Tyler Scott7ae6be02016-06-22 15:29:26 -0600328 if (segment.toSegment() !== data.getMetaInfo().getFinalBlockId().toSegment()) {
329 name = name.getPrefix(-1);
330 //Remove segment
Tyler Scott66a965d2016-02-29 15:41:33 -0700331 name.appendSegment(segment.toSegment() + 1);
332 scope.expressInterest(name, getAll, function() {
333 console.warn("Autocomplete timed out, results may be incomplete.");
334 callback(result);
335 //Return if we get a timeout.
336 });
337 } else {
338 callback(result);
339 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700340 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700341 this.query(this.catalog, {
342 "?": field
343 }, getAll);
Tyler Scott66a965d2016-02-29 15:41:33 -0700344 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600345
346 Atmos.prototype.showResults = function(resultIndex) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600347 var results = this.results.slice(this.resultsPerPage * resultIndex, this.resultsPerPage * (resultIndex + 1));
Tyler Scott7ae6be02016-06-22 15:29:26 -0600348 var resultDOM = $(results.reduce(function(prev, current) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700349 prev.push('<tr><td><input class="resultSelector" type="checkbox"></td><td class="popover-container"><a href="#" class="metaDataLink">');
350 prev.push(current);
351 prev.push('</a></td></tr>');
352 return prev;
Tyler Scott7ae6be02016-06-22 15:29:26 -0600353 }, ['<tr><th><input id="resultSelectAll" type="checkbox"> Select All</th><th>Name</th></tr>']).join(''));
Tyler Scott66a965d2016-02-29 15:41:33 -0700354 resultDOM.find('#resultSelectAll').click(function() {
355 if ($(this).is(':checked')) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600356 resultDOM.find('.resultSelector:not([disabled])').prop('checked', true);
357 } else {
358 resultDOM.find('.resultSelector:not([disabled])').prop('checked', false);
359 }
360 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600361 this.resultTable.hide().empty().append(resultDOM).slideDown('slow');
Tyler Scottcdfcde82015-09-14 16:13:29 -0600362 this.resultMenu.find('.pageNumber').text(resultIndex + 1);
363 this.resultMenu.find('.pageLength').text(this.resultsPerPage * resultIndex + results.length);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600364 if (this.resultsPerPage * (resultIndex + 1) >= this.resultCount) {
365 this.resultMenu.find('.next').addClass('disabled');
Tyler Scott66a965d2016-02-29 15:41:33 -0700366 } else if (resultIndex === 0) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600367 this.resultMenu.find('.next').removeClass('disabled');
368 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700369 if (resultIndex === 0) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600370 this.resultMenu.find('.previous').addClass('disabled');
371 } else if (resultIndex === 1) {
372 this.resultMenu.find('.previous').removeClass('disabled');
373 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700374 $.scrollTo("#results", 500, {
375 interrupt: true
376 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700377 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600378
Tyler Scott66a965d2016-02-29 15:41:33 -0700379 Atmos.prototype.getResults = function(index) {
Tyler Scott7ae6be02016-06-22 15:29:26 -0600380
Chengyu Fan7b978f82015-12-09 17:03:23 -0700381 var scope = this;
Tyler Scottcdfcde82015-09-14 16:13:29 -0600382
Tyler Scott66a965d2016-02-29 15:41:33 -0700383 if ($('#results').hasClass('hidden')) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600384 $('#results').removeClass('hidden').slideDown();
385 }
386
Tyler Scott66a965d2016-02-29 15:41:33 -0700387 if ((scope.results.length === scope.resultCount) || (scope.resultsPerPage * (index + 1) < scope.results.length)) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600388 //console.log("We already have index", index);
Chengyu Fan7b978f82015-12-09 17:03:23 -0700389 scope.page = index;
390 scope.showResults(index);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600391 return;
392 }
393
Tyler Scott66a965d2016-02-29 15:41:33 -0700394 if (scope.name === null ) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600395 console.error("This shouldn't be reached! We are getting results before a search has occured!");
396 throw new Error("Illegal State");
397 }
398
Chengyu Fan7b978f82015-12-09 17:03:23 -0700399 var interestName = new Name(scope.name);
Chengyu Fan7b978f82015-12-09 17:03:23 -0700400 // Interest name should be /<catalog-prefix>/query/<query-param>/<version>/<#seq>
401 if (scope.name.size() === (scope.catalogPrefix.size() + 3)) {
402 interestName = interestName.appendSegment(scope.retrievedSegments++);
Tyler Scott66a965d2016-02-29 15:41:33 -0700403 //console.log("Requesting data index: (", scope.retrievedSegments - 1, ") at ", interestName.toUri());
Chengyu Fan7b978f82015-12-09 17:03:23 -0700404 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600405
Tyler Scott7ae6be02016-06-22 15:29:26 -0600406 this.expressInterest(interestName, function(interest, data) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700407 //Response
Tyler Scott66a965d2016-02-29 15:41:33 -0700408 if (data.getContent().length === 0) {
409 scope.resultMenu.find('.totalResults').text(0);
410 scope.resultMenu.find('.pageNumber').text(0);
411 scope.resultMenu.find('.pageLength').text(0);
412 console.log("Empty response.");
413 scope.resultTable.html("<tr><td>Empty response. This usually means no results.</td></tr>");
414 return;
Tyler Scottcdfcde82015-09-14 16:13:29 -0600415 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600416
Tyler Scott66a965d2016-02-29 15:41:33 -0700417 var content = JSON.parse(data.getContent().toString().replace(/[\n\0]/g, ""));
418
419 if (!content.results) {
420 scope.resultMenu.find('.totalResults').text(0);
421 scope.resultMenu.find('.pageNumber').text(0);
422 scope.resultMenu.find('.pageLength').text(0);
423 console.log("No results were found!");
424 scope.resultTable.html("<tr><td>No Results</td></tr>");
425 return;
426 }
427
428 scope.results = scope.results.concat(content.results);
Tyler Scott66a965d2016-02-29 15:41:33 -0700429 scope.resultCount = content.resultCount;
Tyler Scott66a965d2016-02-29 15:41:33 -0700430 scope.resultMenu.find('.totalResults').text(scope.resultCount);
Tyler Scott66a965d2016-02-29 15:41:33 -0700431 scope.page = index;
Tyler Scott66a965d2016-02-29 15:41:33 -0700432 // reset scope.name
433 scope.name = new Name(data.getName().getPrefix(scope.catalogPrefix.size() + 3));
Tyler Scott66a965d2016-02-29 15:41:33 -0700434 scope.getResults(index);
435 //Keep calling this until we have enough data.
Tyler Scott7ae6be02016-06-22 15:29:26 -0600436 }, function() {});//Ignore failure
Tyler Scott66a965d2016-02-29 15:41:33 -0700437
438 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600439 Atmos.prototype.query = function(prefix, parameters, callback, timeout) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600440 var queryPrefix = new Name(prefix);
441 queryPrefix.append("query");
Tyler Scottcdfcde82015-09-14 16:13:29 -0600442 var jsonString = JSON.stringify(parameters);
443 queryPrefix.append(jsonString);
Tyler Scott66a965d2016-02-29 15:41:33 -0700444 this.expressInterest(queryPrefix, callback, timeout);
Tyler Scott66a965d2016-02-29 15:41:33 -0700445 }
Tyler Scottd61bf832015-11-30 16:36:17 -0700446
Tyler Scott66a965d2016-02-29 15:41:33 -0700447 Atmos.prototype.expressInterest = function(name, success, failure) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700448 var interest = new Interest(name);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600449 interest.setInterestLifetimeMilliseconds(500);
Tyler Scott66a965d2016-02-29 15:41:33 -0700450 interest.setMustBeFresh(true);
Tyler Scott66a965d2016-02-29 15:41:33 -0700451 const face = this.face;
Tyler Scott66a965d2016-02-29 15:41:33 -0700452 async.retry(4, function(done) {
453 face.expressInterest(interest, function(interest, data) {
Tyler Scottd61bf832015-11-30 16:36:17 -0700454 done();
Tyler Scott66a965d2016-02-29 15:41:33 -0700455 success(interest, data);
456 }, function(interest) {
457 done("Interest timed out 4 times.", interest);
458 });
459 }, function(err, interest) {
460 if (err) {
461 console.log(err, interest);
462 failure(interest);
Tyler Scott8724e422015-10-13 17:59:07 -0600463 }
Tyler Scottd61bf832015-11-30 16:36:17 -0700464 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700465 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600466
467 /**
468 * This function returns a map of all the categories active filters.
469 * @return {Object<string, string>}
470 */
Tyler Scott66a965d2016-02-29 15:41:33 -0700471 Atmos.prototype.getFilters = function() {
472 var filters = this.filters.children().toArray().reduce(function(prev, current) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600473 var data = $(current).text().split(/:/);
474 prev[data[0]] = data[1];
475 return prev;
Tyler Scott66a965d2016-02-29 15:41:33 -0700476 }, {});
477 //Collect a map<category, filter>.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600478 //TODO Make the return value map<category, Array<filter>>
479 return filters;
Tyler Scott66a965d2016-02-29 15:41:33 -0700480 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600481
482 /**
483 * Creates a closable alert for the user.
Tyler Scott66a965d2016-02-29 15:41:33 -0700484
Tyler Scottcdfcde82015-09-14 16:13:29 -0600485 * @param {string} message
486 * @param {string} type - Override the alert type.
487 */
488 Atmos.prototype.createAlert = function(message, type) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600489 var alert = $('<div class="alert"><div>');
Tyler Scott66a965d2016-02-29 15:41:33 -0700490 alert.addClass(type ? type : 'alert-info');
Tyler Scottcdfcde82015-09-14 16:13:29 -0600491 alert.text(message);
492 alert.append(closeButton);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600493 this.alerts.append(alert);
Tyler Scott66a965d2016-02-29 15:41:33 -0700494 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600495
496 /**
497 * Requests all of the names represented by the buttons in the elements list.
Tyler Scott66a965d2016-02-29 15:41:33 -0700498
Tyler Scottcdfcde82015-09-14 16:13:29 -0600499 * @param elements {Array<jQuery>} A list of the table row elements
Tyler Scottf355e452015-11-06 21:35:14 -0700500 * @param subsetFileName {String} If present then do a subsetting request instead.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600501 */
Tyler Scott66a965d2016-02-29 15:41:33 -0700502 Atmos.prototype.request = function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600503 //Pseudo globals.
504 var keyChain;
505 var certificateName;
506 var keyAdded = false;
Tyler Scott66a965d2016-02-29 15:41:33 -0700507 return function(elements, subsetFilename) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600508
509 var names = [];
Tyler Scott7ae6be02016-06-22 15:29:26 -0600510
Tyler Scott66a965d2016-02-29 15:41:33 -0700511 $(elements).find('.metaDataLink').each(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600512 var name = $(this).text();
513 names.push(name);
Tyler Scottf355e452015-11-06 21:35:14 -0700514 });
Tyler Scottf355e452015-11-06 21:35:14 -0700515 var subset = false;
Tyler Scott66a965d2016-02-29 15:41:33 -0700516 if (!subsetFilename) {
Tyler Scottf355e452015-11-06 21:35:14 -0700517 $('#subsetting').hide();
518 } else {
519 $('#subsetting').show();
520 subset = true;
521 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600522
523 var scope = this;
Tyler Scott384f37a2016-05-05 16:09:05 -0600524
525 //FIXME The following is temporary, it allows people to direct download from
526 //a single host with a small set of names. It is to demo the functionality but
527 //could use improvement. (Multiple servers, non static list, etc)
528 var directDls = $('#directDownloadList').empty();
Tyler Scott7ae6be02016-06-22 15:29:26 -0600529 names.forEach(function(name) {
530 if (scope.conversions[name]) {
531 //If the name exists in the conversions.
Tyler Scott384f37a2016-05-05 16:09:05 -0600532 var ele = $('<a href="http://atmos-mwsc.ucar.edu/ucar/' + conversions[name] + '" class="list-group-item>' + name + '</a>');
533 directDls.append(ele);
534 }
535 });
536
Tyler Scott66a965d2016-02-29 15:41:33 -0700537 this.requestForm.on('submit', function(e) {
538 //This will be registered for the next submit from the form.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600539 e.preventDefault();
Tyler Scottf355e452015-11-06 21:35:14 -0700540 $('#request .alert').remove();
Tyler Scottf355e452015-11-06 21:35:14 -0700541 var variables = [];
Tyler Scott66a965d2016-02-29 15:41:33 -0700542 if (subset) {
543 $('#subsetVariables .row').each(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700544 var t = $(this);
545 var values = {};
Tyler Scott66a965d2016-02-29 15:41:33 -0700546 t.find('.values input').each(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700547 var t = $(this);
548 values[t.attr('name')] = t.val();
549 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700550 variables.push({
551 variable: t.find('.variable').val(),
552 values: values
553 });
Tyler Scottf355e452015-11-06 21:35:14 -0700554 });
555 }
556
Tyler Scottcdfcde82015-09-14 16:13:29 -0600557 //Form checking
558 var dest = scope.requestForm.find('#requestDest .active');
Tyler Scott66a965d2016-02-29 15:41:33 -0700559 if (dest.length !== 1) {
Tyler Scottf355e452015-11-06 21:35:14 -0700560 var alert = $('<div class="alert alert-warning">A destination is required!' + closeButton + '<div>');
561 $('#request > .panel-body').append(alert);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600562 return;
563 }
564
Tyler Scott66a965d2016-02-29 15:41:33 -0700565 $('#request').modal('hide');
Tyler Scottb59e6de2015-09-18 14:46:30 -0600566
Tyler Scott7ae6be02016-06-22 15:29:26 -0600567 //Initial params are ok. We can close the form.
Tyler Scottb59e6de2015-09-18 14:46:30 -0600568 scope.cleanRequestForm();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600569
Tyler Scott7ae6be02016-06-22 15:29:26 -0600570 $(this).off(e); //Don't fire this again, the request must be regenerated
Tyler Scottcdfcde82015-09-14 16:13:29 -0600571
572 //Key setup
Tyler Scott66a965d2016-02-29 15:41:33 -0700573 if (!keyAdded) {
574 if (!scope.config.retrieval.demoKey || !scope.config.retrieval.demoKey.pub || !scope.config.retrieval.demoKey.priv) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600575 scope.createAlert("This host was not configured to handle retrieval! See console for details.", 'alert-danger');
576 console.error("Missing/invalid key! This must be configured in the config on the server.", scope.config.demoKey);
577 return;
578 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600579 //FIXME base64 may or may not exist in other browsers. Need a new polyfill.
Tyler Scott66a965d2016-02-29 15:41:33 -0700580 var pub = new Buffer(base64.toByteArray(scope.config.retrieval.demoKey.pub));
581 //MUST be a Buffer (Buffer != Uint8Array)
Tyler Scottcdfcde82015-09-14 16:13:29 -0600582 var priv = new Buffer(base64.toByteArray(scope.config.retrieval.demoKey.priv));
Tyler Scottcdfcde82015-09-14 16:13:29 -0600583 var identityStorage = new MemoryIdentityStorage();
584 var privateKeyStorage = new MemoryPrivateKeyStorage();
Tyler Scott7ae6be02016-06-22 15:29:26 -0600585 keyChain = new KeyChain(new IdentityManager(identityStorage,privateKeyStorage),new SelfVerifyPolicyManager(identityStorage));
Tyler Scottcdfcde82015-09-14 16:13:29 -0600586 var keyName = new Name("/retrieve/DSK-123");
Tyler Scott7ae6be02016-06-22 15:29:26 -0600587 certificateName = keyName.getSubName(0, keyName.size() - 1).append("KEY").append(keyName.get(-1)).append("ID-CERT").append("0");
Tyler Scott66a965d2016-02-29 15:41:33 -0700588 identityStorage.addKey(keyName, KeyType.RSA, new Blob(pub,false));
Tyler Scottcdfcde82015-09-14 16:13:29 -0600589 privateKeyStorage.setKeyPairForKeyName(keyName, KeyType.RSA, pub, priv);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600590 scope.face.setCommandSigningInfo(keyChain, certificateName);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600591 keyAdded = true;
Tyler Scottcdfcde82015-09-14 16:13:29 -0600592 }
593
594 //Retrieval
595 var retrievePrefix = new Name("/catalog/ui/" + guid());
Tyler Scott7ae6be02016-06-22 15:29:26 -0600596 scope.face.registerPrefix(retrievePrefix, function(prefix, interest, face, interestFilterId, filter) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700597 //On Interest
598 //This function will exist until the page exits but will likely only be used once.
Tyler Scott66a965d2016-02-29 15:41:33 -0700599 var data = new Data(interest.getName());
600 var content;
601 if (subset) {
602 content = JSON.stringify({
603 name: subsetFilename,
604 subset: variables
Tyler Scottd61bf832015-11-30 16:36:17 -0700605 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700606 } else {
607 content = JSON.stringify(names);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600608 }
Tyler Scott7ae6be02016-06-22 15:29:26 -0600609
Tyler Scott66a965d2016-02-29 15:41:33 -0700610 //Blob breaks the data! Don't use it
611 data.setContent(content);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600612
Tyler Scott66a965d2016-02-29 15:41:33 -0700613 //TODO Packetize this.
614 keyChain.sign(data, certificateName);
615
616 try {
617 face.putData(data);
618 console.log("Responded for", interest.getName().toUri(), data);
619 scope.createAlert("Data retrieval has initiated.", "alert-success");
620 } catch (e) {
621 console.error("Failed to respond to", interest.getName().toUri(), data);
622 scope.createAlert("Data retrieval failed.");
623 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700624 }, function(prefix) {
625 //On fail
626 scope.createAlert("Failed to register the retrieval URI! See console for details.", "alert-danger");
627 console.error("Failed to register URI:", prefix.toUri(), prefix);
628 }, function(prefix, registeredPrefixId) {
629 //On success
630 var name = new Name(dest.text());
631 name.append(prefix);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600632 scope.expressInterest(name, function(interest, data) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700633 //Success
634 console.log("Request for", name.toUri(), "succeeded.", interest, data);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600635 }, function() {
Tyler Scott66a965d2016-02-29 15:41:33 -0700636 console.warn("Failed to request from retrieve agent.");
Tyler Scott7ae6be02016-06-22 15:29:26 -0600637 });
638 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600639 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700640 $('#request').modal();
641 //This forces the form to be the only option.
Tyler Scott66a965d2016-02-29 15:41:33 -0700642 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600643 }();
644
645 Atmos.prototype.filterSetup = function() {
646 //Filter setup
Tyler Scottcdfcde82015-09-14 16:13:29 -0600647 var prefix = new Name(this.catalog).append("filters-initialization");
648
649 var scope = this;
650
Tyler Scott66a965d2016-02-29 15:41:33 -0700651 this.getAll(prefix, function(data) {
652 //Success
653 var raw = JSON.parse(data.replace(/[\n\0]/g, ''));
654 //Remove null byte and parse
Tyler Scottcdfcde82015-09-14 16:13:29 -0600655 console.log("Filter categories:", raw);
656
Tyler Scott66a965d2016-02-29 15:41:33 -0700657 $.each(raw, function(index, object) {
658 //Unpack list of objects
Tyler Scott7ae6be02016-06-22 15:29:26 -0600659
Tyler Scott66a965d2016-02-29 15:41:33 -0700660 $.each(object, function(category, searchOptions) {
661 //Unpack category from object (We don't know what it is called)
Tyler Scottcdfcde82015-09-14 16:13:29 -0600662 //Create the category
663 var e = $('<li><a href="#">' + category.replace(/_/g, " ") + '</a><ul class="subnav nav nav-pills nav-stacked"></ul></li>');
Tyler Scottcdfcde82015-09-14 16:13:29 -0600664 var sub = e.find('ul.subnav');
Tyler Scott66a965d2016-02-29 15:41:33 -0700665 $.each(searchOptions, function(index, name) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600666 //Create the filter list inside the category
Tyler Scott7ae6be02016-06-22 15:29:26 -0600667
Tyler Scottcdfcde82015-09-14 16:13:29 -0600668 var item = $('<li><a href="#">' + name + '</a></li>');
669 sub.append(item);
Tyler Scott66a965d2016-02-29 15:41:33 -0700670 item.click(function() {
671 //Click on the side menu filters
672 if (item.hasClass('active')) {
673 //Does the filter already exist?
Tyler Scottcdfcde82015-09-14 16:13:29 -0600674 item.removeClass('active');
675 scope.filters.find(':contains(' + category + ':' + name + ')').remove();
Tyler Scott66a965d2016-02-29 15:41:33 -0700676 } else {
677 //Add a filter
Tyler Scottcdfcde82015-09-14 16:13:29 -0600678 item.addClass('active');
679 var filter = $('<span class="label label-default"></span>');
680 filter.text(category + ':' + name);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600681 scope.filters.append(filter);
Tyler Scott66a965d2016-02-29 15:41:33 -0700682 filter.click(function() {
683 //Click on a filter
Tyler Scottcdfcde82015-09-14 16:13:29 -0600684 filter.remove();
685 item.removeClass('active');
686 });
687 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600688 });
689 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600690 //Toggle the menus. (Only respond when the immediate tab is clicked.)
Tyler Scott66a965d2016-02-29 15:41:33 -0700691 e.find('> a').click(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600692 scope.categories.find('.subnav').slideUp();
693 var t = $(this).siblings('.subnav');
Tyler Scott66a965d2016-02-29 15:41:33 -0700694 if (!t.is(':visible')) {
695 //If the sub menu is not visible
696 t.slideDown(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600697 t.triggerHandler('focus');
Tyler Scott66a965d2016-02-29 15:41:33 -0700698 });
699 //Make it visible and look at it.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600700 }
701 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600702 scope.categories.append(e);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600703 });
704 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700705 }, function(interest) {
706 //Timeout
Tyler Scottcdfcde82015-09-14 16:13:29 -0600707 scope.createAlert("Failed to initialize the filters!", "alert-danger");
708 console.error("Failed to initialize filters!", interest);
709 ga('send', 'event', 'error', 'filters');
710 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700711 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600712
713 /**
714 * This function retrieves all segments in order until it knows it has reached the last one.
715 * It then returns the final joined result.
Tyler Scott66a965d2016-02-29 15:41:33 -0700716
Tyler Scottf355e452015-11-06 21:35:14 -0700717 * @param prefix {String|Name} The ndn name we are retrieving.
718 * @param callback {function(String)} if successful, will call the callback with a string of data.
719 * @param failure {function(Interest)} if unsuccessful, will call failure with the last failed interest.
720 * @param stop {boolean} stop if no finalBlock.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600721 */
Tyler Scott66a965d2016-02-29 15:41:33 -0700722 Atmos.prototype.getAll = function(prefix, callback, failure, stop) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600723 var scope = this;
724 var d = [];
Tyler Scottd61bf832015-11-30 16:36:17 -0700725 var name = new Name(prefix);
726 var segment = 0;
Tyler Scott66a965d2016-02-29 15:41:33 -0700727 var request = function() {
Tyler Scottd61bf832015-11-30 16:36:17 -0700728 var n2 = new Name(name);
729 n2.appendSegment(segment);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600730 scope.expressInterest(n2, handleData, function(err, interest) {
731 failure(interest)
732 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700733 //Forward to handleData and ignore error
734 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700735 var handleData = function(interest, data) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600736 d.push(data.getContent().toString());
Tyler Scottf355e452015-11-06 21:35:14 -0700737 var hasFinalBlock = data.getMetaInfo().getFinalBlockId().value.length === 0;
738 var finalBlockStop = hasFinalBlock && stop;
Tyler Scott7ae6be02016-06-22 15:29:26 -0600739 if (finalBlockStop || (!hasFinalBlock && interest.getName().get(-1).toSegment() == data.getMetaInfo().getFinalBlockId().toSegment())) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600740 callback(d.join(""));
741 } else {
Tyler Scottd61bf832015-11-30 16:36:17 -0700742 segment++;
743 request();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600744 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700745 }
Tyler Scottd61bf832015-11-30 16:36:17 -0700746 request();
Tyler Scott66a965d2016-02-29 15:41:33 -0700747 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600748
Tyler Scott66a965d2016-02-29 15:41:33 -0700749 Atmos.prototype.cleanRequestForm = function() {
Tyler Scottb59e6de2015-09-18 14:46:30 -0600750 $('#requestDest').prev().removeClass('btn-success').addClass('btn-default');
751 $('#requestDropText').text('Destination');
752 $('#requestDest .active').removeClass('active');
Tyler Scottf355e452015-11-06 21:35:14 -0700753 $('#subsetMenu').attr('class', 'collapse');
754 $('#subsetVariables').empty();
755 $('#request .alert').alert('close').remove();
Tyler Scott66a965d2016-02-29 15:41:33 -0700756 }
Tyler Scottb59e6de2015-09-18 14:46:30 -0600757
Tyler Scott66a965d2016-02-29 15:41:33 -0700758 Atmos.prototype.setupRequestForm = function() {
Tyler Scottb59e6de2015-09-18 14:46:30 -0600759 var scope = this;
Tyler Scott66a965d2016-02-29 15:41:33 -0700760 this.requestForm.find('#requestCancel').click(function() {
761 $('#request').unbind('submit')//Removes all event handlers.
762 .modal('hide');
763 //Hides the form.
Tyler Scottb59e6de2015-09-18 14:46:30 -0600764 scope.cleanRequestForm();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600765 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700766 var dests = $(this.config['retrieval']['destinations'].reduce(function(prev, current) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600767 prev.push('<li><a href="#">');
768 prev.push(current);
769 prev.push("</a></li>");
770 return prev;
771 }, []).join(""));
Tyler Scott7ae6be02016-06-22 15:29:26 -0600772 this.requestForm.find('#requestDest').append(dests).on('click', 'a', function(e) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600773 $('#requestDest .active').removeClass('active');
Tyler Scottb59e6de2015-09-18 14:46:30 -0600774 var t = $(this);
775 t.parent().addClass('active');
776 $('#requestDropText').text(t.text());
777 $('#requestDest').prev().removeClass('btn-default').addClass('btn-success');
Tyler Scottcdfcde82015-09-14 16:13:29 -0600778 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700779 var addVariable = function(selector) {
780 var ele = $(selector).clone().attr('id', '');
781 ele.find('.close').click(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700782 ele.remove();
783 });
784 $('#subsetVariables').append(ele);
Tyler Scott66a965d2016-02-29 15:41:33 -0700785 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700786 $('#subsetAddVariableBtn').click(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700787 addVariable('#customTemplate');
788 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700789 $('#subsetAddTimeVariable').click(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700790 addVariable('#timeTemplate');
791 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700792 $('#subsetAddLocVariable').click(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700793 addVariable('#locationTemplate');
794 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700795 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600796
Tyler Scott66a965d2016-02-29 15:41:33 -0700797 Atmos.prototype.getMetaData = (function() {
Tyler Scott48f92cd2015-10-16 18:31:20 -0600798 var cache = {};
Tyler Scott48f92cd2015-10-16 18:31:20 -0600799 return function(element) {
800 var name = $(element).text();
Tyler Scottf355e452015-11-06 21:35:14 -0700801 ga('send', 'event', 'request', 'metaData');
Tyler Scottf355e452015-11-06 21:35:14 -0700802 var subsetButton = '<button class="btn btn-default subsetButton" type="button">Subset</button>';
Tyler Scott48f92cd2015-10-16 18:31:20 -0600803 if (cache[name]) {
Tyler Scottf355e452015-11-06 21:35:14 -0700804 return [subsetButton, '<pre class="metaData">', cache[name], '</pre>'].join('');
Tyler Scott48f92cd2015-10-16 18:31:20 -0600805 }
Tyler Scott48f92cd2015-10-16 18:31:20 -0600806 var prefix = new Name(name).append("metadata");
Tyler Scott66a965d2016-02-29 15:41:33 -0700807 var id = guid();
808 //We need an id because the return MUST be a string.
Tyler Scott48f92cd2015-10-16 18:31:20 -0600809 var ret = '<div id="' + id + '"><span class="fa fa-spinner fa-spin"></span></div>';
Tyler Scott66a965d2016-02-29 15:41:33 -0700810 this.getAll(prefix, function(data) {
Tyler Scott48f92cd2015-10-16 18:31:20 -0600811 var el = $('<pre class="metaData"></pre>');
812 el.text(data);
Tyler Scottf355e452015-11-06 21:35:14 -0700813 var container = $('<div></div>');
814 container.append($(subsetButton));
815 container.append(el);
816 $('#' + id).empty().append(container);
Tyler Scott48f92cd2015-10-16 18:31:20 -0600817 cache[name] = data;
Tyler Scott66a965d2016-02-29 15:41:33 -0700818 }, function(interest) {
Tyler Scott48f92cd2015-10-16 18:31:20 -0600819 $('#' + id).text("The metadata is unavailable for this name.");
820 console.log("Data is unavailable for " + name);
821 });
Tyler Scott48f92cd2015-10-16 18:31:20 -0600822 return ret;
Tyler Scott66a965d2016-02-29 15:41:33 -0700823 }
Tyler Scott48f92cd2015-10-16 18:31:20 -0600824 })();
825
Tyler Scottcdfcde82015-09-14 16:13:29 -0600826 return Atmos;
827
828})();