Spec-Zone.ru › Web APIs

Выбор: метод getComposedRanges()

Ограниченная доступность

Эта функция не относится к Baseline, так как она не работает в некоторых из самых широко используемых браузеров.

  • Узнать больше
  • Полная совместимость
  • Отправить отзыв

Экспериментальная: Это экспериментальная технология
Перед использованием в продакшене тщательно проверьте таблицу совместимости с браузерами.

Метод Selection.getComposedRanges() возвращает массив объектов StaticRange, представляющих текущие выделенные диапазоны, и может возвращать диапазоны, потенциально пересекающие границы теней.

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

Возвращаемые диапазоны представляют диапазон на момент вызова getComposedRanges(). Если DOM или теневое DOM изменены, выбранный диапазон, вероятно, будет неверным. Прикладной код может использовать MutationObserver для отслеживания изменений DOM, а затем вызвать Selection.setBaseAndExtent() для обновления выделения.

Примечание: Этот метод следует использовать вместо Selection.getRangeAt(), когда требуется выделение диапазонов, потенциально пересекающих границы корней теней. Selection.getRangeAt() не учитывает корни теней. Возвращаемый диапазон не определён и варьируется в разных браузерах.

Синтаксис

getComposedRanges()
getComposedRanges(shadowRoot1)
getComposedRanges(shadowRoot1, shadowRoot2)
getComposedRanges(shadowRoot1, shadowRoot2, /* …, */ shadowRootN)

Параметры

shadowRoot1, …, shadowRootN

Ноль или более аргументов ShadowRoot. Если конечная точка выделения находится внутри одного из предоставленных корней теней, диапазон сможет возвращать узлы внутри соответствующего дерева Shadow DOM. В противном случае, если выделение пересекает границу тени, а соответствующий ShadowRoot не предоставлен, возвращаемый диапазон будет изменён, чтобы включать весь хост-элемент для корня тени.

Значение возврата

Массив объектов StaticRange, представляющих выделенные диапазоны в составе (сплошном) дереве документа. На момент написания спецификации ожидается, что этот массив будет содержать только один объект.

Примеры

Выбор через встроенные корни тени

Этот пример демонстрирует, как ведет себя getComposedRanges(), как при передаче корней теней, так и без них, а также контрастирует его с Selection.getRangeAt().

Он позволяет выбрать текст, определённый в разных узлах DOM и во внутренних и закрытых корнях теней, скопировать диапазон для выделения с использованием различных подходов и затем повторно применить диапазон, чтобы посмотреть, как хорошо работало исходное выделение.

HTML

HTML определяет некоторые текстовые узлы с некоторыми элементами <span>, к которым мы подключим корни тени с помощью JavaScript. Мы также добавим некоторые кнопки для копирования и применения выделения с помощью нескольких различных методов.

<p>
  DOM Text One<span id="openHost"></span>DOM Text Two<span
    id="closedHost"></span
  >DOM Text Three
</p>
<button id="copySelection">Copy range not passing shadow roots</button>
<button id="copySelectionWithShadowRoots">
  Copy range passing shadow roots
</button>
<button id="applySelection">Apply selection</button>
<hr />
<button id="copySelectionRangeAt">Copy range with getRangeAt()</button>
<button id="applySelectionGetRangeAt">Apply selection</button>

CSS

CSS ничего интересного не делает. Мы просто выстраиваем кнопки вертикально, чтобы их было проще читать.

button {
  display: block;
}

JavaScript

Большая часть работы происходит в JavaScript. Сначала мы выводим сообщение, если getComposedRanges() не поддерживается, хотя мы фактически не предотвращаем попытку использовать его в остальной части примера.

if (!("getComposedRanges" in Selection.prototype)) {
  log("getComposedRanges() method not supported in this browser");
}

Затем мы создаем открытый и закрытый корни теней и подключаем их к двум элементам <span>, которые мы создали в HTML. Они содержат некоторый простой текст полужирным шрифтом, чтобы мы могли легко идентифицировать узлы тени при рендеринге HTML.

let openRoot = openHost.attachShadow({ mode: "open" });
openRoot.innerHTML = `<b>Open Shadow DOM Text</b>`;

let closedRoot = closedHost.attachShadow({ mode: "closed" });
closedRoot.innerHTML = `<b>Closed Shadow DOM Text</b>`;

