<style>
.uc-main-menu a.active-anchor,
.uc-main-menu a.active-anchor .tn-atom__button-text {
color: #ffffff !important;
}
.uc-main-menu a,
.uc-main-menu a .tn-atom__button-text{
transition: all 0.2s ease-in-out;
}
</style>
<script>
(function() {
'use strict';
let menuLinks = [];
let anchors = [];
let ticking = false;
let offset = 20; // Отступ от верха экрана
let currentPageUrl = '';
function init() {
currentPageUrl = window.location.pathname.replace(/\/$/, '') || '/';
findMenuContainers();
findAnchors();
setupEventListeners();
requestAnimationFrame(() => {
sortAnchorsByPosition();
setInitialActiveAnchor();
});
}
function findMenuContainers() {
const containers = document.querySelectorAll('.uc-main-menu');
if (!containers.length) return;
menuLinks = [];
containers.forEach(container => {
container.querySelectorAll('a').forEach(link => {
const href = link.getAttribute('href');
if (!href) return;
const hashIndex = href.indexOf('#');
const anchorName = hashIndex !== -1 ? href.substring(hashIndex + 1) : null;
const pathPart = hashIndex !== -1 ? href.substring(0, hashIndex) : href;
const normPath = pathPart.replace(/\/$/, '') || '/';
if (anchorName && (pathPart === '' || normPath === currentPageUrl)) {
menuLinks.push({ element: link, anchorName, type: 'anchor' });
} else if (!anchorName && normPath === currentPageUrl) {
menuLinks.push({ element: link, anchorName: null, type: 'page' });
}
});
});
}
function findAnchors() {
anchors = [];
const anchorNames = [...new Set(menuLinks
.filter(link => link.type === 'anchor')
.map(link => link.anchorName))];
anchorNames.forEach(name => {
let el = document.getElementById(name);
if (!el) el = document.querySelector(`[name="${name}"]`);
if (el) {
anchors.push({ name, element: el });
} else {
console.warn(`Якорь "${name}" не найден в DOM. Проверьте id/name секций.`);
}
});
}
function sortAnchorsByPosition() {
const scrollY = window.scrollY || window.pageYOffset;
anchors.sort((a, b) => {
const topA = a.element.getBoundingClientRect().top + scrollY;
const topB = b.element.getBoundingClientRect().top + scrollY;
return topA - topB;
});
}
function setupEventListeners() {
window.addEventListener('scroll', function() {
if (!ticking) {
requestAnimationFrame(function() {
updateActiveAnchor();
ticking = false;
});
ticking = true;
}
}, { passive: true });
window.addEventListener('resize', function() {
sortAnchorsByPosition();
updateActiveAnchor();
});
}
function setInitialActiveAnchor() {
updateActiveAnchor();
if (window.location.hash) {
const hash = window.location.hash.substring(1);
const target = document.getElementById(hash) || document.querySelector(`[name="${hash}"]`);
if (target) {
setTimeout(() => updateActiveAnchor(), 150);
}
}
}
function updateActiveAnchor() {
if (menuLinks.length === 0) {
updateMenuClasses(null);
return;
}
const scrollPosition = window.scrollY || window.pageYOffset;
let activeAnchor = null;
for (let i = 0; i < anchors.length; i++) {
const rect = anchors[i].element.getBoundingClientRect();
const absoluteTop = rect.top + scrollPosition;
if (absoluteTop > scrollPosition + offset + 5) {
break;
}
activeAnchor = anchors[i];
}
updateMenuClasses(activeAnchor);
}
function updateMenuClasses(activeAnchor) {
const activeName = activeAnchor ? activeAnchor.name : null;
menuLinks.forEach(link => {
const shouldBeActive = (activeName && link.type === 'anchor' && link.anchorName === activeName) ||
(!activeName && link.type === 'page');
const isActive = link.element.classList.contains('active-anchor');
if (shouldBeActive && !isActive) {
link.element.classList.add('active-anchor');
} else if (!shouldBeActive && isActive) {
link.element.classList.remove('active-anchor');
}
});
}
window.UCMainMenu = {
reinit: function() {
currentPageUrl = window.location.pathname.replace(/\/$/, '') || '/';
findMenuContainers();
findAnchors();
sortAnchorsByPosition();
updateActiveAnchor();
},
setOffset: function(val) { offset = val; updateActiveAnchor(); }
};
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', init);
} else {
init();
}
})();
</script>