## Name HTML::D3 - A simple Perl module for generating charts using D3.js. ## Version Version 0.29 ## Synopsis ```perl use HTML::D3; my $chart = HTML::D3->new( width => 1024, height => 768, title => 'Sample Bar Chart' ); my $data = [ ['Category 1', 10], ['Category 2', 20], ['Category 3', 30] ]; my $html = $chart->render_bar_chart($data); print $html; $chart = HTML::D3->new(title => 'Sales Data'); $data = [ ['Product A', 100], ['Product B', 150], ['Product C', 200] ]; $html = $chart->render_line_chart($data); print $html; ``` ## Description HTML::D3 is a Perl module that provides functionality to create simple charts using D3.js. The module generates HTML and JavaScript code to render the chart in a web browser. Text in a chart's data and options is written into a ` ``` #### Arguments - `$data` - An array reference of data points. Each point is an array reference with two required elements - the label (string) and the value (numeric) - and an optional third element: a hash reference of extra key/value pairs to display in the tooltip after the label and value rows. ``` [$x, $y] # basic point [$x, $y, \%row] # point with extra tooltip data ``` - `\%opts` - Optional hash reference of rendering options: - `id` (string, default `'chart'`) - Override the `id` attribute of the ` element. Use this when embedding multiple charts on the same page. - `responsive` (boolean, default `0`) - If true, emit `viewBox="0 0 W H" width="100%"`, with no `height`, instead of fixed pixel dimensions, so the chart scales with its container. Falls back to `$self->{responsive}` when not set per call. #### Return Value A hash reference with: - `svg_id` - The `id` attribute used on the ` element. - `html` - The embeddable fragment string (Perl character string). #### Errors - Dies with `'Data must be an array of arrays'` when `$data` is not an ARRAY reference. #### Side Effects None. The method is read-only. #### Api Specification ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { id => { type => 'string', optional => 1 }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ### Render\_Zoomable\_Line\_Chart\_Snippet ```perl my $fragment = $chart->render_zoomable_line_chart_snippet($data); my $fragment = $chart->render_zoomable_line_chart_snippet($data, { animated => 1 }); # $fragment->{svg_id} - the id attribute of the element # $fragment->{html} - embeddable HTML fragment (style + button + svg + script) ``` Like `render_line_chart_snippet`, but adds brush-to-zoom: the user can drag across a range of the x-axis to zoom into that region. A _Reset zoom_ button (hidden until a zoom is active) returns the chart to its original extent. Subsequent brushes on the zoomed view zoom in further; Reset always returns to the full dataset. The caller is responsible for loading D3 in the page `. Accepts the same arguments as `render_line_chart_snippet`: an array reference of data points, each `[$x, $y]` or `[$x, $y, \%extra]`, plus an optional second argument `$opts` (hashref). #### Options - `animated` (boolean, default `0`) - when true, the initial page load animates the line drawing left-to-right via the `stroke-dashoffset` technique (1200 ms, `d3.easeLinear`), then fades in data-point circles after the line finishes (300 ms after a 1200 ms delay). Respects `prefers-reduced-motion`: when the user has requested reduced motion the line is drawn immediately at full opacity. Subsequent zoom and reset redraws are never animated regardless of this flag. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, default => {} }, } Each element of C<$data> is C<[ Str, Num ]> or C<[ Str, Num, HashRef ]>; passing C or a non-arrayref dies. Recognised C key: C (boolean, default C<0>). ``` ##### Output ``` HashRef -- C<{ svg_id =E 'chart', html =E Str }>; embeddable fragment; no DOCTYPE, no page shell, no D3 CDN tag. ``` #### Errors Dies with _Data must be an array of arrays_ if `$data` is not an arrayref. ### Render\_Multi\_Series\_Line\_Chart\_With\_Tooltips ``` $html = $chart->render_multi_series_line_chart_with_tooltips($data); ``` Generates HTML and JavaScript code to render a chart of many lines with mouseover tooltips. Accepts the following arguments: - `$data` - An array reference of series hashes. Each element is a hashref with a `name` key (string) and a `data` key (array reference of `{label, value}` hashrefs). ```perl [ { name => 'Series A', data => [{ label => 'Jan', value => 100 }, ...] }, ... ] ``` Returns a string containing the HTML and JavaScript code for the chart. Tooltip strings use `<\/b>` rather than `` for html-tidy compliance. #### Errors - Throws `Data must be an array of hashes` when `$data` is not an ARRAY reference. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, } Each element of C<$data> is a hashref with keys C (string) and C (arrayref of hashrefs with C`, or `` wrapper; D3.js must be loaded by the host page. #### Arguments - `\@series` - An array reference of series. Each series is a hash reference with a `name` (string) and a `data` array reference of `{ label => Str, value => Num }` points: ```perl [ { name => 'North', data => [ { label => 'Jan', value => 12 }, ... ] }, { name => 'South', data => [ { label => 'Jan', value => 8 }, ... ] }, ] ``` Series need not share labels: the X domain is the union of every series' labels, in the order `x_order` gives. One line and one set of dots is drawn per series, and a clickable legend toggles each series on and off. - `\%opts` - Optional hash reference: - `scheme` (string, default `'tableau10'`) - D3 categorical colour scheme (for example `'category10'`, `'set2'`, `'set3'`, `'paired'`). `categorical_schemes()` lists the names, and `palette()` hands a Perl caller the colours of one. - `x_label` (string, default `''`) - Label shown below the X axis. - `y_label` (string, default `''`) - Label shown beside the Y axis. - `animated` (boolean, default 0) - If true each line draws itself left to right by animating its stroke dash offset. Respects `prefers-reduced-motion`. - `x_order` (`'auto'`, `'data'` or `'sort'`, default `'auto'`) - the order of the X domain. `'data'` takes the labels in the order they are met, series by series, as before 0.29. `'sort'` sorts them: numerically when every label is a number, otherwise as strings. `'auto'` sorts them when every label is a number or an ISO 8601 date or date-time (`2026-01-15`, `2026-01`, `2026-01-15T09:30`), and otherwise keeps the order they are met in, so that `Jan`, `Feb`, `Mar` stay in the caller's order. Taken as met, two series of dates gave an axis such as `15, 19, 16, 17`. Whenever the labels are sorted, each line's points are drawn in the axis order. The caller's series are not changed. - `responsive` (boolean, optional) - SVG responsive sizing override. - `id` (string, default `'chart'`) - `id` of the ` element. Returns `{ svg_id => 'chart', html => Str }`. #### Errors - Throws `Data must be an array of series` when `\@series` is not an ARRAY reference. - Throws `Each series must be a hashref with name and data` when a series is not a hashref, has no `name`, or has a `data` that is not an ARRAY reference. - Throws `Unknown x_order: ` when `x_order` is not `auto`, `data` or `sort`. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { scheme => { type => 'string', optional => 1, default => 'tableau10' }, x_label => { type => 'string', optional => 1, default => '' }, y_label => { type => 'string', optional => 1, default => '' }, x_order => { type => 'string', optional => 1, default => 'auto' }, animated => { type => 'boolean', optional => 1, default => 0 }, responsive => { type => 'boolean', optional => 1 }, id => { type => 'string', optional => 1, default => 'chart' }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => 'chart', html => Str } ``` ### Render\_Scatter\_Chart\_Snippet ```perl my $fragment = $chart->render_scatter_chart_snippet($data); my $fragment = $chart->render_scatter_chart_snippet($data, \%opts); # $fragment->{svg_id} - the id attribute of the element # $fragment->{html} - embeddable HTML fragment (style + svg + script) ``` Generates an embeddable HTML fragment for a scatter plot with mouseover tooltips. Returns a fragment with no `, `, `, or ` wrapper; the caller is responsible for loading D3 in the page. #### Arguments - `$data` - An array reference of data points. Each point is an array reference with two required numeric elements (x, y), an optional third hash reference of extra key/value pairs shown as extra tooltip rows, and an optional fourth hash reference carrying the `series` (colour group) and `size` (bubble radius) dimensions: ```perl [$x, $y] # basic point [$x, $y, \%row] # point with extra tooltip data [$x, $y, \%row, { series => 'North', size => 42 }] # colour and size ``` - `\%opts` - Optional hash reference: - `id` (string, default `'scatter_chart'`) - `id` of the ` element. - `color` (CSS colour or `'categorical'`, default `'steelblue'`) - Fill colour for the data points. `'categorical'` uses the Tableau-10 palette. A value holding anything a CSS colour cannot, such as a quote or `<`, is ignored and the default used. - `x_label` (string, default `''`) - Label for the X axis. - `y_label` (string, default `''`) - Label for the Y axis. - `value_label` (string, default `'Value'`) - Prefix for the tooltip value row. - `colour_by_series` (boolean, default 0) - Colour each point by its `series` value instead of by point index, and draw a legend listing the series to the right of the plot. Ignored for points with no `series` value. - `scheme` (string, default `'tableau10'`) - D3 categorical colour scheme used when `colour_by_series` is set, for example `'category10'`, `'set2'`, `'set3'`, or `'paired'`. `categorical_schemes()` lists the names, and `palette()` hands a Perl caller the colours of one. - `series_col` (string, default `'Series'`) - Row label for the series value in the tooltip. - `size_col` (string, default `'Size'`) - Row label for the size value in the tooltip. - `radius_range` (arrayref of two numbers, default `[3, 15]`) - Pixel radii mapped from the smallest and largest observed `size` value. The mapping is by area (`d3.scaleSqrt`), so a point twice as large is drawn with four times the area. A point with no `size` value is drawn at the lower radius. - `animated` (boolean, default 0) - If true, circles fade in from opacity 0 on page load (400 ms). Respects `prefers-reduced-motion`. - `responsive` (boolean, default 0) - See `render_bar_chart_snippet`. #### Return Value A hash reference with `svg_id` (string) and `html` (Perl character string). #### Errors - Dies with `'Data must be an array of arrays'` when `$data` is not an ARRAY ref. - Dies with `'Each data point must be an array reference'` when an element is not an ARRAY ref. - Dies with `'Each data point must have at least 2 elements'` when a point has fewer than 2 items. - Dies with `'X value must be numeric'` when the x element is not a number. - Dies with `'Y value must be numeric'` when the y element is not a number. #### Api Specification ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { id => { type => 'string', optional => 1 }, color => { type => 'string', optional => 1, default => 'steelblue' }, x_label => { type => 'string', optional => 1, default => '' }, y_label => { type => 'string', optional => 1, default => '' }, value_label => { type => 'string', optional => 1, default => 'Value' }, colour_by_series => { type => 'boolean', optional => 1, default => 0 }, scheme => { type => 'string', optional => 1, default => 'tableau10' }, series_col => { type => 'string', optional => 1, default => '' }, size_col => { type => 'string', optional => 1, default => '' }, radius_range => { type => 'arrayref', optional => 1, default => [3, 15] }, animated => { type => 'boolean', optional => 1, default => 0 }, responsive => { type => 'boolean', optional => 1, default => 0 }, }, }, } ``` ### Render\_Table\_Snippet ```perl my $fragment = $chart->render_table_snippet($data); my $fragment = $chart->render_table_snippet($data, \%opts); # $fragment->{table_id} - the id attribute of the element # $fragment->{html} - embeddable HTML fragment (style + table + script) ``` Generates an embeddable HTML fragment for a sortable, filterable data table. Returns a fragment with no page-shell wrapper; the caller loads D3 if needed. #### Arguments - `$data` - An array reference of row array references. The first row is treated as the header row. Every subsequent row must have the same number of columns as the header. ``` [ ['Name', 'Value', 'Category'], # header ['Alpha', 300, 'A'], ['Beta', 150, 'B'], ] ``` - `\%opts` - Optional hash reference: - `id` (string, default `'data_table'`) - `id` of the ` element. - `sortable` (boolean, default 1) - If true, clicking a column header sorts the table by that column (toggle ascending/descending). - `caption` (string, default `''`) - Optional ` element text. #### Return Value A hash reference with `table_id` (string) and `html` (Perl character string). Note: returns `table_id`, not `svg_id`, because this method renders an HTML table rather than an SVG chart. #### Errors - Dies with `'Data must be an array of arrays'` when `$data` is not an ARRAY ref. - Dies with `'Data must have at least one row (header row)'` when `$data` is empty. - Dies with `'Each row must be an array reference'` when a row is not an ARRAY ref. #### Api Specification ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { id => { type => 'string', optional => 1, default => 'data_table' }, sortable => { type => 'boolean', optional => 1, default => 1 }, caption => { type => 'string', optional => 1, default => '' }, }, }, } ``` ### Render\_Stacked\_Bar\_Snippet ```perl my $result = $chart->render_stacked_bar_snippet(\@rows, \%opts); ``` Generates an embeddable stacked bar chart (no page shell, no CDN tag). Each element of `\@rows` is a hashref with three keys named by `opts`: `cat_col` (the X-axis grouping), `seg_col` (the stacking segment), and `val_col` (the numeric measure). Multiple rows sharing the same cat+seg combination are summed. Accepted `\%opts` keys: - `cat_col` (string, default `'cat'`) - row key for the X-axis category. - `seg_col` (string, default `'seg'`) - row key for the stacking segment. - `val_col` (string, default `'val'`) - row key for the numeric value. - `orient` (string `'v'` or `'h'`, default `'v'`) - bar orientation. - `scheme` (string, default `'tableau10'`) - D3 categorical colour scheme. Supported: `tableau10`, `category10`, `set2`, `set3`, `paired` - the names `categorical_schemes()` returns, whose colours `palette()` makes available to Perl. - `x_label` (string, optional) - axis label shown below the category axis. - `sort` (string, optional) - sort categories: `'value'` (desc total) or `'label'` (alpha). - `id` (string, optional) - override the default `svg_id` value. - `responsive` (boolean, optional) - SVG responsive sizing override. Returns `{ svg_id => 'stacked_bar', html => Str }`. #### Errors - Throws `Data must be an array of hashes` when `$data` is not an ARRAY reference. - Throws `Each data point must be a hash reference` when a row is not a hashref. - Throws `Value must be numeric` when a value field is not a number. - Throws `orient must be 'v' or 'h'` for an invalid `orient` value. - Throws `sort must be 'value' or 'label'` for an invalid `sort` value. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { cat_col => { type => 'string', optional => 1, default => 'cat' }, seg_col => { type => 'string', optional => 1, default => 'seg' }, val_col => { type => 'string', optional => 1, default => 'val' }, orient => { type => 'string', optional => 1, default => 'v' }, scheme => { type => 'string', optional => 1, default => 'tableau10' }, x_label => { type => 'string', optional => 1, default => '' }, sort => { type => 'string', optional => 1 }, id => { type => 'string', optional => 1, default => 'stacked_bar' }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => Str, html => Str } ``` ### Render\_Combo\_Snippet ```perl my $result = $chart->render_combo_snippet(\@rows, \%opts); ``` Generates an embeddable combo chart: bars for one measure on the left Y axis, a line for another measure on the right Y axis, sharing the same X (category) axis. Each element of `\@rows` is a hashref with at least three keys named by `opts`: `x_col` (X-axis label), `bar_col` (bar measure), and `line_col` (line measure). Accepted `\%opts` keys: - `x_col` (string, default `'x'`) - row key for the X-axis label. - `bar_col` (string, default `'bar_val'`) - row key for the bar measure. - `line_col` (string, default `'line_val'`) - row key for the line measure. - `bar_label` (string, default `'Bar'`) - legend/axis label for bars. - `line_label` (string, default `'Line'`) - legend/axis label for line. - `bar_color` (string, optional CSS colour, default `'steelblue'`) - bar fill. A value holding anything a CSS colour cannot, such as a quote or `<`, is ignored and the default used. - `line_color` (string, optional CSS colour, default `'#e15759'`) - line stroke. Checked as `bar_color` is. - `scheme` (string, optional) - a categorical scheme, as `categorical_schemes()` lists them. The bars take its first colour and the line its second, as `colour_at($scheme, 0)` and `colour_at($scheme, 1)`. `bar_color` and `line_color` still win when given. Any other name is ignored and the defaults used. - `id` (string, optional) - override the default `svg_id` value. - `responsive` (boolean, optional) - SVG responsive sizing override. Returns `{ svg_id => 'combo_chart', html => Str }`. #### Errors - Throws `Data must be an array of hashes` when `$data` is not an ARRAY reference. - Throws `Each data point must be a hash reference` when a row is not a hashref. - Throws `Bar value must be numeric` when a bar value field is not a number. - Throws `Line value must be numeric` when a line value field is not a number. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { x_col => { type => 'string', optional => 1, default => 'x' }, bar_col => { type => 'string', optional => 1, default => 'bar_val' }, line_col => { type => 'string', optional => 1, default => 'line_val' }, bar_label => { type => 'string', optional => 1, default => 'Bar' }, line_label => { type => 'string', optional => 1, default => 'Line' }, bar_color => { type => 'string', optional => 1, default => 'steelblue' }, line_color => { type => 'string', optional => 1, default => '#e15759' }, scheme => { type => 'string', optional => 1 }, id => { type => 'string', optional => 1, default => 'combo_chart' }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => Str, html => Str } ``` ### Render\_Treemap\_Snippet ```perl my $result = $chart->render_treemap_snippet(\@rows_or_tree, \%opts); ``` Generates an embeddable treemap (no page shell, no CDN tag). Leaf area is proportional to the numeric measure. Accepts two data formats: - **Flat path** (arrayref of hashrefs): each row must have a `path` key (e.g. `'Root/A/X'`) and a `value` key. The module converts this to a D3 stratify hierarchy in JS. Override the path separator with `opts->{path_sep}`. - **Nested tree** (hashref): a pre-built D3-compatible hierarchy with `name`/`children`/`value` structure. Passed directly to `d3.hierarchy()`. **Colour by value.** A flat row, or a node of the tree, may also carry `color_value`, a second number that colours its tile: the area says how much and the colour says how well -- sales sized by revenue and coloured by margin. As soon as one tile has one, every tile is shaded from the sequential `color_scheme` over the smallest to the largest `color_value`, in place of its top-level group's colour; a tile without one is grey. The tooltip gives the value under `color_label`, a legend at the foot of the chart gives the range, and labels on light tiles are drawn dark. When every tile has the same value they all take the middle of the scheme. ```perl ->render_treemap_snippet([ { path => 'All/North', value => 1200, color_value => 0.18 }, { path => 'All/South', value => 800, color_value => 0.05 }, ], { color_scheme => 'Blues', color_label => 'Margin' }); ``` Accepted `\%opts` keys: - `path_sep` (string, default `'/'`) - path separator (flat format only). - `scheme` (string, default `'tableau10'`) - D3 categorical colour scheme. Supported: `tableau10`, `category10`, `set2`, `set3`, `paired` - the names `categorical_schemes()` returns, whose colours `palette()` makes available to Perl. - `label` (boolean, default `1`) - show node labels inside cells. - `color_scheme` (string, default `'YlOrRd'`) - the sequential scheme tiles are coloured from when they carry `color_value`: `YlOrRd`, `Blues`, `Greens`, `Purples`, `RdPu` or `YlGnBu`, as for `render_heatmap_snippet`. Not read when no tile has a `color_value`. - `color_label` (string, default `'Colour'`) - what `color_value` measures, for the tooltip and the legend. - `id` (string, optional) - override the default `svg_id` value. - `responsive` (boolean, optional) - SVG responsive sizing override. Returns `{ svg_id => 'treemap', html => Str }`. #### Errors - Throws `Data must be an array of hashes or a hash tree` when `$data` is neither an ARRAY nor a HASH reference. - Throws `Each flat row must be a hash reference` when a flat row is not a hashref. - Throws `Each flat row must have a 'path' key` when a flat row lacks `path`. - Throws `Each flat row must have a numeric 'value' key` when a value is not numeric. - Throws `Each flat row's 'color_value' must be numeric` when a flat row's `color_value` is defined but not a finite number. - Throws `Each node's 'color_value' must be numeric` when a node of the tree has a `color_value` that is defined but not a finite number. - Throws `Unknown color_scheme: ` when a tile has a `color_value` and `color_scheme` is not one of the sequential schemes. #### Api Specification ##### Input ```perl { data => { type => 'arrayref | hashref' }, opts => { type => 'hashref', optional => 1, keys => { path_sep => { type => 'string', optional => 1, default => '/' }, scheme => { type => 'string', optional => 1, default => 'tableau10' }, label => { type => 'boolean', optional => 1, default => 1 }, color_scheme => { type => 'string', optional => 1, default => 'YlOrRd' }, color_label => { type => 'string', optional => 1, default => 'Colour' }, id => { type => 'string', optional => 1, default => 'treemap' }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => Str, html => Str } ``` ### Render\_Histogram\_Snippet ```perl my $result = $chart->render_histogram_snippet(\@values, \%opts); ``` Generates an embeddable frequency histogram (no page shell, no CDN tag). `\@values` is an arrayref of numeric scalars (already extracted and coerced by the caller). Accepted `\%opts` keys: - `bins` (integer or `undef`, default `20`) - number of bins. Pass `undef` for automatic bin count using Sturges' rule: `ceil(log2(n) + 1)`. Ignored when `binned` is set. - `binned` (boolean, default 0) - treat `$data` as pre-computed bins rather than as raw values. Each element is a hashref with a `count` and either a `label` or a numeric `lo`/`hi` pair from which the label `[lo,hi)` is derived: ```perl { label => '[0,10)', count => 3 } { lo => 10, hi => 20, count => 5 } ``` The caller owns the binning, so `d3.bin()` is never called: one bar is drawn per entry, in the order supplied, and the supplied counts are authoritative. The bin labels are drawn rotated. The plot gives up as much room as they need, up to half the chart's height and a quarter of its width, so that they and `x_label` do not overlap and stay inside the chart. - `scheme` (string, optional) - D3 categorical colour scheme (for example `'tableau10'` or `'category10'`) whose first colour is used as the bar fill when `color` is not given. That colour is `colour_at($scheme, 0)`, so a caller shading the same data by hand starts from the same colour the bars do. - `x_label` (string, optional) - label shown below the X axis. - `color` (string, default `'steelblue'`) - bar fill colour. A value holding anything a CSS colour cannot, such as a quote or `<`, is ignored and the default used. - `id` (string, optional) - override the default `svg_id` value. - `responsive` (boolean, optional) - SVG responsive sizing override. Returns `{ svg_id => 'histogram', html => Str }`. #### Errors - Throws `Data must be an array of numeric values` when `$data` is not an ARRAY reference. - Throws `Each value must be numeric` when any element is non-numeric. - Throws `bins must be a positive integer` when `bins` is defined but not a positive integer. - Throws `Data must contain at least one bin` when `binned` is set and `$data` holds no bins. - Throws `Each pre-binned entry must be a hash reference` when a pre-binned element is not a hashref. - Throws `Bin count must be numeric` when a pre-binned `count` is missing or not numeric. - Throws `Bin count must not be negative` when a pre-binned `count` is negative. - Throws `Each pre-binned entry must have a label or numeric lo and hi` when a pre-binned entry has neither a `label` nor a numeric `lo`/`hi` pair. #### Api Specification ##### Input ```perl { data => { type => 'arrayref' }, opts => { type => 'hashref', optional => 1, keys => { bins => { type => 'integer', optional => 1, default => 20 }, binned => { type => 'boolean', optional => 1, default => 0 }, x_label => { type => 'string', optional => 1, default => '' }, color => { type => 'string', optional => 1, default => 'steelblue' }, scheme => { type => 'string', optional => 1 }, id => { type => 'string', optional => 1, default => 'histogram' }, responsive => { type => 'boolean', optional => 1 }, }, }, } ``` ##### Output ```perl HashRef -- { svg_id => Str, html => Str } ``` ## Support This module is provided as-is without any warranty. Please report any bugs or feature requests to `bug-html-d3 at rt.cpan.org`, or through the web interface at [http://rt.cpan.org/NoAuth/ReportBug.html?Queue=HTML-D3](http://rt.cpan.org/NoAuth/ReportBug.html?Queue=HTML-D3). I will be notified, and then you'll automatically be notified of progress on your bug as I make changes. You can find documentation for this module with the perldoc command. ``` perldoc HTML::D3 ``` You can also look for information at: ## Bugs It would help to have the render routine to return the head and body components separately. ## See Also - [Configure an Object at Runtime](https://metacpan.org/pod/Object%3A%3AConfigure) - [Test Dashboard](https://nigelhorne.github.io/HTML-D3/coverage/) ## Author Nigel Horne ## Formal Specification ### Render\_Bar\_Chart ``` render_bar_chart : HTML::D3 × (ArrayRef | undef) → Str ∪ ⊥ pre data = undef ⇒ die "Data is not optional" pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of arrays" post result ∈ Str post " N ⇒ |result_slices| = N ∧ "Other" ∈ result_labels post opts.separator = S ⇒ " S " ⊆ result.html (HTML legend: label S value (pct%)) ``` ### Render\_Heatmap\_Snippet ``` render_heatmap_snippet : HTML::D3 × (ArrayRef | undef) × (HashRef | undef) → HashRef ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of arrays" pre ∃ pt ∈ data . ref(pt) ≠ 'ARRAY' ⇒ die "Each data point must be an array reference" pre ∃ pt ∈ data . |pt| < 3 ⇒ die "Each data point must have at least 3 elements" pre ∃ pt ∈ data . defined(pt[2]) ∧ ¬numeric(pt[2]) ⇒ die "Value must be numeric" pre opts.color_scheme = S ∧ S ∉ {YlOrRd,Blues,Greens,Purples,RdPu,YlGnBu} ⇒ die "Unknown color_scheme: S" pre opts.cell_padding = N ∧ (N < 0 ∨ N > 8) ⇒ die "cell_padding must be between 0 and 8" pre ∀ pt ∈ data . pt[2] = undef ⇒ pt ∉ result -- undef rows skipped pre ∃ pt₁,pt₂ ∈ data . pt₁[0]=pt₂[0] ∧ pt₁[1]=pt₂[1] ⇒ last-write wins post result ∈ HashRef post result.svg_id = "heatmap" post result.html ∈ Str post " N ⇒ |result_bars| = N ∧ "Other" ∈ result_labels ``` ### Render\_Multi\_Series\_Line\_Chart\_Snippet ``` render_multi_series_line_chart_snippet : HTML::D3 × (ArrayRef | undef) × (HashRef | undef) → HashRef ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of series" pre ∃ s ∈ data . ref(s) ≠ 'HASH' ⇒ die "Each series must be a hashref with name and data" pre ∃ s ∈ data . ¬defined(s.name) ∨ ref(s.data) ≠ 'ARRAY' pre opts.x_order ∉ {undef, 'auto', 'data', 'sort'} ⇒ die "Unknown x_order: " ⇒ die "Each series must be a hashref with name and data" post result ∈ HashRef post result.svg_id = opts.id // "chart" post L = the labels of every series, first-seen order, as strings post opts.x_order ≠ 'data' ∧ ∀ l ∈ L . numeric(l) ⇒ the X domain is L sorted numerically post opts.x_order = 'auto' ∧ ∀ l ∈ L . iso_date(l) ⇒ the X domain is L sorted as strings post opts.x_order = 'sort' ∧ ∃ l ∈ L . ¬numeric(l) ⇒ the X domain is L sorted as strings post otherwise ⇒ the X domain is L post the X domain is sorted ⇒ each series' points are in domain order post result.html ∈ Str post " expression post opts.animated = 1 ⇒ "stroke-dashoffset" ⊆ result.html ∧ "prefers-reduced-motion" ⊆ result.html ``` ### Render\_Scatter\_Chart\_Snippet ``` render_scatter_chart_snippet : HTML::D3 × (ArrayRef | undef) × (HashRef | undef) → HashRef ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of arrays" pre ∃ pt ∈ data . ref(pt) ≠ 'ARRAY' ⇒ die "Each data point must be an array reference" pre ∃ pt ∈ data . |pt| < 2 ⇒ die "Each data point must have at least 2 elements" pre ∃ pt ∈ data . ¬numeric(pt[0]) ⇒ die "X value must be numeric" pre ∃ pt ∈ data . ¬numeric(pt[1]) ⇒ die "Y value must be numeric" post result ∈ HashRef post result.svg_id = opts.id // "scatter_chart" post result.html ∈ Str post "" ∉ result.html ∧ "<\/b>" ∈ result.html ``` ### Render\_Treemap\_Snippet ``` render_treemap_snippet : HTML::D3 × (ArrayRef | HashRef | undef) × (HashRef | undef) → HashRef ∪ ⊥ pre ref(data) ∉ {'ARRAY','HASH'} ⇒ die "Data must be an array of hashes or a hash tree" pre ref(data) = 'ARRAY' ∧ ∃ row ∈ data . ref(row) ≠ 'HASH' ⇒ die "Each flat row must be a hash reference" pre ref(data) = 'ARRAY' ∧ ∃ row ∈ data . ¬exists(row.path) ⇒ die "Each flat row must have a 'path' key" pre ref(data) = 'ARRAY' ∧ ∃ row ∈ data . ¬numeric(row.value) ⇒ die "Each flat row must have a numeric 'value' key" pre ref(data) = 'ARRAY' ∧ ∃ row ∈ data . defined(row.color_value) ∧ ¬finite(row.color_value) ⇒ die "Each flat row's 'color_value' must be numeric" pre ref(data) = 'HASH' ∧ ∃ node ∈ tree . defined(node.color_value) ∧ ¬finite(node.color_value) ⇒ die "Each node's 'color_value' must be numeric" pre BV ∧ opts.color_scheme ∉ sequential schemes ⇒ die "Unknown color_scheme: " where BV ≡ ∃ tile . defined(tile.color_value) post result ∈ HashRef post result.svg_id = opts.id // "treemap" post result.html ∈ Str post "" ∉ result ∧ "<\/b>" ∈ result ``` ### Render\_Multi\_Series\_Line\_Chart\_With\_Tooltips ``` render_multi_series_line_chart_with_tooltips : HTML::D3 × (ArrayRef | undef) → Str ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of hashes" post result ∈ Str post "" ∉ result ∧ "<\/b>" ∈ result ``` ### Render\_Multi\_Series\_Line\_Chart\_With\_Animated\_Tooltips ``` render_multi_series_line_chart_with_animated_tooltips : HTML::D3 × (ArrayRef | undef) → Str ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of hashes" post result ∈ Str post "" ∉ result ∧ "<\/b>" ∈ result ``` ### Render\_Multi\_Series\_Line\_Chart\_With\_Legends ``` render_multi_series_line_chart_with_legends : HTML::D3 × (ArrayRef | undef) → Str ∪ ⊥ pre ref(data) ≠ 'ARRAY' ⇒ die "Data must be an array of hashes" post result ∈ Str post "