D3 Click + Drag Events

... working together in harmony. Unfortunately the extra variable is needed. This version uses data instead of a global variable.

by langdonx

HTML

<svg></svg>

JavaScript

var container,
    rect,
    dragBehavior;

container = d3.select('svg')
    .append('g');

rect = container.append('rect')
    .attr('width', 100)
    .attr('height', 100);

dragBehavior = d3.behavior.drag()
    .on('dragend', onDragStart)
    .on('drag', onDrag)
    .on('dragend', onDragEnd);

container
    .data([{ wasDragged: true }])
    .call(dragBehavior)
    .on('click', onClick);

function flashRect() {
    rect.attr('fill', 'red').transition().attr('fill', 'black');
}

function onDragStart() {
    console.log('onDragStart');
}

function onDrag(d) {
    console.log('onDrag');

    var x = (d3.event.sourceEvent.pageX - 50);

    container.attr('transform', 'translate(' + x + ')');

    d.wasDragged = true;
}

function onDragEnd(d) {
    if (d.wasDragged === true) {
        console.log('onDragEnd');

        // always do this on drag end
        flashRect();
    }
    
    d.wasDragged = false;
}

function onClick(d) {
    if (d3.event.defaultPrevented === false) {
        console.log('onClick');

        // only do this on click if we didn't just finish dragging
        flashRect();
    }
}