List Sorting with HTML5 Drag'n'Drop - Drop Above or Below Depending on Mouse

前端 未结 1 1164
一向
一向 2021-02-04 07:32

Background

I am working on a sortable list, to avoid having to manually type in sorting order numbers in a database. It works via HTML5\'s drag\'n\'drop functionality,

相关标签:
1条回答
  • 2021-02-04 08:23

    Answer

    So in a twist of fate, a comment response on another question pointed me to the answer here. wolf-war deserves credit here for pointing me to the right event and method.

    Anyway, on to the answer. The solution lies in using the dragover event, rather than using the dragenter event. dragover keeps firing as long as you are hovering.

    Code Changes From Question Code

    We get rid of the dragenter code:

    document.addEventListener('dragenter', function(event) {
        event.target.style['border-bottom'] = 'solid 4px blue';
    });
    

    Replace it with:

    document.addEventListener('dragover', function(event) {
        event.preventDefault();
        var bounding = event.target.getBoundingClientRect()
        var offset = bounding.y + (bounding.height/2);
        if ( event.clientY - offset > 0 ) {
            event.target.style['border-bottom'] = 'solid 4px blue';
            event.target.style['border-top'] = '';
        } else {
            event.target.style['border-top'] = 'solid 4px blue';
            event.target.style['border-bottom'] = '';
        }
    });
    

    Then in the drop section, we check to see which border the drop target has, and use that to insert the dragged content either above or below.

    Full Working Code:

    var dragging = null;
    
    document.addEventListener('dragstart', function(event) {
        var target = getLI( event.target );
        dragging = target;
        event.dataTransfer.setData('text/plain', null);
        event.dataTransfer.setDragImage(self.dragging,0,0);
    });
    
    document.addEventListener('dragover', function(event) {
        event.preventDefault();
        var target = getLI( event.target );
        var bounding = target.getBoundingClientRect()
        var offset = bounding.y + (bounding.height/2);
        if ( event.clientY - offset > 0 ) {
           	target.style['border-bottom'] = 'solid 4px blue';
            target.style['border-top'] = '';
        } else {
            target.style['border-top'] = 'solid 4px blue';
            target.style['border-bottom'] = '';
        }
    });
    
    document.addEventListener('dragleave', function(event) {
        var target = getLI( event.target );
        target.style['border-bottom'] = '';
        target.style['border-top'] = '';
    });
    
    document.addEventListener('drop', function(event) {
        event.preventDefault();
        var target = getLI( event.target );
        if ( target.style['border-bottom'] !== '' ) {
            target.style['border-bottom'] = '';
            target.parentNode.insertBefore(dragging, event.target.nextSibling);
        } else {
            target.style['border-top'] = '';
            target.parentNode.insertBefore(dragging, event.target);
        }
    });
    
    function getLI( target ) {
        while ( target.nodeName.toLowerCase() != 'li' && target.nodeName.toLowerCase() != 'body' ) {
            target = target.parentNode;
        }
        if ( target.nodeName.toLowerCase() == 'body' ) {
            return false;
        } else {
            return target;
        }
    }
    ul {
      margin:0;
      padding:0
    }
    li {
      cursor:move;
      display:block;
      padding:20px 10px;
      background:white;
      border-bottom:solid 1px gray;
    }
    <ul>
        <li draggable="true">List Item 1</li>
        <li draggable="true">List Item 2</li>
        <li draggable="true">List Item 3</li>
        <li draggable="true">List Item 4</li>
        <li draggable="true">List Item 5</li>
        <li draggable="true">List Item 6</li>
        <li draggable="true">List Item 7</li>
        <li draggable="true">List Item 8</li>
        <li draggable="true">List Item 9</li>
        <li draggable="true">List Item 10</li>
    </ul>

    0 讨论(0)
提交回复
热议问题