Display a close button for every individual item and use JavaScript to conceal the current item

I have a list that contains input fields along with delete link elements. I want to display the delete link element when the user hovers over the respective input field. Additionally, clicking on the close button (X) should hide the entire list item (li) from the list.

Currently, I am using vanilla JavaScript to achieve this functionality, but I have encountered an issue. The code I have written only shows the first close button, regardless of which field I hover over.

Custom HTML

<ul class="social-links-list">
  <li class="social-link">
    <input type="text" name="" id="" placeholder="http://facebook.com/id">
    <span class="delete-link" onclick=''>X</span>
  </li>
    <li class="social-link">
    <input type="text" name="" id="" placeholder="http://facebook.com/id">
    <span class="delete-link">X</span>
  </li>
    <li class="social-link">
    <input type="text" name="" id="" placeholder="http://facebook.com/id">
    <span class="delete-link">X</span>
  </li>
</ul>

Styling with CSS

ul {
  list-style: none;
}

input[type='text'] {
  height: 1rem;
  padding: 0.5rem;
  margin-bottom: 1rem;
  border-radius: 3px;
  border: 1px solid #ccc;
}

.delete-link {
  color: red;
  opacity: 0;
  cursor: pointer;
}

JavaScript Approach

var socialField = document.querySelectorAll('.social-link');

socialField.forEach(function(el) {
    el.addEventListener('mouseover', function(){
        closeBtn.style.opacity = 1;
    });
      el.addEventListener('mouseout', function(){
        closeBtn.style.opacity = 0;
    });
    var closeBtn = document.querySelector('.social-link .delete-link');

    for (i = 0; i < closeBtn.length; i++) {
      closeBtn[i].addEventListener("click", function() {
        this.parentElement.style.display = 'none';
      });
    }
});

For a live example, you can check this JSFiddle.

Answer №1

Almost there.


To make it easier to manage, you can store your .delete-link element as a variable (closeBtn) and then add a click event listener to it:

var socialField = document.querySelectorAll('.social-link');

socialField.forEach(function(el) {
  var closeBtn = el.querySelector('.delete-link');
  
  el.addEventListener('mouseover', function() {    
    closeBtn.style.opacity = 1;
  });

  el.addEventListener('mouseout', function() {
    closeBtn.style.opacity = 0;
  });
  
  closeBtn.addEventListener('click', function() {
    closeBtn.parentElement.style.display = 'none';
  });
});
ul {
  list-style: none;
}

input[type='text'] {
  height: 1rem;
  padding: 0.5rem;
  margin-bottom: 1rem;
  border-radius: 3px;
  border: 1px solid #ccc;
}

.delete-link {
  color: red;
  opacity: 0;
  cursor: pointer;
}
<ul class="social-links-list">
  <li class="social-link">
    <input type="text" name="" id="" placeholder="http://facebook.com/id-1">
    <span class="delete-link">X</span>
  </li>
  <li class="social-link">
    <input type="text" name="" id="" placeholder="http://facebook.com/id-2">
    <span class="delete-link">X</span>
  </li>
  <li class="social-link">
    <input type="text" name="" id="" placeholder="http://facebook.com/id-3">
    <span class="delete-link">X</span>
  </li>
</ul>

I have updated the placeholders of the input fields to indicate the correctly modified elements.

Answer №2

The issue lies with your closeBtn selector. The current implementation does not target the child element within your parent element. Instead, it selects the first matching item, not all items as intended.

To resolve this, create a separate variable specifically for the span child.

var closeBtn = el.querySelectorAll(".delete-link")[0];

This will explicitly target the .delete-link span within the current element. Once this is done, the for-loop can be removed as it is redundant.

var socialField = document.querySelectorAll('.social-link');

socialField.forEach(function(el) {
    var closeBtn = el.querySelectorAll(".delete-link")[0];

    el.addEventListener('mouseover', function(){
        closeBtn.style.opacity = 1;
    });
    el.addEventListener('mouseout', function(){
        closeBtn.style.opacity = 0;
    });

    closeBtn.addEventListener("click", function() {
       this.parentElement.style.display = 'none';
    })
});

For a working example, refer to this Fiddle: http://jsfiddle.net/0u7jxtfk/2/

Answer №3

To streamline the code, you can make use of CSS to easily hide or display the delete link. Furthermore, you can directly access the delete link from the social link node.

var socialField = document.querySelectorAll('.social-link');

socialField.forEach(function(el) {
  var closeBtn = el.querySelector('.delete-link');
  closeBtn.addEventListener("click", function() {
    el.style.display = 'none';
  });
});
ul {
  list-style: none;
}

input[type='text'] {
  height: 1rem;
  padding: 0.5rem;
  margin-bottom: 1rem;
  border-radius: 3px;
  border: 1px solid #ccc;
}

.delete-link {
  color: red;
  opacity: 0;
  cursor: pointer;
}

.social-link .delete-link {
  opacity: 0;
}

.social-link:hover .delete-link {
  opacity: 1;
}
<ul class="social-links-list">
  <li class="social-link">
    <input type="text" name="" id="" placeholder="http://facebook.com/id">
    <span class="delete-link" onclick=''>X</span>
  </li>
  <li class="social-link">
    <input type="text" name="" id="" placeholder="http://facebook.com/id">
    <span class="delete-link">X</span>
  </li>
  <li class="social-link">
    <input type="text" name="" id="" placeholder="http://facebook.com/id">
    <span class="delete-link">X</span>
  </li>
