处理选择标记之间的交集


9

我在UI上有一个标记按钮,单击后,所有用户选择都标记为红色。没问题 我通过实现document.execCommand("insertHTML")

但是我还有一个附加要求,如果创建的新选择是旧选择标记的交集,则旧选择的红色标记应该消失。

举个例子:

在下图中:测试已标记。现在,如果我选择他是TES从一开始,点击标记,旧标志的这个测试应该离开,只有他是TES应标,因为有一个路口。

在此处输入图片说明

码:

const button = document.getElementById("button");

button.addEventListener('click', ()=>{
	const s = window.getSelection();
  const selectionStr = s.toString();
  document.execCommand("insertHTML", false, `<span class="bg-red">${selectionStr}<span>`);
})
.bg-red {  
background: red;
}
<div contenteditable="true">
 this is testing  this is testing  this is testing
</div>

<button id="button">mark</button>

Answers:


4

您可以通过找到“ startContainerendContainergetRangeAt,并与进行比较contentContainer。如果它们不等于 contentContainer,则删除bg-red该类。

const button = document.getElementById("button");

button.addEventListener('click', ()=>{
  let contentContainer = document.getElementById("contentContainer");
  const selection = window.getSelection();
  if (selection.rangeCount > 0){
    let startContainer =  selection.getRangeAt(0).startContainer.parentNode;
    let endContainer =  selection.getRangeAt(0).endContainer.parentNode;
    if(startContainer != contentContainer)
      startContainer.classList.remove('bg-red')
    if(endContainer != contentContainer)
      endContainer.classList.remove('bg-red')
  }
  const selectionStr = selection.toString();
  document.execCommand("insertHTML", false, `<span class="bg-red">${selectionStr}<span>`); 
})
.bg-red {  
  background: red;
}
<div id="contentContainer" contenteditable="true">
 this is testing  this is testing  this is testing
</div>

<button id="button">mark</button>


4

如果不需要IE支持,则可以使用selection.containsNodehttps : //developer.mozilla.org/en-US/docs/Web/API/Selection/containsNode

这使您可以标记选择中包含的节点。您需要将partialContainment标志设置为true,以便它将检测仅部分选择的节点。

因此,第一次使用特定的类名称标记选择所包含的节点。然后,执行execCommand以应用样式。然后,您删除了被设置先前标记的标签outerHTML这些节点上的innerHTML。您将保留刚刚应用的样式,但将删除以前的样式。像这样:

const button = document.getElementById("button");

button.addEventListener('click', () => {
  const s = window.getSelection();
  const selectionStr = s.toString();

  tagIntersection(s)
  document.execCommand("insertHTML", false, `<span class="bg-red">${selectionStr}<span>`);
  removeIntersection(s)
})

function tagIntersection(s) {
  const redSpans = document.getElementsByClassName('bg-red')
  for (let i = 0; i < redSpans.length; i++) {
    if (s.containsNode(redSpans[i], true)) {
      redSpans[i].classList.add('to-remove');
    }
  }
}

function removeIntersection(s) {
  // using querySelector because getElements returns a live nodelist 
  // which is a problem when you manipulate the nodes
  const toRemovespans = document.querySelectorAll('.to-remove')
  for (let i = 0; i < toRemovespans.length; i++) {
    toRemovespans[i].outerHTML = toRemovespans[i].innerHTML;
  }
}
.bg-red {
  background: red;
}
<div contenteditable="true" id="editableDiv">
  this is testing this is testing this is testing
</div>

<button id="button">mark</button>


0

我试图检测'getSelection'.anchorNode.parentNode是否具有bg-red类,并将其替换,但是出现了太多的副作用。

因此,使用正则表达式的解决方案...

(* 1) —如果您检查content-editable元素的代码,您将看到它的结构:每行新行都是一个单独的div。必须\n使用“换行” HTML 替换每个换行符号,以允许多行选择。

(* 2) -浏览器将自己的更正插入HTML,并防止正确替换。我被迫插入任何非HTML字符串,该字符串不太可能出现在文本中。在所有替换之后-插入有效的HTML。

(* 3) -我建议在这里分析所有正则表达式→ https://regex101.com/r/j88wc0/1主要思想是替换<span class="bg-red"> anything instead of closing span <span class="bg-red">或的所有重复出现</span> anything instead of starting span tag </span>

请注意,每次单击按钮时,此代码都会刷新所有innerHTML。几千行文字无法正常工作)

let button = document.getElementById("button");
let block = document.getElementById("block");

button.addEventListener('click', function(){
  let s = window.getSelection();
  let str = s.toString().replace(/\n/g,'</span></div><div><span class="bg-red">'); // (*1)

  document.execCommand("insertHTML", false, `bubufication`); // (*2)

  block.innerHTML = block.innerHTML
    .replace(/bubufication/, `<span class="bg-red">${str}</span>`)
    .replace(/<span class="bg-red">(.*?)<\/span><span class="bg-red">/g,'$1<span class="bg-red">')
    .replace(/<span class="bg-red">(((?!<\/span>).)*?<span class="bg-red">)/g,"$1")
    .replace(/(<\/span>((?!<span class="bg-red">).)*)<\/span>/g,"$1"); // (*3)
});
.bg-red {
  background-color: red;
}
<div id="block" contenteditable="true">
  <div>this is testing  this is testing  this is testing</div>
  <div>this is testing  this is testing  this is testing</div>
</div>

<button id="button">mark</button>

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.