blob: 5203fdcd3a214bf78547a245169787b18bfedf02 [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) {
Chengyu Fan96130f92016-12-23 17:56:01 -0700121 return field + element.name + (last ? "/" : "");
Tyler Scott66a965d2016-02-29 15:41:33 -0700122 //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) {
Chengyu Fan96130f92016-12-23 17:56:01 -0700211 return (path == "/" ? "/" : "") + element.name + "/";
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 Scotta55f0912016-08-09 22:25:28 +0000349 prev.push('<tr><td><input class="resultSelector" type="checkbox"></td><td class="popover-container">');
350 if (current.has_metadata){
351 prev.push('<a href="#" class="metaDataLink">');
352 }
353 prev.push(current.name);
354 if (current.has_metadata){
355 prev.push('</a>');
356 }
357 prev.push('</td></tr>');
Tyler Scott66a965d2016-02-29 15:41:33 -0700358 return prev;
Tyler Scott7ae6be02016-06-22 15:29:26 -0600359 }, ['<tr><th><input id="resultSelectAll" type="checkbox"> Select All</th><th>Name</th></tr>']).join(''));
Tyler Scott66a965d2016-02-29 15:41:33 -0700360 resultDOM.find('#resultSelectAll').click(function() {
361 if ($(this).is(':checked')) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600362 resultDOM.find('.resultSelector:not([disabled])').prop('checked', true);
363 } else {
364 resultDOM.find('.resultSelector:not([disabled])').prop('checked', false);
365 }
366 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600367 this.resultTable.hide().empty().append(resultDOM).slideDown('slow');
Tyler Scottcdfcde82015-09-14 16:13:29 -0600368 this.resultMenu.find('.pageNumber').text(resultIndex + 1);
369 this.resultMenu.find('.pageLength').text(this.resultsPerPage * resultIndex + results.length);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600370 if (this.resultsPerPage * (resultIndex + 1) >= this.resultCount) {
371 this.resultMenu.find('.next').addClass('disabled');
Tyler Scott66a965d2016-02-29 15:41:33 -0700372 } else if (resultIndex === 0) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600373 this.resultMenu.find('.next').removeClass('disabled');
374 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700375 if (resultIndex === 0) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600376 this.resultMenu.find('.previous').addClass('disabled');
377 } else if (resultIndex === 1) {
378 this.resultMenu.find('.previous').removeClass('disabled');
379 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700380 $.scrollTo("#results", 500, {
381 interrupt: true
382 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700383 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600384
Tyler Scott66a965d2016-02-29 15:41:33 -0700385 Atmos.prototype.getResults = function(index) {
Tyler Scott7ae6be02016-06-22 15:29:26 -0600386
Chengyu Fan7b978f82015-12-09 17:03:23 -0700387 var scope = this;
Tyler Scottcdfcde82015-09-14 16:13:29 -0600388
Tyler Scott66a965d2016-02-29 15:41:33 -0700389 if ($('#results').hasClass('hidden')) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600390 $('#results').removeClass('hidden').slideDown();
391 }
392
Tyler Scott66a965d2016-02-29 15:41:33 -0700393 if ((scope.results.length === scope.resultCount) || (scope.resultsPerPage * (index + 1) < scope.results.length)) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600394 //console.log("We already have index", index);
Chengyu Fan7b978f82015-12-09 17:03:23 -0700395 scope.page = index;
396 scope.showResults(index);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600397 return;
398 }
399
Tyler Scott66a965d2016-02-29 15:41:33 -0700400 if (scope.name === null ) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600401 console.error("This shouldn't be reached! We are getting results before a search has occured!");
402 throw new Error("Illegal State");
403 }
404
Chengyu Fan7b978f82015-12-09 17:03:23 -0700405 var interestName = new Name(scope.name);
Chengyu Fan7b978f82015-12-09 17:03:23 -0700406 // Interest name should be /<catalog-prefix>/query/<query-param>/<version>/<#seq>
407 if (scope.name.size() === (scope.catalogPrefix.size() + 3)) {
408 interestName = interestName.appendSegment(scope.retrievedSegments++);
Tyler Scott66a965d2016-02-29 15:41:33 -0700409 //console.log("Requesting data index: (", scope.retrievedSegments - 1, ") at ", interestName.toUri());
Chengyu Fan7b978f82015-12-09 17:03:23 -0700410 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600411
Tyler Scott7ae6be02016-06-22 15:29:26 -0600412 this.expressInterest(interestName, function(interest, data) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700413 //Response
Tyler Scott66a965d2016-02-29 15:41:33 -0700414 if (data.getContent().length === 0) {
415 scope.resultMenu.find('.totalResults').text(0);
416 scope.resultMenu.find('.pageNumber').text(0);
417 scope.resultMenu.find('.pageLength').text(0);
418 console.log("Empty response.");
419 scope.resultTable.html("<tr><td>Empty response. This usually means no results.</td></tr>");
420 return;
Tyler Scottcdfcde82015-09-14 16:13:29 -0600421 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600422
Tyler Scott66a965d2016-02-29 15:41:33 -0700423 var content = JSON.parse(data.getContent().toString().replace(/[\n\0]/g, ""));
424
425 if (!content.results) {
426 scope.resultMenu.find('.totalResults').text(0);
427 scope.resultMenu.find('.pageNumber').text(0);
428 scope.resultMenu.find('.pageLength').text(0);
429 console.log("No results were found!");
430 scope.resultTable.html("<tr><td>No Results</td></tr>");
431 return;
432 }
433
434 scope.results = scope.results.concat(content.results);
Tyler Scott66a965d2016-02-29 15:41:33 -0700435 scope.resultCount = content.resultCount;
Tyler Scott66a965d2016-02-29 15:41:33 -0700436 scope.resultMenu.find('.totalResults').text(scope.resultCount);
Tyler Scott66a965d2016-02-29 15:41:33 -0700437 scope.page = index;
Tyler Scott66a965d2016-02-29 15:41:33 -0700438 // reset scope.name
439 scope.name = new Name(data.getName().getPrefix(scope.catalogPrefix.size() + 3));
Tyler Scott66a965d2016-02-29 15:41:33 -0700440 scope.getResults(index);
441 //Keep calling this until we have enough data.
Tyler Scott7ae6be02016-06-22 15:29:26 -0600442 }, function() {});//Ignore failure
Tyler Scott66a965d2016-02-29 15:41:33 -0700443
444 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600445 Atmos.prototype.query = function(prefix, parameters, callback, timeout) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600446 var queryPrefix = new Name(prefix);
447 queryPrefix.append("query");
Tyler Scottcdfcde82015-09-14 16:13:29 -0600448 var jsonString = JSON.stringify(parameters);
449 queryPrefix.append(jsonString);
Tyler Scott66a965d2016-02-29 15:41:33 -0700450 this.expressInterest(queryPrefix, callback, timeout);
Tyler Scott66a965d2016-02-29 15:41:33 -0700451 }
Tyler Scottd61bf832015-11-30 16:36:17 -0700452
Tyler Scott66a965d2016-02-29 15:41:33 -0700453 Atmos.prototype.expressInterest = function(name, success, failure) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700454 var interest = new Interest(name);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600455 interest.setInterestLifetimeMilliseconds(500);
Tyler Scott66a965d2016-02-29 15:41:33 -0700456 interest.setMustBeFresh(true);
Tyler Scott66a965d2016-02-29 15:41:33 -0700457 const face = this.face;
Tyler Scott66a965d2016-02-29 15:41:33 -0700458 async.retry(4, function(done) {
459 face.expressInterest(interest, function(interest, data) {
Tyler Scottd61bf832015-11-30 16:36:17 -0700460 done();
Tyler Scott66a965d2016-02-29 15:41:33 -0700461 success(interest, data);
462 }, function(interest) {
463 done("Interest timed out 4 times.", interest);
464 });
465 }, function(err, interest) {
466 if (err) {
467 console.log(err, interest);
468 failure(interest);
Tyler Scott8724e422015-10-13 17:59:07 -0600469 }
Tyler Scottd61bf832015-11-30 16:36:17 -0700470 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700471 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600472
473 /**
474 * This function returns a map of all the categories active filters.
475 * @return {Object<string, string>}
476 */
Tyler Scott66a965d2016-02-29 15:41:33 -0700477 Atmos.prototype.getFilters = function() {
478 var filters = this.filters.children().toArray().reduce(function(prev, current) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600479 var data = $(current).text().split(/:/);
480 prev[data[0]] = data[1];
481 return prev;
Tyler Scott66a965d2016-02-29 15:41:33 -0700482 }, {});
483 //Collect a map<category, filter>.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600484 //TODO Make the return value map<category, Array<filter>>
485 return filters;
Tyler Scott66a965d2016-02-29 15:41:33 -0700486 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600487
488 /**
489 * Creates a closable alert for the user.
Tyler Scott66a965d2016-02-29 15:41:33 -0700490
Tyler Scottcdfcde82015-09-14 16:13:29 -0600491 * @param {string} message
492 * @param {string} type - Override the alert type.
493 */
494 Atmos.prototype.createAlert = function(message, type) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600495 var alert = $('<div class="alert"><div>');
Tyler Scott66a965d2016-02-29 15:41:33 -0700496 alert.addClass(type ? type : 'alert-info');
Tyler Scottcdfcde82015-09-14 16:13:29 -0600497 alert.text(message);
498 alert.append(closeButton);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600499 this.alerts.append(alert);
Tyler Scott66a965d2016-02-29 15:41:33 -0700500 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600501
502 /**
503 * Requests all of the names represented by the buttons in the elements list.
Tyler Scott66a965d2016-02-29 15:41:33 -0700504
Tyler Scottcdfcde82015-09-14 16:13:29 -0600505 * @param elements {Array<jQuery>} A list of the table row elements
Tyler Scottf355e452015-11-06 21:35:14 -0700506 * @param subsetFileName {String} If present then do a subsetting request instead.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600507 */
Tyler Scott66a965d2016-02-29 15:41:33 -0700508 Atmos.prototype.request = function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600509 //Pseudo globals.
510 var keyChain;
511 var certificateName;
512 var keyAdded = false;
Tyler Scott66a965d2016-02-29 15:41:33 -0700513 return function(elements, subsetFilename) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600514
515 var names = [];
Tyler Scott7ae6be02016-06-22 15:29:26 -0600516
Tyler Scott66a965d2016-02-29 15:41:33 -0700517 $(elements).find('.metaDataLink').each(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600518 var name = $(this).text();
519 names.push(name);
Tyler Scottf355e452015-11-06 21:35:14 -0700520 });
Tyler Scottf355e452015-11-06 21:35:14 -0700521 var subset = false;
Tyler Scott66a965d2016-02-29 15:41:33 -0700522 if (!subsetFilename) {
Tyler Scottf355e452015-11-06 21:35:14 -0700523 $('#subsetting').hide();
524 } else {
525 $('#subsetting').show();
526 subset = true;
527 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600528
529 var scope = this;
Tyler Scott384f37a2016-05-05 16:09:05 -0600530
531 //FIXME The following is temporary, it allows people to direct download from
532 //a single host with a small set of names. It is to demo the functionality but
533 //could use improvement. (Multiple servers, non static list, etc)
534 var directDls = $('#directDownloadList').empty();
Tyler Scott7ae6be02016-06-22 15:29:26 -0600535 names.forEach(function(name) {
536 if (scope.conversions[name]) {
537 //If the name exists in the conversions.
Tyler Scott384f37a2016-05-05 16:09:05 -0600538 var ele = $('<a href="http://atmos-mwsc.ucar.edu/ucar/' + conversions[name] + '" class="list-group-item>' + name + '</a>');
539 directDls.append(ele);
540 }
541 });
542
Tyler Scott66a965d2016-02-29 15:41:33 -0700543 this.requestForm.on('submit', function(e) {
544 //This will be registered for the next submit from the form.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600545 e.preventDefault();
Tyler Scottf355e452015-11-06 21:35:14 -0700546 $('#request .alert').remove();
Tyler Scottf355e452015-11-06 21:35:14 -0700547 var variables = [];
Tyler Scott66a965d2016-02-29 15:41:33 -0700548 if (subset) {
549 $('#subsetVariables .row').each(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700550 var t = $(this);
551 var values = {};
Tyler Scott66a965d2016-02-29 15:41:33 -0700552 t.find('.values input').each(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700553 var t = $(this);
554 values[t.attr('name')] = t.val();
555 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700556 variables.push({
557 variable: t.find('.variable').val(),
558 values: values
559 });
Tyler Scottf355e452015-11-06 21:35:14 -0700560 });
561 }
562
Tyler Scottcdfcde82015-09-14 16:13:29 -0600563 //Form checking
564 var dest = scope.requestForm.find('#requestDest .active');
Tyler Scott66a965d2016-02-29 15:41:33 -0700565 if (dest.length !== 1) {
Tyler Scottf355e452015-11-06 21:35:14 -0700566 var alert = $('<div class="alert alert-warning">A destination is required!' + closeButton + '<div>');
567 $('#request > .panel-body').append(alert);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600568 return;
569 }
570
Tyler Scott66a965d2016-02-29 15:41:33 -0700571 $('#request').modal('hide');
Tyler Scottb59e6de2015-09-18 14:46:30 -0600572
Tyler Scott7ae6be02016-06-22 15:29:26 -0600573 //Initial params are ok. We can close the form.
Tyler Scottb59e6de2015-09-18 14:46:30 -0600574 scope.cleanRequestForm();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600575
Tyler Scott7ae6be02016-06-22 15:29:26 -0600576 $(this).off(e); //Don't fire this again, the request must be regenerated
Tyler Scottcdfcde82015-09-14 16:13:29 -0600577
578 //Key setup
Tyler Scott66a965d2016-02-29 15:41:33 -0700579 if (!keyAdded) {
580 if (!scope.config.retrieval.demoKey || !scope.config.retrieval.demoKey.pub || !scope.config.retrieval.demoKey.priv) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600581 scope.createAlert("This host was not configured to handle retrieval! See console for details.", 'alert-danger');
582 console.error("Missing/invalid key! This must be configured in the config on the server.", scope.config.demoKey);
583 return;
584 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600585 //FIXME base64 may or may not exist in other browsers. Need a new polyfill.
Tyler Scott66a965d2016-02-29 15:41:33 -0700586 var pub = new Buffer(base64.toByteArray(scope.config.retrieval.demoKey.pub));
587 //MUST be a Buffer (Buffer != Uint8Array)
Tyler Scottcdfcde82015-09-14 16:13:29 -0600588 var priv = new Buffer(base64.toByteArray(scope.config.retrieval.demoKey.priv));
Tyler Scottcdfcde82015-09-14 16:13:29 -0600589 var identityStorage = new MemoryIdentityStorage();
590 var privateKeyStorage = new MemoryPrivateKeyStorage();
Tyler Scott7ae6be02016-06-22 15:29:26 -0600591 keyChain = new KeyChain(new IdentityManager(identityStorage,privateKeyStorage),new SelfVerifyPolicyManager(identityStorage));
Tyler Scottcdfcde82015-09-14 16:13:29 -0600592 var keyName = new Name("/retrieve/DSK-123");
Tyler Scott7ae6be02016-06-22 15:29:26 -0600593 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 -0700594 identityStorage.addKey(keyName, KeyType.RSA, new Blob(pub,false));
Tyler Scottcdfcde82015-09-14 16:13:29 -0600595 privateKeyStorage.setKeyPairForKeyName(keyName, KeyType.RSA, pub, priv);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600596 scope.face.setCommandSigningInfo(keyChain, certificateName);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600597 keyAdded = true;
Tyler Scottcdfcde82015-09-14 16:13:29 -0600598 }
599
600 //Retrieval
601 var retrievePrefix = new Name("/catalog/ui/" + guid());
Tyler Scott7ae6be02016-06-22 15:29:26 -0600602 scope.face.registerPrefix(retrievePrefix, function(prefix, interest, face, interestFilterId, filter) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700603 //On Interest
604 //This function will exist until the page exits but will likely only be used once.
Tyler Scott66a965d2016-02-29 15:41:33 -0700605 var data = new Data(interest.getName());
606 var content;
607 if (subset) {
608 content = JSON.stringify({
609 name: subsetFilename,
610 subset: variables
Tyler Scottd61bf832015-11-30 16:36:17 -0700611 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700612 } else {
613 content = JSON.stringify(names);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600614 }
Tyler Scott7ae6be02016-06-22 15:29:26 -0600615
Tyler Scott66a965d2016-02-29 15:41:33 -0700616 //Blob breaks the data! Don't use it
617 data.setContent(content);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600618
Tyler Scott66a965d2016-02-29 15:41:33 -0700619 //TODO Packetize this.
620 keyChain.sign(data, certificateName);
621
622 try {
623 face.putData(data);
624 console.log("Responded for", interest.getName().toUri(), data);
625 scope.createAlert("Data retrieval has initiated.", "alert-success");
626 } catch (e) {
627 console.error("Failed to respond to", interest.getName().toUri(), data);
628 scope.createAlert("Data retrieval failed.");
629 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700630 }, function(prefix) {
631 //On fail
632 scope.createAlert("Failed to register the retrieval URI! See console for details.", "alert-danger");
633 console.error("Failed to register URI:", prefix.toUri(), prefix);
634 }, function(prefix, registeredPrefixId) {
635 //On success
636 var name = new Name(dest.text());
637 name.append(prefix);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600638 scope.expressInterest(name, function(interest, data) {
Tyler Scott66a965d2016-02-29 15:41:33 -0700639 //Success
640 console.log("Request for", name.toUri(), "succeeded.", interest, data);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600641 }, function() {
Tyler Scott66a965d2016-02-29 15:41:33 -0700642 console.warn("Failed to request from retrieve agent.");
Tyler Scott7ae6be02016-06-22 15:29:26 -0600643 });
644 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600645 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700646 $('#request').modal();
647 //This forces the form to be the only option.
Tyler Scott66a965d2016-02-29 15:41:33 -0700648 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600649 }();
650
651 Atmos.prototype.filterSetup = function() {
652 //Filter setup
Tyler Scottcdfcde82015-09-14 16:13:29 -0600653 var prefix = new Name(this.catalog).append("filters-initialization");
654
655 var scope = this;
656
Tyler Scott66a965d2016-02-29 15:41:33 -0700657 this.getAll(prefix, function(data) {
658 //Success
659 var raw = JSON.parse(data.replace(/[\n\0]/g, ''));
660 //Remove null byte and parse
Tyler Scottcdfcde82015-09-14 16:13:29 -0600661 console.log("Filter categories:", raw);
662
Tyler Scott66a965d2016-02-29 15:41:33 -0700663 $.each(raw, function(index, object) {
664 //Unpack list of objects
Tyler Scott7ae6be02016-06-22 15:29:26 -0600665
Tyler Scott66a965d2016-02-29 15:41:33 -0700666 $.each(object, function(category, searchOptions) {
667 //Unpack category from object (We don't know what it is called)
Tyler Scottcdfcde82015-09-14 16:13:29 -0600668 //Create the category
669 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 -0600670 var sub = e.find('ul.subnav');
Tyler Scott66a965d2016-02-29 15:41:33 -0700671 $.each(searchOptions, function(index, name) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600672 //Create the filter list inside the category
Tyler Scott7ae6be02016-06-22 15:29:26 -0600673
Tyler Scottcdfcde82015-09-14 16:13:29 -0600674 var item = $('<li><a href="#">' + name + '</a></li>');
675 sub.append(item);
Tyler Scott66a965d2016-02-29 15:41:33 -0700676 item.click(function() {
677 //Click on the side menu filters
678 if (item.hasClass('active')) {
679 //Does the filter already exist?
Tyler Scottcdfcde82015-09-14 16:13:29 -0600680 item.removeClass('active');
681 scope.filters.find(':contains(' + category + ':' + name + ')').remove();
Tyler Scott66a965d2016-02-29 15:41:33 -0700682 } else {
683 //Add a filter
Tyler Scottcdfcde82015-09-14 16:13:29 -0600684 item.addClass('active');
685 var filter = $('<span class="label label-default"></span>');
686 filter.text(category + ':' + name);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600687 scope.filters.append(filter);
Tyler Scott66a965d2016-02-29 15:41:33 -0700688 filter.click(function() {
689 //Click on a filter
Tyler Scottcdfcde82015-09-14 16:13:29 -0600690 filter.remove();
691 item.removeClass('active');
692 });
693 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600694 });
695 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600696 //Toggle the menus. (Only respond when the immediate tab is clicked.)
Tyler Scott66a965d2016-02-29 15:41:33 -0700697 e.find('> a').click(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600698 scope.categories.find('.subnav').slideUp();
699 var t = $(this).siblings('.subnav');
Tyler Scott66a965d2016-02-29 15:41:33 -0700700 if (!t.is(':visible')) {
701 //If the sub menu is not visible
702 t.slideDown(function() {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600703 t.triggerHandler('focus');
Tyler Scott66a965d2016-02-29 15:41:33 -0700704 });
705 //Make it visible and look at it.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600706 }
707 });
Tyler Scottcdfcde82015-09-14 16:13:29 -0600708 scope.categories.append(e);
Tyler Scottcdfcde82015-09-14 16:13:29 -0600709 });
710 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700711 }, function(interest) {
712 //Timeout
Tyler Scottcdfcde82015-09-14 16:13:29 -0600713 scope.createAlert("Failed to initialize the filters!", "alert-danger");
714 console.error("Failed to initialize filters!", interest);
715 ga('send', 'event', 'error', 'filters');
716 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700717 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600718
719 /**
720 * This function retrieves all segments in order until it knows it has reached the last one.
721 * It then returns the final joined result.
Tyler Scott66a965d2016-02-29 15:41:33 -0700722
Tyler Scottf355e452015-11-06 21:35:14 -0700723 * @param prefix {String|Name} The ndn name we are retrieving.
724 * @param callback {function(String)} if successful, will call the callback with a string of data.
725 * @param failure {function(Interest)} if unsuccessful, will call failure with the last failed interest.
726 * @param stop {boolean} stop if no finalBlock.
Tyler Scottcdfcde82015-09-14 16:13:29 -0600727 */
Tyler Scott66a965d2016-02-29 15:41:33 -0700728 Atmos.prototype.getAll = function(prefix, callback, failure, stop) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600729 var scope = this;
730 var d = [];
Tyler Scottd61bf832015-11-30 16:36:17 -0700731 var name = new Name(prefix);
732 var segment = 0;
Tyler Scott66a965d2016-02-29 15:41:33 -0700733 var request = function() {
Tyler Scottd61bf832015-11-30 16:36:17 -0700734 var n2 = new Name(name);
735 n2.appendSegment(segment);
Tyler Scott7ae6be02016-06-22 15:29:26 -0600736 scope.expressInterest(n2, handleData, function(err, interest) {
737 failure(interest)
738 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700739 //Forward to handleData and ignore error
740 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700741 var handleData = function(interest, data) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600742 d.push(data.getContent().toString());
Tyler Scottf355e452015-11-06 21:35:14 -0700743 var hasFinalBlock = data.getMetaInfo().getFinalBlockId().value.length === 0;
744 var finalBlockStop = hasFinalBlock && stop;
Tyler Scott7ae6be02016-06-22 15:29:26 -0600745 if (finalBlockStop || (!hasFinalBlock && interest.getName().get(-1).toSegment() == data.getMetaInfo().getFinalBlockId().toSegment())) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600746 callback(d.join(""));
747 } else {
Tyler Scottd61bf832015-11-30 16:36:17 -0700748 segment++;
749 request();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600750 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700751 }
Tyler Scottd61bf832015-11-30 16:36:17 -0700752 request();
Tyler Scott66a965d2016-02-29 15:41:33 -0700753 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600754
Tyler Scott66a965d2016-02-29 15:41:33 -0700755 Atmos.prototype.cleanRequestForm = function() {
Tyler Scottb59e6de2015-09-18 14:46:30 -0600756 $('#requestDest').prev().removeClass('btn-success').addClass('btn-default');
757 $('#requestDropText').text('Destination');
758 $('#requestDest .active').removeClass('active');
Tyler Scottf355e452015-11-06 21:35:14 -0700759 $('#subsetMenu').attr('class', 'collapse');
760 $('#subsetVariables').empty();
761 $('#request .alert').alert('close').remove();
Tyler Scott66a965d2016-02-29 15:41:33 -0700762 }
Tyler Scottb59e6de2015-09-18 14:46:30 -0600763
Tyler Scott66a965d2016-02-29 15:41:33 -0700764 Atmos.prototype.setupRequestForm = function() {
Tyler Scottb59e6de2015-09-18 14:46:30 -0600765 var scope = this;
Tyler Scott66a965d2016-02-29 15:41:33 -0700766 this.requestForm.find('#requestCancel').click(function() {
767 $('#request').unbind('submit')//Removes all event handlers.
768 .modal('hide');
769 //Hides the form.
Tyler Scottb59e6de2015-09-18 14:46:30 -0600770 scope.cleanRequestForm();
Tyler Scottcdfcde82015-09-14 16:13:29 -0600771 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700772 var dests = $(this.config['retrieval']['destinations'].reduce(function(prev, current) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600773 prev.push('<li><a href="#">');
774 prev.push(current);
775 prev.push("</a></li>");
776 return prev;
777 }, []).join(""));
Tyler Scott7ae6be02016-06-22 15:29:26 -0600778 this.requestForm.find('#requestDest').append(dests).on('click', 'a', function(e) {
Tyler Scottcdfcde82015-09-14 16:13:29 -0600779 $('#requestDest .active').removeClass('active');
Tyler Scottb59e6de2015-09-18 14:46:30 -0600780 var t = $(this);
781 t.parent().addClass('active');
782 $('#requestDropText').text(t.text());
783 $('#requestDest').prev().removeClass('btn-default').addClass('btn-success');
Tyler Scottcdfcde82015-09-14 16:13:29 -0600784 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700785 var addVariable = function(selector) {
786 var ele = $(selector).clone().attr('id', '');
787 ele.find('.close').click(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700788 ele.remove();
789 });
790 $('#subsetVariables').append(ele);
Tyler Scott66a965d2016-02-29 15:41:33 -0700791 }
Tyler Scott66a965d2016-02-29 15:41:33 -0700792 $('#subsetAddVariableBtn').click(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700793 addVariable('#customTemplate');
794 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700795 $('#subsetAddTimeVariable').click(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700796 addVariable('#timeTemplate');
797 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700798 $('#subsetAddLocVariable').click(function() {
Tyler Scottf355e452015-11-06 21:35:14 -0700799 addVariable('#locationTemplate');
800 });
Tyler Scott66a965d2016-02-29 15:41:33 -0700801 }
Tyler Scottcdfcde82015-09-14 16:13:29 -0600802
Tyler Scott66a965d2016-02-29 15:41:33 -0700803 Atmos.prototype.getMetaData = (function() {
Tyler Scott48f92cd2015-10-16 18:31:20 -0600804 var cache = {};
Tyler Scott48f92cd2015-10-16 18:31:20 -0600805 return function(element) {
806 var name = $(element).text();
Tyler Scottf355e452015-11-06 21:35:14 -0700807 ga('send', 'event', 'request', 'metaData');
Tyler Scottf355e452015-11-06 21:35:14 -0700808 var subsetButton = '<button class="btn btn-default subsetButton" type="button">Subset</button>';
Tyler Scott48f92cd2015-10-16 18:31:20 -0600809 if (cache[name]) {
Tyler Scottf355e452015-11-06 21:35:14 -0700810 return [subsetButton, '<pre class="metaData">', cache[name], '</pre>'].join('');
Tyler Scott48f92cd2015-10-16 18:31:20 -0600811 }
Tyler Scott48f92cd2015-10-16 18:31:20 -0600812 var prefix = new Name(name).append("metadata");
Tyler Scott66a965d2016-02-29 15:41:33 -0700813 var id = guid();
814 //We need an id because the return MUST be a string.
Tyler Scott48f92cd2015-10-16 18:31:20 -0600815 var ret = '<div id="' + id + '"><span class="fa fa-spinner fa-spin"></span></div>';
Tyler Scott66a965d2016-02-29 15:41:33 -0700816 this.getAll(prefix, function(data) {
Tyler Scott48f92cd2015-10-16 18:31:20 -0600817 var el = $('<pre class="metaData"></pre>');
818 el.text(data);
Tyler Scottf355e452015-11-06 21:35:14 -0700819 var container = $('<div></div>');
820 container.append($(subsetButton));
821 container.append(el);
822 $('#' + id).empty().append(container);
Tyler Scott48f92cd2015-10-16 18:31:20 -0600823 cache[name] = data;
Tyler Scott66a965d2016-02-29 15:41:33 -0700824 }, function(interest) {
Tyler Scott48f92cd2015-10-16 18:31:20 -0600825 $('#' + id).text("The metadata is unavailable for this name.");
826 console.log("Data is unavailable for " + name);
827 });
Tyler Scott48f92cd2015-10-16 18:31:20 -0600828 return ret;
Tyler Scott66a965d2016-02-29 15:41:33 -0700829 }
Tyler Scott48f92cd2015-10-16 18:31:20 -0600830 })();
831
Tyler Scottcdfcde82015-09-14 16:13:29 -0600832 return Atmos;
833
834})();