Skip to content

Commit

Permalink
Merge 010a290 into e37ef42
Browse files Browse the repository at this point in the history
  • Loading branch information
raspo committed Oct 11, 2016
2 parents e37ef42 + 010a290 commit a84fbd1
Show file tree
Hide file tree
Showing 5 changed files with 109 additions and 7 deletions.
8 changes: 6 additions & 2 deletions demo/component/BarChart.js
Expand Up @@ -213,6 +213,10 @@ export default React.createClass({
console.log(`Pv Bar (${index}) Click: `, data);
},

handleClickTooltip(data, index, e) {
console.log(`Tooltip (${index}) Click: `, data);
},

render() {
const { data, data01, data02 } = this.state;

Expand Down Expand Up @@ -301,12 +305,12 @@ export default React.createClass({
</BarChart>
</div>

<p>Stack BarChart</p>
<p>Stack BarChart (Click anywhere on chart and open console)</p>
<div className="bar-chart-wrapper">
<BarChart width={400} height={400} data={data}>
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Tooltip onClick={this.handleClickTooltip} />
<CartesianGrid vertical={false}/>
<Bar stackId="0" dataKey="uv" fill="#ff7300"/>
<Bar stackId="0" dataKey="pv" fill="#387908" label={RenderLabel}/>
Expand Down
8 changes: 6 additions & 2 deletions demo/component/ComposedChart.js
Expand Up @@ -14,17 +14,21 @@ const data = [
export default React.createClass({
displayName: 'ComposedChartDemo',

handleClickTooltip(data, index, e) {
console.log(`Tooltip (${index}) Click: `, data);
},

render () {
return (
<div className="line-charts">
<p>A simple ComposedChart of Line, Bar, Area</p>
<p>A simple ComposedChart of Line, Bar, Area (Click anywhere on chart and open console)</p>
<div className="composed-chart-wrapper">
<ResponsiveContainer width="100%" height={300}>
<ComposedChart width={800} height={400} data={data}
margin={{ top: 20, right: 20, bottom: 5, left: 20 }}>
<XAxis dataKey="name" />
<YAxis />
<Tooltip />
<Tooltip onClick={this.handleClickTooltip} />
<Legend layout="vertical" align="right" verticalAlign="middle"/>
<CartesianGrid stroke="#f5f5f5" />
<Area type="monotone" dataKey='amt' fill="#8884d8" stroke="#8884d8" />
Expand Down
6 changes: 5 additions & 1 deletion demo/component/LineChart.js
Expand Up @@ -72,6 +72,10 @@ export default React.createClass({
this.setState(() => _.mapValues(initilaState, changeNumberOfData));
},

handleClickTooltip(data, index, e) {
console.log(`Tooltip (${index}) Click: `, data);
},

render() {
const { data, data01, data02 } = this.state;

Expand Down Expand Up @@ -116,7 +120,7 @@ export default React.createClass({
<LineChart width={400} height={400} data={data}
margin={{top: 10, bottom: 10, left: 30, right: 30}}>
<XAxis dataKey='name'/>
<Tooltip/>
<Tooltip onClick={this.handleClickTooltip} />
<CartesianGrid stroke='#f5f5f5'/>
<Line type='monotone' dataKey='uv' stroke='#ff7300' yAxisId={0} activeDot={{fill: '#ff7300', stroke: 'none'}}/>
<Line type='monotone' dataKey='pv' stroke='#387908' yAxisId={1} activeDot={{fill: '#387908', stroke: 'none', r: 6}}/>
Expand Down
25 changes: 25 additions & 0 deletions src/chart/generateCategoricalChart.js
Expand Up @@ -496,6 +496,28 @@ const generateCategoricalChart = (ChartComponent, GraphicalChild) => {
dataEndIndex: endIndex,
});
};

handleClickTooltip(offset, xAxisMap, yAxisMap, onClickTooltip, items, e) {
if (!onClickTooltip || !_.isFunction(onClickTooltip)) { return; }

const container = ReactDOM.findDOMNode(this);
const containerOffset = getOffset(container);
const ne = calculateChartCoordinate(e, containerOffset);
const mouse = this.getMouseInfo(xAxisMap, yAxisMap, offset, ne);

if (!mouse) { return; }

const { activeTooltipIndex, dataStartIndex, dataEndIndex } = this.state;
const data = this.props.data.slice(dataStartIndex, dataEndIndex + 1);

if (activeTooltipIndex < 0 || !items || !items.length
|| activeTooltipIndex >= data.length) {
return;
}

onClickTooltip(data[activeTooltipIndex], activeTooltipIndex, e);
}

/**
* The handler of mouse entering chart
* @param {Object} offset The offset of main part in the svg element
Expand Down Expand Up @@ -782,10 +804,13 @@ const generateCategoricalChart = (ChartComponent, GraphicalChild) => {

const tooltipItem = findChildByType(children, Tooltip);
const events = tooltipItem ? {
onClick: this.handleClickTooltip.bind(this, offset, xAxisMap, yAxisMap,
tooltipItem.props.onClick, items),
onMouseEnter: this.handleMouseEnter.bind(this, offset, xAxisMap, yAxisMap),
onMouseMove: this.handleMouseMove.bind(this, offset, xAxisMap, yAxisMap),
onMouseLeave: this.handleMouseLeave,
} : null;

const attrs = getPresentationAttributes(others);

return (
Expand Down
69 changes: 67 additions & 2 deletions test/specs/component/TooltipSpec.js
Expand Up @@ -2,6 +2,7 @@ import React from 'react';
import { expect } from 'chai';
import { AreaChart, Area, Tooltip } from 'recharts';
import { mount, render } from 'enzyme';
import sinon from 'sinon';

describe('<Tooltip />', () => {
const data = [
Expand All @@ -15,8 +16,8 @@ describe('<Tooltip />', () => {
it('Render 1 default tooltip', () => {
const wrapper = mount(
<AreaChart width={100} height={50} data={data}>
<Area type="monotone" dataKey="uv" stroke="#ff7300" fill="#ff7300"/>
<Tooltip/>
<Area type="monotone" dataKey="uv" stroke="#ff7300" fill="#ff7300" />
<Tooltip />
</AreaChart>
);

Expand All @@ -36,6 +37,70 @@ describe('<Tooltip />', () => {
expect(wrapper.find(Tooltip).length).to.equal(1);
});

it('click on chart should invoke onClick callback', () => {
const onClick = sinon.spy();
const wrapper = mount(
<AreaChart width={100} height={50} data={data}>
<Area type="monotone" dataKey="uv" stroke="#ff7300" fill="#ff7300" />
<Tooltip onClick={onClick} />
</AreaChart>
);

// I simulate to hover on the AreaChart, then the tooltip should show!
wrapper.setState({
isTooltipActive: true,
chartX: 86,
chartY: 21,
activeTooltipIndex: 4,
activeTooltipLabel: 4,
activeTooltipCoord: {
x: 95,
y: 21,
},
});

const chart = wrapper.find(Area);
chart.simulate('click', { pageX: 50, pageY: 30 });
expect(onClick.calledOnce).to.equal(true);
expect(onClick.lastCall.args[0]).to.deep.equal({
name: 'Page E',
uv: 189,
pv: 4800,
amt: 2400,
});
expect(onClick.lastCall.args[1]).to.equal(4);
});

it('clicking outside the chart should not trigger onClick callback', () => {
const onClick = sinon.spy();
const wrapper = mount(
<AreaChart width={100} height={50} data={data} margin={{ left: 10 }}>
<Area type="monotone" dataKey="uv" stroke="#ff7300" fill="#ff7300" />
<Tooltip onClick={onClick} />
</AreaChart>
);

// I simulate to hover on the AreaChart, then the tooltip should show!
wrapper.setState({
isTooltipActive: true,
chartX: 86,
chartY: 21,
activeTooltipIndex: 4,
activeTooltipLabel: 4,
activeTooltipCoord: {
x: 95,
y: 21,
},
});

const chart = wrapper.find(Area);
chart.simulate('click', { pageX: 5, pageY: 30 });
expect(onClick.calledOnce).to.equal(false);

chart.simulate('click', { pageX: 50, pageY: 30 });
expect(onClick.calledOnce).to.equal(true);
});

// it('Render customized tooltip when content is set to be a react element', () => {
// const Customized = () => {
// return <div className="customized"/>
Expand Down

0 comments on commit a84fbd1

Please sign in to comment.