Series: Drag-n-Drop Image Uploads

dragEnter and dragLeave

Published on Jul 05, 2015

Our drag and drop from episode 51 is functional, but it isn't very clear how to use it.

In this episode we'll combine the dragEnter and dragLeave events with some css in order to improve the experience and make it more obvious when you're supposed to drop your file.


Links

Code

//stylesheets.css.scss
.dropzone.uploader {
  width: 300px;
  height: 200px;
  background-color: grey;
  position: relative;

  &.is-dragging {
    background-color: #9D9;
    border: 4px solid #191;
    border-radius: 4px;
  }

  img {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
  }
}
//components/file-upload/component.js
import Ember from 'ember';

export default Ember.Component.extend({  
  tagName: 'div',
  classNames: ['uploader', 'dropzone'],
  isDragging: Ember.computed.gt('dragCounter', 0),
  classNameBindings: ['isDragging'],
  dragCounter: 0,

  dragEnter() {
    this.incrementProperty('dragCounter')
  },
  dragLeave(){
    this.decrementProperty('dragCounter')
  },

  dragOver(event) {
    event.preventDefault()
  },

  drop(event) {
    event.preventDefault()

    this.set('dragCounter', 0)

    var file = event.dataTransfer.files[0]
    this.sendAction('fileInputChanged', file)
  }
});
//post/edit-fields/template.hbs
{{#file-upload fileInputChanged="receiveFile"}}
  <img id="preview-image" src="{{model.thumbnailImage.thumbnail_image.url}}" class="small-image" />
{{/file-upload}}

Transcript

In Episode 51, we created a drag-and-drop file uploader. We got the functionality down, but it’s a bit ugly, and it’s not really intuitive how to use it. We’re going to to fix that, and along the way we’ll learn a bit more about browser events, especially dragEnter and dragLeave.

So we want some sort of acknowledgement that we’re dragging over the dropzone, that is aside from the disappearance of the green plus icon. We’ll create an isDragging attribute and we’ll set it to true at first so we can see what we’re doing, and then we’ll have it as a className binding. In our css, we’ll set the isDragging class to change the color and the border. So that’s what it will look like when we’re dragging something over the dropzone.

To make this happen, we’ll turn off the isDragging property as default, and then have it turned on or off when you’re leaving the dropzone. We’ll do this using the dragEnter and dragLeave events. And we’ll also make sure to turn off isDragging when the drop event fires. This is a pretty cool effect, but we’re not done. We’re going to make another improvement and see how it interferes with what we just did.

The next thing to tackle is image centering. We want the image preview to be in the center of the drop field. Let’s wrap the image in the component and add in some css to make it centered. There we go. It’s centered and when we drag it in, it lights up. But when we drag it over the image, the component stops highlighting. Even worse, exiting the picture doesn’t re-highlight the component.

To diagnose the problem, we’ll put a console.log on the dragEnter and dragLeave events. So then we can see that when we enter the picture, a dragEnter and dragLeave are both fired and both caught on our component. But the dragEnter is usually fired before the dragLeave, so the isDragging attribute gets set to true again, then immediately to false. Oh-oh.

Our solution is an integer called dragCounter. It starts at 0, and is incremented by 1 when entering and decremented by 1 when leaving. Dropping sets it to 0 again. If it’s above 0, then isDragging is true, and the component is highlighted.

So that’s how to give good feedback for our drag-and-drop with dragEnter and dragLeave. Even with the complication of an internal element, Ember made things easy. So good luck out there this week, and keep on being awesome.

Drag-n-Drop Image Uploads

Subscribe to our mailing list