Поиск диапазона выделенного текста по родительскому узлу

#javascript #html #range

#javascript #HTML #диапазон

Вопрос:

Я хочу найти диапазон выделенного текста относительно родительского элемента. Итак, в этом <p> элементе anchorOffset amp; focusOffset для «fox» равно [16,19]

 <p>The quick brown fox jumps over the lazy dog.</p>
 

Но если мы добавим <b> тег перед «fox», то значения изменятся на [1,4] .

 <p>The quick <b>brown</b> fox jumps over the lazy dog.</p>
 

Я думаю, что подсчет индекса начинается с конца </b> тега. Но я хочу, чтобы он по-прежнему отображал исходное значение, независимо от HTML внутри <p> . Для этого я попытался создать диапазон, но все равно не смог его понять. Ниже приведен код в виде функции.

 function rangefun() {
  var range = document.createRange();
  var referenceNode = document.getElementsByTagName('P').item(0);
  range.selectNode(referenceNode);
  var selection = window.getSelection();
  var start = selection.anchorOffset;
  var end = selection.focusOffset;
  console.log("start: "   start);
}
 

Ответ №1:

Ниже приведена модифицированная версия вашего кода, которая делает то, что вы хотите.

Он принимает как узлы anchor и extent , которые являются дочерними элементами <p> selection переменной (т.Е. window.getSelection() ).

Эти два узла передаются calculateOffset функции. Для каждого из узлов вычисляется сумма длины текста предыдущих братьев и сестер. Увеличение этой общей длины текста на относительное смещение выделения (то, которое находится в дочернем узле) приведет к start end смещениям и относительно длины <p> текста.

 function rangefun() {
  var selection = window.getSelection();
  var start = selection.anchorOffset;
  var end = selection.extentOffset;
  var anchorNode = selection.anchorNode;
  var extentNode = selection.extentNode;

  var startIndex = calculateOffset(anchorNode, start);
  var endIndex = calculateOffset(extentNode, end);
  console.log('start: '   startIndex);
  console.log('end: '   endIndex);
}

function calculateOffset(child, relativeOffset) {
  var parent = child.parentElement;
  
  // verify whether or not the correct parent element is selected, modify if necessary
  if (parent.tagName != 'P') {
    parent = parent.closest('p');
    child = child.parentElement;
  }
  var children = [];

  // add the child's preceding siblings to an array
  for (var c of parent.childNodes) {
    if (c === child) break;
    children.push(c);
  }

  // calculate the total text length of all the preceding siblings and increment with the relative offset
  return relativeOffset   children.reduce((a, c) => a   c.textContent.length, 0);
}
 

Комментарии:

1. Спасибо, я смог сделать это с помощью focusOffset вместо extentOffset.