Search code examples
javascriptd3.jssvgdom-eventsevent-bubbling

Remove event listener with d3js not working


I have an SVG structure where there are some shapes inside. I want to fire an event when a shape is clicked and another one when is clicked over the SVG. The problem is the SVG event is always fired.

In order to prevent this I'm disabling event bubbling from the shape. Also I've tried to disable the event with d3 but seems to not work. Also tried to disable event with the native Javascript code.

An example of the super simple code is:

SVG structure

<svg id="canvas" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <g>
        <circle class="shape" r="10" cx="10" cy="10">
    </g>
</svg>

Javascript code

d3.select('#canvas').on('click',svgClickEvents);

d3.selectAll('.item')
    .on("mouseover",mouseoverItem)
    .on('mouseleave',mouseleaveItem);

//click
d3.selectAll('.item',function(){

    //when an item is clicked, svgClickEvents must not be fired   
    d3.select('#canvas').on('click',null);  //this should remove the event listener
    //also tried with getElementById('canvas').removeEventListener('click',clickEvents,false);

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

I know event is not being disabled because I'm getting the onsole.log() text alert from clickEvents function.


Solution

  • In this case, the syntax:

    d3.selectAll('.classname', function() { ... });
    

    does not work in d3.js. Instead you should use something like:

    d3.selectAll('.classname').each(function() { ... });
    

    So in your code above, this should work:

    d3.selectAll('.item')
      .each(function(){
    
        //when an item is clicked, svgClickEvents must not be fired   
        d3.select('#canvas').on('click', null);  //this should remove the event listener
    
        d3.select(this).on("click",function() {
                d3.event.stopPropagation(); 
                console.log("click circle");
            });
    });