Далее мы создаём код для получения выделенных диапазонов с помощью getComposedRanges() при нажатии первых двух кнопок. Первая кнопка вызывает getComposedRanges() без передачи корней теней, а вторая передаёт оба корня теней. В обоих случаях составной диапазон сохраняется в переменной.

const copySelectionButton = document.querySelector("#copySelection");
let composedRangeSelection = null;
copySelectionButton.addEventListener("click", () => {
  composedRangeSelection = window.getSelection().getComposedRanges()[0];
  log(`Selection copied (no shadow roots passed)`);
});

const copySelectionWithShadowRootsButton = document.querySelector(
  "#copySelectionWithShadowRoots",
);
copySelectionWithShadowRootsButton.addEventListener("click", () => {
  composedRangeSelection = window
    .getSelection()
    .getComposedRanges(openRoot, closedRoot)[0];
  log(`Selection has been copied (shadow roots passed)`);
});

Обработчик кнопки "Применить выделение" показан ниже. Он вызывает setBaseAndExtent() для установки текущего выделения, передавая узлы и смещения из сохранённого диапазона.

const applySelectionButton = document.querySelector("#applySelection");
applySelectionButton.addEventListener("click", () => {
  if (composedRangeSelection) {
    window
      .getSelection()
      .setBaseAndExtent(
        composedRangeSelection.startContainer,
        composedRangeSelection.startOffset,
        composedRangeSelection.endContainer,
        composedRangeSelection.endOffset,
      );
    log(`Selection applied`);
  } else {
    log(`No selection to apply`);
  }
});

Последняя часть кода определяет кнопки для копирования текущего выделенного диапазона с помощью Selection.getRangeAt() и затем повторного применения выделения.

const copySelectionRangeAtButton = document.querySelector(
  "#copySelectionRangeAt",
);
let rangeSelection = null;
copySelectionRangeAtButton.addEventListener("click", () => {
  const selection = window.getSelection();
  if (selection.rangeCount > 0) {
    log(`Selection copied using getRangeAt()`);
    rangeSelection = selection.getRangeAt(0);
  } else {
    log(`No range selected`);
  }
});

const applySelectionGetRangeAtButton = document.querySelector(
  "#applySelectionGetRangeAt",
);
applySelectionGetRangeAtButton.addEventListener("click", () => {
  if (rangeSelection) {
    window
      .getSelection()
      .setBaseAndExtent(
        rangeSelection.startContainer,
        rangeSelection.startOffset,
        rangeSelection.endContainer,
        rangeSelection.endOffset,
      );
    log(`Selection applied`);
  } else {
    log(`No selection to apply`);
  }
});

Результаты

Выполняемый пример показан ниже. Выделите текст в верхней строке, начиная с обычного текста и заканчивая жирным разделом, чтобы выделились узлы из DOM в корень тени. Если вы выберите "Скопировать диапазон, передавая корни теней", а затем кнопку "Применить выделение", вы заметите, что выделение не изменится, потому что код предоставил доступ ко всем узлам в корне тени, даже если он закрыт. Если затем вы выберете кнопку "Скопировать диапазон, не передавая корни теней", а затем применить, выделение будет расширено до конца текста в корне тени. Это происходит потому, что выделение переопределяется до конца узла хоста, поскольку методу getComposedRanges() не предоставлялась видимость внутри дерева тени.

Также проверьте, что происходит при использовании кнопок "Скопировать диапазон с помощью getRangeAt()" и "Применить выделение". Вы должны обнаружить, что выделенный диапазон является достаточно произвольным, если вы переходите в корень тени, и он отличается в зависимости от используемого браузера.

Спецификации

Спецификация
Selection API
# dom-selection-getcomposedranges

Совместимость с браузерами

Рабочий стол Мобильный
Chrome Edge Firefox Opera Safari Chrome Android Firefox для Android Opera Android Safari на iOS Samsung Internet WebView Android
getComposedRanges Нет Нет предварительный просмотр Нет 17 Нет Нет Нет 17 Нет Нет
returns_multiple_ranges Нет Нет предварительный просмотр Нет Нет Нет Нет Нет Нет Нет Нет

См. также

  • Selection, интерфейс, к которому он принадлежит.

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Selection/getComposedRanges

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API