问题
I'm working on an application which needs to insert text into a contenteditable="true" div (a Draftjs based textfield to be precise).
Now I am aware that Draft.js uses react and that it should be used that way, but in this case, the application already exists and this is a third party electron app that works with it.
I'm working on in-line notification replying on macOS, so I need that reply text to be pasted inside the draftJS field, however, when I do so using:
document.querySelector('div[contenteditable="true"]').focus();
document.execCommand('insertText', false, 'message');
It throws an error:
I was able to make it work using:
const event = document.createEvent('TextEvent');
event.initTextEvent('textInput', true, true, window, 'message', 0, locale);
but this API is deprecated and doesn't work properly if the message contains an emoji.
Is there any way to do this that doesn't cause an error?
I found out that the new API that is supposed to replace initTextEvent is just new Event() (see docs), but I can't find out if it supports textInput events.
To play around with it you can just go to https://draftjs.org/ and play with it in chrome dev tools.
I would really appreciate some help here as I don't know what to do to make it work anymore. Also, I know people are a fan of jquery, but I'd prefer a native js solution (although any solution is welcome).
edit:
Please note: I'm not using react, the input field I want to modify (draftjs) is using react and I want to input text into it using native js.
edit 2:
For anyone else coming across this issue, I wanted to insert text into the Facebook messenger text field (which uses Draftjs).
I managed to find a working workaround.
It does use the deprecated API (event.initTextEvent), but it's the only way that I've found that works, even with emoji. Please do post an answer if you have a better solution to this.
It works like this:
async function sendReply(message: string): Promise<void> {
const inputField = document.querySelector('[contenteditable="true"]') as HTMLElement;
if (inputField) {
const previousMessage = inputField.textContent;
// Send message
inputField.focus();
await insertMessageText(message, inputField);
(await elementReady('._30yy._38lh._39bl')).click();
// Restore (possible) previous message
if (previousMessage) {
insertMessageText(previousMessage, inputField);
}
}
}
function insertMessageText(text: string, inputField: HTMLElement): void {
// Workaround: insert placeholder value to get execCommand working
if (!inputField.textContent) {
const event = document.createEvent('TextEvent');
event.initTextEvent('textInput', true, true, window, '_', 0, '');
inputField.dispatchEvent(event);
}
document.execCommand('selectAll', false, undefined);
document.execCommand('insertText', false, text);
}
This is typescript code, so you might want to change it up to use js.
It works by inserting a placeholder value inside the textField using event.initTextEvent, and then replacing that text with:
document.execCommand('selectAll', false, undefined);
document.execCommand('insertText', false, 'text');
tested in Chrome: Version 71.0.3578.98
来源:https://stackoverflow.com/questions/54256517/make-document-execcommandinserttext-false-message-work-with-draftjs