51工具盒子

依楼听风雨
笑看云卷云舒,淡观潮起潮落

JS文本选区变化selectionchange事件实践小记


selectionchange事件文章封面占位图

2年前有个中台文档产品有个划词评论的功能,那时候还写了篇文章介绍了相关的技术实现,参见:"划词评论与Range开发若干经验分享"

一直运行的好好的。

突然,就在最近,老板提了一嘴,这手机上怎么没法划词评论。

好了,需求就来了。

当时手机上内置的复制、翻译等tips等与划词评论小按钮会有冲突,以及开发成本等原因(台式机模拟touch长按有些麻烦),就没做。

简单研究了下,事件是通用的,就是selectionchange事件。

一、关于selectionchange事件

根据我的测试,selectionchange发生在选区范围发生变化的时候,假如你拖拽选区范围的"棒棒子"改变文本的选中范围,此事件是不断触发的。

拖拽的棒棒示意

使用示意:

尝试选中这段文字:《HTML并不简单》是目前市面上...
<p id="result"></p>
document.addEventListener('selectionchange', function () {
    const selection = document.getSelection();
    result.textContent = selection.toString().trim();    
});

此时,我们选中任何选区,p#result元素就会显示选中的文本内容,截图示意:

选中文字显示

这个demo手机也可以体验,您可以狠狠地点击这里:JS selectionchange事件体验demo

二、选区执行时机的区别

在PC端和移动端,由于选区消失的时机是有区别的,因此,在交互处理上会有所不同。

例如,我们选中选区,悬浮一个按钮,点击此按钮,使用surroundContents() API包裹选中的文字,在PC端,我们可以给按钮使用click事件。

因为在PC端(Android好像也是),文字选区的消失是在click事件之后。

但是在iOS端,不知道是不是客户端APP的问题,选区的消失在click事件之前。

因此,在实际处理的时候,按钮的点击事件需要使用touchstart处理才行。

这是其中的一个执行细节,希望可以帮助到做类似需求的同行。

三、selectionchange绑定元素和事件对象

selectionchange事件只能绑定在document上,以及原生的可输入元素上,是不能绑定在普通元素之上的。

例如,下面的JS代码是不会触发任何行为执行的:

document.body.addEventListener('selectionchange', function () {
    // 不会触发执行    
});

但如果是输入框,例如<input>或者<textarea>则是没问题的,例如:

input.addEventListener('selectionchange', function () {
    // 可以执行    
});

那如果是一个普通的元素,但是设置了contenteditable="true",变得可输入,那还支持'selectionchange'吗?

根据我的测试,是不支持的。

事件对象

相比传统的事件,selectionchange事件的event对象会有很多缺失,例如坐标位置等信息,以Chrome浏览器举例,支持的属性见如下截图。

事件属性

因此,如果希望元素相对于选区定位,event对象是帮不上任何忙的,还是需要使用选区本身的API才行,具体见本文一开始提到的那篇文章。

四、其他就没有什么了

其他就没什么了,比较冷门的一个JS DOM事件API,但我使用下来,还挺好用的,比较稳健,其兼容性也不错,如下截图所示:

selectionchange事件的兼容性

希望可以帮到诸位道友,哎呀,嘴瓢了,同行,行友,看制作精良的韩跑跑傻屌漫看得有些走火入魔了,哈哈哈。

韩跑跑截图

(本篇完)

赞(0)
未经允许不得转载:工具盒子 » JS文本选区变化selectionchange事件实践小记