如何避免选中连续DOM div时浏览器自动将选择范围扩展至相邻未选中div?
如何避免选中连续DOM div时浏览器自动将选择范围扩展至相邻未选中div?
嘿,我太懂你遇到的这个糟心问题了!三击选中连续div里的文本时,浏览器居然悄悄把下一个没选中的div也囊括进来,这种默认行为确实挺烦人的。不过别担心,咱们可以通过几个办法来绕开这个坑:
手动修正选择范围:在你写的
get_selected_sentences_range函数里,加一步范围校验,把浏览器多选中的部分给截掉。比如先拿到选择范围的起始和结束元素,判断结束元素是不是额外被误选的,如果是,就手动把选择范围的终点调整到这个元素的前面,再更新选择对象。具体代码可以这么改:function get_selected_sentences_range() { var selection = window.getSelection(); var sentences_order_range = []; if (selection.rangeCount > 0) { var range = selection.getRangeAt(0); // 追溯到起始和结束对应的元素节点 let startEl = range.startContainer; while (startEl && startEl.nodeType !== Node.ELEMENT_NODE) { startEl = startEl.parentNode; } let endEl = range.endContainer; while (endEl && endEl.nodeType !== Node.ELEMENT_NODE) { endEl = endEl.parentNode; } // 检查是否选中了额外的div(这里假设你的目标div有.sentences_contain类) const isExtraDiv = endEl && !range.intersectsNode(endEl.firstChild) || endEl !== startEl && !range.isPointInRange(endEl.firstChild, 0); if (isExtraDiv) { // 把选择范围的终点设到额外div的前面 range.setEndBefore(endEl); selection.removeAllRanges(); selection.addRange(range); // 更新endEl为真正选中的最后一个div endEl = endEl.previousSibling; } // 收集真正选中的div let currentNode = startEl; while (currentNode && currentNode !== endEl?.nextSibling) { if (currentNode.classList.contains('sentences_contain')) { sentences_order_range.push(currentNode); } currentNode = currentNode.nextSibling; } } return sentences_order_range; }接管三击选择行为:直接阻止浏览器默认的三击选中逻辑,自己手动控制选中的范围。比如给每个目标div绑定点击事件,统计点击次数,当检测到三击时,就手动选中当前div的全部内容,不让浏览器乱扩展范围:
let clickTimer = null; let clickCount = 0; document.querySelectorAll('.sentences_contain').forEach(div => { div.addEventListener('mousedown', (e) => { clickCount++; clearTimeout(clickTimer); if (clickCount === 3) { e.preventDefault(); // 手动选中当前div的所有内容 const selection = window.getSelection(); const range = document.createRange(); range.selectNodeContents(div); selection.removeAllRanges(); selection.addRange(range); clickCount = 0; } // 超过300ms没连续点击就重置计数 clickTimer = setTimeout(() => { clickCount = 0; }, 300); }); });过滤选中结果:如果不想改选择范围的逻辑,也可以在最后收集选中div的时候,加一层过滤。比如只保留那些选择范围真正覆盖的div,用
range.intersectsNode()或者range.containsNode()方法来判断,把浏览器误选的那个div排除掉。
备注:内容来源于stack exchange,提问作者Cecel
相关产品推荐
相关产品推荐

