blob: 42f074c49c31f99baf4aecd0aac62ed1f9b29377 [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 = {}; //Placeholder for the class.
Tyler Scott3c17d5f2015-06-23 17:49:29 -060011
Tyler Scotta1ac69d2015-07-02 17:42:03 -060012(function(){
13 "use strict"; //Magic (If you really wanna know, look it up.)
Tyler Scott3c17d5f2015-06-23 17:49:29 -060014
Tyler Scotta1ac69d2015-07-02 17:42:03 -060015 function Atmos(catalog, config){
16 //Internal variables.
17 this.searchMenuOptions = {}
18 this.results = []
19 this.resultCount = 0;
20 this.page = 1;
21 this.totalPages = 1;
22 this.selectedSearch = {};
23 this.dropdown = [];
24 this.state = {};
25 this.currentViewIndex = 0;
26
27 this.face = new Face(config);
28 this.categories = $('#side-menu');
29 this.resultTable = $('#resultTable');
30
31 var scope = this;
32
33 this.resultTable.on('click', '.interest-button', function(){
34 var button = $(this);
35
36 var name = button.parent().prev().text();
37 var interest = new Interest(new Name('/retrieve' + name));
38 scope.face.expressInterest(interest, function(){
39 var message = $('<div class="success"><span class="glyphicon glyphicon-ok"></span> Success!</div>');
40 message.insertAfter(button);
41 message.fadeOut(5000);
42 }, function(){
43 var message = $('<div class="fail"><span class="glyphicon glyphicon-remove"></span> Failed!</div>');
44 message.insertAfter(button);
45 message.fadeOut(5000);
46 });
47
48 });
49
50 $.getJSON("search_catagories.json").done(function (data) {
51 $.each(data, function (pageSection, contents) {
52 if (pageSection == "SearchCatagories") {
53 $.each(contents, function (search, searchOptions) {
54 search = search.replace(/\_/g, " ");
55
56 searchMenu.append('<li id="' + search + '" onclick="getDropDown(this.id)"><a href="#">' + search + '</a></li>');
57 scope.searchMenuOptions[String(search)] = searchOptions;
58 });
59 }
60 });
61 });
62
63 }
64
65 Atmos.prototype.onData = function(data) {
66 var payloadStr = data.content.toString().split("\n")[0];
67
68 var queryResults = JSON.parse(payloadStr);
69
70 var scope = this;
71
72 $.each(this.queryResults, function (queryResult, field) {
73
74 if (queryResult == "next") {
75 scope.populateAutocomplete(field);
Tyler Scott3c17d5f2015-06-23 17:49:29 -060076 }
Tyler Scotta1ac69d2015-07-02 17:42:03 -060077
78 $.each(field, function (entryCount, name) {
79 scope.results.push(name);
80 });
Tyler Scott3c17d5f2015-06-23 17:49:29 -060081 });
Tyler Scotta1ac69d2015-07-02 17:42:03 -060082
83 // Calculating the current page and the view
84 this.totalPages = Math.ceil(this.resultCount / 20);
85 this.populateResults(0);
86 }
87
88 Atmos.prototype.query = function(prefix, parameters, callback, pipeline) {
89 this.results = [];
90 this.dropdown = [];
91 this.resultTable.empty();
92 this.resultTable.append('<tr><th colspan="2">Results</th></tr>');
93
94 var queryPrefix = new Name(prefix);
95 queryPrefix.append("query");
96
97 var jsonString = JSON.stringify(parameters);
98 queryPrefix.append(jsonString);
99
100 this.state = {
101 prefix: new Name(prefix),
102 userOnData: callback,
103 outstanding: {},
104 nextSegment: 0,
105 };
106
107 /*if (state.hasOwnProperty("version")) {
108 console.log("state already has version");
109 }*/
110
111 var queryInterest = new Interest(queryPrefix);
112 queryInterest.setInterestLifetimeMilliseconds(10000);
113
114 var scope = this;
115
116 this.face.expressInterest(queryInterest,
117 function(){
118 onQueryData()
119 }, function(){
120 onQueryTimeout()
121 }
122 );
123
124 this.state["outstanding"][queryInterest.getName().toUri()] = 0;
125 }
126
127})(); //Run as soon as the script loads but keep the "use strict"" from escaping to the global space.
128
129
130var atmos = {}; //Comment this out if you don't want debug access.
131
132//Run when the document loads.
133$(function () {
134
135 atmos = new Atmos(catalog, config);
Tyler Scottf65b7102015-06-30 18:40:14 -0600136
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600137});
138
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600139function expressNextInterest() {
140 // @todo pipelines
141 var nextName = new Name(state["results"]);
142 nextName.appendSegment(state["nextSegment"]);
143
144 var nextInterest = new Interest(nextName);
145 nextInterest.setInterestLifetimeMilliseconds(10000);
146
147 face.expressInterest(nextInterest,
148 onQueryResultsData,
149 onQueryResultsTimeout);
150
151 state["nextSegment"] ++;
152 state["outstanding"][nextName.toUri()] = 0;
153}
154
155function onQueryData(interest, data) {
156 var name = data.getName();
157
158 delete state["outstanding"][interest.getName().toUri()];
159
160 state["version"] = name.get(state["prefix"].size() + 2).toVersion();
161
162 state["results"] = new Name(state["prefix"]).append("query-results").appendVersion(state["version"]);
163
164 expressNextInterest();
165}
166
167function onQueryResultsData(interest, data) {
168 var name = data.getName();
169 delete state["outstanding"][interest.getName().toUri()];
Tyler Scottf08ab962015-06-30 16:31:29 -0600170 if (!name.get(-1).equals(data.getMetaInfo().getFinalBlockId())) {
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600171 expressNextInterest();
Tyler Scottf08ab962015-06-30 16:31:29 -0600172 } //else {
173 //alert("found final block");
174 //}
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600175
176 state["userOnData"](data);
177}
178
179function onQueryTimeout(interest) {
180 var uri = interest.getName().toUri();
181 if (state["outstanding"][uri] < 1) {
182 state["outstanding"][uri] ++;
183 face.expressInterest(interest,
184 onQueryData,
185 onQueryTimeout);
186 } else {
187 delete state["outstanding"][uri];
188
189 // We modify the autocomplete box here because we need to know
190 // we have all of the entries first. Fairly hacky.
191 var autocompleteFullName = autocompleteText.value;
192 for (var i = 0; i < dropdown.length; ++i) {
193 if (dropdown[i].substr(0, dropdown[i].length - 1).toUpperCase === autocompleteText.value.toUpperCase || dropdown.length == 1) {
194 autocompleteText.value = dropdown[i];
195 }
196 }
197 }
198}
199
200function onQueryResultsTimeout(interest) {
201 var uri = interest.getName().toUri();
202 if (state["outstanding"][uri] < 1) {
203 state["outstanding"][uri] ++;
204 face.expressInterest(interest,
205 onQueryResultsData,
206 onQueryResultsTimeout);
207 } else {
208 delete state["outstanding"][uri];
209 // We modify the autocomplete box here because we need to know
210 // we have all of the entries first. Fairly hacky.
211 var autocompleteFullName = autocompleteText.value;
212 for (var i = 0; i < dropdown.length; ++i) {
213 if (dropdown[i].substr(0, dropdown[i].length - 1).toUpperCase === autocompleteText.value.toUpperCase || dropdown.length == 1) {
214 autocompleteText.value = dropdown[i];
215 }
216 }
217 }
218}
219
220
Tyler Scotta1ac69d2015-07-02 17:42:03 -0600221
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600222
223function populateResults(startIndex) {
224 var resultTable = $(".resultTable");
225 resultTable.empty();
Tyler Scottf08ab962015-06-30 16:31:29 -0600226 resultTable.append('<tr><th colspan="2">Results</th></tr>');
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600227
228
229 for (var i = startIndex; i < startIndex + 20 && i < results.length; ++i) {
Tyler Scottf65b7102015-06-30 18:40:14 -0600230 resultTable.append('<tr><td>' + results[i]
231 + '</td><td><button class="interest-button btn btn-default btn-xs">Express Interest</button></td></tr>');
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600232 }
233
234 if (results.length <= 20) {
235 page = 1;
236 } else {
237 page = startIndex / 20 + 1;
238 }
239
240 totalPages = Math.ceil(results.length / 20);
241
242 var currentPage = $(".page");
243 currentPage.empty();
244 if (page != 1) {
245 currentPage.append('<a href="#" onclick="getPage(this.id);" id="<"><</a>');
246 }
247 // This section of code creates the paging for the results.
248 // To prevent it from having a 1000+ pages, it will only show the 5 pages before/after
249 // the current page and the total pages (expect users not to really jump around a lot).
250 for (var i = 1; i <= totalPages; ++i) {
251 if (i == 1 || i == totalPages // Min or max
252 || (i <= page && i + 5 >= page) // in our current page range
253 || (i >= page && i - 5 <= page)) { // in our current page range
254 if (i != page) {
Tyler Scottf08ab962015-06-30 16:31:29 -0600255 currentPage.append(' <a href="#" onclick="getPage(' + i + ');">' + i + '</a>')
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600256 if (i == 1 && page > i + 5) {
257 currentPage.append(' ... ');
258 }
259 } else {
260 currentPage.append(' ' + i);
261 }
262 } else { // Need to skip ahead
263 if (i == page + 6) {
264 currentPage.append(' ... ');
265
Tyler Scottf08ab962015-06-30 16:31:29 -0600266 currentPage.append(' <a href="#" onclick="getPage(this.id);" id=">">></a>')
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600267 i = totalPages - 1;
268 }
269 }
270 }
271 currentPage.append(' ' + results.length + ' results');
272}
273
274var dropState = "";
275
276function getDropDown(str) {
277 var searchMenu = $("#side-menu");
278 if (str == dropState) {
279 dropState = "";
280 searchMenu.find("#" + str).find("#options_" + str).empty();
281 } else {
282 dropState = str;
283
284 $.each(searchMenuOptions, function (search, fields) {
285 if (search === str) {
286 searchMenu.find("#" + search).append('<ul id="options_' + search + '" class="sub-menu">');
287 for (var i = 0; i < fields.length; ++i) {
Tyler Scottf08ab962015-06-30 16:31:29 -0600288 searchMenu.find("#options_" + search).append('<li id="' + fields[i] + '" onclick="submitCatalogSearch(this.id)"><a href="#">' + fields[i] + '</a></li>');
Tyler Scott3c17d5f2015-06-23 17:49:29 -0600289 }
290 searchMenu.append('</ul>');
291 } else {
292 var ul = $("options_" + search);
293 ul.empty();
294 searchMenu.find("#" + search).find("#options_" + search).empty();
295 }
296 });
297 }
298}
299
300function getPage(clickedPage) {
301 console.log(clickedPage);
302
303 var nextPage = clickedPage;
304 if (clickedPage === "<") {
305 nextPage = page - 5;
306 } else if (clickedPage === ">") {
307 console.log("> enabled");
308
309 nextPage = page + 5;
310 }
311
312 nextPage--; // Need to adjust for starting at 0
313
314 if (nextPage < 0 ) {
315 nextPage = 0;
316 console.log("0 enabled");
317 } else if (nextPage > totalPages - 1) {
318 nextPage = totalPages - 1;
319 console.log("total enabled");
320 }
321
322 populateResults(nextPage * 20);
323 return false;
324}
325
326function submitAutoComplete() {
327 if (autocompleteText.value.length > 0) {
328 var selection = autocompleteText.value;
329 $.each(dropdown, function (i, dropdownEntry) {
330 if (dropdownEntry.substr(0, dropdownEntry.length - 1) == selection) {
331 selection = dropdownEntry;
332 }
333 });
334
335 selectedSearch["?"] = selection;
336 query(catalog, selectedSearch, onData, 1);
337 delete selectedSearch["?"];
338 }
339}
340
341function submitCatalogSearch(field) {
342 console.log("Sumbit Catalog Search: " + field);
343 // @todo: this logic isn't quite right
344 var remove = false;
345 $.each(selectedSearch, function (search, f) {
346 if (field == f) {
347 delete selectedSearch[field];
348 remove = true;
349 }
350 });
351 if (!remove) {
352 $.each(searchMenuOptions, function (search, fields) {
353 $.each(fields, function (index, f) {
354 if (f == field) {
355 selectedSearch[search] = field;
356 }
357 });
358 });
359 }
360 query(catalog, selectedSearch, onData, 1);
361 populateCurrentSelections();
362 return false;
363}
364
365function populateAutocomplete(fields) {
366 var isAutocompleteFullName = (autocompleteText.value.charAt(autocompleteText.value.length - 1) === "/");
367 var autocompleteFullName = autocompleteText.value;
368 for (var i = 0; i < fields.length; ++i) {
369 var fieldFullName = fields[i];
370 var entry = autocompleteFullName;
371 var skipahead = "";
372
373 if (isAutocompleteFullName) {
374 skipahead = fieldFullName.substr(autocompleteText.value.length, fieldFullName.length);
375 } else {
376 if (fieldFullName.charAt(autocompleteText.value.length) === "/") {
377 entry += "/";
378 skipahead = fieldFullName.substr(autocompleteText.value.length + 1, fieldFullName.length);
379 } else {
380 skipahead = fieldFullName.substr(autocompleteText.value.length, fieldFullName.length);
381 }
382 }
383 if (skipahead.indexOf("/") != -1) {
384 entry += skipahead.substr(0, skipahead.indexOf("/") + 1);
385 } else {
386 entry += skipahead;
387 }
388
389 var added = false;
390 for (var j = 0; j < dropdown.length && !added; ++j) {
391 if (dropdown[j] === entry) {
392 added = true;
393 } else if (dropdown[j] > entry) {
394 dropdown.splice(j, 0, entry);
395 added = true;
396 }
397 }
398 if (!added) {
399 dropdown.push(entry);
400 }
401
402 }
403 $("#autocompleteText").autocomplete({
404 source: dropdown
405 });
406}
407
408function populateCurrentSelections() {
409 var currentSelection = $(".currentSelections");
410 currentSelection.empty();
411
412 currentSelection.append("<p>Filtering on:");
413
414 $.each(selectedSearch, function (searchMenuCatagory, selection) {
415 currentSelection.append(' <a href="#" onclick="removeFilter(this.id);" id="' + searchMenuCatagory + ':' + selection + '">[X] ' + searchMenuCatagory + ":" + selection + '</a>');
416 });
417
418 currentSelection.append("</p>");
419}
420
421
422function removeFilter(filter) {
423 console.log("Remove filter" + filter);
424 var searchFilter = filter.split(":");
425
426 var search = "";
427 for (var j = 0; j < searchFilter.length; ++j) {
428 search += searchFilter[j] + " ";
429 }
430 console.log("Split values: '" + search + "'");
431
432 delete selectedSearch[searchFilter[0]];
433 query(catalog, selectedSearch, onData, 1);
434 populateCurrentSelections();
435
436 return false;
Tyler Scottf08ab962015-06-30 16:31:29 -0600437}