blob: 08fe6f576178bbaefacc332407fbc2ca4b8eaaef [file] [log] [blame]
Alison Craigef12da82015-03-06 09:41:43 -07001<!DOCTYPE html>
2<html lang="en-US">
3
4<head>
5 <title>Atmospheric Query and Retrieval Tool</title>
6 <meta charset="UTF-8" />
7
8
Alison Craig1aced7d2015-04-10 12:00:02 -06009 <script type="text/javascript" src="../jquery/jquery-latest.min.js"></script>
10 <script type="text/javascript" src="../jquery/ui/1.10.1/jquery-ui.js"></script>
11 <script type="text/javascript" src="../ndn-js/build/ndn.js"></script>
Alison Craigef12da82015-03-06 09:41:43 -070012
13
14 <link rel="stylesheet" href="query.css">
Alison Craig1aced7d2015-04-10 12:00:02 -060015 <link rel="stylesheet" href="../jquery/ui/1.11.4/themes/smoothness/jquery-ui.css">
Alison Craigef12da82015-03-06 09:41:43 -070016
17 <script>
Alison Craig1aced7d2015-04-10 12:00:02 -060018 // {@ @todo: this need to be configured before the document load
19 var catalog = "/catalog/myUniqueName";
20 var face = new Face({
21 host: "localhost",
22 port: 9696
23 });
24
25 // @}
26
27 var searchMenuOptions = {}
28 var results = [];
Alison Craigef12da82015-03-06 09:41:43 -070029 var resultCount = 0;
30 var page = 1;
31 var totalPages = 1;
Alison Craig1aced7d2015-04-10 12:00:02 -060032 var selectedSearch = {};
33 var dropdown = [];
Alison Craigef12da82015-03-06 09:41:43 -070034
35 $(document).ready(function () {
36 var searchMenu = $(".cssmenu");
37 var currentPage = $(".page");
38 var resultTable = $(".resultTable");
Alison Craig1aced7d2015-04-10 12:00:02 -060039 var data = $.getJSON("search_catagories.json", function () {}).done(function (data) {
Alison Craigef12da82015-03-06 09:41:43 -070040 $.each(data, function (pageSection, contents) {
41 if (pageSection == "SearchCatagories") {
Alison Craigef12da82015-03-06 09:41:43 -070042 $.each(contents, function (search, searchOptions) {
43 search = search.replace(/\_/g, " ");
44
45 searchMenu.append('<li id="' + search + '" onclick="getDropDown(this.id)"><a href="#">' + search + '</a></li>');
Alison Craig1aced7d2015-04-10 12:00:02 -060046 searchMenuOptions[String(search)] = searchOptions;
Alison Craigef12da82015-03-06 09:41:43 -070047 });
Alison Craigef12da82015-03-06 09:41:43 -070048 }
49 });
Alison Craig1aced7d2015-04-10 12:00:02 -060050 });
Alison Craigef12da82015-03-06 09:41:43 -070051 });
52
Alison Craig1aced7d2015-04-10 12:00:02 -060053 function onData(data) {
54 var payloadStr = data.content.toString().split("\n")[0];
55
56 var queryResults = JSON.parse(payloadStr);
57
58 var resultTable = $(".resultTable");
59 $.each(queryResults, function (queryResult, field) {
60
61 if (queryResult == "next") {
62 populateAutocomplete(field);
63 }
64
65 $.each(field, function (entryCount, name) {
66 results.push(name);
67 });
68 });
69
70 // Calculating the current page and the view
71 totalPages = Math.ceil(resultCount / 20);
72 populateResults(0);
73 }
74
75 var state = {};
76
77 function query(prefix, parameters, callback, pipeline) {
78 results = [];
79 dropdown = [];
Alison Craig1aced7d2015-04-10 12:00:02 -060080 var resultTable = $(".resultTable");
81 resultTable.empty();
82 resultTable.append('<tr><td>Results</td></tr>');
83
84 var queryPrefix = new Name(prefix);
85 queryPrefix.append("query");
86
Chengyu Fanb25835b2015-04-28 17:09:35 -060087 var jsonString = JSON.stringify(parameters);
Alison Craig1aced7d2015-04-10 12:00:02 -060088 queryPrefix.append(JSON.stringify(parameters));
89
90 state = {
91 prefix: new Name(prefix),
92 userOnData: callback,
93 outstanding: {},
94 nextSegment: 0,
95 };
96
97 /*if (state.hasOwnProperty("version")) {
98 console.log("state already has version");
99 }*/
100
101 var queryInterest = new Interest(queryPrefix);
102 queryInterest.setInterestLifetimeMilliseconds(10000);
103
104 face.expressInterest(queryInterest,
105 onQueryData,
106 onQueryTimeout);
107
108 state["outstanding"][queryInterest.getName().toUri()] = 0;
109 }
110
111 function expressNextInterest() {
112 // @todo pipelines
113 var nextName = new Name(state["results"]);
114 nextName.appendSegment(state["nextSegment"]);
115
116 var nextInterest = new Interest(nextName);
117 nextInterest.setInterestLifetimeMilliseconds(10000);
118
119 face.expressInterest(nextInterest,
120 onQueryResultsData,
121 onQueryResultsTimeout);
122
123 state["nextSegment"] ++;
124 state["outstanding"][nextName.toUri()] = 0;
125 }
126
127 function onQueryData(interest, data) {
128 var name = data.getName();
129
130 delete state["outstanding"][interest.getName().toUri()];
131
132 state["version"] = name.get(state["prefix"].size() + 2).toVersion();
133
134 state["results"] = new Name(state["prefix"]).append("query-results").appendVersion(state["version"]);
135
136 expressNextInterest();
137 }
138
139 function onQueryResultsData(interest, data) {
140 var name = data.getName();
141 delete state["outstanding"][interest.getName().toUri()];
Chengyu Fanb25835b2015-04-28 17:09:35 -0600142 if (!name.get(-1).equals(data.getMetaInfo().getFinalBlockId())) {
Alison Craig1aced7d2015-04-10 12:00:02 -0600143 expressNextInterest();
144 } else {
Chengyu Fanb25835b2015-04-28 17:09:35 -0600145 //alert("found final block");
Alison Craig1aced7d2015-04-10 12:00:02 -0600146 }
147
148 state["userOnData"](data);
149 }
150
151 function onQueryTimeout(interest) {
152 var uri = interest.getName().toUri();
153 if (state["outstanding"][uri] < 1) {
154 state["outstanding"][uri] ++;
155 face.expressInterest(interest,
156 onQueryData,
157 onQueryTimeout);
158 } else {
159 delete state["outstanding"][uri];
160
161 // We modify the autocomplete box here because we need to know
162 // we have all of the entries first. Fairly hacky.
163 var autocompleteFullName = autocompleteText.value;
164 for (var i = 0; i < dropdown.length; ++i) {
165 if (dropdown[i].substr(0, dropdown[i].length - 1).toUpperCase === autocompleteText.value.toUpperCase || dropdown.length == 1) {
166 autocompleteText.value = dropdown[i];
167 }
168 }
169 }
170 }
171
172 function onQueryResultsTimeout(interest) {
173 var uri = interest.getName().toUri();
174 if (state["outstanding"][uri] < 1) {
175 state["outstanding"][uri] ++;
176 face.expressInterest(interest,
177 onQueryResultsData,
178 onQueryResultsTimeout);
179 } else {
180 delete state["outstanding"][uri];
181 // We modify the autocomplete box here because we need to know
182 // we have all of the entries first. Fairly hacky.
183 var autocompleteFullName = autocompleteText.value;
184 for (var i = 0; i < dropdown.length; ++i) {
185 if (dropdown[i].substr(0, dropdown[i].length - 1).toUpperCase === autocompleteText.value.toUpperCase || dropdown.length == 1) {
186 autocompleteText.value = dropdown[i];
187 }
188 }
189 }
190 }
191
192
193 var currentViewIndex = 0;
194
195 function populateResults(startIndex) {
196 var resultTable = $(".resultTable");
197 resultTable.empty();
198 resultTable.append('<tr><td>Results</td></tr>');
199
200
201 for (var i = startIndex; i < startIndex + 20 && i < results.length; ++i) {
202 resultTable.append('<tr><td>' + results[i] + '</td></tr>');
203 }
204
205 if (results.length <= 20) {
206 page = 1;
207 } else {
208 page = startIndex / 20 + 1;
209 }
210
211 totalPages = Math.ceil(results.length / 20);
212
213 var currentPage = $(".page");
214 currentPage.empty();
215 if (page != 1) {
216 currentPage.append('<a href="#" onclick="getPage(this.id);" id="<"><</a>');
217 }
218 // This section of code creates the paging for the results.
219 // To prevent it from having a 1000+ pages, it will only show the 5 pages before/after
220 // the current page and the total pages (expect users not to really jump around a lot).
221 for (var i = 1; i <= totalPages; ++i) {
222 if (i == 1 || i == totalPages // Min or max
223 || (i <= page && i + 5 >= page) // in our current page range
224 || (i >= page && i - 5 <= page)) { // in our current page range
225 if (i != page) {
226 currentPage.append(' <a href="#" onclick="getPage(' + i + ');">' + i + '</a>')
227 if (i == 1 && page > i + 5) {
228 currentPage.append(' ... ');
229 }
230 } else {
231 currentPage.append(' ' + i);
232 }
233 } else { // Need to skip ahead
234 if (i == page + 6) {
235 currentPage.append(' ... ');
236
237 currentPage.append(' <a href="#" onclick="getPage(this.id);" id=">">></a>')
238 i = totalPages - 1;
239 }
240 }
241 }
242 currentPage.append(' ' + results.length + ' results');
243 }
244
245 var dropState = "";
Alison Craigef12da82015-03-06 09:41:43 -0700246
247 function getDropDown(str) {
248 var searchMenu = $(".cssmenu");
Alison Craig1aced7d2015-04-10 12:00:02 -0600249 if (str == dropState) {
250 dropState = "";
Alison Craigef12da82015-03-06 09:41:43 -0700251 searchMenu.find("#" + str).find("#options_" + str).empty();
252 } else {
Alison Craig1aced7d2015-04-10 12:00:02 -0600253 dropState = str;
Alison Craigef12da82015-03-06 09:41:43 -0700254
255 $.each(searchMenuOptions, function (search, fields) {
256 if (search === str) {
257 searchMenu.find("#" + search).append('<ul id="options_' + search + '" class="sub-menu">');
258 for (var i = 0; i < fields.length; ++i) {
Alison Craig1aced7d2015-04-10 12:00:02 -0600259 searchMenu.find("#options_" + search).append('<li id="' + fields[i] + '"onclick="submitCatalogSearch(this.id)"><a href="#">' + fields[i] + '</a></li>');
Alison Craigef12da82015-03-06 09:41:43 -0700260 }
261 searchMenu.append('</ul>');
262 } else {
263 var ul = $("options_" + search);
264 ul.empty();
265 searchMenu.find("#" + search).find("#options_" + search).empty();
266 }
267 });
268 }
269 }
270
Alison Craig1aced7d2015-04-10 12:00:02 -0600271 function getPage(clickedPage) {
272 console.log(clickedPage);
Alison Craigef12da82015-03-06 09:41:43 -0700273
Alison Craig1aced7d2015-04-10 12:00:02 -0600274 var nextPage = clickedPage;
275 if (clickedPage === "<") {
276 nextPage = page - 5;
277 } else if (clickedPage === ">") {
278 console.log("> enabled");
Alison Craigef12da82015-03-06 09:41:43 -0700279
Alison Craig1aced7d2015-04-10 12:00:02 -0600280 nextPage = page + 5;
Alison Craigef12da82015-03-06 09:41:43 -0700281 }
282
Alison Craig1aced7d2015-04-10 12:00:02 -0600283 nextPage--; // Need to adjust for starting at 0
284
285 if (nextPage < 0 ) {
286 nextPage = 0;
287 console.log("0 enabled");
288 } else if (nextPage > totalPages - 1) {
289 nextPage = totalPages - 1;
290 console.log("total enabled");
291 }
292
293 populateResults(nextPage * 20);
294 return false;
295 }
296
297 function submitAutoComplete() {
298 if (autocompleteText.value.length > 0) {
299 var selection = autocompleteText.value;
300 $.each(dropdown, function (i, dropdownEntry) {
301 if (dropdownEntry.substr(0, dropdownEntry.length - 1) == selection) {
302 selection = dropdownEntry;
303 }
304 });
305
306 selectedSearch["?"] = selection;
307 query(catalog, selectedSearch, onData, 1);
308 delete selectedSearch["?"];
309 }
310 }
311
312 function submitCatalogSearch(field) {
313 console.log("Sumbit Catalog Search: " + field);
314 // @todo: this logic isn't quite right
315 var remove = false;
316 $.each(selectedSearch, function (search, f) {
317 if (field == f) {
318 delete selectedSearch[field];
319 remove = true;
320 }
321 });
322 if (!remove) {
323 $.each(searchMenuOptions, function (search, fields) {
324 $.each(fields, function (index, f) {
325 if (f == field) {
326 selectedSearch[search] = field;
327 }
328 });
329 });
330 }
331 query(catalog, selectedSearch, onData, 1);
332 populateCurrentSelections();
333 return false;
334 }
335
336 function populateAutocomplete(fields) {
337 var isAutocompleteFullName = (autocompleteText.value.charAt(autocompleteText.value.length - 1) === "/");
338 var autocompleteFullName = autocompleteText.value;
339 for (var i = 0; i < fields.length; ++i) {
340 var fieldFullName = fields[i];
341 var entry = autocompleteFullName;
342 var skipahead = "";
343
344 if (isAutocompleteFullName) {
345 skipahead = fieldFullName.substr(autocompleteText.value.length, fieldFullName.length);
346 } else {
347 if (fieldFullName.charAt(autocompleteText.value.length) === "/") {
348 entry += "/";
349 skipahead = fieldFullName.substr(autocompleteText.value.length + 1, fieldFullName.length);
350 } else {
351 skipahead = fieldFullName.substr(autocompleteText.value.length, fieldFullName.length);
352 }
353 }
354 if (skipahead.indexOf("/") != -1) {
355 entry += skipahead.substr(0, skipahead.indexOf("/") + 1);
356 } else {
357 entry += skipahead;
358 }
359
360 var added = false;
361 for (var j = 0; j < dropdown.length && !added; ++j) {
362 if (dropdown[j] === entry) {
363 added = true;
364 } else if (dropdown[j] > entry) {
365 dropdown.splice(j, 0, entry);
366 added = true;
367 }
368 }
369 if (!added) {
370 dropdown.push(entry);
371 }
372
373 }
374 $("#autocompleteText").autocomplete({
375 source: dropdown
376 });
377 }
378
379 function populateCurrentSelections() {
380 var currentSelection = $(".currentSelections");
381 currentSelection.empty();
382
383 currentSelection.append("<p>Filtering on:");
384
385 $.each(selectedSearch, function (searchMenuCatagory, selection) {
386 currentSelection.append(' <a href="#" onclick="removeFilter(this.id);" id="' + searchMenuCatagory + ':' + selection + '">[X] ' + searchMenuCatagory + ":" + selection + '</a>');
387 });
388
389 currentSelection.append("</p>");
390 }
391
392
393 function removeFilter(filter) {
394 console.log("Remove filter" + filter);
395 var searchFilter = filter.split(":");
396
397 var search = "";
398 for (var j = 0; j < searchFilter.length; ++j) {
399 search += searchFilter[j] + " ";
400 }
401 console.log("Split values: '" + search + "'");
402
403 delete selectedSearch[searchFilter[0]];
404 query(catalog, selectedSearch, onData, 1);
405 populateCurrentSelections();
406
407 return false;
Alison Craigef12da82015-03-06 09:41:43 -0700408 }
409 </script>
410</head>
411
412<body id="body">
413 <header>
414 <h1>Atmospheric Query and Retrieval Tool</h1>
415 </header>
416
417 <ul class='cssmenu'>
418
419 </ul>
420
Alison Craig1aced7d2015-04-10 12:00:02 -0600421 <div class="currentSelections"></div>
422
423
Alison Craigef12da82015-03-06 09:41:43 -0700424 <div class="autocomplete">
Alison Craig1aced7d2015-04-10 12:00:02 -0600425 <div class="ui-widget">
426 <label for="tags"> Search: </label>
427 <input id="autocompleteText" placeholder="/cmip" class="textbox" onkeydown="if (event.keyCode == 13) submitAutoComplete(); ">
428 <button id="autoButton" value="Search" onclick="submitAutoComplete()" id="autocompleteButton">Search</button>
429 </div>
430
431 <div class="page"></div>
432
433 <table class="resultTable">
434
435
436 </table>
Alison Craigef12da82015-03-06 09:41:43 -0700437 </div>
Alison Craigef12da82015-03-06 09:41:43 -0700438
439
Alison Craigef12da82015-03-06 09:41:43 -0700440</body>
441
442</html>