Cleaning up sources

Change-Id: I8d6799333da60355861119b23cc91cd045e8016d
diff --git a/client/query/query.js b/client/query/query.js
index 42f074c..5241edf 100644
--- a/client/query/query.js
+++ b/client/query/query.js
@@ -7,136 +7,182 @@
 
 // @}
 
-var Atmos = {}; //Placeholder for the class.
-
-(function(){
-  "use strict"; //Magic (If you really wanna know, look it up.)
-
-  function Atmos(catalog, config){
-    //Internal variables.
-    this.searchMenuOptions = {}
-    this.results = []
-    this.resultCount = 0;
-    this.page = 1;
-    this.totalPages = 1;
-    this.selectedSearch = {};
-    this.dropdown = [];
-    this.state = {};
-    this.currentViewIndex = 0;
-
-    this.face = new Face(config);
-    this.categories = $('#side-menu');
-    this.resultTable = $('#resultTable');
-
-    var scope = this;
-
-    this.resultTable.on('click', '.interest-button', function(){
-      var button = $(this);
-
-      var name = button.parent().prev().text();
-      var interest = new Interest(new Name('/retrieve' + name));
-      scope.face.expressInterest(interest, function(){
-        var message = $('<div class="success"><span class="glyphicon glyphicon-ok"></span> Success!</div>');
-        message.insertAfter(button);
-        message.fadeOut(5000);
-      }, function(){
-        var message = $('<div class="fail"><span class="glyphicon glyphicon-remove"></span> Failed!</div>');
-        message.insertAfter(button);
-        message.fadeOut(5000);
-      });
-
-    });
-
-    $.getJSON("search_catagories.json").done(function (data) {
-      $.each(data, function (pageSection, contents) {
-        if (pageSection == "SearchCatagories") {
-          $.each(contents, function (search, searchOptions) {
-            search = search.replace(/\_/g, " ");
-
-            searchMenu.append('<li id="' + search + '" onclick="getDropDown(this.id)"><a href="#">' + search + '</a></li>');
-            scope.searchMenuOptions[String(search)] = searchOptions;
-          });
-        }
-      });
-    });
-
-  }
-
-  Atmos.prototype.onData = function(data) {
-    var payloadStr = data.content.toString().split("\n")[0];
-
-    var queryResults = JSON.parse(payloadStr);
-
-    var scope = this;
-
-    $.each(this.queryResults, function (queryResult, field) {
-
-      if (queryResult == "next") {
-        scope.populateAutocomplete(field);
-      }
-
-      $.each(field, function (entryCount, name) {
-        scope.results.push(name);
-      });
-    });
-
-    // Calculating the current page and the view
-    this.totalPages = Math.ceil(this.resultCount / 20);
-    this.populateResults(0);
-  }
-
-  Atmos.prototype.query = function(prefix, parameters, callback, pipeline) {
-    this.results = [];
-    this.dropdown = [];
-    this.resultTable.empty();
-    this.resultTable.append('<tr><th colspan="2">Results</th></tr>');
-
-    var queryPrefix = new Name(prefix);
-    queryPrefix.append("query");
-
-    var jsonString = JSON.stringify(parameters);
-    queryPrefix.append(jsonString);
-
-    this.state = {
-        prefix: new Name(prefix),
-        userOnData: callback,
-        outstanding: {},
-        nextSegment: 0,
-    };
-
-    /*if (state.hasOwnProperty("version")) {
-                  console.log("state already has version");
-              }*/
-
-    var queryInterest = new Interest(queryPrefix);
-    queryInterest.setInterestLifetimeMilliseconds(10000);
-
-    var scope = this;
-
-    this.face.expressInterest(queryInterest,
-      function(){
-        onQueryData()
-      }, function(){
-        onQueryTimeout()
-      }
-    );
-
-    this.state["outstanding"][queryInterest.getName().toUri()] = 0;
-  }
-
-})(); //Run as soon as the script loads but keep the "use strict"" from escaping to the global space.
-
-
 var atmos = {}; //Comment this out if you don't want debug access.
 
 //Run when the document loads.
 $(function () {
-
+  
+  //remove "atmos =" if you don't want debug access
   atmos = new Atmos(catalog, config);
   
 });
 
