HTRACE-45. Add Span details page skeleton (Abraham Elmahrek via Colin P.  McCabe)
diff --git a/htrace-core/src/web/app/setup.js b/htrace-core/src/web/app/setup.js
index 12bd691..211b2ea 100644
--- a/htrace-core/src/web/app/setup.js
+++ b/htrace-core/src/web/app/setup.js
@@ -16,12 +16,68 @@
  * specific language governing permissions and limitations
  * under the License.
  */
- 
+
+var Router = Backbone.Router.extend({
+
+  routes: {
+    "": "search",
+    "spans/:span": "span"
+  },
+
+  initialize: function() {
+    this.spansCollection = spans.clone();
+    this.spanViews = {};
+
+    this.listSpansView = new App.ListSpansView({
+      "collection": this.spansCollection,
+      "id": "span-list"
+    });
+    this.searchView = new App.SearchView({
+      "collection": this.spansCollection,
+      "el": $("#list").find("[role='form']")
+    });
+
+
+    this.spansCollection.trigger('change');
+  },
+
+  search: function() {
+    var root = $("#list");
+
+    $("*[role='application']").css('display', 'none');
+
+    root.find("*[role='main']").append(this.listSpansView.$el);
+
+    root.show();
+  },
+
+  span: function(span) {
+    var root = $("#span");
+
+    // Cache views to avoid leaks
+    if (!(span in this.spanViews)) {
+      this.spanViews[span] = new App.SpanView({
+        "model": this.spansCollection.findWhere({
+          "spanId": parseInt(span)
+        }),
+        "id": "span-details"
+      });
+    }
+
+    var view = this.spanViews[span];
+
+    $("*[role='application']").css('display', 'none');
+
+    view.render();
+    root.find("*[role='main']").empty();
+    root.find("*[role='main']").append(view.$el);
+
+    root.show();
+  }
+});
+
+window.urlconf = new Router();
+
 $(function() {
-  var spansCollection = spans.clone();
-
-  $("*[role='main']").append(new App.SpanView({"collection": spansCollection, "id": "span-list"}).$el);
-  spansCollection.trigger('change');
-
-  var search = new App.SearchView({"collection": spansCollection, "el": $("*[role='form']")});
-})
\ No newline at end of file
+  Backbone.history.start();
+});
diff --git a/htrace-core/src/web/app/views/span.js b/htrace-core/src/web/app/views/span.js
index 81cf59c..d976a71 100644
--- a/htrace-core/src/web/app/views/span.js
+++ b/htrace-core/src/web/app/views/span.js
@@ -17,10 +17,13 @@
  * under the License.
  */
  
-App.SpanView = Backbone.View.extend({
+App.ListSpansView = Backbone.View.extend({
   "tagName": "ul",
   "className": "spans",
-  "template": _.template($("#span-template").html()),
+  "template": _.template($("#list-span-template").html()),
+  "events": {
+    "click li": "spanClicked"
+  },
 
   initialize: function() {
     _.bindAll(this, "render");
@@ -30,9 +33,44 @@
   },
 
   "render": function() {
+    if (this.rendered) {
+      $(this.el).empty();
+    }
+
+    $(this.el).append(
+        this.template({
+          "spans": this.collection.toJSON()
+        }));
+
+    this.rendered = true;
+
+    return this;
+  },
+
+  "spanClicked": function(e) {
+    e.preventDefault();
+    var spanId = $(e.currentTarget).data("id");
+    window.urlconf.navigate("/spans/" + spanId, true);
+  }
+});
+
+App.SpanView = Backbone.View.extend({
+  "tagName": "div",
+  "className": "span",
+  "template": _.template($("#span-details-template").html()),
+
+  initialize: function() {
+    _.bindAll(this, "render");
+    this.model.bind('change', this.render);
+
+    this.rendered = false;
+  },
+
+  "render": function() {
     var context = {
-      "spans": this.collection.toJSON()
+      "span": this.model.toJSON()
     };
+    context["span"]["duration"] = this.model.duration();
 
     if (this.rendered) {
       $(this.el).empty();
diff --git a/htrace-core/src/web/index.html b/htrace-core/src/web/index.html
index 443116e..efb8ff0 100644
--- a/htrace-core/src/web/index.html
+++ b/htrace-core/src/web/index.html
@@ -40,7 +40,14 @@
         </div>
       </nav>
     </header>
-    <div class="container-fluid" role="application">
+
+    <div class="container-fluid" id="span" role="application">
+      <div class="row">
+        <div class="col-md-12" role="main"></div>
+      </div>
+    </div>
+
+    <div class="container-fluid" id="list" role="application">
       <div class="row">
         <div class="col-md-3" role="form">
           <div class="panel panel-default">
@@ -83,26 +90,62 @@
         <div class="col-md-9" role="main"></div>
       </div>
     </div>
+
     <footer></footer>
 
-    <script id="span-template" type="text/html">
-    <% _.each(spans, function(span) { %>
-    <li class="span">
-      <div class="panel panel-primary">
-        <div class="panel-heading">
-          <h3 class="panel-title">
-            <p class="pull-right"><%- span.processId %></p>
-            <p class="pull-left"><%- span.spanId %>&nbsp;&nbsp;</p>
-            <p class="pull-left"><%- span.description %></p>
-            <div style="clear: both; line-height: 0px; font-size: 0px;"></div>
-          </h3>
+    <script id="span-details-template" type="text/html">
+      <div class="page-header">
+        <h1><%- span.description %></h1>
+      </div>
+      <div class="page-contents">
+        <div class="row">
+          <div class="col-md-2">
+            <h4>Span id</h4>
+          </div>
+          <div class="col-md-10"><%- span.spanId %></div>
         </div>
-        <div class="panel-body">
-
+        <div class="row">
+          <div class="col-md-2">
+            <h4>Process id</h4>
+          </div>
+          <div class="col-md-10"><%- span.processId %></div>
+        </div>
+        <div class="row">
+          <div class="col-md-2">
+            <h4>Begin time</h4>
+          </div>
+          <div class="col-md-10"><%- span.beginTime %></div>
+        </div>
+        <div class="row">
+          <div class="col-md-2">
+            <h4>End time</h4>
+          </div>
+          <div class="col-md-10"><%- span.stopTime %></div>
+        </div>
+        <div class="row">
+          <div class="col-md-2">
+            <h4>Duration</h4>
+          </div>
+          <div class="col-md-10"><%- span.duration %></div>
         </div>
       </div>
-    </li>
-    <% }); %>
+    </script>
+
+    <script id="list-span-template" type="text/html">
+      <% _.each(spans, function(span) { %>
+      <li class="span" data-id="<%- span.spanId %>">
+        <div class="panel panel-primary">
+          <div class="panel-heading">
+            <h3 class="panel-title">
+              <p class="pull-right"><%- span.processId %></p>
+              <p class="pull-left"><%- span.spanId %>&nbsp;&nbsp;</p>
+              <p class="pull-left"><%- span.description %></p>
+              <div style="clear: both; line-height: 0px; font-size: 0px;"></div>
+            </h3>
+          </div>
+        </div>
+      </li>
+      <% }); %>
     </script>
 
     <script src="lib/js/jquery-2.1.3.min.js" type="text/javascript"></script>
@@ -118,8 +161,5 @@
     <script src="app/views/span.js" type="text/javascript"></script>
     <script src="app/views/search.js" type="text/javascript"></script>
     <script src="app/setup.js" type="text/javascript"></script>
-    <script type="text/javascript">
-      
-    </script>
   </body>
 </html>