shared functions used throughout datawrapper
npm install @datawrapper/shareda set of shared methods that can be used throughout Datawrapper
Import single functions:
``js`
import purifyHtml from '@datawrapper/shared/purifyHtml';
Import entire package:
`js`
import shared from '@datawrapper/shared';
shared.purifyHtml();
shared.httpReq();
- \_\_(key, scope) ⇒ string
- area(vertices) ⇒ number
- arrayToObject(o) ⇒ object
- autoTickFormat(column) ⇒ string
- autoTickFormatDate(range, precision) ⇒ string
- autoTickFormatNumber(range) ⇒ string
- clone(object) ⇒ \*
- colorLightness(hexColor) ⇒ number
- columnFormatter(numeral, column, metadata, axis) ⇒ function
- columnNameToVariable(name) ⇒ string
- combinations(input) ⇒ Array.<array>
- dateColumnFormatter(column) ⇒ function
- decodeHtml(input) ⇒ string
- defaultColors(theme) ⇒ \*
- defaultOverlayTitle(vis, colName) ⇒ string
- ~~deleteJSON(url, callback) ⇒ Promise~~
- drawPattern(parameters)
- equalish(a, b) ⇒ boolean
- escapeHtml(unsafe) ⇒ string
- estimateTextWidth(text, fontSize) ⇒ number
- ~~fetchJSON(url, method, credentials, body, callback) ⇒ Promise~~
- formatNumber(numeral, value, options) ⇒ string
- get(object, key, \_default) ⇒
- ~~getJSON(url, credentials, callback) ⇒ Promise~~
- highlightTimer(action, delay) ⇒ object
- httpReq(path, options) ⇒ Promise
- .delete()
- .get()
- .head()
- .patch()
- .post()
- .put()
- isValidUrl(input) ⇒ boolean
- kMeans(values, numCluster) ⇒ array.<Array.<number>>
- loadScript(src, callback)
- loadStylesheet(src, callback)
- normalizeAlphaNumKey(key) ⇒ string
- normalizeNumKey(key) ⇒ number
- numberColumnFormatter(numeral, config) ⇒ function
- observeFonts(fontsJSON, typographyJSON) ⇒ Promise
- opts : object
- ~~patchJSON(url, body, callback) ⇒ Promise~~
- postEvent(chartId) ⇒ function
- ~~postJSON(url, body, callback) ⇒ Promise~~
- purifyHtml(input, allowed) ⇒ string
- ~~putJSON(url, body, callback) ⇒ Promise~~
- round(value, decimals) ⇒ number
- set(object, key, value) ⇒
- significantDimension(values, tolerance) ⇒ number
- smartRound(values, addPrecision, tolerance) ⇒
- tailLength(value) ⇒ number
- toFixed(value) ⇒ string
- trackEvent(category, category, category, category)
- trackPageView(loadTime)
- truncate(str, start, end) ⇒ string
stringtranslates a message key. translations are originally stored in a
Google spreadsheet that we're pulling into Datawrapper using the
scripts/update-translations script, which stores them as :locale.json
files in the /locale folders (both in core as well as inside plugin folders)
for the client-side translation to work we are also storing the translations
in the global window.dw.backend.__messages object. plugins that need"svelte": true
client-side translations must set in their plugin.json
Returns: string - -- the translated text
| Param | Type | Default | Description |
| ----- | ------------------- | ----------------------------- | ----------------------------------------------------- |
| key | string | | - the key to be translated, e.g. "signup / hed" |
| scope | string | "core" | - the translation scope, e.g. "core" or a plugin name |
---
Computes the area of a polygon
Returns: number - -- polygon area, might be negative
| Param | Type | Description |
| -------- | -------------------------------- | ----------------------------------------------- |
| vertices | Array.<array> | - polygon vertices as [[x,y], [x,y], ...] array |
---
This function fixes an uglyness when working with PHP backends.
in PHP, there is no distiction between arrays and objects, so
PHP converts an empty object {} to a empty array [].
When this empty array then ends up in client-side JS functions which
might start to assign values to the array using arr.foo = "bar"
which results in a data structure like this:
| Param | Type | Description |
| ----- | ------------------ | ----------- |
| o | array | the input |
Example
`js
console.log(arr);
[]
foo: "bar"
length: 0
console.log(arrayToObject(arr));
Object { foo: "bar" }
`
---
Convenient wrapper around autoTickFormatNumber and autoTickFormatDate.
Returns either a numeral.js or day.js format, depending on the column type.
Returns: string - -- a numeral|dayjs format string
| Param | Type | Description |
| ------ | ------------------- | -------------------------------------------------- |
| column | object | - dw.column instance that is displayed on the axis |
---
auto-detects a nice default axis tick format for date
columns based on the input range and precision
Returns: string - - day.js compatible format string
| Param | Type | Description |
| --------- | ------------------- | ------------------------------ | ------- | ----- | ---- | --- | ---- |
| range | array | [min, max] of the data |
| precision | string | the input data precision (year | quarter | month | week | day | ...) |
Example
`js`
import { autoTickFormatDate } from '@datawrapper/shared/autoTickFormat';
autoTickFormatDate([new Date(2000, 0, 1), new Date(2002, 0, 1)], 'quarter'); // 'YYYY|[Q]Q'
---
auto-detects a nice default axis tick format for numeric
columns based on the input range
Returns: string - - numeral.js compatible format string
| Param | Type | Description |
| ----- | ------------------ | ---------------------- |
| range | array | [min, max] of the data |
Example
`js`
import { autoTickFormatNumber } from '@datawrapper/shared/autoTickFormat';
autoTickFormatNumber([0, 100]); // '0,0.[00]'
autoTickFormatNumber([0.2, 0.7]); // '0,0.00[00]'
---
Clones an object
Returns: \* - - the cloned thing
| Param | Type | Description |
| ------ | --------------- | ------------------------------- |
| object | \* | the thing that should be cloned |
---
Returns the Lab lightness value of a given hexidecimal
RGB color. Uses chroma-js to convert from Hex to Lab, but
only adds a few hundreds bytes to your build.
To use this function, you have to manually install chroma-js using
npm install chroma-js.
Returns: number - - the Lab lightness, between 0 (black) and 100 (white)
| Param | Type | Description |
| -------- | ------------------- | --------------------------------------------------- |
| hexColor | string | the RGB color as hexadecimal string, e.g. "#330066" |
Example
`js`
import colorLightness from '@datawrapper/shared/colorLightness';
colorLightness('#ff3399'); // 57.9
---
This function returns a formatting function based, given a column object,
a metadata object and the axis column name.
| Param | Type | Description |
| -------- | ------------------- | --------------------------- |
| numeral | object | Numeral.js instance |
| column | object | the date column object |
| metadata | object | the full metadata object |
| axis | string | the column name of the axis |
---
converts a column name to a variable name that can be used in the custom
column editor. variable names can't contain spaces and special characters
and are also converted to lowercase.
Returns: string - -- variable name
| Param | Type | Description |
| ----- | ------------------- | -------------------- |
| name | string | - name of the column |
Example
`js
import columnNameToVariable from '@datawrapper/shared/columnNameToVariable';
columnNameToVariable('GDP (per cap.)'); // gdp_per_cap
`
---
computes all combinations of input elements
Returns: Array.<array> - -- array of combinations
| Param | Type | Description |
| ----- | -------------------------------- | -------------------------------------------------------- |
| input | Array.<array> | - array of input objects, could be numbers, strings, etc |
Example
`js`
// returns [['a','b'], ['a'], ['b']]
combinations(['a', 'b']);
Example
`js`
// returns [[1,2,3], [1,2], [1,3], [1], [2,3], [2], [3]]
combinations([1, 2, 3]);
---
This function returns a date formatting function based on a
dw column object. The implementation is backwards-compatible with
our old Globalize-based date formatting, but uses dayjs under the
hood.
| Param | Type | Description |
| ------ | ------------------- | ---------------------- |
| column | object | the date column object |
---
Removes all html tags and decodes html entities like
| Param | Type |
| ----- | ------------------- |
| input | string |
---
defines colors for the various chart elements like axis text, gridlines,
bar background etc. based on the theme background color, and some other optional theme parameters
Returns: \* - -- object with color definitions and blendColor function
| Param | Type | Description |
| ----- | --------------- | ------------------------ |
| theme | \* | - theme data for a chart |
Example
`js`
// returns {"tickText":{"secondary":"#9d9d9d","primary":"#d9d9d9"},"series":"#f1f1f1","value":"#d9d9d9","axis":"#f1f1f1","gridline":"#707070","fallbackBaseColor":"#f1f1f1", blendColor: function}
defaultColors({ colors: { background: '#333333' } });
Example
`js`
// returns {"tickText":{"secondary":"#ffffff","primary":"#ffffff"},"series":"#ffffff","value":"#fef2e4","axis":"#ffffff","gridline":"#fedeb5","fallbackBaseColor":"#ffffff"}
defaultColors({
colors: {
bgBlendRatios: { gridline: 0.5, tickText: { primary: 0, secondary: 0 } },
chartContentBaseColor: '#ffffff',
background: '#FCB716'
}
});
---
returns the overlays column title
| Param | Type |
| ------- | ------------------- |
| vis | object |
| colName | string |
---
Promise~~_Deprecated_
Download and parse a remote JSON endpoint via DELETE. credentials
are included automatically
Use httpReq or delete instead.
| Param | Type |
| -------- | --------------------- |
| url | string |
| callback | function |
Example
`js
import { deleteJSON } from '@datawrapper/shared/fetch';
deleteJSON('http://api.example.org/chart/123').then(() => {
console.log('deleted!');
});
`
---
draws a configurable pattern into an svg pattern def, so that it can be used as a fill
| Param | Type | Description |
| ---------- | --------------- | ---------------------------------- |
| parameters | \* | - style parameters for the pattern |
---
returns true if two numeric values are close enough
| Param | Type |
| ----- | ------------------- |
| a | number |
| b | number |
Example
`js`
// returns true
equalish(0.333333, 1 / 3);
Example
`js`
// returns false
equalish(0.333, 1 / 3);
---
returns escaped HTML that can be used to display untrusted content
| Param | Type |
| ------ | ------------------- |
| unsafe | string |
---
returns the estimated width of a given text in Roboto.
this method has proven to be a good compromise between pixel-perfect
but expensive text measuring methods using canvas or getClientBoundingRect
and just multiplying the number of characters with a fixed width.
be warned that this is just a rough estimate of the text width. the
character widths will vary from typeface to typeface and may be
off quite a bit for some fonts (like monospace fonts).
| Param | Type | Description |
| -------- | ------------------- | ---------------------------------------------- |
| text | string | the text to measure |
| fontSize | number | the output font size (optional, default is 14) |
Example
`js`
import estimateTextWidth from '@datawrapper/shared/estimateTextWidth';
// or import {estimateTextWidth} from '@datawrapper/shared';
const width = estimateTextWidth('my text', 12);
---
Promise~~_Deprecated_
Download and parse a remote JSON document. Use httpReq instead
| Param | Type | Description |
| ----------- | --------------------------------------------- | ---------------------------------------------------------------- |
| url | string | |
| method | string | HTTP method, either GET, POST or PUT |
| credentials | string \| undefined | set to "include" if cookies should be passed along CORS requests |
| body | string | |
| callback | function | |
Example
`js`
import { fetchJSON } from '@datawrapper/shared/fetch';
fetchJSON('http://api.example.org', 'GET', 'include');
---
special number formatting that can deal with microtypography
and "prepend currencies" (e.g., −$1234.57)
Returns: string - - the formatted number
| Param | Type | Description |
| ----------------- | ------------------- | -------------------------------------- |
| numeral | object | Numeral.js instance |
| value | number | the number to format |
| options | object | options, see below |
| options.format | string | numeral.js compatible number format |
| options.prepend | string | string to prepend to number |
| options.append | string | string to append to number |
| options.minusChar | string | custom character to use for minus |
| options.multiply | number | multiply number before applying format |
Example
`js`
// returns '1234.57'
formatNumber(numeral, 1234.567);
Example
`js`
// returns '−$1234.57'
formatNumber(numeral, -1234.567, { prepend: '$' });
---
Safely access object properties without throwing nasty
cannot access X of undefined errors if a property along the
way doesn't exist.
Returns: the value
| Param | Type | Description |
| --------- | -------------------------------------------------------- | ------------------------------------------------------------------ |
| object | | the object which properties you want to acccess |
| key | String \| Array.<String> | path to the property as a dot-separated string or array of strings |
| \_default | \* | the fallback value to be returned if key doesn't exist |
Example
`js`
import get from '@datawrapper/shared/get';
const someObject = { key: { list: ['a', 'b', 'c'] } };
get(someObject, 'key.list[2]'); // returns 'c'
get(someObject, 'missing.key'); // returns undefined
get(someObject, 'missing.key', false); // returns false
---
Promise~~_Deprecated_
Download and parse a JSON document via GET.
Use httpReq or get instead.
| Param | Type | Description |
| ----------- | --------------------------------------------- | ------------------------------------------------- |
| url | string | |
| credentials | string \| undefined | optional, set to undefined to disable credentials |
| callback | function | |
Example
`js`
import { getJSON } from '@datawrapper/shared/fetch';
// use it callback style
getJSON('http://api.example.org', 'include', function (data) {
console.log(data);
});
// or promise-style
getJSON('http://api.example.org').then(data => {
console.log(data);
});
---
A delayed highlight setter
| Param | Type | Description |
| ------ | --------------------- | ------------------------------------------------------------------------------------------ |
| action | function | the highlight action callback |
| delay | int | how long something needs to be highlighted before the highlight triggers (in milliseconds) |
Example
`js
import { highlightTimer } from '@datawrapper/shared';
const myTimer = highlightTimer(value => {
if (value) {
selection.style('opacity', d => (d === value ? 1 : 0.3));
} else {
selection.style('opacity', 1);
}
});
lines.on('mouseenter', d => myTimer.set(d));
chart.on('mouseleave', myTimer.clear);
`
---
The response body is automatically parsed according
to the response content type.
Returns: Promise - promise of parsed response body or raw response
| Param | Type | Description |
| --------------- | -------------------- | ------------------------------------------------------------------ |
| path | string | the url path that gets appended to baseUrl |
| options.body | object | raw body to be send with req |
| options.payload | object | raw JSON payload to be send with req (will overwrite options.body) |
| options.raw | boolean | disable parsing of response body, returns raw response |
| options.baseUrl | string | base for url, defaults to dw api domain |
| options | \* | see documentation for window.fetch for additional options |
Example
`js/v3/charts/${chartId}/data
import httpReq from '@datawrapper/shared/httpReq';
let res = await httpReq('/v3/charts', {
method: 'post',
payload: {
title: 'My new chart'
}
});
import { post } from '@datawrapper/shared/httpReq';
res = await post('/v3/charts', {
payload: {
title: 'My new chart'
}
});
// send raw csv
await httpReq.put(, {`
body: csvData,
headers: {
'Content-Type': 'text/csv'
}
});
- httpReq(path, options) ⇒ Promise
- .get()
- .patch()
- .put()
- .post()
- .head()
- .delete()
---
#### httpReq.delete()
Like httpReq but with fixed http method DELETE
See: httpReq
---
#### httpReq.get()
Like httpReq but with fixed http method GET
See: httpReq
---
#### httpReq.head()
Like httpReq but with fixed http method HEAD
See: httpReq
---
#### httpReq.patch()
Like httpReq but with fixed http method PATCH
See: httpReq
---
#### httpReq.post()
Like httpReq but with fixed http method POST
See: httpReq
---
#### httpReq.put()
Like httpReq but with fixed http method PUT
See: httpReq
---
checks if a given string is a valid URL
| Param | Type |
| ----- | ------------------- |
| input | string |
---
Performs one-dimensional k-means clustering on an array of
numbers. Useful for finding n groups of "similar values".
Returns: array.<Array.<number>> - - array of clusters
| Param | Type | Description |
| ---------- | --------------------------------- | ------------------------- |
| values | Array.<number> | sorted array of numbers |
| numCluster | number | the desired cluster count |
Example
`js
import kMeans from '@datawrapper/shared/kMeans';
const values = [1, 1.1, 1.2, 2.1, 3, 3.1, 3.2, 3.3, 7, 7.1, 10];
// returns [[1, 1.1, 1.2, 2.1], [3, 3.1, 3.2, 3.3], [7, 7.1, 10]]
kMeans(values, 3);
`
---
injects a