HTRACE-99: gui: Double clicking on spans should bring up span details (iwasakims / cmccabe)
diff --git a/htrace-webapp/src/main/web/app/search_results_view.js b/htrace-webapp/src/main/web/app/search_results_view.js
index 3f009d4..81197c3 100644
--- a/htrace-webapp/src/main/web/app/search_results_view.js
+++ b/htrace-webapp/src/main/web/app/search_results_view.js
@@ -96,6 +96,17 @@
this.draw();
},
+ handleDblclick: function(e) {
+ e.preventDefault();
+ this.widgetManager.handle({
+ type: "dblclick",
+ x: this.getCanvasX(e),
+ y: this.getCanvasY(e),
+ raw: e
+ });
+ this.draw();
+ },
+
render: function() {
console.log("SearchResultsView#render.");
$(this.el).html(_.template($("#search-results-view-template").html()));
@@ -259,6 +270,10 @@
$("#resultsCanvas").on("mousemove", function(e) {
view.handleMouseMove(e);
});
+ $("#resultsCanvas").off("dblclick");
+ $("#resultsCanvas").on("dblclick", function(e) {
+ view.handleDblclick(e);
+ });
$("#resultsCanvas").off("contextmenu");
$("#resultsCanvas").on("contextmenu", function(e) {
return false;
@@ -269,7 +284,10 @@
$(window).off("resize");
$("#resultsCanvas").off("mousedown");
$("#resultsCanvas").off("mouseup");
+ $("#resultsCanvas").off("mouseout");
$("#resultsCanvas").off("mousemove");
+ $("#resultsCanvas").off("dblclick");
+ $("#resultsCanvas").off("contextmenu");
Backbone.View.prototype.remove.apply(this, arguments);
},
diff --git a/htrace-webapp/src/main/web/app/span_widget.js b/htrace-webapp/src/main/web/app/span_widget.js
index e06c8b4..1ef402c 100644
--- a/htrace-webapp/src/main/web/app/span_widget.js
+++ b/htrace-webapp/src/main/web/app/span_widget.js
@@ -19,7 +19,7 @@
var htrace = htrace || {};
-htrace.fillSpanDetailsView = function(span) {
+htrace.showSpanDetails = function(span) {
var info = {
spanID: span.get("spanID"),
begin: htrace.dateToString(span.get("begin"), 10),
@@ -94,17 +94,12 @@
for (i = 0; i < len; i++) {
// Make every other row grey to improve visibility.
var colorString = ((i%2) == 1) ? "#f1f1f1" : "#ffffff";
- h += _.template('<tr bgcolor="' + colorString + '">' +
- '<td style="width:30%;word-wrap:break-word"><%- key %></td>' +
- '<td style="width:70%;word-wrap:break-word"><%- val %></td>' +
- "</tr>")({key: keys[i], val: info[keys[i]]});
+ h += _.template($("#table-row-template").html())(
+ {bgcolor: colorString, key: keys[i], val: info[keys[i]]});
}
h += '</table>';
- $("#spanDetails").html(h);
-};
-
-htrace.clearSpanDetailsView = function() {
- $("#spanDetails").html("");
+ htrace.showModal(_.template($("#modal-table-template").html())(
+ {title: "Span Details", body: h}));
};
// Widget containing the trace span displayed on the canvas.
@@ -182,6 +177,17 @@
// ", begin=" + this.span.get('begin') + ", end=" + this.span.get('end'));
this.ctx.fillRect(beginX, this.y0 + gapY, endX - beginX,
this.ySize - (gapY * 2));
+
+ // Draw a dots showing time points where annotations are.
+ var annotations = this.span.get('timeAnnotations');
+ var annotationY = this.y0 + gapY;
+ var annotationW = 4;
+ var annotationH = (this.ySize - (gapY * 2)) / 2;
+ this.ctx.fillStyle="#419641";
+ for (var i = 0; i < annotations.length; i++) {
+ this.ctx.fillRect(this.timeToPosition(annotations[i].t), annotationY,
+ annotationW, annotationH);
+ }
}
// Draw description text
@@ -209,45 +215,40 @@
return true;
}
if (e.raw.ctrlKey) {
- // If the control key is pressed, we can unselect the current
- // selection, or create multiple selections.
+ // If the control key is pressed, we toggle the current selection.
+ // The user can create multiple selections this way.
if (this.span.get("selected")) {
this.span.set("selected", false);
} else {
this.span.set("selected", true);
}
- var selection = null;
- var multipleSelections = false;
- this.manager.searchResultsView.applyToAllSpans(function(span) {
- if (span.get("selected")) {
- if (selection == null) {
- selection = span;
- } else {
- multipleSelections = true;
- }
- }
- });
- if (multipleSelections) {
- selection = null;
- }
- if (selection == null) {
- htrace.clearSpanDetailsView();
- } else {
- htrace.fillSpanDetailsView(selection);
- }
} else {
+ var that = this;
this.manager.searchResultsView.applyToAllSpans(function(span) {
- if (span.get("selected")) {
+ // Note: we don't want to set the selection state unless we need
+ // to. Setting the state (even to the same thing it already is)
+ // triggers a full re-render, if the span is one in the results
+ // collection. A full re-render slows us down and disrupts events
+ // like double-clicking.
+ if (that.span === span) {
+ if (!span.get("selected")) {
+ span.set("selected", true);
+ }
+ } else if (span.get("selected")) {
span.set("selected", false);
}
});
- this.span.set("selected", true);
- htrace.fillSpanDetailsView(this.span);
}
return true;
case "draw":
this.draw();
return true;
+ case "dblclick":
+ if (htrace.inBoundingBox(e.x, e.y,
+ this.x0, this.xF, this.y0, this.yF)) {
+ htrace.showSpanDetails(this.span);
+ }
+ return true;
}
};
@@ -303,5 +304,6 @@
});
}
this.manager.register("mouseDown", this);
+ this.manager.register("dblclick", this);
return this;
};
diff --git a/htrace-webapp/src/main/web/app/widget_manager.js b/htrace-webapp/src/main/web/app/widget_manager.js
index 5f393b0..ae14b2b 100644
--- a/htrace-webapp/src/main/web/app/widget_manager.js
+++ b/htrace-webapp/src/main/web/app/widget_manager.js
@@ -32,6 +32,7 @@
"mouseUp": [],
"mouseMove": [],
"mouseOut": [],
+ "dblclick": [],
"draw": [],
};
diff --git a/htrace-webapp/src/main/web/index.html b/htrace-webapp/src/main/web/index.html
index 0e8e6c3..77cbe09 100644
--- a/htrace-webapp/src/main/web/index.html
+++ b/htrace-webapp/src/main/web/index.html
@@ -92,14 +92,6 @@
</div>
<div class="panel panel-default">
<div class="panel-heading">
- <h1 class="panel-title">Span Details</h1>
- </div style="border: 1px solid #000000;">
- <div class="panel-body">
- <div id="spanDetails" ></div>
- </div>
- </div>
- <div class="panel panel-default">
- <div class="panel-heading">
<h1 class="panel-title">Search</h1>
</div style="border: 1px solid #000000;">
<div class="panel-body">
@@ -197,6 +189,33 @@
</div>
</script>
+ <script id="modal-table-template" type="text/template">
+ <div class="modal-dialog modal-lg">
+ <div class="modal-content">
+ <div class="modal-header">
+ <button type="button" class="close" data-dismiss="modal"
+ aria-label="Close">
+ <span aria-hidden="true">×</span>
+ </button>
+ <h4 class="modal-title"><%= title %></h4>
+ </div>
+ <div class="modal-body">
+ <%= body %><p/>
+ </div>
+ <div class="modal-footer">
+ <button type="button" class="btn btn-primary" data-dismiss="modal">Close</button>
+ </div>
+ </div>
+ </div>
+ </script>
+
+ <script id="table-row-template" type="text/template">
+ <tr bgcolor="<%= bgcolor %>">
+ <td style="width:30%;word-wrap:break-word"><%- key %></td>
+ <td style="width:70%;word-wrap:break-word"><%- val %></td>
+ </tr>
+ </script>
+
<script src="lib/jquery-2.1.4.js" type="text/javascript"></script>
<script src="lib/bootstrap-3.3.1/js/bootstrap.min.js" type="text/javascript"></script>
<script src="lib/underscore-1.7.0.js" type="text/javascript"></script>