У меня проблема с включением класса .active для каждого пункта меню, который я нажимаю на панели навигации моего веб-сайта (который построен на HTML, CSS, JS). Я использую файл nav.html для загрузки панели навигации на всех моих страницах с помощью этого кода:
<header id = "hero-header">
<script> AOS.init();
</script>
<div class = "logo-container">
<a href = "home.html"><img class = "logo-desktop" id = "logo-hero" src = "assets/img/logo.svg"></a>
<a href = "home.html"><img class = "logo-mobile" id = "logo-hero" src = "assets/img/mobile-logo.svg"></a>
</div>
<ul>
<li data-aos = "fade-down" data-aos-duration = "600"><a href = "home.html" class = "menu-item-desktop">Home</a></li>
<!-- <li data-aos = "fade-down" data-aos-duration = "600"><a href = "map.html" class = "">Map</a></li> -->
<div data-aos = "fade-down" data-aos-duration = "800" class = "menu-item-desktop dropdown">
<button class = "dropbtn">LifePulse ID</button>
<div class = "dropdown-content">
<a href = "before-donation.html">Before Donation</a>
<a href = "after-donation.html">After Donation</a>
<a href = "how-else-can-I-help.html" class = "">How else can I help</a>
</div>
</div>
<li data-aos = "fade-down" data-aos-duration = "1000"><a href = "team.html" class = "menu-item-desktop">Team</a></li>
<li data-aos = "fade-down" data-aos-duration = "1000"><a href = "news.html" class = "menu-item-desktop ">News</a></li>
<li data-aos = "fade-down" data-aos-duration = "1200"><a href = "partners.html" class = "menu-item-desktop ">Partners</a></li>
<li data-aos = "fade-down" data-aos-duration = "1400"><a href = "contact.html" class = "menu-item-desktop ">Contact</a></li>
<div data-aos = "fade-down" data-aos-duration = "1600" class = "search-button">
<form action = "/search">
<input type = "search" name = "q" id = "search" placeholder = "Type and click enter">
<a href = "#" id = "btn-close">
<span class = "fontawesome-close">
<i class = "fa-solid fa-times" style = "color: #ffffff;"></i>
</span>
</a>
<a href = "#" id = "btn-search">
<span class = "fontawesome-search">
<i class = "fa-solid fa-magnifying-glass" style = "color: #ffffff;"></i>
</span>
</a>
</form>
</div>
</ul>
<div class = "button-container">
<a href = "contact.html">
<div class = "magnetic">
<div class = "wrap">
<div class = "span span-1 go"></div>
<div class = "span span-2 go"></div>
<div class = "span span-3 go"></div>
<div class = "span span-4 go"></div>
<div class = "span span-1 go"></div>
<img src = "assets/img/hand.png">
</div>
</div>
</a>
</div>
</header>
<div id = "hero-bottom">
<div class = "city">Thessaloniki, GR</div>
<ul>
<a href = "https://www.instagram.com/lifepulse_gr" target = "_blank"><li><i class = "fa-brands fa-instagram " style = "color: #ffffff;"></i></li></a>
<a href = "https://www.facebook.com/lifepulsegreece" target = "_blank"><li><i class = " fa-brands fa-facebook-f social-icons fa-s" style = "color: #ffffff;"></i></li></a>
<a href = "https://www.linkedin.com/company/lifepulse-blood-donation" target = "_blank"><li><i class = "fa-brands fa-linkedin-in" style = "color: #ffffff;"></i></li></a>
</ul>
</div>Я хочу, чтобы каждый раз, когда я нажимаю на пункт меню, этот конкретный элемент переходил в активное состояние. Я попытался создать файл menu.js с помощью этого кода:
const links =document.querySelectorAll(".menu-item-desktop ");
links.forEach(btn => btn.addEventListener("click",(e)=>{
e.preventDefault();
btn.classList.add("active")
}));и добавил его внизу тега body на каждой html-странице, но это не сработало. Что мне не хватает?
Я использую файл nav.html для загрузки панели навигации на всех моих страницах. Как именно «загрузить nav.html на все ваши страницы»? Похоже, вы хотите запустить свой код после того, как это произойдет.
Что console.info(document.querySelectorAll(".menu-item-desktop").length) дает вам?
@fdomn-m возвращает 6. Кроме того, что касается вашего другого вопроса, внутри тега body на каждой имеющейся у меня html-странице я использую: <script> $(function(){ $("#nav-placeholder").load( "нав.html"); </script> с соответствующим тегом div в качестве заполнителя, и меню загружается.
6 — хорошо, если бы это было 0, код запустился бы слишком рано. Вы добавили это прямо перед const links= (то есть сделать console.info(links.length))? или вы запускали его в консоли после загрузки страницы?
@fdomn-m Я запустил его в консоли после загрузки страницы. Теперь я добавил его перед моим «constlinks=» и получил 0. Все еще получаю 6, если запустил его в консоли.
Вероятно, вам придется подождать, пока документ будет проанализирован и DOM будет завершен. См. Документацию MDN — DOMContentLoaded. Вы также можете переместить JavaScript из вашего nav.html (вызов AOS.init()) в конец файла. Поможет ли это?
Да, вы получаете 6, потому что это после запуска вашего сценария «загрузки заголовка». Сначала вы получаете 0, потому что код выполняется до загрузки заголовка — отсюда и просьба уточнить. Когда ваш код работает, верхний/нижний колонтитул не загружается. Вам необходимо переместить код обработчика событий в обратный вызов complete функции .load.
@PeterPointer К вашему сведению, ОП загружает навигацию с помощью $(function(){ $("#nav-placeholder").load("nav.html"); }); (см. комментарии)
@PanosFusu Пробовал мою версию?
@Godot Да, но, к сожалению, пункты меню не переходят в активное состояние.
@PanosFusu Извините, я делегировал полномочия не из того контейнера. Я обновил. Я не могу протестировать свой код, поскольку ни AJAX, ни localStorage не поддерживаются во фрагментах SO. Если вам действительно нужно, я могу посмеяться над чем-нибудь в jsfiddle.net.
@Godot, только если у тебя есть время, так как речь идет о небольшом обновлении на моем сайте. Я наверняка сам делаю что-то не так, и это все равно не работает. Я использую предоставленный вами код как внутри тега сценария в конце тега body, так и в другом файле (menus.js), который я импортирую на свою html-страницу. Ничего из этого не помогло, но я опять же уверен, что делаю что-то не так.
Посмотрите на мой ответ и скрипку
Спасибо вам обоим за уделенное время! Мне удалось найти решение после некоторого изучения и подсказок gpt в чате. Благодарю вас <3
Если какие-либо ответы вам помогли, не забудьте проголосовать за них.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Если вы хотите щелкнуть ссылки, которые заменяют страницу, на которой вы находитесь, на другую страницу, И чтобы элементы навигации были активны? Затем вам нужно сохранить то, что было нажато, в localStorage.
Альтернативно загрузите HTML-страницы по ссылкам, используя тот же метод .load, который вы используете для nav.html.
Если нет, используйте делегирование, потому что это более простой способ.
Вам нужно делегировать из ближайшего STATIC-контейнера - того, в который вы загружаете навигацию.
Кроме того, поскольку вы загружаете навигационное меню с помощью .load, вам нужен сценарий, который обрабатывает щелчки, чтобы НЕ находиться в этом файле, поскольку JS не будет запускаться на HTML-странице, загруженной с использованием AJAX (что и есть .load).
Этот код должен находиться на загружаемой вами странице (внешний скрипт подойдет), а не в nav.html.
Вот версия jQuery, которая загрузит делегат nav AND
https://jsfiddle.net/x6ourewL/1/
$(() => { // page loading
const activeURL = localStorage.getItem('activeURL');
const $container = $('#nav-placeholder')
.load('nav.html', function() {
// AOS.init(); // if that is needed in the nav
$links = $('.menu-item-desktop a');
console.info(activeURL, $(`[href = "${activeURL}"]`).attr('href'))
$link = activeURL ? $(`[href = "${activeURL}"]`).eq(0) : $links.eq(0);
$link.addClass('active'); // activate the first or first of found link (if that makes sense)
})
.on('click', '.menu-item-desktop a', function() { // delegation
localStorage.setItem('activeURL',$(this).attr('href')); // before the link loads the new page
});
});
Ваша проблема в том, что код обработчика событий запускается до загрузки элементов и, следовательно, не добавляет никаких событий.
У вас есть несколько вариантов:
complete обратный вызовРазмещение кода обработчика событий внутри документа load/doc.ready не будет работать, поскольку он сработает до вашей вторичной загрузки.
Как указано в комментариях, ваш код в настоящее время (я предполагаю, что код события находится в doc.ready, не имеет значения)
$(function(){
$("#nav-placeholder").load("nav.html");
const links = document.querySelectorAll(".menu-item-desktop");
links.forEach(btn => btn.addEventListener("click",(e)=>{
e.preventDefault();
btn.classList.add("active")
}));
});
Измените это, чтобы добавить код события в обратный вызов загрузки:
$("#nav-placeholder").load("nav.html", function() {
const links = document.querySelectorAll(".menu-item-desktop");
links.forEach(btn => btn.addEventListener("click",(e)=>{
e.preventDefault();
btn.classList.add("active")
}));
});
Делегирование событий будет осуществляться с использованием jquery, как вы использовали jquery для doc/ready и загрузки:
$(function(){
$("#nav-placeholder").load("nav.html");
$(document).on("click", ".menu-item-desktop", function(e) {
e.preventDefault();
$(".active").removeClass("active");
$(this).addClass("active");
});
});
Не могу не поблагодарить вас за вашу помощь и время! Подход делегирования событий в некоторой степени сработал: теперь все мои элементы переходят в активное состояние при нажатии (а когда я нажимаю на другой пункт меню, предыдущий активный элемент возвращается в состояние по умолчанию). Проблема этого кода в том, что ссылки не работают. Итак, я нажимаю на элемент, состояние меняется (СПАСИБО ЗА ЭТО <3), но я не перенаправляюсь на соответствующую страницу.
"но меня не перенаправляют на соответствующую страницу" - это потому, что вы добавили e.preventDefault, который... предотвращает дефолтную (навигацию). Удалите эту строку, и ваш код начнет перемещаться. В этот момент новая страница не будет выделена, потому что это новая страница - в этот момент обратитесь к ответу @Godot, чтобы восстановить подсветку навигации при загрузке страницы. Но это не то, что спросили, а то, что будет, когда вы исправите то, что спросили. Примечание. Ответ @Godot необходимо будет применять в сочетании с этим ответом (в обратном вызове .load).
Ребята, я очень ценю время, которое вы потратили на мою проблему, я также очень удивлен тем, как быстро вы отвечаете. Мы (фактически вы) разобрались в причине моей проблемы (изменение активного состояния и нагрузка), и я уже узнал кое-что новое. Так что спасибо вам от всего сердца.
@fdomn-m - позже я понял (из-за комментариев, опубликованных Panos), что навигация загружается в nav-placeholder - поэтому мой скрипт будет работать при делегировании из этого контейнера, без необходимости запуска в обратном вызове загрузки
Что действительно сработало в конце, так это скрипт:
$(document).ready(function() {
$("#nav-placeholder").load("nav.html", function() {
// Get current page URL
var url = window.location.pathname;
// Find the menu item that matches the current URL
$('#nav-placeholder a').each(function() {
if ($(this).attr('href') === url) {
$(this).addClass('active');
}
});
});
});на всех моих html-страницах, чуть ниже
<div id = "nav-placeholder"></div>
Пожалуйста, определите «это не сработало». Что не так с вашим текущим кодом?