Visualize.Chart.Summary (Visualize v0.8.3)

Copy Markdown View Source

A chart's text alternative (spec/14 §21, D-142): what a screen reader says for a chart, generated from the design and the data it was applied to.

new/1 reads an applied chart into a summary: its name — the design's meta.name, else its kind — and, frame by frame, the chart's kind (a line chart, a gauge, a treemap), the series its marks draw and how many rows, each axis with the range or the categories its scale holds, and the extremes of the values the marks draw. text/1 is that summary as sentences, which Visualize.Chart.generate/2 writes into the root's <desc> (§21.2). A value is written as its axis writes it — the axis's format, its measure's display unit, its prefix and unit (§4.4) — to four significant digits rather than at the ticks' step, so an extreme is not rounded to a tick.

table/2 is the other half of the text alternative (§21.3): the rows each mark draws as an HTML <table>, visually hidden, for a host to place beside the chart. A role="img" root hides its children from assistive technology, so the table cannot live inside the <svg>.

attrs/2 and description/2 name an element that stands for the chart — a <canvas>, or the wrapper of a hybrid chart's layers (§21.4).

Examples

iex> design = %{
...>   version: 2,
...>   meta: %{name: "Load"},
...>   sources: %{primary: %{fields: [:t, :v]}},
...>   frames: %{main: %{
...>     kind: :cartesian,
...>     scales: %{x: %{kind: :linear}, y: %{kind: :linear}},
...>     axes: [%{scale: :x, side: :bottom}, %{scale: :y, side: :left}]
...>   }},
...>   marks: [%{type: :line, data: :primary, channels: %{x: :t, y: :v}}]
...> }
iex> {:ok, applied} = Visualize.Chart.apply(design, sources: %{primary: %{t: [1, 2, 3], v: [4, 9, 2]}})
iex> summary = Visualize.Chart.Summary.new(applied)
iex> summary.name
"Load"
iex> Visualize.Chart.Summary.text(summary)
"Line chart, 1 series (v) of 3 points. Bottom axis t, from 1 to 3. Left axis v, from 2 to 9. Highest v 9 at t 2; lowest v 2 at t 3."

Summary

Types

An axis as the summary says it: its scale's range, or its categories.

The highest and the lowest value one mark draws, each with where it is; rows is how many values there were, and a mark of one says its value alone.

One frame of the summary.

t()

Functions

The attributes that make an element stand for the chart (§21.4) — a <canvas>, or the wrapper of a hybrid chart's layers: role="img", the name as aria-label, and aria-describedby the id of description/2's element, which the page renders with the same id. A keyword list, to spread into a HEEx tag.

The element attrs/2 points aria-describedby at: the summary's text in a <p> with the id <id>-summary and the hidden attribute, read as a description and never shown. Inside a <canvas> it is also the canvas's fallback content.

The summary of an applied chart: its name and, per frame in drawing order (z, ties by name, §4.2), its kind, series, axes and extremes.

The data-table fallback (§21.3): the rows each data mark draws, one HTML <table> per mark — a mark repeating another's table is left out — in a <div> that is visually hidden and still read. Each table has a <caption> — the chart's name, and the source's name when there are several — <th scope="col"> headers named by field, and every value written as the summary writes it. All text is escaped.

The summary as sentences: per frame, the kind with its series, one sentence per axis, then the extremes; a design of several frames says each frame's name first.

Types

axis()

@type axis() :: %{
  scale: atom(),
  side: atom(),
  title: String.t(),
  range: {String.t(), String.t()} | nil,
  categories: [String.t()] | nil
}

An axis as the summary says it: its scale's range, or its categories.

extreme()

@type extreme() :: %{
  field: String.t(),
  rows: non_neg_integer(),
  high: {String.t(), String.t() | nil},
  low: {String.t(), String.t() | nil}
}

The highest and the lowest value one mark draws, each with where it is; rows is how many values there were, and a mark of one says its value alone.

frame()

@type frame() :: %{
  name: atom() | nil,
  kind: String.t(),
  series: [String.t()],
  rows: non_neg_integer(),
  unit: String.t(),
  axes: [axis()],
  extremes: [extreme()]
}

One frame of the summary.

t()

@type t() :: %Visualize.Chart.Summary{frames: [frame()], name: String.t()}

Functions

attrs(summary, id)

@spec attrs(t(), String.t()) :: keyword()

The attributes that make an element stand for the chart (§21.4) — a <canvas>, or the wrapper of a hybrid chart's layers: role="img", the name as aria-label, and aria-describedby the id of description/2's element, which the page renders with the same id. A keyword list, to spread into a HEEx tag.

description(summary, id)

@spec description(t(), String.t()) :: String.t()

The element attrs/2 points aria-describedby at: the summary's text in a <p> with the id <id>-summary and the hidden attribute, read as a description and never shown. Inside a <canvas> it is also the canvas's fallback content.

new(applied)

@spec new(Visualize.Chart.Applied.t()) :: t()

The summary of an applied chart: its name and, per frame in drawing order (z, ties by name, §4.2), its kind, series, axes and extremes.

table(applied, opts \\ [])

@spec table(Visualize.Chart.Applied.t(), keyword()) :: String.t()

The data-table fallback (§21.3): the rows each data mark draws, one HTML <table> per mark — a mark repeating another's table is left out — in a <div> that is visually hidden and still read. Each table has a <caption> — the chart's name, and the source's name when there are several — <th scope="col"> headers named by field, and every value written as the summary writes it. All text is escaped.

Options

  • :hidden - visually hide the tables (default true)
  • :id - the <div>'s id (default none)
  • :class - the <div>'s class (default "vis-data-table")
  • :caption - the caption (default the summary's name)
  • :limit - the rows a table holds; a table cut short says how many it left out (default 1000)

text(applied)

@spec text(t() | Visualize.Chart.Applied.t()) :: String.t()

The summary as sentences: per frame, the kind with its series, one sentence per axis, then the extremes; a design of several frames says each frame's name first.