Creating a function in JavaScript to enable image uploading without replicating the image

I am working on creating an image upload function using JavaScript, but encountering an issue. When I delete the first image (by clicking the 'X') and try to re-upload another image, both images appear instead of just one. I need to resolve this using only JavaScript without any external libraries. Below is the code snippet:

var container = document.querySelector('.image_container'); 

function upload(id,imageBox, deleteBtn){ 

 var inputTarget = document.getElementById(id); 
 var imageBox = document.getElementById(imageBox);
 var deleteBtn = document.getElementById(deleteBtn);
 var imagePrev = document.createElement('img');
  
inputTarget.addEventListener('change', function({target}){
    var file = target.files[0];
    var reader = new FileReader();
    reader.onload = function(e){ 
      deleteBtn.style.display = 'block';
      imageBox.style.display = 'none';
      imagePrev.src = e.target.result;
      imagePrev.className = id;
      container.appendChild(imagePrev);
    };
    reader.readAsDataURL(file);
  });
}

function deleteImg(id,imageBox,btnId){
  var targetInput = document.getElementById(id);
  var imageBox = document.getElementById(imageBox); 
  var imagePrev = document.querySelector('.'+id);
  var deleteBtn = document.querySelector('#'+btnId);

  imageBox.style.display = 'block';
  targetInput.value = "";
  deleteBtn.style.display = 'none';
  container.removeChild(imagePrev);
}
.image_container input[type="file"] {
    display: none;
}
.image_container #image_area1  {
    width: 100px;
    height: 100px;
    cursor: pointer;
    text-align: center;
    display: inline-block;
    line-height: 90px;
    background: rgb(211, 211, 211);
    border-radius: 3px;
    background-size: cover;           
    background-repeat: no-repeat;
    background-position: center center;
}
.image_container {
    display: inline-block;
}
button {
  display: block;
  margin: 20px 0;
}
#close_button {
  background: white;
    border-radius: 50px;
    width: 21px;
    height: 21px;
    text-align: center;
    position: absolute;
    top: 0;
    left: 0;
    cursor: pointer;
    display: none;
}
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title></title>
</head>
<body>
<div class="image_container">
  <label>
    <input 
      type="file" 
      class="upload_button-first"
      id="target1"
      onclick="upload('target1','image_area1', 'close_button')">
    <span id="image_area1">upload image</span>   
  </label>
  <div id="close_button" onclick="deleteImg('target1','image_area1','close_button')">x</div>
</div>
</body>
</html>

Answer №1

Make sure to only register the one-time event; otherwise, the event will trigger n times when adding n images.

var handler = function(target) {
    var file = target.files[0];
    var reader = new FileReader();
    reader.onload = function(e) {
        deleteBtn.style.display = 'block';
        imageBox.style.display = 'none';
        imagePrev.src = e.target.result;
        imagePrev.className = id;
        container.appendChild(imagePrev);
    };
    reader.readAsDataURL(file);
    inputTarget.removeEventListener('change', handler);
};
inputTarget.addEventListener('change', handler);

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

Vue: update data and trigger function upon completion of animation transformation, utilizing animation transformation completion listener

Check out this straightforward Vue example: https://codesandbox.io/s/sleepy-haze-cstnc2?file=/src/App.vue https://i.stack.imgur.com/zboCb.png Whenever I click on the square, it not only changes color but also expands to 200% of its original size with a 3 ...

What is the best way to transform arrays like this into a JSON object?

