Split JS code by classes into different files

This commit is contained in:
2015-03-18 17:14:22 +07:00
parent 0e5f20d48c
commit e2ad2739cd
19 changed files with 566 additions and 568 deletions
+103
View File
@@ -0,0 +1,103 @@
var Bar = React.createClass({
mixins: [ReactRouter.Navigation, ChartAnimationMixin],
height: 30,
labelPaddingH: 5, // Label horizontal padding
labelPaddingV: 2, // Label vertical padding
labelMarginV: 5, // Same as padding
labelHeight: 16, // Text size
labelOuterHeight: 20, // labelHeight + 2*labelPaddingV,
getInitialState: function() {
return {
labelX: 0,
lastLabelX: this.labelPaddingH
};
},
componentDidMount: function() {
this.calculateLabelPosition();
},
componentWillReceiveProps: function(newProps) {
if (_.isEqual(this.props, newProps)) {
return;
}
this.setState({
lastBarX: (this.props.x !== undefined ? this.props.x : newProps.x),
lastBarWidth: (this.props.width !== undefined ? this.props.width : newProps.width),
lastLabelX: this.state.labelX
}, this.calculateLabelPosition);
},
calculateLabelPosition: function() {
var val = this.props.value,
offset = this.props.offset,
label = this.props.item + ': ' + formatNumber(val),
labelWidth = textWidth(label),
labelOffsetWidth = labelWidth + 2*this.labelPaddingH,
labelX;
if (offset === 0) {
labelX = this.labelPaddingH;
} else {
if (val < 0) {
if (offset >= labelOffsetWidth) {
labelX = offset - labelOffsetWidth + this.labelPaddingH;
} else {
labelX = offset + this.labelPaddingH;
}
} else {
if (offset + labelOffsetWidth <= this.props.max) {
labelX = offset + this.labelPaddingH;
} else {
labelX = offset - labelOffsetWidth + this.labelPaddingH;
}
}
}
this.setState({
labelX: labelX,
barWidth: (this.props.item && this.props.width < 5 ? 5 : this.props.width)
}, this.animateAll);
},
animateAll: function() {
this.clearAnimations(this.refs.bar);
this.clearAnimations(this.refs.label);
this.animate(this.refs.bar, 'width', this.state.lastBarWidth, this.state.barWidth);
this.animate(this.refs.bar, 'x', this.state.lastBarX, this.props.x);
this.animate(this.refs.label, 'x', this.state.lastLabelX, this.state.labelX);
},
render: function() {
var label = this.props.item ? (this.props.item + ': ' + formatNumber(this.props.value)) : '',
labelWidth = textWidth(label),
labelOuterWidth = (labelWidth == 0 ? 0 : labelWidth + 2*this.labelPaddingH),
barX = (this.state.lastBarX && this.state.lastBarX !== this.props.x
? this.state.lastBarX
: this.props.x),
barWidth = (this.state.lastBarWidth && this.state.lastBarWidth !== this.state.barWidth
? this.state.lastBarWidth
: this.state.barWidth);
return (
<g onClick={this.props.onClick}>
<rect ref="bar" className="bar"
fill={this.props.color}
width={barWidth}
height={this.props.height}
x={barX}
y={this.props.y}
rx="2"
ry="2" />
<text ref="label" className="label"
x={this.state.labelX}
y={this.props.y + this.labelMarginV + this.labelHeight}>
{label}
</text>
</g>
);
}
});
@@ -193,107 +193,3 @@ var BarChart = React.createClass({
);
}
});
var Bar = React.createClass({
mixins: [ReactRouter.Navigation, ChartAnimationMixin],
height: 30,
labelPaddingH: 5, // Label horizontal padding
labelPaddingV: 2, // Label vertical padding
labelMarginV: 5, // Same as padding
labelHeight: 16, // Text size
labelOuterHeight: 20, // labelHeight + 2*labelPaddingV,
getInitialState: function() {
return {
labelX: 0,
lastLabelX: this.labelPaddingH
};
},
componentDidMount: function() {
this.calculateLabelPosition();
},
componentWillReceiveProps: function(newProps) {
if (_.isEqual(this.props, newProps)) {
return;
}
this.setState({
lastBarX: (this.props.x !== undefined ? this.props.x : newProps.x),
lastBarWidth: (this.props.width !== undefined ? this.props.width : newProps.width),
lastLabelX: this.state.labelX
}, this.calculateLabelPosition);
},
calculateLabelPosition: function() {
var val = this.props.value,
offset = this.props.offset,
label = this.props.item + ': ' + formatNumber(val),
labelWidth = textWidth(label),
labelOffsetWidth = labelWidth + 2*this.labelPaddingH,
labelX;
if (offset === 0) {
labelX = this.labelPaddingH;
} else {
if (val < 0) {
if (offset >= labelOffsetWidth) {
labelX = offset - labelOffsetWidth + this.labelPaddingH;
} else {
labelX = offset + this.labelPaddingH;
}
} else {
if (offset + labelOffsetWidth <= this.props.max) {
labelX = offset + this.labelPaddingH;
} else {
labelX = offset - labelOffsetWidth + this.labelPaddingH;
}
}
}
this.setState({
labelX: labelX,
barWidth: (this.props.item && this.props.width < 5 ? 5 : this.props.width)
}, this.animateAll);
},
animateAll: function() {
this.clearAnimations(this.refs.bar);
this.clearAnimations(this.refs.label);
this.animate(this.refs.bar, 'width', this.state.lastBarWidth, this.state.barWidth);
this.animate(this.refs.bar, 'x', this.state.lastBarX, this.props.x);
this.animate(this.refs.label, 'x', this.state.lastLabelX, this.state.labelX);
},
render: function() {
var label = this.props.item ? (this.props.item + ': ' + formatNumber(this.props.value)) : '',
labelWidth = textWidth(label),
labelOuterWidth = (labelWidth == 0 ? 0 : labelWidth + 2*this.labelPaddingH),
barX = (this.state.lastBarX && this.state.lastBarX !== this.props.x
? this.state.lastBarX
: this.props.x),
barWidth = (this.state.lastBarWidth && this.state.lastBarWidth !== this.state.barWidth
? this.state.lastBarWidth
: this.state.barWidth);
return (
<g onClick={this.props.onClick}>
<rect ref="bar" className="bar"
fill={this.props.color}
width={barWidth}
height={this.props.height}
x={barX}
y={this.props.y}
rx="2"
ry="2" />
<text ref="label" className="label"
x={this.state.labelX}
y={this.props.y + this.labelMarginV + this.labelHeight}>
{label}
</text>
</g>
);
}
});
-31
View File
@@ -1,31 +0,0 @@
var SVGChartMixin = {
calculateViewBoxWidth: function() {
this.setState({
canvasWidth: this.refs.svg.getDOMNode().offsetWidth
});
}
};
var fontFamily = "'Open Sans', Helvetica, Arial, sans-serif",
fontSize = 16;
function textWidth(str) {
var svg = document.createElementNS('http://www.w3.org/2000/svg', "svg");
text = document.createElementNS('http://www.w3.org/2000/svg', "text");
svg.width = 500;
svg.height = 500;
svg.style.position = 'absolute';
svg.style.left = '-1000px';
text.appendChild(document.createTextNode(str))
text.style.fontFamily = fontFamily;
text.style.fontSize = fontSize +'px';
svg.appendChild(text);
document.body.appendChild(svg);
var box = text.getBBox();
document.body.removeChild(svg);
return box.width;
}
+29
View File
@@ -0,0 +1,29 @@
var Area = React.createClass({
mixins: [ChartAnimationMixin],
getInitialState: function() {
return {};
},
componentWillReceiveProps: function(newProps) {
this.setState({
lastd: this.props.d || newProps.d,
}, this.animateAll);
},
animateAll: function() {
this.clearAnimations(this.refs.path);
this.animate(this.refs.path, 'd', this.state.lastd, this.props.d);
},
render: function() {
return (
<path ref="path"
className={'path path-'+ this.props.i}
d={this.state.lastd || this.props.d}
fill={this.props.color}
onMouseOver={this.props.onMouseOver}
shapeRendering="optimizeQuality" />
);
}
});
+68
View File
@@ -0,0 +1,68 @@
var Axis = React.createClass({
topMargin: 2,
markHeight: 5,
render: function() {
if (this.props.weeks.length === 0) {
return null;
}
var renderMark = function(week, i) {
var len = this.props.weeks.length,
x = i/(len - 1)*this.props.width,
showLabel,
ta = (i === 0 // Text anchor for the leftmost label
? 'start'
: (i === len - 1 // Text anchor for the rightmost label
? 'end'
: 'middle')); // Text anchor for other labels
// Thin out labels
if (len > 20) {
showLabel = (i % 3 === 0);
} else if (len > 10) {
showLabel = (i % 2 === 0);
} else {
showLabel = true;
}
return (
<g key={'mark-'+ i}>
<line className="axis"
x1={x}
y1={this.props.y + this.topMargin}
x2={x}
y2={this.props.y + this.topMargin + this.markHeight} />
{!showLabel ? null : <text className="axis-mark"
x={x}
y={this.props.y + this.topMargin + 14}
textAnchor={ta}
>
{formatDate(week)}
</text>}
</g>
);
}.bind(this);
return (
<g ref="axis">
<rect // This rect hides area bouncing glitches
x="0"
y={this.props.y}
width={this.props.width}
height={this.props.height}
fill="#fff" />
<line className="axis"
x1="0"
y1={this.props.y + this.topMargin}
x2={this.props.width}
y2={this.props.y + this.topMargin} />
{this.props.weeks.map(renderMark)}
<line className="axis"
x1={this.props.width - 1}
y1={this.props.y + this.topMargin}
x2={this.props.width - 1}
y2={this.props.y + this.topMargin + this.markHeight} />
</g>
)
}
});
+36
View File
@@ -0,0 +1,36 @@
var Dot = React.createClass({
mixins: [ChartAnimationMixin],
radius: 10,
getInitialState: function() {
return {};
},
componentWillReceiveProps: function(newProps) {
this.setState({
lastY: this.props.y || newProps.y
}, this.animateAll);
},
animateAll: function() {
this.clearAnimations(this.refs.dot);
this.animate(this.refs.dot, 'cy', this.state.lastY, this.props.y);
},
render: function() {
return (
<g className={'dot dot-'+ this.props.i} onMouseOver={this.props.onMouseOver}>
<circle ref="dot"
cx={this.props.x}
cy={this.state.lastY || this.props.y}
r={this.radius} />
<text ref="value"
x={this.props.x}
y={this.props.y+4}>
{this.props.value}
</text>
</g>
);
}
});
@@ -191,7 +191,7 @@ var StackedAreaChart = React.createClass({
var item = pair[0], path = pair[1];
// NOTE: Rounded bottom corners is a side-effect
return (
<StackedArea key={'area-'+ i}
<Area key={'area-'+ i}
item={item} i={i}
d={roundPathCorners(this.buildPathD(path), 3)}
color={Colors[i]}
@@ -334,139 +334,3 @@ var StackedAreaChart = React.createClass({
);
}
});
var StackedArea = React.createClass({
mixins: [ChartAnimationMixin],
getInitialState: function() {
return {};
},
componentWillReceiveProps: function(newProps) {
this.setState({
lastd: this.props.d || newProps.d,
}, this.animateAll);
},
animateAll: function() {
this.clearAnimations(this.refs.path);
this.animate(this.refs.path, 'd', this.state.lastd, this.props.d);
},
render: function() {
return (
<path ref="path"
className={'path path-'+ this.props.i}
d={this.state.lastd || this.props.d}
fill={this.props.color}
onMouseOver={this.props.onMouseOver}
shapeRendering="optimizeQuality" />
);
}
});
var Dot = React.createClass({
mixins: [ChartAnimationMixin],
radius: 10,
getInitialState: function() {
return {};
},
componentWillReceiveProps: function(newProps) {
this.setState({
lastY: this.props.y || newProps.y
}, this.animateAll);
},
animateAll: function() {
this.clearAnimations(this.refs.dot);
this.animate(this.refs.dot, 'cy', this.state.lastY, this.props.y);
},
render: function() {
return (
<g className={'dot dot-'+ this.props.i} onMouseOver={this.props.onMouseOver}>
<circle ref="dot"
cx={this.props.x}
cy={this.state.lastY || this.props.y}
r={this.radius} />
<text ref="value"
x={this.props.x}
y={this.props.y+4}>
{this.props.value}
</text>
</g>
);
}
});
var Axis = React.createClass({
topMargin: 2,
markHeight: 5,
render: function() {
if (this.props.weeks.length === 0) {
return null;
}
var renderMark = function(week, i) {
var len = this.props.weeks.length,
x = i/(len - 1)*this.props.width,
showLabel,
ta = (i === 0 // Text anchor for the leftmost label
? 'start'
: (i === len - 1 // Text anchor for the rightmost label
? 'end'
: 'middle')); // Text anchor for other labels
// Thin out labels
if (len > 20) {
showLabel = (i % 3 === 0);
} else if (len > 10) {
showLabel = (i % 2 === 0);
} else {
showLabel = true;
}
return (
<g key={'mark-'+ i}>
<line className="axis"
x1={x}
y1={this.props.y + this.topMargin}
x2={x}
y2={this.props.y + this.topMargin + this.markHeight} />
{!showLabel ? null : <text className="axis-mark"
x={x}
y={this.props.y + this.topMargin + 14}
textAnchor={ta}
>
{formatDate(week)}
</text>}
</g>
);
}.bind(this);
return (
<g ref="axis">
<rect // This rect hides area bouncing glitches
x="0"
y={this.props.y}
width={this.props.width}
height={this.props.height}
fill="#fff" />
<line className="axis"
x1="0"
y1={this.props.y + this.topMargin}
x2={this.props.width}
y2={this.props.y + this.topMargin} />
{this.props.weeks.map(renderMark)}
<line className="axis"
x1={this.props.width - 1}
y1={this.props.y + this.topMargin}
x2={this.props.width - 1}
y2={this.props.y + this.topMargin + this.markHeight} />
</g>
)
}
});
+7
View File
@@ -0,0 +1,7 @@
var SVGChartMixin = {
calculateViewBoxWidth: function() {
this.setState({
canvasWidth: this.refs.svg.getDOMNode().offsetWidth
});
}
};