Автоматическое оглавление на странице

Допу­стим, вы напи­са­ли боль­шую ста­тью. В ней мно­го раз­де­лов и заго­лов­ков — так нуж­но по смыс­лу.

Что­бы чита­тель как-то ори­ен­ти­ро­вал­ся в вашей ста­тье, вы реша­е­те сде­лать оглав­ле­ние: из него мож­но перей­ти к любо­му раз­де­лу в ста­тье, как в Вики­пе­дии.

Вы соби­ра­е­те оглав­ле­ние вруч­ную, пуб­ли­ку­е­те, а потом реша­е­те поме­нять места­ми пару раз­де­лов или доба­вить новые. Оглав­ле­ние тоже при­дёт­ся пере­де­лать. Ну уж нет!

Сего­дня напи­шем скрипт, кото­рый сам собе­рёт оглав­ле­ние для ваших эпи­че­ских лон­гри­дов.

Задача скрипта

  1. Най­ти все под­за­го­лов­ки <h2> на стра­ни­це
  2. Собрать их в одном месте
  3. Сде­лать из них ссыл­ки

Подготовка

Возь­мём стан­дарт­ный шаб­лон стра­ни­цы и запол­ним его тек­стом из нашей ста­тьи про чужой код:

    
language: HTML
<!DOCTYPE html>

<html>

 

<head>

 

  <title>Автооглавление</title>

  <meta charset="utf-8">

  <meta http-equiv="X-UA-Compatible" content="IE=edge">

  <meta name="viewport" content="width=device-width, initial-scale=1">

 

  <style type="text/css">

 

  </style>

<!-- Закрываем служебную часть страницы -->

</head>

<body>

  <h2>Ситуация </h2>

  <p>

  Вам нужно решить задачу, с которой вы ещё не сталкивались, например, вывести данные в виде красивого графика.</p>

 

  <p>

  Можно с нуля погрузиться в графическую систему языка и за 3–4 дня разобраться, как это сделать. Это полезно, если дальше вам нужно будет постоянно, каждый день рисовать новые графики. Вы освоите все возможности графической системы и в дальнейшем будете рисовать графики легко и быстро.</p>

 

  <p>

  Но если эта функция вам нужна только один раз и больше вы не планируете ничего рисовать, то это очень нерациональный ход — вы потратите много времени на то, что больше не пригодится.</p>

 

  <h2>Решение</h2>

  За 10 минут найти в интернете уже готовый код, который делает что нужно, адаптировать под свой проект и спокойно продолжить работу. Код может быть неидеальным, не очень красиво написан, но:</p>

 

  <p>

  ✔️ вы потратили в разы меньше времени;<br>

  ✔️ проект движется дальше, а не стоит на месте;<br>

  ✔️ вы примерно поняли, как это сделано, и если что — сможете повторить в другом проекте.</p>

 

  <h2>Как сделать этот подход ещё лучше</h2>

  <p>

  Выучить английский. Большинство справочников разработчика и форумов с готовыми решениями — на английском. Чтобы понять, что там написано, что делает код и для каких ситуаций он подходит, нужно знать английский хотя бы на базовом уровне (а лучше — владеть техническим английским).</p>

 

  

  <h2>Что может пойти не так</h2>

  <p>

  Бывает, что разработчик без разбора копипастит код с форумов. Он не разбирается в том, что за код он использует, а просто вставляет его в свой проект. Работает — и ладно.</p>

 

  <p>

  А может оказаться, что, например, код плохо оптимизирован и будет со страшной силой тормозить всю программу; или в коде могут быть ошибки, которые проявятся при дальнейшей эксплуатации; или на тестовых данных всё работало, а в реальности ломается.</p>

</body>

<!-- Конец всей страницы -->

</html>


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Пока нам нужен про­сто текст с заго­лов­ка­ми.

Добавляем место для оглавления

Мы будем делать оглав­ле­ние в виде мар­ки­ро­ван­но­го спис­ка с бул­ле­та­ми, но вы може­те сде­лать его каким угод­но. Глав­ное — пони­мать прин­цип рабо­ты.

Для тако­го спис­ка нам пона­до­бит­ся тег <ul>..</ul>, внут­ри кото­ро­го и будет наше оглав­ле­ние. На стар­те мы не зна­ем, что в него поло­жит скрипт, поэто­му сде­ла­ем его пустым и доба­вим в самое нача­ло стра­ни­цы:

<ul id="nav"></ul>

Что­бы из скрип­та мы смог­ли обра­тить­ся к это­му эле­мен­ту и рабо­тать с ним напря­мую, сра­зу дадим ему назва­ние — nav. Мож­но дать любое дру­гое и про­сто ука­зать это в скрип­те.

Пишем скрипт

Пер­вым делом под­клю­ча­ем jQuery — он нам помо­жет рабо­тать с эле­мен­та­ми на стра­ни­це:

<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

Сам скрипт дол­жен делать вот что:

  1. Най­ти все под­за­го­лов­ки <h2>.
  2. Доба­вить к ним id с каким-то име­нем, что­бы мож­но было пере­хо­дить к нему из оглав­ле­ния.
  3. Доба­вить новый эле­мент в оглав­ле­ние с таким же назва­ни­ем, как и под­за­го­ло­вок.
  4. Сде­лать из него внут­рен­нюю ссыл­ку, что­бы мож­но было перей­ти в нуж­ную часть ста­тьи.

