Assigning the style of the parent element based on the child element

Currently, I am attempting to develop a customized dropdown field and here is the code I have come up with:

const list = document.querySelector('.list');
const listItems = list.getElementsByTagName('p');

document.querySelector('#category').onclick = function() {
  // I can display the .list DOM element
  list.style.display = 'block';
}

Array.from(listItems)
  .forEach(function(listItem) {
    listItem.onclick = function() {

      // Struggling to hide the .list DOM element
      list.style.display = 'none';

      // The value of .listItem is being outputted
      console.log(listItem.getAttribute('value'));
    }
  }
);
<div class="dropdown" id="category" name="category">
  <div class="trigger">
    <p class="selected-category">Category</p>
  </div>
  <div class="list">
    <p value="">None</p>
    <p value="1">harum inventore</p>
    <p value="2">dolorem voluptatem</p>
    <p value="3">dolores consectetur</p>
    <p value="4">velit culpa</p>
    <p value="5">beatae nulla</p>
  </div>
</div>

My challenge lies in switching the display attribute of the list from block to none. Despite my efforts, this task seems unachievable even after attempting it from two different segments in the code.

Being relatively new to JavaScript prompts me to seek assistance. I believe I may have missed something crucial or taken an incorrect route, although I tried multiple remedies without success. Therefore, I apologize for any inconvenience caused in advance.

Answer №1

It seems like your code was functioning correctly, but the issue arose because both the parent and child elements had click event listeners attached to them. As a result, you were toggling the visibility of the list repeatedly.

If you're interested in learning more about event bubbling, check out this resource: https://javascript.info/bubbling-and-capturing

const list = document.querySelector('.list');
const listItems = list.getElementsByTagName('p');

// Overlapping event listener 1
document.querySelector('#category').onclick = function() {
  list.style.display = 'block';
}

Array.from(listItems)
  .forEach(function(listItem) {
    // Overlapping event listener 2
    listItem.onclick = function(event) {
      // To prevent the double event issue, stop it from bubbling up
      event.stopImmediatePropagation();
      list.style.display = 'none';
      console.log(listItem.getAttribute('data-value'));
    }
  }
);
<div class="dropdown" id="category" name="category">
  <div class="trigger">
    <p class="selected-category">Category</p>
  </div>
  <div class="list">
    <p data-value="">None</p>
    <p data-value="1">harum inventore</p>
    <p data-value="2">dolorem voluptatem</p>
    <p data-value="3">dolores consectetur</p>
    <p data-value="4">velit culpa</p>
    <p data-value="5">beatae nulla</p>
  </div>
</div>

Answer №2

Whenever you click on a child element of the parent #category, the event listener attached to the parent element is triggered. To stop the click event from propagating up to the parent, you can use the stopPropagation() method within the child elements' event listener.

Additionally, as noted by @connexo in the comments, <p> elements do not possess a value attribute. It seems like you may be referring to a <ul> element with <li> children instead.


To see an illustration of the above concept in action, review and execute the following Code Snippet:

const list = document.querySelector('.list');
  const listItems = document.querySelectorAll('.list li');

  document.querySelector('#category').onclick = function() {
    list.style.display = 'block';                     // Display the .list DOM element
  }

  Array.from(listItems)
    .forEach(function(listItem) {
      listItem.onclick = function(e) {
          e.stopPropagation(); // Prevents parent's event listener from being executed
        list.style.display = 'none';                  // Hide the .list DOM element
      }
    }
  );
  
.list {display: none; list-style: none;}
<div class="dropdown" id="category" name="category">
    <div class="trigger">
      <p class="selected-category">Category</p>
    </div>
    <ul class="list">
      <li>None</li>
      <li>harum inventore</li>
      <li>dolorem voluptatem</li>
      <li>dolores consectetur</li>
      <li>velit culpa</li>
      <li>beatae nulla</li>
    </ul>
  </div>

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

What is the best way to incorporate multiple countdown timers on a single HTML page?

I am in the process of developing an online auction site and I need to include the end time and date for each auction. To achieve this, I have created a countdown.js file with the following code: // set the date we're counting down to var target_dat ...

Having trouble with JavaScript not working when clicking an image and toggling a div?

Why isn't the onclick image and toggle div functionality working with JavaScript? I made the change from: <input type="button" id="Showdiv1" name="Showdiv1" value="Show Div 1" onclick="showDiv('div1')" /> to: <img src="https://d ...

Deploying a single node.js app on two separate servers and running them simultaneously

