Jason
Jason

Reputation: 11363

D3 events - How to allow button click in d3 element?

I have a SVG rendering of all the counties in the US. Each path has four events bound to it:

click : opens up tooltip graphic with three buttons
dblclick : executes zoom effect
mouseover : shows tooltip with county/state data, changes fill
mouseout : returns fill to original

My issue is that I want to differentiate between a click event for the map which opens up the tooltip with buttons, and the buttons inside that tooltip.

I create the tooltip via

thisObj._tooltip = d3.select("body")
  .append("div")
  .attr("class", "tooltip")
  .style("opacity", 0);

and the map is created via

d3.json("/static/js/json/us-counties.json", function(json){

  thisObj._svg.selectAll("path")
    .data(json.features)
    .enter().append("path")
    .attr("d", thisObj._path)
    .attr("class", "states")
    .attr("id", function(d){
      return d.id;
    })
    .style("fill", "gray")
    .style("stroke", "black")
    .style("stroke-width", "0.5px")
    .on("click", mapClick)
    .on("dblclick", mapZoom)
    .on("mouseover", mapMouseOver)
    .on("mouseout", mapMouseOut);
});

My mapClick handler is

var mapClick = function(d, i){

    if (thisObj._tooltipOpen){

        if ($(".button").is(":checked")){

            console.log($(this).attr("id") + " was clicked");

        } else {

            console.log("Close tooltip click recorded");
            thisObj._tooltip.transition()
                .duration(500)
                .style("opacity", 0);

            thisObj._tooltipOpen = false;

            mapMouseOut(d);
        }

    } else {
        console.log("Open tooltip click recorded");

        //tooltip template in html, want to handle a button click on these buttons
        var template = "<div id = 'tooltip_template'>" + 
            "<div class = 'county_data'>" + d.name + ", " + d.properties.StateCode + "</div>" +
            "<button id = 'add_prospective_market' class = 'button'>Prospective Market</button>" +
            "<button id = 'add_market' class = 'button'>Market County</button>" +
            "<button id = 'remove_market' class = 'button'>Remove Market</button></div>";

        thisObj._tooltip.html(template)
            .style("left", (d3.event.pageX) + "px")
            .style("top", (d3.event.pageY + "px"));

        $(".button").button();

        thisObj._tooltip.transition()
            .duration(1000)
            .style("opacity", .8);

        thisObj._tooltipOpen = true;
    }
}

I have a button handler instanciated via

$("#add_market").on("click", function(){
   console.log("Add Market button clicked");
}

but it is never activated, and the only logging I get is the tooltip open/close notifications. Given this code, how can I modify the click handler to differentiate between a button click and a non-button click?

Upvotes: 1

Views: 6023

Answers (2)

if the parent element has css property "pointer-events" with value "none" then it will block the mouse and touch events of the child elements and the solution for this is add the same property("pointer-events") with value "auto" to the child elements then child elements will trigger the events.

Upvotes: 1

reblace
reblace

Reputation: 4185

I'm guessing you are doing the

$("#add_market").on("click", function(){
   console.log("Add Market button clicked");
}

handler registration before that id exists and so the handler is not getting registered to anything. Since that's a jQuery selection, you won't get an error if it's empty, which is what will happen if the element with id "add_market" doesn't exist yet.

Try putting a logging statement before/after the block of code that registers the handler:

console.log("About to register the listener");
$("#add_market").on("click", function(){
   console.log("Add Market button clicked");
}
console.log("Done registering the listener");

and see if it's before/after the "Open tooltip click recorded" log message. Or, you can put a breakpoint on this line:

$("#add_market").on("click", function(){

and see if the "$("#add_market")" jQuery selection finds anything.

To fix it, you could register the listener in the template itself or you could stick the listener registration code after you create the tooltip and buttons.

Upvotes: 2

Related Questions