问题
In essence, I'm trying to implement a feature which highlights certain text when selected. This is strictly for the Google Chrome browser.
For example: Before selection:
<html>
<body>
<p>sample text</p>
</body>
</html>
After selecting "text" from "sample text":
<html>
<body>
<p>sample <span class="state-highlighted">text</span> </p>
</body>
</html>
JavaScript:
document.body.addEventListener("mousedown", (event) => {
document.body.addEventListener("mouseup", (event) => {
// Assume we have checked that mousedown position is different from mouseup position.
// Not sure what to do after this.
});
});
I could start with a simpler question: How do I insert a span element into a paragragh element, let's say on click?
回答1:
There is a Range.surroundContents method that would come handy here, but it will throw when selecting only part of an element.
So in your case it might be better to extract the content of the current Range, append it in your new node, and then insert that new node where the Range is:
document.getElementById('target').addEventListener('mouseup', e => {
const sel = getSelection();
const range = sel.getRangeAt(0);
const highlighter = document.createElement('span');
highlighter.classList.add('highlight');
highlighter.append(range.extractContents());
range.insertNode(highlighter);
})
.highlight { color: red; }
<p id="target">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
回答2:
On mouseup, call window.getSelection()
to get a Selection object. You can examine it to find the start and end text of the selection inside the <p>
. Then replace the <p>
's HTML to surround that section of text with <span class="highlighted">
:
const p = document.body.querySelector('p');
const origContent = p.textContent;
p.addEventListener('mousedown', () => {
p.textContent = origContent;
});
p.addEventListener('mouseup', (e) => {
const selection = window.getSelection();
if (!selection) {
return;
}
const range = selection.getRangeAt(0);
// If user starts highlighting on the right, and drags mouse to the left,
// endOffset will be smaller than startOffset:
const startIndex = Math.min(range.startOffset, range.endOffset);
const { length } = String(selection);
const endIndex = startIndex + length;
p.textContent = p.textContent;
p.innerHTML = (
p.textContent.slice(0, startIndex) +
'<span class="highlighted">' +
selection +
'</span>' +
p.textContent.slice(endIndex)
);
});
.highlighted {
background-color: orange;
}
<p>sample text sample text sample text sample text sample text sample text sample text sample text sample text</p>
If the user might select more than one part of the text at a time, and you'd want to highlight both discontiguous pieces of text, you can iterate over the ranges from 0 to selection.rangeCount
and slice the original context to create the new HTML accordingly.
来源:https://stackoverflow.com/questions/59606037/how-do-i-dynamically-append-a-span-tag-into-a-specific-location-of-the-p-tag