Skip to content

Commit

Permalink
[feature/compressed-editor-controls] EuiRange + EuiFormRow (#2321)
Browse files Browse the repository at this point in the history
* focus management

* add euiformrow to some examples

* use prevention flag

* Revert "add euiformrow to some examples"

This reverts commit f93ef4e.

* clean up
  • Loading branch information
thompsongl authored Sep 10, 2019
1 parent 9ee5620 commit c96f483
Show file tree
Hide file tree
Showing 2 changed files with 82 additions and 59 deletions.
86 changes: 53 additions & 33 deletions src/components/form/range/dual_range.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,7 @@ export class EuiDualRange extends Component {
rangeWidth: null,
};

maxNode = null;
minNode = null;
preventPopoverClose = false;
rangeSliderRef = null;
handleRangeSliderRefUpdate = ref => {
this.rangeSliderRef = ref;
Expand Down Expand Up @@ -234,21 +233,48 @@ export class EuiDualRange extends Component {
});
};

onInputFocus = () => {
onThumbFocus = e => {
if (this.props.onFocus) {
this.props.onFocus(e);
}
this.toggleHasFocus(true);
};

onThumbBlur = e => {
if (this.props.onBlur) {
this.props.onBlur(e);
}
this.toggleHasFocus(false);
};

onInputFocus = e => {
if (this.props.onFocus) {
this.props.onFocus(e);
}
this.preventPopoverClose = true;
this.setState({
isPopoverOpen: true,
});
};

onInputBlur = e => {
// Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget`
const relatedTarget = e.relatedTarget || e.explicitOriginalTarget;
if (!relatedTarget || relatedTarget.id !== this.state.id) {
onInputBlur = e =>
setTimeout(() => {
// Safari does not recognize any focus-related eventing for input[type=range]
// making it impossible to capture its state using active/focus/relatedTarget
// Instead, a prevention flag is set on mousedown, with a waiting period here.
// Mousedown is viable because in the popover case, it is inaccessable via keyboard (intentionally)
if (this.preventPopoverClose) {
this.preventPopoverClose = false;
return;
}
if (this.props.onBlur) {
this.props.onBlur(e);
}
this.closePopover();
}
};
}, 200);

closePopover = () => {
this.preventPopoverClose = false;
this.setState({
isPopoverOpen: false,
});
Expand All @@ -260,22 +286,6 @@ export class EuiDualRange extends Component {
});
};

inputRef = (node, ref) => {
if (!this.props.showInput !== 'inputWithPopover') return;

// IE11 doesn't support the `relatedTarget` event property for blur events
// but does add it for focusout. React doesn't support `onFocusOut` so here we are.
if (this[ref] != null) {
this[ref].removeEventListener('focusout', this.onInputBlur);
}

this[ref] = node;

if (this[ref]) {
this[ref].addEventListener('focusout', this.onInputBlur);
}
};

