Fine-grained event handling with D3 brushes

http://stackoverflow.com/questions/14697495/fine-grained-event-handling-with-d3-brushes

CSS

svg { cursor: pointer; }

JavaScript

var target, locked;

var svg = d3.select("body").append("svg")
    .attr({width: 200, height: 200});
var rect = svg.append("rect")
    .attr({width: 200, height: 200});
var circle = svg.append("circle")
    .style("fill", "white")
    .attr({cx: 100, cy: 100, r: 40})

var results = {},
    types = ["mousemove", "mouseout", "mousedown"];
for ( var i in types ) {
    results[types[i]] = d3.select("body").append("p").text("Last " + types[i] + ": ").append("span").text("None");
}
    
svg
    .on("mousemove", function() { 
        var target = d3.event.target || d3.event.srcElement;
        results.mousemove.text(target === rect.node() ? "rect" : circle.node() ? "circle" : "svg"); 
        if ( target === rect.node() ) {
            rect.style("fill", "green");
        } else {
            d3.select(target).style("fill", "red"); 
        }
        if ( locked === circle.node() ) {
            var mouse = d3.mouse(svg.node());
            circle.attr({cx: mouse[0], cy: mouse[1]});
        }
    })
    .on("mouseout", function() { 
        var target = d3.event.target || d3.event.srcElement;
        results.mouseout.text(target === rect.node() ? "rect" : circle.node() ? "circle" : "svg"); 
        if ( target === rect.node() ) {
            rect.style("fill", "black");
        } else {
            d3.select(target).style("fill", "white");
        }
        locked = undefined;
    })
    .on("mouseup", function() { locked = undefined; })
    .on("mousedown", function() { 
        locked = d3.event.target || d3.event.srcElement;
        results.mousedown.text(locked === rect.node() ? "rect" : circle.node() ? "circle" : "svg"); 
    } );