Highlight Text Fragments Selected By User Without Nesting Tags
I have a
some test phrase
and I need to allow user to select different fragments of text and highlight them in different colors. Also I need to allow user to
Solution 1:
I think you can start with this. You should thouroughly test it if it satisfy your case. Perhaps you should also refactor it to better fit you needs.
function mark() {
let selection = document.getSelection();
if(selection.type !== 'Range') { return;}
let pos = window.placeOfSelections;
let ranges = [];
let start = 0;
Array.prototype.forEach.call(pos.childNodes, function(chD)
{
ranges.push([start, start + chD.textContent.length, chD.nodeName === 'MARK']);
start += chD.textContent.length;
});
let text = pos.textContent;
let range = selection.getRangeAt(0);
let firstNode = range.startContainer;
let lastNode = range.endContainer;
selection.removeAllRanges();
let firstNodeIndex = Array.prototype.findIndex.call(pos.childNodes, node => node === firstNode || node.firstChild === firstNode);
let lastNodeIndex = Array.prototype.findIndex.call(pos.childNodes, node => node === lastNode || node.firstChild === lastNode);
let newSelectionStart = ranges[firstNodeIndex][0] + range.startOffset;
let newSelectionEnd = ranges[lastNodeIndex][0] + range.endOffset;
pos.innerHTML = text;
range.setStart(pos.childNodes[0], newSelectionStart);
range.setEnd(pos.childNodes[0], newSelectionEnd);
let node = document.createElement('MARK');
let cnt = range.extractContents();
node.appendChild(cnt);
range.insertNode(node);
let marks = ranges.filter(r => r[2]);
while(marks.length != 0)
{
let startEnd = marks.shift();
if(startEnd[0]>= newSelectionStart && startEnd[1] <= newSelectionEnd)
{
continue;
}
if(startEnd[0]>= newSelectionStart && startEnd[0] <= newSelectionEnd)
{
startEnd[0] = newSelectionEnd;
}
else
if(startEnd[1]>= newSelectionStart && startEnd[1] <= newSelectionEnd)
{
startEnd[1] = newSelectionStart;
}
else
if(startEnd[0] <=newSelectionStart && startEnd[1] >= newSelectionEnd)
{
marks.push([newSelectionEnd, startEnd[1]]);
startEnd[1] = newSelectionStart;
}
let tnStart = 0, tnEnd = 0;
let textNode = Array.prototype.find.call(pos.childNodes, function(tn)
{
tnEnd += tn.textContent.length;
if(tnStart <= startEnd[0] && startEnd[1] <= tnEnd )
{
return true;
}
tnStart += tn.textContent.length ;
});
range.setStart(textNode, startEnd[0] - tnStart);
range.setEnd(textNode, startEnd[1] - tnStart);
node = document.createElement('MARK');
node.appendChild(range.extractContents());
range.insertNode(node);
}
}
window.placeOfSelections.addEventListener('keyup', mark);
window.placeOfSelections.addEventListener('mouseup', mark);
function unmark(e) {
var tgt = e.target;
if ((tgt.tagName === 'MARK' || (e.parentNode && e.parentNode.tagName === "MARK")) && e.ctrlKey) {
let txt = tgt.textContent;
tgt.parentNode.replaceChild(document.createTextNode(txt), tgt);
}
}
window.placeOfSelections.addEventListener('mousedown', unmark);
mark {background-color: #BCE937 ;}
<p id="placeOfSelections">some test phrase</p>
Post a Comment for "Highlight Text Fragments Selected By User Without Nesting Tags"