JavaScript onclick event ceases to function after initial click

I am currently working on designing a custom selection menu using HTML, CSS, and JavaScript. The concept is simple: there is a div element styled to look like an input field that, when clicked, reveals another div containing a list of options. The user can then select an option from the menu, causing it to hide and the chosen entry to appear in the input div. However, I have encountered an issue where subsequent clicks on the input div do not reopen the menu div.

This is the HTML code I have written:

<div id="destination">
<div class="list">
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body1</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body2</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body3</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body4</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body5</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body6</p>
</div>
</body>

Here is my CSS styling:

#destination{
  margin: 10% auto;
  width: 14.15em;
  height: 2em;
  border: 1px solid black;
  box-sizing: border-box;
  background: transparent;
}

.list{
  display: none;
  width: 10em;
  height: 5em;
  overflow:scroll;
  border: 1px solid black;
  padding: .5em;
  background:white;
  position: relative;
  left: 10.5%;
  top:-105%;
}

.body{
  display: block;
  text-align: center;
  margin:0;
  padding:.25em;
}

.visible{
  display:inherit;
}

And this is the JavaScript part of the code:

// identify the input div
let destination= document.getElementById('destination');

// identify the menu div
let list= document.querySelector('.list');

// show or hide the menu div upon click event
destination.addEventListener('click',function(){
    list.classList.toggle('visible');
});

// functions for highlighting entries
function highlight(elem){
    elem.style.cssText = "background: rgba(0,0,0,0.3); transition: background .5s linear";
}
function back(elem){
    elem.style.cssText = "background: inherit; transition: background .5s linear";
}

// upon selecting an option, hide the menu div and update the input div with the selected entry
function select(elem){
  list.classList.toggle('visible');
  destination.innerHTML = elem.innerText;
  destination.style.cssText = "padding-top: .35em; padding-left: 5.75em;"
}

Despite not receiving any error messages from the browser console, I am struggling to resolve the issue with the menu not reopening after the first click on the input div.

Answer №1

For the desired outcome, follow the steps below:

  1. Check the length of childNodes in the destination div
  2. If the length is greater than 1, toggle the class of the list to 'visible'
  3. If the length is equal to 1, append the list, as it will be cleared by the innerHTML from the select method on dropdown selection

destination.addEventListener('click',function(){
  if(this.childNodes.length > 1){
       list.classList.toggle('visible'); 
  }else{
    this.append(list);<br>
  }
});

Problem: By using innerHTML when clicking on the dropdown list, you are overwriting the child nodes of the destination div and consequently removing the list. Upon a second click, the list is no longer available for display.

CodePen example - https://codepen.io/nagasai/pen/YoaxGY

Sample code here:

let destination = document.getElementById('destination');

let destination2 = document.getElementById('sub-destination');

let list = document.querySelector('.list');

destination.addEventListener('click',function(){
  if(this.childNodes.length > 1){
       list.classList.toggle('visible'); 
  }else{
    this.append(list);    
  }
});

// Hover effect + transition
function highlight(elem){
    elem.style.cssText = "background: rgba(0,0,0,0.3); transition: background .5s linear";
}
function back(elem){
    elem.style.cssText = "background: inherit; transition: background .5s linear";
}

function select(elem){
  list.classList.toggle('visible');
  destination.innerHTML = elem.innerText;
  destination.style.cssText = "padding-top: .35em; padding-left: 5.75em;"
}
#destination{
  margin: 10% auto;
  width: 14.15em;
  height: 2em;
  border: 1px solid black;
  box-sizing: border-box;
  background: transparent;
}  

.list{
  display: none;
  width: 10em;
  height: 5em;
  overflow:scroll;
  border: 1px solid black;
  padding: .5em;
  background:white;
  position: relative;
  left: 10.5%;
  top:-105%;
}

.body{
  display: block;
  text-align: center;
  margin:0;
  padding:.25em;
}

.visible{
  display:inherit;
}
<div id="destination">
  <div class="list">
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body1</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body2</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body3</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body4</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body5</p>
  <p class="body" onmouseover="highlight(this)" onmouseleave="back(this)" onclick="select(this)">Body6</p>
</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

Using AngularJS to send data from a controller to a factory

Looking to implement a basic pagination feature with data from the backend. Each page should display 10 activities. /feed/1 -> displays 0-10 /feed/2 -> displays 10-20 /feed/3 -> displays 20-30 The goal is to start at page 1 and increment the pag ...

I'm curious if there are any APIs available in both the browser and Node.js that can efficiently convert a base64 string to a utf8

const decodeBase64ToUtf8 = (encodedString) => Buffer.from(encodedString, 'base64').toString('latin1') Is there a versatile API that can handle base64 to utf8 conversion seamlessly in both Node.js and web browsers? In Node.js, you c ...

