javascript - 使 document.execCommand('insertText', false, 'message') 与 Draftjs 一起使用?
问题描述
我正在开发一个需要将文本插入contenteditable="true"
div 的应用程序(Draftjs
准确地说是基于文本字段)。
现在我知道 Draft.js 使用 react 并且应该以这种方式使用它,但在这种情况下,应用程序已经存在,这是一个可以使用它的第三方电子应用程序。
我正在处理在 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 已弃用且无法正常工作。
有什么方法可以做到这一点不会导致错误?我发现应该替换 initTextEvent 的新 API 只是new Event()
(请参阅文档),但我无法确定它是否支持 textInput 事件。
要使用它,您只需访问https://draftjs.org/并在 chrome 开发工具中使用它。
我真的很感激这里的一些帮助,因为我不知道该怎么做才能让它工作了。另外,我知道人们是 jquery 的粉丝,但我更喜欢原生 js 解决方案(尽管欢迎任何解决方案)。
编辑:
请注意:我没有使用react,我要修改的输入字段(draftjs)正在使用react,我想使用本机js向其中输入文本。
编辑2:
对于遇到此问题的其他人,我想将文本插入 Facebook Messenger 文本字段(使用 Draftjs)。
我设法找到了一个可行的解决方法。它确实使用了已弃用的 API ( event.initTextEvent
),但这是我发现的唯一可行的方法,即使使用表情符号也是如此。如果您对此有更好的解决方案,请发布答案。
它是这样工作的:
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
解决方案
尽管很久以前就提出了这个问题并且@JoniVR 找到了解决方法,但这可能对其他人有所帮助。
在进行扩展时,我也遇到了类似的问题。我还尝试了方法 document.execCommand('insertText', false, text)。它在 LinkedIn 上有效,但在 Facebook 上无效。它在错误的节点中插入文本。尽管document.execCommand API 在某些地方有效,但现在已经过时了。
对于 Facebook 和任何其他使用 drafjs 编辑器的网站,我们需要使用dataTransfer和clipBoardEvent API 发送一个 paste 事件,以使 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();
}
如果需要更多信息,请检查此链接。
推荐阅读
- laravel - 如何修复 cpanel 中损坏的链接和被阻止的文件夹
- prolog - 如何比较序言中列表的元素
- c++ - 写入访问是否有“缓存友好性”?
- php - 获取父a-tag php xpath的href元素
- excel - VBA中的Excel复选框下拉填充选项?
- spring-boot - 当 kafka 代理不可用时,如何防止正在运行的 Spring Boot 应用程序崩溃?
- c - 在可执行二进制文件中嵌入修订号
- jquery - 如何使用键和值在 for 循环中转换 forEach?
- spring - 来自单个登录表单入口点的 Spring Boot 多个身份验证提供程序
- asp.net - GridView.Rows.Count 中未显示动态添加的行