# Vue.js Dragon
Easy & flexible unopinionated drag & drop library for Vue.js.

## Installation

### Using modules
```javascript
import Dragon from "v-dragon"; // Install this using `npm install vuedragon`
Vue.use(Dragon);
```

### Using browser-based JavaScript
```html
<script src="https://cdn.jsdelivr.net/npm/v-dragon/dragon.js"></script>
```

## Concepts

### Items
An item (`v-dragon`) is an element that can be dragged and/or dropped, and can be a `dragon-sink` and/or a `dragon-source`.  
A `dragon-sink` can be used to drop stuff onto, a `dragon-source` can be dragged onto other items. Not specifiying any of them is the same as specifiying both.

### Payload
The `dragon-payload` is the object sent to the `dragon-drop` event, and should contain all necessary information so you know *which* thing (payload of the dragged item) has been dragged *where* (payload of the drop target).

### The `dragon-drop` Event
This event is called on the drop target after a drag & drop has occurred, and its `$event` object contains the payload of the dragged item as `from`, and the payload of the drop target as `to`. It can then be used to run your own logic to process the event.  
The `$event` object also contains the boolean values `keyCtrl`, `keyAlt`, `keyShift`, `mouseLeft`, `mouseMiddle` and `mouseRight` to work with modifiers. The modifiers are determined on the start of the drag process.

There's also a `dragon-drag` event which is called on the dragged item instead of the drop target; to avoid confusion though, its usage is discouraged unless you need to access something only available from the source.

### Classes
A `dragon-class` specifies the type of the object - think of it like the `name` property of radio buttons. You can only drag a dragon onto a dragon of the same class.

### Handle
A `dragon-handle` is an element that can initiate a drag process (the thing where you can "grab" your item with the mouse). You can use more than one handle, and if an item contains no handle at all, it will be draggable everywhere.

### Area of Effect
The `dragon-aoe` specifies how far away from a target something can be dropped while still considering that target. If multiple targets come into question, the closest target will be taken.  
It should only be used on elements that *can* have a `::before` pseudo-element, and *don't already* have one.

### CSS Classes
`dragon-aim` is assigned to an item (that could become a target if the mouse button is released) while hovering above it with an eligible dragged element.  
`dragon-use` is assigned to a dragged element during a drag process.

## Usage Example
```html
<template>
    <ul>
        <!-- I'm a sink, so I can not be dragged, but you can drop stuff on me -->
        <!-- I also have an AoE of 25 pixels, so you don't have to aim that much -->
        <li
          v-dragon dragon-sink :dragon-payload="{dragon: null, index: -1}"
          dragon-class="game-of-thrones"
          dragon-aoe="25"
          v-on:dragon-drop="drop"></li>

        <!-- I'm a normal dragon, you can drop stuff onto me -->
        <li
          v-for="(d, i) in dragons" v-bind:key="d"
          dragon-item :dragon-payload="{dragon: d, index: i}"
          dragon-class="game-of-thrones"
          v-on:dragon-drop="drop">
            <i dragon-handle class="fa fa-dragon"></i>
            {{ d }}
        </li>
        
        <!-- I'm a source, so I can only be dragged -->
        <li
          v-dragon dragon- :dragon-payload="{dragon: newDragon, index: -1}"
          dragon-class="game-of-thrones">
            <i dragon-handle class="fa fa-dragon"></i>
            <input type="text" placeholder="The new dragon" v-model="newDragon">
        </li>
    </ul>
</template>
<script>
export default {
    data() {
        return {
            dragons: ['Drogon','Rhaegal','Viserion','Balerion','Vhagar','Meraxes','Sunfyre','Syrax','Caraxes','Meleys','Vermax','Arrax','Stormcloud','Sheepstealer','Seasmoke','Silverwing','Vermithor','Shrykos','Tyraxes','Dreamfyre','Vermithrax','Ghiscar','Valryon','Essovius','Archonei','The last dragon'],
            newDragon: ""
        };
    },
    methods: {
        drag() {
            if (window.event.data.from.index >= 0) this.dragons.splice(window.event.data.from.index, 1); // Remove the old dragon
            this.dragons.splice(window.event.data.to.index + (window.event.data.to.index > window.event.data.from.index ? 0 : 1), 0, window.event.data.from.dragon); // Insert it at the new position
            if (window.event.data.from.index == -1) this.newDragon = ""; // Clear the newDragon field
        }
    }
}
</script>
<style>
    li { transition: box-shadow 0.5s; }
    [dragon-handle] { cursor: grabbing; }
    .dragon-aim { box-shadow: 0 0 10px #089E71; }
    .dragon-use { opacity: 0.8; }
</style>
```
