Estoy tratando de crear pestañas con JavaScript estándar, cada pestaña tiene un ícono y un título dentro del enlace
<div class="tabs-bar-item"> <a href="#tab3"> <img class="icon" src="img/school.png"> <h3 class="title">Instruktāžas datu aizsardzībā</h3> </a> </div>Debería abrir el contenido de la pestaña.
<div id="tab3" class="tabs-content-item"> El problema es que .getAttribute("href"); devuelve nulo cuando tengo elementos <img> y <h3> dentro del enlace. Todo funciona si cambio la pestaña a
<div class="tabs-bar-item"> <img class="icon" src="img/school.png"> <a href="#tab3">Instruktāžas datu aizsardzībā</a> </div> pero quiero que el contenido de la pestaña se abra cuando se haga clic en cualquier lugar en .tabs-bar-item . ¿Cómo se puede hacer en Vanilla JavaScript?
Código JS completo:
let tabs = document.querySelectorAll('.tabs-bar .tabs-bar-item'); function tabClicks(tabClickEvent) { for (let i = 0; i < tabs.length; i++) { tabs[i].classList.remove("active"); } let clickedTab = tabClickEvent.currentTarget; clickedTab.classList.add("active"); tabClickEvent.preventDefault(); let contentPanes = document.querySelectorAll('.tabs-content-item'); for (i = 0; i < contentPanes.length; i++) { contentPanes[i].classList.remove("active"); } let anchorReference = tabClickEvent.target; let activePaneId = anchorReference.getAttribute("href"); let activePane = document.querySelector(activePaneId); activePane.classList.add("active"); } for (i = 0; i < tabs.length; i++) { tabs[i].addEventListener("click", tabClicks) }Css para el contenido de la pestaña:
.tabs-content .tabs-content-item { display: none; } .tabs-content .tabs-content-item.active { display: block; }Element.closest busca en el DOM para encontrar un elemento que coincida con el selector pasado como argumento. Si Element ya coincide con el selector, se devuelve Element (el nodo en el que se llama closest ).
Por lo tanto, intente cambiar
let anchorReference = tabClickEvent.target;a
let anchorReference = tabClickEvent.target.closest('a');como por ejemplo en
let tabs = document.querySelectorAll('.tabs-bar .tabs-bar-item'); function tabClicks(tabClickEvent) { for (let i = 0; i < tabs.length; i++) { tabs[i].classList.remove("active"); } let clickedTab = tabClickEvent.currentTarget; clickedTab.classList.add("active"); tabClickEvent.preventDefault(); let contentPanes = document.querySelectorAll('.tabs-content-item'); for (i = 0; i < contentPanes.length; i++) { contentPanes[i].classList.remove("active"); } let anchorReference = tabClickEvent.target.closest('a'); console.log( anchorReference); let activePaneId = anchorReference.getAttribute("href"); let activePane = document.querySelector(activePaneId); activePane.classList.add("active"); } for (i = 0; i < tabs.length; i++) { tabs[i].addEventListener("click", tabClicks) } .tabs-content .tabs-content-item { display: none; } .tabs-content .tabs-content-item.active { display: block; } <div class="tabs-bar"> <div class="tabs-bar-item"> <a href="#tab3"> <img class="icon" src="img/school.png"> <h3 class="title">Instruktāžas datu aizsardzībā</h3> </a> </div> </div> <div class=tabs-content> <div id="tab3" class="tabs-content-item"> content of tab3 with self contained link: <a id="here" href="#here">here</a>. Clicking "here" should not close the tab! </div> </div>En primer lugar: puede hacer esto en CSS puro con la pseudo-clase de destino , no se necesita JS.
.tabs-content .tabs-content-item { display: none; } .tabs-content .tabs-content-item:target { display: block; }En un futuro cercano, también puede diseñar el enlace de la pestaña para la pestaña actualmente abierta utilizando la pseudoclase :local-link .
En su código, tabClickEvent.currentTarget siempre se refiere al elemento DIV al que adjuntó el oyente. Ese elemento no tiene href . Hay varias formas de arreglar eso. Eliminar el DIV por completo sería un buen comienzo, luego puede adjuntar un oyente a los enlaces o crear un oyente global que verifique si se ha hecho clic en un enlace o su descendiente (usando element.closest('a') ).
De cualquier manera, implementar correctamente la navegación con JavaScript no es tan fácil como podría pensar (esta es también la razón por la cual la solución CSS pura es buena). Por ejemplo, si el usuario desea abrir el enlace en una nueva pestaña (navegador), deberá agregar un código para leer el fragmento de la página en carga y abrir la pestaña correcta sin la interacción del usuario.