Reputation: 139
Given a page like this:
<p>
<span class="1">Here's some text</span>
<span class="2">that the user</span>
<span class="3">could select.</span>
</p>
If a user selects the whole sentence (from "Here's" to "select."), I want to return "1" and "3".
If a user selects part of the sentence (from "some" in span 1 to "the" in span 2), I want to return "1" and "2".
What's the best approach here?
*Edit - I'm looking for a solution that allows for highlighting multiple pieces of (non-overlapping) text concurrently.
For example: "Here's some text that" and "user could select." - In this case, [[1,2],[2,3]] would be returned.
Upvotes: 0
Views: 60
Reputation: 3
so here is the html
<span class="class-1"
onmousedown="getElementBegin('1')" onmouseup="getElementEnd('1')" >
algum texto 1
</span> <br>
<span class="class-2"
onmousedown="getElementBegin('2')" onmouseup="getElementEnd('2')">
algum texto 2
</span> <br>
<span class="class-3"
onmousedown="getElementBegin('3')" onmouseup="getElementEnd('3')">
algum texto 3
</span> <br>
<p id="selected"> nada!</p>
And here is the js:
let begin
let end
let selection
document.onmouseup = function () {
selection = window.getSelection().toString()
console.log(selection);
selected = document.getElementById('selected')
selected.innerHTML = `selection goes to: ${begin} until ${end} <br> selection: ${selection}`
}
function getElementBegin(beginElement) {
begin = beginElement
console.log(begin)
}
function getElementEnd(endElement) {
end = endElement
console.log(end)
}
Upvotes: 0
Reputation: 9354
Edit: I just found out there is actually a selection.containsNode method which sounds like it would be perfect for you but apparently it's still an experimental technology.
There is no extensive highlight event in javascript so the solution is not going to be straightforward, and the fact that the text is split up across multiple elements makes it more difficult. You could use document.selection
as the top answer to this similar question suggests, but then you still need to parse the returned text against the innerHTML of the span
elements which seems like it would be pretty fiddly.
I think your best bet in this case would be to basically recreate highlight functionality using the existing JS events. Here is a naive implementation missing some functionality like double clicking to select and keyboard selection but you get the idea.
const hLights = Array.from(document.querySelectorAll('.hlight'));
let active = false;
let hoveredEls = [];
window.addEventListener('mousedown', function() {
active = true;
});
window.addEventListener('mouseup', function() {
active = false;
console.log(hoveredEls);
hoveredEls = [];
});
hLights.forEach(el => {
el.addEventListener('mousemove', function() {
if (active && !hoveredEls.includes(el.id)) hoveredEls.push(el.id);
});
el.addEventListener('mouseenter', function() {
if (active) {
if(hoveredEls.includes(el.id)) {
const idx = hoveredEls.findIndex(el => el === el.id);
hoveredEls.splice(idx, 1);
} else {
hoveredEls.push(el.id);
}
}
});
});
<p>
<span id="1" class="hlight">Here's some text</span>
<span id="2" class="hlight">that the user</span>
<span id="3" class="hlight">could select.</span>
</p>
Upvotes: 1