Using JavaScript to delete a class from an HTML element

For the past 48 hours, I've been grappling with the challenge of removing an added class from an Element. Despite scouring the internet for a solution, I haven't been able to find one.

I have successfully added a class to the navigation to display the submenu, which works perfectly fine.

However, when attempting to hide the menu upon a user click anywhere on the window, the code to remove the class fails to work. I am solely using Vanilla JS without relying on jquery as I aim to master JS independently first.

Your assistance would be greatly appreciated as I have been unable to find a resolution online!

https://jsfiddle.net/dx6ofnvs/4/

HTML

 <nav> 
  <div class="nav__navigation">
    <ul>
      
      <li id="services__btn"> <a href="#"> Services</a></li>
        <div class="services__dropdown__container">
          <ul id="services__dropdown" class="dropdown">
              <li> <a href="#"> Link One</a></li>
              <li> <a href="#"> Link Two</a></li>
              <li> <a href="#"> Link Three</a></li>
              <li> <a href="#"> Link Four</a></li>
           
          </ul> 
        </div>
      
   
    
    </ul>
  </div>
  
  <div class="burger">
    <div class="line1"></div>
    <div class="line2"></div>
    <div class="line3"></div>
  </div>

</nav>

CSS


const burger = document.querySelector(".burger");
const nav = document.querySelector(".nav__navigation");
const navLinks = document.querySelectorAll(".nav__navigation li");
const servicesBtn = document.querySelector("#services__btn");
const servicesDropdown = document.querySelector("#services__dropdown");
const servicesDropdownContainer = document.querySelector("#services__dropdown__container")
const html = document.querySelector("html")

///// Open Mobile Menu

burger.addEventListener("click", (navSlide));

function navSlide() {
    nav.classList.toggle("nav-active");
}



///// Expand Dropdown Desktop View
 servicesBtn.addEventListener("click", (e) => {
    servicesDropdown.classList.add("dropdown--active");    
}) 



window.addEventListener("click", (e) => {      
    if(e.target != servicesDropdown) {

/// The issue appears to lie within this particular code snippet where it removes the class immediately after being displayed.

        servicesDropdown.classList.remove("dropdown--active")
        console.log('clicked');        
    }    
})


Answer №1

Instead of targeting the button in the window function, you should be targeting the link. Make sure to check for the link instead. I have updated your fiddle with this modification for reference.

    <li id="services__btn"> <a class="button" href="#"> Leistungen</a></li>

...

window.addEventListener("click", (e) => {
    let button = document.querySelector(".button");
        if(e.target !== button && servicesDropdown.classList.contains("dropdown--active")) {
            servicesDropdown.classList.remove("dropdown--active")
            console.log('clicked');        
        }
        console.log('e', e.target);
})

Updated Fiddle Link

Answer №2

If you're dealing with a situation like this, there's a handy (DOM) function called contains that can come to the rescue. Here's how you can put it into action:

const burger = document.querySelector(".burger");
const nav = document.querySelector(".nav__navigation");
const navLinks = document.querySelectorAll(".nav__navigation li");
const servicesBtn = document.querySelector("#services__btn");
const servicesDropdown = document.querySelector("#services__dropdown");
const servicesDropdownContainer = document.querySelector(".services__dropdown__container");
const html = document.querySelector("html");

///// Open Mobile Menu

burger.addEventListener("click", navSlide);

function navSlide() {
    nav.classList.toggle("nav-active");
}

///// Open Dropdown Desktop Width
servicesBtn.addEventListener("click", (e) => {
    servicesDropdown.classList.toggle("dropdown--active");    
}); 

document.addEventListener("click", (e) => {
    if(!servicesDropdownContainer.parentNode.contains(e.target) && servicesDropdown.classList.contains("dropdown--active")) {
        servicesDropdown.classList.remove("dropdown--active");
        console.log('clicked');        
    }    
});

Also, keep in mind that services__dropdown__container is a class and not an id.

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

Store JWT as a cookie in Vue JavaScript and ensure it is successfully saved before proceeding

Upon logging in, my page sends the login and password information to the backend, receives a jwt token in return, saves it to the cookies, and redirects to /home. However, there seems to be an issue with the authentication check on the /home route. When c ...

Send a file from a form using Gatsby to getform.io using the axios library

