Как динамически добавить тег <span>в указанное c расположение тега <p>? - PullRequest
2 голосов
/ 06 января 2020

По сути, я пытаюсь реализовать функцию, которая выделяет определенный текст при выборе. Это строго для браузера Google Chrome.

Например: перед выбором:

<html>
    <body>
        <p>sample text</p>
    </body>
</html>

После выбора «текста» из «образца текста»:

<html>
    <body>
        <p>sample <span class="state-highlighted">text</span> </p>
    </body>
</html>

JavaScript:

document.body.addEventListener("mousedown", (event) => {
  document.body.addEventListener("mouseup", (event) => {

    // Assume we have checked that mousedown position is different from mouseup position.
    // Not sure what to do after this.

  });
});

Я мог бы начать с более простого вопроса: как вставить элемент span в элемент paragragh, скажем, по щелчку?

Ответы [ 2 ]

2 голосов
/ 06 января 2020

При наведении мыши вызовите window.getSelection(), чтобы получить объект Selection . Вы можете проверить его, чтобы найти начальный и конечный текст выделения внутри <p>. Затем замените <p> HTML, чтобы окружить этот фрагмент текста <span class="highlighted">:

const p = document.body.querySelector('p');
const origContent = p.textContent;
p.addEventListener('mousedown', () => {
  p.textContent = origContent;
});
p.addEventListener('mouseup', (e) => {
  const selection = window.getSelection();
  if (!selection) {
    return;
  }
  const range = selection.getRangeAt(0);
  // If user starts highlighting on the right, and drags mouse to the left,
  // endOffset will be smaller than startOffset:
  const startIndex = Math.min(range.startOffset, range.endOffset);
  const { length } = String(selection);
  const endIndex = startIndex + length;
  p.textContent = p.textContent;
  p.innerHTML = (
    p.textContent.slice(0, startIndex) +
    '<span class="highlighted">' +
    selection +
    '</span>' +
    p.textContent.slice(endIndex)
  );
});
.highlighted {
  background-color: orange;
}
<p>sample text sample text sample text sample text sample text sample text sample text sample text sample text</p>

Если пользователь может выбрать более одной части текста за раз, и вы хотите выделить оба несмежных фрагмента текста, Вы можете перебирать диапазоны от 0 до selection.rangeCount и выделять исходный контекст для создания нового HTML соответственно.

1 голос
/ 06 января 2020

Существует метод Range.surroundContents, который пригодится здесь, но он выбрасывает при выделении только части элемента.
Так что в вашем случае может быть лучше извлечь содержимое текущего диапазона, добавьте его в новый узел, а затем вставьте этот новый узел, в котором находится диапазон:

document.getElementById('target').addEventListener('mouseup', e => {
  const sel = getSelection();
  const range = sel.getRangeAt(0);
  const highlighter = document.createElement('span');
  highlighter.classList.add('highlight');
  highlighter.append(range.extractContents());
  range.insertNode(highlighter);
})
.highlight { color: red; }
<p id="target">Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.</p>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...