JavaScript. Подробное руководство, 6-е издание, стр. 216
<b> // Отыскать все элементы заголовков разделов </b><b> var headings;</b><b> if (document.querySelectorAll) // Возможно есть более простой путь?</b><b> headings = document.querySelectorAll(”h1,h2,h3.h4, h5. h6”);</b><b> else // Иначе отыскать заголовки более сложным способом</b><b> headings = findHeadings(document.body, []);</b><b> // Выполняет рекурсивный обход тела документа в поисках заголовков </b><b> function findHeadings(root, sects) {</b><b> for(var с = root.firstChild; c != null; c = c.nextSibling) {</b><b> if (c.nodeType !== 1) continue;</b><b> if (c.tagName.length == 2 && c.tagName.charAt(O) == "H")</b><b> sects.push(c);</b><b> else</b><b> findHeadings(c, sects);</b><b> }</b><b> return sects;</b><b> }</b><b> // Инициализировать массив, хранящий номера разделов, </b><b> var sectionNumbers = [0,0,0,0,0,0];</b><b> // Выполнить цикл по найденным элементам заголовков.</b><b> for(var h = 0; h < headings.length; h++) {</b><b> var heading = headings[h];</b><b> // Пропустить заголовки, находящиеся в контейнере оглавления,</b><b> if (heading.parentNode == toc) continue;</b><b> // Определить уровень заголовка.</b><b> var level = parseInt(heading.tagName.charAt(1));</b><b> if (isNaN(level) || level < 1 || level > 6) continue;</b><b> // Увеличить номер раздела для этого уровня и установить</b><b> // номера разделов более низкого уровня равными нулю.</b><b> sectionNumbers[level-1]++;</b><b> for(var і = level; і < 6; і++) sectionNumbers[i] = 0;</b><b> // Объединить номера разделов всех уровней,</b><b> // чтобы получился номер вида 2.3.1.</b><b> var sectionNumber = sectionNumbers.slice(0,level).join(".")</b><b> // Добавить номер раздела в заголовок. Номер помещается в элемент <span>,</b><b> // чтобы его можно было стилизовать с помощью CSS.</b><b> var span = document.createElement("span");</b><b> span.className = "TOCSectNum";</b><b> span.innerHTML = sectionNumber;</b><b> heading.insertBefore(span, heading.firstChild);</b><b> // Обернуть заголовок якорным элементом, чтобы можно было</b><b> // сконструировать ссылку на него.</b><b> var anchor = document.сreateElement("а");</b><b> anchor.name = "TOC"+sectionNumber;</b><b> heading.parentNode.insertBefore(anchor, heading);</b><b> anchor.appendChild(heading);</b><b> // Создать ссылку на этот раздел,</b><b> var link = document.createElement("а");</b><b> link.href = "#T0C" + sectionNumber; // Адрес назначения ссылки </b><b> link.innerHTML = heading.innerHTML; // Текст ссылки совпадает</b><b> // с текстом заголовка</b><b> // Поместить ссылку в элемент div, чтобы обеспечить возможность</b><b> // стилизации в зависимости от уровня.</b><b> var entry = document.сreateElement("div");</b><b> entry.className = "TOCEntry TOCLevel" + level;</b><b> entry.appendChild(link);</b><b> // И добавить элемент div в контейнер оглавления, </b><b> toc.appendChild(entry);</b><b> }</b><b>});</b>15.8. Геометрия документа и элементов и прокрутка
До сих пор в этой главе мы рассматривали документы как некие абстрактные деревья элементов и текстовых узлов. Но когда броузер отображает документ в своем окне, он создает визуальное представление документа, в котором каждый элемент имеет определенную позицию и размеры. Часто веб-приложения могут интерпретировать документы как деревья элементов и никак не заботиться о том, как эти элементы отображаются на экране. Однако иногда бывает необходимо определить точные геометрические характеристики элемента. Например, в главе 16 мы увидим, что элемент можно поместить в определенную позицию с помощью CSS. Если вам потребуется использовать CSS для динамического позиционирования элемента (такого как всплывающая подсказка или сноска) рядом с элементом, который позиционируется броузером, вам необходимо иметь возможность определять положение этого элемента.