Is it possible to set up my game to run on both the west coast and east coast servers, while still using the same domain? In my code structure, app.js runs on the server with the home route serving as the entry point for the game. This means that users si ...

What could be the reason for the onmessage listener not handling the initial SSE event?

When a client connects to a Node Express server, it creates a new EventSource. The server sends an SSE event upon initial connection and then at a 30-second interval thereafter. Strangely, the client's onmessage handler does not respond to the initial ...

Conceal picture when clicked

My goal is to hide an image upon clicking and then show it again by clicking a specific tag. I've attempted various codes, but none have been successful. Every time I click, the image continues to add to the page. <body> <a href="#" class= ...

Navigate down to the bottom of the element located on the webpage

I'm trying to create a feature where clicking an anchor tag will smoothly scroll to a specific element on the page. Currently, I am using jquery scrollTo for this purpose. Here's the code snippet: $.scrollTo( this.hash, 1500, { easing:&apos ...

Trigger a function upon the addition of a class to a div element | Execute AnimatedNumber()

Is there a way to trigger a function when a specific div receives a certain class? I have an animated div that only appears when scrolling, and once it's visible, it gains the class "in-view". I want to execute a function every time this div has the ...

Would you like to learn how to display the value of a different component in this specific Angular 2 code and beyond

Hey there, I need your expertise to review this code and help me locate the issue causing variable "itemCount" to not display any value in about.component.html while everything works fine in home.component.html. I am attempting to only show "itemCount" in ...

Incorporating list view separators using JQuery Mobile

I recently started using the Jquery Mobile Flat UI Theme and I'm really impressed. However, I would like to enhance it by adding a separator between each listview. Here is my current listview: Can someone please advise me on which code I need to add ...

Handling Errors in Node.js with Express

To access the complete repository for this project, visit: https://github.com/austindickey/FriendFinder After downloading the directory, follow the instructions in the ReadMe to set it up on your computer. Encountering an issue where my survey.html page ...

What is the best way to implement a delay in axios requests within a loop array?

I am currently working on a project in Vue where I need to add a delay to axios requests within a loop involving an array. let promises = []; for (const item of this.itemsWithIndex) { const cmd = "od_kioskPaperUpdate"; ...

Is it possible to center content with Bootstrap?

Is there a different method to center content with empty space on either side? For instance: <div class="col-md-3"></div> <div class="col-md-6"> <div class="form-group"> .... </div> </div> <div class="col ...

What is the process of converting an Array that is nested within an Object?

I am facing compile errors while attempting to convert an Object containing an Array of Objects. Here is the initial structure: export interface CourseRaw { metaInfo: MetaInfoRaw; gameCode: number; gameText: string; images?: ImageRaw[]; // Having ...

Activate a side navigation bar in AdminLTE-3

I am using AdminLTE3 as my admin panel in Laravel, but I am facing an issue with the nav-item links not activating when clicked. Even though I have all the required assets for AdminLTE3 and used the starter.html file, the navigation items are not working p ...

Display one div and conceal all others

Currently, I am implementing a toggle effect using fadeIn and fadeOut methods upon clicking a button. The JavaScript function I have created for this purpose is as follows: function showHide(divId){ if (document.getElementById(divID).style.display == ...

How can you turn off CSS3 animations for browsers that don't support them

Upon page load, a fade-in animation is applied to the main container. Although it functions properly in most browsers, it seems to have an issue in IE(9). Is there a method to identify if the user's browser does not support CSS3 animations and disabl ...

What is the best way to transfer information to a different component using Vue router?

At the moment, I have a component that is displayed on the page. When I check the this.$router variable inside this component, I notice that the full path property is '/hello/reports?report=3849534583957' and the path property is '/hello/rep ...

What is the best way to convert a 2D PHP array into a JavaScript array?

I have encountered a problem with a PHP array setup as follows: $output = array(array(1,1,1,1),array(2,2,2,2),array(3,3,3,3)); When I encoded the array to JSON, I received this output: $output = {"1":[1,1,1,1],"2":[2,2,2,2],"3":[3,3,3,3]} My goal is to ...

Tips for preventing the use of eval when invoking various functions

Here's a snippet of code I've been using that involves the use of eval. I opted for this approach as it seemed like the most straightforward way to trigger various factory functions, each responsible for different web service calls. I'm awa ...

Optimizing Animation Effects: Tips for Improving jQuery and CSS Transitions Performance

Wouldn't it be cool to have a magic line that follows your mouse as you navigate through the header menu? Take a look at this example: It works seamlessly and smoothly. I tried implementing a similar jQuery script myself, but it's not as smoot ...