How can I target specific elements to toggle the active class using Javascript?

At the moment, I have a function that highlights my navbar menu items based on which one I clicked.

However, the issue arises when there is a button inside my navbar receiving the highlight class upon clicking.

I'm unsure of how to modify the JavaScript to ensure that the button does not obtain the highlight class when clicked.

Below is the current JS implementation:

      const menu = document.querySelector('#mobile-menu');
      const menuLinks = document.querySelectorAll('.navbar__menu');

      const activeMenu = e => {
        const elems = document.querySelector('.highlight');
        const button = document.querySelector('.button');

        if (elems) {
          elems.classList.remove('highlight');
        }

        if(!button.contains(e.target)) {
          e.target.className = 'navbar__links highlight';
        }
      };

      menuLinks.forEach(link => {
          link.addEventListener('click', activeMenu);
      });

Here is the HTML code for the Navbar:

    <ul class="navbar__menu">
      <li class="navbar__item">
        <a href="#home" class="navbar__links" id="homePage">Home</a>
      </li>
      <li class="navbar__item">
        <a href="#about" class="navbar__links" id="about-us">About 
     Us</a>
      </li>
      <li class="navbar__item">
        <a href="#services" class="navbar__links" 
    id="service">Services</a>
      </li>
      <li class="navbar__btn">
        <a href="#sign-up" class=" button" id="signup">Sign Up</a>
      </li>
    </ul>

Answer №1

Check out this fully functional code that addresses all your concerns. By clicking on the logo, it will apply a highlight class to the homepage only if the window width is greater than 768 pixels - ensuring that the class is added to the homepage exclusively.

//logo event listener
logo.addEventListener('click', function() {
  if (window.innerWidth > 768) {
    const homeMenu = document.querySelector('#homePage');
    homeMenu.classList.add('highlight');
  }
});

In addition, to prevent the highlight class from being added to the signup button, you can validate whether the clicked list item's id is not 'signup' using the getAttribute() method.

// adds 'highlight' class to my menu item here - except the button
if (window.innerWidth > 768) {
  if (e.target.getAttribute('id') != 'signup') {
    e.target.classList.add('highlight');
  }
}

Take a look at the complete working demonstration:

const menu = document.querySelector('#mobile-menu');
const menuLinks = document.querySelector('.navbar__menu');
const logo = document.querySelector('#navbar__logo');

const activeMenu = e => {
  const elem = document.querySelector('.highlight');

  // adds 'highlight' class to my menu item here
  if (window.innerWidth > 768) {
    if (e.target.getAttribute('id') != 'signup') {
      e.target.classList.add('highlight');
    }
  }

  //Remove class from others when click on li
  if (elem && window.innerWidth < 768 || elem) {
    elem.classList.remove('highlight');
  }
};

//Click event on li
menuLinks.addEventListener('click', activeMenu);

//logo event listener
logo.addEventListener('click', function() {
  if (window.innerWidth > 768) {
    const homeMenu = document.querySelector('#homePage');
    homeMenu.classList.add('highlight');
  }
});


//on resize
window.addEventListener('resize', function(event) {
  const links = document.querySelectorAll('.navbar__links');
  links.forEach(function(x) {
    if (window.innerWidth < 768) {
      x.classList.remove('highlight'); //remove highlught class
    }
  })
});
.highlight {
  background: red;
}
<a href="#home" id="navbar__logo">COLOR</a>
<div class="navbar__toggle" id="mobile-menu">
  <span class="bar"></span> <span class="bar"></span>
  <span class="bar"></span>
</div>

<ul class="navbar__menu">
  <li class="navbar__item">
    <a href="#home" class="navbar__links" id="homePage">Home</a>
  </li>
  <li class="navbar__item">
    <a href="#about" class="navbar__links" id="about-us">About
      Us</a>
  </li>
  <li class="navbar__item">
    <a href="#services" class="navbar__links" id="service">Services</a>
  </li>
  <li class="navbar__btn">
    <a href="#sign-up" class="button" id="signup">Sign Up</a>
  </li>
</ul>

Answer №2

Instead of registering a click event on every item in the menu, it is better to register the event on the

<ul class="navbar__menu">
element and use the event's target property to determine which item was clicked.

If you want to remove the highlight class from the previously selected item, you can do so by using

document.querySelector('.highlight').classList.remove('highlight');
, followed by adding the class to the newly selected item.

Here is an example code snippet for this:

menuLinks.addEventListener('click', evt => {
  // Remove highlight class from previous selection
  document.querySelector('.highlight').classList.remove('highlight');

  // Add highlight class to current selection
  evt.target.classList.add('highlight');
});

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

Is there a way to duplicate a GLTF model that has been imported into the Autodesk Viewer?

I encountered an issue while trying to dynamically clone a loaded GLB model and allow the user to position it in the scene. Despite using the model.clone() method, the cloned model ends up appearing at the same position as the original, causing changes in ...

Preserve the item from the predetermined model

I'm currently developing a music website. One feature I want to incorporate is the ability for users to add songs to their favorites list. I've completed everything, but I'm unsure about how to save it. Below is the code snippet I have: mo ...