Немного о внутренних ссылках

Обыч­но ссыл­ки ведут на дру­гие стра­ни­цы. Когда стра­ни­ца загру­жа­ет­ся, мы видим её верх­нюю часть и скрол­лим вниз. Инту­и­тив­но понят­но.

Но есть и такая шту­ка: с помо­щью спе­ци­аль­ной мет­ки мож­но заста­вить бра­у­зер пока­зать нам не верх стра­ни­цы, а какое-то её кон­крет­ное место. Такая мет­ка назы­ва­ет­ся яко­рем.

Что­бы якорь сра­бо­тал, нуж­но две вещи:

  1. Дать спе­ци­аль­ное имя какому-то объ­ек­ту на стра­ни­це. Для это­го исполь­зу­ют свой­ство тега id="name", где name — любое назва­ние.
  2. В адре­се стра­ни­цы в кон­це доба­вить мар­кер #name — что озна­ча­ет «доскролль до объ­ек­та с id="name"».

Полу­ча­ет­ся, что, если бра­у­зер видит в адре­се #name, он нахо­дит нуж­ный объ­ект на стра­ни­це и сра­зу мгно­вен­но доскрол­ли­ва­ет до него.

Напри­мер, нам нуж­но, что­бы стра­ни­ца сра­зу откры­лась на фор­ме опла­ты. Пишем в адре­се page.html#payment, а в самой стра­ни­це гово­рим фор­ме опла­ты: id="payment" — и всё, она про­скрол­лит­ся до нуж­но­го места. И потом мож­но скрол­лить, как нам нуж­но. Ссыл­ка долж­на выгля­деть так:

<a href="page.html#payment">Оплатить</a>

А если нуж­но пере­ки­нуть на нуж­ное место в стра­ни­це, то про­сто:

<a href="#payment">Оплатить</a>

Боевой скрипт

Теперь посмот­рим на скрипт, кото­рый дела­ет имен­но то, что нам нуж­но. Читай­те ком­мен­та­рии в коде, что­бы понять, что про­ис­хо­дит:

    
language: JavaScript
// создаём пока пустой массив, где будут жить наше оглавление

const links = [];

 

// находим все подзаголовки и добавляем им id, который состоит из слова h2- и порядкового номера этого заголовка

[...document.querySelectorAll('h2')].forEach((el, i) => 

    {

        // присваиваем id каждому элементу, добавляя к нему порядковый номер этого элемента

        el.id = `h2-${i}`;

        // отправляем в наш изначально пустой массив новый элемент с уже готовым HTML-кодом для ссылки

        links.push(`<li><a href="#h2-${i}">${el.textContent}</a></li>`);

});

// отправляем наш код в раздел nav, который отвечает за оглавление

nav.innerHTML = links.join('');


Ско­пи­ро­вать код
Код ско­пи­ро­ван

Вся магия здесь в двух момен­тах:

  1. Три точ­ки в коман­де ...document.querySelectorAll('h2') поз­во­ля­ют нам най­ти все эле­мен­ты на стра­ни­це, обо­зна­чен­ные тэгом h2 — так мы нахо­дим все под­за­го­лов­ки.
  2. Коман­да links.push(`<li><a href="#h2-${i}">${el.textContent}</a></li>`); фор­ми­ру­ет новую строч­ку оглав­ле­ния, кото­рая для пер­во­го под­за­го­лов­ка будет выгля­деть, напри­мер, вот так:

    <li><a href="#h2-1">Ситуация</a></li>

    Эта коман­да взя­ла поряд­ко­вый номер это­го под­за­го­лов­ка (нуле­вой, так как счи­та­ет­ся с нуля), доба­ви­ла его в ссыл­ку, потом взя­ла текст само­го заго­лов­ка, доба­ви­ла его в текст ссыл­ки и из все­го это­го сде­ла­ла кусок HTML-кода. Теперь, когда послед­няя коман­да доба­вит его на стра­ни­цу, бра­у­зер смо­жет его про­чи­тать и обра­бо­тать как нуж­но.

Доба­вим наш скрипт в самый конец стра­ни­цы. Теперь, если мы что-то поме­ня­ем в струк­ту­ре стра­ни­цы, доба­вим или убе­рём какие-то под­за­го­лов­ки, оглав­ле­ние само най­дёт все изме­не­ния и сде­ла­ет пра­виль­ные ссыл­ки.

👉 Если его поста­вить в нача­ло, то он не будет рабо­тать — на момент запус­ка скрип­та на стра­ни­це не успе­ет появить­ся ни одно­го под­за­го­лов­ка.


Авто­ма­ти­че­ское оглав­ле­ние точ­но повто­ря­ет все назва­ния наших под­за­го­лов­ков.

Что дальше

У нас про­стое, но не самое уни­вер­саль­ное реше­ние — скрипт не обра­ща­ет вни­ма­ния на более мел­кие под­за­го­лов­ки — <h3>, <h4> и так далее. Но, вла­дея зна­ни­я­ми из этой ста­тьи, вы смо­же­те без про­блем это испра­вить.