[SOLVED] Switch tabs with click

Issue

This Content is from Stack Overflow. Question asked by lidxve

Hello I am trying to build a page with a sidebar and have it where I click one of the links at the top and it switches the tab and the content within it. The current formula that I have isn’t working and I get one error:

Uncaught TypeError: Cannot read properties of null (reading ‘click’)

I have provided my code below. Thanks!:

HTML:

<!DOCTYPE html>
<html lang="en" >
<head>
  <meta charset="UTF-8">
  <title>StudioPick</title>
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/meyer-reset/2.0/reset.min.css">
  <link rel="stylesheet" href="./style.css">

  

</head>
<body>
<!---Navbar--->
<header>
    <nav class="navbar navbar-expand-lg navbar-light">
      <div class="container-fluid">
        <a style="font-size: 45px; color: #A388E7;" class="navbar-brand" href="#"><strong>StudioPick</a>
          <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
            <span class="navbar-toggler-icon"></span>
          </button>
          <div class="collapse navbar-collapse" id="navbarSupportedContent">
            <ul class="navbar-nav ms-auto mb-2 mb-lg-0">
              <li class="nav-item">
                <a class="nav-link active" aria-curresnt="page" href="index.html">Home</a>
              </li>
              <li class="nav-item2">
                <div class="action">
                  <div class="profile" onclick="menuToggle();">
                    <img src="./assets/avatar.jpg" />
                  </div>
                  <div class="menu">
                    <h3 id="profile-name"><strong>User Name</strong></h3>
                    <p class="text-muted" id="userType" style="position: relative; top: -20px; right: -60px; font-size: 12px !important">Studio</p>
                    <ul>
                      <li>
                        <img src="./assets/icons/user.png" /><a href="studiodash.html">Dashboard</a>
                      </li>
                      <li>
                        <img src="./assets/icons/edit.png" /><a href="editprofile.html">Edit profile</a>
                      </li>
                      <li>
                        <img src="./assets/icons/envelope.png" /><a href="#">Inbox</a>
                      </li>
                      <li>
                        <img src="./assets/icons/settings.png" /><a href="#">Setting</a>
                      </li>
                      <li><img src="./assets/icons/question.png" /><a href="#">Help</a></li>
                      <li>
                        <img src="./assets/icons/log-out.png" /><a href="#" onclick="signOut();">Logout</a>
                      </li>
                    </ul>
                  </div>
                </div>
              </li>
            </ul>
          </div>
      </div>
    </nav>
  </header>
  <!---Navbar--->
<main class="main">
    <div class="responsive-wrapper">
        <div class="main-header">
            <h1>Settings</h1>
            <div class="search">
                <input type="text" placeholder="Search" />
                <button type="submit">
                    <i class="ph-magnifying-glass-bold"></i>
                </button>
            </div>
        </div>
        <div class="horizontal-tabs">
            <button class="tab-button" href="#" data-for-tab="1">Profile</button>
            <button class="tab-button" href="#" data-for-tab="2">My Rooms</button>
            <button class="tab-button" href="#">Session Management</button>
            <button class="tab-button" href="#">Payment History</button>
            <button class="tab-button" href="#">Edit Payment</button>
        </div>
        <div class="content-header">
            <div class="content-header-intro">
                <h2>Manage your profile</h2>
                <p>Edit your profile information such email, username, password, etc.</p>
            </div>
            
        </div>
        <div class="content" data-tab="1">
            <div class="content-main">
                <div class="card-grid">
                    
                </div>
            </div>
        </div>
        <div class="content-header">
            <div class="content-header-intro">
                <h2>Manage your studio rooms</h2>
                <p>Add, delete, and edit the room images for your studio profile.</p>
            </div>
            <div class="content-header-actions">
                <a href="#" class="button">
                    <i class="ph-faders-bold"></i>
                    <span>Filters</span>
                </a>
                <a href="#" class="button">
                    <i class="ph-plus-bold"></i>
                    <span>Add a room</span>
                </a>
            </div>
        </div>
        <div class="content" data-tab="2">
            <div class="content-panel">
                <div class="vertical-tabs">
                    <a href="#" class="active">View all</a>
                    <a href="#">Developer tools</a>
                    <a href="#">Communication</a>
                    <a href="#">Productivity</a>
                    <a href="#">Browser tools</a>
                    <a href="#">Marketplace</a>
                </div>
            </div>
            <div class="content-main">
                <div class="card-grid">
                    <article class="card">
                        <div class="card-header">
                            <div>
                                <span><img src="https://assets.codepen.io/285131/zeplin.svg" /></span>
                                <h3>Zeplin</h3>
                            </div>
                            <label class="toggle">
                                <input type="checkbox" checked>
                                <span></span>
                            </label>
                        </div>
                        <div class="card-body">
                            <p>Collaboration between designers and developers.</p>
                        </div>
                        <div class="card-footer">
                            <a href="#">View integration</a>
                        </div>
                    </article>
                    <article class="card">
                        <div class="card-header">
                            <div>
                                <span><img src="https://assets.codepen.io/285131/github.svg" /></span>
                                <h3>GitHub</h3>
                            </div>
                            <label class="toggle">
                                <input type="checkbox" checked>
                                <span></span>
                            </label>
                        </div>
                        <div class="card-body">
                            <p>Link pull requests and automate workflows.</p>
                        </div>
                        <div class="card-footer">
                            <a href="#">View integration</a>
                        </div>
                    </article>
                    <article class="card">
                        <div class="card-header">
                            <div>
                                <span><img src="https://assets.codepen.io/285131/figma.svg" /></span>
                                <h3>Figma</h3>
                            </div>
                            <label class="toggle">
                                <input type="checkbox" checked>
                                <span></span>
                            </label>
                        </div>
                        <div class="card-body">
                            <p>Embed file previews in projects.</p>
                        </div>
                        <div class="card-footer">
                            <a href="#">View integration</a>
                        </div>
                    </article>
                </div>
            </div>
        </div>
        
    </div>
