diff options
| author | Jules Laplace <julescarbon@gmail.com> | 2020-06-08 00:53:10 +0200 |
|---|---|---|
| committer | Jules Laplace <julescarbon@gmail.com> | 2020-06-08 00:53:10 +0200 |
| commit | 734c19347e5ff307c2412289248f95dc66db94f1 (patch) | |
| tree | 11dfa40e49275f54154bc46212d5078df843209f /frontend/common/slider.component.js | |
| parent | 084333904ab589788a121b44461f242006545594 (diff) | |
slider component
Diffstat (limited to 'frontend/common/slider.component.js')
| -rw-r--r-- | frontend/common/slider.component.js | 98 |
1 files changed, 98 insertions, 0 deletions
diff --git a/frontend/common/slider.component.js b/frontend/common/slider.component.js new file mode 100644 index 0000000..70a4abd --- /dev/null +++ b/frontend/common/slider.component.js @@ -0,0 +1,98 @@ +import { React, Component } from 'preact' + +const SLIDER_THROTTLE_TIME = 100 + +export default class Slider extends Component { + constructor(props){ + super(props) + this.timeout = 0 + this.state = { + value: props.value + } + this.handleInput = this.handleInput.bind(this) + this.handleRange = this.handleRange.bind(this) + } + UNSAFE_componentWillReceiveProps(nextProps) { + let next_value = nextProps.value || nextProps.opt[nextProps.name] + if (next_value !== this.state.value) { + if (this.props.type === 'int') { + next_value = parseInt(next_value) + } + this.setState({ value: next_value }) + } + } + handleInput(e){ + let { name, opt } = this.props + let old_value = opt[name] + let new_value = e.target.value + if (new_value === '') { + new_value = this.props.defaultValue || (this.props.max - this.props.min) / 2 + } + else if (this.props.type === 'int') { + new_value = parseInt(new_value) + } + else if (this.props.type === 'odd') { + new_value = parseInt(Math.floor(new_value / 2) * 2 + 1) + } + if (old_value !== new_value) { + this.setState({ value: new_value }) + this.props.onChange && this.props.onChange(new_value) + } + clearTimeout(this.timeout) + } + handleRange(e){ + clearTimeout(this.timeout) + let new_value = e.target.value + if (this.props.type === 'int') { + new_value = parseInt(new_value) + } + if (this.props.type === 'odd') { + new_value = parseInt(Math.floor(new_value / 2) * 2 + 1) + } + if (this.props.type === 'list') { + new_value = this.props.options[new_value] || this.props.options[0] + } + this.setState({ value: new_value }) + this.timeout = setTimeout(() => { + this.props.onChange && this.props.onChange(new_value) + }, SLIDER_THROTTLE_TIME) + } + render(){ + let { name, title } = this.props + let value = this.state.value + if (typeof value === 'undefined') { + value = this.props.min + } + let text_value = value + let step; + let min = this.props.min || 0 + let max = this.props.max || 0 + if (this.props.type === 'int') { + step = 1 + } else if (this.props.type === 'list') { + min = 0 + max = this.props.options.length-1 + step = 1 + value = this.props.options.indexOf(value) + } else { + step = (this.props.max - this.props.min) / 100 + text_value = parseFloat(value).toFixed(2) + } + return ( + <div className='slider param'> + <label> + <span>{title || name.replace(/_/g, ' ')}</span> + <input type='text' value={text_value} onBlur={this.handleInput} /> + </label> + <input + type='range' + min={min} + max={max} + step={step} + value={value} + onInput={this.handleRange} + /> + </div> + ) + } +} |
