blob: 5241edf7052466ea3551ca890e2fb38792de9990 [file] [log] [blame]
Tyler Scottf08ab962015-06-30 16:31:29 -06001//{@ @todo: this need to be configured before the document load
Tyler Scott3c17d5f2015-06-23 17:49:29 -06002var catalog = "/catalog/myUniqueName";
Tyler Scotta1ac69d2015-07-02 17:42:03 -06003var config = {
4 host: "atmos-csu.research-lan.colostate.edu",
Tyler Scott3c17d5f2015-06-23 17:49:29 -06005 port: 9696
Tyler Scotta1ac69d2015-07-02 17:42:03 -06006};
Tyler Scott3c17d5f2015-06-23 17:49:29 -06007
8// @}
9
Tyler Scotta1ac69d2015-07-02 17:42:03 -060010var atmos = {}; //Comment this out if you don't want debug access.
11
12//Run when the document loads.
13$(function () {
Tyler Scott7d076e22015-07-06 19:21:50 -060014
15 //remove "atmos =" if you don't want debug access
Tyler Scotta1ac69d2015-07-02 17:42:03 -060016 atmos = new Atmos(catalog, config);
Tyler Scottf65b7102015-06-30 18:40:14 -060017
Tyler Scott3c17d5f2015-06-23 17:49:29 -060018});
19
Tyler Scott7d076e22015-07-06 19:21:50 -060020/*
21 Atmos
22 Version 2
23*/
24
25function Atmos(catalog, config){
26 "use strict";
27 //Internal variables.
28 this.results = []
29 this.resultCount = 0;
30 this.page = 1;
31 this.totalPages = 1;
32 this.selectedSearch = {};
33 this.dropdown = [];
34 this.state = {};
35 this.currentViewIndex = 0;
36
37 this.face = new Face(config);
38 this.categories = $('#side-menu');
39 this.resultTable = $('#resultTable');
40
41 var scope = this;
42
43 this.resultTable.on('click', '.interest-button', function(){
44 var button = $(this);
45
46 var name = button.parent().prev().text();
47 var interest = new Interest(new Name('/retrieve' + name));
48 scope.face.expressInterest(interest, function(){
49 var message = $('<div class="success"><span class="glyphicon glyphicon-ok"></span> Success!</div>');
50 message.insertAfter(button);
51 message.fadeOut(5000);
52 }, function(){
53 var message = $('<div class="fail"><span class="glyphicon glyphicon-remove"></span> Failed!</div>');
54 message.insertAfter(button);
55 message.fadeOut(5000);
56 });
57
58 });
59
60 $.getJSON("search_catagories.json").done(function (data) {
61 $.each(data, function (pageSection, contents) {
62 if (pageSection == "SearchCatagories") {
63 $.each(contents, function (search, searchOptions) {
64 var e = $('<li><a href="#">' + search.replace(/\_/g, " ") + '</a><ul class="subnav nav nav-pills nav-stacked"></ul></li>');
65
66 var sub = e.find('ul.subnav');
67 $.each(searchOptions, function(index, name){
68 var item = $('<li><a href="#">' + name + '</a></li>');
69 sub.append(item);
70 item.click(function(){
71 scope.submitCatalogSearch(name);
72 });
73 });
74
75 //Toggle the menus.
76 e.click(function(){
77 scope.categories.find('.subnav').slideUp();
78 var t = $(this).find('.subnav');
79 if ( !t.is(':visible')){
80 t.slideDown().triggerHandler('focus'); //Cancel other animations and slide down.
81 }
82 });
83
84 scope.categories.append(e);
85 });
86 }
87 });
88 });
89
90 $('#searchBar').submit(function(e){
91 e.preventDefault();
92 })
93
94}
95
96Atmos.prototype.onData = function(data) {
97 var payloadStr = data.content.toString().split("\n")[0];
98
99 var queryResults = JSON.parse(payloadStr);
100
101 var scope = this;
102
103 $.each(this.queryResults, function (queryResult, field) {
104
105 if (queryResult == "next") {
106 scope.populateAutocomplete(field);
107 }
108
109 $.each(field, function (entryCount, name) {
110 scope.results.push(name);
111 });
112 });
113
114 // Calculating the current page and the view
115 this.totalPages = Math.ceil(this.resultCount / 20);
116 this.populateResults(0);
117}
118
119Atmos.prototype.query = function(prefix, parameters, callback, pipeline) {
120 this.results = [];
121 this.dropdown = [];
122 this.resultTable.empty();
123 this.resultTable.append('<tr><th colspan="2">Results</th></tr>');
124
125 var queryPrefix = new Name(prefix);
126 queryPrefix.append("query");
127
128 var jsonString = JSON.stringify(parameters);
129 queryPrefix.append(jsonString);
130
131 this.state = {
132 prefix: new Name(prefix),
133 userOnData: callback,
134 outstanding: {},
135 nextSegment: 0,
136 };
137
138 /*if (state.hasOwnProperty("version")) {
139 console.log("state already has version");
140 }*/
141
142 var queryInterest = new Interest(queryPrefix);
143 queryInterest.setInterestLifetimeMilliseconds(10000);
144
145 var scope = this;
146
147 this.face.expressInterest(queryInterest,
148 function(){ //FIXME
149 scope.onQueryData.apply(scope, arguments); //TODO
150 }, function(){
151 scope.onQueryTimeout.apply(scope, arguments);
152 }
153 );
154
155 this.state["outstanding"][queryInterest.getName().toUri()] = 0;
156}
157
158Atmos.prototype.submitCatalogSearch = function(field) {
159 console.log("Sumbit Catalog Search: " + field);
160 // @todo: this logic isn't quite right
161 var remove = false;
162 var scope = this;
163 $.each(scope.selectedSearch, function (search, f) {
164 if (field == f) {
165 delete scope.selectedSearch[field];
166 remove = true;
167 }
168 });
169 if (!remove) {
170 $.each(scope.searchMenuOptions, function (search, fields) {
171 $.each(fields, function (index, f) {
172 if (f == field) {
173 scope.selectedSearch[search] = field;
174 }
175 });
176 });
177 }
178 this.query(scope.catalog, scope.selectedSearch, function(){
179 scope.onData.apply(scope, arguments); //Unknown arguments. FIXME (Works but could be improved for readability)
180 }, 1);
181 scope.populateCurrentSelections();
182 return false;//?? Is this used?
183}
184
185Atmos.prototype.expressNextInterest = function() {
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600186 // @todo pipelines
187 var nextName = new Name(state["results"]);
188 nextName.appendSegment(state["nextSegment"]);
189
190 var nextInterest = new Interest(nextName);
191 nextInterest.setInterestLifetimeMilliseconds(10000);
192
Tyler Scott7d076e22015-07-06 19:21:50 -0600193 var scope = this;
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600194
Tyler Scott7d076e22015-07-06 19:21:50 -0600195 this.face.expressInterest(nextInterest,
196 function(){
197 scope.onQueryResultsData.apply(scope, arguments); //FIXME
198 },
199 function(){
200 scope.onQueryResultsTimeout.apply(scope, arguments); //FIXME
201 });
202
203 this.state["nextSegment"] ++;
204 this.state["outstanding"][nextName.toUri()] = 0;
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600205}
206
Tyler Scott7d076e22015-07-06 19:21:50 -0600207Atmos.prototype.onQueryData = function(interest, data) {
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600208 var name = data.getName();
209
Tyler Scott7d076e22015-07-06 19:21:50 -0600210 delete this.state["outstanding"][interest.getName().toUri()];
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600211
Tyler Scott7d076e22015-07-06 19:21:50 -0600212 this.state["version"] = name.get(this.state["prefix"].size() + 2).toVersion();
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600213
Tyler Scott7d076e22015-07-06 19:21:50 -0600214 this.state["results"] = new Name(this.state["prefix"]).append("query-results").appendVersion(this.state["version"]);
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600215
Tyler Scott7d076e22015-07-06 19:21:50 -0600216 this.expressNextInterest();
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600217}
218
Tyler Scott7d076e22015-07-06 19:21:50 -0600219Atmos.prototype.onQueryResultsData = function(interest, data) {
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600220 var name = data.getName();
Tyler Scott7d076e22015-07-06 19:21:50 -0600221 delete this.state["outstanding"][interest.getName().toUri()];
Tyler Scottf08ab962015-06-30 16:31:29 -0600222 if (!name.get(-1).equals(data.getMetaInfo().getFinalBlockId())) {
Tyler Scott7d076e22015-07-06 19:21:50 -0600223 this.expressNextInterest();
Tyler Scottf08ab962015-06-30 16:31:29 -0600224 } //else {
225 //alert("found final block");
226 //}
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600227
Tyler Scott7d076e22015-07-06 19:21:50 -0600228 this.state["userOnData"](data);
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600229}
230
Tyler Scott7d076e22015-07-06 19:21:50 -0600231Atmos.prototype.onQueryTimeout = function(interest) {
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600232 var uri = interest.getName().toUri();
Tyler Scott7d076e22015-07-06 19:21:50 -0600233 if (this.state["outstanding"][uri] < 1) {
234 this.state["outstanding"][uri] ++;
235 var scope = this;
236 this.face.expressInterest(interest,
237 function(){
238 scope.onQueryData.apply(scope, arguments);
239 },
240 function(){
241 scope.onQueryTimeout.apply(scope, arguments);
242 });
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600243 } else {
Tyler Scott7d076e22015-07-06 19:21:50 -0600244 delete this.state["outstanding"][uri];
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600245
246 // We modify the autocomplete box here because we need to know
247 // we have all of the entries first. Fairly hacky.
Tyler Scott7d076e22015-07-06 19:21:50 -0600248 /* TODO FIXME
249 var autocompleteFullName = this.autocompleteText.value;
250 for (var i = 0; i < dropdown.length; ++i) {
251 if (this.dropdown[i].substr(0, dropdown[i].length - 1).toUpperCase === this.autocompleteText.value.toUpperCase || dropdown.length == 1) {
252 autocompleteText.value = dropdown[i];
253 }
254 }
255 */
256 }
257}
258
259Atmos.prototype.onQueryResultsTimeout = function(interest) {
260 var uri = interest.getName().toUri();
261 if (this.state["outstanding"][uri] < 1) {
262 this.state["outstanding"][uri] ++;
263 var scope = this;
264 this.face.expressInterest(interest,
265 function(){
266 scope.onQueryResultsData.apply(scope, arguments);
267 },
268 function(){
269 scope.onQueryResultsTimeout.apply(scope, arguments);
270 });
271 } else {
272 delete this.state["outstanding"][uri];
273 // We modify the autocomplete box here because we need to know
274 // we have all of the entries first. Fairly hacky.
275 /* TODO FIXME
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600276 var autocompleteFullName = autocompleteText.value;
277 for (var i = 0; i < dropdown.length; ++i) {
278 if (dropdown[i].substr(0, dropdown[i].length - 1).toUpperCase === autocompleteText.value.toUpperCase || dropdown.length == 1) {
279 autocompleteText.value = dropdown[i];
280 }
281 }
Tyler Scott7d076e22015-07-06 19:21:50 -0600282 */
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600283 }
284}
285
Tyler Scott7d076e22015-07-06 19:21:50 -0600286Atmos.prototype.populateResults = function(startIndex) {
287 this.resultTable.empty();
288 this.resultTable.append('<tr><th colspan="2">Results</th></tr>');
289
290
291 for (var i = startIndex; i < startIndex + 20 && i < this.results.length; ++i) {
292 resultTable.append('<tr><td>' + this.results[i]
293 + '</td><td><button class="interest-button btn btn-default btn-xs">Retrieve</button></td></tr>');
294 }
295
296 if (this.results.length <= 20) {
297 this.page = 1;
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600298 } else {
Tyler Scott7d076e22015-07-06 19:21:50 -0600299 this.page = startIndex / 20 + 1;
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600300 }
301
Tyler Scott7d076e22015-07-06 19:21:50 -0600302 this.totalPages = Math.ceil(this.results.length / 20);
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600303
Tyler Scott7d076e22015-07-06 19:21:50 -0600304 //TODO Fix the page to fit the theme.
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600305 var currentPage = $(".page");
306 currentPage.empty();
Tyler Scott7d076e22015-07-06 19:21:50 -0600307 if (this.page != 1) {
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600308 currentPage.append('<a href="#" onclick="getPage(this.id);" id="<"><</a>');
309 }
310 // This section of code creates the paging for the results.
311 // To prevent it from having a 1000+ pages, it will only show the 5 pages before/after
312 // the current page and the total pages (expect users not to really jump around a lot).
Tyler Scott7d076e22015-07-06 19:21:50 -0600313 for (var i = 1; i <= this.totalPages; ++i) {
314 if (i == 1 || i == this.totalPages // Min or max
315 || (i <= this.page && i + 5 >= this.page) // in our current page range
316 || (i >= this.page && i - 5 <= this.page)) { // in our current page range
317 if (i != this.page) {
Tyler Scottf08ab962015-06-30 16:31:29 -0600318 currentPage.append(' <a href="#" onclick="getPage(' + i + ');">' + i + '</a>')
Tyler Scott7d076e22015-07-06 19:21:50 -0600319 if (i == 1 && this.page > i + 5) {
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600320 currentPage.append(' ... ');
321 }
322 } else {
323 currentPage.append(' ' + i);
324 }
325 } else { // Need to skip ahead
326 if (i == page + 6) {
327 currentPage.append(' ... ');
328
Tyler Scottf08ab962015-06-30 16:31:29 -0600329 currentPage.append(' <a href="#" onclick="getPage(this.id);" id=">">></a>')
Tyler Scott7d076e22015-07-06 19:21:50 -0600330 i = this.totalPages - 1;
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600331 }
332 }
333 }
Tyler Scott7d076e22015-07-06 19:21:50 -0600334 currentPage.append(' ' + this.results.length + ' results');
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600335}
336
Tyler Scott7d076e22015-07-06 19:21:50 -0600337Atmos.prototype.getPage = function(clickedPage) {
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600338 console.log(clickedPage);
339
340 var nextPage = clickedPage;
341 if (clickedPage === "<") {
Tyler Scott7d076e22015-07-06 19:21:50 -0600342 nextPage = this.page - 5;
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600343 } else if (clickedPage === ">") {
344 console.log("> enabled");
345
Tyler Scott7d076e22015-07-06 19:21:50 -0600346 nextPage = this.page + 5;
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600347 }
348
349 nextPage--; // Need to adjust for starting at 0
350
351 if (nextPage < 0 ) {
352 nextPage = 0;
353 console.log("0 enabled");
Tyler Scott7d076e22015-07-06 19:21:50 -0600354 } else if (nextPage > this.totalPages - 1) {
355 nextPage = this.totalPages - 1;
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600356 console.log("total enabled");
357 }
358
Tyler Scott7d076e22015-07-06 19:21:50 -0600359 this.populateResults(nextPage * 20);
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600360 return false;
361}
362
Tyler Scott7d076e22015-07-06 19:21:50 -0600363
364Atmos.prototype.submitAutoComplete = function() {
365 /* FIXME TODO
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600366 if (autocompleteText.value.length > 0) {
367 var selection = autocompleteText.value;
368 $.each(dropdown, function (i, dropdownEntry) {
369 if (dropdownEntry.substr(0, dropdownEntry.length - 1) == selection) {
370 selection = dropdownEntry;
371 }
372 });
373
374 selectedSearch["?"] = selection;
375 query(catalog, selectedSearch, onData, 1);
376 delete selectedSearch["?"];
377 }
Tyler Scott7d076e22015-07-06 19:21:50 -0600378 */
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600379}
380
Tyler Scott7d076e22015-07-06 19:21:50 -0600381Atmos.prototype.populateAutocomplete = function(fields) {
382 /* FIXME TODO
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600383 var isAutocompleteFullName = (autocompleteText.value.charAt(autocompleteText.value.length - 1) === "/");
384 var autocompleteFullName = autocompleteText.value;
385 for (var i = 0; i < fields.length; ++i) {
386 var fieldFullName = fields[i];
387 var entry = autocompleteFullName;
388 var skipahead = "";
389
390 if (isAutocompleteFullName) {
391 skipahead = fieldFullName.substr(autocompleteText.value.length, fieldFullName.length);
392 } else {
393 if (fieldFullName.charAt(autocompleteText.value.length) === "/") {
394 entry += "/";
395 skipahead = fieldFullName.substr(autocompleteText.value.length + 1, fieldFullName.length);
396 } else {
397 skipahead = fieldFullName.substr(autocompleteText.value.length, fieldFullName.length);
398 }
399 }
400 if (skipahead.indexOf("/") != -1) {
401 entry += skipahead.substr(0, skipahead.indexOf("/") + 1);
402 } else {
403 entry += skipahead;
404 }
405
406 var added = false;
407 for (var j = 0; j < dropdown.length && !added; ++j) {
408 if (dropdown[j] === entry) {
409 added = true;
410 } else if (dropdown[j] > entry) {
411 dropdown.splice(j, 0, entry);
412 added = true;
413 }
414 }
415 if (!added) {
416 dropdown.push(entry);
417 }
418
419 }
420 $("#autocompleteText").autocomplete({
421 source: dropdown
422 });
Tyler Scott7d076e22015-07-06 19:21:50 -0600423 */
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600424}
425
Tyler Scott7d076e22015-07-06 19:21:50 -0600426Atmos.prototype.populateCurrentSelections = function() { //TODO
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600427 var currentSelection = $(".currentSelections");
428 currentSelection.empty();
429
430 currentSelection.append("<p>Filtering on:");
431
Tyler Scott7d076e22015-07-06 19:21:50 -0600432 var scope = this;
433
434 $.each(this.selectedSearch, function (searchMenuCatagory, selection) {
435 var e = $('<a href="#">[X] ' + searchMenuCatagory + ":" + selection + '</a>');
436 e.onclick(function(){
437 var searchFilter = $(this).text();
438
439 var search = "";
440 for (var j = 0; j < searchFilter.length; ++j) {
441 search += searchFilter[j] + " ";
442 }
443 console.log("Split values: '" + search + "'");
444
445 delete this.selectedSearch[searchFilter[0]];
446 this.query(catalog, selectedSearch, onData, 1);
447 populateCurrentSelections();
448 });
449 currentSelection.append(e);
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600450 });
451
452 currentSelection.append("</p>");
453}