</main>
<!-- partial -->
  <script src='https://unpkg.com/phosphor-icons'></script>
  <script  src="./script.js"></script>

  <script>
    function menuToggle() {
      const toggleMenu = document.querySelector(".menu");
      toggleMenu.classList.toggle("active");
    }
  </script>
<!----More Bootstrap--->
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.10.2/dist/umd/popper.min.js" integrity="sha384-7+zCNj/IqJ95wo16oMtfsKbZ9ccEh31eOz1HGyDuCQ6wgnyJNSYdrPa03rtR1zdB" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js" integrity="sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13" crossorigin="anonymous"></script>
<!----More Bootstrap--->

</body>
</html>

CSS:

@import url("https://fonts.googleapis.com/css2?family=Be+Vietnam+Pro:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap");
:root {
  --c-text-primary: #282a32;
  --c-text-secondary: #686b87;
  --c-text-action: #404089;
  --c-accent-primary: #434ce8;
  --c-border-primary: #eff1f6;
  --c-background-primary: #ffffff;
  --c-background-secondary: #fdfcff;
  --c-background-tertiary: #ecf3fe;
  --c-background-quaternary: #e9ecf4;
}

body {
  line-height: 1.5;
  min-height: 100vh;
  font-family: "Be Vietnam Pro", sans-serif;
  background-color: #E5E5E5 !important;
  color: var(--c-text-primary);
}


:focus {
  outline: 0;
}

.navbar-light {
  background-color: #ffffff;
}
.navbar-nav{
  justify-content: space-between;
}
.navbar-brand {
  font-size: 45px;
  color: #A388E7 !important;
  font-weight: bolder;
  padding-top: 0.3125rem;
  padding-bottom: 0.3125rem;
  margin-right: 1rem;
  text-decoration: none;
  white-space: nowrap;
}

.nav-item{
  color: #686868 !important;
  font-size: 20px;
  position: relative;
  right: -1675px !important;
}
.nav-item a {
  display: block;
  padding: 0.5rem 1rem;
  color: #000000;
  text-decoration: none;
  transition: color .15s ease-in-out,background-color .15s ease-in-out,border-color .15s ease-in-out;
}

#alert{
  position: relative;
  right: -3px !important;
}

.action {
  position: fixed;
  top: 20px;
  right: 30px;
}

.action .profile {
  position: relative;
  width: 60px;
  height: 60px;
  border-radius: 50%;
  overflow: hidden;
  cursor: pointer;
}

