X-Git-Url: https://osm.etsi.org/gitweb/?a=blobdiff_plain;ds=sidebyside;f=skyquake%2Fframework%2Fwidgets%2Finput-range-slider%2Freact-rangeslider.jsx;fp=skyquake%2Fframework%2Fwidgets%2Finput-range-slider%2Freact-rangeslider.jsx;h=feff1eb1c47c3d901122fe1ebee1c7033b49fae5;hb=e29efc315df33d546237e270470916e26df391d6;hp=0000000000000000000000000000000000000000;hpb=9c5e457509ba5a1822c316635c6308874e61b4b9;p=osm%2FUI.git diff --git a/skyquake/framework/widgets/input-range-slider/react-rangeslider.jsx b/skyquake/framework/widgets/input-range-slider/react-rangeslider.jsx new file mode 100644 index 000000000..feff1eb1c --- /dev/null +++ b/skyquake/framework/widgets/input-range-slider/react-rangeslider.jsx @@ -0,0 +1,251 @@ + +/* + * + * Copyright 2016 RIFT.IO Inc + * + * 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. + * + */ +/** + * https://github.com/larsmaultsby/react-rangeslider + * + * + * Forked from: https://github.com/whoisandie/react-rangeslider + * + * + The MIT License (MIT) + + Copyright (c) 2015 Bhargav Anand + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + SOFTWARE. + * + */ + +import React, { PropTypes, Component, findDOMNode } from 'react'; +import joinClasses from 'react/lib/joinClasses'; + +function capitalize(str) { + return str.charAt(0).toUpperCase() + str.substr(1); +} + +function maxmin(pos, min, max) { + if (pos < min) { return min; } + if (pos > max) { return max; } + return pos; +} + +const constants = { + orientation: { + horizontal: { + dimension: 'width', + direction: 'left', + coordinate: 'x', + }, + vertical: { + dimension: 'height', + direction: 'top', + coordinate: 'y', + } + } +}; + +class Slider extends Component { + static propTypes = { + min: PropTypes.number, + max: PropTypes.number, + step: PropTypes.number, + value: PropTypes.number, + orientation: PropTypes.string, + onChange: PropTypes.func, + className: PropTypes.string, + } + + static defaultProps = { + min: 0, + max: 100, + step: 1, + value: 0, + orientation: 'horizontal', + } + + state = { + limit: 0, + grab: 0 + } + + // Add window resize event listener here + componentDidMount() { + this.calculateDimensions(); + window.addEventListener('resize', this.calculateDimensions); + } + + componentWillUnmount() { + window.removeEventListener('resize', this.calculateDimensions); + } + + handleSliderMouseDown = (e) => { + let value, { onChange } = this.props; + if (!onChange) return; + value = this.position(e); + onChange && onChange(value); + } + + handleKnobMouseDown = () => { + document.addEventListener('mousemove', this.handleDrag); + document.addEventListener('mouseup', this.handleDragEnd); + } + + handleDrag = (e) => { + let value, { onChange } = this.props; + if (!onChange) return; + value = this.position(e); + onChange && onChange(value); + } + + handleDragEnd = () => { + document.removeEventListener('mousemove', this.handleDrag); + document.removeEventListener('mouseup', this.handleDragEnd); + } + + handleNoop = (e) => { + e.stopPropagation(); + e.preventDefault(); + } + + calculateDimensions = () => { + let { orientation } = this.props; + let dimension = capitalize(constants.orientation[orientation].dimension); + const sliderPos = findDOMNode(this.refs.slider)['offset' + dimension]; + const handlePos = findDOMNode(this.refs.handle)['offset' + dimension] + this.setState({ + limit: sliderPos - handlePos, + grab: handlePos / 2, + }); + } + getPositionFromValue = (value) => { + let percentage, pos; + let { limit } = this.state; + let { min, max } = this.props; + percentage = (value - min) / (max - min); + pos = Math.round(percentage * limit); + + return pos; + } + + getValueFromPosition = (pos) => { + let percentage, value; + let { limit } = this.state; + let { orientation, min, max, step } = this.props; + percentage = (maxmin(pos, 0, limit) / (limit || 1)); + + if (orientation === 'horizontal') { + value = step * Math.round(percentage * (max - min) / step) + min; + } else { + value = max - (step * Math.round(percentage * (max - min) / step) + min); + } + + return value; + } + + position = (e) => { + let pos, value, { grab } = this.state; + let { orientation } = this.props; + const node = findDOMNode(this.refs.slider); + const coordinateStyle = constants.orientation[orientation].coordinate; + const directionStyle = constants.orientation[orientation].direction; + const coordinate = e['client' + capitalize(coordinateStyle)]; + const direction = node.getBoundingClientRect()[directionStyle]; + + pos = coordinate - direction - grab; + value = this.getValueFromPosition(pos); + + return value; + } + + coordinates = (pos) => { + let value, fillPos, handlePos; + let { limit, grab } = this.state; + let { orientation } = this.props; + value = this.getValueFromPosition(pos); + handlePos = this.getPositionFromValue(value); + + if (orientation === 'horizontal') { + fillPos = handlePos + grab; + } else { + fillPos = limit - handlePos + grab; + } + + return { + fill: fillPos, + handle: handlePos, + }; + } + + render() { + let dimension, direction, position, coords, fillStyle, handleStyle, displayValue; + let { value, orientation, className } = this.props; + + dimension = constants.orientation[orientation].dimension; + direction = constants.orientation[orientation].direction; + + position = this.getPositionFromValue(value); + coords = this.coordinates(position); + + fillStyle = {[dimension]: `${coords.fill}px`}; + handleStyle = {[direction]: `${coords.handle}px`}; + + if(this.props.displayValue) { + displayValue =
{this.props.value}
; + } + + return ( +
+
+
+ {displayValue} +
+
+ ); + } +} + +export default Slider;