@transformation-dev/dragster
Version:
Port of Ben Smithett's dragster to ES6. Wraps native dragenter/dragleave to behave like mouse event when hovering over child DOM elements.
81 lines (71 loc) • 2.3 kB
JavaScript
import Debug from 'debug'
const debug = Debug('blueprint:dragster') // Don't forget to set environment variable with 'DEBUG=blueprint:*' and localStorage with debug='blueprint:*'
export class Dragster {
constructor(el) {
this.dragenter = this.dragenter.bind(this)
this.dragleave = this.dragleave.bind(this)
this.el = el
this.first = false
this.second = false
this.el.addEventListener('dragenter', this.dragenter, false)
this.el.addEventListener('dragleave', this.dragleave, false)
this.destroy = this._destroy.bind(this)
if (!Dragster.dragsters) {
Dragster.dragsters = {}
}
if (Dragster.dragsters[this.el.id]) {
debug('WARNING: A Dragster for element with id "%O" has already been instantiated. This replaces that.', this.el.id)
}
Dragster.dragsters[this.el.id] = this
}
static getDragster(id) {
return Dragster.dragsters[id]
}
static reset(el) {
Dragster.dragsters[el.id].reset()
}
dragenter(event) {
event.preventDefault()
if (this.first) {
this.second = true
} else {
this.first = true
this.customEvent = document.createEvent('CustomEvent')
this.customEvent.initCustomEvent('dragster-enter', true, true, {
dataTransfer: event.dataTransfer,
sourceEvent: event,
})
this.el.dispatchEvent(this.customEvent)
}
}
dragleave(event) {
if (this.second) {
this.second = false
} else if (this.first) {
this.first = false
}
if (!this.first && !this.second) {
this.customEvent = document.createEvent('CustomEvent')
this.customEvent.initCustomEvent('dragster-leave', true, true, {
dataTransfer: event.dataTransfer,
sourceEvent: event,
})
this.el.dispatchEvent(this.customEvent)
}
}
removeListeners() {
this.el.removeEventListener('dragenter', this.dragenter, false)
return this.el.removeEventListener('dragleave', this.dragleave, false)
}
// Must call after drop or a second drop to the same target sometimes gets missed
reset() {
this.first = false
return this.second = false
}
_destroy() {
if (Dragster.dragsters[this.el.id]) {
Dragster.dragsters[this.el.id].removeListeners()
delete Dragster.dragsters[this.el.id]
}
}
}