block by armollica 97b90b0aa19234b52117ee96dfa38d61

React Scatterplot

Full Screen

Figuring out how to make React and D3 work together.

This blog post by Tom Macwright has some good ideas. The <Axis /> component is adapted from this gist he wrote. The chart is a replication of the example found in the documentation for ggplot2’s facet_wrap() function. The data also come from this R package.

index.html

<!DOCTYPE html>
<head>
	<meta charset="UTF-8">
	<link href="https://fonts.googleapis.com/css?family=Raleway:400,500" rel="stylesheet">
	<style>
		html {
			font-family: 'Raleway', sans-serif;
		}

		a {
			color: inherit;
			text-decoration: none;
			border-bottom: 1px dashed #888;
		}

		#app {
			width: 960px;
		}

		.plot {
			float: left;
		}

		.plot-title h3 {
			margin-top: 7px;
		}

		.plot-title p {
			font-size: 13px;
		}

		.axis-label {
			font-size: 10px;
			color: #888;
		}

		.chart-title {
			font-size: 18px;
			font-weight: 500;
		}

		.Axis path,
		.Axis line {
			stroke: #888;
		}

		.Axis text {
			fill: #888;
		}
		
	</style>
</head>
<body>
	<div id="app"></div>
	<script src="index.js"></script>
</body>
</html>

App.js

import React from "react";
import * as d3 from "d3";
import Scatterplot from "./Scatterplot";

var carClasses = [
	{ abbrev: "compact", name: "Compacts"},
	{ abbrev: "midsize", name: "Mid-size cars"},
	{ abbrev: "suv", name: "SUVs"},
	{ abbrev: "2seater", name: "Two-seaters"},
	{ abbrev: "minivan", name: "Minivans"},
	{ abbrev: "pickup", name: "Pickups"},
	{ abbrev: "subcompact", name: "Subcompacts"}
];

class App extends React.Component {
	constructor(props) {
		super(props);
		this.state = { data: []	};
	}

	componentWillMount() {
		d3.tsv("mpg.tsv", row, ready.bind(this));

		function row(d) {
			return {
				class: d.class,
				hwy: +d.hwy,
				displ: +d.displ
			};
		}

		function ready(error, data) {
			if (error) throw error;
			this.setState({ data: data });
		}
	}
	
	render() {
		var width = 960 / 4,
				height = 960 / 5;

		var plots = carClasses.map((carClass, i) => {

			var annotations = getAnnotations(carClass);

			return (
				<div key={i} className="plot" style={{position: "relative"}}>

					<Scatterplot
						width={width}
						height={height}
						marginTop="40"
						x={d => d.displ}
						y={d => d.hwy}
						r={d => 2}
						fill={d => d.class === carClass.abbrev ? "#000" : "#ddd"}
						xDomain={[1, 7]}
						yDomain={[10, 45]}
						xTickArguments={[5]}
						yTickArguments={[5]}
						data={this.state.data} />
	
					<div style={{position: "absolute", left: 0, top: 0}}>
						{annotations}
					</div>

				</div>
			);
		});

		return (
			<div className="plots">
				<div 
					className="plot plot-title"
					style={{width: (width - 50), height: height, marginRight: 50}}>
					<h3>Fuel Efficiency vs. Engine Displacement</h3>
					<p>
						The <a href="https://en.wikipedia.org/wiki/Fuel_efficiency">fuel efficiency</a>{" "}
						and	<a href="https://en.wikipedia.org/wiki/Engine_displacement">engine displacement</a>{" "} 
						of over 200 cars grouped by car class. 
						Efficiency is measured as miles per gallon of highway driving. 
						Engine displacement is in liters. 
					</p>
				</div>

				{plots}
			</div>
		);
	}
}

function getAnnotations(carClass) {
	return [
		(
			<span
				key="0"
				className="chart-title"
				style={{position: "absolute", left: -5, top: 10, width: 200}}>
				{carClass.name}
			</span>
		),
		(
			<span
				key="1"
				className="axis-label"
				style={{position: "absolute", left: 149, top: 182}}>
				Displacement
			</span>
		),
		(
			<span
				key="2"
				className="axis-label"
				style={{position: "absolute", left: -100, top: 134, width: 200,
								MsTransform: "rotate(90deg)",
								WebkitTransform: "rotate(90deg)",
								transform: "rotate(90deg)"}}>
				MPG
			</span>
		)
	];
}