Incorporating JSON data seamlessly into a visually appealing Highcharts pie chart

It seems like I'm facing a minor issue here. Everything was working fine until... $(document).ready(function() { // Original data var data = [{ "name": "Tokyo", "y": 3.0 }, { "name": "NewYork", "y": 2.0 }, { "name": "Berlin", ...

What is preventing me from adding content to a <p> element?

I'm currently developing a ToDo list web application and I'm working on retrieving the information from 4 text boxes to create the content for each ToDo item. However, when I attempt to link the elements generated from the form, I encounter the ...

The functions that have been imported are not defined

I encountered a Error in created hook: "TypeError: _api__WEBPACK_IMPORTED_MODULE_0__.default.$_playerApi_getPlayers is not a function" issue while using Webpack through Vue CLI on my webpage. Below is the structure of my project directory: . + main.js + ...

Creating a customized navigation bar with a unique menu list underline feature using JavaScript

I recently created a customized navbar using a script to add a hover effect to the menu links. You can find the script I used here: https://github.com/shadeed/underliner. Although I was able to get it partially working, there are still some issues. The we ...

JS seems to kick in only after a couple of page refreshes

I'm facing an issue with my 3 columns that should have equal heights. I've implemented some JavaScript to achieve this, which you can see in action through the DEMO link below. <script> $(document).foundation(); </script> <scri ...

In the Vercel production environment, when building Next.js getStaticPaths with URL parameters, the slashes are represented as %

I've encountered an issue while implementing a nextjs dynamic route for my static documentation page. Everything works perfectly in my local environment, and the code compiles successfully. However, when I try to access the production URL, it doesn&ap ...

Error: The requested resource /test.html cannot be found. This issue is related to

Currently facing challenges while setting up my development environment for learning Angular.js, following the instructions in Pro Angularjs. Despite researching solutions to similar issues encountered by others, I am still unable to resolve the problems. ...

Utilizing setState within the useEffect hook can lead to the application experiencing

Why does my code result in an endless loop error? This issue is pointing to the line marked with *: function Blog() { const [blog, setBlog] = useState({}); const query = useQuery(); async function fetchBlog(query) { const data = awai ...

What is the best way to retrieve an attribute from an object dynamically using JavaScript?

Inside my object, I have the following values: obj.resposta1 obj.resposta2 obj.resposta3 obj.resposta4 How can I access each value inside a loop like this: for ( var int = 1; int < 5; int++) Thank you, Celso ...

Sending a URL through the $.post method to various websites

Trying to populate my address using JavaScript $.post('/Endereco/getEnderecos', { CardCode: dado }, function (data) { if (data) { (...) Encountering an issue: when I host my website on 'localhost', it works fine, but when host ...

Leveraging AngularJS to fetch data from two distinct JSON files

I am faced with the challenge of incorporating 2 JSON file examples into my project. The format of each file is different, so I am exploring the best approach using an angular controller to handle them effectively. These JSON files are not being fetched fr ...

Tips for building a carousel-style transition using React Router

I am looking to implement a carousel animation in my React Router. My website has pages named A, B, C, and D. When transitioning from page A to B, I want the animation to move from right to left. When going from B to A, I want it to move from left to rig ...

How can you transfer data from a jQuery function to a designated div element?

I'm struggling to transfer data from a function to a specific div, but I can't seem to make it work. I'm in the process of creating a gallery viewer and all I want is to pass the counter variable, which I use to display images, and the total ...

JavaScript interactive chart utilizing a table format

My goal is to create an engaging chart in the form of a table that informs users whether a service was operational or not on specific days of the month in a particular year. When a user clicks on a field, it should open a new URL with more detailed informa ...

What initiates the activation of a hot observable series within reactive statements?

Can someone explain to me when the mouse move observable is activated in this example from RxJS on GitHub? What exactly triggers it to start sampling the mousemove event? I initially thought that subscribing would begin the sequences for all observables i ...

What is the best method to initialize a JavaScript function only once on a website that uses AJAX

Currently, I am facing an issue with a javascript function that needs to be contained within the content element rather than in the header. This is due to a dynamic ajax reload process which only refreshes the main content area and not the header section. ...

Tips on adjusting the label size of a radar chart in chart.js

My radar chart labels are appearing skewed and messed up on mobile devices, so I decided to scale them using the following code within ComponentDidMount(): const plugins = [{ beforeDraw: function(c) { var chartHeight = c.chart.height; c ...

I'm having trouble grasping the concept of this asynchronous behavior

After reviewing the output provided, my initial expectation was for working to be displayed between the lines of begin and end. Here is the rule: Is there a possible solution to achieve this outcome without modifying the app.js file? app.js const se ...