Search code examples
d3.jsbrush

How to prevent d3 brush events from firing after calling brush.move


I am displaying several identical charts (showing different datasets) side-by-side. Upon brushing on one chart, the brush should be replicated on all others.

Currently, I do this by calling brush.move on a selection of all charts excluding the currently brushed chart, as soon as someone brushes on a chart. This happens in a brush-type eventListener.

However, this brush.move triggers the brush-type event attached to the brush, leading to an error (or, more generally, an infinite loop).

How can I prevent this?


Solution

  • You can use the d3.event object to check what caused the update of the brush. From the API docs on brush events:

    Brush Events

    When a brush event listener is invoked, d3.event is set to the current brush event. The event object exposes several fields:

    • sourceEvent - the underlying input event, such as mousemove or touchmove.

    If your brush is modified programtically, i.e. by calling brush.move(), the d3.event.sourceEvent property will be null, because no input event caused this update. In your event handler you can check this property to skip execution for programmatic changes:

    if (!d3.event.sourceEvent) return;
    

    The same technique is employed by Mike Bostock in his Brush Snapping Block. While handling the actual input event the brush is modified again to snap to the nearest value, which, obviously, should not trigger another run of the event handler.