export default App;

Axis.js

// Refactored version of Tom MacWright's port of d3-axis:
// https://gist.github.com/tmcw/b8ce5c3d03255f287141e9687538ffc2

import * as d3 from 'd3';
import React from 'react';

const top = 1;
const right = 2;
const bottom = 3;
const left = 4;
const epsilon = 1e-6;

function translateX(scale0, scale1, d) {
  const x = scale0(d);
  return `translate(${(isFinite(x) ? x : scale1(d))},0)`;
}

function translateY(scale0, scale1, d) {
  const y = scale0(d);
  return `translate(0,${(isFinite(y) ? y : scale1(d))})`;
}

let identity = x => x;

const orientations = {
  top: 1,
  right: 2,
  bottom: 3,
  left: 4
};

class Axis extends React.Component {
	render() {
    const orient = orientations[this.props.orientation] || 4;
    const scale = this.props.scale;

    var tickArguments = this.props.tickArguments,
      	tickValues = null,
      	tickFormat = null,
      	tickSizeInner = 6,
      	tickSizeOuter = 6,
      	tickPadding = 3;

    var values = tickValues == null ? (scale.ticks ?
        scale.ticks.apply(scale, tickArguments) : scale.domain()) : tickValues;

    var format = tickFormat == null ? (scale.tickFormat ?
    	scale.tickFormat.apply(scale, tickArguments) : identity) : tickFormat;

  	var spacing = Math.max(tickSizeInner, 0) + tickPadding,
				transform = orient === top || orient === bottom ? translateX : translateY,
				range = scale.range(),
				range0 = range[0] + 0.5,
				range1 = range[range.length - 1] + 0.5,
				position = (scale.bandwidth ? center : identity)(scale.copy()),
				k = orient === top || orient === left ? -1 : 1,
				x,
				y = orient === left || orient === right ? (x = 'x', 'y') : (x = 'y', 'x');

    let lineProps = {
      [x + 2]: k * tickSizeInner,
      [y + 1]: 0.5,
      [y + 2]: 0.5
    };

    let textProps = {
			[x]: k * spacing,
			[y]: 0.5
    };

		var pathString = orient === left || orient == right
			? 'M' + k * tickSizeOuter + ',' + range0 + 'H0.5V' + range1 + 'H' + k * tickSizeOuter
			: 'M' + range0 + ',' + k * tickSizeOuter + 'V0.5H' + range1 + 'V' + k * tickSizeOuter;
		
		var gTicks = values.map((d, i) =>{
			return (
				<g
					className="tick"
					transform={transform(position, position, d)}
					key={i}>
					<line stroke='#000'	{...lineProps} />
					<text
						fill='#000'
						textAnchor={orient === right ? 'start' : orient === left ? 'end' : 'middle'}
						{...textProps}
						dy={orient === top ? '0em' : orient === bottom ? '0.71em' : '0.32em'}>
						{format(d)}
					</text>
				</g>
			)
		});
			
    return (
			<g className="Axis" fill="none" fontSize="10" fontFamily="sans-serif" textAnchor="end">
				<path d={pathString} stroke="#000"/>
				{gTicks}
			</g>	
		);
  }
}

Axis.propTypes = {
	orientation: React.PropTypes.string.isRequired,
	scale: React.PropTypes.func.isRequired,
	tickArguments: React.PropTypes.array
};

Axis.defaultProps = {
	tickArguments: []
};

export default Axis;

Points.js

import React from "react";

class Points extends React.Component {
	render() {
		var circles = this.props.data.map((d, i) => {
			return (
				<circle
					key={i}
					cx={d.x}
					cy={d.y}
					r={d.r}
					fill={d.fill}
					stroke={d.stroke} >
				</circle>
			)
		});
		return (
			<g className="Points">
				{circles}
			</g>
		);
	}
}

export default Points;

Scatterplot.js

import React from "react";
import * as d3 from "d3";
import Points from "./Points";
import Axis from "./Axis";

