Event Streams

Event streams are the primary means of modeling user input to enable dynamic, interactive visualizations. Event streams capture a sequence of input events such as mouse click, touch movement, or signal updates. When events that match a stream definition occur, they cause any corresponding signal event handlers to evalute, potentially updating a signal value.

{
  "name": "signalName",
  "on": [
    {
      "events": <<event-stream-definition>>,
      "update": ...
    }
  ]
}

An event stream definition can be specified in multiple ways:

Supported Event Types

The supported DOM event types for mark items are:

Other event types supported by the browser (e.g., resize events on the window object) may be captured from DOM elements on the same web page as the Vega visualization. The list above applies only to mark items contained within the Vega view’s scenegraph.

Event Stream Objects

A basic event stream consists of an event source and type:

Property Type Description
source String The input event source. This defaults to "view" to monitor events from the current Vega view component. Other legal values are "scope" (indicating only events originating within the group in which the event stream is defined), "window" for the browser window object, or a CSS selector string indicating external DOM elements.
type String Required. The event type to monitor (e.g., "click", "keydown"). For more, see the supported event types list.

Any event stream object may also include the following properties for filtering or modifying an event stream:

Property Type Description
between EventStream[ ] A two-element array of event stream objects, indicating sentinel starting and ending events. Only events that occur between these two events will be captured.
consume Boolean A boolean flag (default false) indicating if this stream should consume the event by invoking event.preventDefault(). To control event consumption more globally, see the event handling configuration.
filter Expression | Expression[ ] One or more filter expressions, each of which must evaluate to a truthy value in order for the event to be captured. These expressions may not reference signal values, only event properties.
debounce Number The minimum time to wait between event occurrence and processing. If a new event arrives during a debouncing window, the debounce timer will restart and only the new event will be captured.
markname String The unique name of a mark set for which to monitor input events. Events originating from other marks will be ignored.
marktype String The type or marks (arc, rect, etc.) to monitor for input events. Events originating from other mark types will be ignored.
throttle Number The minimum time in milliseconds between captured events (default 0). New events that arrive within the throttling window will be ignored.

For example, to capture click events on rect marks:

{"type": "click", "marktype": "rect"}

To capture resize events on the browser window:

{"source": "window", "type": "resize"}

To capture mousedown events on image marks if the control key is pressed and the left mouse button is used:

{
  "type": "mousedown",
  "marktype": "image",
  "filter": ["event.ctrlKey", "event.button === 0"]
}

To capture mousemove events that occur between mousedown and mouseup events:

{
  "type": "mousemove",
  "between": [
    {"type": "mousedown"},
    {"type": "mouseup"}
  ]
}

Derived Event Streams

In addition to basic streams, an event stream object can serve as input for a derived event stream.

Property Type Description
stream EventStream Required. An input event stream to modify with additional parameters.

For example:

{
  "stream": {"marktype": "rect", "type": "click"},
  "filter": "event.shiftKey",
  "debounce": 500
}

Merged Event Streams

A set of event streams can also be merged together.

Property Type Description
merge EventStream[ ] Required. An array of event streams to merge into a single stream.

For example:

{
  "merge": [
    {"marktype": "symbol", "type": "mousedown"},
    {"marktype": "symbol", "type": "touchstart"}
  ]
}

Event Stream Selectors

An event selector is a convenient shorthand, inspired by CSS selectors, for defining an event stream of interest.

Basic Selectors

A basic selector specifies an event type, an optional event source, and optional filter expressions.

The general form of a basic selector (using a regexp-style syntax) is:

(source:)?type([filter])*({throttle(,debounce)?})?

The source property supports the following options:

  • If undefined, all marks and the view itself will be monitored, equivalent to an event object with source property "view".
  • A valid mark type. For example, arc, image, or rect.
  • A mark name preprended by @. For example, @cell. Matching items must have the name property specified in their mark definition.
  • The string *, indicating any mark type, but not the view component itself.
  • The string window, indicating the browser window object.
  • If none of the above, source will be interpreted as a CSS selector string indicating DOM elements to monitor.

The type property must be a supported DOM event type. To indicate that an event should be consumed (i.e., that event.preventDefault() is called), include an exclamation point (!) at the end of the event type.

One or more filter expressions can be included as bracket-delimited ([]) expressions. If multiple filters are provided, they will be combined into a single filter via boolean “and”. Filter expressions may not make reference to any signals, only to the event object itself.

To throttle or debounce an event stream, add timing information in milliseconds within curly braces ({}) at the end of a selector.

Here are some examples of basic event selectors:

mousedown           // capture all mousedown events, regardless of source
*:mousedown         // mousedown events on marks, but not the view itself
rect:mousedown      // mousedown events on any rect marks
@foo:mousedown      // mousedown events on marks named 'foo'
symbol:mousedown!   // capture and consume mousedown events on symbol marks
window:mousemove    // capture mousemove events from the browser window
mousemove{100}      // throttle the stream by 100 ms
mousemove{100, 200} // also debounce the stream by 200 ms
mousemove{0, 200}   // debounce by 200 ms, but do not throttle
mousemove[event.buttons] // mousemove events with any mouse button pressed
click[event.shiftKey]    // click events with the shift key pressed

Merge Selectors

To merge event streams, simply use multiple selectors separated by commas.

selector1, selector2, ...

For example, to capture both mousedown and touchstart events on path marks:

path:mousedown, path:touchstart

Between Filters

To capture events that occur between two other events, use a bracket notation.

[startSelector, stopSelector] > selector

Between filters are particularly useful to capture streams of drag events:

[rect:mousedown, window:mouseup] > window:mousemove

This example initiates a drag upon mousedown on a rect mark, then tracks the drag using events on the browser window. Using the window as the event source lets the drag continue if the mouse pointer leaves the initial rect mark or the view component.

Signal References

Event stream definitions can also be simple signal references:

"on": [
  {
    "events": {"signal": "foo"},
    "update": "..."
  }
]

In this case, an update will be triggered whenever the signal foo changes. Signal references can be combined with event stream objects by providing an array to the events property:

"on": [
  {
    "events": [{"signal": "foo"}, {"type": "click", "marktype": "rect"}],
    "update": "..."
  }
]