menangani persimpangan antara tanda seleksi

9

Saya memiliki tombol tanda di UI, mengklik yang, pilihan pengguna mana saja ditandai merah. Tidak ada masalah di sini. Saya mencapai ini dengandocument.execCommand("insertHTML")

Tetapi saya memiliki persyaratan tambahan bahwa jika seleksi baru dibuat yang merupakan perpotongan dari tanda pilihan lama, tanda merah pilihan lama harus hilang.

Sebagai contoh:

Pada gambar berikut: ini dan pengujian ditandai. Sekarang jika saya memilih tesnya dari tanda mulai dan klik, tanda lama ini dan pengujian harus pergi dan hanya tesnya yang harus ditandai karena ada persimpangan.

masukkan deskripsi gambar di sini

kode:

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>

asdasd
sumber

Jawaban:

4

Anda dapat menemukan startContainer& endContainerdari teks yang dipilih getRangeAt, dan membandingkannya dengan contentContainer. Dan jika mereka tidak sama dengan contentContainer, maka hapus bg-redkelasnya.

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>

Bahador Raghibizadeh
sumber
4

Jika Anda tidak memerlukan dukungan IE, Anda dapat menggunakan selection.containsNode : https://developer.mozilla.org/en-US/docs/Web/API/Selection/containsNode

Ini memungkinkan Anda menandai flag yang terkandung dalam seleksi. Anda perlu mengatur flag partialContainment menjadi true, sehingga akan mendeteksi node yang hanya dipilih sebagian.

Jadi, pertama kali Anda menandai node yang berisi seleksi dengan nama kelas tertentu. Kemudian Anda melakukan perintah execc Anda untuk menerapkan gaya Anda. Kemudian, Anda menghapus tag yang ditandai sebelumnya dengan menetapkan outerHTML pada node ini ke innerHTML . Anda akan mempertahankan gaya yang baru saja Anda terapkan, tetapi akan menghapus yang sebelumnya. Seperti ini:

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>

Julien Grégoire
sumber
0

Saya sudah mencoba mendeteksi apakah 'getSelection'.anchorNode.parentNode memiliki kelas bg-red, dan menggantinya, tetapi terlalu banyak efek samping yang muncul.

Jadi, solusinya dengan regexp ...

(* 1) - Jika Anda memeriksa kode elemen yang dapat diedit konten, Anda akan melihat strukturnya: Setiap baris baru adalah div terpisah. Anda harus mengganti setiap simbol baris baru \ndengan HTML "pemecah garis", untuk memungkinkan pemilihan multi-baris.

(* 2) - Browser memasukkan koreksi sendiri ke HTML dan mencegah penggantian yang benar. Saya terpaksa memasukkan string Non-HTML, yang sepertinya tidak akan muncul dalam teks. Dan setelah semua penggantian - masukkan HTML yang valid.

(* 3) - Saya sarankan untuk menganalisis semua ekspresi reguler di sini → https://regex101.com/r/j88wc0/1 Gagasan utamanya adalah mengganti semua tampilan ganda <span class="bg-red"> anything instead of closing span <span class="bg-red">atau </span> anything instead of starting span tag </span>.

Perhatikan, bahwa kode ini menyegarkan semua innerHTML, setiap kali Anda menekan tombol. Ini tidak akan berfungsi juga dengan teks dari beberapa ribu baris)

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>

OPTIMUS PRIME
sumber