Fix paste in Inputs (#4854)

* Wait for the value to have changed in the input

* Better onPaste handler // Use ESC to revert to initial value
This commit is contained in:
Nicolas Gotchac 2017-03-10 14:08:21 +01:00 committed by Jaco Greeff
parent e5defeaada
commit 95745ef4c8

View File

@ -17,6 +17,7 @@
import React, { Component, PropTypes } from 'react'; import React, { Component, PropTypes } from 'react';
import { TextField } from 'material-ui'; import { TextField } from 'material-ui';
import { noop } from 'lodash'; import { noop } from 'lodash';
import keycode from 'keycode';
import { nodeOrStringProptype } from '~/util/proptypes'; import { nodeOrStringProptype } from '~/util/proptypes';
@ -92,6 +93,9 @@ export default class Input extends Component {
allowCopy: false, allowCopy: false,
hideUnderline: false, hideUnderline: false,
floatCopy: false, floatCopy: false,
onBlur: noop,
onFocus: noop,
onChange: noop,
readOnly: false, readOnly: false,
submitOnBlur: true, submitOnBlur: true,
style: {} style: {}
@ -120,7 +124,7 @@ export default class Input extends Component {
render () { render () {
const { value } = this.state; const { value } = this.state;
const { autoFocus, children, className, hideUnderline, disabled, error, focused, label } = this.props; const { autoFocus, children, className, hideUnderline, disabled, error, focused, label } = this.props;
const { hint, onClick, onFocus, multiLine, rows, type, min, max, style, tabIndex } = this.props; const { hint, onClick, multiLine, rows, type, min, max, style, tabIndex } = this.props;
const readOnly = this.props.readOnly || disabled; const readOnly = this.props.readOnly || disabled;
@ -169,7 +173,8 @@ export default class Input extends Component {
onChange={ this.onChange } onChange={ this.onChange }
onClick={ onClick } onClick={ onClick }
onKeyDown={ this.onKeyDown } onKeyDown={ this.onKeyDown }
onFocus={ onFocus } onKeyUp={ this.onKeyUp }
onFocus={ this.onFocus }
onPaste={ this.onPaste } onPaste={ this.onPaste }
readOnly={ readOnly } readOnly={ readOnly }
ref='input' ref='input'
@ -216,7 +221,12 @@ export default class Input extends Component {
event.persist(); event.persist();
this.setValue(value, () => { this.setValue(value, () => {
this.props.onChange && this.props.onChange(event, value); this.props.onChange(event, value);
if (this.pasted) {
this.pasted = false;
return this.onSubmit(value);
}
}); });
} }
@ -228,28 +238,54 @@ export default class Input extends Component {
this.onSubmit(value); this.onSubmit(value);
} }
this.props.onBlur && this.props.onBlur(event); this.props.onBlur(event);
}
onFocus = (event) => {
const { onFocus } = this.props;
this.intialValue = event.target.value;
return onFocus(event);
} }
onPaste = (event) => { onPaste = (event) => {
// Wait for the onChange handler to be called this.pasted = true;
window.setTimeout(() => {
this.onSubmit(this.state.value);
}, 200);
} }
onKeyDown = (event) => { onKeyDown = (event) => {
const codeName = keycode(event);
const { value } = event.target; const { value } = event.target;
if (event.which === 13) { if (codeName === 'enter') {
this.onSubmit(value, true); this.onSubmit(value, true);
} else if (event.which === 27) {
// TODO ESC, revert to original
} }
this.props.onKeyDown && this.props.onKeyDown(event); this.props.onKeyDown && this.props.onKeyDown(event);
} }
/**
* Revert to initial value if pressed ESC key
* once. Don't do anything (propagate the event) if
* ESC has been pressed twice in a row (eg. input in a Portal modal).
*
* NB: it has to be `onKeyUp` since the Portal is using
* the `onKeyUp` event to close the modal ; it mustn't be propagated
* if we only want to revert to initial value
*/
onKeyUp = (event) => {
const codeName = keycode(event);
if (codeName === 'esc' && !this.pressedEsc && this.intialValue !== undefined) {
event.stopPropagation();
event.preventDefault();
this.pressedEsc = true;
this.onChange(event, this.intialValue);
} else if (this.pressedEsc) {
this.pressedEsc = false;
}
}
onSubmit = (value, performDefault) => { onSubmit = (value, performDefault) => {
const { onDefaultAction, onSubmit } = this.props; const { onDefaultAction, onSubmit } = this.props;