Заставить 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();
}

Проверьте эту ссылку, если потребуется дополнительная информация.

Другие вопросы по тегам