Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I add a click event to show a tooltip in an NVD3 Pie Chart?

There isn't much documentation on nvd3. In the following plunkr, the tooltip displays on a hover event. That's native to the framework. After reading other stackoverflow questions, one would use someting like the following to display the tooltip via a click versus the hover:

d3.selectAll('.nv-slice')
  .on('click', function(d) {
    console.log(d.data.label);
  }); 

How can I apply a click event to trigger the tooltip to display? http://plnkr.co/edit/QYuol3Q10xsA3pziiWGl?p=preview

like image 878
Kode_12 Avatar asked Jan 06 '23 19:01

Kode_12


2 Answers

So, first of all you have to set a css rule, because the tooltip element does not exist until the first mouse over.

Add to your style.css

.nvtooltip {
    display: none!important;
}

Then you need a callback function after the graph was created, so add the onready attribute to your nvd3 element like this

<nvd3 options="options" data="data" on-ready="callback"></nvd3>

And now you can implement your hack to open and close the tooltip, so add the callback function under your data object inside your app.js

$scope.callback = function(scope, element){
  // Add a click event
  d3.selectAll('.nv-slice').on('click', function(){
    d3.selectAll('.nvtooltip').each(function(){
        this.style.setProperty('display', 'block', 'important');
    });
  });
  // Clear tooltip on mouseout
  d3.selectAll('.nv-slice').each(function(){
    this.addEventListener('mouseout', function(){
        d3.selectAll('.nvtooltip').each(function(){
            this.style.setProperty('display', 'none', 'important');
        });
    }, false);
  });
  // we use foreach and event listener because the on('mouseout')
  // was overidding some other function
};

Here you are: http://plnkr.co/edit/7WkFK2LqzDyDmnIt2xlf?p=preview

Edit How to, for beginers.

First I searched the web for any doc of the library. As the author of the question mention, the documentation is not so good. So, I found out that i could turn of the tooltips with css by finding the tooltip element using the build in web tools of the browser.

After that I checked in the javascript console, how I could affect the display of the tooltip using the d3.selectAll. It was realy easy to just enable it on click and maybe disable it on mouseout of a pie element.

The last problem I had to solve, was when the code had to be fired, the pie graph (the elements) must be already created before the code run. So i searched the documentation for events, onload events mostly.

Then I came accross the on-ready="callback" attribute and I just inserted the code on the callback function.

Code Explanation Every slice element has the classname "nv-slice" so by using d3.selectAll('.nv-slice') we get a list of the slice elements (this looks like jQuery not pure Javascript) and then we attach an event on them using the .on(eventname, callbackFunction)

As we want when we click each one of them, to show the tooltip, our event name is click and on the callback function we implement the code that shows the tooltip.

On the callback function : Every tooltip has the classname nvtooltip so we sellect them using the command d3.selectAll('.nvtooltip') which is a list. In our case we have only one tooltip, but just to be sure we use it as a list of tooltips. So for each tooltip .each(callbackFunction) we want to change the css to make the tooltip visible. Normaly when we get a callback from an element event, the this variable points to the element. So

function(){
    // Access the element style
    this.style.setProperty('display', 'block', 'important');
    /* And overide the display property that the style.css gave it
       as the style css has a "important" we also have to include one
       otherwise we would fail to overide the rule*/
}

The onclick is now is working, but maybe we need to close the tooltip once we leave the slice we clicked...

So an easy solution is to hide the tooltip when the cursor leave the slice.

To do this, we again get all the slices using the d3.selectAll('.nv-slice') and now normaly, we would use the on('mouseout', function(){...}) command to get a callback from the event.

But for some reason this has some visual problems that suggest us that maybe an other function was listening there and we overide it (maybe a bug).

So in order not to overide it we can use addEventListener function which creates a new event callback.

To do so, we have to get the element in pure javascript an not in some jQuery like lib. For that reason, we use the each function which returns us the element inside the this variable.

We then attach on the element a mouseout event using this.addEventListener('mouseout', function(){...}, false); and again exactly like before we implement inside the callback a function to hide all the tooltips.

like image 64
GramThanos Avatar answered Jan 29 '23 04:01

GramThanos


On mouse enter hide the tooltip.Then when we click on individual pie section then show tooltip.

Check out this Plunk:

http://plnkr.co/edit/Bx1aNqJ7Y2Kd42PKqFaG?p=preview

   function HideTooltip() {
        $(".nvtooltip").hide();
    }

    function ShowTooltip() {
        $(".nvtooltip").show();
    }

    d3.select("#svgElement").selectAll(".nv-slice").on("mouseenter", HideTooltip)
        .on("mouseleave", HideTooltip)
        .on("click", ShowTooltip);
like image 28
Varatharaj Avatar answered Jan 29 '23 04:01

Varatharaj