seçim işaretleri arasındaki kavşağı işleme


9

Bir var işareti düğmesini UI üzerinde, herhangi bir kullanıcı seçimi kırmızı işaretlenir, tıklatarak. Burada sorun yok. Bunu elde ederimdocument.execCommand("insertHTML")

Ancak, eski seçim işaretlerinin kesişimi olan yeni seçim oluşturulursa, eski seçimin kırmızı işaretinin kaybolması gerektiğini de ek bir gereksinimim var.

Örnek olarak:

Aşağıdaki resimde: bu ve test işaretlenmiştir. Ben seçmek Şimdi eğer onun tes baştan ve işaretini tıklayın, eski işaretler bu ve test uzağa gitmeli ve sadece onun tes bir kavşak olduğundan işaretlenmiş olmalıdır.

resim açıklamasını buraya girin

kod:

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>

Yanıtlar:


4

Seçili metnin startContainer& endContainerişaretini ile bulabilir getRangeAtve ile karşılaştırabilirsiniz contentContainer. Ve eğer eşit değilse contentContainer, o zaman bg-redsınıfı kaldırın .

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 desteğine ihtiyacınız yoksa selection.containsNode'u kullanabilirsiniz : https://developer.mozilla.org/en-US/docs/Web/API/Selection/containsNode

Bu, seçimde bulunan düğümleri işaretlemenizi sağlar. PartialContainment bayrağını true olarak ayarlamanız gerekir , böylece yalnızca kısmen seçilen düğümleri algılar.

Böylece, ilk kez belirli bir sınıf adıyla seçimin içerdiği düğümleri işaretlersiniz. Sonra stilinizi uygulamak için execCommand yaparsınız . Daha sonra, bu düğümlerdeki externalHTML öğesini innerHTML olarak ayarlayarak daha önce işaretlenen etiketleri sildiniz . Az önce uyguladığınız stili koruyacaksınız, ancak öncekileri kaldıracaksınız. Bunun gibi:

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

Ben 'getSelection'.anchorNode.parentNode sınıf bg-red olup olmadığını tespit etmeye çalıştım ve değiştirin, ama çok fazla yan etkisi ortaya çıkıyor.

Yani, regexp ile çözüm ...

(* 1) - İçerik düzenlenebilir öğenin kodunu incelerseniz, yapısını görürsünüz: Her yeni satır ayrı bir div'dir. \nÇok satırlı seçimlere izin vermek için her yeni satır sembolünü "satır kesen" HTML ile değiştirmeniz gerekir .

(* 2) - Tarayıcı kendi düzeltmelerini HTML'ye ekler ve doğru değiştirmeleri önler. Metinde görünmesi muhtemel olmayan HTML olmayan bir dize eklemek zorunda kaldım. Ve tüm değişikliklerden sonra - geçerli HTML ekleyin.

(* 3) - Ben → burada tüm düzenli ifadeleri analiz etmek tavsiye https://regex101.com/r/j88wc0/1 ana fikri tüm çift görünüşleri değiştirmektir <span class="bg-red"> anything instead of closing span <span class="bg-red">ya </span> anything instead of starting span tag </span>.

Düğmeye her bastığınızda bu kodun tüm innerHTML'yi yenilediğini unutmayın. Birkaç bin satırlık metinle iyi çalışmaz)

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>

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.