render() {
const {
className,
Expand All @@ -294,7 +304,9 @@ export class EuiDualRange extends Component {
tickInterval,
ticks,
levels,
onBlur,
onChange,
onFocus,
showRange,
value,
style,
Expand Down Expand Up @@ -322,12 +334,15 @@ export class EuiDualRange extends Component {
name={`${name}-minValue`}
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
onFocus={canShowDropdown ? this.onInputFocus : undefined}
onFocus={canShowDropdown ? this.onInputFocus : onFocus}
onBlur={canShowDropdown ? this.onInputBlur : onBlur}
readOnly={readOnly}
autoSize={!showInputOnly}
fullWidth={!!showInputOnly && fullWidth}
controlOnly={showInputOnly}
inputRef={node => this.inputRef(node, 'minNode')}
onMouseDown={
showInputOnly ? () => (this.preventPopoverClose = true) : null
}
/>
) : (
undefined
Expand All @@ -348,12 +363,15 @@ export class EuiDualRange extends Component {
name={`${name}-maxValue`}
aria-describedby={this.props['aria-describedby']}
aria-label={this.props['aria-label']}
onFocus={canShowDropdown ? this.onInputFocus : undefined}
onFocus={canShowDropdown ? this.onInputFocus : onFocus}
onBlur={canShowDropdown ? this.onInputBlur : onBlur}
readOnly={readOnly}
autoSize={!showInputOnly}
fullWidth={!!showInputOnly && fullWidth}
controlOnly={showInputOnly}
inputRef={node => this.inputRef(node, 'maxNode')}
onMouseDown={
showInputOnly ? () => (this.preventPopoverClose = true) : null
}
/>
) : (
undefined
Expand Down Expand Up @@ -412,6 +430,8 @@ export class EuiDualRange extends Component {
aria-hidden={true}
tabIndex={-1}
showRange={showRange}
onFocus={onFocus}
onBlur={onBlur}
{...rest}
/>

Expand All @@ -425,8 +445,8 @@ export class EuiDualRange extends Component {
showTicks={showTicks}
showInput={!!showInput}
onKeyDown={this.handleLowerKeyDown}
onFocus={() => this.toggleHasFocus(true)}
onBlur={() => this.toggleHasFocus(false)}
onFocus={this.onThumbFocus}
onBlur={this.onThumbBlur}
style={this.calculateThumbPositionStyle(
this.lowerValue || min,
this.state.rangeWidth
Expand All @@ -442,8 +462,8 @@ export class EuiDualRange extends Component {
showTicks={showTicks}
showInput={!!showInput}
onKeyDown={this.handleUpperKeyDown}
onFocus={() => this.toggleHasFocus(true)}
onBlur={() => this.toggleHasFocus(false)}
onFocus={this.onThumbFocus}
onBlur={this.onThumbBlur}
style={this.calculateThumbPositionStyle(
this.upperValue || max,
this.state.rangeWidth
Expand Down
55 changes: 29 additions & 26 deletions src/components/form/range/range.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class EuiRange extends Component {
isPopoverOpen: false,
};

this.inputNode = null;
this.preventPopoverClose = false;
}

handleOnChange = e => {
Expand All @@ -38,42 +38,38 @@ export class EuiRange extends Component {
return isWithinRange(this.props.min, this.props.max, this.props.value);
}

onInputFocus = () => {
onInputFocus = e => {
if (this.props.onFocus) {
this.props.onFocus(e);
}
this.setState({
isPopoverOpen: true,
});
};

onInputBlur = e => {
// Firefox returns `relatedTarget` as `null` for security reasons, but provides a proprietary `explicitOriginalTarget`
const relatedTarget = e.relatedTarget || e.explicitOriginalTarget;
if (!relatedTarget || relatedTarget.id !== this.state.id) {
onInputBlur = e =>
setTimeout(() => {
// Safari does not recognize any focus-related eventing for input[type=range]
// making it impossible to capture its state using active/focus/relatedTarget
// Instead, a prevention flag is set on mousedown, with a waiting period here.
// Mousedown is viable because in the popover case, it is inaccessable via keyboard (intentionally)
if (this.preventPopoverClose) {
this.preventPopoverClose = false;
return;
}
if (this.props.onBlur) {
this.props.onBlur(e);
}
this.closePopover();
}
};
}, 200);

closePopover = () => {
this.preventPopoverClose = false;
this.setState({
isPopoverOpen: false,
});
};

inputRef = node => {
if (!this.props.showInput !== 'inputWithPopover') return;

// IE11 and Safar don't support the `relatedTarget` event property for blur events
// but do add it for focusout. React doesn't support `onFocusOut` so here we are.
if (this.inputNode != null) {
this.inputNode.removeEventListener('focusout', this.onInputBlur);
}

this.inputNode = node;

if (this.inputNode) {
this.inputNode.addEventListener('focusout', this.onInputBlur);
}
};

render() {
const {
className,
Expand All @@ -96,7 +92,9 @@ export class EuiRange extends Component {
showValue,
valueAppend,
valuePrepend,
onBlur,
onChange,
onFocus,
value,
style,
tabIndex,
Expand All @@ -121,10 +119,10 @@ export class EuiRange extends Component {
compressed={compressed}
onChange={this.handleOnChange}
name={name}
onFocus={canShowDropdown ? this.onInputFocus : undefined}
onFocus={canShowDropdown ? this.onInputFocus : onFocus}
onBlur={canShowDropdown ? this.onInputBlur : onBlur}
fullWidth={showInputOnly && fullWidth}
autoSize={!showInputOnly}
inputRef={this.inputRef}
{...rest}
/>
) : (
Expand Down Expand Up @@ -180,6 +178,11 @@ export class EuiRange extends Component {
showTicks={showTicks}
showRange={showRange}
tabIndex={showInput ? -1 : tabIndex || null}
onMouseDown={
showInputOnly ? () => (this.preventPopoverClose = true) : null
}
onFocus={showInput === true ? null : onFocus}
onBlur={showInputOnly ? this.onInputBlur : onBlur}
{...rest}
/>

Expand Down

0 comments on commit c96f483

Please sign in to comment.