summaryrefslogtreecommitdiff
path: root/frontend/common/slider.component.js
diff options
context:
space:
mode:
authorJules Laplace <julescarbon@gmail.com>2020-06-08 00:53:10 +0200
committerJules Laplace <julescarbon@gmail.com>2020-06-08 00:53:10 +0200
commit734c19347e5ff307c2412289248f95dc66db94f1 (patch)
tree11dfa40e49275f54154bc46212d5078df843209f /frontend/common/slider.component.js
parent084333904ab589788a121b44461f242006545594 (diff)
slider component
Diffstat (limited to 'frontend/common/slider.component.js')
-rw-r--r--frontend/common/slider.component.js98
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>
+ )
+ }
+}