-
Notifications
You must be signed in to change notification settings - Fork 4.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Fix autocompletion in IE11 #6667
Fix autocompletion in IE11 #6667
Conversation
I'm finding that We can still use it if we want, but we'd need to loop and check if parent nodes are contained until we reach the document root or find containment. |
Hi @brandonpayton thank you for creating this PR. I like this version and I think it is better when compared to what was proposed in #5914 as it avoids the need for a new component.
|
372fdb0
to
f563468
Compare
Hi @jorgefilipecosta, thanks for commenting on this. I'll work to clean this up for merge. I haven't found a good feature test, so for now, I plan to conditionally add the
I was uncomfortable with the string-based containment check because we could have false positives. It's not really that important because this is just for a development warning, but since we may want to use |
I played around with this a bit more and found a couple of things that could be used for a feature test:
☝️ I'm posting this in case this is interesting to someone, but I don't want to use such complicated testing per TinyMCE instance, which is what we'd need to do since IE11 contenteditable input behavior depends on the element. Something like this is simpler and at least limited to IE11: const listenForTextInput =
/Trident/.test( navigator.userAgent ) &&
! /input/i.test( tagName ) &&
! /textarea/i.test( tagName ); |
Is this still WIP? |
@noisysocks Yeah, I need to make the fix conditional and probably split out the change to |
It turns out that IE11's I like that this fix produces a real I plan to look at this more tomorrow. |
f563468
to
3a00f3e
Compare
IE11 doesn't dispatch `input` events for contenteditable, just for `<input>` and `<textarea>` elements. However, it does dispatch a similar `textinput` event for contenteditable. In this change, we listen for `textinput` events and manually dispatches an `input` event on the same target. In addition, because `textinput` isn't dispatched for deletions, we also dispatch `input` for Delete and Backspace `keyup` events.
3a00f3e
to
4313ff9
Compare
This is ready for review. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tested in IE11, Edge and Chrome. It fixes the bug!
I left some minor comments but nothing blocking.
} | ||
|
||
/** | ||
* Applies a fix that provides `input` events for contenteditable in InternetExplorer. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: Internet Explorer has a space 👀
this.removeInternetExplorerInputFix = | ||
editorNode && needsInternetExplorerInputFix( editorNode ) ? | ||
applyInternetExplorerInputFix( editorNode ) : | ||
null; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: I think this would read better as an if
, e.g.
if ( editorNode && needsInternetExplorerInputFix( editorNode ) ) {
this.removeInternetExplorerInputFix = applyInternetExplorerInputfix( editorNode );
}
@@ -96,6 +182,23 @@ export default class TinyMCE extends Component { | |||
} ); | |||
} | |||
|
|||
saveEditorNode( editorNode ) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor: bindEditorNode
is more consistent with how we name these sorts of functions elsewhere in the codebase.
function needsInternetExplorerInputFix( editorNode ) { | ||
return ( | ||
// Rely on userAgent in the absence of a reasonable feature test for contenteditable `input` events. | ||
/Trident/.test( window.navigator.userAgent ) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we borrow what Modernizr does here? Or is that for a different input
event?
https://github.com/Modernizr/Modernizr/blob/master/feature-detects/event/oninput.js
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I thought about that too. Unfortunately, the test returns true for even a non-contenteditable <div>
in IE11 because of the first part that sets an oninput
attribute and checks the type of the element's oninput
property. The browser does support the input
event but doesn't dispatch it for contenteditable
text input.
I tried to adapt the latter half of the test that dispatches a KeyboardEvent and listens for input
but didn't have any luck getting it to work in IE11. It's possible I missed something but didn't think I should spend more time on it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, thank you for taking the time to look and make this suggestion, @noisysocks . I actually forgot that I'd looked at this until I worked through it again. :)
/** | ||
* A ref function can be used for cleanup because React calls it with | ||
* `null` when unmounting. | ||
*/ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, that's cool!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah, I love being able to keep allocation and cleanup in one place while also handling real situations where a ref is removed and re-added during the life of a component.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Shouldn't we just use componentDidMount
and componentWillUnmount
?
Related: The latest version of React includes a new React.createRef
function which may become the recommended standard in place of the ref
callback:
https://reactjs.org/docs/refs-and-the-dom.html#creating-refs
// Rely on userAgent in the absence of a reasonable feature test for contenteditable `input` events. | ||
/Trident/.test( window.navigator.userAgent ) && | ||
// IE11 dispatches input events for `<input>` and `<textarea>`. | ||
! /input/i.test( editorNode.tagName ) && |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do we check this? A rich text field can never be an input or textarea.
Description
This is a PR to fix autocompletion in IE11.
Fixes #3409.
Details
The cause for this breakage is that IE11 doesn't dispatch
input
events for contenteditable, only for<input>
and<textarea>
elements.The proposed fix is to update our TinyMCE component to listen for IE11's comparable
textinput
event and manually creating and dispatching aninput
on the same target. In addition, becausetextinput
isn't dispatched for deletions, we also dispatchinput
for Delete and Backspacekeyup
events.How has this been tested?
Loaded Gutenberg in IE11, Chrome, Firefox, and Safari and exercised the block and user completers.
I also used the IE11 and Chrome debuggers to verify the fix is applied for just IE and that its event listeners are removed when unmounted.
Screenshots
Checklist: