containsNode()
方法采用可选的第二个参数,即partialContainment
。
当我将其设置为
true
时,它似乎工作正常,但有时会拾取不属于可见选择的相邻元素。我将其设置为 false
以更严格,但它遗漏了元素。
页面上可见的“突出显示”与 API 如何解释“选定”内容之间有区别吗?
在下面的示例中,如果您选择部分文本,则某些字母不会变为活动状态,即使它们明显突出显示。我需要更改什么才能使显示为选中的任何内容的文本变为红色?
const sequences = ['CRABAPPLE', 'ORANGES', 'SQUASH'];
const handleTextSelection = (e) => {
const selection = window.getSelection();
const $container = $(e.currentTarget);
const $sequence = $(e.target).closest('.sequence');
$sequence.find('.letter').each((i, el) => {
$(el).toggleClass('letter-active', selection.containsNode(el, false));
});
selection.empty();
};
$('#container').append(sequences.map(sequence =>
$('<div>', { class: 'sequence' }).append(sequence.split('').map(letter =>
$('<div>', { class: 'letter', text: letter })))));
$('#container').on('mouseup', handleTextSelection);
html, body, #container { width: 100%; height: 100%; margin: 0; padding: 0; }
#container { display: flex; flex-direction: row; gap: 0.25rem; align-items: center; justify-content: center; }
.sequence { display: flex; flex-direction: row; }
.sequence:after { content: ','; }
.sequence:last-child:after { content: none; }
.letter-active { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container"><div>
以下似乎工作得更好一些,但它仍然将部分(未实际选择的)字母计为所选字母。
const sequences = ['CRABAPPLE', 'ORANGES', 'SQUASH'];
const getLetter = (node) => {
let letter = node;
if (node.nodeName === '#text') { node = node.parentElement; }
return node.classList.contains('letter') ? node : null;
};
const handleTextSelection = (e) => {
const selection = window.getSelection();
const range = selection.getRangeAt(0);
const { startContainer, endContainer } = range
const $container = $(e.currentTarget);
const $sequence = $(range.commonAncestorContainer);
const letterStart = getLetter(startContainer);
const letterEnd = getLetter(endContainer);
if (!letterStart || !letterEnd) { return; }
let active = false;
$sequence.find('.letter').each((i, el) => {
if (el === letterStart) { active = true; }
$(el).toggleClass('letter-active', active);
if (el === letterEnd) { active = false; }
});
selection.empty();
};
$('#container').append(sequences.map(sequence =>
$('<div>', { class: 'sequence' }).append(sequence.split('').map(letter =>
$('<div>', { class: 'letter', text: letter })))));
$('#container').on('mouseup', handleTextSelection);
html, body, #container { width: 100%; height: 100%; margin: 0; padding: 0; }
#container { display: flex; flex-direction: row; gap: 0.25rem; align-items: center; justify-content: center; }
.sequence { display: flex; flex-direction: row; }
.sequence:after { content: ','; }
.sequence:last-child:after { content: none; }
.letter-active { color: red; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="container"><div>