Skip to content Skip to sidebar Skip to footer

Delete An Image() Object From Memory On Click Event Of Sibling Element — Javascript

I have an image previewer that uses the JavaScript Image() object to preview images prior to them being processed with PHP. I have a div that contains an 'x' SVG graphic that is ta

Solution 1:

Problem:

You are not updating fileUploader.files when you add/remove an item.

Solution

Every time you drop/remove a file you need to update the fileUploader input. The first step is to create a function to handle the FileList object and change only two lines of your code:

//--> to create a FileListfunction getFileListItems (files) {
  var transferObject = new ClipboardEvent("").clipboardData || new DataTransfer()
  for (var i = 0; i<files.length; i++) transferObject.items.add(files[i])
  return transferObject.files;
}

 

Add files during the drop event:

//--> Updating files during drop event
 fileUploader.files = getFileListItems([...fileUploader.files, ...evt.dataTransfer.files]);

Removing a file:

fileUploader.files = getFileListItems([...fileUploader.files].filter(f => file!==f));

See a complete working example:

const dropZone = document.getElementById("drop-zone"),
  showSelectedImages = document.getElementById("show-selected-images"),
  fileUploader = document.getElementById("standard-upload-files");

dropZone.addEventListener("click", (evt) => {
  // assigns the dropzone to the hidden input element so when you click 'select files' it brings up a file picker window
  fileUploader.click();
});

// Prevent browser default when draging over
dropZone.addEventListener("dragover", (evt) => {
  evt.preventDefault();
});

fileUploader.addEventListener("change", (evt) => {
  // this function is further down but declared here and shows a thumbnail of the image
  [...fileUploader.files].forEach(updateThumbnail);
});

functiongetFileListItems(files) {
  var transferObject = newClipboardEvent("").clipboardData || newDataTransfer()
  for (var i = 0; i < files.length; i++) transferObject.items.add(files[i])
  return transferObject.files;
}

dropZone.addEventListener("drop", (evt) => {
  evt.preventDefault();
  // assign dropped files to the hidden input elementif (evt.dataTransfer.files.length) {
    fileUploader.files = getFileListItems([...fileUploader.files, ...evt.dataTransfer.files]);
  }
  // function is declared here but written further down
  [...evt.dataTransfer.files].forEach(updateThumbnail);
});

// updateThumbnail function that needs to be able to handle multiple filesfunctionupdateThumbnail(file) {
  if (file.type.startsWith("image/")) {
    let uploadImageWrapper = document.createElement("article"),
      removeImage = document.createElement("div"),
      thumbnailElement = newImage();

    // 'x' that deletes the image
    removeImage.classList.add("remove-image");
    removeImage.innerHTML =
      '<svg id="remove-x" viewBox="0 0 150 150"><path fill="#000" d="M147.23,133.89a9.43,9.43,0,1,1-13.33,13.34L75,88.34,16.1,147.23A9.43,9.43,0,1,1,2.76,133.89L61.66,75,2.76,16.09A9.43,9.43,0,0,1,16.1,2.77L75,61.66,133.9,2.77a9.42,9.42,0,1,1,13.33,13.32L88.33,75Z"/></svg>';

    // image thumbnail
    thumbnailElement.classList.add("drop-zone__thumb");
    thumbnailElement.src = URL.createObjectURL(file);

    // appending elements
    showSelectedImages.append(uploadImageWrapper); // <article> element
    uploadImageWrapper.append(removeImage); // 'x' to delete
    uploadImageWrapper.append(thumbnailElement); // image thumbnail// Delete images
    removeImage.addEventListener("click", (evt) => {
      if (evt.target) {
        var deleteImage = removeImage.parentElement;
        deleteImage.remove();
        fileUploader.files = getFileListItems([...fileUploader.files].filter(f => file !== f));
      }
    });
  }
} // end of 'updateThumbnail' function
body {
  margin: 0;
  display: flex;
  justify-content: center;
  width: 100%;
}

form {
  width: 30%;
}

#drop-zone {
  border: 1px dashed;
  width: 100%;
  padding: 1rem;
  margin-bottom: 1rem;
}

.select-files {
  text-decoration: underline;
  cursor: pointer;
}


/* image that is preview prior to form submit*/.drop-zone__thumb {
  width: 200px;
  height: auto;
  display: block;
}

#remove-x {
  width: 1rem;
  height: 1rem;
}

#submit-images {
  margin: 1rem0;
}

#show-selected-images {
  display: flex;
}
<formid="upload-images-form"enctype="multipart/form-data"method="post"><h1>Upload Your Images</h1><divid="drop-zone"class="drop-zone flex"><pclass="td text-center">DRAG AND DROP IMAGES HERE</p><pclass="td text-center"style="margin: 0">Or</p><pclass="tl text-center select-files text-bold pointer">Select Files</p></div><inputid="standard-upload-files"style="display:none"style="min-width: 100%"type="file"name="standard-upload-files[]"multiple><inputtype="submit"name="submit-images"id="submit-images"value="SUBMIT IMAGES"><divid="show-selected-images"></div></form>

Working example

Solution 2:

This is because when a form submitted, it doesn't submit every HTML element in the form, but only values of input, textarea, pressed button and some others that have name attribute.

So what you need is clear the file input field too:

const showSelectedImages = document.getElementById("preview");
const input = document.getElementById("test");

functionupdateThumbnail(file) {
  if (file.type.startsWith("image/")) {

    // image and 'x' to delete wrapper const uploadImageWrapper = document.createElement('article')

    // div that holds the 'x' to deleteconst removeImage = document.createElement('div')

    // image preview element
    thumbnailElement = newImage()

    // 'x' that deletes the image
    removeImage.classList.add("remove-image")
    removeImage.innerHTML = 'x'// image thumbnail
    thumbnailElement.classList.add("drop-zone__thumb")
    thumbnailElement.src = URL.createObjectURL(file)

    // appending elements
    showSelectedImages.append(uploadImageWrapper) // <article> element
    uploadImageWrapper.append(removeImage) // 'x' to delete
    uploadImageWrapper.append(thumbnailElement) // image thumbnail// Delete Images when the 'x' div is clicked
    removeImage.addEventListener('click', (evt) => {
      if (evt.target) {
        var deleteImage = removeImage.parentElement
        deleteImage.remove();

        /* for single file input is enough clear value property *///        input.value = null;/* for multiple files input we'll need recreate new files list excluding deleted file */const dt = newDataTransfer();
        for (let f of input.files) {
          if (f !== file)
            dt.items.add(f);
        }

        input.files = dt.files;
      }
    })
  }

}

functionupdateThumbnails(files) {
  showSelectedImages.innerHTML = ""; //remove all previous previewsfor (let f of files)
    updateThumbnail(f);
}

functionshowform(form) {
  const list = {};
  for (let i of [...newFormData(form).entries()]) {
    const key = i[0].match(/^([^\[]+)\[\]$/);
    if (key) {
      if (!list[key[1]])
        list[key[1]] = [];
      list[key[1]][list[key[1]].length] = i[1];
    } else
      list[i[0]] = i[1];
  }
  console.log(list)
  returnfalse;
}
.remove-image {
  cursor: pointer;
}

article {
  display: inline-block;
}
<formtype="post"onsubmit="return showform(this);"><inputtype="hidden"name="myHiddenInput"value="blah"><inputtype="file"name="test[]"id="test"oninput="updateThumbnails(this.files)"multiple><spanid="preview"></span><buttontype="submit">submit</button></form>

Post a Comment for "Delete An Image() Object From Memory On Click Event Of Sibling Element — Javascript"