I am trying to make a web app which allows the user to select some text on a page, and then with the click of another button highlight it. When the user goes back to the page, I want the highlight to show up in the same spot as well.
So I've gotten as far as:
var selectedRange = document.getSelection().getRangeAt(0);
highlightRange(selectedRange);
Where highlightRange is a function that highlights the range. This works so far.
The problem is, I need a way to save the selectedRange into a database so that it can be fetched again later. After that, I need to re-create the range from this data and highlight it again. I've found this method:
document.createRange();
From this page here:
But I'm not really sure how I can make this work
UPDATE:
I know I'll need to re-create the range from scratch afterwards. And to do that I will use something like this:
var range = document.createRange();
range.setStart(startNode,startOffset);
range.setEnd(endNode,endOffset);
I can easily store startOffset and endOffset because those are just numbers. But startNode and endNode are node objects. I don't know how to store this in a database?
More specifically, I need to store the reference to the node in a database.
I am trying to make a web app which allows the user to select some text on a page, and then with the click of another button highlight it. When the user goes back to the page, I want the highlight to show up in the same spot as well.
So I've gotten as far as:
var selectedRange = document.getSelection().getRangeAt(0);
highlightRange(selectedRange);
Where highlightRange is a function that highlights the range. This works so far.
The problem is, I need a way to save the selectedRange into a database so that it can be fetched again later. After that, I need to re-create the range from this data and highlight it again. I've found this method:
document.createRange();
From this page here: https://developer.mozilla/en-US/docs/Web/API/range
But I'm not really sure how I can make this work
UPDATE:
I know I'll need to re-create the range from scratch afterwards. And to do that I will use something like this:
var range = document.createRange();
range.setStart(startNode,startOffset);
range.setEnd(endNode,endOffset);
I can easily store startOffset and endOffset because those are just numbers. But startNode and endNode are node objects. I don't know how to store this in a database?
More specifically, I need to store the reference to the node in a database.
Share Improve this question edited May 5, 2014 at 21:57 adrianmcli asked May 5, 2014 at 18:46 adrianmcliadrianmcli 1,9963 gold badges23 silver badges49 bronze badges 1- @JayBlanchard I have updated my post with more detail, thanks. – adrianmcli Commented May 5, 2014 at 21:58
2 Answers
Reset to default 5I 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 paring 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);
run the following script when user select texts
let sel = window.getSelection();
let range = sel.getRangeAt(0);
let startNode = range.startContainer;
let endNode = range.endContainer;
if (startNode.nodeType == 3) {
var startIsText = true;
var startFlag = startNode.parentNode;
startNode = startNode.nodeValue;
} else {
var startIsText = false;
var startFlag = startNode;
}
if (endNode.nodeType == 3) {
var endIsText = true;
var endFlag = endNode.parentNode;
endNode = endNode.nodeValue;
} else {
var endIsText = false;
var endFlag = endNode;
}
let startOffset = range.startOffset;
let endOffset = range.endOffset;
let startTagName = startFlag.nodeName;
let startHTML = startFlag.innerHTML;
let endTagName = endFlag.nodeName;
let endHTML = endFlag.innerHTML;
//you can store this in database and use it
let rInfo = {
startNode: startNode,
startOffset: startOffset,
startIsText: startIsText,
startTagName: startTagName,
startHTML: startHTML,
endNode: endNode,
endOffset: endOffset,
endIsText: endIsText,
endTagName: endTagName,
endHTML: endHTML
};
window.localStorage.setItem("r", JSON.stringify(rInfo));
then use the following scripts when user go back to the page
function findEle(tagName, innerHTML) {
let list = document.getElementsByTagName(tagName);
for (let i = 0; i < list.length; i++) {
if (list[i].innerHTML == innerHTML) {
return list[i];
}
}
}
function show(startNode,startIsText,startOffset,
endNode,endIsText,endOffset,sP,eP) {
var s, e;
if (startIsText) {
let childs = sP.childNodes;
console.log(childs);
for (let i = 0; i < childs.length; i++) {
console.log(childs[i].nodeValue);
console.log(startNode);
if (childs[i].nodeType == 3 && childs[i].nodeValue == startNode)
s = childs[i];
console.log(s);
}
} else {
s = startNode;
}
if (endIsText) {
let childs = eP.childNodes;
console.log(childs);
for (let i = 0; i < childs.length; i++) {
if (childs[i].nodeType == 3 && childs[i].nodeValue == endNode)
e = childs[i];
console.log(e);
}
} else {
e = endNode;
}
let range = document.createRange();
range.setStart(s, startOffset);
range.setEnd(e, endOffset);
let sel = window.getSelection();
sel.removeAllRanges();
sel.addRange(range);
}
function use(obj) {
let sP = findEle(obj.startTagName, obj.startHTML);
let eP = findEle(obj.endTagName, obj.endHTML);
show(
obj.startNode,
obj.startIsText,
obj.startOffset,
obj.endNode,
obj.endIsText,
obj.endOffset,
sP,
eP
);
}
let a = window.localStorage.getItem("r");
use(JSON.parse(a));