CanvasXpress Automatic Broadcasting

Seamlessly connect and update multiple visualizations on a dashboard without extra code.

Introduction to Automatic Broadcasting

The CanvasXpress platform includes a gold-standard automatic broadcast mechanism that offers intuitive communication of events to all web page visualizations. This automated data decision-making process requires no extra coding, simplifying the creation of interactive dashboards.

When you click a data point in one visualization, all other visualizations on the page are automatically updated to reflect that selection, highlighting the corresponding data points. This seamless feature is available by default and can be customized to suit your needs.

Broadcasting is not limited to clicks. Filtering in one visualization also propagates to every other visualization on the page, and named views of the whole page can be saved and restored across all graphs at once. These capabilities are covered in the sections below.

Interactive Dashboard

Below is a simple dashboard displaying the following sample dataset.

Name Weight Height Waist Hip Age Gender Excercise
Keith 65.6 174 71.5 93.5 21 Male Low
Nina 51.6 161 66.5 92.0 22 Female Moderate
Freddy 80.7 194 83.2 95.0 28 Male Moderate
Tracey 49.2 160 61.2 91.0 19 Female Moderate
Isabelle 55.2 173 66.5 90.3 32 Female Low
Penny 48.7 151 61.6 90.0 35 Female Intense

To see the corresponding data points, simply click any data point inside a graph. The selected data will be automatically highlighted on all other visualizations. This feature is available on CanvasXpress without any extra coding. Press 'ESC' to reset all graphs.

Height vs Weight
Total Records
Age
Exercise Frequency
Gender
Age Histogram
Measurements Heatmap
Data and Configuration

The JavaScript used to create the CanvasXpress visualization can be seen below. Take note that no additional configuration was needed to implement broadcasting. This shows how the automated CanvasXpress event broadcast works across dashboards.

// Dataset 1
var ds1 = {
  "y": {
    "vars": ["Keith", "Nina", "Freddy", "Tracey", "Isabelle", "Penny"],
    "smps": ["Height", "Weigth"],
    "data": [
      [174, 65.6],
      [161, 51.6],
      [194, 80.7],
      [160, 49.2],
      [173, 55.2],
      [151, 48.7]
    ]
  }
}
var cX1 = new CanvasXpress("canvasId1", ds1, {
  graphType: "Scatter2D",
  dataPointSizeScaleFactor: 2,
  xAxisTitle: "Height",
  yAxisTitle: "Weigth",
  theme: "CanvasXpress"
});

// Dataset 2 - one "Records" value per person; the meter counts them
var ds2 = {
  "y": {
    "vars": ["Records"],
    "smps": ["Keith", "Nina", "Freddy", "Tracey", "Isabelle", "Penny"],
    "data": [
      [1, 1, 1, 1, 1, 1]
    ]
  }
}
var cX2 = new CanvasXpress("canvasId2", ds2, {
  graphType: "Meter",
  meterType: "ring",
  meterProgress: true,
  summaryType: "count",
  meterCard: true,
  xAxis: ["Records"],
  title: "Total Records",
  theme: "CanvasXpress"
});

// Dataset 3
var ds3 = {
  "x": {
    "Gender": ["Male", "Female", "Male", "Female", "Female", "Female"]
  },
  "y": {
    "vars": ["Age"],
    "smps": ["Keith", "Nina", "Freddy", "Tracey", "Isabelle", "Penny"],
    "data": [
      [21, 22, 28, 19, 32, 35]
    ]
  }
}
var cX3 = new CanvasXpress("canvasId3", ds3, {
  graphType: "Bar",
  graphOrientation: "vertical",
  showLegend: false,
  theme: "CanvasXpress"
});

// Dataset 4
var ds4 = {
  "x": {
    "Gender": ["Male", "Female", "Male", "Female", "Female", "Female"],
    "Excercise": ["Low", "Moderate", "Moderate", "Moderate", "Low", "Intense"]
  },
  "y": {
    "vars": ["Age"],
    "smps": ["Keith", "Nina", "Freddy", "Tracey", "Isabelle", "Penny"],
    "data": [
      [21, 22, 28, 19, 32, 35]
    ]
  }
}
var cX4 = new CanvasXpress("canvasId4", ds4, {
  graphType: "Bar",
  treemapBorderWidth: 0,
  theme: "CanvasXpress"
}, false, false, [
  ["createTreemap", ["Excercise"]]
]);

