@datawrapper/shared
v1.13.0-1
Published
shared functions used throughout datawrapper
Downloads
445
Readme
@datawrapper/shared
a set of shared methods that can be used throughout Datawrapper
Import single functions:
import purifyHtml from '@datawrapper/shared/purifyHtml';
Import entire package:
import shared from '@datawrapper/shared';
shared.purifyHtml();
shared.httpReq();
API reference
- __(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
- 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
__(key, scope) ⇒ string
translates 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
client-side translations must set "svelte": true
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 |
area(vertices) ⇒ number
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 |
arrayToObject(o) ⇒ object
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
console.log(arr);
[]
foo: "bar"
length: 0
<prototype>: Array []
console.log(arrayToObject(arr));
Object { foo: "bar" }
autoTickFormat(column) ⇒ string
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 |
autoTickFormatDate(range, precision) ⇒ string
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
import { autoTickFormatDate } from '@datawrapper/shared/autoTickFormat';
autoTickFormatDate([new Date(2000, 0, 1), new Date(2002, 0, 1)], 'quarter'); // 'YYYY|[Q]Q'
autoTickFormatNumber(range) ⇒ string
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
import { autoTickFormatNumber } from '@datawrapper/shared/autoTickFormat';
autoTickFormatNumber([0, 100]); // '0,0.[00]'
autoTickFormatNumber([0.2, 0.7]); // '0,0.00[00]'
clone(object) ⇒ *
Clones an object
Returns: * - - the cloned thing
| Param | Type | Description | | ------ | --------------- | ------------------------------- | | object | * | the thing that should be cloned |
colorLightness(hexColor) ⇒ number
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
import colorLightness from '@datawrapper/shared/colorLightness';
colorLightness('#ff3399'); // 57.9
columnFormatter(numeral, column, metadata, axis) ⇒ function
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 |
columnNameToVariable(name) ⇒ string
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
import columnNameToVariable from '@datawrapper/shared/columnNameToVariable';
columnNameToVariable('GDP (per cap.)'); // gdp_per_cap
combinations(input) ⇒ Array.<array>
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
// returns [['a','b'], ['a'], ['b']]
combinations(['a', 'b']);
Example
// returns [[1,2,3], [1,2], [1,3], [1], [2,3], [2], [3]]
combinations([1, 2, 3]);
dateColumnFormatter(column) ⇒ function
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 |
decodeHtml(input) ⇒ string
Removes all html tags and decodes html entities like
| Param | Type | | ----- | ------------------- | | input | string |
defaultColors(theme) ⇒ *
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
// returns {"tickText":{"secondary":"#9d9d9d","primary":"#d9d9d9"},"series":"#f1f1f1","value":"#d9d9d9","axis":"#f1f1f1","gridline":"#707070","fallbackBaseColor":"#f1f1f1", blendColor: function}
defaultColors({ colors: { background: '#333333' } });
Example
// 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'
}
});
defaultOverlayTitle(vis, colName) ⇒ string
returns the overlays column title
| Param | Type | | ------- | ------------------- | | vis | object | | colName | string |
~~deleteJSON(url, callback) ⇒ 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
import { deleteJSON } from '@datawrapper/shared/fetch';
deleteJSON('http://api.example.org/chart/123').then(() => {
console.log('deleted!');
});
drawPattern(parameters)
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 |
equalish(a, b) ⇒ boolean
returns true if two numeric values are close enough
| Param | Type | | ----- | ------------------- | | a | number | | b | number |
Example
// returns true
equalish(0.333333, 1 / 3);
Example
// returns false
equalish(0.333, 1 / 3);
escapeHtml(unsafe) ⇒ string
returns escaped HTML that can be used to display untrusted content
| Param | Type | | ------ | ------------------- | | unsafe | string |
estimateTextWidth(text, fontSize) ⇒ number
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
import estimateTextWidth from '@datawrapper/shared/estimateTextWidth';
// or import {estimateTextWidth} from '@datawrapper/shared';
const width = estimateTextWidth('my text', 12);
~~fetchJSON(url, method, credentials, body, callback) ⇒ 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
import { fetchJSON } from '@datawrapper/shared/fetch';
fetchJSON('http://api.example.org', 'GET', 'include');
formatNumber(numeral, value, options) ⇒ string
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
// returns '1234.57'
formatNumber(numeral, 1234.567);
Example
// returns '−$1234.57'
formatNumber(numeral, -1234.567, { prepend: '$' });
get(object, key, _default) ⇒
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
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
~~getJSON(url, credentials, callback) ⇒ 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
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);
});
highlightTimer(action, delay) ⇒ object
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
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);
httpReq(path, options) ⇒ Promise
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
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(`/v3/charts/${chartId}/data`, {
body: csvData,
headers: {
'Content-Type': 'text/csv'
}
});
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
isValidUrl(input) ⇒ boolean
checks if a given string is a valid URL
| Param | Type | | ----- | ------------------- | | input | string |
kMeans(values, numCluster) ⇒ array.<Array.<number>>
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
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);
loadScript(src, callback)
injects a <script>
element to the page to load a new JS script
| Param | Type | | -------- | --------------------- | | src | string | | callback | function |
Example
import { loadScript } from '@datawrapper/shared/fetch';
loadScript('/static/js/library.js', () => {
console.log('library is loaded');
});
loadStylesheet(src, callback)
injects a <link>
element to the page to load a new stylesheet
| Param | Type | | -------- | ------------------------------------------------- | | src | string | opts | | callback | function |
Example
import { loadStylesheet } from '@datawrapper/shared/fetch';
loadStylesheet('/static/css/library.css', () => {
console.log('library styles are loaded');
});
normalizeAlphaNumKey(key) ⇒ string
normalize an alphanumerical key for less-strict matching (e.g. in maps)
Returns: string - - normalized key
| Param | Type | Description | | ----- | ------------------- | ------------------ | | key | string | alphanumerical key |
normalizeNumKey(key) ⇒ number
normalize a numerical key for less-strict matching (e.g. in maps)
Returns: number - - normalized key
| Param | Type | Description | | ----- | ------------------------------------------ | ------------- | | key | string | number | numerical key |
numberColumnFormatter(numeral, config) ⇒ function
This function returns a number formatting function based on a column configuration object stored in metadata.data.column-format. The implementation is backwards-compatible with our old Globalize-based number formatting, but uses numeral under the hood.
| Param | Type | Description | | ------- | ------------------- | -------------------------------------- | | numeral | object | Numeral.js instance | | config | object | the column configuration from metadata |
observeFonts(fontsJSON, typographyJSON) ⇒ Promise
Function that returns a promise, that resolves when all fonts, specified in fontsJSON and typographyJSON have been loaded.
| Param | Type | | -------------- | ----------------------------------------- | | fontsJSON | Object | Array | | typographyJSON | Object |
opts : object
Properties
| Name | Type | Description | | ------------- | ----------------------- | ---------------------------------- | | src | string | stylesheet URL to load | | parentElement | DOMElement | DOM element to append style tag to |
~~patchJSON(url, body, callback) ⇒ Promise~~
Deprecated
| Param | Type | | -------- | --------------------- | | url | string | | body | string | | callback | function |
Example
import { patchJSON } from '@datawrapper/shared/fetch';
patchJSON(
'http://api.example.org',
JSON.stringify({
query: 'foo',
page: 12
})
);
postEvent(chartId) ⇒ function
Use this function to post event messages out of Datawrapper iframe embeds to the parent website.
| Param | Type | Description | | ------- | ------------------- | ----------------------------------------------- | | chartId | string | the chart id each message should be signed with |
Example
import genPostEvent from '@datawrapper/shared/postEvent';
const postEvent = genPostEvent(chart.get('id'));
postEvent('bar:hover', { value: 123 });
~~postJSON(url, body, callback) ⇒ Promise~~
Deprecated
Download and parse a remote JSON endpoint via POST. credentials are included automatically. Use httpReq or post instead.
| Param | Type | | -------- | --------------------- | | url | string | | body | string | | callback | function |
Example
import { postJSON } from '@datawrapper/shared/fetch';
postJSON(
'http://api.example.org',
JSON.stringify({
query: 'foo',
page: 12
})
);
purifyHtml(input, allowed) ⇒ string
Remove all non-whitelisted html tags from the given string
Returns: string - - the cleaned html output
| Param | Type | Description |
| ------- | ------------------- | ------------------------------------------------------------------------------------------- |
| input | string | dirty html input |
| allowed | string | list of allowed tags, defaults to <a><b><br><br/><i><strong><sup><sub><strike><u><em><tt>
|
~~putJSON(url, body, callback) ⇒ Promise~~
Deprecated
Download and parse a remote JSON endpoint via PUT. credentials are included automatically Use httpReq or put instead.
| Param | Type | | -------- | --------------------- | | url | string | | body | string | | callback | function |
Example
import { putJSON } from '@datawrapper/shared/fetch';
putJSON(
'http://api.example.org',
JSON.stringify({
query: 'foo',
page: 12
})
);
round(value, decimals) ⇒ number
rounds a value to a certain number of decimals
Returns: number - - rounded value
| Param | Type | Description | | -------- | ------------------- | ----------------------- | | value | number | the value to be rounded | | decimals | number | the number of decimals |
Example
import round from '@datawrapper/shared/round';
round(1.2345); // 1
round(1.2345, 2); // 1.23
round(12345, -2); // 12300
set(object, key, value) ⇒
safely set 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 | | value | * | the value to be set |
significantDimension(values, tolerance) ⇒ number
computes the significant dimension for a list of numbers That's the number of decimals to which we can round the numbers without loosing information
Returns: number - - number of significant dimensions (= the number of decimals)
| Param | Type | Description | | --------- | --------------------------------- | -------------------------------------------------- | | values | Array.<number> | list of input numbers | | tolerance | number | percent of input values that we allow to "collide" |
Example
import { significantDimension } from '@datawrapper/shared/significantDimension';
significantDimension([0, 10, 20, 30]); // -1
smartRound(values, addPrecision, tolerance) ⇒
rounds an array of numbers to the least number of decimals without loosing any information due to the rounding
Returns: the rounded values
| Param | Type | Description | | ------------ | ------------------- | ---------------------------------------------------------------------------- | | values | array | the numbers to be rounded | | addPrecision | number | force more precision (=numbers of decimals) to the rounding | | tolerance | number | the percent of uniq input values that we can tolerate to lose after rounding |
Example
import { smartRound } from '@datawrapper/shared/smartRound';
smartRound([9, 10.5714, 12.1428, 13.7142]); // [9, 11, 12, 14]
smartRound([9, 10.5714, 12.1428, 12.4142]); // [9, 10.6, 12.1, 12.4]
tailLength(value) ⇒ number
returns the length of the "tail" of a number, meaning the number of meaningful decimal places
| Param | Type | | ----- | ------------------- | | value | number |
Example
// returns 3
tailLength(3.123);
Example
// returns 2
tailLength(3.12999999);
toFixed(value) ⇒ string
Automatically converts a numeric value to a string. this is better than the default number to string conversion in JS which sometimes produces ugly strings like "3.999999998"
| Param | Type | | ----- | ------------------- | | value | number |
Example
import toFixed from '@datawrapper/shared/toFixed';
// returns '3.1'
toFixed(3.100001);
trackEvent(category, category, category, category)
tracks a custom event in Matomo
| Param | Type | Description | | -------- | ------------------------------------------ | ------------------------- | | category | string | the event category | | category | string | the event action | | category | string | the event name | | category | string | number | the event value, optional |
trackPageView(loadTime)
tracks a custom page view in Matomo. Useful for single page apps in Datawrapper, such as the locator maps UI. The page title and URL are automatically detected using the window object.
| Param | Type | Description | | -------- | ------------------- | ---------------------------------------------------- | | loadTime | number | optional page load time, has to be measured manually |
truncate(str, start, end) ⇒ string
Shorten a string by removing characters from the middle
| Param | Type | Description | | ----- | ------------------- | ------------------------------------- | | str | string | | | start | number | characters to keep at start of string | | end | number | characters to keep at end off string |
Example
import truncate from '@datawrapper/shared/truncate';
// returns 'This is a…tring'
truncate('This is a very very long string');