class Scatterplot extends React.Component {
	render() {
		var innerWidth = this.props.width - this.props.marginLeft - this.props.marginRight;
		var innerHeight = this.props.height - this.props.marginTop - this.props.marginBottom;
		var innerTransform = `translate(${this.props.marginLeft},${this.props.marginTop})`;

		var xDomain = this.props.xDomain || d3.extent(this.props.data, this.props.x);
		var yDomain = this.props.yDomain || d3.extent(this.props.data, this.props.y);

		var xScale = d3.scaleLinear()
			.domain(xDomain)
			.range([0, innerWidth]);
		
		var yScale = d3.scaleLinear()
			.domain(yDomain)
			.range([innerHeight, 0]);
		
		var xValue = d => xScale(this.props.x(d));
		var yValue = d => yScale(this.props.y(d));
		var rValue = d => this.props.r(d);
		var fillValue = d => this.props.fill(d);
		var strokeValue = d => this.props.stroke(d);

		var pointsData = this.props.data.map(d => {
			return {
				x: xValue(d),
				y: yValue(d),
				r: rValue(d),
				fill: fillValue(d),
				stroke: strokeValue(d)
			};
		});

		var bottomAxisTransform = `translate(0,${innerHeight})`;
 
		return (
			<svg 
				className="Scatterplot"
				width={this.props.width}
				height={this.props.height}>

				<g transform={innerTransform}>

					<Points	data={pointsData} />

					<g transform={bottomAxisTransform}>
						<Axis 
							orientation="bottom" 
							scale={xScale} 
							tickArguments={this.props.xTickArguments}/>
					</g>
					
					<Axis 
						orientation="left" 
						scale={yScale}
						tickArguments={this.props.yTickArguments} />	
				</g>

			</svg>
		);
	}
}

Scatterplot.propType = {
	marginTop: React.PropTypes.number,
	marginLeft: React.PropTypes.number,
	marginBottom: React.PropTypes.number,
	marginRight: React.PropTypes.number,
	width: React.PropTypes.number,
	height: React.PropTypes.number,
	x: React.PropTypes.func,
	y: React.PropTypes.func,
	r: React.PropTypes.func,
	fill: React.PropTypes.func,
	stroke: React.PropTypes.func,
	xDomain: React.PropTypes.number,
	yDomain: React.PropTypes.number,
	xTickArguments: React.PropTypes.array,
	yTickArguments: React.PropTypes.array,
	data: React.PropTypes.array.isRequired
};

Scatterplot.defaultProps = {
	marginTop: 10,
	marginLeft: 30,
	marginBottom: 30,
	marginRight: 30,
	width: 960,
	height: 500,
	x: d => d.x,
	y: d => d.y,
	r: d => 3,
	fill: d => "#000",
	stroke: d => "none",
	xTickArguments: [],
	yTickArguments: []
};

export default Scatterplot;

main.js

import React from "react";
import ReactDOM from "react-dom";
import App from "./App";

ReactDOM.render(<App />, document.getElementById("app"));

mpg.tsv

