선택 표시 사이의 교차점 처리


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>

답변:


4

선택한 텍스트 의 startContainer& endContainergetRangeAt찾아와 비교할 수 있습니다 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.containsNode를 사용할 수 있습니다 : https://developer.mozilla.org/en-US/docs/Web/API/Selection/containsNode

이를 통해 선택에 포함 된 노드를 플래그 할 수 있습니다. partialContainment 플래그를 true 로 설정해야 하므로 부분적으로 만 선택된 노드를 감지합니다.

따라서 처음으로 특정 클래스 이름으로 선택에 포함 된 노드에 플래그를 지정합니다. 그런 다음 execCommand 를 수행 하여 스타일을 적용하십시오. 그런 다음 이 노드에서 outerHTMLinnerHTML 로 설정하여 이전에 플래그가 지정된 태그를 삭제했습니다 . 방금 적용한 스타일은 유지하지만 이전 스타일은 제거합니다. 이처럼 :

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) — 내용 편집 가능한 요소의 코드를 검사하면 그 구조를 볼 수 있습니다. 각 줄은 별도의 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>

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.