summaryrefslogtreecommitdiff
path: root/app/client/common/slider.component.js
blob: 174877d3129ffc6cbd56f14a2aae1c4b75cef7cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
import { h, Component } from 'preact'
import { connect } from 'react-redux'
import { bindActionCreators } from 'redux'
import * as liveActions from '../live/actions'

const SLIDER_THROTTLE_TIME = 100

class Slider extends Component {
  constructor(props){
    super(props)
    this.timeout = 0
    this.state = {
      value: props.opt[props.name]
    }
    this.handleInput = this.handleInput.bind(this)
    this.handleRange = this.handleRange.bind(this)
  }
  componentWillReceiveProps(nextProps) {
    const next_value = nextProps.value || nextProps.opt[nextProps.name]
    if (next_value !== this.state.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 (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 (old_value !== new_value) {
      this.setState({ value: new_value })
      this.props.actions.set_param(this.props.name, 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)
    }
    this.setState({ value: new_value })
    this.timeout = setTimeout(() => {
      this.props.actions.set_param(this.props.name, new_value)
      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;
    if (this.props.type === 'int') {
      step = 1
    } else {
      step = (this.props.max - this.props.min) / 100
      text_value = parseFloat(value).toFixed(2)
    }
    return (
      <div class='slider param'>
        <label>
          <span>{title || name.replace(/_/g, ' ')}</span>
          <input type='text' value={text_value} onBlur={this.handleInput} />
        </label>
        <input
          type='range'
          min={this.props.min}
          max={this.props.max}
          step={step}
          value={value}
          onInput={this.handleRange}
        />
      </div>
    )
  }
}

const mapStateToProps = state => ({
  opt: state.live.opt,
})

const mapDispatchToProps = (dispatch, ownProps) => ({
  actions: bindActionCreators(liveActions, dispatch)
})

export default connect(mapStateToProps, mapDispatchToProps)(Slider)