manufacturer	model	displ	year	cyl	trans	drv	cty	hwy	fl	class
audi	a4	1.8	1999	4	auto(l5)	f	18	29	p	compact
audi	a4	1.8	1999	4	manual(m5)	f	21	29	p	compact
audi	a4	2	2008	4	manual(m6)	f	20	31	p	compact
audi	a4	2	2008	4	auto(av)	f	21	30	p	compact
audi	a4	2.8	1999	6	auto(l5)	f	16	26	p	compact
audi	a4	2.8	1999	6	manual(m5)	f	18	26	p	compact
audi	a4	3.1	2008	6	auto(av)	f	18	27	p	compact
audi	a4 quattro	1.8	1999	4	manual(m5)	4	18	26	p	compact
audi	a4 quattro	1.8	1999	4	auto(l5)	4	16	25	p	compact
audi	a4 quattro	2	2008	4	manual(m6)	4	20	28	p	compact
audi	a4 quattro	2	2008	4	auto(s6)	4	19	27	p	compact
audi	a4 quattro	2.8	1999	6	auto(l5)	4	15	25	p	compact
audi	a4 quattro	2.8	1999	6	manual(m5)	4	17	25	p	compact
audi	a4 quattro	3.1	2008	6	auto(s6)	4	17	25	p	compact
audi	a4 quattro	3.1	2008	6	manual(m6)	4	15	25	p	compact
audi	a6 quattro	2.8	1999	6	auto(l5)	4	15	24	p	midsize
audi	a6 quattro	3.1	2008	6	auto(s6)	4	17	25	p	midsize
audi	a6 quattro	4.2	2008	8	auto(s6)	4	16	23	p	midsize
chevrolet	c1500 suburban 2wd	5.3	2008	8	auto(l4)	r	14	20	r	suv
chevrolet	c1500 suburban 2wd	5.3	2008	8	auto(l4)	r	11	15	e	suv
chevrolet	c1500 suburban 2wd	5.3	2008	8	auto(l4)	r	14	20	r	suv
chevrolet	c1500 suburban 2wd	5.7	1999	8	auto(l4)	r	13	17	r	suv
chevrolet	c1500 suburban 2wd	6	2008	8	auto(l4)	r	12	17	r	suv
chevrolet	corvette	5.7	1999	8	manual(m6)	r	16	26	p	2seater
chevrolet	corvette	5.7	1999	8	auto(l4)	r	15	23	p	2seater
chevrolet	corvette	6.2	2008	8	manual(m6)	r	16	26	p	2seater
chevrolet	corvette	6.2	2008	8	auto(s6)	r	15	25	p	2seater
chevrolet	corvette	7	2008	8	manual(m6)	r	15	24	p	2seater
chevrolet	k1500 tahoe 4wd	5.3	2008	8	auto(l4)	4	14	19	r	suv
chevrolet	k1500 tahoe 4wd	5.3	2008	8	auto(l4)	4	11	14	e	suv
chevrolet	k1500 tahoe 4wd	5.7	1999	8	auto(l4)	4	11	15	r	suv
chevrolet	k1500 tahoe 4wd	6.5	1999	8	auto(l4)	4	14	17	d	suv
chevrolet	malibu	2.4	1999	4	auto(l4)	f	19	27	r	midsize
chevrolet	malibu	2.4	2008	4	auto(l4)	f	22	30	r	midsize
chevrolet	malibu	3.1	1999	6	auto(l4)	f	18	26	r	midsize
chevrolet	malibu	3.5	2008	6	auto(l4)	f	18	29	r	midsize
chevrolet	malibu	3.6	2008	6	auto(s6)	f	17	26	r	midsize
dodge	caravan 2wd	2.4	1999	4	auto(l3)	f	18	24	r	minivan
dodge	caravan 2wd	3	1999	6	auto(l4)	f	17	24	r	minivan
dodge	caravan 2wd	3.3	1999	6	auto(l4)	f	16	22	r	minivan
dodge	caravan 2wd	3.3	1999	6	auto(l4)	f	16	22	r	minivan
dodge	caravan 2wd	3.3	2008	6	auto(l4)	f	17	24	r	minivan
dodge	caravan 2wd	3.3	2008	6	auto(l4)	f	17	24	r	minivan
dodge	caravan 2wd	3.3	2008	6	auto(l4)	f	11	17	e	minivan
dodge	caravan 2wd	3.8	1999	6	auto(l4)	f	15	22	r	minivan
dodge	caravan 2wd	3.8	1999	6	auto(l4)	f	15	21	r	minivan
dodge	caravan 2wd	3.8	2008	6	auto(l6)	f	16	23	r	minivan
dodge	caravan 2wd	4	2008	6	auto(l6)	f	16	23	r	minivan
dodge	dakota pickup 4wd	3.7	2008	6	manual(m6)	4	15	19	r	pickup
dodge	dakota pickup 4wd	3.7	2008	6	auto(l4)	4	14	18	r	pickup
dodge	dakota pickup 4wd	3.9	1999	6	auto(l4)	4	13	17	r	pickup
dodge	dakota pickup 4wd	3.9	1999	6	manual(m5)	4	14	17	r	pickup
dodge	dakota pickup 4wd	4.7	2008	8	auto(l5)	4	14	19	r	pickup
dodge	dakota pickup 4wd	4.7	2008	8	auto(l5)	4	14	19	r	pickup
dodge	dakota pickup 4wd	4.7	2008	8	auto(l5)	4	9	12	e	pickup
dodge	dakota pickup 4wd	5.2	1999	8	manual(m5)	4	11	17	r	pickup
dodge	dakota pickup 4wd	5.2	1999	8	auto(l4)	4	11	15	r	pickup
dodge	durango 4wd	3.9	1999	6	auto(l4)	4	13	17	r	suv
dodge	durango 4wd	4.7	2008	8	auto(l5)	4	13	17	r	suv
dodge	durango 4wd	4.7	2008	8	auto(l5)	4	9	12	e	suv
dodge	durango 4wd	4.7	2008	8	auto(l5)	4	13	17	r	suv
dodge	durango 4wd	5.2	1999	8	auto(l4)	4	11	16	r	suv
dodge	durango 4wd	5.7	2008	8	auto(l5)	4	13	18	r	suv
dodge	durango 4wd	5.9	1999	8	auto(l4)	4	11	15	r	suv
dodge	ram 1500 pickup 4wd	4.7	2008	8	manual(m6)	4	12	16	r	pickup
dodge	ram 1500 pickup 4wd	4.7	2008	8	auto(l5)	4	9	12	e	pickup
dodge	ram 1500 pickup 4wd	4.7	2008	8	auto(l5)	4	13	17	r	pickup
dodge	ram 1500 pickup 4wd	4.7	2008	8	auto(l5)	4	13	17	r	pickup
dodge	ram 1500 pickup 4wd	4.7	2008	8	manual(m6)	4	12	16	r	pickup
dodge	ram 1500 pickup 4wd	4.7	2008	8	manual(m6)	4	9	12	e	pickup
dodge	ram 1500 pickup 4wd	5.2	1999	8	auto(l4)	4	11	15	r	pickup
dodge	ram 1500 pickup 4wd	5.2	1999	8	manual(m5)	4	11	16	r	pickup
dodge	ram 1500 pickup 4wd	5.7	2008	8	auto(l5)	4	13	17	r	pickup
dodge	ram 1500 pickup 4wd	5.9	1999	8	auto(l4)	4	11	15	r	pickup
ford	expedition 2wd	4.6	1999	8	auto(l4)	r	11	17	r	suv
ford	expedition 2wd	5.4	1999	8	auto(l4)	r	11	17	r	suv
ford	expedition 2wd	5.4	2008	8	auto(l6)	r	12	18	r	suv
ford	explorer 4wd	4	1999	6	auto(l5)	4	14	17	r	suv
ford	explorer 4wd	4	1999	6	manual(m5)	4	15	19	r	suv
ford	explorer 4wd	4	1999	6	auto(l5)	4	14	17	r	suv
ford	explorer 4wd	4	2008	6	auto(l5)	4	13	19	r	suv
ford	explorer 4wd	4.6	2008	8	auto(l6)	4	13	19	r	suv
ford	explorer 4wd	5	1999	8	auto(l4)	4	13	17	r	suv
ford	f150 pickup 4wd	4.2	1999	6	auto(l4)	4	14	17	r	pickup
ford	f150 pickup 4wd	4.2	1999	6	manual(m5)	4	14	17	r	pickup
ford	f150 pickup 4wd	4.6	1999	8	manual(m5)	4	13	16	r	pickup
ford	f150 pickup 4wd	4.6	1999	8	auto(l4)	4	13	16	r	pickup
ford	f150 pickup 4wd	4.6	2008	8	auto(l4)	4	13	17	r	pickup
ford	f150 pickup 4wd	5.4	1999	8	auto(l4)	4	11	15	r	pickup
ford	f150 pickup 4wd	5.4	2008	8	auto(l4)	4	13	17	r	pickup
ford	mustang	3.8	1999	6	manual(m5)	r	18	26	r	subcompact
ford	mustang	3.8	1999	6	auto(l4)	r	18	25	r	subcompact
ford	mustang	4	2008	6	manual(m5)	r	17	26	r	subcompact
ford	mustang	4	2008	6	auto(l5)	r	16	24	r	subcompact
ford	mustang	4.6	1999	8	auto(l4)	r	15	21	r	subcompact
ford	mustang	4.6	1999	8	manual(m5)	r	15	22	r	subcompact
ford	mustang	4.6	2008	8	manual(m5)	r	15	23	r	subcompact
ford	mustang	4.6	2008	8	auto(l5)	r	15	22	r	subcompact
ford	mustang	5.4	2008	8	manual(m6)	r	14	20	p	subcompact
honda	civic	1.6	1999	4	manual(m5)	f	28	33	r	subcompact
honda	civic	1.6	1999	4	auto(l4)	f	24	32	r	subcompact
honda	civic	1.6	1999	4	manual(m5)	f	25	32	r	subcompact
honda	civic	1.6	1999	4	manual(m5)	f	23	29	p	subcompact
honda	civic	1.6	1999	4	auto(l4)	f	24	32	r	subcompact
honda	civic	1.8	2008	4	manual(m5)	f	26	34	r	subcompact
honda	civic	1.8	2008	4	auto(l5)	f	25	36	r	subcompact
honda	civic	1.8	2008	4	auto(l5)	f	24	36	c	subcompact
honda	civic	2	2008	4	manual(m6)	f	21	29	p	subcompact
hyundai	sonata	2.4	1999	4	auto(l4)	f	18	26	r	midsize
hyundai	sonata	2.4	1999	4	manual(m5)	f	18	27	r	midsize
hyundai	sonata	2.4	2008	4	auto(l4)	f	21	30	r	midsize
hyundai	sonata	2.4	2008	4	manual(m5)	f	21	31	r	midsize
hyundai	sonata	2.5	1999	6	auto(l4)	f	18	26	r	midsize
hyundai	sonata	2.5	1999	6	manual(m5)	f	18	26	r	midsize
hyundai	sonata	3.3	2008	6	auto(l5)	f	19	28	r	midsize
hyundai	tiburon	2	1999	4	auto(l4)	f	19	26	r	subcompact
hyundai	tiburon	2	1999	4	manual(m5)	f	19	29	r	subcompact
hyundai	tiburon	2	2008	4	manual(m5)	f	20	28	r	subcompact
hyundai	tiburon	2	2008	4	auto(l4)	f	20	27	r	subcompact
hyundai	tiburon	2.7	2008	6	auto(l4)	f	17	24	r	subcompact
hyundai	tiburon	2.7	2008	6	manual(m6)	f	16	24	r	subcompact
hyundai	tiburon	2.7	2008	6	manual(m5)	f	17	24	r	subcompact
jeep	grand cherokee 4wd	3	2008	6	auto(l5)	4	17	22	d	suv
jeep	grand cherokee 4wd	3.7	2008	6	auto(l5)	4	15	19	r	suv
jeep	grand cherokee 4wd	4	1999	6	auto(l4)	4	15	20	r	suv
jeep	grand cherokee 4wd	4.7	1999	8	auto(l4)	4	14	17	r	suv
jeep	grand cherokee 4wd	4.7	2008	8	auto(l5)	4	9	12	e	suv
jeep	grand cherokee 4wd	4.7	2008	8	auto(l5)	4	14	19	r	suv
jeep	grand cherokee 4wd	5.7	2008	8	auto(l5)	4	13	18	r	suv
jeep	grand cherokee 4wd	6.1	2008	8	auto(l5)	4	11	14	p	suv
land rover	range rover	4	1999	8	auto(l4)	4	11	15	p	suv
land rover	range rover	4.2	2008	8	auto(s6)	4	12	18	r	suv
land rover	range rover	4.4	2008	8	auto(s6)	4	12	18	r	suv
land rover	range rover	4.6	1999	8	auto(l4)	4	11	15	p	suv
lincoln	navigator 2wd	5.4	1999	8	auto(l4)	r	11	17	r	suv
lincoln	navigator 2wd	5.4	1999	8	auto(l4)	r	11	16	p	suv
lincoln	navigator 2wd	5.4	2008	8	auto(l6)	r	12	18	r	suv
mercury	mountaineer 4wd	4	1999	6	auto(l5)	4	14	17	r	suv
mercury	mountaineer 4wd	4	2008	6	auto(l5)	4	13	19	r	suv
mercury	mountaineer 4wd	4.6	2008	8	auto(l6)	4	13	19	r	suv
mercury	mountaineer 4wd	5	1999	8	auto(l4)	4	13	17	r	suv
nissan	altima	2.4	1999	4	manual(m5)	f	21	29	r	compact
nissan	altima	2.4	1999	4	auto(l4)	f	19	27	r	compact
nissan	altima	2.5	2008	4	auto(av)	f	23	31	r	midsize
nissan	altima	2.5	2008	4	manual(m6)	f	23	32	r	midsize
nissan	altima	3.5	2008	6	manual(m6)	f	19	27	p	midsize
nissan	altima	3.5	2008	6	auto(av)	f	19	26	p	midsize
nissan	maxima	3	1999	6	auto(l4)	f	18	26	r	midsize
nissan	maxima	3	1999	6	manual(m5)	f	19	25	r	midsize
nissan	maxima	3.5	2008	6	auto(av)	f	19	25	p	midsize
nissan	pathfinder 4wd	3.3	1999	6	auto(l4)	4	14	17	r	suv
nissan	pathfinder 4wd	3.3	1999	6	manual(m5)	4	15	17	r	suv
nissan	pathfinder 4wd	4	2008	6	auto(l5)	4	14	20	p	suv
nissan	pathfinder 4wd	5.6	2008	8	auto(s5)	4	12	18	p	suv
pontiac	grand prix	3.1	1999	6	auto(l4)	f	18	26	r	midsize
pontiac	grand prix	3.8	1999	6	auto(l4)	f	16	26	p	midsize
pontiac	grand prix	3.8	1999	6	auto(l4)	f	17	27	r	midsize
pontiac	grand prix	3.8	2008	6	auto(l4)	f	18	28	r	midsize
pontiac	grand prix	5.3	2008	8	auto(s4)	f	16	25	p	midsize
subaru	forester awd	2.5	1999	4	manual(m5)	4	18	25	r	suv
subaru	forester awd	2.5	1999	4	auto(l4)	4	18	24	r	suv
subaru	forester awd	2.5	2008	4	manual(m5)	4	20	27	r	suv
subaru	forester awd	2.5	2008	4	manual(m5)	4	19	25	p	suv
subaru	forester awd	2.5	2008	4	auto(l4)	4	20	26	r	suv
subaru	forester awd	2.5	2008	4	auto(l4)	4	18	23	p	suv
subaru	impreza awd	2.2	1999	4	auto(l4)	4	21	26	r	subcompact
subaru	impreza awd	2.2	1999	4	manual(m5)	4	19	26	r	subcompact
subaru	impreza awd	2.5	1999	4	manual(m5)	4	19	26	r	subcompact
subaru	impreza awd	2.5	1999	4	auto(l4)	4	19	26	r	subcompact
subaru	impreza awd	2.5	2008	4	auto(s4)	4	20	25	p	compact
subaru	impreza awd	2.5	2008	4	auto(s4)	4	20	27	r	compact
subaru	impreza awd	2.5	2008	4	manual(m5)	4	19	25	p	compact
subaru	impreza awd	2.5	2008	4	manual(m5)	4	20	27	r	compact
toyota	4runner 4wd	2.7	1999	4	manual(m5)	4	15	20	r	suv
toyota	4runner 4wd	2.7	1999	4	auto(l4)	4	16	20	r	suv
toyota	4runner 4wd	3.4	1999	6	auto(l4)	4	15	19	r	suv
toyota	4runner 4wd	3.4	1999	6	manual(m5)	4	15	17	r	suv
toyota	4runner 4wd	4	2008	6	auto(l5)	4	16	20	r	suv
toyota	4runner 4wd	4.7	2008	8	auto(l5)	4	14	17	r	suv
toyota	camry	2.2	1999	4	manual(m5)	f	21	29	r	midsize
toyota	camry	2.2	1999	4	auto(l4)	f	21	27	r	midsize
toyota	camry	2.4	2008	4	manual(m5)	f	21	31	r	midsize
toyota	camry	2.4	2008	4	auto(l5)	f	21	31	r	midsize
toyota	camry	3	1999	6	auto(l4)	f	18	26	r	midsize
toyota	camry	3	1999	6	manual(m5)	f	18	26	r	midsize
toyota	camry	3.5	2008	6	auto(s6)	f	19	28	r	midsize
toyota	camry solara	2.2	1999	4	auto(l4)	f	21	27	r	compact
toyota	camry solara	2.2	1999	4	manual(m5)	f	21	29	r	compact
toyota	camry solara	2.4	2008	4	manual(m5)	f	21	31	r	compact
toyota	camry solara	2.4	2008	4	auto(s5)	f	22	31	r	compact
toyota	camry solara	3	1999	6	auto(l4)	f	18	26	r	compact
toyota	camry solara	3	1999	6	manual(m5)	f	18	26	r	compact
toyota	camry solara	3.3	2008	6	auto(s5)	f	18	27	r	compact
toyota	corolla	1.8	1999	4	auto(l3)	f	24	30	r	compact
toyota	corolla	1.8	1999	4	auto(l4)	f	24	33	r	compact
toyota	corolla	1.8	1999	4	manual(m5)	f	26	35	r	compact
toyota	corolla	1.8	2008	4	manual(m5)	f	28	37	r	compact
toyota	corolla	1.8	2008	4	auto(l4)	f	26	35	r	compact
toyota	land cruiser wagon 4wd	4.7	1999	8	auto(l4)	4	11	15	r	suv
toyota	land cruiser wagon 4wd	5.7	2008	8	auto(s6)	4	13	18	r	suv
toyota	toyota tacoma 4wd	2.7	1999	4	manual(m5)	4	15	20	r	pickup
toyota	toyota tacoma 4wd	2.7	1999	4	auto(l4)	4	16	20	r	pickup
toyota	toyota tacoma 4wd	2.7	2008	4	manual(m5)	4	17	22	r	pickup
toyota	toyota tacoma 4wd	3.4	1999	6	manual(m5)	4	15	17	r	pickup
toyota	toyota tacoma 4wd	3.4	1999	6	auto(l4)	4	15	19	r	pickup
toyota	toyota tacoma 4wd	4	2008	6	manual(m6)	4	15	18	r	pickup
toyota	toyota tacoma 4wd	4	2008	6	auto(l5)	4	16	20	r	pickup
volkswagen	gti	2	1999	4	manual(m5)	f	21	29	r	compact
volkswagen	gti	2	1999	4	auto(l4)	f	19	26	r	compact
volkswagen	gti	2	2008	4	manual(m6)	f	21	29	p	compact
volkswagen	gti	2	2008	4	auto(s6)	f	22	29	p	compact
volkswagen	gti	2.8	1999	6	manual(m5)	f	17	24	r	compact
volkswagen	jetta	1.9	1999	4	manual(m5)	f	33	44	d	compact
volkswagen	jetta	2	1999	4	manual(m5)	f	21	29	r	compact
volkswagen	jetta	2	1999	4	auto(l4)	f	19	26	r	compact
volkswagen	jetta	2	2008	4	auto(s6)	f	22	29	p	compact
volkswagen	jetta	2	2008	4	manual(m6)	f	21	29	p	compact
volkswagen	jetta	2.5	2008	5	auto(s6)	f	21	29	r	compact
volkswagen	jetta	2.5	2008	5	manual(m5)	f	21	29	r	compact
volkswagen	jetta	2.8	1999	6	auto(l4)	f	16	23	r	compact
volkswagen	jetta	2.8	1999	6	manual(m5)	f	17	24	r	compact
volkswagen	new beetle	1.9	1999	4	manual(m5)	f	35	44	d	subcompact
volkswagen	new beetle	1.9	1999	4	auto(l4)	f	29	41	d	subcompact
volkswagen	new beetle	2	1999	4	manual(m5)	f	21	29	r	subcompact
volkswagen	new beetle	2	1999	4	auto(l4)	f	19	26	r	subcompact
volkswagen	new beetle	2.5	2008	5	manual(m5)	f	20	28	r	subcompact
volkswagen	new beetle	2.5	2008	5	auto(s6)	f	20	29	r	subcompact
volkswagen	passat	1.8	1999	4	manual(m5)	f	21	29	p	midsize
volkswagen	passat	1.8	1999	4	auto(l5)	f	18	29	p	midsize
volkswagen	passat	2	2008	4	auto(s6)	f	19	28	p	midsize
volkswagen	passat	2	2008	4	manual(m6)	f	21	29	p	midsize
volkswagen	passat	2.8	1999	6	auto(l5)	f	16	26	p	midsize
volkswagen	passat	2.8	1999	6	manual(m5)	f	18	26	p	midsize
volkswagen	passat	3.6	2008	6	auto(s6)	f	17	26	p	midsize

webpack.config.js

module.exports = {
	entry: "./main.js",
	output: {
		path: "./",
		filename: "index.js"
	},
	devServer: {
		inline: true,
		port: 3333
	},
	module: {
		loaders: [
			{
				test: /\.js$/,
				exclude: /node_modules/,
				loader: "babel",
				query: {
					presets: ["es2015", "react"]
				}
			}
		]
	}
};