What is the best way to make sure that only one tab changes color when clicked?

I have been working on a function that changes the color of a tab to gold when clicked, which is working fine. However, I also want to toggle the active property of each tab so that it displays a nice white outline. The problem I'm facing is that the white outline remains unless the tab is clicked again. Any suggestions on how to fix this? Thank you.

This is my current code:

let timesClicked = 1;

let navItems = document.querySelectorAll('.changeColor');
navItems.forEach(item => {
  item.addEventListener("click", () => {
    timesClicked++;
    console.log(timesClicked);
    let previousItem = item;
    if (timesClicked % 2 == 0) {
      item.style.color = "#f0a500";
      item.classList.toggle('active');
      console.log(item);
    } else {
      previousItem.classList.toggle('active');
      console.log(previousItem);
    };

    navItems.forEach(otherItem => {
      if (otherItem !== item) {
        otherItem.style.color = "#1A1C20";
      };
    });

  });
})
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

<ul class="nav nav-tabs nav-fill justify-content-center mt-3" id="myTab" role="tablist">
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor active" id="mathematics-tab" data-toggle="tab" href="#Mathematics" role="tab"
      aria-controls="Mathematics" aria-selected="true">Mathematics</a>
  </li>
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor black-text-start" id="english-tab" data-toggle="tab" href="#profile" role="tab"
      aria-controls="profile" aria-selected="false">English</a>
  </li>
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor black-text-start" id="verbal-tab" data-toggle="tab" href="#contact" role="tab"
      aria-controls="contact" aria-selected="false">Verbal</a>
  </li>
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor black-text-start" id="nonverbal-tab" data-toggle="tab" href="#contact" role="tab"
      aria-controls="contact" aria-selected="false">Nonverbal</a>
  </li>
</ul>

Answer №1

After reviewing your code, I made the following adjustments to correct it:

  1. Set the first tab as the default active one before clicking.
  2. When clicking on any tab, deactivate the previous tab, and keep track of the active tab using the variable previousItem (ensure to declare this variable outside of forEach(..)).

let navItems = document.querySelectorAll('.changeColor');
let previousItem = navItems[0];

navItems.forEach(item => {
  item.addEventListener("click", () => {

    if(previousItem == item)return;

    item.style.color = "#f0a500";
    item.classList.toggle('active');

    previousItem.classList.toggle('active');
    previousItem.style.color = "#1A1C20";

    previousItem = item;
 });
})
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

<ul class="nav nav-tabs nav-fill justify-content-center mt-3" id="myTab" role="tablist">
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor active" id="mathematics-tab" data-toggle="tab" href="#Mathematics" role="tab"
      aria-controls="Mathematics" aria-selected="true" style="color:#f0a500;">Mathematics</a>
  </li>
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor black-text-start" id="english-tab" data-toggle="tab" href="#profile" role="tab"
      aria-controls="profile" aria-selected="false">English</a>
  </li>
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor black-text-start" id="verbal-tab" data-toggle="tab" href="#contact" role="tab"
      aria-controls="contact" aria-selected="false">Verbal</a>
  </li>
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor black-text-start" id="nonverbal-tab" data-toggle="tab" href="#contact" role="tab"
      aria-controls="contact" aria-selected="false">Nonverbal</a>
  </li>
</ul>

Answer №2

It's easier to simplify your code by using the querySelectorAll and forEach method.

To achieve this, remove the active class and color from all nav items and only add them to the clicked menu item using the Event.target method.

Check out the simplified code demo:

let navItems = document.querySelectorAll('.changeColor');
navItems.forEach(item => {
  item.addEventListener("click", (e) => {
    navItems.forEach(otherItem => {
      otherItem.style.color = "#1A1C20";
      otherItem.classList.remove('active');
    });
    e.target.classList.add('active');
    e.target.style.color = "#f0a500";
  });
})
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">

<ul class="nav nav-tabs nav-fill justify-content-center mt-3" id="myTab" role="tablist">
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor active" id="mathematics-tab" data-toggle="tab" href="#Mathematics" role="tab" aria-controls="Mathematics" aria-selected="true">Mathematics</a>
  </li>
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor black-text-start" id="english-tab" data-toggle="tab" href="#profile" role="tab" aria-controls="profile" aria-selected="false">English</a>
  </li>
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor black-text-start" id="verbal-tab" data-toggle="tab" href="#contact" role="tab" aria-controls="contact" aria-selected="false">Verbal</a>
  </li>
  <li class="nav-item" role="presentation">
    <a class="nav-link changeColor black-text-start" id="nonverbal-tab" data-toggle="tab" href="#contact" role="tab" aria-controls="contact" aria-selected="false">Nonverbal</a>
  </li>
</ul>

Answer №3

Here is the solution I came up with for your issue:

const changeColorItems = document.querySelectorAll('.changeColor');
function handleColorChange({ target }) {
  changeColorItems.forEach((element) => {
    element.style.color = '#1A1C20';
    element.classList.remove('active');
  });
  target.style.color = '#f0a500';
  target.classList.toggle('active');
}
changeColorItems.forEach((element) => {
  element.addEventListener('click', (e) => handleColorChange(e));
});

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Attempting to create a button that will only appear for items with a defined value for a specific variable

