dev*_*oid 20 javascript getselection
我有一个带有文本内容的html页面.在选择任何文本并按突出显示按钮时,我可以更改所选文本的样式以突出显示相同的文本.为了实现这个功能,我写了以下方法.
sel = window.getSelection();
var range = sel.getRangeAt(0);
var span = document.createElement('span');
span.className = "highlight" + color;
range.surroundContents(span);
Run Code Online (Sandbox Code Playgroud)
如果您选择没有html标记的文本,但是当文本中间有任何html标记时,它会正常工作
无法在'Range'上执行'surroundContents':Range已部分选择了非Text节点.
如何解决这个问题呢.是否可以为每个部分分别突出显示相同的内容(除以html标签)?
And*_*ion 27
document.getElementById('execute').addEventListener('click', function() {
var range = window.getSelection().getRangeAt(0),
span = document.createElement('span');
span.className = 'highlight';
span.appendChild(range.extractContents());
range.insertNode(span);
});Run Code Online (Sandbox Code Playgroud)
.highlight { background-color: yellow; }Run Code Online (Sandbox Code Playgroud)
<div id="test">
Select any part of <b>this text and</b> then click 'Run'.
</div>
<button id="execute">Run</button>Run Code Online (Sandbox Code Playgroud)
与其重新发明轮子,不如使用Rangy的突出显示功能。
我已经分叉了RGraham创建的小提琴,并创建了一个新的小提琴以显示其工作原理。这是这样做的:
var applier = rangy.createClassApplier("highlight");
var highlighter = rangy.createHighlighter();
highlighter.addClassApplier(applier);
document.getElementById('execute').addEventListener('click', function() {
highlighter.removeAllHighlights();
highlighter.highlightSelection("highlight");
});
Run Code Online (Sandbox Code Playgroud)
这样做是创建一个荧光笔,该荧光笔将highlight在完全位于选择区域内的元素上设置类,并highlight根据需要跨该选择区域的元素使用该类创建跨度。单击带有id execute的按钮时,将删除旧的突出显示并应用新的突出显示。
荧光笔功能是Rangy版本的一部分,被认为是“ alpha”。不过,我一直在持续使用几年四肢瘦长的alpha版本,但现在它已经非常罕见,我发现与我的应用程序的问题,我可以追溯到瘦长。几次我发现Rangy存在问题,Tim Down(作者)反应灵敏。
我的解决方案突出显示所有选定的节点。
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("range", 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);
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);
}
Run Code Online (Sandbox Code Playgroud)
示例https://codesandbox.io/s/api-selection-multiple-with-nodes-gx2is?file=/index.html
dev*_*oid -3
if (window.getSelection) {
var sel = window.getSelection();
if (!sel) {
return;
}
var range = sel.getRangeAt(0);
var start = range.startContainer;
var end = range.endContainer;
var commonAncestor = range.commonAncestorContainer;
var nodes = [];
var node;
for (node = start.parentNode; node; node = node.parentNode){
var tempStr=node.nodeValue;
if(node.nodeValue!=null && tempStr.replace(/^\s+|\s+$/gm,'')!='')
nodes.push(node);
if (node == commonAncestor)
break;
}
nodes.reverse();
for (node = start; node; node = getNextNode(node)){
var tempStr=node.nodeValue;
if(node.nodeValue!=null && tempStr.replace(/^\s+|\s+$/gm,'')!='')
nodes.push(node);
if (node == end)
break;
}
for(var i=0 ; i<nodes.length ; i++){
var sp1 = document.createElement("span");
sp1.setAttribute("class", "highlight"+color );
var sp1_content = document.createTextNode(nodes[i].nodeValue);
sp1.appendChild(sp1_content);
var parentNode = nodes[i].parentNode;
parentNode.replaceChild(sp1, nodes[i]);
}
}
Run Code Online (Sandbox Code Playgroud)