- Операторы
- Управляющие инструкции
- JS Объекты
- браузер BOM
- HTML DOM
- Свойства узлов
- «Семья» элементов
- Выборка элементов DOM
- Добавление и удаление узлов
- Размеры и прокрутка
- Intersection Observer API
- Атрибуты и стили
- CSSStyleSheet
- Выделение
- Хранение данных
- События
- HTML Объекты
- Промисы, async/await
- Сетевые запросы
- Бинарные данные и файлы
- Модули
- Классы
- Разное
Выделение: Range, TextRange и Selection
На этой странице помещена информация об объектах Range, TextRange и Selection. Информация была позаимствована у learn.javascript.ru, www.webmaster.ee, habrahabr.ru, developer.mozilla.org.
Range
– это объект, соответствующий фрагменту документа, который может включать узлы и участки текста из этого документа. Наиболее подробно объект Range
описан в спецификации DOM Range.
Чтобы понять о чем речь, обратимся к самому простому случаю Range
, который будет подробно рассмотрен ниже – к выделениям. В приводимом ниже примере выделите несколько слов в предложении. Будет выводиться текстовое содержимое выделяемой области:
Соберем микс из жирности, курсива и ссылки и повыделяем здесь.
Но такие области можно создавать не только с помощью пользовательского выделения, но и из JavaScript-сценария, выполняя с ними определенные манипуляции. Однако, написать простой иллюстрирующий код сразу не выйдет, т.к. есть одно НО – Internet Explorer до версии 9. В Microsoft создали собственную реализацию – объект TextRange. Разберём каждую реализацию по-отдельности.
Range
Range
состоит из двух граничных точек (boundary-points), соответствующих началу и концу области. Позиция любой граничной точки определяется в документе с помощью двух свойств: узел (node) и смещение (offset).
Контейнером (container) называют узел, содержащий граничную точку. Сам контейнер и все его предки называются родительскими контейнерами (ancestor containers) для граничной точки. Родительский контейнер, включающий обе граничные точки, называют корневым контейнером (root container).
На изображении выше граничные точки выделения лежат в текстовых узлах (#text1
и #text2
), которые являются контейнерами. Для левой границы родительскими контейнерами являются #text1
, H1
, BODY
, для правой – #text2
, P
, BODY
. Общий родитель для обоих граничных точек – BODY
, этот элемент является корневым контейнером.
Если контейнер является текстовым узлом, то смещение определяется в символах от начала DOM-узла. Если контейнер является элементом (Document
, DocumentFragment
, Element
…), то смещение определяется в дочерних узлах.
Смотрим на иллюстрацию:
Граничные точки объекта Range
s1 лежат в текстовых узлах, поэтому смещение задается в символах от начала узла. Для s2 граничные точки расставлены так, что включают весь абзац <p>Blah xyz</p>, поэтому контейнером является элемент BODY
, и смещение считается в позициях дочерних узлов.
Объекты Range
создаются с помощью вызова
document.createRange()
Объект при этом создается пустой, и граничные точки нужно задать далее его методами setStart
и setEnd
. Смотрим пример.
<div id="ex2" style="border:1px dashed #999; color:#666; background:#EEE; padding:2px 5px; margin:10px 0;"> <h2 style="color:#333; margin:0; padding:0 0 7px 0; font:bold 15px Arial;">Соз|даем Range-объект</h2> <p style="color:#333; margin:0; font:13px Arial;"> От третье|го символа заголовка до десятого символа это абзаца. </p> </div> <button onclick="alert1(domRangeCreate())"> Создать Range и вывести его текст </button> <p id="demo"></p> <script> function alert1(x) {document.getElementById('demo').innerHTML = x.replace(/[\r\n]+/g,'<br>');} function domRangeCreate() { // Найдем корневой контейнер var root = document.getElementById('ex2'); // Найдем контейнеры граничных точек (в данном случае тестовые) var start = root.getElementsByTagName('h2')[0].firstChild; var end = root.getElementsByTagName('p')[0].firstChild; if (document.createRange) { // Создаем Range var rng = document.createRange(); // Задаем верхнюю граничную точку, передав контейнер и смещение rng.setStart(start, 3); // Аналогично для нижней границы rng.setEnd(end, 10); // Теперь мы можем вернуть текст, который содержится в полученной области return rng.toString(); } else { return 'Вероятно, у вас IE8-'; } } </script>
Свойства и методы Range
collapsed
Свойство collapsed вернет true
, если граничные точки имеют одинаковые контейнеры и смещение (false
в противном случае).
Синтаксис
// boolean, чтение и изменение rng.collapsed [ = true|false ]
commonAncestorContainer
Свойство commonAncestorContainer возвращает ссылку на узел в дереве документа, в котором расположены начальная и конечная точка диапазона. Нередко получается, что начальная точка области находится в одном узле, а конечная - в другом- В этом случае обобщённый узел в большинстве случаев состоит из обоих узлов (в некоторых случаях это узел document.body). В спецификации W3C DOM разделяемый обобщенный узел называется корневым узлом области (термин, который предоставляет больше информации).
Синтаксис
// ссылка на объект узла, чтение и изменение rng.commonAncestorContainer [ = ссылкаНаОбъектУзла ]
startContainer, endContainer
Свойства startContainer и endContainer возвращают ссылку на узел дерева иерархической структуры документа, содержащим начальную и конечную точку области, соответственно.
Синтаксис
// ссылка на объект узла, чтение и изменение rng.startContainer [ = ссылкаНаОбъектУзла ] rng.endContainer [ = ссылкаНаОбъектУзла ]
Комментарии
Имейте в виду, объектная модель автоматически рассчитывает размер контейнера, сам же контейнер может и не соответствовать необходимой ссылке, используемой для установки начальной и конечной точек области. Например, при использовании метода selectNode() для установки начальной и конечной точки области, окружающей необходимый узел, контейнеры конечных точек наиболее вероятно будут попадать в следующие по уровню узлы. Таким образом, если сначала необходимо расширить область для включения в нее узла, содержащего текущую начальную точку, необходимо использовать значение, возвращаемое свойством startContainer, в качестве параметра метода setStartBefore():
rng.setStartBefore(rng.startContainer)
startOffset, endOffset
Свойства startOffset и endOffset возвращают целочисленное значение количества символов или узлов, которое определяет расположение начальной и конечной точки области, соответственно. Эти смещения указаны для узлов, выполняющих роли контейнеров для области.
Синтаксис
// Целое число, чтение и изменение rng.startOffset [ = смещение ] rng.endOffset [ = смещение ]
Описание, комментарии, примеры
Когда граница области находится на границе узла (или лучше сказать между узлами), возвращаемое целое число задает количество узлов (отсчет начинается с нуля от граничного контейнера). Однако, когда граница области находится посредине текстового узла, возвращаемое целое число представляет собой индекс символа внутри этого узла. Тот факт, что каждая граница имеют свою систему измерения (символы или узлы, в зависимости от используемых контейнеров), может привести к путанице, если не быть достаточно внимательным. При этом возвращаемое целое число для конечной точки может быть меньшим, нежели значение для начальной точки. Давайте рассмотрим следующие вложенные элементы:
<P> This paragraph has an <EM>emphasized</EM> segment.</P>
Следующий оператор устанавливает значение начальной точки области внутри первого узла, а конечную точку области в закрывающем элементе ем
узла:
var rng = document.createRange() rng.setStart(document.getElementById("myP").firstChild, 19); rng.setEndAfter(document.getElementById("myEM"));
Используя полужирный шрифт для представления текста области и символ вертикальной черты ( | ) для определения границ в пределах узлов, можно достаточно просто представить, как выполняется описанный выше сценарий:
<P ID="myP"> This paragraph has |an <EM>emphasized</EM> segment.</P>
Поскольку начало области находится в текстовом узле (первый дочерний узел элемента Р), значение startOffset равно 19; оно определяет расположение символа а относительно an относительно начала узла, его содержащего. Однако конечная точка находится в конце элемента ЕМ. Сценарий распознает эту точку как границу узла и поэтому осуществляет подсчет значения endOffset внутри содержимого внешнего контейнера- элемента Р. Значение endOffset равно 2 (текстовый узел элемента Р имеет индекс 0; элемент ем имеет индекс 1; конечная точка находится в начале последнего текстового узла элемента Р, имеющего индекс 2).
При создании сценариев используются значения endOffset и startOffset достаточно часто; также часто используются свойства endContainer и startContainer для получения целочисленных значений смещения
setStart(), setEnd()
Методы setStart() и setEnd()) задают контейнер (ссылка на узел) и смещение (целочисленное значение) для соответствующих граничных точек.
Синтаксис
rng.setStart (ссылкаНаУзел, смещение) rng.setEnd (ссылкаНаУзел, смещение)
Параметры
- ссылкаНаУзел
- Ссылка на узел. Эта ссылка может указывать на элемент или текстовый узел.
- смещение
- Если первый параметр является узлом элемента, смещение подсчитывается как приращение дочерних узлов внутри определенного элемента узла. Однако, если первый параметр представляет собой текстовый узел, то смещение подсчитывается как приращение Символов внутри текстового узла.
Комментарии
При определении начальной и конечной точек области с помощью этих методов не накладываются никакие ограничения на симметричность границ области. Одна из границ может быть определена относительно текстовое узла, а другая - относительно узла элемента, или наоборот, Для задания конечной точки области, равной последнему узлу или символу внутри текстового узла (в зависимости от единиц измерения параметра смещения), используйте свойствоlength
. Например:
var nodeRef = document.getElementById("myP").lastChild; rng.setEnd(nodeRef.nodeValue.length);
setStartBefore(), setStartAfter(), setEndBefore(), setEndAfter()
Методы setStartBefore(), setStartAfter(), setEndBefore(), setEndAfter() принимают в качестве единственного аргумента ссылку на узел и устанавливают граничные точки в соответствии с естественной границей переданного узла.
Синтаксис
rng.setStartAfter (ссылкаНаУзел) rng.serStartBefore (ссылкаНаУзел) rng.setEndAfter (ссылкаНаУзел) rng.setEndBefore (ссылкаНаУзел)
Комментарии
Начальную и конечную точки текстовой области можно задавать в соответствии с существующими границами узла с помощью этих четырех методов. Ключевые слова before
и after
в названиях методов используются для того, чтобы определить, какую из границ узла необходимо использовать в качестве границы области- Например, применение методов setStartBefore() и setEndAfter() для одного и того же узла элемента в качестве параметра аналогично использованию метода selectNode() для того же элемента. В качестве параметра любого из этих методов можно определить текстовый узел. Однако поскольку эти методы оперируют границами исключительно узлов, значения смещения всегда определяются с учетом расположения узла, а не символа.
Возьмите на заметку, что границы области необязательно должны быть симметричными, другими словами, одна граница может располагаться внутри одного узла, а другая-внутри другого.
Пример
<span id="s1">First</span> <span id="s2">Second</span>
var rng = document.createRange(); // Установит верхнюю граничную точку по левой границе спана #s1 rng.setStartBefore(document.getElementById('s1')); // Установит нижнюю граничную точку по правой границе спана #s2 rng.setEndAfter(document.getElementById('s2'));
selectNode(), selectNodeContents()
Методы selectNode() и selectNodeContents() позволяют создать объект Range
по границам узла, ссылку на который они принимают в качестве единственного аргумента.
Синтаксис
rng.selectNode (ссылкаНаУзел) rng.selectNodeContents (ссылкаНаУзел)
Комментарии
Методы selectNode() и selectNodeContents() - это наиболее удобные методы для задания начальной и конечной точек, между которыми размещается узел или его содержимое. Тип узла, который применяемся в качестве параметра в обоих методах (текстовый узел или узел элемента), зависит от контейнера области и единиц измерения смещения точек.
При использовании selectNode передаваемый узел также войдет в Range
, в то время как selectNodeContents создаст объект только из содержимого узла:
collapse()
Метод collapse() объединяет граничные точки объекта Range
. В качестве единственного аргумента принимает булево значение (true
– для объединения в верхней точке, false
– в нижней). По-умолчанию true
.
Синтаксис
rng.collapse ( [ true|false ] )
toString()
Метод toString() вернет текстовое содержимое объекта Range
.
Синтаксис
rng.toString ()
Возвращаемое значение
Строка, представляющая текстовое содержимое объекта Range
.
cloneContents()
Метод cloneContents() вернет копию содержимого объекта Range
в виде фрагмента документа.
Синтаксис
rng.cloneContents ()
cloneRange()
Метод cloneRange() вернет копию самого объекта Range
.
Синтаксис
rng.cloneRange ()
deleteContents()
Метод deleteContents() удаляет всё содержимое объекта Range
.
Синтаксис
rng.deleteContents ()
detach()
Метод detach() извлекает текущий объект из DOM, так что на него больше нельзя сослаться.
Синтаксис
rng.detach ()
insertNode()
Метод insertNode() принимает в качестве единственного аргумента ссылку на узел (или фрагмент документа) и вставляет его в содержимое объекта Range
в начальной точке.
Синтаксис
rng.insertNode (ссылкаНаУзел)
extractContents()
Методы extractContents() вырезает содержимое объекта Range
и возвращает ссылку на полученный фрагмент документа.
Синтаксис
rng.extractContents ()
Возвращаемое значение
ссылка на узел documentFragment
surroundContents()
Метод surroundContents помещает всё содержимое текущего объекта Range
в новый родительский элемент, ссылка на который принимается в качестве единственного аргумента.
Синтаксис
rng.surroundContents (ссылкаНаУзел)
Пример
Для примера решим небольшую задачку. Найдём в текстовом узле фразу и подсветим её голубым фоном.
<div id="ex3" style="border:1px dashed #999; color:#666; background:#EEE; padding:2px 5px; margin:10px 0;"> Найдем в этом тексте слово "Abuela" и подсветим его синим фоном </div> <div> <input onclick="domRangehighlight('Abuela'); this.style.display = 'none';" type="button" value="Найти!"> </div> <script> function domRangehighlight(text) { var root = document.getElementById('ex3').firstChild; var content = root.nodeValue; if (~content.indexOf(text)) { if (document.createRange) { var rng = document.createRange(); rng.setStart(root, content.indexOf(text)); rng.setEnd(root, content.indexOf(text) + text.length); var highlightDiv = document.createElement('span'); highlightDiv.style.backgroundColor = '#00ffff'; rng.surroundContents(highlightDiv); } else alert('Вероятно, у вас IE8-'); } else alert('Совпадений не найдено'); } </script>
TextRange
Объект TextRange в реализации MSIE – это текстовый диапазон нулевой и более длины. У данного диапазона также есть свои границы, «перемещать» которые можно на целое число текстовых единиц: character(символ), word (слово), sentence (предложение). То есть можно взять и сдвинуть границу на 2(5, 8 и т.д.) слова (символа, предложения) вправо (влево). При этом у объекта сохраняются данные о HTML-содержимом диапазона и есть методы взаимодействия с DOM.
Объект TextRange создается с помощью метода createTextRange
, который можно вызывать в контексте элементов BODY
, BUTTON
, INPUT
(большинство типов), TEXTAREA
.
Рассмотрим свойства и методы объекта TextRange (не все, только самые необходимые):
-
Свойство boundingWidth (boundingHeight) вернет ширину (высоту), которую занимает объект TextRange в пикселях.
-
Свойство boundingTop (boundingLeft) вернет Y(X)-координату верхнего левого угла тестовой области относительно окна документа.
-
Свойство htmlText вернет HTML-содержимое объекта.
-
Свойство text вернет текстовое содержимое объекта (см. пример выше).
-
Свойство offsetTop (offsetLeft) вернет Y(X)-координату верхнего левого угла тестовой области относительно предка.
-
Метод collapse объединяет граничные точки диапазона. В качестве единственного аргумента принимает булево значение (
true
– для объединения в верхней точке,false
– в нижней). По-умолчанию true. -
Метод duplicate клонирует имеющийся текстовый диапазон, возвращая новый, точно такой же.
-
Метод expand расширяет текущий тектовый диапазон до единицы текста, переданной в качестве единственного текстового аргумента:
"character'
– символ."word"
– слово"sentence"
– предложение"textedit"
– сворачивает до первоначального диапазона.
Вернет
true
(false
) в случае успеха (неудачи). -
Метод findText ищет в диапазоне совпадения с текстовой строкой, передаваемой в качестве первого аргумента (без учета регистра). Если совпадение найдено, то границы диапазона сворачиваются до него. В качестве второго (необязательного) аргумента можно передать целое число, указывающее число символов от верхней точки, в которых нужно производить поиск. Далее в качестве аргументов можно перечислять INT-флаги, которые вам вряд ли понадобятся.
-
Метод getBookmark возвращает в случае успешного вызова строку, по которой можно будет восстановить текущее состояние текстового диапазона с помощью метода moveToBookmark.
-
Метод inRange принимает в качестве аргумента другой TextRange и проверяет, входит ли его текстовый диапазон в диапазон контекстного объекта. Возвращает булево значение.
-
Метод isEqual проверяет является ли текущий TextRange идентичным переданному в качестве аргумента. Возвращает булево значение.
-
Метод move(sUnit [, iCount]) сворачивает текущий диапазон до нулевой длины и передвигает на единицу текста, переданного в качестве первого аргумента (character | word | sentence | textedit). В качестве второго (необязательного) аргумента можно передать число единиц, на которое следует передвинуть диапазон.
-
Метод moveEnd (moveStart), аналогично методу move, передвигает верхнюю (нижнюю) границу диапазона на единицу текста, число которых также можно задать необязательным вторым параметром.
-
Метод moveToElementText принимает в качестве аргумента ссылку на DOM-элемент и выставляет границы диапазона Textобъекта Range по границам полученного элемента.
-
Метод moveToPoint принимает в качестве двух обязательных аргументов X и Y-координаты (в пикселях) относительно верхнего левого угла документа и переносит границы диапазона туда.
-
Метод parentElement вернет ссылку на элемент, который полностью содержит диапазон объекта TextRange (или
null
). -
Метод pasteHTML заменяет HTML-содержимое текущего текстового диапазона на строку, переданную в качестве единственного аргумента.
-
Метод select формирует выделение на основе содержимого объекта TextRange, о чем мы подробнее поговорим ниже.
-
Метод setEndPoint принимает в качестве обязательных аргументов текстовый указатель и ссылку на другой TextRange, устанавливая в зависимости от значения указателя границы диапазона. Указатели могут быть следующими: „StartToEnd“, „StartToStart“, „EndToStart“, „EndToEnd“.
Также к TextRange применимы команды метода execCommand, который умеет делать текст жирным, курсивным, копировать его в буфер обмена (только IE) и т.п.
Для закрепления сделаем задачку по поиску текстового содержимого, аналогичную той, что была выше:
<div id="ex4" style="border:1px dashed #999; color:#666; background:#EEE; padding:2px 5px; margin:10px 0;"> Найдем в этом тексте слово "Abuela" и подсветим его голубым фоном </div> <div> <input onclick="ieTextRangeHighlight('Abuela'); this.style.display = 'none';" type="button" value="Найти!"> </div> <script> function ieTextRangeHighlight(text) { var root = document.getElementById('ex4'); var content = root.firstChild.nodeValue; if (~content.indexOf(text)) { if (document.body.createTextRange) { var rng = document.body.createTextRange(); rng.moveToElementText(root); if (rng.findText(text)) rng.pasteHTML('<span style="background:#00ffff;">' + text + '</span>'); } else alert('Вероятно, у вас не IE, смотрите реализацию Range выше'); } else alert('Совпадений не найдено'); } </script>
Selection
Всем знакомо выделение элементов на странице, когда, зажав левую кнопку мыши и передвигая курсор, мы выделяем нужный фрагмент. Или зажимаем Shift и жмём на стрелочки клавиатуры. Или еще как-то, неважно. В данной части статьи мы кроссбраузерно научимся решать две задачи: получать пользовательское выделение и устанавливать собственное.
Получаем пользовательское выделение
Эту задачу мы уже решали в самом начале статьи в примере с миксом. Теперь рассмотрим код:
<div id="demoMix" onmouseup="alert(FgetText())" style="border:1px dashed #999; color:#666; background:#EEE; padding:2px 5px; margin:10px 0;"> Соберем микс из <b>жирности</b>, <em>курсива</em> и <a href="javascript:void(0)">ссылки</a> и повыделяем здесь. </div> <script> function FgetText() { var txt = ''; if (txt = window.getSelection) { // Не IE, используем метод getSelection txt = window.getSelection().toString(); } else { // IE, используем объект selection txt = document.selection.createRange().text; } return txt; } </script>
Все браузеры, кроме IE8-
поддерживают метод window.getSelection()
, который возвращает объект Selection, схожий с рассмотренным ранее Range. У этого объекта есть точка начала выделения (anchor) и фокусная точка окончания (focus). Точки могут совпадать. Рассмотрим свойства и методы объекта Selection:
- Свойство anchorNode вернет контейнер, в котором начинается выделение. Замечу, что началом выделения считается та граница, от которой вы начали выделение. То есть, если вы выделяете справа налево, то началом будет именно правая граница. Это правило работает везде, кроме браузера Opera, в котором anchorNode вернет ссылку на узел левого края выделения.
- Свойство anchorOffset вернет смещение для начала выделения в пределах контейнера anchorNode.
- Свойства focusNode и focusOffset работают аналогично для фокусных точек, то есть точек окончания выделения. Opera и здесь отличилась, возвращает вместо фокусной точки узел правого края выделения.
- Свойство rangeCount возвращает число объектов Range, которые входят в полученное выделение. Это свойство полезно при использовании метода addRange.
- Метод getRangeAt принимает в качестве аргумента индекс объекта Range и возвращает сам объект. Если rangeCount == 1, то работать будет только getRangeAt(0). Таким образом, мы можем получить объект Range, полностью соответствующий текущему выделению.
- Метод collapse сворачивает выделение в точку (каретку). Методу можно передать в качестве первого аргумента узел, в который нужно поместить каретку.
- Метод extend принимает в качестве аргументов ссылку на контейнер и смещение (parentNode, offset), и перемещает фокусную точку в это положение.
- Метод collapseToStart (collapseToEnd) перемещает фокусную (начальную) границу к начальной (фокусной), тем самым сворачивая выделение в каретку.
- Метод selectAllChildren принимает в качестве единственного аргумента ссылку на узел и добавляет всех его потомков в выделение.
- Метод addRange принимает в качестве аргумента объект Range и добавляет его в выделение. Таким образом можно увеличить количество объектов Range, число которых нам подскажет свойство rangeCount.
- Метод removeRange (removeAllRanges) удаляет переданный (все) объект Range из выделения.
- Метод toString вернет текстовое содержимое выделения.
IE предоставляет собственный интерфейс взаимодействия с выделениями – объект selection в контексте document. Для работы с этим объектом используются следующие методы:
- Метод clear убирает выделение вместе с содержимым.
- Метод createRange (ВАЖНО! Не путать со стандартным методом document.createRange() для создания объектов Range!) создает из содержимого выделения TextRange.
- Метод empty убирает выделение, но оставляет содержимое.
Установка собственного выделения
Допустим, вам хочется, чтобы какой-то текстовый фрагмент на странице был выделен, как пользовательское выделение. Это нужно при клиентской реализации поиска по странице и некоторых других задач.
Проще всего решить эту задачу следующим образом:
- Создать объект
Range
(TextRange
для IE8-). - Перевести полученный объект в выделение.
Смотрим реализацию:
<div id="ex5" style="border:1px dashed #999; color:#666; background:#EEE; padding:2px 5px; margin:10px 0;"> Снова будем выделять <span>Abuela</span>, на этот раз без поиска. </div> <div> <input onclick="setSelection()" type="button" value=" Выделить «Abuela» "> <input onclick="clearSelection()" type="button" value=" Снять выделение "> </div> <script> function setSelection() { // Выделить var target = document.getElementById('ex5').getElementsByTagName('span')[0]; var rng, sel; if (document.createRange) { rng = document.createRange(); rng.selectNode(target) sel = window.getSelection(); sel.removeAllRanges(); sel.addRange(rng); } else { var rng = document.body.createTextRange(); rng.moveToElementText(target); rng.select(); } } function clearSelection() { // Снять выделение try { // современный объект Selection window.getSelection().removeAllRanges(); } catch (e) { // для IE8- document.selection.empty(); } } </script>
Совместимость
- В современных браузерах поддерживается стандартный объект Range
- В IE8- поддерживается только собственный объект TextRange.
Есть библиотеки, которые «исправляют» объект TextRange
, добавляя ему нужные свойства из Range
.
Здесь предлагается маленькая библиотека fixIERangeObject.js.
<script src="fixIERangeObject.js"></script> <script> function test() { var range = getRangeObject(); if (range) { var t = "<em>range</em>: «" + range + '»<br>' + "<em>startContainer</em>: " + range.startContainer.nodeValue + '<br>' + "<em>startOffset</em>: " + range.startOffset + '<br>' + "<em>endOffset</em>: " + range.endOffset; document.getElementById('demo').innerHTML = t; } else { alert('Сначала выделите текст'); } } </script> <p>Выделите текст:</p> <pre> Библиотека fixIERangeObject "исправляет" объект TextRange, добавляя ему нужные свойства из Range.</pre> <input type="button" value=" Вывести выделение и свойства startContainer, startOffset, endOffset " onclick="test();" /> <p id="demo"></p>
Вырезать и копировать в буффер обмена
Начиная с IE10 добавлена поддержка команд «Копировать» и «Вырезать» с помощью метода Document.execCommand().
Любой текст выделенный в браузере при выполнении одной из этих команд будет скопирован или вырезан в буфер обмена пользователя. Это позволяет предложить пользователю простой метод выделить часть текста и скопировать в буфер обмена.
Примеры
Для примера, давайте добавим кнопку которая скопирует email адрес в буфер обмена.
Мы добавим email адрес, в наш HTML, с кнопкой клик по которой будет инициировать копирование email.
Добавим обработчик клика по кнопке, который выделит email из содержимого ссылки js-emaillink, выполнит команду копирования, так что бы адрес электронной почты оказался в буфере пользователя и после этого снять выделение с электронной почты, так что пользователь даже не увидит выделение.
В этом примере используется метод document.queryCommandEnabled(), который проверяет возможность выполнения определенной команды.
<p>Мой E-Mail: <a class="js-emaillink" href="mailto:matt@example.co.uk">matt@example.co.uk</a></p> <p><button class="js-emailcopybtn"> Скопировать email-адрес в буфер обмена </button></p> <input id="demo" type="hidden" size='40' placeholder="Скопировать из буфера обмена (Ctrl+V) "> <script> var demo = document.getElementById('demo'); var copyEmailBtn = document.querySelector('.js-emailcopybtn'); try { copyEmailBtn.disabled = !document.queryCommandSupported('copy'); } catch(err) { copyEmailBtn.disabled = true;} if (!copyEmailBtn.disabled) { copyEmailBtn.addEventListener('click', function(event) { // Выборка ссылки с электронной почтой var emailLink = document.querySelector('.js-emaillink'); var range = document.createRange(); range.selectNode(emailLink); window.getSelection().addRange(range); // Теперь, когда мы выбрали текст ссылки, выполним команду копирования if (document.execCommand('copy')) {demo.type="text"; demo.focus();}; // Снятие выделения - ВНИМАНИЕ: вы должны использовать // removeRange(range) когда это возможно window.getSelection().removeAllRanges(); }); } </script>
Здесь используется метод window.getSelection()
, что бы программно выделить текст внутри ссылки, который мы хотим скопировать в буфер обмена пользователя. После вызова document.execCommand()
мы можем снять выделение с помощью window.getSelection().removeAllRanges()
.
Если вы хотите проверить что все прошло успешно, то вы можете рассмотреть результат возвращаемый функцией document.execCommand(). Результат будет false
если функция не поддерживается или отключена.
Команда «вырезать» (cut
) может быть использована для текстовых полей ввода, там, где вы хотите удалить текст и поместить этот текст в буфер обмена.
Использование textarea и кнопки:
<p><textarea class="js-cuttextarea" cols='80' rows='4'> Команда «вырезать» может быть использована для текстовых полей ввода, там, где вы хотите удалить текст и поместить этот текст в буфер обмена. </textarea></p> <p><button class="js-textareacutbtn"> Вырезать Textarea и скопировать в буФер обмена. </button></p> <textarea id="demo" style="display:none" cols='80' rows='4' placeholder="Скопировать из буфера обмена (Ctrl+V) "> </textarea> <script> var demo = document.getElementById('demo'); var cutTextareaBtn = document.querySelector('.js-textareacutbtn'); try { cutTextareaBtn.disabled = !document.queryCommandSupported('cut'); } catch(err) { cutTextareaBtn.disabled = true;} if (!cutTextareaBtn.disabled) { cutTextareaBtn.addEventListener('click', function(event) { var cutTextarea = document.querySelector('.js-cuttextarea'); cutTextarea.select(); if ( document.execCommand('cut') ) { demo.style.display = ''; demo.focus(); } }); } </script>
execCommand()
Метод execCommand() выполняет одну из предопределённых операций над документом.
Синтаксис
document.execCommand ("aCommandName", aShowDefaultUI, aValueArgument)
Параметры
- aCommandName
Наименование одной из комманд метода execCommand()- aShowDefaultUI
Необязательный. Логическое значение (true
илиfalse
), определяющее, поддерживает ли комманда элементы пользовательского интерфейса- aValueArgument
Параметр комманды, если требуется.
Возвращаемое значение
true
при успешном выполнении комманды; false
в обратном случае.
queryCommandSupported()
Метод определяет, поддерживается ли комманда execCommand.
Синтаксис
document.queryCommandSupported ("aCommandName")
Параметры
- aCommandName
- Наименование одной из комманд метода execCommand()
Возвращаемое значение
true
если требуемая комманда может быть выполнена; false
в обратном случае.
Комментарии
Перед вызовом document.execCommand() необходимо убедиться что эти API поддерживаются с помощью queryCommandSupported(). В примерах выше, по результатам проверки совместимости блокируется кнопка.
queryCommandEnabled()
Метод определяет, может ли комманда execCommand быть успешно выполнена при текущем состоянии документа.
Синтаксис
document.queryCommandEnabled ("aCommandName")
Параметры
- aCommandName
- Наименование одной из комманд метода execCommand()
Возвращаемое значение
true
если требуемая комманда может быть выполнена; false
в обратном случае.
Комментарии
Отличие между queryCommandSupported() и queryCommandEnabled() в том, что команды «копировать» и «вырезать» могут поддерживаться браузером, но если текст не выделен, то они не будут доступны. Это удобно в том случае если вы не выбрали фрагмент текста программно и хотите что бы команда отработала ожидаемо, в противном случае показать сообщение пользователю.
Команды execCommand
Команды, которые поддерживаются Вашим браузером, выделены «жирным» шрифтом.
2D-Position | Комманда, позволяющая пользователю передвигать абсолютно позиционированные элементы. |
AbsolutePosition | Комманда, устанавливающая свойство position данного элемента в значение "absolute". |
backColor | Изменить цвет фона документа. В режиме styleWithCss командой устанавливается цвет фона родительского блока. Необходима передача строкового значения цвета в качестве аргумента. (Internet Explorer таким образом устанавливает цвет фона текста.) |
bold | Включает/отключает выделение жирным bold отмеченного текста или начиная с места ввода тескта. (Internet Explorer ипсользует тег <strong> > вместо <b> .) |
contentReadOnly | Делает содержимое документа либо неизменяемым либо редактируемым. Требуется передача булевого true/false в качестве аргумента. (Не поддерживается Internet Explorer.) |
copy | Копирует выделенное в буфер обмена. Возможность такого поведения отличается от браузера к браузеру и расширяется со временем. Следует проверить таблицу совместимости, чтобы убедиться в возможности использования. |
createBookmark | Комманда, создающая "якорь" из выделенного фрагмента текста или возвращает имя "якоря" для выделенного фрагмента текста. |
createLink | Создает ссылку из выделения, если таковое имеется. Необходима передача HREF URI в качестве аргумента. URI должен содержать как минимум один символ, допускается пробельный. (Internet Explorer создаст ccылку и без URI.) |
cut | Вырезает выделенное и помещает его в буфер обмена. Возможность такого поведения отличается от браузера к браузеру и расширяется со временем. Следует проверить таблицу совместимости, чтобы убедиться в возможности использования. |
delete | Удаляет выделенное. |
enableInlineTableEditing | Включает/выключает возможность вставки и удаления строк/столбцов таблицы. (Не поддерживается Internet Explorer.) |
enableObjectResizing | Включает/выключает возможность изменения размера картинок и других объектов. (Не поддерживается Internet Explorer.) |
fontName | Изменяет название шрифта для выделенного текста или с меств ввода текста. Требует передачи в качестве аргумента наименования шрифта (напр., "Arial") |
fontSize | Изменяет размер шрифта выделенного текста или с места ввода текста. Требует передачи в качестве аргумента размера шрифта (1-7). |
foreColor | Изменяет цвет шрифта выделенного текста или с места ввода текста. Требует передачи в качестве аргумента наименования шрифта. |
formatBlock | Добавляет тег HTML-блока вокруг строк, содержащих в себе выделенный текст, заменяя блочный элемент, содержащий такие строки если он существует (в Firefox, BLOCKQUOTE является исключением - он обернет любой блочный элемент). Требует передачи в качестве аргумента наименования Тега. Теоретически может использоваться любой блочный тег (напр., "H1", "P", "DL", "BLOCKQUOTE"). (Internet Explorer поддерживает только теги заголовков H1 - H6, ADDRESS и PRE, которые должны также быть заключены в символы < >, как например: "<H1>".) |
forwardDelete | Удаляет символ справа от курсора, так же как при нажатии на клавишу delete. |
heading | Добавляет тег заголовка вокруг выделенного текста либо в месте где установлен курсор. Требует передачи строки имени тега в качестве аргумента. (то есть "H1", "H6"). (Не поддерживается в Internet Explorer и Safari) |
hiliteColor | Изменяет цвет фона для выделенного текста либо в месте где установлен курсор. Требует передачи цвета в качестве аргумента. UseCSS должен быть включен для работы этой функции. (Не поддерживается в Internet Explorer) |
increaseFontSize | Добавляет тег BIG вокруг выделенного текста или на месте курсора. (Не поддерживается в Internet Explorer) |
indent | Добавляет отступ в строку в которой расположен курсор (или что-то выделено). В Firefox, если выделение охватывает несколько строк с разными уровнями отступа, будут сдвинуты только строки с наименьшим отступом. |
insertBrOnReturn | Добавляет тег :<br> или разбивает текущий эелемент на два блока. Не работает в Internet Explorer |
insertButton | Комманда, вставляющая в документ кнопку(<BUTTON>). |
insertHorizontalRule | Вставляет горизонтальную линию на месте курсора (удаляет выделение). |
insertHTML | Вставляет HTML текст на месте курсора (удаляет выделенный текст). Требует передачи правильной HTML строки как аргумент. (Не поддерживается в Internet Explorer) |
insertIFrame | Комманда, вставляющая в документ "плавающий" фрейм. |
insertImage | Вставляет изображение на место курсора (удаляет выделенный текст). Необходимо указывать ссылку на изображение в параметре "aValueArgument". (Internet Explorer может создавать изображения с пустым SRC) |
insertInputButton | Комманда, вставляющая в документ командную кнопку. |
insertInputCheckbox | Комманда, вставляющая в документ кнопку-"флажок". |
insertInputFileUpload | Комманда, вставляющая в документ элемент управления для отправки файла на сервер. |
insertInputHidden | Комманда, вставляющая в документ скрытое поле. |
insertInputImage | Комманда, вставляющая в документ изображение как элемент управления. |
insertInputPassword | Комманда, вставляющая в документ поле ввода пароля. |
insertInputRadio | Комманда, вставляющая в документ радиокнопку. |
insertInputReset | Комманда, вставляющая в документ кнопку сброса данных формы. |
insertInputSubmit | Комманда, вставляющая в документ кнопку отправки данных из формы на сервер. |
insertInputText | Комманда, вставляющая в документ поле ввода текста. |
insertMarquee | Комманда, вставляющая в документ прокручивающийся текст. |
insertOrderedList | Комманда, вставляющая в документ нумерованный список. |
insertOrderedList | Создает пронумерованный список из выбранного или на месте курсора. |
insertParagraph | Вставляет параграф вокруг выделения или для текущей строки. (Internet Explorer вставляет параграф в месте курсора и удалаяет выделенный текст) |
insertSelectDropdown | Комманда, вставляющая в документ выпадающий список. |
insertSelectListbox | Комманда, вставляющая в документ список. |
insertText | Вставляет простой текст в месте курсора или выделения (выделенный текст будет заменен). |
insertTextArea | Комманда, вставляющая в документ область редактирования текста. |
insertUnorderedList | Создает список из выбранного или на месте курсора. |
italic | Переключает курсив в месте курсора или выделения. (Internet Explorer использует теги <em> вместо <i> .) |
justifyCenter | Центрирует строку в которой есть выделение или установлен курсор. |
justifyFull | Выравнивает строку в которой есть выделение или установлен курсор по ширине. |
justifyLeft | Выравнивает строку в которой есть выделение или установлен курсор по левому краю. |
justifyRight | Выравнивает строку в которой есть выделение или установлен курсор по правому краю. |
liveResize | Комманда, включающая или выключающая режим мгновенного("живого") отображения размеров или местоположения элементов страницы во время изменения размеров последней. |
multipleSelection | Комманда, позволяющая или запрещающая выделение сразу нескольких элементов web-строницы. |
outdent | Добавляет выступ для строки в которой расположен курсор (или что-то выделено). |
overWrite | Комманда, переключающая режим ввода текста между вставкой и заменой. |
paste | Вставляет данные из буфера обмена в место курсора или выделения (последнее заменяется). Доступ к буферу обмена должен быть включен в файле user.js |
Комманда, открывающая диалоговое окно "Печать". | |
redo | Повтор последнего действия. (Если было отменено с помощью undo или ctrl+z) |
refresh | Комманда, перезагружающая данный документ с сервера. |
removeFormat | Очищает форматирование для выделенного. |
saveAs | Комманда, сохраняющая текущую web-страницу в файл. |
selectAll | Выделяет всё в редактируемом документе. |
strikeThrough | Переключает зачеркивание текста для выделенния или на месте курсора. |
styleWithCSS | Переключает режим стилизации HTML и CSS для генерируемой разметки. Может принимать только булевые значения true/false, т.е. true модифицирует/генерирует атрибуты стиля в разметке, false генерирует элементы форматирования. |
subscript | Переключает нижний индекс для выбранного или на месте курсора. |
superscript | Переключает верхний индекс для выбранного или на месте курсора. |
unBookmark | Комманда, удаляющая элемент закладки из текущего фрагмента выделенного текста. |
underline | Переключает подчёркивание для выбранного или на месте курсора. |
undo | Отмена последнего действия. |
unlink | Удаляет ссылку или якорь для выбранной ссылки/якоря |
unselect | Комманда, очищающая данный фрагмент выделенного текста. |