在文本区域中插入文本并更新撤销/重做队列是否可行?

12

几天前,我发布了一个关于如何在Internet Explorer中更新文本的问题。然而,这种方法似乎在Firefox中也无法使用。

这让我想到是否有一种方法可以修改textarea的值并更新撤销/重做队列(调用ctrl-Zdocument.execCommand('undo');)。

到目前为止,我已经找到了两种可能性,但它们并不适用于所有浏览器:

选项1:

var event = document.createEvent('TextEvent');
event.initTextEvent('textInput', true, true, null, text, 9, "en-US");
textarea.focus();
textarea[0].setSelectionRange(selection.start, selection.end);
textarea[0].dispatchEvent(event);

注意:这似乎在IE(完全不起作用)和Firefox中不起作用。

选项2:

document.execCommand("insertText", false, "the text to insert");

在IE中无法正常工作(在9及以下版本测试过,但似乎根本没有实现),其他浏览器情况未知。


这在IE中没有实现,包括IE11,这真的很令人沮丧!但在Edge中可以正常工作。 - w.stoettinger
4个回答

7

到目前为止,我想出的解决方案是这样的,但我也开放接受更好的建议:

我通过document.queryCommandSupported检查insertText是否存在。如果存在,我就使用它。如果不存在,我只需替换文本:

var text = "hello world",
    textarea = jQuery("textarea"),
    selection = {'start': textarea[0].selectionStart, 'end': textarea[0].selectionEnd};

if (document.queryCommandSupported('insertText')) {
    document.execCommand('insertText', false, text);
}
else {
    textarea.val(textarea.val().substring(0, selection.start) + text + textarea.val().substring(selection.end, textarea.val().length));
}

1
我也在寻找答案,insertText 能用,但似乎会稍微弄乱撤销/重做历史记录。参见 http://jsfiddle.net/rudiedirkx/k4spa0dv/ 在撤销和重做一些编程更改后,它会失去最后几个历史记录项,因此重做不会重做所有内容...有什么想法吗?(顺便说一下,这是在Chrome中测试的) - Rudie
document.execCommand返回true,如果命令成功执行,我使用返回值而不是首先检查queryCommandSupported。此外,在更改值而没有execCommand的情况下,请不要忘记使用.setSelectionRange(start,end)更新插入符位置。 - w.stoettinger
1
注意!这不适用于Firefox!insertText命令受支持,但仅适用于contenteditable元素。不适用于textarea。 - Nux

2

截至2016年8月19日,Option 1表现良好,但在Chrome的即将发布的版本中已经被弃用。分派事件会生成以下警告:

从JavaScript生成的DOM事件已经触发了浏览器内部的默认操作。这种行为是非标准的,并将在M53(大约在2016年9月)中被删除。有关更多详细信息,请参见https://www.chromestatus.com/features/5718803933560832


1
太好了!..前进一步,后退两步。 :p - Cyril N.
看起来 dispatchEvent 现在已经广泛可用了:https://caniuse.com/?search=dispatchEvent - Avatar

0

只有支持document.execCommand("insertText")的浏览器才具有撤销功能(目前为止:Chrome、Safari、Opera)。其他浏览器有各种插入文本的方式,但没有撤销功能。

尝试使用insert-text-textarea来包装此页面上一些解决方案,以获得现代浏览器的支持。如果需要IE8+支持,请尝试insert-text-at-cursor包。


0

仍然存在混乱的历史记录(Chrome):http://jsfiddle.net/rudiedirkx/k4spa0dv/。撤销和重做几次后,他完全困惑了,重做/撤销历史记录也丢失了。Firefox根本不起作用。 - Rudie
似乎仍然没有跨浏览器的解决方案。至少在jsfiddle中提出的任何方法中,IE都不能正常工作。真是太遗憾了。 - Joshua Muheim

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接