HTML5, JS implement drag and drop sorting of elements

insert image description here
First introduce the drag attribute of html5, drag and drop (Drag and drop) is an integral part of the HTML5 standard. To enable dragging, just add draggable="true" to the element (except Safari 5.1.2).

Drag event
Events are divided into two categories, events on the currently dragged element, and events received by the position to be dropped.
1. Events that occur on dragged elements:

Event name Trigger timing Trigger times
dragstart Trigger once when dragging starts 1
drag Trigger repeatedly after dragging starts n
dragend Trigger once after dragging ends

2. Events that occur on the target element

Event name Trigger timing Trigger times
dragenter Trigger once when the dragged element enters the target 1
dragover Trigger repeatedly when the dragged element is within the range of the target element n
drop When the dragged element is released within the target element (on the premise that the dropover event is set ) 1

Information transfer

When dragging elements, you can set the passed information
event.dataTransfer.setData("te", "sss);
two parameters, the first parameter key, the second parameter value.
Note that only strings and urls can be passed, but When firefox uses text or Text as a key, it will open a new tab, so don't use them as a key.

Note: The drop will only be triggered after dragover is set! !

Here is a code example:


<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        *{
    
    
           list-style: none;
           margin: 0;
           padding: 0;
       }

       #container{
    
    
           width: 500px;
           margin: 100px auto;
       }

        .ele {
    
    
            width:100%;
            height: 40px;
            border: 1px solid #999;
            background: cadetblue;
            margin-top: 2px;
            border-radius: 10px;
            padding-left: 10px;
            color: white;
            cursor: move;
        }
    </style>
</head>
<body>
<ul id="container">
    <li class="ele" draggable="true">1</li>
    <li class="ele" draggable="true">2</li>
    <li class="ele" draggable="true">3</li>
    <li class="ele" draggable="true">4</li>
</ul>
<script>
    var node = document.querySelector("#container");
    var draging = null;
    //使用事件委托,将li的事件委托给ul
    node.ondragstart = function(event) {
    
    
        //console.log("start");
        //firefox设置了setData后元素才能拖动!!!!
        //event.target出发事件的元素
        event.dataTransfer.setData("te", event.target.innerText); //不能使用text,firefox会打开新tab
        //event.dataTransfer.setData("self", event.target);
        draging = event.target;
    }
    node.ondragover = function(event) {
    
    
        //console.log("onDrop over");
        //取消默认行为
        event.preventDefault();
        var target = event.target;
        //因为dragover会发生在ul上,所以要判断是不是li
        if (target.nodeName === "LI") {
    
    
            if (target !== draging) {
    
    
                //getBoundingClientRect()用于获取某个元素相对于视窗的位置集合
                var targetRect = target.getBoundingClientRect();
                var dragingRect = draging.getBoundingClientRect();
                if (target) {
    
    
                    if (target.animated) {
    
    
                        return;
                    }
                }
                if (_index(draging) < _index(target)) {
    
    
                    //nextSibling 属性可返回某个元素之后紧跟的节点(处于同一树层级中)。
                    target.parentNode.insertBefore(draging, target.nextSibling);
                } else {
    
    
                    target.parentNode.insertBefore(draging, target);
                }
                _animate(dragingRect, draging);
                _animate(targetRect, target);
            }
        }
    }
    //获取元素在父元素中的index
    function _index(el) {
    
    
        var index = 0;

        if (!el || !el.parentNode) {
    
    
            return -1;
        }
        //previousElementSibling属性返回指定元素的前一个兄弟元素(相同节点树层中的前一个元素节点)。
        while (el && (el = el.previousElementSibling)) {
    
    
            //console.log(el);
            index++;
        }

        return index;
    }

    function _animate(prevRect, target) {
    
    
        var ms = 300;

        if (ms) {
    
    
            var currentRect = target.getBoundingClientRect();
           //nodeType 属性返回以数字值返回指定节点的节点类型。1=元素节点  2=属性节点
            if (prevRect.nodeType === 1) {
    
    
                prevRect = prevRect.getBoundingClientRect();
            }
            _css(target, 'transition', 'none');
            _css(target, 'transform', 'translate3d(' +
                (prevRect.left - currentRect.left) + 'px,' +
                (prevRect.top - currentRect.top) + 'px,0)'
            );

            target.offsetWidth; // 触发重绘
            //放在timeout里面也可以
            // setTimeout(function() {
    
    
            //     _css(target, 'transition', 'all ' + ms + 'ms');
            //     _css(target, 'transform', 'translate3d(0,0,0)');
            // }, 0);
            _css(target, 'transition', 'all ' + ms + 'ms');
            _css(target, 'transform', 'translate3d(0,0,0)');

            clearTimeout(target.animated);
            target.animated = setTimeout(function() {
    
    
                _css(target, 'transition', '');
                _css(target, 'transform', '');
                target.animated = false;
            }, ms);
        }
    }
    //给元素添加style
    function _css(el, prop, val) {
    
    
        var style = el && el.style;

        if (style) {
    
    
            if (val === void 0) {
    
    
                //使用DefaultView属性可以指定打开窗体时所用的视图
                if (document.defaultView && document.defaultView.getComputedStyle) {
    
    
                    val = document.defaultView.getComputedStyle(el, '');
                } else if (el.currentStyle) {
    
    
                    val = el.currentStyle;
                }

                return prop === void 0 ? val : val[prop];
            } else {
    
    
                if (!(prop in style)) {
    
    
                    prop = '-webkit-' + prop;
                }

                style[prop] = val + (typeof val === 'string' ? '' : 'px');
            }
        }
    }
</script>
</body>
</html>

Guess you like

Origin blog.csdn.net/qq_37215621/article/details/131405196