Javascript选择文本突出显示概率

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

Range.extractContents:

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)

  • 把兄弟放在那里而不是孩子而且它会破坏:http://jsfiddle.net/sL7joxhs/ - 突出显示来自`test1`和`test2`的一些文本,它将两个div包裹在一个跨度中并打破结构 (3认同)

Lou*_*uis 5

与其重新发明轮子,不如使用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(作者)反应灵敏。


Ale*_*nez 5

我的解决方案突出显示所有选定的节点。

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)