Skip to content

Commit 16e22bd

Browse files
committed
Added highlight to all blocks within same range when block size is less than 16x16px.
Added tooltips specific to range. Added minBlockSize and rangeHoverSize attributes for overrides. PTNFLY-1226
1 parent 1648215 commit 16e22bd

File tree

1 file changed

+71
-4
lines changed

1 file changed

+71
-4
lines changed

src/charts/heatmap/heatmap.directive.js

Lines changed: 71 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,14 @@
1818
* @param {boolean=} showLegend flag to show the legend, defaults to true
1919
* @param {array=} legendLabels the labels for the legend - defaults: ['< 70%', '70-80%' ,'80-90%', '> 90%']
2020
* @param {number=} maxBlockSize the maximum size for blocks in the heatmap. Default: 50, Range: 5 - 50
21+
* @param {number=} minBlockSize the minimum size for blocks in the heatmap. Default: 2
2122
* @param {number=} blockPadding the padding in pixels between blocks (default: 2)
2223
* @param {array=} thresholds the threshold values for the heapmap - defaults: [0.7, 0.8, 0.9]
2324
* @param {array=} heatmapColorPattern the colors that correspond to the various threshold values (lowest to hightest value ex: <70& to >90%) - defaults: ['#d4f0fa', '#F9D67A', '#EC7A08', '#CE0000']
2425
* @param {function=} clickAction function(block) function to call when a block is clicked on
26+
* @param {number=} rangeHoverSize the maximum size for highlighting blocks in the same range. Default: 15
27+
* @param {boolean=} rangeOnHover flag to highlight blocks in the same range on hover, defaults to true
28+
* @param {array=} rangeTooltips the tooltips for blocks in the same range - defaults: ['< 70%', '70-80%' ,'80-90%', '> 90%']
2529
* @example
2630
<example module="patternfly.charts">
2731
<file name="index.html">
@@ -31,12 +35,16 @@
3135
<div pf-heatmap id="id" chart-title="title" data="data" chart-data-available="dataAvailable"
3236
show-legend="showLegends"></div>
3337
</div>
34-
<div class="col-md-5 example-heatmap-container">
38+
<div class="col-md-3 example-heatmap-container">
3539
<div pf-heatmap id="id" chart-title="titleAlt" data="data" chart-data-available="dataAvailable"
3640
show-legend="showLegends" legend-labels="legendLabels" max-block-size="20" block-padding="5"
3741
heatmap-color-pattern="heatmapColorPattern" thresholds="thresholds"
3842
click-action="clickAction"></div>
3943
</div>
44+
<div class="col-md-3 example-heatmap-container">
45+
<div pf-heatmap id="id" chart-title="titleSmall" data="data" chart-data-available="dataAvailable"
46+
show-legend="showLegends" max-block-size="15" range-tooltips="rangeTooltips"></div>
47+
</div>
4048
</div>
4149
<div class="row">
4250
<div class="col-md-3">
@@ -119,7 +127,9 @@
119127
$scope.dataAvailable = true;
120128
$scope.title = 'Utilization - Using Defaults';
121129
$scope.titleAlt = 'Utilization - Overriding Defaults';
130+
$scope.titleSmall = 'Utilization - Small Blocks';
122131
$scope.legendLabels = ['< 60%','70%', '70-80%' ,'80-90%', '> 90%'];
132+
$scope.rangeTooltips = ['Memory Utilization < 70%<br\>40 Nodes', 'Memory Utilization 70-80%<br\>4 Nodes', 'Memory Utilization 80-90%<br\>4 Nodes', 'Memory Utilization > 90%<br\>4 Nodes'];
123133
$scope.thresholds = [0.6, 0.7, 0.8, 0.9];
124134
$scope.heatmapColorPattern = ['#d4f0fa', '#F9D67A', '#EC7A08', '#CE0000', '#f00'];
125135
@@ -144,16 +154,21 @@ angular.module('patternfly.charts').directive('pfHeatmap', function ($compile, $
144154
showLegend: '=?',
145155
legendLabels: '=?',
146156
maxBlockSize: '@',
157+
minBlockSize: '@',
147158
blockPadding: '@',
148159
thresholds: '=?',
149160
heatmapColorPattern: '=?',
150-
clickAction: '=?'
161+
clickAction: '=?',
162+
rangeOnHover: '=?',
163+
rangeHoverSize: '@',
164+
rangeTooltips: '=?'
151165
},
152166
templateUrl: 'charts/heatmap/heatmap.html',
153167
controller: function ($scope) {
154168
var thresholdDefaults = [0.7, 0.8, 0.9];
155169
var heatmapColorPatternDefaults = ['#d4f0fa', '#F9D67A', '#EC7A08', '#CE0000'];
156170
var legendLabelDefaults = ['< 70%', '70-80%' ,'80-90%', '> 90%'];
171+
var rangeTooltipDefaults = ['< 70%', '70-80%' ,'80-90%', '> 90%'];
157172
var heightDefault = 200;
158173

159174
//Allow overriding of defaults
@@ -168,12 +183,30 @@ angular.module('patternfly.charts').directive('pfHeatmap', function ($compile, $
168183
}
169184
}
170185

186+
if ($scope.minBlockSize === undefined || isNaN($scope.minBlockSize)) {
187+
$scope.minSize = 2;
188+
} else {
189+
$scope.minSize = parseInt($scope.minBlockSize);
190+
}
191+
171192
if ($scope.blockPadding === undefined || isNaN($scope.blockPadding)) {
172193
$scope.padding = 2;
173194
} else {
174195
$scope.padding = parseInt($scope.blockPadding);
175196
}
176197

198+
if ($scope.rangeHoverSize === undefined || isNaN($scope.rangeHoverSize)) {
199+
$scope.rangeHoverSize = 15;
200+
} else {
201+
$scope.rangeHoverSize = parseInt($scope.rangeHoverSize);
202+
}
203+
204+
$scope.rangeOnHover = ($scope.rangeOnHover === undefined || $scope.rangeOnHover) ? true : false;
205+
206+
if (!$scope.rangeTooltips) {
207+
$scope.rangeTooltips = rangeTooltipDefaults;
208+
}
209+
177210
if (!$scope.thresholds) {
178211
$scope.thresholds = thresholdDefaults;
179212
}
@@ -215,7 +248,15 @@ angular.module('patternfly.charts').directive('pfHeatmap', function ($compile, $
215248
blockSize * numberOfRows > containerHeight) {
216249
numberOfRows = (blockSize === 0) ? 0 : Math.floor(containerHeight / blockSize);
217250
}
251+
} else if ((blockSize - scope.padding) < scope.minSize) {
252+
blockSize = scope.padding + scope.minSize;
218253

254+
// Attempt to square off the area, check if square fits
255+
numberOfRows = Math.ceil(Math.sqrt(scope.data.length));
256+
if (blockSize * numberOfRows > containerWidth ||
257+
blockSize * numberOfRows > containerHeight) {
258+
numberOfRows = (blockSize === 0) ? 0 : Math.floor(containerHeight / blockSize);
259+
}
219260
} else {
220261
numberOfRows = (blockSize === 0) ? 0 : Math.floor(containerHeight / blockSize);
221262
}
@@ -246,14 +287,25 @@ angular.module('patternfly.charts').directive('pfHeatmap', function ($compile, $
246287
var redraw = function () {
247288
var data = scope.data;
248289
var color = d3.scale.threshold().domain(scope.thresholds).range(scope.heatmapColorPattern);
290+
var rangeTooltip = d3.scale.threshold().domain(scope.thresholds).range(scope.rangeTooltips);
249291
var blocks;
250292
var fillSize = blockSize - scope.padding;
251293
var highlightBlock = function (block, active) {
252294
block.style('fill-opacity', active ? 1 : 0.4);
253295
};
296+
var highlightBlockColor = function (block, fillColor) {
297+
// Get fill color from given block
298+
var blockColor = color(block.map(function (d) {
299+
return d[0].__data__.value;
300+
}));
301+
// If given color matches, apply highlight
302+
if (blockColor === fillColor) {
303+
block.style('fill-opacity', 1);
304+
}
305+
};
306+
254307
var svg = window.d3.select(thisComponent);
255308
svg.selectAll('*').remove();
256-
257309
blocks = svg.selectAll('rect').data(data).enter().append('rect');
258310
blocks.attr('x', function (d, i) {
259311
return Math.floor(i / numberOfRows) * blockSize;
@@ -262,6 +314,9 @@ angular.module('patternfly.charts').directive('pfHeatmap', function ($compile, $
262314
}).attr('width', fillSize).attr('height', fillSize).style('fill', function (d) {
263315
return color(d.value);
264316
}).attr('tooltip-html-unsafe', function (d, i) { //tooltip-html is throwing an exception
317+
if (scope.rangeOnHover && fillSize <= scope.rangeHoverSize) {
318+
return rangeTooltip(d.value);
319+
}
265320
return d.tooltip;
266321
}).attr('tooltip-append-to-body', function (d, i) {
267322
return true;
@@ -271,8 +326,20 @@ angular.module('patternfly.charts').directive('pfHeatmap', function ($compile, $
271326

272327
//Adding events
273328
blocks.on('mouseover', function () {
329+
var fillColor;
274330
blocks.call(highlightBlock, false);
275-
d3.select(this).call(highlightBlock, true);
331+
if (scope.rangeOnHover && fillSize <= scope.rangeHoverSize) {
332+
// Get fill color for current block
333+
fillColor = color(d3.select(this).map(function (d) {
334+
return d[0].__data__.value;
335+
}));
336+
// Highlight all blocks matching fill color
337+
blocks[0].forEach(function (block) {
338+
highlightBlockColor(d3.select(block), fillColor);
339+
});
340+
} else {
341+
d3.select(this).call(highlightBlock, true);
342+
}
276343
});
277344
blocks.on('click', function (d) {
278345
if (scope.clickAction) {

0 commit comments

Comments
 (0)