選択マーク間の交差の処理


9

私が持っているマークボタン UI上で、任意のユーザの選択が赤でマークされ、クリックします。ここでは問題ありません。私はこれを達成しますdocument.execCommand("insertHTML")

しかし、古い選択のマーキングの共通部分である新しい選択が作成された場合、古い選択の赤いマーキングが消えるという追加の要件があります。

例として:

次の画像では、これテストがマークされています。今、私が最初から彼のテスを選択しマークをクリックすると、これの古いマーキングとテストが消え、交差があるため、彼のテスのみがマークされるはずです。

ここに画像の説明を入力してください

コード:

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

で選択したテキストのstartContainerendContainerを検索しgetRangeAt、と比較できますcontentContainer。そして、それらがと等しくない場合は contentContainerbg-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) — 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>

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.