Do you want to request a _feature_ or report a _bug_?
Feature
What is the current behavior?
Currently there is no way to manipulate content before being copied to the clipboard. We are currently hacking the Editor instance to override the onCopy handler but this is not ideal.
What is the expected behavior?
Ideally, we could set the text/html that is copied to the clipboard and/or manipulate the editor state that is passed into getFragmentFromSelection(). (lib/editOnCopy.js:32)
@sarmstrong This sounds like a great feature to add. Sounds like you currently have something in place to do this, would you be able to create a pull request for it?
Thanks @tylercraft, what I have now is kind of a hack but I'll work on a more formal approach and submit a PR, thanks!
Can you give more details for your hack? I'm actually in need of something like this but I'm having trouble getting anything to work
We ended up reverting the hack . . . it didn't work. I'm trying to find some time to do a formal pull request. The idea would be to manipulate the internal clipboard data before being set and also giving the option to manipulate the OS clipboard.
@sarmstrong @MrDarkHorse Check out my branch here to see if it it helps. I recreated the way in which Sublime Text will copy/cut the full line of text if your selection is collapsed. The branch has an example included (handleBeforeCutCopy) that shows this working. Just add a few lines of text, then Cmd+C/X on a line with a collapsed selection and then Cmd+V to see the pasted result.
@tylercraft let me know if you'd like me to create a PR for this. Here's a diff of the changes.
I achieved this by providing additional API methods on the Editor component: handleBeforeCopy and handleBeforeCut. But rather than just returning handled or not-handled from these methods, editOnCopy/editOnPaste also check if the return value is an object, using it as the new value for editorState in the remainder of those functions.
Looks good to me. Thanks @ericbiewener! Hope PR gets accepted
This would be really helpful, and I like what @ericbiewener has done! A few thoughts though:
While I agree that it could be convenient to access the editorState in the handleBefore-methods, it's not consistent with how other handlers work in Draft, e.g. handleBeforeInput. If the editorState is needed, it can still be passed (e.g. by currying).
The same is true for the option to return an editorState. It could be really convenient, but it's not how the other handler methods work.
Having said that, a PR would be a good next step! @ericbiewener are you still planning on creating one?
@tobiasandersen I'm also a bit uncomfortable with changing the way these handler methods work. That's partly why I never opened a PR for it -- I was hoping to get some discussion going that would lead to a more appropriate approach. At this point I'm not planning on opening a PR until one of the maintainers shows some interest.
We really need this... the text within an entity is not usually the best representation for copying. Any insight as to whether this is possible to achieve without forking?
Having the same issue in 2018- would've been super awesome to have a handleBeforeCutCopy!
As it is, it looks like we may have to create our own fork of the codebase just to support just this single feature
Until this is added to draft-js, this can be done by adding an event listener to the content editable:
function onCutCopy(event) {
event.preventDefault();
event.clipboardData.setData('text/plain', 'hello');
}
componentDidMount() {
const node = ReactDOM.findDOMNode(this.editor);
const contentEditable = node.querySelector('[contenteditable]');
contentEditable.addEventListener('copy', onCutCopy);
contentEditable.addEventListener('cut', onCutCopy);
}
Starting with Draft.js 0.11.0 there are onCopy and onCut props which could be used for the use case suggested here, however they completely override the built-in editOnCopy and editOnCut) behavior. While the logic in editOnCopy is simple enough to replicate, that of editOnCut isn’t – so it would be nice for these to take the direction outlined in this issue, that was already implemented in #1757. Oh well.
In the meantime, it looks like the solution to implement custom logic is something like:
import editOnCut from "draft-js/lib/editOnCut";
import editOnCopy from "draft-js/lib/editOnCopy";
export const onDraftEditorCopy = (
editor: Editor,
e: Event & {
clipboardData: DataTransfer,
},
) => {
draftEditorCopyCutListener(editor, e);
editOnCopy(editor, e);
};
export const onDraftEditorCut = (
editor: Editor,
e: Event & {
clipboardData: DataTransfer,
},
) => {
draftEditorCopyCutListener(editor, e);
editOnCut(editor, e);
};
// [...]
<Editor
onCopy={onDraftEditorCopy}
onCut={onDraftEditorCut}
/>
This isn’t that much easier than the snippet from @ibash but does have the advantage of not having extra event listeners that you then have to keep track of and remember to unregister.
Most helpful comment
Thanks @tylercraft, what I have now is kind of a hack but I'll work on a more formal approach and submit a PR, thanks!