Автор: Stasyuk Eugene 100 Метки: 06.06.2022

Что это?

На некоторых сайтах периодически можно встретить нечто подобное:

nav

Работает эта штука следующим образом:

  • Каждый пункт содержимого — это заголовок статьи h2, h3, h4 …
  • Кликая на какой-либо из этих пунктов мы перемещаемся с помощью якорной ссылки в необходимую нам область страницы.
  • Также, когда мы пролистываем страницу и в поле зрения пользователя попадает определенная область с заголовком, этот пункт навигации каким-либо образом подсвечивается давая понять где мы находимся.

Скачать готовый файл можно по этой ссылке

Как это работает?

А теперь разберем все поэтапно. Будем собирать файл скрипта по кускам.

Разметка нашей навигации будет выглядеть следующим образом:

<ul>
	<li>
		<a href="#article_title1">Title H2</a>
		<ul>
			<li>
				<a href="#article_title2">Title H3</a>
			</li>
			<li>
				<a href="#article_title3">Title H4</a>
			</li>
		</ul>
	</li>

	<li>
		<a href="#article_title4">Title H2</a>
		<ul>
			<li>
				<a href="#article_title5">Title H3</a>
			</li>
			<li>
				<a href="#article_title6">Title H4</a>
			</li>
		</ul>
	</li>
</ul>

Как видно из примера, наша навигация будет иметь вложенность.

1) Создаем переменную, в которую помещаем заголовоки контента в необходимой нам области:

const titles = document.querySelector('.post-content__content .text').querySelectorAll('h2,h3,h4');

2) Добаввляем к нашим заголовкам id:

let i = 0;
titles.forEach(title=>{
    title.setAttribute('id', `articles_title${i}`);
    i++;
});

3) Создаем объект и переменную, которые помогут нам сделать вложенность

let titlesObj = {},
        h2;

for(let i = 0; i < titles.length; i++){

    if(titles[i].classList.contains('no-active')){
        continue;
    }

    if(titles[i].tagName == 'H2'){
        titlesObj[titles[i].textContent] = {
            'id': titles[i].getAttribute('id')
        };

        if(titles[i+1] && titles[i+1].tagName != 'H2'){
            h2 = titles[i].textContent;
            titlesObj[titles[i].textContent]['titles'] = {};
        }
    }

    if(titles[i].tagName != 'H2'){
        titlesObj[h2]['titles'][titles[i].textContent] = {
            'id': titles[i].getAttribute('id')
        }
    }
}

4) Создаем структуру нашего содержимого

let navigation = '';

for(let item in titlesObj){
    let subLinks = '';

    if(titlesObj[item]['titles']){
        subLinks = subLinks + '<ul>';

        for(let sub in titlesObj[item]['titles']){
            subLinks = subLinks + `<li><a href="#${titlesObj[item]['titles'][sub]['id']}">${sub}</a></li>`;
        }

        subLinks = subLinks + '</ul>';
    }

    navigation = navigation + `<li><a href="#${titlesObj[item]['id']}">${item}</a>${subLinks}</li>`;
}

5) Добавляем разметку навигации в необходимую нам область

document.querySelector('#articles_nav ul').innerHTML = navigation;

6) Создаем и вызываем функцию которая будет:
— плавно перемещать страницу в область с заголовком при клике на пункт навигации.
— будет подсвечивать нужный пункт меню при скролле страницы.

postContentNavigation();

function postContentNavigation(){
    // 6.1) Заносим все ссылки навигации в переменную
    const smoothLinks = document.querySelectorAll('#articles_nav a');

    if(smoothLinks){

            // 6.2) Навешиваем на каждую ссылку событие клика
            for (let smoothLink of smoothLinks) {
                    smoothLink.addEventListener('click', function (e) {
                            e.preventDefault();
                            const id = smoothLink.getAttribute('href');

                            document.querySelector(id).scrollIntoView({
                                    behavior: 'smooth',
                                    block: 'start'
                            });
                    });
            };

            // 6.3) Подсвечиваем пункты меню 
            $(window).scroll(function(){
                    var $sections = $('.post-content__content h2, .post-content__content h3, .post-content__content h4');
                    $sections.each(function(i,el){
                            var top  = $(el).offset().top-50;
                            var bottom = top +$(el).height();
                            var scroll = $(window).scrollTop();
                            var id = $(el).attr('id');
                            if( scroll > top && scroll < bottom){
                                    $('li.active').removeClass('active');
                                    $('a[href="#'+id+'"]').parents('li').addClass('active');

                            }
                    });
            });
    }
}

Другие статьи

Wp Favs — менеджер плагинов для WordPress

Wp Favs — менеджер плагинов для WordPress

Wp Favs — менеджер плагинов для WordPress

Когда ты на регулярной основе создаешь шаблоны для WordPress, то сталкиваешься с одним рутинным моментом, который отнимает у тебя часть времени — загрузка и активация плагинов. Довольно успешно эту проблему решает плагин WP Favs. Вы просто создаете список плагинов, который вы регулярно используете, и потом скопом загружаете его к себе на сайт. Процесс работы с […]

DOMSubtreeModified — событие при изменении элемента action

DOMSubtreeModified — событие при изменении элемента

DOMSubtreeModified — событие при изменении элемента

Краткая предыстория Был у меня в работе сайт, в котором формы были настроены на плагине Contact Form 7. Сами же эти формы были интегрированы с Mailchimp. Задача состояла в следующем: после того, как пользователь заполнит и отправит определенную форму, сообщение должно попадать в сервис с определенным тегом (теги Mailchimp — это самый простой способ организовать […]