目录:
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
<style>
div {
padding: 30px;
}
.highlight {
background-color: yellow;
}
</style>
</head>
<body>
<div class="container">
<section>
<h1>Heading 1</h1>
Text without tag
<p id="p1">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quae esse
tempora architecto, debitis fugit
<span style="color: red;">Span Text</span> amet mollitia quidem minima
numquam suscipit labore quod magnam temporibus odit sint totam itaque
quo maxime.
</p>
<p id="p2">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptas
cupiditate ratione ullam veniam ab corporis, tempore impedit repellat
mollitia incidunt error fuga voluptates omnis, qui enim sapiente ut
culpa ipsum?
</p>
<p id="p3">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Distinctio,
laboriosam inventore nemo id architecto nostrum ipsum est culpa hic
recusandae qui ad consequuntur! Deleniti dolorem quae reprehenderit
quasi! Iusto, dolores!
</p>
</section>
<section>
<h1>Heading 2</h1>
Text without tag
<p id="p1">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quae esse
tempora architecto, debitis fugit
<span style="color: red;">Span Text</span> amet mollitia quidem minima
numquam suscipit labore quod magnam temporibus odit sint totam itaque
quo maxime.
</p>
<p id="p2">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptas
cupiditate ratione ullam veniam ab corporis, tempore impedit repellat
mollitia incidunt error fuga voluptates omnis, qui enim sapiente ut
culpa ipsum?
</p>
<p id="p3">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Distinctio,
laboriosam inventore nemo id architecto nostrum ipsum est culpa hic
recusandae qui ad consequuntur! Deleniti dolorem quae reprehenderit
quasi! Iusto, dolores!
</p>
</section>
<section>
<h1>Heading 3</h1>
<p id="p4">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Quae esse
tempora architecto, debitis fugit
<span style="color: red;">Span Text</span> amet mollitia quidem minima
numquam suscipit labore quod magnam temporibus odit sint totam itaque
quo maxime.
</p>
<p id="p5">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Voluptas
cupiditate ratione ullam veniam ab corporis, tempore impedit repellat
mollitia incidunt error fuga voluptates omnis, qui enim sapiente ut
culpa ipsum?
</p>
<p id="p6">
Lorem ipsum dolor sit amet consectetur adipisicing elit. Distinctio,
laboriosam inventore nemo id architecto nostrum ipsum est culpa hic
recusandae qui ad consequuntur! Deleniti dolorem quae reprehenderit
quasi! Iusto, dolores!
</p>
</section>
</div>
<button id="highlightButton">Highlight</button>
<script src="src/index.js"></script>
</body>
</html>
index.js
console.clear();
document.getElementById("highlightButton").addEventListener("click", () => {
document.getElementById("highlightButton").disabled = true;
highlight();
});
function highlight() {
const sel = window.getSelection();
const range = sel.getRangeAt(0);
const {
commonAncestorContainer,
startContainer,
endContainer,
startOffset,
endOffset
} = range;
const nodes = [];
console.group("range");
console.log("rage", range);
console.log("commonAncestorContainer", commonAncestorContainer);
console.log("startContainer", startContainer);
console.log("endContainer", endContainer);
console.log("startOffset", startOffset);
console.log("endOffset", endOffset);
console.log("startContainer.parentNode", startContainer.parentNode);
console.groupEnd();
if (startContainer === endContainer) {
const span = document.createElement("span");
span.className = "highlight";
range.surroundContents(span);
nodes.push(startContainer);
console.log(nodes);
return;
}
// get all posibles selected nodes
function getNodes(childList) {
console.group("***** getNode: ", childList);
childList.forEach((node) => {
console.log("node:", node, "nodoType", node.nodeType);
const nodeSel = sel.containsNode(node, true);
console.log("nodeSel", nodeSel);
// if is not selected
if (!nodeSel) return;
const tempStr = node.nodeValue;
console.log("nodeValue:", tempStr);
if (node.nodeType === 3 && tempStr.replace(/^\s+|\s+$/gm, "") !== "") {
console.log("nodo agregado");
nodes.push(node);
}
if (node.nodeType === 1) {
if (node.childNodes) getNodes(node.childNodes);
}
});
console.groupEnd();
}
getNodes(commonAncestorContainer.childNodes);
console.log(nodes);
nodes.forEach((node, index, listObj) => {
const { nodeValue } = node;
let text, prevText, nextText;
if (index === 0) {
prevText = nodeValue.substring(0, startOffset);
text = nodeValue.substring(startOffset);
} else if (index === listObj.length - 1) {
text = nodeValue.substring(0, endOffset);
nextText = nodeValue.substring(endOffset);
} else {
text = nodeValue;
}
const span = document.createElement("span");
span.className = "highlight";
span.append(document.createTextNode(text));
const { parentNode } = node;
parentNode.replaceChild(span, node);
if (prevText) {
const prevDOM = document.createTextNode(prevText);
parentNode.insertBefore(prevDOM, span);
}
if (nextText) {
const nextDOM = document.createTextNode(nextText);
parentNode.insertBefore(nextDOM, span.nextSibling);
}
});
sel.removeRange(range);
}
效果图:
取消标记,改个class就好了~~
找了半天终于找到可用的~
https://codesandbox.io/s/api-selection-multiple-with-nodes-forked-tzvkd