</ul>

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

Enhance Your List with Icon Decorations

Is it feasible to utilize a sprite image in place of the default bullet for an ul list? Is this achievable? ...

React transmits an incorrect argument through the function

Having a bit of trouble passing a parameter alongside the function in my for loop to create SVG paths. The props are working fine with the correct 'i' value except for selectRegion(i) which ends up getting the final value of 'i' after t ...

How can audio be efficiently streamed to the browser in small chunks using JavaScript?

I am currently working on setting up an internet radio station where I want to easily switch songs and overlay sounds. My goal is to limit the audio rate so that the feed can be adjusted before being sent out. Additionally, I would like to provide continuo ...

How big is the array size in the WebAudio API data?

Exploring the visualization of waveform and FFT generated by the audio stream from the microphone through the WebAudio API. Curiosity strikes - what is the size of each data array available at a given moment? Delving into the getByteTimeDomainData, it men ...

Automating the process of posting a file to a form with javascript

I have a piece of client-side JavaScript that creates a jpeg file through HTML5 canvas manipulation when the user clicks an "OK" button. My goal is to automatically insert this jpeg output into the "Upload Front Side" field in a form, simulating a user up ...

Identify the occurrence of isolated "<" or ">" characters in a string that includes HTML elements

As an example, consider a string similar to: "This is a <b> Sample </b> string with characters < 100" The user has the ability to include HTML tags such as <b>, <div>, and more. These tags are permitted in this scenario. The ma ...

Apply a specific class to a list once scrolling beyond a certain offset of a group of division elements

I seem to be getting close, but I'm struggling to finalize this task. Essentially, as you scroll down to each image, the div containing that image's offset from the top of the window (with a buffer of -500) should add a .selected class to the cor ...

Display the name of the file on the screen

Is there a way to dynamically display the file name in a view instead of hardcoding it? I would appreciate any assistance. Thank you! Here is my code snippet: <li> @if (Model.Picture2 != null) { base2 = Convert.ToBase64String(Model.Pict ...

The operation to set a nickname in Discord.js was unsuccessful due to insufficient permissions

Recently, I started using discord.js to create a simple bot. Whenever I try to change the nickname by calling message.member.setNickname("Another Nickname").then(console.log, console.log); I receive the following error message: { name: ' ...

Having trouble establishing a connection with Mongo.Client on localhost 27017 for MongoDB

Encountering issues with connecting to MongoDB database and storing data in localhost:27017 using MongoClient. Unable to display connection results in the console for both successful and failed connections. var express = require('express'); var r ...

Only display entries with no content

When attempting to filter data from a search, all results are being displayed on the submit button even when entering 1, 2, or 3. Here is my code below. Please let me know if I am making a mistake somewhere. ...

An error occurred: [object Object] does not contain the function 'bootstrapDatepicker'

After spending countless hours searching for a solution, I continue to encounter the dreaded 'Uncaught TypeError' without any successful resolutions. The issue seems to stem from a clash between tribe-events-ajax-calendar.js and foundation.min.j ...

Two challenges I encountered with my CSS dropdown menu bar

I've been working on a CSS top dropdown navigation bar, but I'm encountering two issues that I can't seem to resolve. The first problem is that my nav div either extends too far down or my 1px right border tabs aren't reaching the botto ...

jQuery Mobile offers a feature that allows users to create collapsible elements

I recently ran a coding validation check at and encountered the following errors: <div data-role="collapsible-set" id="col"> <div data-role="collapsible" data-collapsed-icon="carat-d" data-expanded-icon="carat-u" class="ui-nodisc-icon"> ...

Is the float floating within another float?

This question may have a strange title, but I couldn't think of anything better to call it. So, here's the situation: I have a grid layout where I need my .search-wrapper to be 50% wide and floated to the right. In my demonstration on jsfiddle, ...

Leveraging React's useEffect hook to asynchronously fetch and load data

In my coding scenario, there is a parent component containing a child component which loads data asynchronously. This is what I currently have: <Parent> <AsyncChild data={props.data} /> <Child /> </Parent> Within the AsyncChil ...

Is there a way for me to automatically generate and send a random collection each time a GET request is made on my Node.js

I have been developing a typing application that utilizes an API to fetch random quotes from . I successfully created an API using MongoDB, Node.js, and Express which functions well. However, I encountered an issue when trying to send a random collection ...

Trouble with formatting credit card numbers in Vue.js

My payment gateway component includes a feature where selecting credit card triggers the _formatCreditCard method to format the credit card number like this: 4444 2442 4342 3434 This is the function in question: _formatCreditCard: function() { var n ...

Developing a dynamic modal using Angular and embedding Google Maps within an iframe

I'm currently working on implementing a modal in my Angular application that, when opened, displays Google Maps within an iframe. The problem I'm facing is that the iframe isn't loading and I'm receiving this error in the browser conso ...

Personalized HTML characteristics

Within the realm of AngularJS (and possibly jQuery UI), I've come across tags such as ui:some_random_name and ng:some_random_name. It seems that according to the HTML specification, non-standard attributes are not allowed. So how do these libraries m ...