.action .profile img {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.action .menu {
  position: absolute;
  top: 120px;
  right: -10px;
  padding: 10px 20px;
  background: #fff;
  width: 200px;
  box-sizing: 0 5px 25px rgba(0, 0, 0, 0.1);
  border-radius: 15px;
  transition: 0.5s;
  visibility: hidden;
  opacity: 0;
  
}

.action .menu.active {
  top: 80px;
  visibility: visible;
  opacity: 1;
}

.action .menu::before {
  content: "";
  position: absolute;
  top: -5px;
  right: 28px;
  width: 20px;
  height: 20px;
  background: #fff;
  transform: rotate(45deg);
}

*, ::after, ::before {
  box-sizing: border-box;
}

.action .menu h3 {
  width: 100%;
  text-align: center;
  font-size: 18px;
  padding: 20px 0;
  font-weight: 500;
  color: #555;
  line-height: 1.5em;
}

.action .menu h3 span {
  font-size: 14px;
  color: #cecece;
  font-weight: 300;
}

.action .menu ul li {
  list-style: none;
  padding: 16px 0;
  border-top: 1px solid rgba(0, 0, 0, 0.05);
  display: flex;
  align-items: center;
}

.action .menu ul li img {
  max-width: 20px;
  margin-right: 10px;
  opacity: 0.5;
  transition: 0.5s;
}

.action .menu ul li:hover img {
  opacity: 1;
}

.action .menu ul li a {
  display: inline-block;
  text-decoration: none;
  color: #555;
  font-weight: 500;
  transition: 0.5s;
}

.action .menu ul li:hover a {
  color: #9370DB;
}


.responsive-wrapper {
  width: 90%;
  max-width: 1280px;
  margin-left: auto;
  margin-right: auto;
}

.button {
  font: inherit;
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 1em;
  height: 40px;
  border-radius: 8px;
  line-height: 1;
  border: 2px solid var(--c-border-primary);
  color: var(--c-text-action);
  font-size: 0.875rem;
  transition: 0.15s ease;
  background-color: var(--c-background-primary);
}
.button i {
  margin-right: 0.5rem;
  font-size: 1.25em;
}
.button span {
  font-weight: 500;
}
.button:hover, .button:focus {
  border-color: var(--c-accent-primary);
  color: var(--c-accent-primary);
}



.main {
  padding-top: 3rem;
}

.main-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
}
.main-header h1 {
  font-size: 1.75rem;
  font-weight: 600;
  line-height: 1.25;
}
@media (max-width: 550px) {
  .main-header h1 {
    margin-bottom: 1rem;
  }
}

.search {
  position: relative;
  display: flex;
  align-items: center;
  width: 100%;
  max-width: 340px;
}
.search input {
  font: inherit;
  color: inherit;
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  padding: 0 1em 0 36px;
  height: 40px;
  border-radius: 8px;
  border: 2px solid var(--c-border-primary);
  color: var(--c-text-action);
  font-size: 0.875rem;
  transition: 0.15s ease;
  width: 100%;
  line-height: 1;
}
.search input::-moz-placeholder {
  color: var(--c-text-action);
}
.search input:-ms-input-placeholder {
  color: var(--c-text-action);
}
.search input::placeholder {
  color: var(--c-text-action);
}
.search input:focus, .search input:hover {
  border-color: var(--c-accent-primary);
}
.search button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 0;
  background-color: transparent;
  position: absolute;
  left: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 1.25em;
  color: var(--c-text-action);
  padding: 0;
  height: 40px;
}

.horizontal-tabs {
  margin-top: 1.5rem;
  display: flex;
  align-items: center;
  overflow-x: auto;
}
@media (max-width: 1000px) {
  .horizontal-tabs {
    scrollbar-width: none;
    position: relative;
  }
  .horizontal-tabs::-webkit-scrollbar {
    display: none;
  }
}
.horizontal-tabs a {
  display: inline-flex;
  flex-shrink: 0;
  align-items: center;
  height: 48px;
  padding: 0 0.25rem;
  font-weight: 500;
  color: inherit;
  border-bottom: 3px solid transparent;
  text-decoration: none;
  transition: 0.15s ease;
}
.horizontal-tabs a:hover, .horizontal-tabs a:focus, .horizontal-tabs a.active {
  color: var(--c-accent-primary);
  border-bottom-color: var(--c-accent-primary);
}
.horizontal-tabs a + * {
  margin-left: 1rem;
}

.content-header {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  padding-top: 3rem;
  margin-top: -1px;
  border-top: 1px solid var(--c-border-primary);
}

.content-header-intro h2 {
  font-size: 1.25rem;
  font-weight: 600;
}
.content-header-intro p {
  color: var(--c-text-secondary);
  margin-top: 0.25rem;
  font-size: 0.875rem;
  margin-bottom: 1rem;
}

@media (min-width: 800px) {
  .content-header-actions a:first-child {
    display: none;
  }
}

.content {
  border-top: 1px solid var(--c-border-primary);
  margin-top: 2rem;
  display: none;
  align-items: flex-start;
}

.content-active {
  border-top: 1px solid var(--c-border-primary);
  margin-top: 2rem;
  display: flex;
  align-items: flex-start;
}


 

.content-panel {
  display: none;
  max-width: 280px;
  width: 25%;
  padding: 2rem 1rem 2rem 0;
  margin-right: 3rem;
}
@media (min-width: 800px) {
  .content-panel {
    display: block;
  }
}

.vertical-tabs {
  display: flex;
  flex-direction: column;
}
.vertical-tabs a {
  display: flex;
  align-items: center;
  padding: 0.75em 1em;
  background-color: transparent;
  border-radius: 8px;
  text-decoration: none;
  font-weight: 500;
  color: var(--c-text-action);
  transition: 0.15s ease;
}
.vertical-tabs a:hover, .vertical-tabs a:focus, .vertical-tabs a.active {
  background-color: var(--c-background-tertiary);
  color: var(--c-accent-primary);
}
.vertical-tabs a + * {
  margin-top: 0.25rem;
}

