diff --git a/public/heatmap.html b/public/heatmap.html
index 1ee986c..0d81b32 100644
--- a/public/heatmap.html
+++ b/public/heatmap.html
@@ -1,3 +1,4 @@
-
+
+
diff --git a/public/heatmap.js b/public/heatmap.js
index c883c59..a1d2a7f 100644
--- a/public/heatmap.js
+++ b/public/heatmap.js
@@ -1,11 +1,13 @@
require('plugins/heatmap/heatmap.less');
+require('plugins/heatmap/heatmap_tooltip.css');
require('plugins/heatmap/color_directive.js');
require('plugins/heatmap/lib/heatmap_controller.js');
require('plugins/heatmap/lib/heatmap_directive.js');
+require('plugins/heatmap/heatmap_tooltip_directive.js');
function HeatmapProvider(Private) {
- var TemplateVisType = Private(require('ui/template_vis_type/TemplateVisType'));
- var Schemas = Private(require('ui/Vis/Schemas'));
+ var TemplateVisType = Private(require('ui/template_vis_type/template_vis_type'));
+ var Schemas = Private(require('ui/vis/schemas'));
var colors = require('plugins/heatmap/colors.js');
return new TemplateVisType({
diff --git a/public/heatmap_tooltip.css b/public/heatmap_tooltip.css
new file mode 100644
index 0000000..3261b8d
--- /dev/null
+++ b/public/heatmap_tooltip.css
@@ -0,0 +1,25 @@
+.heatmap-tooltip {
+ position: absolute;
+ width: auto;
+ fadeout(@gray-darker, 7%);
+ gray-darker: #222222;
+ -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;
+}
+.heatmap-tooltip-list span{
+ font-size: 12px;
+}
+.heatmap-tooltip-list span.key{
+ font-weight: bold;
+}
\ No newline at end of file
diff --git a/public/heatmap_tooltip.html b/public/heatmap_tooltip.html
new file mode 100644
index 0000000..1e5fa00
--- /dev/null
+++ b/public/heatmap_tooltip.html
@@ -0,0 +1,8 @@
+
\ No newline at end of file
diff --git a/public/heatmap_tooltip_directive.js b/public/heatmap_tooltip_directive.js
new file mode 100644
index 0000000..6c95457
--- /dev/null
+++ b/public/heatmap_tooltip_directive.js
@@ -0,0 +1,58 @@
+var d3 = require("d3");
+var _ = require("lodash");
+var module = require('ui/modules').get('heatmap');
+
+module.directive('tooltip', 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);
+ };
+
+ this.hideOnOut = function(){
+ $scope.isShown = false;
+ };
+ }
+
+ 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);
+
+ scope.$watch("ngShow", function (newVal) {
+ ctrl.hideOnOut();
+ });
+ };
+
+ return {
+ restrict: "E",
+ scope: {
+ top: "=",
+ left: "=",
+ items: "=",
+ ngShow: "="
+ },
+ replace: true,
+ controller: controller,
+ link: link,
+ template: require("plugins/heatmap/heatmap_tooltip.html")
+ };
+});
\ No newline at end of file
diff --git a/public/lib/heatmap_controller.js b/public/lib/heatmap_controller.js
index a7aa6db..074f1de 100644
--- a/public/lib/heatmap_controller.js
+++ b/public/lib/heatmap_controller.js
@@ -47,7 +47,7 @@ module.controller('HeatmapController', function ($scope, Private) {
$scope.data = null;
return;
}
-
+
// Add row, column, and metric titles as vis parameters
_.merge($scope.vis.params, {
rowAxis: { title: getLabel($scope.vis.aggs, 'rows') },
@@ -58,5 +58,53 @@ module.controller('HeatmapController', function ($scope, Private) {
$scope.data = [{
cells: processTableGroups(tabifyAggResponse($scope.vis, resp), $scope)
}];
+
+ $scope.eventListeners = {
+ mouseover: [ mouseover ],
+ mouseout: [ mouseout ]
+ };
+
+ 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 () {
+ var params = $scope.vis.params;
+ $scope.tooltipItems = Object.keys(d)
+ .filter(function (key) { return key !== "data"; })
+ .map(function (key) {
+
+ var title = d3.selectAll('text.title');
+ var value = d[key];
+ if (key.toUpperCase() === 'ROW') {
+ key = params.columnAxis.title || 'ROW';
+ }
+ if (key.toUpperCase() === 'COL') {
+ key = params.rowAxis.title || 'COL';
+ }
+ return {
+ key: key.toUpperCase(),
+ value: value
+ };
+ });
+
+ $scope.top = d.data.row + parseInt(params.margin.top) + OFFSET;
+ $scope.left = d.data.col + parseInt(params.margin.left) + OFFSET;
+ });
+ }
+ };
+
+ function mouseout(event){
+ $scope.$apply(function () {
+ $scope.tooltipItems = [];
+ $scope.top = 0;
+ $scope.left = 0;
+ });
+ }
});
});
diff --git a/public/tooltip_directive.js b/public/tooltip_directive.js
new file mode 100644
index 0000000..b09a538
--- /dev/null
+++ b/public/tooltip_directive.js
@@ -0,0 +1,51 @@
+var _ = require("lodash");
+var module = require('ui/modules').get('heatmap');
+
+module.directive('tooltip', function () {
+ debugger;
+ function controller($scope) {
+ $scope.isShown = false;
+ debugger;
+ /*
+ * 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) {
+ debugger;
+ 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) {
+ debugger;
+ render(scope);
+ }, 250);
+ }
+
+ return {
+ restrict: "E",
+ scope: {
+ top: "=",
+ left: "=",
+ items: "="
+ },
+ replace: true,
+ controller: controller,
+ link: link,
+ template: require("plugins/heatmap/heatmap_tooltip.html")
+ };
+});
\ No newline at end of file
diff --git a/public/vis/components/axis/axis.js b/public/vis/components/axis/axis.js
index db2f5ac..98794ea 100644
--- a/public/vis/components/axis/axis.js
+++ b/public/vis/components/axis/axis.js
@@ -58,7 +58,7 @@ function axes() {
var text = g.selectAll('text.title')
.data([data]);
-
+
text.exit().remove();
text.enter().append('text')
.attr('class', title.class || 'title');
diff --git a/public/vis/components/control/events.js b/public/vis/components/control/events.js
index dfd5ecf..c3b1ce4 100644
--- a/public/vis/components/control/events.js
+++ b/public/vis/components/control/events.js
@@ -14,9 +14,8 @@ function events() {
}
d3.entries(listeners).forEach(function (d) {
- svg.on(d.key, function () {
+ element.on(d.key, function () {
d3.event.stopPropagation(); // => event.stopPropagation()
-
_.forEach(d.value, function (listener) {
listener.call(this, processor(d3.event));
});
diff --git a/public/vis/components/elements/text.js b/public/vis/components/elements/text.js
index 63bcbc9..0500c15 100644
--- a/public/vis/components/elements/text.js
+++ b/public/vis/components/elements/text.js
@@ -15,7 +15,7 @@ function text() {
selection.each(function (data) {
var text = d3.select(this).selectAll('text.' + cssClass)
.data(data);
-
+
text.exit().remove();
text.enter().append('text')
diff --git a/public/vis/index.js b/public/vis/index.js
index 44be53d..e78df43 100644
--- a/public/vis/index.js
+++ b/public/vis/index.js
@@ -15,7 +15,7 @@ function vis() {
function generator(selection) {
selection.each(function (data) {
events.listeners(listeners);
-
+
layout.attr({
type: opts.layout || 'grid',
columns: opts.numOfColumns || 0,