import populateTemplate from '../utils/populateTemplate';
/**
* Data Tracker Widget
*
* @module DataTracker
* @prop {string} selectors - DOM selector
* @prop {string} states - CSS class names for different states
*/
const DataTracker = {
selectors: {
main: '.c-dataTracker',
title: '.c-dataTracker__title',
lastUpdated: '.c-dataTracker__lastUpdated',
entries: '.c-dataTracker__entries',
source: '.c-dataTracker__source',
footnote: '.c-dataTracker__footnote',
},
states: {
loading: 'c-dataTracker--loading',
hidden: 'is-hidden',
entry: 'c-dataTracker__entry',
},
templates: {
entry: `
<span class="c-dataTracker__label">{{label}}</span>
<span class="c-dataTracker__value">{{value}}</span>
<span class="c-dataTracker__diff">{{diff}}</span>
`,
chart: `
<svg class="c-dataTracker__svg" width="{{width}}" height="{{height}}">
<defs>
<marker id="datatracker-{{metric}}" viewBox="0 0 10 10"
refX="3" refY="3" markerUnits="strokeWidth" markerWidth="3"
markerHeight="3">
<circle class="c-dataTracker__marker" cx="5" cy="5" r="5"></circle>
</marker>
</defs>
<path class="c-dataTracker__line" d={{path}} marker-end="url(#datatracker-{{metric}})"></path>
</svg>
<div class="c-dataTracker__pctChange">Daily {{label}} {{direction}} {{change}}% over past 14 days</div>
`,
chartFooter: `
<div class="c-dataTracker__pctChange">Daily {{label}} {{direction}} {{change}}% over past 14 days</div>
`,
},
/**
* Get data for data tracker to display
*
* @method init
*/
init() {
const $targets = document.querySelectorAll( this.selectors.main );
[].forEach.call( $targets, ( $target, index ) => {
if ( $target.dataset.dataTrackerType ) {
const id = `c-dataTracker${index}`;
$target.id = id; // eslint-disable-line no-param-reassign
$target.classList.add( this.states.loading );
$target.classList.remove( this.states.hidden );
this.getData( $target,
$target.dataset.dataTrackerType,
$target.dataset.dataTrackerParams );
}
});
},
/**
* Get data for specified ajax request type and params
*
* @method getData
* @param {element} $target
* @param {string} type
* @param {object} params
*/
getData( $target, type, params ) {
fetch( `/gnca-ajax-redesign/${type}/${params}` )
.then( response => response.text() )
.then( ( content ) => {
const data = JSON.parse( content );
this.populate( $target, data );
$target.classList.remove( this.states.loading );
});
},
/**
* Populate data into target element
*
* @method populate
* @param {element} $target
* @param {object} data
*/
populate( $target, data ) {
const $title = $target.querySelector( this.selectors.title );
$title.textContent = data.title;
const $lastUpdated = $target.querySelector( this.selectors.lastUpdated );
$lastUpdated.textContent = `Last Updated: ${data.lastUpdated}`;
const $source = $target.querySelector( this.selectors.source );
$source.textContent = `Source: ${data.attribution}`;
const $footnote = $target.querySelector( this.selectors.footnote );
$footnote.innerHTML = data.footnote;
const $entries = $target.querySelector( this.selectors.entries );
// Populate data entries
[].forEach.call( data.entry, ( entry ) => {
const $entry = document.createElement( 'div' );
let direction = '';
let prefix = '';
let $chart = false;
if ( 0 !== entry.diff ) {
prefix = entry.diff > 0 ? '+' : '-';
direction = entry.diff > 0 ? 'growth' : 'decline';
entry.diff = `(${entry.streak} ${prefix}${Math.abs( entry.diff )})`; // eslint-disable-line no-param-reassign
} else {
entry.diff = ''; // eslint-disable-line no-param-reassign
}
if ( false !== entry.trend
&& false !== entry.trend.path
&& false !== entry.trend.theta
&& false !== entry.trend.width
&& false !== entry.trend.height ) {
const trendData = entry.trend;
trendData.metric = entry.metric;
trendData.label = entry.label.toLowerCase();
$chart = this.draw_trend( trendData, entry.showChart );
}
// Apply custom css
$entry.classList.add( this.states.entry );
$entry.classList.add( `${this.states.entry}--${entry.metric}` );
if ( direction ) {
$entry.classList.add( `${this.states.entry}--${direction}` );
}
$entry.innerHTML = populateTemplate( this.templates.entry, entry, true );
if ( $chart ) {
$entry.appendChild( $chart );
}
$entries.appendChild( $entry );
});
},
/**
* Draw trendline SVG chart
*
* @method draw_trend
* @param {object} trendData - data to populate the chart template
* @param {boolean} showChart - whether to show the chart or just the summary text
* @return {element} And SVG chart object with trend data populated
*/
draw_trend( trendData, showChart ) {
const $chart = document.createElement( 'div' );
$chart.classList.add( 'c-dataTracker__trend' );
if ( showChart ) {
$chart.innerHTML = populateTemplate( this.templates.chart, trendData );
} else {
$chart.innerHTML = populateTemplate( this.templates.chartFooter, trendData );
}
return $chart;
},
};
export default DataTracker;