I have a difficult situation with html and javascript. My html page allows user to select text and highlight it with colors. Now I want to save the state into database to sh
You need to capture the path of the node in order to know its location.
This can be done in several ways.
The easiest way is to traverse the dom up until the body and create a selector.
function getPathFromElement(element) {
var stack = [];
while (element.parentNode != document.documentElement) {
var sibCount = 0;
var sibIndex = 0;
var childNodes = element.parentNode.childNodes;
var childLength = childNodes.length;
for (var i = 0; i < childLength; i++) {
var sib = childNodes[i];
if (sib.nodeName == element.nodeName) {
if (sib === element) {
sibIndex = sibCount;
}
sibCount++;
}
}
if (element.hasAttribute("id") && element.id !== "") {
stack.unshift(`${element.nodeName.toLowerCase()}#${element.id}`);
}
else if (sibCount > 1) {
stack.unshift(`${element.nodeName.toLowerCase()}:eq(${sibIndex})`);
}
else {
stack.unshift(element.nodeName.toLowerCase());
}
element = element.parentNode;
}
return stack.join(" > ")
}
Lets assume that you want to give your users two options to select text.
For the first option you can use a button with click handler or mouseup event.
I will use a button for simplicity.
function sendDataToServer(data) {
}
document.querySelector("#button").addEventListener("click", function (e) {
var { target, text } = getSelectionTextAndContainerElement();
var path = getPathFromElement(target);
sendDataToServer({
path: path,
text: text
});
});
getSelectionTextAndContainerElement function basicaly selects the text and the element.
function getSelectionTextAndContainerElement() {
var text;
var containerElement = null;
if (typeof window.getSelection !== "undefined") {
var selection = window.getSelection();
if (selection.rangeCount) {
var node = selection.getRangeAt(0).commonAncestorContainer;
containerElement = node.nodeType == 1 ? node : node.parentNode;
text = selection.toString();
}
}
else if (typeof document.selection !== "undefined" && document.selection.type !== "Control") {
var textRange = document.selection.createRange();
containerElement = textRange.parentElement();
text = textRange.text;
}
return {
text: text,
target: containerElement
};
}
For the second option you can use the select event handler.
document.addEventListener("select", onSelect, false);
function onSelect(e) {
var { text } = getSelectionTextAndContainerElement();
var path = getPathFromElement(e.target);
sendDataToServer({
path: path,
text: text
});
}
For input text or textarea its better to use the select event handler.
If you will use the first option to get the selection you won't get the correct target node because of the fact that input text and textarea are built using Shadow DOM.
So its better to ignore the target node retruned from the getSelectionTextAndContainerElement function, and to use the target property of the select event.
I have created an example in jsfiddle for you.