Can we prevent a component from being mounted every time it is rendered by its parent component?

Is it possible to render the Child component within the Father component without mounting it and resetting its states when the Father component is rendered? I attempted to use the useMemo hook to render the Child component, but it still mounts the compone ...

Combining values with identical keys in a PHP MySQL D3 data set

Is there a way to convert data from a MySQL database into a D3 line chart? I have the following data: [{"key":"Branch1","values":["21","1961"]},{"key":"Branch2","values":["21","1961"]},{"key":"Branch2","values":["22","20040"]}] And I want to transform i ...

Incorporating angularjs within a page loaded with jquery.load

Currently, I am in the process of developing a web application designed to cater to multi-device applications. The foundation of this project involves a framework built using nodejs, socket.io, and express which manages the distribution of views. This fra ...

CSS: Problem Arising from Line Connections Between Tree Elements

I'm currently working on connecting tree nodes with lines in a drawing. I've managed to achieve it to some extent, but there are a few issues like dangling lines that I need to fix. You can find the implementation on codepen here: https://codepe ...

Incorporating a new dropdown menu above the content of a pre-existing jQuery accordion dropdown, causing the content to shift downwards

Seeking a way to overlay a second-level dropdown menu on top of the content beneath a jQuery accordion-style dropdown. Typically, the jQuery accordion pushes down the content below, but I want the second-level dropdown to remain unaffected. Is there a solu ...

Differences in behavior of Backbone.js Ajax calls between Chrome and Firefox

I am encountering an unusual problem in Firefox. When we load a page and call Routers.initializeRouters(); an ajax request is sent to fetch the data, and the loadFormSuccessHandler function populates the response into the views. In Chrome, the Ajax reques ...

Steps for importing an external .js file into a Vue 2 component

Hello, I am currently working on vue.js 2 and I have come across a problem with the JavaScript part. I would like to include the general.js file in my posts.vue file. Can anyone provide assistance with this? Your help would be greatly appreciated :) Below ...

Tips for changing the selected value in a drop-down menu

I have developed a drop-down menu along with several text fields on my HTML page that retrieve option values from the database. The selected values are being inserted into my database table successfully. However, I am facing an issue while attempting to ed ...

"Any tips on maintaining the blue color of my dropdown link when it is selected as active

I'm struggling to keep the bootstrap accordion dropdown link blue when it's active. I've tried different methods but none seem to work. What am I missing? Here's my code: <div class="visible-sm visible-xs" id="accordion" role="t ...

The AJAX request is not triggered before the postback when using a LinkButton in ASP

I am facing an issue with running an insert statement using a button in my application. Although it is functional, I have noticed that whenever I click the button, the Page_Load function runs before the ajax statement executes. How can I ensure that the a ...

What is the quickest way to find and add together the two smallest numbers from a given array of numbers using JavaScript?

const getSumOfTwoSmallestNumbers = (numbers) => { const sortedNumbers = numbers.sort((a, b) => a - b); return sortedNumbers[0] + sortedNumbers[1]; } I encountered this challenge on Code Wars. My function to find the sum of the two smallest num ...

Can someone provide a description for a field within typedoc documentation?

Here is the code snippet: /** * Description of the class */ export class SomeClass { /** * Description of the field */ message: string; } I have tested it on the TSDoc playground and noticed that there is a summary for the class, but not for it ...

Issue with Hover behavior not being implemented on Android Webview

On my webpage, I have multiple CSS hover styles implemented using both the :hover pseudo selector and the cursor property. However, when loading this webpage in an embedded WebView on an Android device equipped with a mouse (such as Chromebooks), the CSS h ...

Methods for displaying a placeholder in a semantic-ui-vue dropdown without using the multiple attribute

When utilizing the dropdown feature in semantic-ui-vue, I have encountered an issue where the placeholder option does not function unless the multiple attribute is included. You can view my sandbox demonstration at this link. I have set up 2 dropdowns: ...

How can you securely transfer the ARRAY OBJECT from JavaScript to PHP using Ajax?

I am attempting to send a Javascript Array Object via Ajax to PHP and then use that object as a true Array on the PHP side. My current approach has not been successful in terms of utilizing the incoming object as an Array within PHP; I can only parse it as ...

Tips for fixing the AnguarJS $injector:modulerr problem (more information provided)

Lately, I've been struggling with implementing custom directives for my web application. Upon checking the JS console in Chrome, an error message pops up saying Failed to instantiate module w2l-direc due to: {1}. It appears that there may be an issue ...

The function from a different .js file cannot be located in NodeJS

I'm brand new to working with Javascript and NodeJS. This is the structure of my website's code: |source | | stylesheets | | | index.styl | | templates | | default.jade | | homepage.jade |static | | [.css generated] | | ...

Embed SQL parameter into HTML code

Every 24 hours, I have a SQL job that sends an email containing data extracted from my database tables. I store the data in : DECLARE @ReportContentBuilder table(LineSequence int identity, Line varchar(2000)) Here's how it's done : INSERT IN ...