New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

cfpb-chart-builder

Package Overview
Dependencies
Maintainers
3
Versions
61
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cfpb-chart-builder - npm Package Compare versions

Comparing version 0.0.9 to 1.0.0

.travis.yml

34

package.json
{
"name": "cfpb-chart-builder",
"version": "0.0.9",
"description": "A package to build charts to CFPB style",
"main": "index.js",
"version": "1.0.0",
"description": "Charts for the Consumer Financial Protection Bureau",
"main": "src/index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
"build": "npm run js && npm run css && npm run minify",
"js": "browserify src/index.js -o dist/cfpb-chart-builder.js",
"css": "lessc src/styles.less dist/cfpb-chart-builder.css",
"minify": "browserify src/index.js -t uglifyify | uglifyjs -c -o dist/cfpb-chart-builder.min.js && lessc --clean-css src/styles.less dist/cfpb-chart-builder.min.css",
"watch": "watchify src/index.js -o dist/cfpb-chart-builder.js -v -d",
"start": "http-server . -p 8088",
"browser-tests": "CI_ENVIRONMENT=true node test/browser-tests.js",
"test": "npm run build && npm run browser-tests",
"preinstall": "git config merge.ours.driver true"
},

@@ -13,3 +21,3 @@ "repository": {

},
"author": "",
"author": "Consumer Financial Protection Bureau",
"license": "CC0-1.0",

@@ -21,4 +29,18 @@ "bugs": {

"dependencies": {
"d3": "4.2.7"
"highcharts": "5.0.7",
"papaparse": "4.1.2",
"xdr": "^0.5.3"
},
"devDependencies": {
"browserify": "^13.3.0",
"http-server": "^0.9.0",
"less": "^2.7.2",
"less-plugin-clean-css": "^1.5.1",
"request": "^2.79.0",
"sauce-connect-launcher": "^1.2.0",
"static-server": "^2.0.4",
"uglify-js": "^2.7.5",
"uglifyify": "^3.0.4",
"watchify": "^3.8.0"
}
}

94

README.md

@@ -1,60 +0,69 @@

