Splunk Search

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 using Simple XML with splunk js?

lyndac
Contributor

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

1 Solution

jeffland
SplunkTrust
SplunkTrust

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!

View solution in original post

jeffland
SplunkTrust
SplunkTrust

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!

michaelrosello
Path Finder

Hi. Where should I define the id=pie using search manager?

0 Karma

jeffland
SplunkTrust
SplunkTrust

You assign it in Simple XML like this:

...
<chart>
  <search id="pie">
    <query>...
0 Karma

lyndac
Contributor

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

0 Karma

jeffland
SplunkTrust
SplunkTrust

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...

0 Karma

lyndac
Contributor

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() {
...
});
0 Karma

jeffland
SplunkTrust
SplunkTrust

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
0 Karma

lyndac
Contributor

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!

0 Karma

splunk24
Path Finder

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 ?

0 Karma

mleProso
New Member

Hi,
What do you mean by [id^highcharts] ? you replace it by something ?
Thanks

0 Karma
Get Updates on the Splunk Community!

.conf24 | Registration Open!

Hello, hello! I come bearing good news: Registration for .conf24 is now open!   conf is Splunk’s rad annual ...

Splunk is officially part of Cisco

Revolutionizing how our customers build resilience across their entire digital footprint.   Splunk ...

Splunk APM & RUM | Planned Maintenance March 26 - March 28, 2024

There will be planned maintenance for Splunk APM and RUM between March 26, 2024 and March 28, 2024 as ...