diff --git a/examples/marks.js b/examples/marks.js index a487bc0..6e1dac6 100644 --- a/examples/marks.js +++ b/examples/marks.js @@ -7,7 +7,15 @@ var ReactDOM = require('react-dom'); var Slider = require('rc-slider'); var style = {width: 400, margin: 50}; -var marks = ['A','B','C','D', 'E', 'F']; +var marks = { + 0: 'A', + 20: 'B', + 40: 'C', + 60: 'D', + 80: 'E', + 100: 'F' +}; + var log = function(value) { console.log(value); }; diff --git a/src/Marks.jsx b/src/Marks.jsx index 7a03023..db7ace7 100644 --- a/src/Marks.jsx +++ b/src/Marks.jsx @@ -1,35 +1,36 @@ import React from 'react'; import rcUtil from 'rc-util'; -const Marks = ({className, marks, index, included}) => { - const marksLen = marks.length; - const unit = 100 / (marksLen - 1); +const Marks = ({className, marks, included, upperBound, lowerBound, max, min}) => { + const marksKeys = Object.keys(marks); + const marksCount = marksKeys.length; + const unit = 100 / (marksCount - 1); const markWidth = unit / 2 + '%'; - const elements = []; - for (let i = 0; i < marksLen; i++) { - const isActived = (included && i <= index) || (!included && i === index); + const range = max - min; + const elements = marksKeys.map(parseFloat).map((point) => { + const isActived = (!included && point === upperBound) || + (included && point <= upperBound && point >= lowerBound); const markClassName = rcUtil.classSet({ [className + '-text']: true, [className + '-text-active']: isActived, }); const style = { width: markWidth }; - const offset = unit * i; - if (i === marksLen - 1) { + if (point === marksCount - 1) { style.right = -unit / 4 + '%'; + } else if (point === 0) { + style.left = -unit / 4 + '%'; } else { - style.left = (i > 0 ? offset - unit / 4 : -unit / 4) + '%'; + style.left = (point - min) / range * 100 - unit / 4 + '%'; } - elements.push( - {marks[i]} - ); - } + return ( + {marks[point]} + ); + }); - return (
- {elements} -
); + return
{elements}
; }; export default Marks; diff --git a/src/Slider.jsx b/src/Slider.jsx index 2baca4a..99fe49a 100644 --- a/src/Slider.jsx +++ b/src/Slider.jsx @@ -25,6 +25,10 @@ function pauseEvent(e) { e.preventDefault(); } +function isEmpty(collection) { + return Object.keys(collection).length === 0; +} + // This is an utility method, tries to get property, then defaultPropery with // special check using 'in', because propery can be '0' function propOrDefault(props, name, fallback) { @@ -40,7 +44,7 @@ class Slider extends React.Component { let upperBound; let lowerBound; const initialValue = props.range ? [0, 0] : 0; - if (props.marks.length > 0) { + if (!isEmpty(props.marks)) { const index = propOrDefault(props, 'index', initialValue); ({lowerBound, upperBound} = this.getBoundsFromIndex(index, props)); } else { @@ -139,7 +143,7 @@ class Slider extends React.Component { pauseEvent(e); } - onSliderMouseDown(e) { + onMouseDown(e) { const position = getMousePosition(e); this.onStart(position); this.addDocumentEvents('mouse'); @@ -209,10 +213,10 @@ class Slider extends React.Component { getIndex(value) { const {marks, min, max, step} = this.props; - if (marks.length === 0) { + if (isEmpty(marks)) { return Math.floor((value - min) / step); } - const unit = ((max - min) / (marks.length - 1)).toFixed(5); + const unit = ((max - min) / (Object.keys(marks).length - 1)).toFixed(5); return Math.round(value / unit); } @@ -228,6 +232,17 @@ class Slider extends React.Component { }; } + getPoints() { + const {marks, step, dots, min, max} = this.props; + const points = new Set(Object.keys(marks)); + if (step > 1 && dots) { + for (let i = min; i <= max; i = i + step) { + points.add(i); + } + } + return Array.from(points); + } + getSliderLength() { const slider = this.refs.slider; if (!slider) { @@ -249,7 +264,7 @@ class Slider extends React.Component { const {handle, lowerBound, upperBound} = state; const props = this.props; const {marks, min, max} = props; - const marksLen = marks.length; + const marksLen = Object.keys(marks).length; const step = (marksLen > 0) ? (max - min) / (marksLen - 1) : props.step; let val = v; @@ -295,7 +310,7 @@ class Slider extends React.Component { } calcValueFromIndex(index, props) { - const marksLen = props.marks.length; + const marksLen = Object.keys(props.marks).length; if (marksLen > 0) { const value = ((props.max - props.min) / (marksLen - 1)) * (index); return parseFloat(value.toFixed(5)); @@ -305,7 +320,7 @@ class Slider extends React.Component { triggerEvents(event, v) { const props = this.props; - const hasMarks = (props.marks.length > 0); + const hasMarks = !isEmpty(props.marks); if (props[event]) { let data; if (hasMarks) { @@ -352,9 +367,9 @@ class Slider extends React.Component { render() { const {handle, upperBound, lowerBound} = this.state; - const {className, prefixCls, disabled, included, dots, range, - marks, step, max, min, tipTransitionName, tipFormatter, children} = this.props; - const marksLen = marks.length; + const {className, prefixCls, disabled, included, range, + marks, max, min, tipTransitionName, tipFormatter, children} = this.props; + const marksLen = Object.keys(marks).length; const sliderClassName = classSet({ [prefixCls]: true, @@ -382,33 +397,20 @@ class Slider extends React.Component { offset={lowerOffset} value={lowerBound} dragging={handle === 'lowerBound'} />); } - const upperIndex = this.getIndex(upperBound); - - let steps = null; - if (marksLen > 0 || (step > 1 && dots)) { - const stepsClassName = prefixCls + '-step'; - const stepNum = marksLen > 0 ? marksLen : Math.floor((max - min) / step) + 1; - steps = (); - } - - let mark = null; - if (marksLen > 0) { - const markClassName = prefixCls + '-mark'; - mark = (); - } - + const isIncluded = included || range; return (
+ onMouseDown={disabled ? noop : this.onMouseDown.bind(this)}> {track} {upper} {lower} - {steps} - {mark} + + {children}
); @@ -435,7 +437,7 @@ Slider.propTypes = { React.PropTypes.number, React.PropTypes.arrayOf(React.PropTypes.number), ]), - marks: React.PropTypes.array, + marks: React.PropTypes.object, included: React.PropTypes.bool, className: React.PropTypes.string, prefixCls: React.PropTypes.string, @@ -455,7 +457,7 @@ Slider.defaultProps = { max: 100, step: 1, defaultIndex: 0, - marks: [], + marks: {}, included: true, className: '', prefixCls: 'rc-slider', diff --git a/src/Steps.jsx b/src/Steps.jsx index da2cdb0..816dcd5 100644 --- a/src/Steps.jsx +++ b/src/Steps.jsx @@ -1,28 +1,23 @@ import React from 'react'; -import rcUtil from 'rc-util'; +import { classSet } from 'rc-util'; -const Steps = ({className, stepNum, included, lowerIndex, upperIndex}) => { - const dotClassName = className.replace('step', 'dot'); - const unit = 100 / (stepNum - 1); - - const elements = []; - for (let i = 0; i < stepNum; i++) { - const offset = unit * i + '%'; +const Steps = ({prefixCls, points, included, lowerBound, upperBound, max, min}) => { + const range = max - min; + const elements = points.map(parseFloat).map((point) => { + const offset = (point - min) / range * 100 + '%'; const style = { left: offset }; - const isActived = (included && i <= upperIndex && i >= lowerIndex ) || - (!included && i === upperIndex); - const stepClassName = rcUtil.classSet({ - [dotClassName]: true, - [dotClassName + '-active']: isActived, + const isActived = (!included && point === upperBound) || + (included && point <= upperBound && point >= lowerBound); + const pointClassName = classSet({ + [prefixCls + '-dot']: true, + [prefixCls + '-dot-active']: isActived, }); - elements.push(); - } + return ; + }); - return (
- {elements} -
); + return
{elements}
; }; export default Steps;