.content-main {
  padding-top: 2rem;
  padding-bottom: 6rem;
  flex-grow: 1;
}

.card-grid {
  display: grid;
  grid-template-columns: repeat(1, 1fr);
  -moz-column-gap: 1.5rem;
       column-gap: 1.5rem;
  row-gap: 1.5rem;
}
@media (min-width: 600px) {
  .card-grid {
    grid-template-columns: repeat(2, 1fr);
  }
}
@media (min-width: 1200px) {
  .card-grid {
    grid-template-columns: repeat(3, 1fr);
  }
}

.card {
  background-color: var(--c-background-primary);
  box-shadow: 0 3px 3px 0 rgba(0, 0, 0, 0.05), 0 5px 15px 0 rgba(0, 0, 0, 0.05);
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
}

.card-header {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  padding: 1.5rem 1.25rem 1rem 1.25rem;
}
.card-header div {
  display: flex;
  align-items: center;
}
.card-header div span {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
}
.card-header div span img {
  max-height: 100%;
}
.card-header div h3 {
  margin-left: 0.75rem;
  font-weight: 500;
}

.toggle span {
  display: block;
  width: 40px;
  height: 24px;
  border-radius: 99em;
  background-color: var(--c-background-quaternary);
  box-shadow: inset 1px 1px 1px 0 rgba(0, 0, 0, 0.05);
  position: relative;
  transition: 0.15s ease;
}
.toggle span:before {
  content: "";
  display: block;
  position: absolute;
  left: 3px;
  top: 3px;
  height: 18px;
  width: 18px;
  background-color: var(--c-background-primary);
  border-radius: 50%;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.15);
  transition: 0.15s ease;
}
.toggle input {
  clip: rect(0 0 0 0);
  -webkit-clip-path: inset(50%);
          clip-path: inset(50%);
  height: 1px;
  overflow: hidden;
  position: absolute;
  white-space: nowrap;
  width: 1px;
}
.toggle input:checked + span {
  background-color: var(--c-accent-primary);
}
.toggle input:checked + span:before {
  transform: translateX(calc(100% - 2px));
}
.toggle input:focus + span {
  box-shadow: 0 0 0 4px var(--c-background-tertiary);
}

.card-body {
  padding: 1rem 1.25rem;
  font-size: 0.875rem;
}

.card-footer {
  margin-top: auto;
  padding: 1rem 1.25rem;
  display: flex;
  align-items: center;
  justify-content: flex-end;
  border-top: 1px solid rgba(0,0,0,.125);
}
.card-footer a {
  color: var(--c-text-action);
  text-decoration: none;
  font-weight: 500;
  font-size: 0.875rem;
}

html::-webkit-scrollbar {
  width: 12px;
}
html::-webkit-scrollbar-thumb {
  background-color: var(--c-text-primary);
  border: 4px solid var(--c-background-primary);
  border-radius: 99em;
}

JS:

function switchTabs(){
    document.querySelectorAll(".tab-button").forEach(link => {
        link.addEventListener("click", () => {
            const menuBar = link.parentElement;
            const tabsContainer = menuBar.parentElement;
            const tabNumber = link.dataset.forTab;
            const tabToActivate = tabsContainer.querySelector(`.content[data-tab="${tabNumber}"]`);

            menuBar.querySelector(".tab-button").forEach(link => {
                link.classList.remove("tabs-button-active");
            })

            tabsContainer.querySelector(".content").forEach(tab => {
                tab.classList.remove("content-active");
            })

            link.classList.add(".tab-button-active");
            tabToActivate.classList.add(".content-active");
        });
    });
}

document.addEventListener("DOMContentLoaded", () => {
    switchTabs();

    document.querySelectorAll(".content").forEach(tabsContainer => {
        tabsContainer.querySelector(".horizontal-tabs .tab-button").click();
    })
});



Solution

Error here:

document.querySelectorAll(".content").forEach(tabsContainer => {
  console.log(tabsContainer);
  tabsContainer.querySelector(".horizontal-tabs .tab-button").click();
})

There’s no horizontal-tabs class in your content class.

So, when you use tabsContainer.querySelector(".horizontal-tabs .tab-button") you got a null element.
Obviously, you call the click function on null element caught an error.

If you don’t sure what elements you select, just print it on the console.


This Question was asked in StackOverflow by lidxve and Answered by Kurt It is licensed under the terms of CC BY-SA 2.5. - CC BY-SA 3.0. - CC BY-SA 4.0.

people found this article helpful. What about you?