Хотя консорциум W3C никогда официально не определял свойство innerHTML как составную часть модели DOM, тем не менее это свойство узлов HTMLElement явля_ ется настолько важным, что поддерживается всеми современными броузерами. При чтении из этого свойства вы в формате HTML получаете текст, который представляет дочерние узлы элемента. При записи в это свойство броузер запус_ кает синтаксический анализатор HTML_кода для разбора строки и замещает до_ черние элементы теми, которые были получены от анализатора.
Описывать HTML_документ в виде строки с текстом в формате HTML обычно удобнее и проще, чем использовать для этих же целей последовательность вызо_ вов createElement() и appendChild(). Снова вернемся к той части примера 15.9, где создается новый элемент <table> и затем к нему добавляется строка заголовка. Благодаря свойству innerHTML этот относительно крупный фрагмент программно_ го кода можно переписать следующим образом:
Веб_броузеры по определению прекрасно справляются с анализом HTML_кода. Оказывается, что использование свойства innerHTML гораздо эффективнее, осо_ бенно при анализе больших фрагментов HTML_текста. Однако следует отметить, что операция добавления небольших фрагментов текста в свойство innerHTML с помощью оператора += обычно не отличается эффективностью, поскольку тре_ бует как сериализации, так и синтаксического анализа.
Свойство innerHML было введено компанией Microsoft в IE 4. Оно входит в квартет наиболее важных и часто используемых свойств. Остальные три свойства, outer_ HTML, innerText и outerText, описанные в конце этой главы, не поддерживаются в Firefox и родственных броузерах.
Пример: динамическое создание оглавления
В предыдущих разделах было продемонстрировано, как использовать модуль Core модели DOM API для обхода документа, выборки элементов из документа, изме_
352 Глава 15. Работа с документами
нения и добавления содержимого документа. Все эти операции собраны воедино в примере 15.11, который автоматически создает оглавление HTML_документа.
В программном коде примера определяется единственный метод maketoc() и ре_ гистрируется обработчик события onload, благодаря чему функция вызывается автоматически после загрузки документа. Метод maketoc() обходит документ в поисках тегов <h1>, <h2>, <h3>, <h4>, <h5> и <h6>, которые, как предполагается, отмечают начало разделов документа. Кроме того, метод maketoc() отыскивает элемент со значением атрибута id="toc" и строит оглавление внутри этого эле_ мента. В ходе этого процесса метод maketoc() добавляет номера разделов в заго_ ловки этих разделов, вставляет именованные якорные элементы и затем встав_ ляет в начало каждого раздела ссылку обратно на оглавление. Оглавление, гене_ рируемое функцией maketoc(), показано на рис. 15.5.
Функция maketoc() может представлять интерес для тех, кто сопровождает и ис_ правляет длинные документы, разбитые на разделы с помощью тегов <h1>, <h2> и им подобных. Оглавления очень полезны в длинных документах, но если доку_ мент редактируется часто, то бывает сложно обеспечивать синхронизацию ог_ лавления с самим документом. Программный код примера 15.11 написан в не_ навязчивом стиле: чтобы воспользоваться им, достаточно просто включить мо_ дуль в HTML_документ и создать контейнерный элемент для метода maketoc(), который и создаст оглавление документа. При желании можно с помощью CSS_ таблицы определить стиль оглавления. Вот пример:
Рис. 15.5. Динамически созданное оглавление
15.9. Пример: динамическое создание оглавления
<script src="TOC.js"></script> <!__ Загрузка функции maketoc() __> <style>
#toc {/* Следующие стили применяются к контейнерному элементу с оглавлением */
.TOCLevel2 { font_size: 12pt; margin_left: .5in; } /* Пункты второго уровня с отступом */
.TOCLevel3 { font_size: 12pt; margin_left: 1in; } /* Пункты третьего уровня */ /* с отступом */
.TOCBackLink { display: block; } /* Обратные ссылки в той же строке */
.TOCSectNum:after { content: ":"; } /* Добавлять двоеточие после номера раздела */ </style>
<body>
<div id="toc"><h1>Оглавление</h1></div> <!__ здесь находится оглавление __> <!__
... здесь находится остальная часть документа ...
__>
Далее следует программный код модуля TOC.js. Пример 15.11 достаточно длин_ ный, но хорошо прокомментирован и основан на уже знакомых вам приемах. Он заслуживает изучения как практический пример возможностей W3C DOM.
Пример 15.11. Автоматическая генерация оглавления
/**
* TOC.js: создает оглавление документа.
*
* В этом модуле определяется единственная функция maketoc(), также он
* регистрирует обработчик события onload, благодаря чему функция
* запускается автоматически сразу же после загрузки документа
* После запуска функция maketoc() сначала просматривает документ в поисках
* элемента со значением атрибута id="toc". Если такой элемент в документе
* отсутствует, maketoc() ничего не делает. Если такой элемент обнаруживается,
* maketoc() обходит документ, отыскивает все теги от <h1> до <h6>
* и создает оглавление, которое затем добавляется в элемент "toc".
* Функция maketoc() добавляет номера разделов к каждому заголовку каждого
* раздела и вставляет перед каждым заголовком обратные ссылки на оглавление
* Ссылки и якорные элементы с именами, начинающимися с префикса "TOC",
* создаются функцией maketoc(), т.е. следует избегать
* использования данного префикса в своих HTML_документах.
*
* Формат вывода пунктов оглавления может настраиваться с помощью CSS.
* Все записи принадлежат к классу "TOCEntry". Кроме того, записи также
* принадлежат классу, имя которого соответствует уровню заголовка раздела.
* Для тегов <h1> генерируются пункты с классом "TOCLevel1",
* Для тегов <h2> – пункты с классом "TOCLevel2", и т.д.
* Номера разделов вставляются в заголовки, принадлежащие классу "TOCSectNum",
* а обратные ссылки на оглавление генерируются для заголовков,
* принадлежащих классу "TOCBackLink".
354 Глава 15. Работа с документами
*
* По умолчанию сгенерированные обратные ссылки содержат текст "Contents".
* Чтобы изменить этот текст (например, с целью интернационализации),
* следует записать его в свойство maketoc.backlinkText.
**/
function maketoc() {
// Найти контейнер. В случае отсутствия такового просто завершить работу. var container = document.getElementById('toc');
if (!container) return;
// Обойти документ, добавить в массив все теги <h1>...<h6>
var sections = []; findSections(document, sections);
// Вставить якорный элемент перед контйнером, чтобы можно было
// создавать обратные ссылки на него
var anchor = document.createElement("a");
// Создать узел <a>
anchor.name
= "TOCtop";
//
Установить атрибуты
anchor.id =
"TOCtop";
//
name и id (для IE)
container.parentNode.insertBefore(anchor,
container); // Вставить перед оглавлением
// Инициализировать массив для отслеживания номеров разделов var sectionNumbers = [0,0,0,0,0,0];
// Обойти в цикле все найденные заголовки разделов
for(var s = 0; s < sections.length; s++) { var section = sections[s];
// Номер помещается в тег <span>, чтобы можно было влиять на формат вывода. var frag = document.createDocumentFragment(); // Для хранения номера и пробела