Dropzone (extends KompElement)

A container that handles drag/drop events

Example

Options

types description default
content String, HTMLElement, Array, Object

content to append to element. Passed to Dolla's content

overlay Function, HTMLElement, Object

layer to render over dropzone when drag happens on window

Drag Here
onFileDrop Function(`File`)

callback for drop action

enabled Boolean

setup events

true

Methods

arguments description
intialize []

method called once for each instantiation, but only after element is connected (required for accessing some properties)

trigger eventName:string, ...args

triggers an event this element passes args

addEventListenerFor element:HTMLElement, eventType:string, ...args

calls callback when eventType is triggered on element, enables component to tear down listener when disconnected.

changed attribute, was, now

called every time an attribute of the element changes. Must include attribute in static watch = ['foo']

[attribute]Changed was, now

called every time attribute of the element changes. Must include attribute in static watch = ['foo']

enabled none

sets up events

disabled none

tears down events

Events

arguments description
beforeRemove []

called before element is removed

afterRemove []

called after element is removed

beforeConnect []

called before element is connected

afterConnect []

called before element is connected

beforeDisconnect []

called before element is disconnected

afterDisconnect []

called before element is disconnected

filedrop File

called in onDrop for each file dropped

SOURCE CODE
import { css, createElement } from 'dolla';
import KompElement from './element.js';

class Dropzone extends KompElement {
    static tagName = "komp-dropzone"
    
    static assignableAttributes = {
        enabled: true,
        onFileDrop: null,
        overlay: {
            content: 'Drag Here'
        }
    }
    
    static bindMethods = ['windowDragEnter', 'windowDragLeave', 'windowDrop', 'drop', 'dragOver', 'dragEnter', 'dragLeave']
    
    constructor (...args) {
        super(...args)

        if (typeof this.overlay == "object" && !(this.overlay instanceof HTMLElement)) {
            this.overlay = createElement('komp-dropzone-overlay', Object.assign({}, this.constructor.assignableAttributes.overlay, this.overlay))
        }
    }
    
    addEventListeners () {
        if (this.getRootNode()) {
            this.getRootNode().addEventListener('dragenter', this.windowDragEnter);
            this.getRootNode().addEventListener('dragleave', this.windowDragLeave);
            this.getRootNode().addEventListener('drop', this.windowDrop);
        }
        this.addEventListener('drop', this.drop)
        this.addEventListener('dragover', this.dragOver)
        this.addEventListener('dragenter', this.dragEnter)
        this.addEventListener('dragleave', this.dragLeave)
    }
    
    removeEventListeners () {
        if (this.getRootNode()) {
            this.getRootNode().removeEventListener('dragenter', this.windowDragEnter);
            this.getRootNode().removeEventListener('dragleave', this.windowDragLeave);
            this.getRootNode().removeEventListener('drop', this.windowDrop);
        }
        this.removeEventListener('drop', this.drop)
        this.removeEventListener('dragover', this.dragOver)
        this.removeEventListener('dragenter', this.dragEnter)
        this.removeEventListener('dragleave', this.dragLeave)
    }
    
    connected () {
        if (css(this, 'position') == "static") {
            this.style.position = 'relative';
        }
        if (this.enabled) {
            this.addEventListeners()
        }
    }
    disconnected () {
        if (this.enabled) {
            this.removeEventListeners()
        }
    }
    
    enable () {
        if (this.enabled) { return }
        this.enabled = true
        this.addEventListeners()
    }
    
    disable () {
        if (this.enabled == false) { return }
        this.enabled = false
        this.removeEventListeners()
    }
    
    /*
        This Events
    */
    
    drop (e) {
        if (e.target == this || this.contains(e.target)) {
            e.preventDefault();
            ([...e.dataTransfer.files]).forEach(file => {
                if (this.onFileDrop) { this.onFileDrop(file) }
                this.trigger('filedrop', file)
            });
        }
        
    }
    
    dragEnter (e) {
        e.preventDefault()
        this.overlay.classList.add('active');
    }
    
    dragLeave (e) {
        e.preventDefault()
        if (!this.contains(e.relatedTarget)) {
            this.overlay.classList.remove('active');
        }
    }
    
    dragOver (e) {
        e.preventDefault();
    }
    
    /*
        Window Events
    */
    
    windowDragEnter (e) {
        e.preventDefault();
        if (!e.relatedTarget || e.relatedTarget.getRootNode() != this.getRootNode()) {
            this.overlay.classList.remove('active');
            this.append(this.overlay);
        }
    }
    
    windowDragLeave (e) {
        e.preventDefault();
        if (!e.relatedTarget || e.relatedTarget.getRootNode() != this.getRootNode()) {
            this.overlay.remove()
        }
    }
    
    windowDrop (e) {
        e.preventDefault();
        this.overlay.remove()
    }
    
    static style = `
        komp-dropzone {
            display: inline-block;
            position: relative;
        }
        komp-dropzone-overlay {
            display: flex;
            position:absolute;
            inset: 0;
            border: 2px dashed blue;
            background: rgba(255,255,255, 0.5);
            backdrop-filter: blur(2px);
            z-index:2;
            color: blue;
            font-weight: bold;
            align-items: center;
            justify-content: center;
            pointer-events: none;
        }
        komp-dropzone-overlay.active {
            background: rgba(0,0,0, 0.3);
            color: black;
        }
    `
}
window.customElements.define(Dropzone.tagName, Dropzone);