# Dragula - 拖放排序库

Dragula 是一个强大的拖放排序库，支持跨容器拖拽、自动排序、视觉反馈等功能。

## 加载方式

```javascript
// 加载 CSS
Wind.css('dragula');

// 加载 JS
Wind.use('dragula', function() {
    // dragula 加载完成，可以使用了
});
```

## 基础用法

### 1. 单列表排序

```html
<ul id="list">
    <li>项目 1</li>
    <li>项目 2</li>
    <li>项目 3</li>
</ul>
```

```javascript
Wind.use('dragula', function() {
    dragula([document.getElementById('list')]);
});
```

### 2. 多列表之间拖拽

```html
<div id="left">
    <div class="item">左 1</div>
    <div class="item">左 2</div>
</div>
<div id="right">
    <div class="item">右 1</div>
    <div class="item">右 2</div>
</div>
```

```javascript
Wind.use('dragula', function() {
    dragula([document.getElementById('left'), document.getElementById('right')]);
});
```

### 3. 看板（Kanban）示例

```html
<div class="board">
    <div class="column" id="todo">
        <h3>待办</h3>
        <div class="card">任务 1</div>
        <div class="card">任务 2</div>
    </div>
    <div class="column" id="doing">
        <h3>进行中</h3>
        <div class="card">任务 3</div>
    </div>
    <div class="column" id="done">
        <h3>已完成</h3>
        <div class="card">任务 4</div>
    </div>
</div>
```

```javascript
Wind.use('dragula', function() {
    dragula([document.getElementById('todo'), 
             document.getElementById('doing'), 
             document.getElementById('done')]);
});
```

## 高级配置

### 配置选项

```javascript
Wind.use('dragula', function() {
    dragula(containers, {
        // 指定哪些元素可以被拖拽（默认所有子元素）
        moves: function(el, source, handle, sibling) {
            return true; // 返回 false 禁止拖拽
        },
        
        // 指定哪些元素可以接受放置
        accepts: function(el, target, source, sibling) {
            return true; // 返回 false 禁止放置
        },
        
        // 指定哪些元素不参与拖拽
        invalid: function(el, handle) {
            return false; // 返回 true 不参与
        },
        
        // 拖拽方向: 'vertical'(垂直) 或 'horizontal'(水平)
        direction: 'vertical',
        
        // 是否复制元素（而不是移动）
        copy: false,
        
        // 复制时是否排序
        copySortSource: false,
        
        // 是否允许撤销拖拽（按 Esc）
        revertOnSpill: false,
        
        // 是否在容器外部移除元素
        removeOnSpill: false,
        
        // 延迟拖拽（毫秒）
        delay: 0,
        
        // 是否只在鼠标左键时拖拽
        ignoreInputTextSelection: true
    });
});
```

### 事件监听

```javascript
Wind.use('dragula', function() {
    var drake = dragula([document.getElementById('list')]);
    
    // 拖拽开始
    drake.on('drag', function(el, source) {
        console.log('开始拖拽', el);
    });
    
    // 拖拽结束
    drake.on('dragend', function(el) {
        console.log('拖拽结束', el);
    });
    
    // 放置到容器
    drake.on('drop', function(el, target, source, sibling) {
        console.log('放置元素', el);
        console.log('目标容器', target);
        console.log('来源容器', source);
        console.log('相邻元素', sibling);
        
        // 这里可以发送 AJAX 请求保存排序
        saveOrder();
    });
    
    // 取消拖拽（按 Esc）
    drake.on('cancel', function(el, container, source) {
        console.log('取消拖拽', el);
    });
    
    // 移除元素（拖到外部）
    drake.on('remove', function(el, container, source) {
        console.log('移除元素', el);
    });
    
    // 阴影元素创建
    drake.on('shadow', function(el, container, source) {
        console.log('阴影元素', el);
    });
    
    // 放置位置变化
    drake.on('over', function(el, container, source) {
        console.log('进入容器', container);
    });
    
    drake.on('out', function(el, container, source) {
        console.log('离开容器', container);
    });
});
```

## 实际应用场景

### 1. 菜单排序

```javascript
Wind.use('dragula', function() {
    var drake = dragula([document.querySelector('.menu-list')], {
        direction: 'vertical',
        moves: function(el, container, handle) {
            // 只有点击拖拽手柄时才拖拽
            return handle.classList.contains('drag-handle');
        }
    });
    
    drake.on('drop', function() {
        // 获取新顺序
        var order = [];
        document.querySelectorAll('.menu-item').forEach(function(item, index) {
            order.push({
                id: item.dataset.id,
                sort: index
            });
        });
        
        // 保存到服务器
        $.post('/menu/sort', {order: order});
    });
});
```

### 2. 图片排序上传

```javascript
Wind.use('dragula', function() {
    dragula([document.getElementById('image-list')], {
        direction: 'horizontal'
    }).on('drop', function() {
        updateImageOrder();
    });
});
```

### 3. 表单字段排序

```javascript
Wind.use('dragula', function() {
    dragula([document.getElementById('form-fields')], {
        moves: function(el, container, handle) {
            return handle.classList.contains('field-drag-handle');
        }
    });
});
```

## 方法

```javascript
Wind.use('dragula', function() {
    var drake = dragula([document.getElementById('list')]);
    
    // 销毁实例
    drake.destroy();
    
    // 添加容器
    drake.containers.push(document.getElementById('new-list'));
    
    // 取消拖拽操作
    drake.cancel();
    
    // 移除元素
    drake.remove();
    
    // 开始拖拽
    drake.start(item);
    
    // 结束拖拽
    drake.end();
});
```

## 浏览器兼容性

- Chrome 所有版本
- Firefox 所有版本
- Safari 所有版本
- Edge 所有版本
- IE 9+

## 更多文档

- 官方文档: https://github.com/bevacqua/dragula
- 在线示例: https://bevacqua.github.io/dragula/
