Заставить document.execCommand('insertText', false, 'message') работать с draftjs?
Я работаю над приложением, которое должно вставить текст в contenteditable="true"
div (a Draftjs
на основе текстового поля, если быть точным).
Теперь я знаю, что Draft.js использует реагирует и его следует использовать таким образом, но в этом случае приложение уже существует, и это стороннее электронное приложение, которое работает с ним.
Я работаю над встроенным уведомлением, отвечающим на macOS, поэтому мне нужно вставить этот текст ответа в поле draftJS, однако, когда я делаю это, используя:
document.querySelector('div[contenteditable="true"]').focus();
document.execCommand('insertText', false, 'message');
Я смог заставить его работать, используя:
const event = document.createEvent('TextEvent');
event.initTextEvent('textInput', true, true, window, 'message', 0, locale);
но этот API устарел и не работает должным образом, если сообщение содержит смайлики.
Есть ли способ сделать это, что не вызывает ошибку? Я обнаружил, что новый API, который должен заменить initTextEvent, просто new Event()
(см. документы), но я не могу выяснить, поддерживает ли он события textInput.
Чтобы поиграть с ним, вы можете просто зайти на https://draftjs.org/ и поиграть с ним в инструментах Chrome Dev.
Я был бы очень признателен за помощь здесь, так как я не знаю, что делать, чтобы это работало. Кроме того, я знаю, что люди являются поклонниками jquery, но я бы предпочел нативное решение js (хотя любое решение приветствуется).
редактировать:
Пожалуйста, обратите внимание: я не использую реагировать, поле ввода, которое я хочу изменить (draftjs), использует реакцию, и я хочу вводить в него текст, используя нативный js.
редактировать 2:
Для всех, кто сталкивался с этой проблемой, я хотел вставить текст в текстовое поле мессенджера Facebook (которое использует Draftjs).
Мне удалось найти рабочий обходной путь. Он использует устаревший API (event.initTextEvent
), но это единственный способ, который я нашел, который работает, даже с Emoji. Пожалуйста, оставьте ответ, если у вас есть лучшее решение для этого. Это работает так:
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);
}
Это машинописный код, поэтому вы можете изменить его на js.
Это работает путем вставки значения заполнителя внутри textField, используя event.initTextEvent
и затем заменить этот текст:
document.execCommand('selectAll', false, undefined);
document.execCommand('insertText', false, 'text');
протестировано в Chrome: версия 71.0.3578.98
0 ответов
Хотя вопрос был задан давно, и @JoniVR нашел обходной путь, это может помочь кому-то другому.
У меня также была аналогичная проблема при работе над расширением. Я также попробовал метод document.execCommand('insertText', false, text). Это сработало в LinkedIn, но не в Facebook. Текст вставлялся не в тот узел. Хотя document.execCommand API работает в некоторых местах, сейчас он устарел.
Для Facebook и любых других сайтов, использующих редактор drafjs, нам нужно отправить событие вставки с помощью API dataTransfer и clipBoardEvent, чтобы draftjs считал, что текст вставлен, и обрабатывал его соответствующим образом.
const dataTransfer = new DataTransfer();
function dispatchPaste(target, text) {
// this may be 'text/html' if it's required
dataTransfer.setData('text/plain', text);
target.dispatchEvent(
new ClipboardEvent('paste', {
clipboardData: dataTransfer,
// need these for the event to reach Draft paste handler
bubbles: true,
cancelable: true
})
);
// clear DataTransfer Data
dataTransfer.clearData();
}
Проверьте эту ссылку, если потребуется дополнительная информация.