我有<ol contenteditable=true>
元素,我想添加一个eventListener,以便在这些列表的任何<li>
进行任何更改之前,将原始textContent
(即任何更改之前的文本)推送到var alterations = []
。
我尝试使用addEventListener("beforeinput", ...
,如下所示:
window.alterations = [];
window.onload = () => {
document.getElementById('main').addEventListener("beforeinput", () => {
alert('event listened!');
window.alterations.push(window.getSelection().anchorNode.parentElement.textContent);
console.log(window.alterations);
});
}
<body>
<section id="main">
<ol contenteditable="true">
<li>First</li>
<li>Second</li>
<li>Third</li>
<li>Fourth</li>
</ol>
<ol contenteditable="true">
<li>First</li>
<li>Second</li>
<li>Third</li>
<li>Fourth</li>
</ol>
</section>
</body>
但是
beforeinput
似乎不适用于contenteditable元素(如以上代码所示,回调函数未执行)。仅input
事件用作addEventListener
的参数,但为时已晚,因为已经输入了一个字母或从原始文本中删除了一个字母。问题:如何获取要通过
contenteditable
更改的元素的原始文本?例如,如果我输入“First” <li>
诸如“not First”之类的其他名称,如何将textContent
的原始<li>
(===仅“First”)推入alterations
数组?编辑:我认为这是浏览器问题。
beforeinput
在基于Chromium的浏览器中有效,但在基于Firefox的浏览器(如Firefox和PaleMoon)中则无效。我的快速解决方案是使用keydown
而不是beforeinput
。该代码可在所有浏览器中使用: for (let x of document.querySelectorAll('[contenteditable="true"]')) {
x.addEventListener('keydown',() => {
let originalText = window.getSelection().anchorNode.textContent;
console.log(originalText);
});
但这有一个不幸的问题,每次按下任何键(例如Ctrl + Shift或Alt)都会触发。我尝试使用
keypress
而不是keydown
,但是基于Chromium的浏览器并未触发删除操作,并且按下的任何“上/下/左/右/上移”键也会触发该代码。我想我可以使用charcode
一对一地处理这些异常,但是除了使用keydown
之外,没有别的方法吗? 最佳答案
好的,这应该可以工作:
window.alterations = [];
window.onload = () => {
document.getElementById('main').addEventListener("keydown", (event) => {
//0 == delete in PaleMoon, 46 == delete in other browsers
/* ALT is needed for some characters, like § and º, but to exclude ALT, META, etc.:
if (event.altKey || event.metaKey) {return;} */
if (event.key.length === 1 || ["Enter", "Delete", "Backspace"].includes(event.key)) {
//when Ctrl is pressed, trigger only if Ctrl+V or Ctrl+X and ALT is not pressed:
if (event.key.toLowerCase() !== 'v' && event.key.toLowerCase() !== 'x' && event.ctrlKey && !event.altKey) {return;}
alert('event listened!');
window.alterations.push(window.getSelection().anchorNode.parentElement.textContent);
console.log(window.alterations);
}
});
}
<body>
<section id="main">
<ol contenteditable="true">
<li>First</li>
<li>Second</li>
<li>Third</li>
<li>Fourth</li>
</ol>
<ol contenteditable="true">
<li>First</li>
<li>Second</li>
<li>Third</li>
<li>Fourth</li>
</ol>
</section>
</body>
从兼容性的 Angular 来看,这似乎是最好的,因为我开始认为每种浏览器对
beforeinput
(可能对没有处理程序的keydown
)都有不同的响应。我下载了基于Chromium的浏览器进行测试,结果似乎与Chrome不同。编辑:我将
event.which
替换为event.key
,因为前者已弃用,并且在不同的浏览器中无法可靠地工作。仍然存在的问题:
~~~
或´´´´
等,则不会处理。
<li>
聚焦时复制文本(Ctrl + C)或使用其他类似的快捷方式,则事件将不愿被触发,因为它监听了c
。 [由于@trysis评论而得到修复]