简体   繁体   English

在更改之前获取contenteditable元素的textContent(或`beforeinput`)

[英]Get textContent of contenteditable element before change (or `beforeinput`)

I have <ol contenteditable=true> elements and I want to add an eventListener so that before any changes in any <li> of these lists, the original textContent (that is, the text prior to any alterations) is pushed to var alterations = [] . 我有<ol contenteditable=true>元素,我想添加一个eventListener,以便在任何<li>这些列表中的任何更改之前 ,原始textContent (即任何更改之前的文本)被推送到var alterations = []

I have tried using addEventListener("beforeinput", ... , as follows: 我尝试过使用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> 

But beforeinput does not seem to work on contenteditable elements (as the above code shows, the callback function is not executed). 但是beforeinput似乎不适用于contenteditable元素(如上面的代码所示,回调函数没有执行)。 Only the input event works as argument to addEventListener , but then is too late, since one letter was already inputted or deleted from the original text. 只有input事件作为addEventListener参数,但是为时已晚,因为已经从原始文本输入或删除了一个字母。

Question : how can I get the original text of the element about to be changed via contenteditable ? 问题 :如何通过contenteditable获取要更改的元素的原始文本? For example, if I type in the "First" <li> something else, like "not First", how can I push the original textContent (=== just "First") of the <li> to the alterations array? 例如,如果我输入“First” <li>其他内容,例如“not First”,如何将<li>的原始textContent (===只是“First”)推送到alterations数组?


EDIT: I think this is a browser issue. 编辑:我认为这是一个浏览器问题。 beforeinput works in Chromium based browsers, but not in Firefox based browsers (like Firefox and PaleMoon). beforeinput适用于基于Chromium的浏览器,但不适用于基于Firefox的浏览器(如Firefox和PaleMoon)。 My quickfix was to use keydown instead of beforeinput . 我的quickfix是使用keydown而不是beforeinput This code works in all browsers: 此代码适用于所有浏览器:

 for (let x of document.querySelectorAll('[contenteditable="true"]')) {
   x.addEventListener('keydown',() => {
     let originalText = window.getSelection().anchorNode.textContent; 
     console.log(originalText);
   });

But this has the unfortunate problem of triggering every time any key is pressed, like Ctrl + Shift or Alt . 但是每次按下任何键时都会触发这个不幸的问题,比如Ctrl + ShiftAlt I tried keypress instead of keydown , but my Chromium based browser didn't trigger on deletions and any "move up/down/left/right/" keys pressed will also trigger the code. 我尝试过keypress而不是keydown ,但我的基于Chromium的浏览器没有触发删除,按下任何“上移/下移/左/右/”按键也会触发代码。 I guess I can handle these exceptions one by one with charcode , but is there no other way than using keydown ? 我想我可以用charcode处理这些异常,但除了使用keydown之外别无他法吗?

OK, this here should work: 好的,这应该工作:

 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> 

And this seems to be best in terms of compatibility, since I'm starting to think each browser has a different response to beforeinput (and maybe to keydown without a handler). 这似乎在兼容性方面是最好的,因为我开始认为每个浏览器对beforeinput有不同的响应(并且可能没有处理程序的keydown )。 I downloaded a Chromium based browser to test it and the results seem different than from Chrome. 我下载了一个基于Chromium的浏览器来测试它,结果与Chrome不同。

EDIT : I replaced event.which for event.key , since the former is deprecated and works unreliably in different browsers. 编辑 :我为event.key替换了event.which ,因为前者已被弃用,并且在不同的浏览器中不可靠。

Remaining problems: 剩下的问题:

  1. If user repeatedly types ~~~ or ´´´´ , etc., this will not be handled. 如果用户重复类型~~~´´´´等等,这将不会被处理。
  2. If user copies the text ( Ctrl + C ), or uses another similar shortcut while <li> is focused, then event will unwillingly be triggered, since it listened to c . 如果用户复制文本( Ctrl + C ),或者在<li>聚焦时使用另一个类似的快捷方式,则会不情愿地触发事件,因为它会听取c [fixed thanks to @trysis comment] [感谢@trysis评论]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM