-
Notifications
You must be signed in to change notification settings - Fork 13
Add tooltip #6 #38
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add tooltip #6 #38
Conversation
auto for width
|
This PR is made as @jccq request |
|
Firstly, @ScorpiOVN and @jccq thanks for this pr. Its something that really needed to get done. While I understand the approach here, I am not completely on board with having events attached directly to the
The heatmap directive is already setup to take an The // Example eventListeners object
// This is added within the heatmap_controller.js file.
{
mouseover: [ myCustomMouseoverFunction, ... ],
mouseout: [ myCustomMouseoutFunction, ...],
...
}For a look at the code to see how events are attached to the The event listeners are attached in one place, on the parent // Added within the heatmap_controller.js file.
function myCustomMouseoverFunction(event) {
var target = d3.select(event.target);
var isHeatmapCell = (target.attr("class") === "cell");
if (isHeatmapCell) {
// get data bound to heatmap cell
var d = _.first(target.data());
// Custom code for tooltip functionality goes here
}
}Now that we can separate the rect generation code from the tooltip code, we need to create the tooltip object. Since Kibana uses angular, the best way is probably to create a tooltip directive. In this way, we can populate the tooltip directive from our // heatmap_tooltip.js
var d3 = require("d3");
var _ = require("lodash");
angular.directive('heatmapTooltip', function () {
function controller($scope) {
$scope.isShown = false;
/*
* Make sure that the items array is populated before tooltip is shown.
* The items variable is an array of objects, e.g.
* [
* { key: "Column", value: "Tuesday" },
* { key: "Row", value: "12pm" },
* { key: "Count", value: 12 }
* ]
*/
this.showOnHover = function () {
$scope.isShown = !!($scope.items && _.isArray($scope.items) && $scope.items.length);
};
}
function link(scope, element, attrs, ctrl) {
function render($scope) {
d3.select(_.first(element))
.style("top", $scope.top + "px")
.style("left", $scope.left + "px");
ctrl.showOnHover();
}
scope.$watchGroup(["top", "left", "items"], function (newVal, oldVal, scope) {
render(scope);
}, 250);
}
return {
restrict: "E",
scope: {
top: "=",
left: "=",
items: "="
},
replace: true,
controller: controller,
link: link,
template: require("plugins/heatmap/heatmap_tooltip.html")
};
});Here is what the html for this directive might look like: <!-- heatmap_tooltip.html -->
<div class="heatmap-tooltip" ng-show="isShown">
<ul class="heatmap-tooltip-list">
<li ng-repeat="item in items">
<span>{{ item.key }}: </span>
<span>{{ item.value }}</span>
</li>
</ul>
</div>Here is what the css for this directive might look like: /* heatmap_tooltip.css */
.heatmap-tooltip {
position: absolute;
width: auto;
height: auto;
padding: 5px;
z-index: 150;
background-color: #d3d3d3;
-webkit-border-radius: 10px;
-moz-border-radius: 10px;
border-radius: 10px;
-webkit-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
-mox-box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
box-shadow: 4px 4px 10px rgba(0, 0, 0, 0.4);
pointer-events: none;
white-space: nowrap;
}
.heatmap-tooltip-list {
padding: 0;
list-style-type: none;
}Finally, we can add the tooltip directive to our <!-- heatmap.html -->
<div ng-controller="HeatmapController" class="heatmap-vis">
<heatmap data="data" options="vis.params" eventListeners="eventListeners"></heatmap>
<heatmap-tooltip top="top" left="left" items="tooltipItems"></heatmap-tooltip>
</div>Now, we would need to complete the tooltip functionality. This would happen in the // heatmap_controller.js
...
$scope.data = [{
cells: processTableGroups(tabifyAggResponse($scope.vis, resp), $scope)
}];
$scope.eventListeners = {
mouseover: [ mouseover ]
};
// Default tooltip settings
$scope.tooltipItems = [];
$scope.top = 0;
$scope.left = 0;
function mouseover(event) {
var target = d3.select(event.target);
var isHeatmapCell = (target.attr("class") === "cell");
var OFFSET = 50;
if (isHeatmapCell) {
// get data bound to heatmap cell
var d = _.first(target.data());
// Custom code for tooltip functionality goes here
$scope.$apply(function () {
$scope.tooltipItems = Object.keys(d)
.filter(function (key) { return key !== "data"; })
.map(function (key) {
return {
key: key.toUpperCase(),
value: d[key]
};
});
$scope.top = d.data.row + OFFSET;
$scope.left = d.data.col + OFFSET;
}
}
});
});While this solution is more involved, it satisfies the criteria above. That is:
|
|
I've found a bug here.
|
|
There should also be a function mouseout() {
$scope.$apply(function () {
$scope.tooltipItems = [];
$scope.top = 0;
$scope.left = 0;
});
} |
|
Hi Stormpython, The: eventListeners="eventListeners" |
|
@tuhp thank you. |
|
Closing in favor of #41. |
Add tooltip #6