Это довольно сложная проблема, но с ней было приятно поиграть.
Вот один день, чтобы сделать это:
Присоедините прослушиватели событий мыши к содержащему элементу.Используйте event.target
, чтобы определить начальный и конечный узлы, которые были выбраны.Используйте эти узлы, чтобы добавить смещения к числам, указанным в необработанном выделении.
Html:
<p id="outer" style="margin: 0px;">
<span>Welcome to India which</span>
<span>
<span>was great country for tourist places</span>
</span>
</p>
Javascript:
const flattenNodes = node =>
Array.from(node.children).reduce((acc, curr) => {
if (curr.childElementCount > 0) {
acc.push(flattenNodes(curr))
} else {
acc.push(curr)
}
return acc
}, [])
const getOffsetForElementAtIndex = nodes => elementIndex =>
nodes.reduce((sum, node, i) => (i < elementIndex ? sum + node.textContent.length : sum), 0)
const getSelection = ev => {
const nodes = flattenNodes(ev.currentTarget).flat()
const startElementIndex = nodes.indexOf(mouseDownElement)
const endElementIndex = nodes.indexOf(ev.target)
const { startOffset, endOffset } = document.getSelection().getRangeAt(0)
const start = startOffset + getOffsetForElementAtIndex(nodes)(startElementIndex)
const end = endOffset + getOffsetForElementAtIndex(nodes)(endElementIndex)
console.log(`start: ${start}, end: ${end}`)
}
let mouseDownElement = null
const el = document.getElementById('outer')
el.addEventListener('mousedown', ev => (mouseDownElement = ev.target))
el.addEventListener('mouseup', ev => getSelection(ev))
здесь кодовый код