-function expressNextInterest() {
+/*
+  Atmos
+  Version 2
+*/
+
+function Atmos(catalog, config){
+  "use strict";
+  //Internal variables.
+  this.results = []
+  this.resultCount = 0;
+  this.page = 1;
+  this.totalPages = 1;
+  this.selectedSearch = {};
+  this.dropdown = [];
+  this.state = {};
+  this.currentViewIndex = 0;
+
+  this.face = new Face(config);
+  this.categories = $('#side-menu');
+  this.resultTable = $('#resultTable');
+
+  var scope = this;
+
+  this.resultTable.on('click', '.interest-button', function(){
+    var button = $(this);
+
+    var name = button.parent().prev().text();
+    var interest = new Interest(new Name('/retrieve' + name));
+    scope.face.expressInterest(interest, function(){
+      var message = $('<div class="success"><span class="glyphicon glyphicon-ok"></span> Success!</div>');
+      message.insertAfter(button);
+      message.fadeOut(5000);
+    }, function(){
+      var message = $('<div class="fail"><span class="glyphicon glyphicon-remove"></span> Failed!</div>');
+      message.insertAfter(button);
+      message.fadeOut(5000);
+    });
+
+  });
+
+  $.getJSON("search_catagories.json").done(function (data) {
+    $.each(data, function (pageSection, contents) {
+      if (pageSection == "SearchCatagories") {
+        $.each(contents, function (search, searchOptions) {
+          var e = $('<li><a href="#">' + search.replace(/\_/g, " ") + '</a><ul class="subnav nav nav-pills nav-stacked"></ul></li>');
+
+          var sub = e.find('ul.subnav');
+          $.each(searchOptions, function(index, name){
+            var item = $('<li><a href="#">' + name + '</a></li>');
+            sub.append(item);
+            item.click(function(){
+              scope.submitCatalogSearch(name);
+            });
+          });
+
+          //Toggle the menus.
+          e.click(function(){
+            scope.categories.find('.subnav').slideUp();
+            var t = $(this).find('.subnav');
+            if ( !t.is(':visible')){
+              t.slideDown().triggerHandler('focus'); //Cancel other animations and slide down.
+            }
+          });
+
+          scope.categories.append(e);
+        });
+      }
+    });
+  });
+
+  $('#searchBar').submit(function(e){
+    e.preventDefault();
+  })
+
+}
+
+Atmos.prototype.onData = function(data) {
+  var payloadStr = data.content.toString().split("\n")[0];
+
+  var queryResults = JSON.parse(payloadStr);
+
+  var scope = this;
+
+  $.each(this.queryResults, function (queryResult, field) {
+
+    if (queryResult == "next") {
+      scope.populateAutocomplete(field);
+    }
+
+    $.each(field, function (entryCount, name) {
+      scope.results.push(name);
+    });
+  });
+
+  // Calculating the current page and the view
+  this.totalPages = Math.ceil(this.resultCount / 20);
+  this.populateResults(0);
+}
+
+Atmos.prototype.query = function(prefix, parameters, callback, pipeline) {
+  this.results = [];
+  this.dropdown = [];
+  this.resultTable.empty();
+  this.resultTable.append('<tr><th colspan="2">Results</th></tr>');
+
+  var queryPrefix = new Name(prefix);
+  queryPrefix.append("query");
+
+  var jsonString = JSON.stringify(parameters);
+  queryPrefix.append(jsonString);
+
+  this.state = {
+      prefix: new Name(prefix),
+      userOnData: callback,
+      outstanding: {},
+      nextSegment: 0,
+  };
+
+  /*if (state.hasOwnProperty("version")) {
+                console.log("state already has version");
+            }*/
+
+  var queryInterest = new Interest(queryPrefix);
+  queryInterest.setInterestLifetimeMilliseconds(10000);
+
+  var scope = this;
+
+  this.face.expressInterest(queryInterest,
+    function(){ //FIXME
+      scope.onQueryData.apply(scope, arguments); //TODO
+    }, function(){
+      scope.onQueryTimeout.apply(scope, arguments);
+    }
+  );
+
+  this.state["outstanding"][queryInterest.getName().toUri()] = 0;
+}
+
+Atmos.prototype.submitCatalogSearch = function(field) {
+  console.log("Sumbit Catalog Search: " + field);
+  // @todo: this logic isn't quite right
+  var remove = false;
+  var scope = this;
+  $.each(scope.selectedSearch, function (search, f) {
+    if (field == f) {
+      delete scope.selectedSearch[field];
+      remove = true;
+    }
+  });
+  if (!remove) {
+    $.each(scope.searchMenuOptions, function (search, fields) {
+      $.each(fields, function (index, f) {
+        if (f == field) {
+          scope.selectedSearch[search] = field;
+        }
+      });
+    });
+  }
+  this.query(scope.catalog, scope.selectedSearch, function(){
+    scope.onData.apply(scope, arguments); //Unknown arguments. FIXME (Works but could be improved for readability)
+  }, 1);
+  scope.populateCurrentSelections();
+  return false;//?? Is this used?
+}
+
+Atmos.prototype.expressNextInterest = function() {
   // @todo pipelines
   var nextName = new Name(state["results"]);
   nextName.appendSegment(state["nextSegment"]);
@@ -144,116 +190,133 @@
   var nextInterest = new Interest(nextName);
   nextInterest.setInterestLifetimeMilliseconds(10000);
 
-  face.expressInterest(nextInterest,
-      onQueryResultsData,
-      onQueryResultsTimeout);
+  var scope = this;
 
-  state["nextSegment"] ++;
-  state["outstanding"][nextName.toUri()] = 0;
+  this.face.expressInterest(nextInterest,
+      function(){
+        scope.onQueryResultsData.apply(scope, arguments); //FIXME
+      },
+      function(){
+        scope.onQueryResultsTimeout.apply(scope, arguments); //FIXME
+      });
+
+  this.state["nextSegment"] ++;
+  this.state["outstanding"][nextName.toUri()] = 0;
 }
 
-function onQueryData(interest, data) {
+Atmos.prototype.onQueryData = function(interest, data) {
   var name = data.getName();
 
-  delete state["outstanding"][interest.getName().toUri()];
+  delete this.state["outstanding"][interest.getName().toUri()];
 
-  state["version"] = name.get(state["prefix"].size() + 2).toVersion();
+  this.state["version"] = name.get(this.state["prefix"].size() + 2).toVersion();
 
-  state["results"] = new Name(state["prefix"]).append("query-results").appendVersion(state["version"]);
+  this.state["results"] = new Name(this.state["prefix"]).append("query-results").appendVersion(this.state["version"]);
 
-  expressNextInterest();
+  this.expressNextInterest();
 }
 
-function onQueryResultsData(interest, data) {
+Atmos.prototype.onQueryResultsData = function(interest, data) {
   var name = data.getName();
-  delete state["outstanding"][interest.getName().toUri()];
+  delete this.state["outstanding"][interest.getName().toUri()];
   if (!name.get(-1).equals(data.getMetaInfo().getFinalBlockId())) {
-    expressNextInterest();
+    this.expressNextInterest();
   } //else {
     //alert("found final block");
   //}
 
-  state["userOnData"](data);
+  this.state["userOnData"](data);
 }
 
-function onQueryTimeout(interest) {
+Atmos.prototype.onQueryTimeout = function(interest) {
   var uri = interest.getName().toUri();
-  if (state["outstanding"][uri] < 1) {
-    state["outstanding"][uri] ++;
-    face.expressInterest(interest,
-        onQueryData,
-        onQueryTimeout);
+  if (this.state["outstanding"][uri] < 1) {
+    this.state["outstanding"][uri] ++;
+    var scope = this;
+    this.face.expressInterest(interest,
+        function(){
+          scope.onQueryData.apply(scope, arguments);
+        },
+        function(){
+          scope.onQueryTimeout.apply(scope, arguments);
+        });
   } else {
-    delete state["outstanding"][uri];
+    delete this.state["outstanding"][uri];
 
     // We modify the autocomplete box here because we need to know
     // we have all of the entries first. Fairly hacky.
+    /* TODO FIXME
+    var autocompleteFullName = this.autocompleteText.value;
+    for (var i = 0; i < dropdown.length; ++i) {
+      if (this.dropdown[i].substr(0, dropdown[i].length - 1).toUpperCase === this.autocompleteText.value.toUpperCase || dropdown.length == 1) {
+        autocompleteText.value = dropdown[i];
+      }
+    }
+    */
+  }
+}
+
+Atmos.prototype.onQueryResultsTimeout = function(interest) {
+  var uri = interest.getName().toUri();
+  if (this.state["outstanding"][uri] < 1) {
+    this.state["outstanding"][uri] ++;
+    var scope = this;
+    this.face.expressInterest(interest,
+        function(){
+          scope.onQueryResultsData.apply(scope, arguments);
+        },
+        function(){
+          scope.onQueryResultsTimeout.apply(scope, arguments);
+        });
+  } else {
+    delete this.state["outstanding"][uri];
+    // We modify the autocomplete box here because we need to know
+    // we have all of the entries first. Fairly hacky.
+    /* TODO FIXME
     var autocompleteFullName = autocompleteText.value;
     for (var i = 0; i < dropdown.length; ++i) {
       if (dropdown[i].substr(0, dropdown[i].length - 1).toUpperCase === autocompleteText.value.toUpperCase || dropdown.length == 1) {
         autocompleteText.value = dropdown[i];
       }
     }
+    */
   }
 }
 
-function onQueryResultsTimeout(interest) {
-  var uri = interest.getName().toUri();
-  if (state["outstanding"][uri] < 1) {
-    state["outstanding"][uri] ++;
-    face.expressInterest(interest,
-        onQueryResultsData,
-        onQueryResultsTimeout);
+Atmos.prototype.populateResults = function(startIndex) {
+  this.resultTable.empty();
+  this.resultTable.append('<tr><th colspan="2">Results</th></tr>');
+
+
+  for (var i = startIndex; i < startIndex + 20 && i < this.results.length; ++i) {
+    resultTable.append('<tr><td>' + this.results[i]
+    + '</td><td><button class="interest-button btn btn-default btn-xs">Retrieve</button></td></tr>');
+  }
+
+  if (this.results.length <= 20) {
+    this.page = 1;
   } else {
-    delete state["outstanding"][uri];
-    // We modify the autocomplete box here because we need to know
-    // we have all of the entries first. Fairly hacky.
-    var autocompleteFullName = autocompleteText.value;
-    for (var i = 0; i < dropdown.length; ++i) {
-      if (dropdown[i].substr(0, dropdown[i].length - 1).toUpperCase === autocompleteText.value.toUpperCase || dropdown.length == 1) {
-        autocompleteText.value = dropdown[i];
-      }
-    }
-  }
-}
-
-
-
-
-function populateResults(startIndex) {
-  var resultTable = $(".resultTable");
-  resultTable.empty();
-  resultTable.append('<tr><th colspan="2">Results</th></tr>');
-
-
-  for (var i = startIndex; i < startIndex + 20 && i < results.length; ++i) {
-    resultTable.append('<tr><td>' + results[i]
-    + '</td><td><button class="interest-button btn btn-default btn-xs">Express Interest</button></td></tr>');
+    this.page = startIndex / 20 + 1;
   }
 
-  if (results.length <= 20) {
-    page = 1;
-  } else {
-    page = startIndex / 20 + 1;
-  }
+  this.totalPages = Math.ceil(this.results.length / 20);
 
-  totalPages = Math.ceil(results.length / 20);
-
+  //TODO Fix the page to fit the theme.
   var currentPage = $(".page");
   currentPage.empty();
-  if (page != 1) {
+  if (this.page != 1) {
     currentPage.append('<a href="#" onclick="getPage(this.id);" id="<"><</a>');
   }
   // This section of code creates the paging for the results.
   // To prevent it from having a 1000+ pages, it will only show the 5 pages before/after
   // the current page and the total pages (expect users not to really jump around a lot).
-  for (var i = 1; i <= totalPages; ++i) {
-    if (i == 1 || i == totalPages     // Min or max
-        || (i <= page && i + 5 >= page)    // in our current page range
-        || (i >= page && i - 5 <= page)) { // in our current page range
-      if (i != page) {
+  for (var i = 1; i <= this.totalPages; ++i) {
+    if (i == 1 || i == this.totalPages      // Min or max
+        || (i <= this.page && i + 5 >= this.page)    // in our current page range
+        || (i >= this.page && i - 5 <= this.page)) { // in our current page range
+      if (i != this.page) {
         currentPage.append(' <a href="#" onclick="getPage(' + i + ');">' + i + '</a>')
-        if (i == 1 && page > i + 5) {
+        if (i == 1 && this.page > i + 5) {
           currentPage.append(' ... ');
         }
       } else {
@@ -264,49 +327,23 @@
         currentPage.append(' ... ');
 
         currentPage.append(' <a href="#" onclick="getPage(this.id);" id=">">></a>')
-        i = totalPages - 1;
+        i = this.totalPages - 1;
       }
     }
   }
-  currentPage.append('  ' + results.length + ' results');
+  currentPage.append('  ' + this.results.length + ' results');
 }
 
-var dropState = "";
-
-function getDropDown(str) {
-  var searchMenu = $("#side-menu");
-  if (str == dropState) {
-    dropState = "";
-    searchMenu.find("#" + str).find("#options_" + str).empty();
-  } else {
-    dropState = str;
-
-    $.each(searchMenuOptions, function (search, fields) {
-      if (search === str) {
-        searchMenu.find("#" + search).append('<ul id="options_' + search + '" class="sub-menu">');
-        for (var i = 0; i < fields.length; ++i) {
-          searchMenu.find("#options_" + search).append('<li id="' + fields[i] + '" onclick="submitCatalogSearch(this.id)"><a href="#">' + fields[i] + '</a></li>');
-        }
-        searchMenu.append('</ul>');
-      } else {
-        var ul = $("options_" + search);
-        ul.empty();
-        searchMenu.find("#" + search).find("#options_" + search).empty();
-      }
-    });
-  }
-}
-
-function getPage(clickedPage) {
+Atmos.prototype.getPage = function(clickedPage) {
   console.log(clickedPage);
 
   var nextPage = clickedPage;
   if (clickedPage === "<") {
-    nextPage = page - 5;
+    nextPage = this.page - 5;
   } else if (clickedPage === ">") {
     console.log("> enabled");
 
-    nextPage = page + 5;
+    nextPage = this.page + 5;
   }
 
   nextPage--; // Need to adjust for starting at 0
@@ -314,16 +351,18 @@
   if (nextPage < 0 ) {
     nextPage = 0;
     console.log("0 enabled");
-  } else if (nextPage > totalPages - 1) {
-    nextPage = totalPages - 1;
+  } else if (nextPage > this.totalPages - 1) {
+    nextPage = this.totalPages - 1;
     console.log("total enabled");
   }
 
-  populateResults(nextPage * 20);
+  this.populateResults(nextPage * 20);
   return false;
 }
 
-function submitAutoComplete() {
+
+Atmos.prototype.submitAutoComplete = function() {
+  /* FIXME TODO
   if (autocompleteText.value.length > 0) {
     var selection = autocompleteText.value;
     $.each(dropdown, function (i, dropdownEntry) {
@@ -336,33 +375,11 @@
     query(catalog, selectedSearch, onData, 1);
     delete selectedSearch["?"];
   }
+  */
 }
 
-function submitCatalogSearch(field) {
-  console.log("Sumbit Catalog Search: " + field);
-  // @todo: this logic isn't quite right
-  var remove = false;
-  $.each(selectedSearch, function (search, f) {
-    if (field == f) {
-      delete selectedSearch[field];
-      remove = true;
-    }
-  });
-  if (!remove) {
-    $.each(searchMenuOptions, function (search, fields) {
-      $.each(fields, function (index, f) {
-        if (f == field) {
-          selectedSearch[search] = field;
-        }
-      });
-    });
-  }
-  query(catalog, selectedSearch, onData, 1);
-  populateCurrentSelections();
-  return false;
-}
-
-function populateAutocomplete(fields) {
+Atmos.prototype.populateAutocomplete = function(fields) {
+  /* FIXME TODO
   var isAutocompleteFullName = (autocompleteText.value.charAt(autocompleteText.value.length - 1) === "/");
   var autocompleteFullName = autocompleteText.value;
   for (var i = 0; i < fields.length; ++i) {
@@ -403,35 +420,34 @@
   $("#autocompleteText").autocomplete({
     source: dropdown
   });
+  */
 }
 
-function populateCurrentSelections() {
+Atmos.prototype.populateCurrentSelections = function() { //TODO
   var currentSelection = $(".currentSelections");
   currentSelection.empty();
 
   currentSelection.append("<p>Filtering on:");
 
-  $.each(selectedSearch, function (searchMenuCatagory, selection) {
-    currentSelection.append('  <a href="#" onclick="removeFilter(this.id);" id="' + searchMenuCatagory + ':' + selection + '">[X] ' + searchMenuCatagory + ":" + selection + '</a>');
+  var scope = this;
+
+  $.each(this.selectedSearch, function (searchMenuCatagory, selection) {
+    var e = $('<a href="#">[X] ' + searchMenuCatagory + ":" + selection + '</a>');
+    e.onclick(function(){
+      var searchFilter = $(this).text();
+
+      var search = "";
+      for (var j = 0; j < searchFilter.length; ++j) {
+        search += searchFilter[j] + " ";
+      }
+      console.log("Split values: '" + search + "'");
+
+      delete this.selectedSearch[searchFilter[0]];
+      this.query(catalog, selectedSearch, onData, 1);
+      populateCurrentSelections();
+    });
+    currentSelection.append(e);
   });
 
   currentSelection.append("</p>");
 }
-
-
-function removeFilter(filter) {
-  console.log("Remove filter" + filter);
-  var searchFilter = filter.split(":");
-
-  var search = "";
-  for (var j = 0; j < searchFilter.length; ++j) {
-    search += searchFilter[j] + " ";
-  }
-  console.log("Split values: '" + search + "'");
-
-  delete selectedSearch[searchFilter[0]];
-  query(catalog, selectedSearch, onData, 1);
-  populateCurrentSelections();
-
-  return false;
-}
\ No newline at end of file