Below is an array that I need to convert into an object: [ [ '560134275538747403', 39953 ], [ '411510958020624384', 36164 ], [ '468512396948930576', 31762 ], [ '482286641982078977', 29434 ], ...

Expandable Grid Sections in React MUI

Is there a way to create a grid layout where items with showDefault: true are always displayed at the top, and then users can click an arrow button to expand the grid and also show the items with showDefault: false? Any suggestions on how to achieve this? ...

Best Practices for Sequencing Vuex Actions and Safely Updating the State in between Calls

I have a Vuex store set up in my application with defined getters, actions, and mutations. One of the actions, called initConfiguration, is responsible for fetching data from an API and then committing this data to a mutation that updates the state. This a ...

Guide on determining if the value in a JSON object is a string or an array in Node.js

Running a Node.js application, I encountered the following JSON array structure. First JSON object: var json1= { bookmarkname: 'My Health Circles', bookmarkurl: 'http://localhost:3000/', bookmark_system_category: [ '22&apos ...

Javascript's callback mechanism allows functions to be passed as arguments

I am currently delving into the intricacies of the callback mechanism in javascript, particularly typescript. If I have a function that expects a callback as an input argument, do I need to explicitly use a return statement to connect it with the actual ca ...

Navigating to lower levels of JSON data in JavaScript instead of starting with the top level

Using a microservice, I fetch multiple sets of JSON data and display them on a Vue.js-powered page. The structure of the data is as follows: {"data":{"getcompanies": [ {"id":6,"name":"Arena","addr ...

JS Issue with Countdown functionality in Internet Explorer and Safari

I am having an issue with a JavaScript countdown not working on Internet Explorer and Safari, despite being tested on Windows 7. It works fine on Chrome and Firefox. I am unable to switch to a jQuery countdown due to certain restrictions on the website, so ...

The CSS remains dormant until the cursor is hovered over

Let's kick things off with a quick video presentation. Check out this video for more details In the video, you can observe that when opening the dropdown menu on the top right corner, all Tailwind Classes seem to be missing. It's puzzling why t ...

The struggle between Node.js 404 errors and Angular's URL refresh issue

I am currently developing a Node.js and AngularJS application. I encountered an issue where a page loads successfully when the URL is entered, but then I added a script to redirect to a 404 error page. Now, only one of the criteria works at a time - either ...

React Quill editor fails to render properly in React project

In the process of developing an application in Ionic React, I am in need of a rich text editor that can save data on Firestore. Despite initializing the editor as shown below and adding it to the homepage component, it is not rendering correctly although i ...

Error handling in a Try Catch statement fails when using SSJS Platform.Response.Redirect

I am currently facing an issue with threadabortexception in .NET, and despite trying various options, I have not been able to resolve it. In essence, the Redirect function is throwing errors and landing in the catch block, regardless of whether the second ...

Is it possible to pass the chart type as a property when using vue-chart.js?

Is it possible to pass the chart type as a property with vue-chart.js? I would love to see some example source code. Can you please provide guidance on this? ...

Guide to making a dropdown menu that pulls information from a text box and displays the location within the text

I'm currently working on a unique dropdown feature that functions like a regular text field, displaying the text position. To achieve this, I've constructed a hidden dropdown menu positioned beneath the text field. My goal is to develop a jQuery ...

The buttons in the Bootstrap modal are unresponsive

I'm attempting to create a modal navigation bar for mobile view but encountering an issue. When I click on the icon bar or menu bar in mobile view, none of the buttons inside the modal are responding. I'm quite stuck on this and would appreciate ...

Is it considered good practice to utilize Vue.js for managing global shared state and implementing for loops outside of components?

Just getting started with Vue.JS and experimenting with creating two lists of books (read and unread) from a shared object in the global data state. This is my approach - working demo (works like a charm! However, I'm wondering if this is considered ...

Is there a Page Views tracker in sinatra?

Help needed with implementing a page views counter using Sinatra and Ruby. I attempted using the @@ variables, but they keep resetting to zero every time the page is reloaded... Here's an example: Appreciate any advice! ...

Iterating over the local storage to locate a specific item

Utilizing local storage extensively has been beneficial for maintaining state by storing the session on the client side. However, a challenge arises when updating the session. Within my code, there are multiple lists of objects that I serialize in JSON fo ...

What happens when two ajax requests are made simultaneously during the same event? How does the typical behavior differ if the requests are synchronous instead?

Within the Javascript code below, I am initiating two Ajax requests simultaneously. Upon inspecting with Firebug, it was noted that there is an unusual behavior where: "whichever Ajax response arrives first is displayed last". Issue 2: If I set the Aj ...

Identify the index of a list item using a custom list created from buttons

When dealing with a dynamically built list like this: <ul id="shortcuts"> <li><input type="checkbox" value="false"/><button>foo</button><button>-</button></li> <li><input type="checkbox" value ...