В данной главе рассматривается объект TextRange, который используется для доступа к содержанию документа и манипулирования им. Динамический HTML определяет объектную модель, которая может манипулировать документом с помощью сценариев, аналогично текстовому редактору. Объект TextRange представляет возможности редактирования браузера и операции, которые составляют модель редактирования. Используя объект TextRange, вы можете редактировать любой текст, а также манипулировать текстом, который пользователь выделил на экране.
В данной главе рассмотрены следующие темы:
Введение в объект TextRange. В этом разделе рассматривается объект TextRange, как он представляет текстовое содержание документа и его отношения со структурой документа. Кроме того, обсуждаются также некоторые ограничения и неопределенности объекта TextRange.
Программирование объекта TextRange. В данном разделе обсуждается перемещение в документе и изменение его содержания с помощью свойств и методов объекта TextRange.
Доступ к выделенной пользователем области. В разделе показано обращение к выделенному пользователем тексту, одному из основных применений объекта TextRange. Выделенным пользователем простым текстом и HTML-текстом можно манипулировать и изменять его.
Выполнение команд. Динамический HTML представляет набор связанных с редактированием методов, которые представлены для документа и объекта TextRange. В разделе показано использование данных методов для запроса информации о документе и манипулирования внешним видом документа. Методы манипулирования документом используются для опосредованного изменения HTML и получения требуемых эффектов. Например, для создания элемента Anchor на основе произвольного текста.
Ранее мы рассматривали изменение документа путем прямого манипулирования индивидуальными элементами или таблицами стилей. Как таблицы глобальных стилей манипулируют стилем документа независимо от его структуры, так и объект TextRange манипулирует содержанием документа независимо от стиля и структуры. Данный объект предназначен для добавления внутренних и внешних свойств элементов с целью манипулирования динамическим содержанием, введенным в главе 13. Эти свойства элементов обеспечивают более надежный результат и их следует использовать в общем случае вместо объекта TextRange.
Объект TextRange обеспечивает доступ к тексту, как большому буферу символов.
<HTML>
<BODY>
<H1>Welcome</H1>
<H2>Table of Contents</H2>
<UL>
<LI>Chapter 1</LI>
<LI>Chapter 2</LI>
</UL>
</BODY>
</HTML>
На рис. 14.1 показан текст данного документа, расположенный ниже дерева анализа. Символы, принадлежащие определенному элементу в дереве, находятся в сфере влияния данного элемента. Например, элемент chapter l находится в сфере влияния первого элемента LI.
Рис. 14.1. Отношения между объектом TextRange и структурой документа
Объекты TextRange могут быть созданы только специальными элементами, которые считаются владельцами редактирования текста (text edit owner). Владелец редактирования текста является элементом, который может создать объект TextRange с помощью метода createTextRange, таким образом предоставляя доступ к основному буферу. На данный момент только два типа элементов HTML могут функционировать в качестве владельцев редактирования текста в динамическом HTML: элемент Body является владельцем редактирования текста для всех воспроизводимых элементов, а элементы ввода, такие как Input, Button и TextArea, являются владельцами редактирования текста для своего содержания. Например, вы можете создать объект TextRange для предыдущего документа путем вызова метода createTextRange объекта body:
var tr = document.body.createTextRange();
После создания объекта TextRange можно легко получить доступ к любому элементу содержания внутри объекта.
Первоначально весь текст, находящийся в области влияния владельца текста, содержится в объекте TextRange. Например, объект TextRange в предыдущем документе охватывает весь текст в элементе Body. Вы можете использовать методы объекта TextRange для изменения положения объекта с целью включения в область действия другого текста. Объект TextRange охватывает текст, над которым в данный момент производятся манипуляции или который изменяют. Сценарий может заменить охватываемый текст так же, как пользователь может выделить старый текст и набрать другой текст в текстовом редакторе. Ниже в разделе данной главы "Выполнение команд" вводятся методы манипулирования внешним видом документа, которые аналогичны выбору пользователем шрифта или изменения стиля текста в текстовом редакторе.
Объект TextRange разработан с большой степенью надежности и предназначен для автоматического приема произвольного HTML, внедряемого в документ. Когда новый текст вставляется в объект TextRange, то HTML также вставляется в документ, аналогично тому, как пользователь выбирает команду Paste (Вставить) из меню Edit (Правка) и вставляет произвольный текст. Данные операции являются мощными, но они не предназначены для предоставления разработчику возможности тщательного контроля документа. Напротив, разработчик может использовать данные операции для изменения документа на высоком уровне, не думая о конкретном коде HTML, который реализует данные модификации. Правила управления кодом HTML, которые генерируют данные операции, вероятно, будут изменены в следующей версии браузера Microsoft Internet Explorer. Поэтому объект TextRange не следует использовать, когда результат операции требует, чтобы HTML принимал определенную форму. Вместо него следует использовать внутренние и внешние свойства.
Объект TextRange не определяет текст, который он охватывает, в терминах порядковых индексов символов начала и конца текстовой области. Он определяет содержащийся в нем текст таким образом, при котором данный текст более свободно связан с положением в документе и может отражать изменения состояния документа. Например, если объект TextRange охватывает все содержание документа, а содержание расширяется или сокращается вследствие работы другого процесса, то объект TextRange автоматически отражает данное изменение и продолжает охватывать все содержание документа.
Ограничения объекта TextRange
Объект TextRange в настоящее время очень тесно связан с символами, что обусловливает неясности между объектом TextRange и структурой документа. Во многих случаях в HTML по положению одиночного символа невозможно точно определить HTML-элемент, в области влияния которого находится символ, как показано ниже:
<P>This is <B><I>bold and italic</I> text.</B></P>
В объекте TextRange данное содержание представлено как строка This is bold and italic text. Предком буквы b в текстовом буфере является элемент italic (курсив), а предком элемента italic является элемент Bold (Полужирный). Символы слова "bold" и предшествующий ему пробел не содержат элементов Bold, которые являются их прямыми предками. Используя свойство TextRange, вы не можете вставить выделение полужирным шрифтом, или курсивом перед словом "bold". Объект TextRange на данный момент основан на одиночной точке выделения, которая может находиться перед буквой b (что устанавливает полужирный курсив текста) или в пробеле после слова is (что не устанавливает выделение текста полужирным начертанием и курсивом). Объект TextRange не может вставить текст между тегами <В> и <I>.
Для вставки текста между тегами <В> и <I> используйте методы insertAdjacentText и InsertAdjacentHTML, введенные в главе 13.
Данные методы могут вставить текст перед или после любого открывающего или закрывающего тега в теле документа.
В данном разделе вводятся свойства и методы манипулирования объектом TextRange. Методы позволяют сценариям манипулировать основным текстом почти так же, как пользователь мог бы редактировать его в текстовом редакторе, выделяя текст и вводя или вставляя новый текст в документ.
Как упоминалось выше, объект TextRange создается путем вызова метода createTextRange элемента, который является владельцем редактирования текста. Подобно свойствам динамического содержания объект TextRange недоступен до тех пор, пока весь документ не будет проанализирован. В ходе анализа документа попытки создания объекта TextRange при помощи метода createTextRange будут неудачными. Поэтому перед использованием методов, которые возвращают объект TextRange, убедитесь, что документ полностью проанализирован.
Объект TextRange, возвращаемый методом createTextRange, должен быть назначен переменной. В противном случае созданный в памяти объект TextRange будет немедленно разрушен. Ниже показано, как правильно создать Объект TextRange:
var tr = document.body.createTextRange();
Так создавать объект TextRange нельзя:
document.body.createTextRange(); // Этот оператор ничего не делает.
Единственная ситуация, когда не требуется назначать новый объект TextRange переменной, возникает в случае, если последовательность операций может быть выполнена одним действием - например, если вы заменяете HTML, который представлен объектом TextRange:
// Заменяет все содержание тела HTML.
document.body.createTextRange().pasteHTML("<H1>New Document</H1>");
Свойство parentTextEdit
Все элементы имеют свойство parentTextEdit, которое ссылается на владельца редактирования текста, ответственного за содержание элемента. Использование данного свойства может обеспечить коду совместимость с будущими версиями объектной модели. В настоящее время свойства parentTextEdit для большинства элементов в документе ссылаются на элемент Body. Элементы, находящиеся внутри элемента Button, являются единственными исключениями. Владельцем редактирования текста данных элементов является элемент Button. Однако будущие версии объектной модели могут поддерживать большее количество элементов в качестве владельцев редактирования текста. При создании объекта TextRange для элемента следует использовать его свойство parentTextEdit для идентификации владельца редактирования текста, и код должен будет работать даже при смене владельца редактирования текста. Приведенный ниже код иллюстрирует данный метод:
// el представляет объект элемента в документе.
var tr;
if (!el.isTextEdit)
tr = el.parentTextEdit.createTextRange();
else
tr = el.createTextRange();
Каждый элемент в теле документа представляет свойство isTextEdit, которое указывает, является ли элемент владельцем текстового редактирования. Приведенный выше код использует элемент el для создания объекта TextRange, если el является владельцем текстового редактирования. В противном случае код использует владельца редактирования текста предка элемента el. Приведенная ниже строка определяет, что элемент Body является владельцем редактирования текста:
alert(document.body.isTextEdit); // true; элемент Body является
// владельцем редактирования текста.
Объект TextRange содержит свойства text и htmlText, которые обеспечивают доступ к форматированному и неформатированному тексту документа.
Свойство text представляет текст документа без разметки HTML. Это свойство доступно для чтения/записи и может быть использовано для замены неформатированного содержания. Свойство text сходно со свойством outerText объектов элемента тем, как оно представляет содержание документа и типами значений, которые могут быть ему присвоены.
Свойство htmlText представляет текст вместе с разметкой HTML. Данное свойство представляет HTML так же, как свойство outerHTML, но в отличие от свойства outerHTML свойство htmlText доступно только для чтения. Для назначения нового HTML объекту TextRange следует использовать метод pasteHTML. Назначение нового HTML обрабатывается отдельным методом, поскольку не является симметричным при чтении текущего HTML. Значение, которое вы вставляете в текстовую область, используя метод pasteHTML, может не совпадать со значением, которое впоследствии возвращается свойством htmlText. Объект TextRange может изменить или очистить вставляемый HTML, и код HTML может даже повлиять на содержание за границами объекта TextRange.
Метод pasteHTML разработан для вставки действительного HTML. При вызове метода pasteHTML для определенного элемента вставляемый фрагмент будет находиться внутри области действия данного элемента и должен быть действительным кодом HTML внутри данной области действия, в соответствии с определением типа документа (DTD). Браузер попытается удалить недействительный код HTML и может расширить HTML за границы, исходно установленные объектом TextRange. При возвращении метода pasteHTML объект TextRange обновляется, чтобы включить вставленный текст в свою область действия.
Сравнение свойств text и htmlText
Главное преимущество использования свойства text по сравнению с htmlText и pasteHTML заключается в обработке компонентов, представляющих угловые скобки. Когда вы присваиваете значение свойству text, это значение анализируется как неформатированный HTML, так что угловые скобки автоматически заменяются на соответствующие компоненты. Например, <is заменяется на <. При чтении свойства text компоненты возвращаются в виде буквенных значений.
При вставке нового текста в текстовую область с помощью метода pasteHTML текст анализируется как код HTML, поэтому любые угловые скобки интерпретируются как часть тегов HTML. Если необходимо вставить угловую скобку в текст, то вы должны заменить соответствующий компонент вручную. Когда вы используете свойство htmlText для извлечения текстовой области, то все угловые скобки в тексте представлены в виде компонентов. Например, <is возвращается как <.
Пробел
Свойство text объекта TextRange представляет пробел так, как он воспроизводится на экране, а не в основном документе. В большинстве случаев в HTML дополнительные пробелы игнорируются. Например, если HTML-документ использует три пробела между словами, то текст будет отображаться с одним пробелом между каждым словом. Кроме того, возвраты каретки внутри HTML-документа игнорируются. Теги блока определяют разрывы строки.
Исключением из данных правил являются элементы PRE и ХМР, в которых существующие пробелы сохраняются и поддерживаются любые пробелы, которые будут вставлены позднее.
Плавающие закрывающие теги
Нельзя закрыть элемент в документе до закрывающего тега. Предположим, что в документе находится элемент Bold:
<B>This is bold text.</B>
Если объект TextRange используется для вставки нового закрывающего тега между словами bold и text, то новый тег не станет закрывающим тегом для элемента Bold.
Метод pasteHTML не вставляет фрагмент в дерево. Фрагмент проверяется на соответствие DTD, которое определяет, что дополнительные закрывающие теги будут игнорироваться. Поэтому вставка тега не окажет влияния на текст или дерево документа.
Недействительная область действия
Некоторые HTML-элементы могут быть действительными только внутри области действия других элементов. Например, считается, что элемент TD находится в элементе TR внутри таблицы Table. В главе 7 описываются правила анализатора для обработки элементов в исходном документе, которые не находятся внутри действительной области действия. Многие правила также применимы к HTML, который вставляется с помощью объекта TextRange. Например, приведенный ниже код пытается заменить тело документа на один элемент TD:
var tr = document.body.createTextRange();
tr.pasteHTML("<TD>Cell outside any table or row</TD>");
В данном примере содержание вставляется в документ, но окружающие теги <TD> игнорируются, поскольку не определена действительная таблица. Нет гарантии, что обработка этой ошибки будет поддержана в последующих версиях динамического HTML. Поэтому для получения предсказуемых результатов следует вводить действительный фрагмент HTML.
Метод parentElelment объекта TextRange сообщает об отношениях между текстовой областью и структурой документа. Данный метод возвращает последний элемент в дереве анализа, который влияет на всю область текста. Как показано на рис. 14.1, на каждый символ в текстовой области влияет конечный узел (leaf node, узел без дочерних элементов). Когда объект TextRange представляет символ, то его метод parentElement возвращает конечный узел, влияющий на символ. Когда объект TextRange представляет область символов, то его метод parentElement является узлом, который воздействует на всю область. Когда объект TextRange сначала создается для элемента Body, то он представляет весь текст, так что его метод parentElement является обычно самим элементом Body.
Изначально объект TextRange заключает в себе весь текст, который находится в области влияния владельца редактирования текста, в котором он был создан. Например, вызов метода createTextRange элемента Body возвращает текстовую область, которая включает все содержание тела.
Набор методов объекта TextRange изменяет положение объекта TextRange для охвата различного текста. Основная архитектура объекта TextRange не связана с порядковыми индексами символов, которые он охватывает в текстовом буфере. Нельзя непосредственно манипулировать конечными точками текстовой области, назначая их новым символьным индексам. Вместо этого методы перемещения объекта TextRange изменяют положение объекта для осуществления операций с текстом. Они могут позиционировать объект TextRange для охвата всех символов, слов, предложений, владельца редактирования текста, элемента или точки на экране. Данные методы не приводят к перемещению текста по документу. Ниже перечислены методы позиционирования объекта TextRange:
Для изменения положения объекта TextRange предназначены методы setEndPoint и moveToBookniark. Метод setEndPoint дополняет метод compareEndPoints.
Эти методы обсуждаются ниже в разделах данной главы "Управление объектами TextRange" и "Манипулирование закладками".
Методы expand и collapse
Метод expand расширяет объект TextRange для полного охвата символа, слова, предложения или всего текста владельца редактирования текста, в котором он был создан. Например, если объект TextRange охватывает часть слова, вызов его метода expand с параметром word приводит к распространению метода на все слово. В случае успеха метод expand возвращает true.
Метод collapse выполняет обратную операцию, помещая открывающие и закрывающие маркеры объекта TextRange вместе в качестве точки вставки. Необязательный параметр определяет, будет ли помещена точка вставки в начале или конце текущей области. Значение по умолчанию равно true, что приводит к установке точки вставки в начало.
Метод moveToElementText
Метод moveToElement размещает объект TextRange для охвата текста, находящегося в области действия данного элемента. Несмотря на согласованность данного метода с поведением объекта TextRange нет гарантии, что присвоение значения объекту TextRange, размещенному с использованием moveToElementText, приведет к изменению только содержания элемента. Если требуется прямо изменить содержание элемента, то следует использовать внутренние и внешние свойства, введенные в главе 13.
Метод moveToElementText применяется для перемещения по документу с целью выполнения последующих манипуляций, например, анализа первого слова всех заголовков. Объект TextRange может быть легко перемещен в элемент без анализа строк кода. В следующем разделе рассматриваются некоторые методы выполнения этой задачи.
Методы move, moveStart u moveEnd
Методы move, moveStart и moveEnd перемещают объект TextRange на определенное расстояние. Методы moveStart и moveEnd изменяют положение открывающих и закрывающих маркеров объекта TextRange. Метод move перемещает открывающий маркер объекта TextRange на определенное расстояние и сжимает объект до точки вставки.
Все три метода принимают два одинаковых параметра. Первый параметр определяет необходимость перемещения слова, символа или предложения в конец текстового потока. Второй параметр определяет расстояние перемещения. Второй параметр может иметь положительное или отрицательное значение, что указывает направление перемещения: вперед или назад. Первый параметр может иметь одно из перечисленных в табл. 14.1 значений:
Таблица 14.1. Значения первого параметра методов move, moveStart и moveEnd
|
|
Единица | Определение |
|
|
character | Перемещает на определенное число символов |
word | Перемещает на определенное число слов |
sentence | Перемещает на определенное число предложений |
textedit | Перемещает на определенное число элементов редактирования текста |
|
|
|
Значение | Описание |
|
|
StartToStart | Устанавливает или сравнивает начальную позицию текущего объекта TextRange с начальной позицией объекта TextRange, определенного во втором параметре |
StartToEnd | Устанавливает или сравнивает начальную позицию текущего объекта TextRange с конечной позицией объекта TextRange, определенного во втором параметре |
EndToEnd | Устанавливает или сравнивает конечную позицию текущего объекта TextRange с конечной позицией объекта TextRange, определенного во втором параметре |
EndToStart | Устанавливает или сравнивает конечную позицию текущего объекта TextRange с начальной позицией объекта TextRange, определенного во втором параметре |
|