// Dataset 5
var ds5 = {
  "x": {
    "Gender": ["Male", "Female", "Male", "Female", "Female", "Female"]
  },
  "y": {
    "vars": ["Age"],
    "smps": ["Keith", "Nina", "Freddy", "Tracey", "Isabelle", "Penny"],
    "data": [
      [21, 22, 28, 19, 32, 35]
    ]
  }
}
var cX5 = new CanvasXpress("canvasId5", ds5, {
  graphType: "Pie",
  showLegend: false,
  theme: "CanvasXpress"
}, false, false, [
  ["createPie", ["Gender"]]
]);

// Dataset 6
var ds6 = {
  "z": {
    "Gender": ["Male", "Female", "Male", "Female", "Female", "Female"],
    "Excercise": ["Low", "Moderate", "Moderate", "Moderate", "Low", "Intense"]
  },
  "y": {
    "vars": ["Keith", "Nina", "Freddy", "Tracey", "Isabelle", "Penny"],
    "smps": ["Age"],
    "data": [
      [21],
      [22],
      [28],
      [19],
      [32],
      [35]
    ]
  }
}
var cX6 = new CanvasXpress("canvasId6", ds6, {
  graphType: "Scatter2D",
  showHistogram: true,
  showLegend: false,
  histogramBins: 5,
  theme: "CanvasXpress"
}, false, false, [
  ["createHistogram", ["Age"]]
]);

// Dataset 7 - measurements per person shown as a heatmap
var ds7 = {
  "y": {
    "vars": ["Weight", "Height", "Waist", "Hip", "Age"],
    "smps": ["Keith", "Nina", "Freddy", "Tracey", "Isabelle", "Penny"],
    "data": [
      [65.6, 51.6, 80.7, 49.2, 55.2, 48.7],
      [174, 161, 194, 160, 173, 151],
      [71.5, 66.5, 83.2, 61.2, 66.5, 61.6],
      [93.5, 92, 95, 91, 90.3, 89.9],
      [21, 22, 28, 19, 32, 35]
    ]
  }
}
var cX7 = new CanvasXpress("canvasId7", ds7, {
  graphType: "Heatmap",
  autoExtend: true,
  variablesClustered: true,
  samplesClustered: true,
  theme: "CanvasXpress"
});

Data Point Selection

By default, selected data points are highlighted, and non-selected data points remain visible. Each visual can also be configured to 'ghost' the non-selected data points for better contrast.

See additional information about the selectionMode parameter on the broadcast page.

Broadcasting Scope

By default, broadcasting is active across all visualizations on a web page. However, you can limit the broadcasting mechanism to a specific group of visualizations by providing a group ID in the broadcastGroup parameter.

You can see an example of this limited-scope capability in the Legend broadcasting section at the end of this page.

Filter Broadcasting

Selections are not the only thing that coordinates. When you filter data in one visualization — through the Data Filters panel (the funnel icon) or a data table's column filters — every other visualization in the same broadcast group narrows to the same records automatically.

The broadcast resolves to the underlying data entities, not to a specific column, so filtering works across visualizations that arrange the same data differently — a field that is a variable in one chart and a sample annotation in another still coordinates correctly. Filtering by a category, a numeric range, or a date window all broadcast, and the coordination flows in every direction: a composite DOE dashboard drives the other graphs as readily as it follows them.

The other visualizations always reflect the origin's current selection: re-checking a value or clearing a filter releases it everywhere, and successive filters never accumulate. Press ESC to reset the filters across the page (or, when a saved state exists, to return to it — see below). Filter broadcasting is on by default; set the `broadcastFilter` parameter to `false` on a visualization to opt it out of driving its peers.

Page-Level Saved States

A coordinated page can be captured as a named state and restored later — across every visualization at once. Filter and arrange the page the way you want, open the Save state dialog, and check "Save across all graphs on the page". The state is stored on every visualization under one shared name, so it appears in — and restores from — each of their state lists.

Selecting a saved state from any single visualization restores the whole page to it; pressing ESC returns the page to the most recent saved state (or, when none is saved, clears the filters); and removing a global state with its × removes it from every visualization. The same capability is available programmatically:

// Save the current page across every CanvasXpress instance (optionally scoped
// to one broadcastGroup) under a shared name. Returns the number of graphs saved.
CanvasXpress.savePageState("My View");

// Restore that state on every instance that carries it. Returns the count applied.
CanvasXpress.applyPageState("My View");

// Remove the state from every instance. Returns the count removed.
CanvasXpress.deletePageState("My View");

// List the distinct page-level state names saved across the page.
CanvasXpress.getPageStates();          // -> ["My View", ...]

// Each accepts an optional broadcastGroup as a second argument to limit the
// operation to one group of visualizations:
CanvasXpress.savePageState("My View", "sales-overview");

A page-level state captures each visualization's own configuration and filter selection, so a discovery — a filtered cohort spread across several linked views — becomes a reproducible view you can return to or hand to a colleague.

