Javascript 插入符号进入contenteditable div中的跨度元素时引发事件

Javascript 插入符号进入contenteditable div中的跨度元素时引发事件,javascript,html,contenteditable,dom-events,Javascript,Html,Contenteditable,Dom Events,我有一个内容可编辑的div,其跨度如下: <div contenteditable="true">some <span>spanned</span> text</div> 一些跨距文本 我想知道是否有任何事件侦听器可以附加到span元素本身,用于检测插入符号是否在span元素内部移动 我不是在寻找一个答案,即有侦听器连接到div,每次div中有活动时都运行检查,例如此答案的解决方案: 您可以使用。并检查观察者回调中的characterData更

我有一个内容可编辑的div,其跨度如下:

<div contenteditable="true">some <span>spanned</span> text</div>
一些跨距文本
我想知道是否有任何事件侦听器可以附加到
span
元素本身,用于检测插入符号是否在
span
元素内部移动

我不是在寻找一个答案,即有侦听器连接到
div
,每次
div
中有活动时都运行检查,例如此答案的解决方案:

您可以使用。并检查观察者回调中的
characterData
更改

以下是一个例子:

var MutationObserver=
window.MutationObserver |
window.webkittionobserver | |
window.mozionobserver;
var config={childList:true,characterData:true,characterDataOldValue:true,子树:true};
var目标=文档
.querySelector('div[contenteditable]”)
.getElementsByTagName('span'))
.项目(0);
var观察者=新的突变观察者(功能(突变){
突变。forEach(功能(突变){
if(mutation.type=='characterData'){
console.clear();
log('old value:',mutation.oldValue);
log('new value:',mutation.target.textContent);
}
});
});
observer.observe(目标,配置)

一些跨文本
实际上,在考虑它时,我真的找不到任何合适的本机事件来解决这个问题

问题是。。。插入符号可以通过多种方式设置:单击、选择(可以在您希望检测的区域开始或结束)、移动光标的键盘事件,甚至外部脚本

没有任何事件能够捕获它们

可悲的是,我认为这样做的唯一方法是循环并检查当前选择(包含插入符号数据)是否匹配良好

为了实现您希望的功能,我使用, 实现主要是让您可以使用任何想要的语法- 是否为:
myElement.dispatchEvent('caretin')
或者只使用html标记语法

我并不认为这是有史以来最好的想法,也不是当前想法的最佳实现,但我认为它涵盖了使用一个循环和原生js/html方法的所有情况

//创建适当的事件并初始化它们
var CaretInEvent=document.createEvent('Event'),
CaretOutEvent=document.createEvent('Event');
initEvent('caretin',true,true);
initEvent('caretout',true,true);
//下一节将提供插入符号处理功能
常量插入检测器Tagname=“插入检测器”;
类CaretDetector扩展HtmleElement{
//这些将用于支持焦点切换元件
静态get lastDetected(){
返回CaretDetector.\u上次检测到;
}
静态设置(元素){
CaretDetector.\u lastDetected=元素;
}
//间歇
静态检测器启动(){
setInterval(函数(){
让focusNode=document.getSelection().focusNode;
if(焦点节点){
focusNode=focusNode.parentNode.closest(CaretDetectorTagName)| | focusNode.parentNode;
如果(CaretDetector.lastDetected&&focusNode!==CaretDetector.lastDetected&&CareTDetected.lastDetected.inStatus===true&&CaretDetector.lastDetected.TriggerCareToot){
CaretDetector.lastDetected.dispatchEvent(CaretOutEvent);
}
if(focusNode.triggerCaretIn&&focusNode.inStatus!==true){
focusNode.dispatchEvent(CaretInEvent);
CaretDetector.lastDetected=focusNode;
}
}
},100);
}
//从听上面提到的事件开始
构造函数(){
超级();
这是错误的;
this.addEventListener('caretin',(…args)=>{
这是真的;
这是triggerCaretIn(…args);
});
this.addEventListener('caretout',(…args)=>{
这是错误的;
this.triggerCaretOut(…args);
});
}
获取inStatus(){
归还这个;
}
triggerCaretIn(事件){
让desiredFn=this.getAttribute('oncaretin'),
wrapperFunction=新函数('event',`${desiredFn};`);
包装器函数(事件);
}
triggerCaretOut(事件){
让desiredFn=this.getAttribute('oncaretout'),
wrapperFunction=新函数('event',`${desiredFn};`);
包装器函数(事件);
}
}
//实际将标记名与上面的类连接起来
定义(CaretDetector标记名,CaretDetector);
//插入符号处于输入或输出状态时要执行的函数
功能信息(事件){
log(event.srcielement.id+“:in”);
}
功能输出(事件){
log(event.srcielement.id+“:out”);
}
window.onload=CaretDetector.detectorStart

012345
对象1的字符串
对象2的字符串

了解用户输入位置的最简单方法是
document.getSelection()
,它提供了一些节点引用,如
baseNode
和当前
focusNode
以及有用的偏移信息

然后,您可以在
文档上使用
selectionchange
事件来了解光标何时移动,而无需检查鼠标是否正在移动/单击,也无需使用键盘事件

var out,itm;//节省处理器时间
document.addEventListener('selectionchange',
函数(ev){//在按键光标移动时调用
//查找并保存我们的主要HTML对象
如果(!out)out=document.getElementById('out');
如果(!itm)itm=document.querySelector('span');
//获取用户选择信息
让grab=document.getSelection(),

text=grab.baseNode | | 0,//我考虑过使用变异观察器,但如果插入符号刚进入跨度,这也会触发,因为这就是我要寻找的。正如Daniel在另一个答案中写道的那样:插入符号可以进入跨度的方式有很多,包括键盘事件,所以仅仅寻找点击事件并不能真正解决问题.David,按键盘箭头移动插入符号不会在“跨距”单词上触发单击事件。Tha