HTML5拖放的封装

本文原创,转载请注明出处

在项目中遇到了拖放的需求,之前虽然了解过,但是时间久了就忘记的差不多了。前些天进行简单实现和封装了一下,自己测试没有发现大问题,有个小问题就是拖放到的位置是以松开鼠标时指针的位置来判断插入位置,所以可能效果不甚完美,后面会继续优化。

自己封装的js放在了GitHub,欢迎提issues:链接
— 2019.6.10更新:解决复杂DOM结构的判断

具体的效果可以点击查看:示例

HTML结构示例
<div class="abs">
	<ul class="drop-div">
        <li id="1-1">
            <div>
                1-1
            </div>
            <p>1</p>
        </li>
        <li id="1-2">
            <div>
                1-2
            </div>
            <p>2</p>
        </li>
        <li>
            <div>
                1-3
            </div>
            <p>3</p>
        </li>
        <li>
            <div>
                1-4
            </div>
            <p>4</p>
        </li>
    </ul>
    <ul class="drop-div">
        <li>
            <div>
                2-1
            </div>
            <p>2-1</p>
        </li>
        <li>
            <div>
                2-2
            </div>
            <p>2-2</p>
        </li>
    </ul>
    <ul class="drop-div">
        <li>
            <div>
                3-1
            </div>
            <p> 3-1</p>
        </li>
        <li>
            <div>
                3-2
            </div>
            <p>3-2</p>
        </li>
        <li>
            <div>
                3-3
            </div>
            <p>3-3</p>
        </li>
    </ul>
</div>
源码
;(function (global, fn, plugin) {
   global[plugin] = fn.call(plugin);
})(window, function () {
    var _callback,
        _type = ['before', 'after', 'appendChild'],
        _isContinue,
        _CORE = {
            bindDrop: function(elem) {
                var parentElem = [].slice.call(document.querySelectorAll(elem));
                parentElem.forEach(function (p, index) {
                    var childElem = [].slice.call(p.children);
                    childElem.forEach(function (l, index1) {
                        l.setAttribute('draggable', true);
                        // 如果没有加入唯一ID,就新增
                        l.dataset.udropId = 'udrop-' + index + '-' + index1;
                        l.addEventListener('dragstart', _CORE.drag); // 拖拽开始
                        l.addEventListener('dragover', _CORE.dropOver); // 拖动
                        l.addEventListener('drop', _CORE.drop); // 放入
                    })
                    p.addEventListener('drop', _CORE.dropParent); // 放入到父级
                    p.addEventListener('dragover', _CORE.dropOver); // 拖动到父级
                });
            },
            drag: function(e) {
                e.dataTransfer.setData("Text", e.target.dataset.udropId);
            },
            drop: function(e) {
                e.preventDefault();
                e.stopPropagation();
                var l = e.dataTransfer.getData('Text');

                var dragElem = document.querySelector('[data-udrop-id="'+ l +'"]'); // 拖动的元素
                var dropElem = _CORE.getDropElem(e.target); // 拖入的元素
                var parentElem = dropElem.parentNode; // 父元素
                var dragIndex; // 获取元素下标

                // 判断是否有相同的父级元素
                var bool = true; // 是否跳出判断
                var copyDragElem = dragElem;
                var copyDropElem = dropElem;
                var copyParentElem = parentElem;
                for (;copyParentElem.parentNode;) {
                    for (;copyDragElem.parentNode.parentNode;) {
                        if (copyParentElem.parentNode.isEqualNode(copyDragElem.parentNode.parentNode)) {
                            dragIndex = _CORE.getIndex(parentElem, dropElem);
                            bool = false;
                            break;
                        } else {
                            copyDragElem = copyDragElem.parentNode;
                        }
                    }
                    if (!bool) {
                        break;
                    }
                    copyDropElem = copyParentElem;
                    copyParentElem = copyParentElem.parentNode;
                    copyDragElem = dragElem;
                }
                var moveY = e.pageY; // 放入时的位置
                var elemY = dropElem.getBoundingClientRect().top; // 放入到元素的位置
                var elemYCenter = dropElem.getBoundingClientRect().height; // 放入到元素的Y轴中心点
                // 判断放入位置,是在放入元素中心靠上,还是靠下,进行区分放入到前面还是后面
                if (moveY < elemY + elemYCenter / 2) { // 加入到上方
                    _callback(dragElem, dropElem, _type[0]);
                    if (!_isContinue) {
                        return false;
                    }
                    parentElem.insertBefore(dragElem, parentElem.childNodes[dragIndex]);
                } else { // 加入到下方
                    _callback(dragElem, dropElem, _type[1]);
                    if (!_isContinue) {
                        return false;
                    }
                    parentElem.insertBefore(dragElem, parentElem.childNodes[dragIndex + 1]);
                }
            },
            dropParent: function (e) {
                e.preventDefault();
                var l = e.dataTransfer.getData('Text'); // 获取拖动的元素id
                var dropElem = document.querySelector('[data-udrop-id="'+ l +'"]');
                _callback(dropElem, e.target, _type[2]);
                if (!_isContinue) {
                    return false;
                }
                e.target.appendChild(dropElem);
            },
            dropOver: function (e) {
                e.preventDefault();
            },
            // 获取相对于父级元素的位置
            getIndex: function (parent, child) {
                var index;
                for (var x = 0; x < parent.childNodes.length; x++) {
                    if (parent.childNodes[x].dataset) {
                        if (parent.childNodes[x].dataset.udropId === child.dataset.udropId) {
                            index = x;
                            break;
                        }
                    }
                }
                return index;
            },
            getDropElem: function (elem) {
                while (elem) {
                    if (elem.dataset.udropId) {
                        return elem;
                    } else {
                        elem = elem.parentNode;
                    }
                }
            }
        };

    return {
        init: function (elem, callback, isContinue) {
            _callback = callback;
            _isContinue = isContinue === undefined ? true : isContinue;
            _CORE.bindDrop(elem);
        }
    };
}, 'udrag');
调用方式
udrag.init('.drop-div li', function (dragElem, dropToElem, type) {
    // console.log(dragElem, dropToElem, type);
}, true);
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值