DOE Dashboard

An alternative way to broadcast events is by putting all data into a single DOE (Design of Experiments) visualization, which acts as an integrated dashboard.

DOE Graph

To filter the data, simply click on any of the pie charts or histograms in the dashboard. To reset the graph, press 'ESC'. This powerful filtering feature is available without any custom code.

You can toggle this visualization in datasets that contain metadata with the help of the context menus (Explore Meta-Data under the Explore menu) or create it programmatically by calling the createDOE function.

var doe = {
  "x" : {
    "Height" : [174, 161, 194, 160, 173, 151],
    "Weight" : [65.6, 51.6, 80.7, 49.2, 55.2, 48.7],
    "Hip": [93.5, 92, 95, 91, 90.3, 89.9],
    "Waist": [71.5, 66.5, 83.2, 61.2, 66.5, 61.6],
    "Gender" : ["Male", "Female", "Male", "Female", "Female", "Female"],
    "Excercise" : ["Low", "Moderate", "Moderate", "Moderate", "Low", "Intense"]
  },
  "y" : {
    "vars" : ["Age"],
    "smps" : ["Keith", "Nina", "Freddy", "Tracey", "Isabelle", "Penny"],
    "data" : [
      [ 21, 22, 28, 19, 32, 35 ]
    ]
  }
}
var cXDOE = new CanvasXpress("canvasDOE", doe, {
  graphType : "Bar",
  histogramBins: 5
}, false, false, [
  ["createDOE", []]
]);

Legend Broadcasting

Another broadcasting flavor is based on legend hide/show events. Click on the legends of the following graphs to see this feature in action. Press `Ctrl` + `Esc` to reset all graphs.

