Hardened the script against some of the corner cases.

Sometimes the results are empty and we need to handle it. An empty
string is not valid in JSON.

Sometimes the results are equal to null which is valid JSON but is not
valid for iterating over.

Change-Id: I1615ccdcbbc43e8cf947f53c7a920c7f7ec0c251
diff --git a/client/query/query.html b/client/query/query.html
index 09b0fba..d2174f7 100644
--- a/client/query/query.html
+++ b/client/query/query.html
@@ -30,7 +30,7 @@
 
 <body id="body">
   <header>
-    <div class="navbar navbar-default container-fluid">
+    <div class="navbar navbar-default navbar-static-top container-fluid">
       <div class="navbar-header">
         <div class="navbar-brand">NDN Query and Retrieval Tool</div>
       </div>
@@ -74,7 +74,7 @@
         </div>
 
         <div class="panel panel-default">
-          <div class="panel-heading">Results:</div>
+          <div class="panel-heading">Results</div>
           <div class="panel-body">
             <div class="page"></div>
             <table id="resultTable" class="table"></table>
diff --git a/client/query/query.js b/client/query/query.js
index 01b1fb2..6e41e67 100644
--- a/client/query/query.js
+++ b/client/query/query.js
@@ -86,10 +86,10 @@
             });
           });
 
-          //Toggle the menus.
-          e.click(function(){
+          //Toggle the menus. (Only respond when the immediate tab is clicked.)
+          e.find('> a').click(function(){
             scope.categories.find('.subnav').slideUp();
-            var t = $(this).find('.subnav');
+            var t = $(this).siblings('.subnav');
             if ( !t.is(':visible')){
               t.slideDown().triggerHandler('focus'); //Cancel other animations and slide down.
             }
@@ -111,33 +111,47 @@
 Atmos.prototype.onData = function(data) {
   var payloadStr = data.content.toString().split("\n")[0];
 
+  if (!payloadStr || payloadStr.length === 0){
+    this.populateResults(0);
+    return; //No results were returned.
+  }
+
   var queryResults = JSON.parse(payloadStr);
 
   var scope = this;
 
   //TODO Fix paging.
 
-  $.each(queryResults, function (queryResult, field) {
+  try {
 
-    if (queryResult == "next") {
-      scope.populateAutocomplete(field);
-    }
+    $.each(queryResults, function (queryResult, field) {
 
-    $.each(field, function (entryCount, name) {
-      scope.results.push(name);
+      if (queryResult == "next") {
+        scope.populateAutocomplete(field);
+      }
+
+      if (queryResult == "results" && field == null){
+        return; //Sometimes the results are null. (We should skip this.)
+      }
+
+      $.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);
+    // Calculating the current page and the view
+    this.totalPages = Math.ceil(this.resultCount / 20);
+    this.populateResults(0);
+
+  } catch (e) {
+    console.error(e.message, e.stack);
+  }
 }
 
 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");
@@ -284,8 +298,7 @@
 
 Atmos.prototype.populateResults = function(startIndex) {
   this.resultTable.empty();
-  this.resultTable.append('<tr><th colspan="2">Results</th></tr>');
-
+  //this.resultTable.append('<tr><th colspan="2">Results</th></tr>');
 
   for (var i = startIndex; i < startIndex + 20 && i < this.results.length; ++i) {
     this.resultTable.append('<tr><td>' + this.results[i]
diff --git a/client/query/sample.json b/client/query/sample.json
index 249817b..260abcc 100644
--- a/client/query/sample.json
+++ b/client/query/sample.json
@@ -724,4 +724,4 @@
             }
         ]
     }
-}
\ No newline at end of file
+}