Skip to content

Commit e0a03c1

Browse files
spirosikmdnhunzaker
authored andcommitted
Extend input type check in selection capabilities (facebook#12062) (facebook#12135)
* Do not set selection when prior selection is undefined (facebook#12062) `restoreSelection` did not account for input elements that have changed type after the commit phase. The new `text` input supported selection but the old `email` did not and `setSelection` was incorrectly trying to restore `null` selection state. We also extend input type check in selection capabilities to cover cases where input type is `search`, `tel`, `url`, or `password`. * Add link to HTML spec for element types and selection * Add reset button to ReplaceEmailInput This commit adds a button to restore the original state of the ReplaceEmailInput fixture so that it can be run multiple times without refreshing the page.
1 parent 79a740c commit e0a03c1

File tree

3 files changed

+71
-2
lines changed

3 files changed

+71
-2
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import Fixture from '../../Fixture';
2+
3+
const React = window.React;
4+
5+
class ReplaceEmailInput extends React.Component {
6+
state = {
7+
formSubmitted: false,
8+
};
9+
10+
onReset = () => {
11+
this.setState({formSubmitted: false});
12+
};
13+
14+
onSubmit = event => {
15+
event.preventDefault();
16+
this.setState({formSubmitted: true});
17+
};
18+
19+
render() {
20+
return (
21+
<Fixture>
22+
<form className="control-box" onSubmit={this.onSubmit}>
23+
<fieldset>
24+
<legend>Email</legend>
25+
{!this.state.formSubmitted ? (
26+
<input type="email" />
27+
) : (
28+
<input type="text" disabled={true} />
29+
)}
30+
</fieldset>
31+
</form>
32+
<button type="button" onClick={this.onReset}>
33+
Reset
34+
</button>
35+
</Fixture>
36+
);
37+
}
38+
}
39+
40+
export default ReplaceEmailInput;

fixtures/dom/src/components/fixtures/text-inputs/index.js

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Fixture from '../../Fixture';
22
import FixtureSet from '../../FixtureSet';
33
import TestCase from '../../TestCase';
44
import InputTestCase from './InputTestCase';
5+
import ReplaceEmailInput from './ReplaceEmailInput';
56

67
const React = window.React;
78

@@ -125,6 +126,21 @@ class TextInputFixtures extends React.Component {
125126
<InputTestCase type="url" defaultValue="" />
126127
</TestCase>
127128

129+
<TestCase
130+
title="Replacing email input with text disabled input"
131+
relatedIssues="12062">
132+
<TestCase.Steps>
133+
<li>Type "[email protected]"</li>
134+
<li>Press enter</li>
135+
</TestCase.Steps>
136+
137+
<TestCase.ExpectedResult>
138+
There should be no selection-related error in the console.
139+
</TestCase.ExpectedResult>
140+
141+
<ReplaceEmailInput />
142+
</TestCase>
143+
128144
<TestCase title="All inputs" description="General test of all inputs">
129145
<InputTestCase type="text" defaultValue="Text" />
130146
<InputTestCase type="email" defaultValue="[email protected]" />

packages/react-dom/src/client/ReactInputSelection.js

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,21 @@ function isInDocument(node) {
2222
* Input selection module for React.
2323
*/
2424

25+
/**
26+
* @hasSelectionCapabilities: we get the element types that support selection
27+
* from https://html.spec.whatwg.org/#do-not-apply, looking at `selectionStart`
28+
* and `selectionEnd` rows.
29+
*/
2530
export function hasSelectionCapabilities(elem) {
2631
const nodeName = elem && elem.nodeName && elem.nodeName.toLowerCase();
2732
return (
2833
nodeName &&
29-
((nodeName === 'input' && elem.type === 'text') ||
34+
((nodeName === 'input' &&
35+
(elem.type === 'text' ||
36+
elem.type === 'search' ||
37+
elem.type === 'tel' ||
38+
elem.type === 'url' ||
39+
elem.type === 'password')) ||
3040
nodeName === 'textarea' ||
3141
elem.contentEditable === 'true')
3242
);
@@ -52,7 +62,10 @@ export function restoreSelection(priorSelectionInformation) {
5262
const priorFocusedElem = priorSelectionInformation.focusedElem;
5363
const priorSelectionRange = priorSelectionInformation.selectionRange;
5464
if (curFocusedElem !== priorFocusedElem && isInDocument(priorFocusedElem)) {
55-
if (hasSelectionCapabilities(priorFocusedElem)) {
65+
if (
66+
priorSelectionRange !== null &&
67+
hasSelectionCapabilities(priorFocusedElem)
68+
) {
5669
setSelection(priorFocusedElem, priorSelectionRange);
5770
}
5871

0 commit comments

Comments
 (0)