I am currently facing an issue with a template that needs proper population. The store locator on my website lists pharmacies and displays their relevant information (phone number, address, hours of operation) along with three buttons (view store, view fl ...

Optimizing Open Graph tags for sharing WhatsApp links

I am utilizing Open Graph tags to optimize sharing on social media platforms. The image I have specified is 1200 x 630 pixels and displays correctly on Facebook as well as Whatsapp: <meta property="og:image" content="https://emotionathlet ...

Change a Character or Word in JavaScript after it's been typed

If I were to type the word "hello" into a textarea, is there a way for me to select that specific word and modify it afterwards? For instance, let's say I typed hello without hitting the space bar; could the system recognize this word and automaticall ...

Aligning the second heading alongside pictures and a lightbox

My issue is that I am struggling to center the "See More" link directly under each title link. Currently, it is pushed to the right and I can't seem to find a solution. Any help with this problem would be greatly appreciated. I attempted using display ...

Styling with CSS or using tables: What should you choose?

Is there a way to replicate the frame=void functionality in CSS, or will I need to manually add frame=void to each table I create in the future? <table border=1 rules=all frame=void> I attempted to search for a solution online, but unfortunately, m ...

Exploring the capabilities of Google Apps Script for looping and generating output

I have two spreadsheets named rawData and processedData. The content of rawData is as follows: Status Title Options Live Title1 Option1, Option2, Option3, Option4 Live Title2 Option1, Option2, Option3, Option4, Option5 Live Title3 Option1, O ...

Guide to creating a reminder feature in NestJS

In my NestJS project, I've created a POST API to add a Date object representing the date and time for sending notifications to a mobile app. Currently, I am working on checking which reminders have been reached for all users in order to trigger remin ...

having difficulties in separating the mat-table header

It may seem like a basic question, but I'm having trouble figuring it out. I'm not sure if this requires a CSS change or something else. I'm looking to add a divider between my table header similar to the one highlighted in the screenshot be ...

Utilize LESS Bootstrap as a guide for incorporating content

I have been struggling to properly integrate Bootstrap into my LESS file. Currently, I am adding Bootstrap to my project using NPM. If I simply use the following import statement in my LESS file: @import (reference) 'node_modules/bootstrap/less/boot ...

Navigate to specific element from bootstrap navigation bar

I am in the process of creating a website for a small organization. The website is being constructed using bootstrap 4, and there is a navbar that connects to various flex-containers. I want these connections to smoothly scroll to their respective elements ...

Steps for adding a row as the penultimate row in a table

There aren't many solutions out there that don't rely on jQuery, but I'm looking to avoid it. The row content needs to be generated dynamically. Here is my flawed approach: function addRow() { let newRow = '<tr><td>B ...

Exploring TingoDB: Trouble encountered when passing global variable to insert operation

During my testing and benchmarking of several embedded databases using node.js, I have encountered an interesting issue with TingoDB. Does anyone have insight into why the following code snippet works as expected: var test = { hello:'world' }; f ...

Example of fetching Pubnub history using AngularJS

I am not a paid PubNub user. I am utilizing the example code for an Angular JS basic chat application from PubNub, and I want to access the chat history. This specific example can be found on the PubNub website. git clone https://github.com/stephenlb/an ...

Organizing table components solely using CSS

Can anyone help me center 3 spans in a list within a table? Currently, the alignment looks like this: spans not properly centered. However, I want it to appear like this: span properly centered. ul { text-align: center; list-style-position: inside; ...

Tips for properly formatting a fixed table header

I'm currently facing an issue with the sticky header style in my data table. I have created a simple Angular component along with a specific directive: sticky.directive.ts @Directive({ selector: '[sticky]' }) export class StickyDirecti ...

Enabling Multi-Row Form Submission in jQuery: Ensure Submit Button is Disabled Until Every Row Has a Checked

I am dealing with a multi-row form that contains single choice radio buttons in each row. My goal is to have the final <button> tag disabled until a radio button has been checked in each row. Although I have found a solution from a previous question ...

Guide to Establishing a Connection to WCF Service using Ionic Project and AngularJS

Greetings, I am currently experiencing an issue tasked with connecting my Ionic project to a WCF service located on another PC (running a C# Application) within the local network. I have verified that the network connection between the PCs is functioning p ...

What is the best way to cancel a Promise if it hasn't been resolved yet

Let's consider a situation where I have implemented a search function to make an HTTP call. Each call made can have varying durations, and it is crucial for the system to cancel any previous HTTP requests and only await results from the latest call. ...

What is the most efficient method for incorporating CSS styles? What are the advantages of using @

I am curious about the benefits and reasons for using @import to bring stylesheets into a pre-existing stylesheet, as opposed to simply including another... <<link rel="stylesheet" type="text/css" href="" /> in the head of the webpage? ...

Approximating Values with JavaScript in Selenium

Hi there! I've been exploring selenium IDE and encountered an issue related to asserting an approximate value. My challenge is to validate a numeric value within an element identified by its id, where the value is in numerical format with commas separ ...