diff --git a/src/components/app.js b/src/components/app.js
index b67e782f..998b2f67 100644
--- a/src/components/app.js
+++ b/src/components/app.js
@@ -6,7 +6,7 @@ import { connect } from "react-redux";
import PulseLoader from "halogen/PulseLoader";
import LeftSideBar from "./leftsidebar";
-import Continuous from "./continuous/continuous";
+import Parallel from "./continuous/parallel";
import DynamicScatterplot from "./scatterplot/scatterplot";
import Joy from "./joy/joy";
import Graph from "./graph/graph";
@@ -70,7 +70,7 @@ class App extends React.Component {
}}>
- {/**/}
+ {/**/}
diff --git a/src/components/continuous/parallel.js b/src/components/continuous/parallel.js
new file mode 100644
index 00000000..9660e084
--- /dev/null
+++ b/src/components/continuous/parallel.js
@@ -0,0 +1,157 @@
+/* rc slider https://www.npmjs.com/package/rc-slider */
+
+import React from 'react';
+import _ from "lodash";
+import { connect } from "react-redux";
+
+import styles from './parallelCoordinates.css';
+import SectionHeader from "../framework/sectionHeader";
+
+import setupParallelCoordinates from "./setupParallelCoordinates";
+import drawAxes from "./drawAxes";
+import drawLinesCanvas from "./drawLinesCanvas";
+
+import {
+ margin,
+ width,
+ height,
+ createDimensions,
+} from "./util";
+
+@connect((state) => {
+
+ const ranges = state.cells.cells && state.cells.cells.data.ranges ? state.cells.cells.data.ranges : null;
+ const metadata = state.cells.cells && state.cells.cells.data.metadata ? state.cells.cells.data.metadata : null;
+
+ const initializeRanges = state.initialize.data && state.initialize.data.data.ranges ? state.initialize.data.data.ranges : null;
+
+ return {
+ ranges,
+ metadata,
+ initializeRanges,
+ colorAccessor: state.controls.colorAccessor,
+ colorScale: state.controls.colorScale,
+ graphBrushSelection: state.controls.graphBrushSelection,
+ currentCellSelection: state.controls.currentCellSelection,
+ axesHaveBeenDrawn: state.controls.axesHaveBeenDrawn,
+ }
+})
+class Parallel extends React.Component {
+ constructor(props) {
+ super(props);
+ this.state = {
+ svg: null,
+ ctx: null,
+ axes: null,
+ dimensions: null,
+ };
+ }
+ componentDidMount() {
+ const {svg, ctx} = setupParallelCoordinates(
+ width,
+ height,
+ margin
+ );
+ this.setState({svg, ctx})
+ }
+ componentWillReceiveProps(nextProps) {
+ this.maybeDrawAxes(nextProps);
+ this.maybeDrawLines(nextProps);
+ }
+ maybeDrawAxes(nextProps) {
+ if (
+ !this.state.axes &&
+ nextProps.initializeRanges /* axes are created on full range of data */
+ ) {
+
+ const dimensions = createDimensions(nextProps.initializeRanges);
+
+ const xscale = d3.scalePoint()
+ .domain(d3.range(dimensions.length))
+ .range([0, width]);
+
+ const axes = drawAxes(
+ this.state.svg,
+ this.state.ctx,
+ dimensions,
+ xscale,
+ height,
+ width,
+ this.handleBrushAction.bind(this),
+ this.handleColorAction.bind(this),
+ );
+
+ this.setState({
+ axes,
+ xscale,
+ dimensions,
+ })
+
+ this.props.dispatch({
+ type: "parallel coordinates axes have been drawn"
+ })
+
+ }
+ }
+ maybeDrawLines = _.debounce((nextProps) => { /* https://stackoverflow.com/questions/23123138/perform-debounce-in-react-js */
+ if (
+ nextProps.ranges &&
+ nextProps.currentCellSelection &&
+ nextProps.axesHaveBeenDrawn
+ ) {
+
+ if (this.state._drawLinesCanvas) {
+ this.state._drawLinesCanvas.invalidate(); /* this is only necessary if the internals of drawLinesCanvas are using the render queue */
+ }
+
+ this.state.ctx.clearRect(0, 0, width, height);
+
+ const _drawLinesCanvas = drawLinesCanvas(
+ nextProps.currentCellSelection,
+ this.state.dimensions,
+ this.state.xscale,
+ this.state.ctx,
+ nextProps.colorAccessor,
+ nextProps.colorScale,
+ );
+
+ this.setState({
+ _drawLinesCanvas, /* this will only exist if the internals of drawLinesCanvas are using the render queue */
+ })
+ }
+ }, 200)
+
+ handleBrushAction (selection) {
+ this.props.dispatch({
+ type: "continuous selection using parallel coords brushing",
+ data: selection
+ })
+ }
+ handleColorAction (key) {
+ this.props.dispatch({
+ type: "color by continuous metadata",
+ colorAccessor: key,
+ rangeMaxForColorAccessor: this.props.initializeRanges[key].range.max
+ });
+ }
+
+ render() {
+
+ return (
+
+ )
+ }
+};
+
+export default Parallel;
+
+
+//