Reputation: 640
I am trying to display tooltip on hovering over the legends. Highcharts doesnt have the function to do so hence i figured that using jquery tooltip plugin I will be able to do so. The graph is generated dynamically using realtime data. As the data is added, the series is generated and simultaneously the series is added in the Legend section. There might be the case that series name is too big and would be truncated.In such condition, I would like to display the entire series name in the form of tooltip when hovered over the name. Can anyone please give me any suggestion for how to go about it? Thanks, :) My chart code is given below:
var chartConfig = {
chart: {
zoomType: 'x',
marginTop: 24,
borderWidth: 1,
borderRadius: 6,
borderColor: '#ccc',
backgroundColor: '#F5F5F5',
resetZoomButton: {
theme: {
display: 'none'
}
},
events: {
selection: function(event){
if (event.xAxis) {
$scope.zoomStart = Math.floor(event.xAxis[0].min).toString();
$scope.zoomEnd = Math.floor(event.xAxis[0].max).toString();
$scope.zoomed = true;
$scope.$apply();
}
},
load: function(){
console.log("successfully loaded");
console.log(chartConfig.legend.text);
},//load
addSeries: function(){
var chart = this;
legend = chart.legend;
console.log('Series added '+legend.allItems.length);
}
}
},
colors: [
'#a6a8ab', //very light grey - severity 0
'#7bc043', //light green - severity 1
'#6798c7', //blue - severity 2
'#edbe1c', //yellow - severity 3
'#ed6a1c', //Red - severity 4
'#ed1c24', //Dark red - severity 5
'#17A768', //green
'#E7E737', //yellow
'#F1AD1D', //orange
'#F76C27', //darker orange
'#E73F3F', //red
'#781800', //darker red
'#A8A8A8', //grey
'#BBAE93', //yellowish grey
'#EBEFC9', //yellow almost white
'#424242', //dark grey
'#A8C0D8', //bluish grey
'#08050E' //nearly black, slightly purple
],
yAxis: {
min: 0,
title: {
style: {
color: '#6D869F',
fontSize: '12px',
fontWeight: 'normal'
}
},
stackLabels: {
enabled: false
}
},
xAxis: {
type: 'datetime',
title: {
text: $filter('i18n')('_EventTimeLabel_'),
style: {
color: '#6D869F',
fontSize: '12px',
fontWeight: 'normal'
}
},
labels: {
rotation: -45,
align: 'right',
style: {
fontSize: '10px',
fontWeight: 'normal'
},
formatter: function() {
return Highcharts.dateFormat('%H:%M:%S', this.value);
}
},
events: {
afterSetExtremes: function(event) {
reloadLegend();
}
}//event ends
},
legend: {
title: {
text: $scope.criteria.eventfieldName
},
layout: 'vertical',
align: 'right',
x: 0,
y: 0,
verticalAlign: 'top',
floating: false,
backgroundColor: 'white',
borderColor: '#CCC',
borderWidth: 1,
shadow: false,
itemStyle: {
//cursor: 'pointer',
fontSize: '11px'
},
labelFormatter: function() {
// this function populates the legend with a total value over the points
// this makes sense for count, but you can't just add up eps per interval to get a total
// it should probably be an average
// Figure 6 intervals with sev 0 at 1 eps, it would total 6 eps, if divided by 6 intervals = 1
var i, len, total = 0, intervals = 0;
if (this.points) {
// during zoom and on updates
len = this.points.length;
for (i = 0; i < len; i++) {
// limit the data points considered viewable in zoom - not accurate
if (this.points[i].x > this.xAxis.min && this.points[i].x < this.xAxis.max) {
total += this.points[i].y;
intervals++;
}
}
debug.log('labelFormatter points',this.name,total,intervals);
} else {
// seems like only during initial load
len = this.yData.length;
for (i = 0; i < len; i++) {
total += this.yData[i];
intervals++;
}
debug.log('labelFormatter yData',this.name,total,intervals);
}
var precision = 0;
if ($scope.modalData.countType === 'Event Count per Second') {
if (intervals < 1) {
//ensure no divide by zero
intervals = 1;
}
total = total/intervals;
precision = Math.floor(Math.log($scope.displayIntervalTime * intervals)/Math.log(10))-2;
}
var nameLabel = this.name;
if (nameLabel === highCardinalitySelector) {
nameLabel = otherLabel;
}
return truncateLegend(nameLabel,16)+'(' + total.toFixed(precision) + ')';
},
itemMarginTop: 2,
enabled: $scope.legendEnabled
},
tooltip: {
formatter: function() {
var content;
content = '<strong>'+ $filter('i18n')('_EventTimeLabel_') +':</strong> ' + Highcharts.dateFormat('%H:%M:%S', this.x) + '<br/>';
var nameLabel = this.series.name;
if (nameLabel === highCardinalitySelector) {
nameLabel = otherLabel;
}
content += '<strong>' + $scope.criteria.eventfieldName + ':</strong> ' + nameLabel + '<br/><strong>' + eventCountTypeLabel + ':</strong> ' + this.y.toFixed(decimals) + '<br/>';
if ($scope.modalData.chartType == 'Stacked Bar 2D') {
content += '<strong>'+ $filter('i18n')('_TotalLabel_') +':</strong> ' + this.point.stackTotal.toFixed(decimals) + '<br/>';
}
return content;
},
style: {
color: '#333',
fontSize: '11px',
padding: '8px'
},
borderColor: '#CCC',
followPointer: true
},
series: series,
title: '',
exporting: {
enabled: false
},
credits: {
enabled: false
},
plotOptions: {
series: {
cursor: 'pointer',
point: {
events: {
click: function() {
var searchStr = '(' + $scope.criteria.filter + ')';
// Add on the tenant filter if selected for view by default tenant
if($scope.activeview.tenant) {
searchStr += ' AND (rv39:"' + $filter('escChars')($scope.activeview.tenant) +'")';
}
if ($scope.legendEnabled) {
// the null entry has been selected
if(this.series.name == nullString) {
searchStr += ' AND NOT (notnull:' + $scope.criteria.eventfield + ')';
} else if(this.series.name != highCardinalitySelector) {
// a non-null entry has been selected
searchStr += ' AND (' + $scope.criteria.eventfield + ':"' + $filter('escChars')(this.series.name) + '")';
} else {
//the other entry '*' has been selected
var excludeStr = '';
var hasNullMember = false;
for(i=0;i<series.length;i++) {
if(series[i].name == nullString)
{
hasNullMember = true;
} else if (series[i].name != highCardinalitySelector) {
excludeStr += $scope.criteria.eventfield + ':"' + $filter('escChars')(series[i].name) + '" ';
}
}
// exclude the ones we know and the null ones if they exist
searchStr += ' AND NOT (' + excludeStr + ')';
if (hasNullMember) {
searchStr += ' AND notnull:' + $scope.criteria.eventfield;
}
}
}
debug.log(searchStr);
$scope.launchSearch(searchStr, this.x.toString(), (this.x + $scope.displayIntervalTime).toString());
}
}
}
}
}
};
Hovering Part:
var redrawChart = function() {
console.log("Redraw function working");
var chart = $element.find('.highcharts').highcharts(); //this could be better
if (chart) {
chart.redraw();
legend=chart.legend;
for (var i = 0, len = legend.allItems.length; i < len; i++) {
(function(i) {
var item = legend.allItems[i].legendItem;
item.on('mouseover', function (e) {
//show custom tooltip here
console.log("mouseover-" + chart.series[i].name);
chart.tooltip.refresh(chart.series[i].data[i]);
//$element(".tooltip[data-series='" + chart.series[i].name + "']"+"saloni").css({left:event.clientX, top:event.clientY}).show();
// chart.tooltip.refresh("its working");
}).on('mouseout', function (e) {
//hide tooltip
console.log("mouseout" + chart.series[i].name);
// chart.tooltip.hide();
});
})(i);
}//for loop
}
debug.log('chart redraw:', chart?'yes':'no');
};
So the hovering is working as i wanted it to be. I have managed to display it in the console. But the tricky part is to display it in the tooltip form. How do i generate the tooltip box such that it is displayed next to the legend?
Upvotes: 0
Views: 1991
Reputation: 4769
A simpler solution is already on SO , See code below and refer existing fiddle at this fiddle
events: {
load: function () {
var chart = this,
legend = chart.legend;
for (var i = 0, len = legend.allItems.length; i < len; i++) {
(function(i) {
var item = legend.allItems[i].legendItem;
item.on('mouseover', function (e) {
//show custom tooltip here
console.log("mouseover" + i);
}).on('mouseout', function (e) {
//hide tooltip
console.log("mouseout" + i);
});
})(i);
}
}
}
Upvotes: 1