Автор: Stasyuk Eugene 112 Метки: 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');

                            }
                    });
            });
    }
}

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

Как перевести тему WordPress на другой язык перевод

Как перевести тему WordPress на другой язык

Как перевести тему WordPress на другой язык

Работая над созданием темы на WordPress мы довольно часто сталкиваемся с такими надписями как «загрузить еще, автор, метки» и т.д. Например как в моем блоге: Хорошо когда сайт на одном языке. Тогда с ними то особо делать ничего и не нужно. Но что делать когда сайт мультиязычный. Если заказчику в перспективе нет необходимости в будущем […]

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

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

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

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