Skip to content

Commit 6924987

Browse files
authored
Merge pull request patternfly#268 from dlabrecq/PTNFLY-1226
Added highlight to all blocks within same range
2 parents c58f926 + 16e22bd commit 6924987

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)