Search code examples
javascripteventsdrag-and-dropdrop

Remove CSS Class on 'Drop' Event - JavaScript


I'm building a file uploader and when I drag files over the target area I have a class that is added on dragover and removed on dragleave. This essentially changes the border color of the drop zone so that the user knows when they can drop the files. This is done by adding and removing a 'drop' class.

I'm trying to make it so when the user drops the actual files into the drop zone the drop event also removes the 'drop' class that is added on dragover (so the border goes back to its original state), but I can't get this to work?

Codepen is: https://codepen.io/emilychews/pen/OJpwzej

Any help really appreciated.

var dropZone = document.getElementById("drop-zone");

// change border on file dragover by adding the class "drop"
dropZone.addEventListener(
  "dragover",
  function (e) {
    e.target.classList.add("drop");
  },
  false
);

// remove border by removing the class "drop" when user leaves the drop zone
dropZone.addEventListener(
  "dragleave",
  function (e) {
    e.target.classList.remove("drop");
  },
  false
);

// -- PART THAT ISN'T WORKING
// also remove border by removing the class "drop" when files are dropped
dropZone.addEventListener(
  "drop",
  function (e) {
    e.target.classList.remove("drop");
  },
  false
);
body {
  margin: 0;
  display: flex;
  justify-content: center;
  align-items: center;
  height: 100vh;
}

.inner-drop-wrapper {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 300px;
  width: 300px;
  border: 1px solid;
}

.inner-drop-wrapper.drop {
  border: 2px solid red;
}
<div class="inner-drop-wrapper" id="drop-zone">
  Drag and drop files here
</div>


Solution

  • You have to allow drop in your div. To achieve that, you need to add

    e.preventDefault();
    

    as the first line of your dragover callback function. This will enable your drop event to fire properly.

    var dropZone = document.getElementById("drop-zone");
    
    // change border on file dragover by adding the class "drop"
    dropZone.addEventListener(
      "dragover",
      function (e) {
        e.preventDefault();
        console.log('dragover');
        e.target.classList.add("drop");
      },
      false
    );
    
    // remove border by removing the class "drop" when user leaves the drop zone
    dropZone.addEventListener(
      "dragleave",
      function (e) {
        console.log('dragleave');
        e.target.classList.remove("drop");
      },
      false
    );
    
    // -- PART THAT ISN'T WORKING
    // also remove border by removing the class "drop" when files are dropped
    dropZone.addEventListener(
      "drop",
      function (e) {
        e.preventDefault();
        console.log('drop');
        e.target.classList.remove("drop");
      },
      false
    );
    body {
      margin: 0;
      display: flex;
      justify-content: center;
      align-items: center;
      height: 100vh;
    }
    
    .inner-drop-wrapper {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 300px;
      width: 300px;
      border: 1px solid;
    }
    
    .inner-drop-wrapper.drop {
      border: 2px solid red;
    }
    <div class="inner-drop-wrapper" id="drop-zone">
      Drag and drop files here
    </div>

    From MDN documentation

    If you want to allow a drop, you must prevent the default handling by cancelling both the dragenter and dragover events. You can do this either by returning false from attribute-defined event listeners, or by calling the event's preventDefault() method. The latter may be more feasible in a function defined in a separate script.

    MDN - Specifying Drop Targets