Диапазон JavaScript — может быть немного полезен

внешний интерфейс JavaScript машинное обучение электронная книга

Диапазон — это встроенный объект JavaScript. Вообще говоря, он не используется во многих местах. В основном он используется в некоторых интерактивных сценах, таких как выделение аннотаций. Лучше сказать, что он не используется. , поэтому я подытожу здесь заметки, не вдаваясь слишком глубоко.

Следует отметить, что многие из методов здесь являются экспериментальными функциями, поэтому использование производственной среды должно быть осторожным.Подробности см. в MDN. Я не буду здесь вдаваться в подробности.

Сценарии применения ассортимента

Таких относительно необычных API-приложений не так много, здесь мы сначала разбираемся со сценариями применения диапазона.

  1. Это обычная электронная книга и так далее.

  2. Базовая документация, необходимая для машинного обучения маркировки человеком (что я сделал)

Конечно, должно быть много других сценариев, и я с ними особо не контактировал, кому интересно, они могут узнать о них сами.

что такое диапазон

Как следует из названия, Range на самом деле можно рассматривать как выделенный текстовый диапазон, но Range не зависит от выбора мыши, и мы можем создать или клонировать его самостоятельно. Но прежде чем мы подробно поговорим о Range, давайте взглянем на Selection.

Как показано на рисунке, когда мы выделяем фрагмент текста, мы можем передатьwindow.getSelectionчтобы получить объект Selection

image

image

Выбор можетwindow.getSelection().toString()Получить выделенный текст напрямую, но часто мы хотим получить не выделенный текст, а получить местоположение выделенного текста и сохранить его. Здесь в игру вступает Range.

window.getSelection().getRangeAt(0)Объект Selection можно преобразовать в объект Range.

image

Нам нужно сосредоточиться на startContainer, endContainer, startOffset, endOffset. Эти четыре свойства могут найти выделенный текст.

image

Как показано на рисунке выше, мы знаем, что элементы Dom расположены в секциях, где контейнер ссылается на каждую секцию, а смещение — это выбранная позиция. Диапазон должен быть непрерывным, чтобы мы могли найти полный диапазон.

Хранение диапазона

Если он используется в качестве выделения, диапазон должен храниться на сервере, но в качестве js-объекта диапазон не может быть напрямую сохранен в базе данных, в это время диапазон должен быть обработан.

Как упоминалось выше, Range можно создать вручную:document.createRange:

var range = document.createRange();

range.setStart(startNode, startOffset);
range.setEnd(endNode, endOffset);

здесьstartNodeОтносится к startContainer, который, естественно, относится к элементу dom. Когда вы видите это, у вас должен быть план в голове. Единственное, что нелегко сохранить, — это элемент dom. Затем мы можем преобразовать элемент dom в селектор и сохраните его.Получите элемент dom с помощью селектора.

Конечно, у нас есть и другие варианты: xpath, в основном потому, что я использовал xpath, когда взялся за проект.Код для преобразования dom в xpath выглядит следующим образом:

// 获取一个元素的xpath
function getElementXPath (element) {
  if (!element) return null

  if (element.id) {
    return `//*[@id=${element.id}]`
  } else if (element.tagName === 'BODY') {
    return '/html/body'
  } else {
    const sameTagSiblings = Array.from(element.parentNode.childNodes)
      .filter(e => e.nodeName === element.nodeName)
    const idx = sameTagSiblings.indexOf(element)

    return getElementXPath(element.parentNode) +
      '/' +
      element.tagName.toLowerCase() +
      (sameTagSiblings.length > 1 ? `[${idx + 1}]` : '')
  }
}

Преобразовать xpath в диапазон:

function createRangeFromXPathRange (xpathRange) {
    var startContainer,
      endContainer,
      endOffset,
      evaluator = new XPathEvaluator()

    // must have legal start and end container nodes
    startContainer = evaluator.evaluate(
      xpathRange.startContainerPath,
      document.documentElement,
      null,
      XPathResult.FIRST_ORDERED_NODE_TYPE,
      null
    )
    if (!startContainer.singleNodeValue) {
      return null
    }

    if (xpathRange.collapsed || !xpathRange.endContainerPath) {
      endContainer = startContainer
      endOffset = xpathRange.startOffset
    } else {
      endContainer = evaluator.evaluate(
        xpathRange.endContainerPath,
        document.documentElement,
        null,
        XPathResult.FIRST_ORDERED_NODE_TYPE,
        null
      )
      if (!endContainer.singleNodeValue) {
        return null
      }

      endOffset = xpathRange.endOffset
    }

    // map to range object
    var range = document.createRange()
    range.setStart(startContainer.singleNodeValue, xpathRange.startOffset)
    range.setEnd(endContainer.singleNodeValue, endOffset)
    return range
  }

Суммировать

Примечания к этой статье не будут представлять слишком много API или слишком глубоко, но идеи использования определены. взаимное поощрение.

image