From 70472fb599cdfac5c149ea4cef3e4bd3532b9081 Mon Sep 17 00:00:00 2001 From: simaQ Date: Wed, 22 Apr 2015 16:11:37 +0800 Subject: [PATCH 1/4] update slider's stylesheet --- assets/index.less | 83 +++++++++++++++++++++++++---------------------- 1 file changed, 45 insertions(+), 38 deletions(-) diff --git a/assets/index.less b/assets/index.less index 60b2d61..d3f0c32 100644 --- a/assets/index.less +++ b/assets/index.less @@ -1,24 +1,21 @@ @prefixClass: rc-slider; // color -@sliderColor: #999; -@trackColor: #b2e9fd; -@normalHandleColor: #d9d9d9; -@activeHandleColor: #2db7f5; -@disabledColor: #e9e9e9; +@disabledColor: #e7eaec; .@{prefixClass} { position: relative; height: 4px; width: 100%; border-radius: 2px; - background-color: @sliderColor; + background-color: #e9e9e9; &-track { position: absolute; + left: 0; height: 4px; border-radius: 2px; - background-color: @trackColor; + background-color: #b2e9fd; z-index: 1; } @@ -30,15 +27,23 @@ height: 10px; cursor: default; border-radius: 50%; - border: solid 2px @normalHandleColor; + border: solid 2px #d9d9d9; background-color: #fff; z-index: 2; - &:hover, &:active, &.active { - border-color: @activeHandleColor; + + &:hover { + border-color: #999; } - &:active { - background-color: @activeHandleColor; - box-shadow: 0 0 3px 0 rgb(45, 183, 245, .75); + &-active { + border-color: #8cddfc; + &:active { + border-color: #2db7f5; + background-color: #2db7f5; + box-shadow: 0 0 0 5px rgba(45, 183, 245, .3); + } + &:hover { + border-color: #23c0fa; + } } } @@ -60,9 +65,13 @@ vertical-align: middle; text-align: center; cursor: pointer; + color: #ccc; &:first-child { text-align: left; - } + } + &-active { + color: #999; + } } &-step { @@ -71,27 +80,31 @@ height: 4px; background: transparent; z-index: 1; - .dot { - position: absolute; - top: -2px; - margin-left: -4px; - width: 4px; - height: 4px; - border: 2px solid #fff; - cursor: pointer; - border-radius: 50%; - vertical-align: middle; - &:first-child { - margin-left: -2px; - } - &:last-child { - margin-left: -6px; - } + } + + &-dot { + position: absolute; + top: -2px; + margin-left: -4px; + width: 4px; + height: 4px; + border: 2px solid #fff; + background-color: #bcbcbc; + cursor: pointer; + border-radius: 50%; + vertical-align: middle; + &:first-child { + margin-left: -2px; + } + &:last-child { + margin-left: -6px; + } + &-active { + background-color: #8cddfc; } } &-disabled { - color: @disabledColor; background-color: @disabledColor; .@{prefixClass}-track { @@ -100,14 +113,8 @@ .@{prefixClass}-handle { border-color: @disabledColor; - background-color: @disabledColor; + background-color: #fff; cursor: not-allowed; - - &:hover, &:active { - border-color: @disabledColor; - background-color: @disabledColor; - box-shadow: none; - } } .@{prefixClass}-mark-text, .dot { From a449b00bf6bfbcca5f68bea4e98f221f6ce8e19a Mon Sep 17 00:00:00 2001 From: simaQ Date: Wed, 22 Apr 2015 16:12:10 +0800 Subject: [PATCH 2/4] fix ie8 event bug --- lib/EventListener.js | 56 +++++++++++++++++++ lib/Slider.js | 129 +++++++++++++++++++++++++++---------------- 2 files changed, 138 insertions(+), 47 deletions(-) create mode 100644 lib/EventListener.js diff --git a/lib/EventListener.js b/lib/EventListener.js new file mode 100644 index 0000000..f8c9c23 --- /dev/null +++ b/lib/EventListener.js @@ -0,0 +1,56 @@ +/** + * Copyright 2013-2014 Facebook, Inc. + * + * This file contains a modified version of: + * https://github.com/facebook/react/blob/v0.12.0/src/vendor/stubs/EventListener.js + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * TODO: remove in favour of solution provided by: + * https://github.com/facebook/react/issues/285 + */ + +/** + * Does not take into account specific nature of platform. + */ +'use strict'; + +var EventListener = { + /** + * Listen to DOM events during the bubble phase. + * + * @param {DOMEventTarget} target DOM element to register listener on. + * @param {string} eventType Event type, e.g. 'click' or 'mouseover'. + * @param {function} callback Callback function. + * @return {object} Object with a `remove` method. + */ + listen: function listen(target, eventType, callback) { + if (target.addEventListener) { + target.addEventListener(eventType, callback, false); + return { + remove: function remove() { + target.removeEventListener(eventType, callback, false); + } + }; + } else if (target.attachEvent) { + target.attachEvent('on' + eventType, callback); + return { + remove: function remove() { + target.detachEvent('on' + eventType, callback); + } + }; + } + } +}; + +module.exports = EventListener; diff --git a/lib/Slider.js b/lib/Slider.js index 44f3237..b5c4146 100644 --- a/lib/Slider.js +++ b/lib/Slider.js @@ -1,5 +1,6 @@ /** @jsx React.DOM */ var React = require('react'); +var EventListener = require('./EventListener'); function pauseEvent(e) { if (e.stopPropagation) { @@ -13,6 +14,13 @@ function pauseEvent(e) { return false; } +function prefixClsFn(prefixCls) { + var args = Array.prototype.slice.call(arguments, 1); + return args.map((s)=> { + return prefixCls + '-' + s; + }).join(' '); +} + var Slider = React.createClass({ propTypes: { min: React.PropTypes.number, @@ -43,7 +51,7 @@ var Slider = React.createClass({ getInitialState: function() { var props = this.props; - var value = props.value; + var value = this._trimAlignValue(props.value); var marksLen = props.marks.length; if (marksLen > 0) { value = ((props.max - props.min) / (marksLen - 1)) * (props.index); @@ -54,7 +62,7 @@ var Slider = React.createClass({ upperBound: 0, sliderLength: 0, value: value, - active: props.disabled ? '' : ((value > 0 || props.index > 0) ? 'active' : '') + active: props.disabled ? '' : ((value > props.min || props.index > 0) ? 'active' : '') }; }, @@ -64,12 +72,14 @@ var Slider = React.createClass({ }, componentDidMount: function() { - window.addEventListener('resize', this.handleResize); + this._onHandleResizeListener = EventListener.listen(window, 'resize', this.handleResize); this.handleResize(); }, componentWillUnmount: function() { - window.removeEventListener('resize', this.handleResize); + if (this._onHandleResizeListener) { + this._onHandleResizeListener.remove(); + } }, getValue: function() { @@ -124,32 +134,30 @@ var Slider = React.createClass({ var nextValue = this._trimAlignValue(this._calcValue(pixelOffset)); - this.setState({value: nextValue, active: 'active'}, callback.bind(this)); + this.setState({value: nextValue, active: 'active'}, callback); }, _triggerEvents: function(event) { - if (this.props[event]) { - this.props[event](this.state.value); + var props = this.props; + var hasMarks = props.marks && props.marks.length > 0; + if (props[event]) { + props[event](hasMarks ? this.getIndex() : this.state.value); } }, - _addEventHandles: function(eventMap) { - for (var key in eventMap) { - document.addEventListener(key, eventMap[key], false); - } + _addEventHandles: function() { + this._onMouseMoveListener = EventListener.listen(document, 'mousemove', this._onMouseMove); + this._onMouseUpListener = EventListener.listen(document, 'mouseup', this._onMouseUp); }, - _removeEventHandles: function (eventMap) { - for (var key in eventMap) { - document.removeEventListener(key, eventMap[key], false); + _removeEventHandles: function () { + if (this._onMouseMoveListener) { + this._onMouseMoveListener.remove(); } - }, - _getMouseEventMap: function() { - return { - mousemove: this._onMouseMove, - mouseup: this._onMouseUp - }; + if (this._onMouseUpListener) { + this._onMouseUpListener.remove(); + } }, _start: function(position) { @@ -165,18 +173,18 @@ var Slider = React.createClass({ }); }, - _end: function(eventMap) { - this._removeEventHandles(eventMap); + _end: function() { + this._removeEventHandles(); this.setState(this._triggerEvents.bind(this, 'onAfterChange')); }, _onMouseUp: function() { - this._end(this._getMouseEventMap()); + this._end(); }, _onMouseMove: function(e) { - var position = e.pageX; - + pauseEvent(e); + var position = e.pageX || e.clientX; var props = this.props; var state = this.state; @@ -201,6 +209,7 @@ var Slider = React.createClass({ var sliderMin = rect.left; var sliderMax = rect.right; + this.setState({ upperBound: slider.clientWidth, sliderLength: Math.abs(sliderMax - sliderMin), @@ -209,27 +218,29 @@ var Slider = React.createClass({ }, handleMouseDown: function() { - return function(e) { + return (e) => { if (this.props.disabled) { return; } - var position = e.pageX; + var position = e.pageX || e.clientX; this._start(position); - this._addEventHandles(this._getMouseEventMap()); + this._addEventHandles(); pauseEvent(e); - }.bind(this); + }; }, handleSliderMouseDown: function(e) { if (this.props.disabled) { return; } - var position = e.pageX; - this._calValueByPos(position, function() { - this._triggerEvents('onChange'); - this._start(position); - this._addEventHandles(this._getMouseEventMap()); - }.bind(this)); + var position = e.pageX || e.clientX; + this._calValueByPos(position, + () => { + this._triggerEvents('onChange'); + this._start(position); + this._addEventHandles(); + } + ); pauseEvent(e); }, @@ -239,15 +250,21 @@ var Slider = React.createClass({ var stepNum = marksLen > 0 ? marksLen : Math.floor((props.max - props.min) / props.step) + 1; var unit = this.state.sliderLength / (stepNum - 1); - var stepClassName = props.className + '-step'; + var prefixCls = props.className; + var stepClassName = prefixClsFn(prefixCls, 'step'); var elements = []; for (var i = 0; i < stepNum; i++) { + var offset = unit * i; var style = { - left: (unit * i).toFixed(5) + 'px' + left: offset.toFixed(5) }; + var className = prefixClsFn(prefixCls, 'dot'); + if (i <= this.getIndex() || (this._calcValue(offset) <= this.getValue())) { + className = prefixClsFn(prefixCls, 'dot', 'dot-active'); + } elements[i] = ( - + ); } @@ -265,16 +282,22 @@ var Slider = React.createClass({ var offset = unit * i; var style = { - width: (unit / 2).toFixed(5) + 'px' + width: (unit / 2).toFixed(5) }; if (i === (marksLen - 1)) { style.right = '0'; style.width = 'auto'; }else { - style.left = (i > 0 ? (offset - (unit / 4)).toFixed(5) : offset) + 'px'; + style.left = (i > 0 ? (offset - (unit / 4)).toFixed(5) : offset); + } + + var prefixCls = this.props.className; + var className = prefixClsFn(prefixCls, 'mark-text'); + + if (i <= this.getIndex()) { + className = prefixClsFn(prefixCls, 'mark-text', 'mark-text-active'); } - var className = this.props.className + '-mark-text '; return ( {this.props.marks[i]} @@ -289,8 +312,11 @@ var Slider = React.createClass({ elements[i] = this.renderMark(i); } + var prefixCls = this.props.className; + var className = prefixClsFn(prefixCls, 'mark'); + return ( -
+
{elements}
); @@ -298,9 +324,15 @@ var Slider = React.createClass({ renderHandle: function(offset) { var handleStyle = { - left: offset + 'px' + left: offset }; - var className = this.props.className + '-handle ' + this.state.active; + + var prefixCls = this.props.className; + var className = prefixClsFn(prefixCls, 'handle'); + + if (this.state.active) { + className = prefixClsFn(prefixCls, 'handle', 'handle-active'); + } return (
); @@ -334,7 +368,8 @@ var Slider = React.createClass({ var steps = (props.step > 1 || props.marks.length > 0) ? this.renderSteps() : null; var sliderMarks = (props.marks.length > 0) ? this.renderMarks() : null; - var sliderClassName = props.className + (props.disabled ? ' '+props.className+ '-disabled' : ''); + var prefixCls = props.className; + var sliderClassName = props.disabled ? prefixClsFn(prefixCls, 'disabled') : prefixCls; return (
From 259d14e73d9bc9211c6c9c7058b35bd9fd7d7538 Mon Sep 17 00:00:00 2001 From: simaQ Date: Wed, 22 Apr 2015 16:12:36 +0800 Subject: [PATCH 3/4] update test case --- tests/index.spec.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/index.spec.js b/tests/index.spec.js index 525794f..87d094b 100644 --- a/tests/index.spec.js +++ b/tests/index.spec.js @@ -38,7 +38,7 @@ describe('rc-slider', function () { expect(node.find('.rc-slider').length).to.be(1); expect(node.find('.rc-slider-handle').length).to.be(1); expect(node.find('.rc-slider-track').length).to.be(1); - expect(node.find('.dot').length).to.be(6); + expect(node.find('.rc-slider-dot').length).to.be(6); expect(slider.getValue()).to.be(0); }); @@ -51,7 +51,7 @@ describe('rc-slider', function () { expect(node.find('.rc-slider').length).to.be(1); expect(node.find('.rc-slider-handle').length).to.be(1); expect(node.find('.rc-slider-track').length).to.be(1); - expect(node.find('.dot').length).to.be(slider.props.marks.length); + expect(node.find('.rc-slider-dot').length).to.be(slider.props.marks.length); expect(node.find('.rc-slider-mark').length).to.be(1); expect(node.find('.rc-slider-mark-text').length).to.be(slider.props.marks.length); expect(slider.getIndex()).to.be(3); From a68e0dcf3efc9d56070f5fc60458313f8b01e5d6 Mon Sep 17 00:00:00 2001 From: simaQ Date: Wed, 22 Apr 2015 19:43:48 +0800 Subject: [PATCH 4/4] correct e.clientX --- lib/Slider.js | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/Slider.js b/lib/Slider.js index b5c4146..5c92e6f 100644 --- a/lib/Slider.js +++ b/lib/Slider.js @@ -137,6 +137,10 @@ var Slider = React.createClass({ this.setState({value: nextValue, active: 'active'}, callback); }, + _getMousePosition: function(e) { + return e.pageX || (e.clientX + document.documentElement.scrollLeft); + }, + _triggerEvents: function(event) { var props = this.props; var hasMarks = props.marks && props.marks.length > 0; @@ -184,7 +188,7 @@ var Slider = React.createClass({ _onMouseMove: function(e) { pauseEvent(e); - var position = e.pageX || e.clientX; + var position = this._getMousePosition(e); var props = this.props; var state = this.state; @@ -222,7 +226,7 @@ var Slider = React.createClass({ if (this.props.disabled) { return; } - var position = e.pageX || e.clientX; + var position = this._getMousePosition(e); this._start(position); this._addEventHandles(); pauseEvent(e); @@ -233,7 +237,7 @@ var Slider = React.createClass({ if (this.props.disabled) { return; } - var position = e.pageX || e.clientX; + var position = this._getMousePosition(e); this._calValueByPos(position, () => { this._triggerEvents('onChange');