cyl
gear
carb
// Dataset 1
var dsL1 = {
  "y": {
    "vars": ["Mazda RX4", "Mazda RX4 Wag", "Datsun 710", "Hornet 4 Drive", "Hornet Sportabout", "Valiant", "Duster 360", "Merc 240D", "Merc 230", "Merc 280", "Merc 280C", "Merc 450SE", "Merc 450SL", "Merc 450SLC", "Cadillac Fleetwood", "Lincoln Continental", "Chrysler Imperial", "Fiat 128", "Honda Civic", "Toyota Corolla", "Toyota Corona", "Dodge Challenger", "AMC Javelin", "Camaro Z28", "Pontiac Firebird", "Fiat X1-9", "Porsche 914-2", "Lotus Europa", "Ford Pantera L", "Ferrari Dino", "Maserati Bora", "Volvo 142E"],
    "smps": ["wt", "mpg"],
    "data": [
      [2.62, 21], [2.875, 21], [2.32, 22.8], [3.215, 21.4], [3.44, 18.7], [3.46, 18.1], [3.57, 14.3], [3.19, 24.4], [3.15, 22.8], [3.44, 19.2], [3.44, 17.8], [4.07, 16.4], [3.73, 17.3], [3.78, 15.2], [5.25, 10.4], [5.424, 10.4], [5.345, 14.7], [2.2, 32.4], [1.615, 30.4], [1.835, 33.9], [2.465, 21.5], [3.52, 15.5], [3.435, 15.2], [3.84, 13.3], [3.845, 19.2], [1.935, 27.3], [2.14, 26], [1.513, 30.4], [3.17, 15.8], [2.77, 19.7], [3.57, 15], [2.78, 21.4]
    ]
  },
  "z": {
    "cyl": [6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 4, 4, 4, 8, 6, 8, 4],
    "gear": [4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 4],
    "carb": [4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2, 2, 4, 2, 1, 2, 2, 4, 6, 8, 2]
  }
}
var cXL1 = new CanvasXpress("canvasIdL1", dsL1, {
  graphType: "Scatter2D",
  xAxisTitle: "wt",
  yAxisTitle: "mpg",
  stringVariableFactors: ["cyl"],
  asSampleFactors: ["cyl"],
  colorBy: "cyl",
  legendScaleFontFactor: 3,
  broadcastGroup: 'legends',
  theme: "CanvasXpress"
});
var dsL2 = {
  "y": {
    "vars": ["Mazda RX4", "Mazda RX4 Wag", "Datsun 710", "Hornet 4 Drive", "Hornet Sportabout", "Valiant", "Duster 360", "Merc 240D", "Merc 230", "Merc 280", "Merc 280C", "Merc 450SE", "Merc 450SL", "Merc 450SLC", "Cadillac Fleetwood", "Lincoln Continental", "Chrysler Imperial", "Fiat 128", "Honda Civic", "Toyota Corolla", "Toyota Corona", "Dodge Challenger", "AMC Javelin", "Camaro Z28", "Pontiac Firebird", "Fiat X1-9", "Porsche 914-2", "Lotus Europa", "Ford Pantera L", "Ferrari Dino", "Maserati Bora", "Volvo 142E"],
    "smps": ["wt", "mpg"],
    "data": [
      [2.62, 21], [2.875, 21], [2.32, 22.8], [3.215, 21.4], [3.44, 18.7], [3.46, 18.1], [3.57, 14.3], [3.19, 24.4], [3.15, 22.8], [3.44, 19.2], [3.44, 17.8], [4.07, 16.4], [3.73, 17.3], [3.78, 15.2], [5.25, 10.4], [5.424, 10.4], [5.345, 14.7], [2.2, 32.4], [1.615, 30.4], [1.835, 33.9], [2.465, 21.5], [3.52, 15.5], [3.435, 15.2], [3.84, 13.3], [3.845, 19.2], [1.935, 27.3], [2.14, 26], [1.513, 30.4], [3.17, 15.8], [2.77, 19.7], [3.57, 15], [2.78, 21.4]
    ]
  },
  "z": {
    "cyl": [6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 4, 4, 4, 8, 6, 8, 4],
    "gear": [4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 4],
    "carb": [4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2, 2, 4, 2, 1, 2, 2, 4, 6, 8, 2]
  }
}
var cXL2 = new CanvasXpress("canvasIdL2", dsL2, {
  graphType: "Scatter2D",
  xAxisTitle: "wt",
  yAxisTitle: "mpg",
  stringVariableFactors: ["gear"],
  asSampleFactors: ["gear"],
  colorBy: "gear",
  legendScaleFontFactor: 3,
  broadcastGroup: 'legends',
  theme: "CanvasXpress"
});
var dsL3 = {
  "y": {
    "vars": ["Mazda RX4", "Mazda RX4 Wag", "Datsun 710", "Hornet 4 Drive", "Hornet Sportabout", "Valiant", "Duster 360", "Merc 240D", "Merc 230", "Merc 280", "Merc 280C", "Merc 450SE", "Merc 450SL", "Merc 450SLC", "Cadillac Fleetwood", "Lincoln Continental", "Chrysler Imperial", "Fiat 128", "Honda Civic", "Toyota Corolla", "Toyota Corona", "Dodge Challenger", "AMC Javelin", "Camaro Z28", "Pontiac Firebird", "Fiat X1-9", "Porsche 914-2", "Lotus Europa", "Ford Pantera L", "Ferrari Dino", "Maserati Bora", "Volvo 142E"],
    "smps": ["wt", "mpg"],
    "data": [
      [2.62, 21], [2.875, 21], [2.32, 22.8], [3.215, 21.4], [3.44, 18.7], [3.46, 18.1], [3.57, 14.3], [3.19, 24.4], [3.15, 22.8], [3.44, 19.2], [3.44, 17.8], [4.07, 16.4], [3.73, 17.3], [3.78, 15.2], [5.25, 10.4], [5.424, 10.4], [5.345, 14.7], [2.2, 32.4], [1.615, 30.4], [1.835, 33.9], [2.465, 21.5], [3.52, 15.5], [3.435, 15.2], [3.84, 13.3], [3.845, 19.2], [1.935, 27.3], [2.14, 26], [1.513, 30.4], [3.17, 15.8], [2.77, 19.7], [3.57, 15], [2.78, 21.4]
    ]
  },
  "z": {
    "cyl": [6, 6, 4, 6, 8, 6, 8, 4, 4, 6, 6, 8, 8, 8, 8, 8, 8, 4, 4, 4, 4, 8, 8, 8, 8, 4, 4, 4, 8, 6, 8, 4],
    "gear": [4, 4, 4, 3, 3, 3, 3, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 4, 4, 4, 3, 3, 3, 3, 3, 4, 5, 5, 5, 5, 5, 4],
    "carb": [4, 4, 1, 1, 2, 1, 4, 2, 2, 4, 4, 3, 3, 3, 4, 4, 4, 1, 2, 1, 1, 2, 2, 4, 2, 1, 2, 2, 4, 6, 8, 2]
  }
}
var cXL3 = new CanvasXpress("canvasIdL3", dsL3, {
  graphType: "Scatter2D",
  xAxisTitle: "wt",
  yAxisTitle: "mpg",
  stringVariableFactors: ["carb"],
  asSampleFactors: ["carb"],
  colorBy: "carb",
  legendScaleFontFactor: 3,
  broadcastGroup: 'legends',
  theme: "CanvasXpress"
});