I am facing an issue with my getform.io form where the file is not getting uploaded properly. The file appears as [] and the files tab remains empty. Upon checking the network tab, I noticed that my request payload includes {email: "[email protec ...

Include the providers after declaring the AppModule

When it comes to Angular 2+, providers are typically registered in the following manner: // Using the @NgModule decorator and its metadata @NgModule({ declarations: [...], imports: [...], providers: [<PROVIDERS GO HERE>], bootstrap: [...] }) ...

Vue automatically populates an empty array with an Observer object

I have been attempting to create an empty array in the data and then fetch a JSON from the server to populate it. The issue I am encountering is that the array consistently includes an extra Observer object, so when I log it, I see: empty items array: ...

Why is it that the .forEach() function has the ability to alter the Vuex state?

After extracting two sets of balances from my vuex state, I decided to merge them into a new array of entries. However, an error is thrown when I try to loop through my copies of the vuex state. Am I missing something? It seems that the issue lies in the ...

The use of ExpressJs res.sendFile is not effective following the implementation of middleware

Currently, my focus is on mastering JWT and its implementation in Node.js with Express. I've developed a middleware that aims to authenticate users using a token: app.use(function(req, res, next) { if(req.headers.cookie) { var authentication = req.h ...

Why are the links in the navgoco slide menu failing to function properly?

I utilized a demo from jQueryRain to create a collapsible menu using jQuery. However, after completion, I discovered that none of the links were functioning properly. Upon visiting the documentation page, I noticed that many users were encountering the sam ...

The text becomes distorted and unreadable after the function is applied. It is impossible to decipher the message

There is a function called getResourceText(''), which takes a key as an argument. This function provides a translation of the requested text when it is called. setFilterName = (isFilterChanged, buttonId, filterName) => { switch (filterName ...

Utilizing asynchronous methods within setup() in @vue-composition

<script lang="ts"> import { createComponent } from "@vue/composition-api"; import { SplashPage } from "../../lib/vue-viewmodels"; export default createComponent({ async setup(props, context) { await SplashPage.init(2000, context.root.$router, ...

What is the best way to conceal a callback form once it has been successfully submitted?

In my callback form, everything seems to be functioning properly. However, there is a slight issue when the client hits the submit button multiple times. Each time they do so, a notification saying "Your request sent successfully" pops up next to the butto ...

Invalid function call detected, transitioning from Reactjs to Nextjs

After spending some time away from the ReactJS world, I decided to make a comeback and try my hand at NextJS. Unfortunately, I ran into an issue with an Invalid Hook Call. I'm in the process of transitioning my ReactJS project to NextJS. To illustrat ...

Show an HTML image encoded in base64 from its origin

Is there a way to embed a base64 image in HTML without having to paste the entire code directly into the file? I'm looking for a more efficient method. For example: <div> <p>Image sourced from an online repository</p> <img src=" ...

Changing the URL parameters to accommodate a specific query

Currently, I have set up the route as follows: app.get("/employees", (req, res) => { data.getAllEmployees().then((data) => { res.json(data); }).catch(function(err) { console.log("An error was encountered: " + err); }); }) ...

How can I quickly send a flash logout notification through Express or verify if a redirection has occurred

Hey everyone, I'm currently dealing with an issue in my server.js setup where I'm trying to display the message "logged out successfully" on the /login page when a user logs out. The problem stems from using multiple middleware and feeling overwh ...

Tips for successfully implementing Typeahead with Bloodhound and a JSON response

Looking for guidance on integrating typeahead.js with bloodhound.js to leverage my JSON data structure. My goal is to implement a type-ahead feature utilizing a preloaded JSON object that remains accessible. Here's the breakdown: The Data/All URL res ...

Using AngularJS to show/hide elements within a colgroup tag

Looking to create a dynamic table allowing users to hide certain columns. Wondering if it's possible to use ng-show with colgroup or col tags instead of adding ngshow to each cell individually. Struggling to make it work... <colgroup ng-repeat="mt ...

Store the response token from a Request.post in a variable

To complete a URL, I only need to extract the token provided in the API response. The response body must be saved in a variable for later use. I am currently using Protractor for automated testing, and as part of this process, I need to consume an API tha ...

The icon is not being displayed when the onHover event on the Material UI component is triggered

I am currently working on adding a delete icon to a Material UI MenuItem component. I've created a state field within the component's state called isHovering, which is initially set to false. The goal is to display the delete icon when hovering o ...

Attempting to retrieve an object's attribute

Hey! I have a question regarding the screenshot in this link: I'm trying to access the user object with the property team. So far, I've attempted using data.Object, but it returns an undefined output. I also tried using data.user but that resul ...

Create a personalized Command Line Interface for the installation of npm dependencies

I am looking to develop a Node CLI tool that can generate new projects utilizing Node, Typescript, Jest, Express, and TSLint. The goal is for this CLI to create a project folder, install dependencies, and execute the necessary commands such as npm i, tsc - ...