Search code examples
javascripthtmlimagehrefgetattribute

Vanilla JavaScript getAttribute("href") from link with image inside


I am trying to create tabs with vanilla JavaScript, each tab has an icon and a title inside the link

<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>

It should open the tab content

<div id="tab3" class="tabs-content-item">

The problem is that .getAttribute("href"); returns null when I have <img> and <h3> elements inside the link. Everything works if I change the tab to

<div class="tabs-bar-item">
    <img class="icon" src="img/school.png">
    <a href="#tab3">Instruktāžas datu aizsardzībā</a>
</div>

but I want the tab content to open when clicked anywhere on .tabs-bar-item. How can it be done in vanilla JavaScript?

Full JS code:

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 for tab content:

.tabs-content .tabs-content-item {
    display: none;
}
.tabs-content .tabs-content-item.active {
    display: block;
}

Solution

  • Element.closest searchs up the DOM to find an element matching the selector passed as argument. If Element already matches the selector, Element (the node on which closest is called) is returned.

    Hence try changing

     let anchorReference = tabClickEvent.target;
    

    to

     let anchorReference = tabClickEvent.target.closest('a');
    

    as for example in

    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>