D3-Dragging


Check out this weirdness that’s part of handling d3 dragging/event handling:

var drag = d3.behavior.drag()
.on("drag", function(d,i) {
    d.x += d3.event.dx
    d.y += d3.event.dy
    d3.select(this).attr("transform", function(d,i){
        return "translate(" + [ d.x,d.y ] + ")"
    })

});
    
var face = d3.select("#charts")
  .append("svg:g")
  .data([ {"x":x, "y":y} ])
  .call(drag);

That last line doesn’t seem to make much sense, does it? What exactly are we invoking when we say .call(drag)? By standard javascript syntax, it seems like .select() or .append() is returning a function, which we’re then invoking, with our drag variable as the context. Huh???

As it turns out, d3 overwrites the call function with their own:

d3_selectionPrototype.call = function(callback) {
  var args = d3_array(arguments);
  callback.apply(args[0] = this, args);
  return this;
};

So when we invoke selection.call(drag), it’s actually invoking the above function, not the JS default, and passing drag as a callack function, not as the context. Our custom function (drag) is then run on the selection, with an event handler for the event drag. Confusing, but cool.