Is it possible to show a custom tooltip whenever a user hovers over a slice of a pie chart, or column in a bar chart? I have been looking at this blog about adding custom tooltip to a table, but I cannot see how to apply that to a chart. The ChartView in splunkjs does not have similar methods as the TableView for adding a renderer.
I have data that contains a code (userid) and the name associated with the code (among other things). I am creating a pie chart to display counts by code. However, when the user hovers over the pie-slice, I want to display the code, the name and the counts/percentage in the tooltip. Customers want to count by code, but be able to see what the code maps to in the tooltip. My search looks like this:
index=yc | stats sum(counts) as counts values(fullName) as fullName by userid| sort -counts | head 10
In statistics view, this gives me:
userid count fullName
jdoe 35424 John Doe
bsmith 4342 Bob Smith
mjones 4212 Mary Jones
jdoeadeer 1234 John Doe
...
So if the user hovers over the largest pie slice I'd like the tooltip to display
userid: jdoe
fullName: John Doe
counts: 35424
counts%: 78.2
This is not yet a complete solution, but it should get you going in the right direction. I had some code for this for Splunk 6.2.5, but since then, some things have changed on the dashboards regarding DOM selection... See how far you want to take it from here.
The idea is to fetch the required field, in your case fullName, from the search manager and add a new row to the tooltip containing that info. You need to add some javascript to your dashboard:
require([
'underscore',
'jquery',
'splunkjs/mvc',
'splunkjs/mvc/searchmanager',
'splunkjs/mvc/simplexml/ready!'
], function (_, $, mvc, SearchManager) {
// get the search manager
var search = splunkjs.mvc.Components.getInstance("pie");
// get its results
var myResults = search.data("results");
var resultArray = [];
myResults.on("data", function() {
resultArray = myResults.data().rows;
});
// add info when opening tooltip (delegate event listening)
$("#chart").on("mouseover", "#highcharts-0 > svg > g.highcharts-series-group > g.highcharts-series.highcharts-tracker", function(){
// get title to compare which series of the chart we're looking at
var title = $("table.highcharts-tooltip > tbody > tr:nth-child(1) > td:nth-child(2)").text();
// select right row
var fullName = "";
for (var i = 0; i < resultArray.length; i++){
if (title == resultArray[i][0]){
fullName = resultArray[i][2];
break;
}
}
// add (or change) the date shown in the tooltip
var text = '<tr class="unique"><td style="text-align: left; color: #cccccc; max-width: 663.9180019451253px;">Full Name</td><td style="text-align: right; color: #ffffff; max-width: 572.0819980548747px;">';
if ($("table.highcharts-tooltip > tbody").find("tr.unique").length == 0) {
$("table.highcharts-tooltip > tbody").append(text+fullName+'</td></tr>');
} else {
$("table.highcharts-tooltip > tbody > tr.unique").replaceWith(text+fullName+'</td></tr>');
}
// re-calculate the size of the black box behind the text
var height = $("table.highcharts-tooltip").height();
var width = $("table.highcharts-tooltip").width();
var node = $("g.highcharts-tooltip")[0];
var bbox = node.getBBox();
var w = width / bbox.width;
var h = height / bbox.height;
var scalex = w*1.15, scaley = h*1.15;
var scalestr = scalex + ',' + scaley;
var regex = /(\w+\(\d+\,\d+\))/; // one way to make sure we only add scale once
node.setAttribute('transform',regex.exec(node.getAttribute("transform"))[0]+'scale('+scalestr+')');
});
});
This assumes your search manager has an id "pie", and your chart has an id "chart". This particular example works for the first chart on a dashboard, you will have to adjust the selectors accordingly.
Feel free to come back with any questions!
This is not yet a complete solution, but it should get you going in the right direction. I had some code for this for Splunk 6.2.5, but since then, some things have changed on the dashboards regarding DOM selection... See how far you want to take it from here.
The idea is to fetch the required field, in your case fullName, from the search manager and add a new row to the tooltip containing that info. You need to add some javascript to your dashboard:
require([
'underscore',
'jquery',
'splunkjs/mvc',
'splunkjs/mvc/searchmanager',
'splunkjs/mvc/simplexml/ready!'
], function (_, $, mvc, SearchManager) {
// get the search manager
var search = splunkjs.mvc.Components.getInstance("pie");
// get its results
var myResults = search.data("results");
var resultArray = [];
myResults.on("data", function() {
resultArray = myResults.data().rows;
});
// add info when opening tooltip (delegate event listening)
$("#chart").on("mouseover", "#highcharts-0 > svg > g.highcharts-series-group > g.highcharts-series.highcharts-tracker", function(){
// get title to compare which series of the chart we're looking at
var title = $("table.highcharts-tooltip > tbody > tr:nth-child(1) > td:nth-child(2)").text();
// select right row
var fullName = "";
for (var i = 0; i < resultArray.length; i++){
if (title == resultArray[i][0]){
fullName = resultArray[i][2];
break;
}
}
// add (or change) the date shown in the tooltip
var text = '<tr class="unique"><td style="text-align: left; color: #cccccc; max-width: 663.9180019451253px;">Full Name</td><td style="text-align: right; color: #ffffff; max-width: 572.0819980548747px;">';
if ($("table.highcharts-tooltip > tbody").find("tr.unique").length == 0) {
$("table.highcharts-tooltip > tbody").append(text+fullName+'</td></tr>');
} else {
$("table.highcharts-tooltip > tbody > tr.unique").replaceWith(text+fullName+'</td></tr>');
}
// re-calculate the size of the black box behind the text
var height = $("table.highcharts-tooltip").height();
var width = $("table.highcharts-tooltip").width();
var node = $("g.highcharts-tooltip")[0];
var bbox = node.getBBox();
var w = width / bbox.width;
var h = height / bbox.height;
var scalex = w*1.15, scaley = h*1.15;
var scalestr = scalex + ',' + scaley;
var regex = /(\w+\(\d+\,\d+\))/; // one way to make sure we only add scale once
node.setAttribute('transform',regex.exec(node.getAttribute("transform"))[0]+'scale('+scalestr+')');
});
});
This assumes your search manager has an id "pie", and your chart has an id "chart". This particular example works for the first chart on a dashboard, you will have to adjust the selectors accordingly.
Feel free to come back with any questions!
Hi. Where should I define the id=pie using search manager?
You assign it in Simple XML like this:
...
<chart>
<search id="pie">
<query>...
I implemented this javascript and it worked great until the brower cache got cleared!
On line 16, you use highcharts-0 since you are working with the first chart. I determined that chart I want to work with is #highcharts-24. That worked great yesterday. But today, the name is highcharts-22 and it changes sometimes when I do a ctrl-refresh. It has been highcharts-22, highcharts-18, highcharts-16. Is there a way to make that name static so I can rely on it in the javascript? Or some other way around this issue?
Thanks for your help
You could give your chart an id and go from there.
I know it's a mess when you start to fiddle with this stuff...
The chart does have an id: in simple xml, i set chart id="src_pie"
My javascript looks like this:
var srcpie=splunkjs.mvc.Components.getInstance("src_pie");
var searchMgr = srcpie.settings.get("managerid");
var search= splunkjs.mvc.Components.get(searchMgr);
var myResults = search.data("results");
var resultArray = [];
myResults.on("data", function() {
resultArray=myResults.data().rows;
});
$("#src_pie").on("mouseover", "#highcharts-24.highcharts-container > svg > g.highcharts-series-group > g.highcharts-series.highcharts-tracker", function() {
...
});
I meant, take a path from that id instead of #highcharts-number-foo
, where foo can be arbitrary. Something like this should do it:
#src_pie > div.panel-body > div.splunk-view > div > div.chart > div > div > svg > g.highcharts-series-group > g.highcharts-series.highcharts-tracker
I got it to work by using:
$("#src_pie").on("mouseover", "[id^highcharts].highcharts-container > svg > g.highcharts-series-group > g.highcharts-series.highcharts-tracker", function() {
...
})
Thanks for all your help!
kindly explain what do you mean by [id^highcharts] this code . and can we use .".highcharts-container > svg > g.highcharts-series-group > g.highcharts-series.highcharts-tracker"
this directly ?
Hi,
What do you mean by [id^highcharts] ? you replace it by something ?
Thanks