-
Notifications
You must be signed in to change notification settings - Fork 4
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
Support pasting html from IE, Edge, and Safari #21
Conversation
This is currently a hacky solution because of the way it requires calling addEventListener to grab the paste event. Besides that unfortunate behavior, however, the codeflow seems to work pretty well!
// the contentEditable div. So, e in this case comes from a direct editor.addEventListener | ||
// Therefore, we need to replicate anything that the SyntheticClipboardEvent does that is used | ||
// Currently, that is only getting the clipboard, which involves falling back to window for IE & Edge. | ||
const clipboard = e.clipboardData ? e.clipboardData : window.clipboardData; |
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 haven't looked but does the code use this pattern or const clipboard = e.clipboardData || window.clipboardData
?
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.
good, point I'll match react directly
return (
'clipboardData' in event ?
event.clipboardData :
window.clipboardData
);```
if (text && !html) { | ||
// The pasted content has text, but not HTML. For certain browsers (old versions of Safari, IE, and Edge) | ||
// the html isn't provided as part of the clipboardData. To work around this, follow the following algorithm: | ||
// Do NOT call e.preventDefault(). Instead, we want the browser to paste, just not in the draft element. |
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: in this code we are Draft so it seems strange to refer to Draft as a 3rd party
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.
done
editor.setMode('paste'); | ||
const pasteTrap = editor._pasteTrap; | ||
pasteTrap.focus(); | ||
setImmediate(() => { |
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.
Just to validate: there are no events to drive this off of?
If I paste and then very quickly type, what will happen? Are those typed characters dropped? Are they interpreted as being part of the paste?
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 agree that this is clearly the risky part of the code, but if it's the only way it's the only way. I'd be curious to see if we get some kind of event in the pasteTrap too
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.
Since focus moves to the pasteTrap, you would get browser-default behavior until the setTimeout elapses. Meaning if you did say, command-b, the bookmark toolbar would show up. Until the setTimeout fires.
The core draft editor should be safe because focus moved & the handlers are turned off.
editor.setMode('paste'); | ||
const pasteTrap = editor._pasteTrap; | ||
pasteTrap.focus(); | ||
setImmediate(() => { |
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 agree that this is clearly the risky part of the code, but if it's the only way it's the only way. I'd be curious to see if we get some kind of event in the pasteTrap too
if (data.data.getData && !data.types.length) { | ||
return undefined; | ||
} | ||
return data.getHTML(); |
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.
To your point in slack, do we have a good grasp on when this function will return text? It seems important as we're driving whether to use the paste trap on the html being present or not
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.
Yes, the code is known. (see slack)
@@ -102,7 +102,7 @@ function editOnPaste(editor: DraftEditor, e: DOMEvent): void { | |||
if (text && !html) { | |||
// The pasted content has text, but not HTML. For certain browsers (old versions of Safari, IE, and Edge) | |||
// the html isn't provided as part of the clipboardData. To work around this, follow the following algorithm: | |||
// Do NOT call e.preventDefault(). Instead, we want the browser to paste, just not in the draft element. | |||
// Do NOT call e.preventDefault(). Instead, we want the browser to paste, just not in the editor element. | |||
// Instead, move focus to a dummy contentEditable div (the pasteTrap), | |||
// let the paste event through, and then copy the html out of the paste trap. | |||
// It is important to call setMode('paste') to disable draft's event handlers (so it is blisfully unaware) |
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: Same comment as earlier. We shouldn't talk about Draft as a 3rd party here.
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.
Fixed
// Do NOT call e.preventDefault(). Instead, we want the browser to paste, just not in the editor element. | ||
// Instead, move focus to a dummy contentEditable div (the pasteTrap), | ||
// let the paste event through, and then copy the html out of the paste trap. | ||
// It is important to call setMode('paste') to disable draft's event handlers (so it is blisfully unaware) |
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: Same comment as earlier, we shouldn't talk about Draft as if it were a 3rd party
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.
🚢
For browsers that don't support grabbing the html out of the clipboardData, instead allow the paste event to go to a dummy pasteTrap and then use that in the remainder of the code