diff options
author | Aldo Cortesi <aldo@corte.si> | 2016-06-11 16:08:14 +1200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2016-06-11 16:08:14 +1200 |
commit | 227d762cace09bc315e57644da2135480bf32cb9 (patch) | |
tree | dd1b458e77d79a8f7867e31f7a352c19e586e129 /web/src/js/components/Header/FilterInput.jsx | |
parent | 250b47487aa071e61f0bd2960992e80222103a3a (diff) | |
parent | 0b241a1da71ef9eb7632fc0e32abcf061dcbd217 (diff) | |
download | mitmproxy-227d762cace09bc315e57644da2135480bf32cb9.tar.gz mitmproxy-227d762cace09bc315e57644da2135480bf32cb9.tar.bz2 mitmproxy-227d762cace09bc315e57644da2135480bf32cb9.zip |
Merge branch 'master' into toxfiddle
Diffstat (limited to 'web/src/js/components/Header/FilterInput.jsx')
-rw-r--r-- | web/src/js/components/Header/FilterInput.jsx | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/web/src/js/components/Header/FilterInput.jsx b/web/src/js/components/Header/FilterInput.jsx new file mode 100644 index 00000000..5b49b788 --- /dev/null +++ b/web/src/js/components/Header/FilterInput.jsx @@ -0,0 +1,133 @@ +import React, { PropTypes, Component } from 'react' +import ReactDOM from 'react-dom' +import classnames from 'classnames' +import { Key } from '../../utils.js' +import Filt from '../../filt/filt' +import FilterDocs from './FilterDocs' + +export default class FilterInput extends Component { + + static contextTypes = { + returnFocus: React.PropTypes.func, + } + + constructor(props, context) { + super(props, context) + + // Consider both focus and mouseover for showing/hiding the tooltip, + // because onBlur of the input is triggered before the click on the tooltip + // finalized, hiding the tooltip just as the user clicks on it. + this.state = { value: this.props.value, focus: false, mousefocus: false } + + this.onChange = this.onChange.bind(this) + this.onFocus = this.onFocus.bind(this) + this.onBlur = this.onBlur.bind(this) + this.onKeyDown = this.onKeyDown.bind(this) + this.onMouseEnter = this.onMouseEnter.bind(this) + this.onMouseLeave = this.onMouseLeave.bind(this) + } + + componentWillReceiveProps(nextProps) { + this.setState({ value: nextProps.value }) + } + + isValid(filt) { + try { + const str = filt == null ? this.state.value : filt + if (str) { + Filt.parse(str) + } + return true + } catch (e) { + return false + } + } + + getDesc() { + if (!this.state.value) { + return <FilterDocs/> + } + try { + return Filt.parse(this.state.value).desc + } catch (e) { + return '' + e + } + } + + onChange(e) { + const value = e.target.value + this.setState({ value }) + + // Only propagate valid filters upwards. + if (this.isValid(value)) { + this.props.onChange(value) + } + } + + onFocus() { + this.setState({ focus: true }) + } + + onBlur() { + this.setState({ focus: false }) + } + + onMouseEnter() { + this.setState({ mousefocus: true }) + } + + onMouseLeave() { + this.setState({ mousefocus: false }) + } + + onKeyDown(e) { + if (e.keyCode === Key.ESC || e.keyCode === Key.ENTER) { + this.blur() + // If closed using ESC/ENTER, hide the tooltip. + this.setState({mousefocus: false}) + } + e.stopPropagation() + } + + blur() { + ReactDOM.findDOMNode(this.refs.input).blur() + this.context.returnFocus() + } + + select() { + ReactDOM.findDOMNode(this.refs.input).select() + } + + render() { + const { type, color, placeholder } = this.props + const { value, focus, mousefocus } = this.state + return ( + <div className={classnames('filter-input input-group', { 'has-error': !this.isValid() })}> + <span className="input-group-addon"> + <i className={'fa fa-fw fa-' + type} style={{ color }}></i> + </span> + <input + type="text" + ref="input" + placeholder={placeholder} + className="form-control" + value={value} + onChange={this.onChange} + onFocus={this.onFocus} + onBlur={this.onBlur} + onKeyDown={this.onKeyDown} + /> + {(focus || mousefocus) && ( + <div className="popover bottom" + onMouseEnter={this.onMouseEnter} + onMouseLeave={this.onMouseLeave}> + <div className="arrow"></div> + <div className="popover-content"> + {this.getDesc()} + </div> + </div> + )} + </div> + ) + } +} |