# CFPB Chart Builder
# CFPB Chart Builder [![Build Status](https://travis-ci.org/cfpb/cfpb-chart-builder.svg?branch=master)](https://travis-ci.org/cfpb/cfpb-chart-builder)
This package builds charts to CFPB styles.
[![Sauce Test Status](https://saucelabs.com/browser-matrix/cct-sauce.svg)](https://saucelabs.com/u/cct-sauce)
Charts for the [Consumer Financial Protection Bureau](https://cfpb.github.io/).
**Screenshot**: Example chart screenshots coming soon.
## Usage
![](https://raw.githubusercontent.com/cfpb/open-source-project-template/master/screenshot.png)
Add a `div` with a class of `cfpb-chart` and the following data attributes to your page:
```
<div class="cfpb-chart"
data-chart-type="line"
data-chart-title="Number of Originations (in millions)"
data-chart-description="Auto loan originations decreased in 2016."
data-chart-color="green"
data-chart-metadata="Number of Loans"
data-chart-source="consumer-credit-trends/auto-loans.csv">
Auto loan originations decreased in 2016.
</div>
```
## Dependencies
Add this library to your page:
Describe any dependencies that must be installed for this software to work.
This includes programming languages, databases or other storage mechanisms, build tools, frameworks, and so forth.
If specific versions of other software are required, or known not to work, call that out.
```
<script type="text/javascript" src="dist/cfpb-chart-builder.min.js"></script>
```
## Installation
It'll generate a chart for you:
Detailed instructions on how to install, configure, and get the project running.
This should be frequently tested to ensure reliability. Alternatively, link to
a separate [INSTALL](INSTALL.md) document.
![Screenshot](screenshot.png)
It can also do column charts and maps.
## Configuration
If the software is configurable, describe it in detail, either here or in other documentation to which you link.
TBD
## Usage
## Contributing
Show users how to use the software.
Be specific.
Use appropriate formatting when showing code snippets.
1. Clone this repository.
1. `npm install`
1. `npm run watch` to bundle the JS and output it to `dist/`.
1. `npm start` to serve the test directory.
1. Open `http://localhost:8088/test` in a browser to see the test page with a dozen random charts on it.
1. Whenever a JS file in `src/` is edited, the JS will be rebundled. Refresh the page.
## How to test the software
Bonus: Visit `http://localhost:8088/test/all-charts.html` to see *all* the CCT charts.
If the software includes automated tests, detail how to run those tests.
Helpful commands:
## Known issues
- `npm run build` - Bundle and minify all assets into the `dist/` directory.
- `npm run watch` - Bundle JS files whenever they're changed.
- `npm start` - Start a local server to demo the charts at `http://localhost:8088/test`.
- `npm test` - Run the test charts through Sauce Labs.
Document any known significant shortcomings with the software.
## Testing
## Getting help
Sauce Labs is used to test the charts in IE 8 through 10.
An [Open Sauce](https://saucelabs.com/open-source) account has been created for this repo.
The `curl` command below will grab the credentials for you.
Instruct users how to get help with this software; this might include links to an issue tracker, wiki, mailing list, etc.
1. `curl -o test/config.json https://GHE/raw/gist/contolini/504ea71f6a19c74090c7a150aff60421/raw/b3850abab5466af62406d3f0d7a3da05f7f92124/config.json`
1. `npm test`
**Example**
The browser tests will take several minutes to run.
The test script simply loads `http://localhost:8088/test` in IE VMs and reports any `window` errors.
If you have questions, concerns, bug reports, etc, please file an issue in this repository's Issue Tracker.
## Getting involved
This section should detail why people should get involved and describe key areas you are
currently focusing on; e.g., trying to get feedback on features, fixing certain bugs, building
important pieces, etc.
General instructions on _how_ to contribute should be stated with a link to [CONTRIBUTING](CONTRIBUTING.md).
----
## Open source licensing info

@@ -64,12 +73,1 @@ 1. [TERMS](TERMS.md)

3. [CFPB Source Code Policy](https://github.com/cfpb/source-code-policy/)
----
## Credits and references
1. These charts are generated using [d3.js](d3js.org).
1. The following Mike Bostock d3 examples were instrumental to the development of this code:
- [Line chart](http://bl.ocks.org/mbostock/3883245) example using the latest v4 of d3
- [Bar chart](https://bl.ocks.org/d3noob/bdf28027e0ce70bd132edc64f1dd7ea4) example using v4
- [State grid](http://bl.ocks.org/mbostock/29cc3cc4078091fd2115)
'use strict';
var d3 = require( 'd3' );
var CFPBChart = require( './CFPBChart' );
var Highcharts = require( 'highcharts/highstock' );
BarChart.prototype = new CFPBChart();
BarChart.prototype.constructor = BarChart;
Highcharts.setOptions({
lang: {
rangeSelectorZoom: '',
thousandsSep: ','
}
});
var yAxisUnit;
var months = [ 'Jan', 'Feb', 'Mar', 'Apr', 'May', 'June',
'July', 'Aug', 'Sept', 'Oct', 'Nov', 'Dec' ];
function BarChart( properties ) {
this.selector = properties.selector;
this.data = properties.data;
this.type = 'BarChart';
this.labels = properties.labels || {};
yAxisUnit = properties.yAxisUnit || '';
function BarChart( props ) {
// var i = props.data.categories.length - 7,
// projected = props.data.categories[i],
// projDate = new Date( projected ),
// projDateText = months[projDate.getMonth()] + ' ' + projDate.getFullYear();
this.drawGraph = function( options ) {
var data = this.data;
var projDateText = 'April 2016';
// variables from options
var baseWidth = options.baseWidth || 200,
baseHeight = options.baseHeight || 100,
paddingDecimal = options.paddingDecimal || .1,
margin = options.margin || {top: 20, right: 20, bottom: 20, left: 20};
var options = {
title: {
text: props.title
},
description: props.description,
credits: false,
rangeSelector : {
inputEnabled:false
},
chart: {
width: 650,
height: 500
},
legend: {
enabled: false
},
plotOptions: {
column: {
pointPadding: 0,
borderWidth: 1,
groupPadding: 0,
shadow: false,
grouping: false
}
},
xAxis: {
tickInterval: 12,
// labels: {
// autoRotation: false,
// formatter: function() {
// var date = new Date( this.value );
// return months[ date.getMonth() ] + ' ' + date.getFullYear();
// },
// style: {
// 'color': '#75787b',
// 'font-size': '16px'
// },
// y: 30
// }
// plotLines: [{
// className: 'bar-chart_projected-line',
// color: '#75787b',
// label: {
// align: 'left',
// rotation: 0,
// style: {
// 'color': '#75787b',
// 'font-size': '16px'
// },
// text: 'Values after ' + projDateText + ' are projected',
// textAlign: 'right',
// // useHTML: true,
// y: -30
// },
// width: 2,
// value: props.data.length - 6.5
// }]
},
yAxis: {
opposite: false,
title: {
text: 'Year-over-year change (%)',
style: {
'color': '#75787b',
'font-size': '16px'
}
}
},
navigator: {
maskFill: 'rgba(0, 0, 0, 0.05)',
handles: {
backgroundColor: '#fff',
borderColor: '#000'
},
series: {
color: '#addc91',
lineWidth: 2
}
},
series: [ {
type: 'column',
data: props.data,
name: 'Year-over-year change (%)',
tooltip: {
valueDecimals: 2
},
zoneAxis: 'x',
zones: [
{
color: '#2CB34A',
value: Date.UTC( 2016, 4, 1 )
},
{
color: '#addc91',
}
]
} ]
}
// calculated variables
var width = baseWidth - margin.left - margin.right,
height = baseHeight - margin.top - margin.bottom;
// @todo - add time interval handling
var x = d3.scaleBand()
.range( [ 0, width ] )
.padding( paddingDecimal );
var y = d3.scaleLinear()
.range( [ height, 0 ] );
var svg = d3.select( this.selector )
.append( 'svg' )
.attr( 'width', width + margin.left + margin.right)
.attr( 'height', height + margin.top + margin.bottom)
.append( 'g' )
.attr( 'transform',
'translate( ' + margin.left + ',' + margin.top + ' )' );
data.forEach( function( d ) {
d.label = d.label;
d.amount = +d.amount;
} );
var ymin = d3.min( data, function(d) { return d.amount } ),
ymax = d3.max( data, function(d) { return d.amount; } );
// If the graph displays values below zero, find new bounds by
// rounding to the absolute greatest factor of 10 and set that
// as the min and max
if ( ymin < 0 ) {
var top = Math.ceil( Math.abs( ymax ) / 10 ) * 10,
bottom = Math.ceil( Math.abs( ymin ) / 10 ) * 10,
max = Math.max( top, bottom );
ymax = max;
ymin = -1 * max;
}
x.domain( data.map( function( d ) { return d.label; } ) );
y.domain( [ Math.min( 0, ymin ), ymax ] );
// x-axis
var xAxis = svg.append( 'g' )
.attr( 'class', 'x axis' )
.attr( 'transform', 'translate( 0,' + Math.max( y( 0 ), y( ymin ) ) + ')' )
.call(
d3.axisBottom( x )
.tickValues( x.domain().filter(
function( d, i ) {
return !( i % 12 );
} )
)
.tickFormat( function( d, i ) { return ' '} )
);
// @todo - this must be customizable!
xAxis.selectAll( 'g' )
.append( 'text' )
.style( 'text-anchor', 'middle' )
.attr( 'y', 25 )
.text( function( d ) { return 'Jan' } )
.attr( 'width', width / 15 );
xAxis.selectAll( 'g' )
.append( 'text' )
.style( 'text-anchor', 'middle' )
.attr( 'y', 45 )
.text( function( d ) { return d.substr( 0, 4 ) } )
.attr( 'width', width / 15 );
// Determine y-axis tick interval
var yTickInterval = 10;
if ( ymax > 130 ) {
yTickInterval = 20;
}
// y-axis
svg.append( 'g' )
.attr( 'class', 'y axis')
.call(
d3.axisLeft( y )
.ticks( ( ymax - ymin ) / yTickInterval )
.tickSize( -width )
.tickFormat( function( d ) {
if ( ymax <= 40 || d % ( 2 * yTickInterval ) === 0 ) {
return d + yAxisUnit;
}
} )
)
.selectAll( 'text' )
.attr( 'dy', '.25em' );
// y-axis label
svg.append( 'text' )
.attr( 'transform', 'rotate(-90)' )
.attr( 'text-anchor', 'middle' )
.attr( 'x', -1 * ( height + ymin ) / 2 )
.attr( 'y', -50 )
.attr( 'class', 'y-axis-label' )
.style( 'font-size', '1em' )
.text( this.labels.yAxisLabel || '' );
svg.selectAll( 'bar' )
.data( data )
.enter().append( 'rect' )
.attr( 'class', 'bar' )
.attr( 'x', function(d) { return x( d.label ); })
.attr( 'width' , x.bandwidth() )
.attr( 'y', function( d ) { return y( Math.max( 0, d.amount ) ); })
.attr( 'height',
function( d ) {
return Math.abs( y( d.amount ) - y( 0 ) );
} )
.attr( 'fill', '#2CB34A' );
return {
chart: svg,
x: x,
y: y
}
}
Highcharts.stockChart( props.selector, options);
}
module.exports = BarChart;
'use strict';
var d3 = require( 'd3' );
var CFPBChart = require( './CFPBChart' );
var getMonth = d3.utcFormat( '%b' );
var getYear = d3.utcFormat( '%Y' );
var Highcharts = require( 'highcharts/highstock' );
LineChart.prototype = new CFPBChart();
LineChart.prototype.constructor = LineChart;
var lineSets = [],
rawData = [],
yAxisTickFactor,
yAxisLabel,
yAxisUnit,
labels = {};
function sortByDateAscending( a, b ) {
return a.x - b.x;
}
function findNewMax( max ) {
var newMax = 0;
if ( max < 50 ) {
newMax = 5 * Math.ceil( max / 5 );
} else if ( max > 100 && max < 500 ) {
newMax = 50 * Math.ceil( max / 50 );
} else {
var pow = max.toString().length - 1;
newMax = Math.pow( 10, pow ) * Math.ceil( max / Math.pow( 10, pow ) );
Highcharts.setOptions({
lang: {
rangeSelectorZoom: '',
thousandsSep: ','
}
});
return newMax;
}
function tickThinker( ymin, ymax, factor ) {
var acceptable = [ .5, .25, .2, .1, .05, .025, .01,
1, 2, 5, 10, 15, 20, 25, 50, 100, 200 ];
// var divisors = [ .5, .25, .2, .1, .05, .025, .01 ];
var range = Math.ceil( ymax - ymin );
var count = Math.floor( range / factor );
var coeff = range / ( factor * count );
for (var count = 10; count >= 5; count-- ) {
coeff = range / ( factor * count );
if ( range % count === 0 && acceptable.indexOf( coeff ) !== -1 ) {
break;
}
/**
* _getTickValue - Convert the data point's unit to M or B.
*
* @param {int} value Data point's value
* @return {int} Data point's value over million or billion.
*/
function _getTickValue( value ) {
// If it's 0 or borked data gets passed in, return it.
if ( !value ) {
return value;
}
var array = [];
for ( var x = 0; x <= count; x++ ) {
array.push( x * coeff * factor );
if ( value % 1000000000 < value ) {
return value / 1000000000 + 'B';
}
return {
valueArray: array,
coefficient: coeff
};
return value / 1000000 + 'M';
}
function labelToString( number, multiplier ) {
var label = number.toString();
if ( multiplier < 1 ) {
if ( label.length > 4 ) {
label = label.substr( 0, 4 );
if ( label.substr( 3, 1 ) === '0' ) {
label = label.substr( 0, 3 );
function LineChart( props ) {
var options = {
title: {
text: props.title
},
description: props.description,
credits: false,
rangeSelector : {
inputEnabled:false
},
plotOptions: {
series: {
states: {
hover: {
enabled: false
}
}
}
}
} else if ( label.indexOf('.') !== -1 ) {
var decPart = label.split('.')[1];
var intPart = label.split('.')[0];
decPart = decPart.substr( 0, 1 )
label = intPart + '.' + decPart;
},
navigator: {
maskFill: 'rgba(0, 0, 0, 0.05)',
handles: {
backgroundColor: '#fff',
borderColor: '#000'
},
series: {
color: '#addc91',
lineWidth: 2
}
},
chart: {
width: 650,
height: 500
},
xAxis: {
startOnTick: true,
type: 'datetime',
dateTimeLabelFormats: {
day: '%b %Y'
},
tickInterval: 60 * 60 * 24 * 365 * 1000 // one year in ms
},
yAxis: {
opposite: false,
className: 'axis-label',
title: {
text: props.title
},
labels: {
formatter: function () {
return _getTickValue( this.value );
}
}
},
series: [
{
name: 'Unadjusted',
data: props.data.unadjusted,
color: '#addc91',
lineWidth: 3,
tooltip: {
valueDecimals: 0
}
},
{
name: 'Seasonally Adjusted',
data: props.data.adjusted,
color: '#20aa3f',
lineWidth: 3,
tooltip: {
valueDecimals: 0
}
}
]
}
return label;
}
Highcharts.stockChart( props.selector, options );
function LineChart( properties ) {
this.selector = properties.selector;
this.type = 'LineChart';
this.data = {};
rawData = properties.data;
labels = properties.labels || {};
lineSets = properties.lineSets || undefined;
yAxisTickFactor = properties.yAxisTickFactor || 1;
yAxisLabel = properties.labels.yAxisLabel || '';
yAxisUnit = properties.labels.yAxisUnit || '';
this.drawGraph = function( options ) {
var data = this.data = this.getDataBySets();
// variables from options
var baseWidth = options.baseWidth || 200,
baseHeight = options.baseHeight || 100,
paddingDecimal = options.paddingDecimal || .1,
margin = options.margin || {top: 20, right: 20, bottom: 20, left: 20};
// calculated variables
var width = baseWidth - margin.left - margin.right,
height = baseHeight - margin.top - margin.bottom;
// @todo: the x-axis is not always time intervals
var x = d3.scaleTime()
.range( [ 0, width ] );
var y = d3.scaleLinear()
.range( [ height, 0 ] );
var xmin = d3.min( rawData, function(d) { return d.x } ),
xmax = d3.max( rawData, function(d) { return d.x; } ),
ymin = d3.min( rawData, function(d) { return d.y } ),
ymax = d3.max( rawData, function(d) { return d.y; } );
// ymin should be 0 or less
ymin = Math.min( ymin, 0 );
// ymax should be "niced" (made into a nice round number)
ymax = findNewMax( ymax );
// check if the yAxisTickFactor is ideal
var bestTickFactors = tickThinker( ymin, ymax, yAxisTickFactor );
var tickMultiplier = bestTickFactors.coefficient;
var tickValueArray = bestTickFactors.valueArray;
x.domain( [ xmin, xmax ] );
y.domain( [ ymin, ymax ] );
var svg = d3.select( this.selector )
.append( 'svg' )
.attr( 'width', width + margin.left + margin.right)
.attr( 'height', height + margin.top + margin.bottom)
.append( 'g' )
.attr( 'transform',
'translate( ' + margin.left + ',' + margin.top + ' )' );
// line function
var line = d3.line()
.x( function( d ) {
return x( d.x );
} )
.y( function( d ) {
return Math.floor( y( d.y ) );
} );
// Add the X Axis
var xAxis = svg.append('g')
.classed('axis axis__x', true)
.attr('transform', 'translate(0,' + height + ')')
.call( d3.axisBottom( x )
.tickFormat( function( d ) { return ''; } )
);
xAxis.selectAll( 'g' )
.append( 'text' )
.style( 'text-anchor', 'middle' )
.attr( 'y', 25 )
.text( function( d) { return getMonth( d ); } )
.attr( 'width', width / 15 );
xAxis.selectAll( 'g' )
.append( 'text' )
.style( 'text-anchor', 'middle' )
.attr( 'y', 45 )
.text( function( d ) { return getYear( d ); } )
.attr( 'width', width / 15 );
// Add the Y Axis
var yAxis = d3.axisLeft( y );
yAxis.tickValues( tickValueArray )
yAxis.tickFormat( function( d ) {
var label = d / yAxisTickFactor;
label = labelToString( label, tickMultiplier );
return label + yAxisUnit;
} )
yAxis.tickSize( -width );
svg.append( 'g' )
.classed( 'axis axis__y', true )
.call( yAxis );
// Iterate all lines:
for ( var key in data ) {
svg.append( 'path' )
.attr( 'd', line( data[key] ) )
.classed( lineSets[key].classes, true);
}
// text label for the y axis
svg.append( 'text' )
.classed( 'axis-label' , true)
.attr( 'transform', 'rotate(-90)' )
.attr( 'text-anchor', 'end' )
.attr( 'x', -20 )
.attr( 'y', -60 )
.text( labels.yAxisLabel );
// add the legend
var legendPositions = [
[ -70, -65 ],
[ -70, -45 ],
[ width / 4, -55 ],
[ width / 4, -35 ]
];
for ( var key in lineSets ) {
if ( lineSets[key].showInLegend !== false ) {
var pos = legendPositions[0];
svg.append( 'line' )
.classed( lineSets[key].classes, true)
.style( 'stroke-width', '10px' )
.attr( 'x1', pos[0] )
.attr( 'x2', pos[0] + 10 )
.attr( 'y1', pos[1] )
.attr( 'y2', pos[1] );
svg.append( 'text' )
.attr( 'text-anchor', 'start' )
.attr( 'x', pos[0] + 20 )
.attr( 'y', pos[1] + 5 )
.attr( 'class', 'gray-text' )
.text( lineSets[key].legendLabel || key );
// Drop the first position so the next entry will
// use the next position, etc
legendPositions = legendPositions.splice( 1 );
}
}
return {
chart: svg,
x: x,
y: y
};
};
this.getDataBySets = function() {
var obj = {};
// create an object property for each set
for ( var key in lineSets ) {
obj[key] = [];
}
for (var x = 0; x < rawData.length; x++ ) {
obj[rawData[x].set].push( rawData[x] );
}
for ( var key in lineSets ) {
obj[key] = obj[key].sort( sortByDateAscending );
}
return obj;
}
}
module.exports = LineChart;
'use strict';
var d3 = require( 'd3' );
var CFPBChart = require( './CFPBChart' );
var stateCoords = require( '../utils/state-tile-coords' );
var fillByValue = require( '../utils/fill-by-value' );
var valueGrid,
legendLabels;
var Highcharts = require('highcharts/highmaps');
TileMap.prototype = new CFPBChart();
TileMap.prototype.constructor = TileMap;
Highcharts.setOptions({
lang: {
thousandsSep: ','
}
});
function TileMap( properties ) {
this.selector = properties.selector;
this.data = properties.data;
this.type = 'TileMap';
valueGrid = properties.valueGrid || [];
legendLabels = properties.legendLabels || [];
function TileMap(props) {
var props = props || {};
this.drawGraph = function( options ) {
var data = this.data;
var options = {
title: {
text: props.title
},
chart: {
width: 650,
height: 500
},
description: props.description,
credits: false,
legend: {
enabled: false
},
tooltip: {
borderColor: 'rgb(117, 120, 123)',
formatter: function() {
return this.point.tooltip;
}
},
series: [{
type: 'map',
borderColor: 'rgb(117, 120, 123)',
states: {
hover: {
brightness: 0,
borderColor: '#000'
}
},
// borderWidth: 0.2,
dataLabels: {
enabled: true,
color: '#FFFFFF',
format: '{point.name}<br />{point.value}%',
style: ''
},
name: props.title,
data: props.data
}]
};
// variables from options
var baseWidth = options.baseWidth || 200,
baseHeight = options.baseHeight || 100,
paddingDecimal = options.paddingDecimal || .1,
margin = options.margin || {top: 20, right: 20, bottom: 20, left: 20};
// calculated variables
var width = baseWidth - margin.left - margin.right,
height = baseHeight - margin.top - margin.bottom,
tileGutterWidth = Math.floor( width / 11 ),
tileWidth = Math.floor( tileGutterWidth - 2 - tileGutterWidth / 20 );
var svg = d3.select( this.selector )
.append( 'svg' )
.attr( 'width', width + margin.left + margin.right)
.attr( 'height', height + margin.top + margin.bottom)
.append( 'g' )
.classed( 'tiles' , true )
.attr( 'transform',
'translate( ' + margin.left + ',' + margin.top + ' )' );
// Add legend group
svg.append( 'g' )
.classed( 'legend' , true );
var legend = svg.selectAll('.legend');
var tiles = svg.selectAll( '.tiles' )
.data( data )
.enter();
tiles.append( 'rect' )
.filter( function( d ) { return stateCoords( d.state ) !== false; } )
.attr( 'x', function( d ) {
return stateCoords( d.state )[0] * tileGutterWidth;
} )
.attr( 'y', function( d ) {
return stateCoords(d.state)[1] * tileGutterWidth + 60;
} )
.attr( 'width', tileWidth )
.attr( 'height', tileWidth )
.style( 'fill', function( d ) {
return fillByValue( d.value, valueGrid )
} )
.style( 'stroke', '#75787B');
tiles.append( 'text' )
.filter( function( d ) { return stateCoords( d.state ) !== false; } )
.attr( 'x', function( d ) {
var x = stateCoords(d.state)[0] * tileGutterWidth;
x += .5 * tileWidth;
return x;
} )
.attr( 'y', function( d ) {
var y = stateCoords(d.state)[1] * tileGutterWidth + 60;
y += tileWidth * .4;
return y;
} )
.attr( 'width', tileWidth )
.attr( 'height', tileWidth )
.attr( 'class', 'state-abbreviation' )
.style( 'font-size', tileWidth * .25 + 'px' )
.style( 'text-anchor', 'middle' )
.text( function( d ) { return d.state; } );
tiles.append( 'text' )
.filter( function( d ) { return stateCoords( d.state ) !== false; } )
.attr( 'x', function( d ) {
var x = stateCoords(d.state)[0] * tileGutterWidth;
x += .5 * tileWidth;
return x;
} )
.attr( 'y', function( d ) {
var y = stateCoords(d.state)[1] * tileGutterWidth + 60;
y += tileWidth * .8;
return y;
} )
.attr( 'width', tileWidth )
.attr( 'height', tileWidth )
.style( 'font-size', tileWidth * .25 + 'px' )
.style( 'text-anchor', 'middle' )
.text( function( d ) {
var val = Math.round( d.value * 100 );
return val + '%';
} );
// draw the legend, rectangles
for ( var x = 0; x < valueGrid.length; x++ ) {
legend.append( 'rect' )
.attr( 'x', x * tileWidth + 15 )
.attr( 'y', 0 )
.attr( 'width', tileWidth )
.attr( 'height', 10 )
.attr( 'fill', valueGrid[x].fillColor )
.style( 'stroke', '#75787B');
}
// draw the legend, text labels
for ( var x = 0; x < legendLabels.length; x++ ) {
legend.append( 'text' )
.attr( 'x', x * tileWidth + 15 )
.attr( 'y', 20 + tileWidth * .125 )
.attr( 'width', tileWidth )
.attr( 'height', 30 )
.style( 'font-size', tileWidth * .25 + 'px' )
.style( 'text-anchor', 'middle' )
.style( 'fill', '#75787B')
.text( legendLabels[x] )
}
return svg;
}
Highcharts.mapChart(props.selector, options);
}
module.exports = TileMap;

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc