I solved this problem by saving 5 pieces of information from the range into the database:
var saveNode = range.startContainer;
var startOffset = range.startOffset; // where the range starts
var endOffset = range.endOffset; // where the range ends
var nodeData = saveNode.data; // the actual selected text
var nodeHTML = saveNode.parentElement.innerHTML; // parent element innerHTML
var nodeTagName = saveNode.parentElement.tagName; // parent element tag name
And then to build the range from the database, I have this function:
function buildRange(startOffset, endOffset, nodeData, nodeHTML, nodeTagName){
var cDoc = document.getElementById('content-frame').contentDocument;
var tagList = cDoc.getElementsByTagName(nodeTagName);
// find the parent element with the same innerHTML
for (var i = 0; i < tagList.length; i++) {
if (tagList[i].innerHTML == nodeHTML) {
var foundEle = tagList[i];
}
}
// find the node within the element by comparing node data
var nodeList = foundEle.childNodes;
for (var i = 0; i < nodeList.length; i++) {
if (nodeList[i].data == nodeData) {
var foundNode = nodeList[i];
}
}
// create the range
var range = cDoc.createRange();
range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);
return range;
}
From there, I can just use my highlightRange
function again to highlight the text.
Update 2022-01
Didn't know this was actually still being used. Thought I might as well give two cents about the two for loops and how we can improve them with modern syntax:
const foundEle = tagList.find(x => x.innerHTML === nodeHTML);
const foundNode = nodeList.find(x => x.data === nodeData);