Attaching 'onclick' event to D3 chart background

JavascriptJqueryd3.js

Javascript Problem Overview


I have a D3 histogram chart, onto which I have attached an 'onclick' event to the bars:

...
var bar = svg.selectAll(".bar")
        .data(data)
        .enter().append("g")
        .attr("class", "bar")
        .attr("transform", function(d) { return "translate(" + x(d.x) + "," + y(d.y) + ")"; })
        .on('mouseover', tip.show)
        .on('mouseout', tip.hide)
        .on('click', function(d,i){ //do stuff  });
...

This works exactly as expected. I would also like to attach an 'onclick' event to the background of the chart (ie. everywhere in the chart that is not a bar), but I am having trouble with this. I have tried attaching the event in a couple ways, but in every case, this new event seems to override my bar-click:

Some attempts:

$("svg:not('.bar')").on("click", function(){ //do stuff });

$("g:not('.bar')").on("click", function(){ //do stuff });

var svg = d3.select("#histogram_block").append("svg")
        .attr("width", width + margin.left + margin.right)
        .attr("height", height + margin.top + margin.bottom)
        .append("g")
        .attr("transform", "translate(" + margin.left + "," + margin.top + ")")
        .on("click", function(d,i){
            if (d) { //do stuff}
            else { //do stuff }
        };

I am assuming there is a way to add the event handler to the SVG object when it is initialized, but I don't know the correct way to go about this.

Javascript Solutions


Solution 1 - Javascript

The event isn't actually overridden, but both are triggered -- the onclick handler for the SVG and for the bar. To prevent this, use the .stopPropagation() method (see the documentation). The code looks like this:

rect.on("click", function() {
  console.log("rect");
  d3.event.stopPropagation();
});

Complete example here. Compare with the behaviour with stopping the propagation of the event here.

Solution 2 - Javascript

In this example (line 246: http://tributary.io/inlet/8361294) I append a new rect with width & height equal to the total chart area, then attach my mouse (or click) events.

svg.append("rect")
        .attr({"class": "overlay" , "width": width , "height": height})
        .on({
          "mouseover": function() { /* do stuff */ },
          "mouseout":  function() { /* do stuff */ }, 
          "click":  function() { /* do stuff */ }, 
        });

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionwoemlerView Question on Stackoverflow
Solution 1 - JavascriptLars KotthoffView Answer on Stackoverflow
Solution 2 - JavascriptDeBraidView Answer on Stackoverflow