HTML5 Drag and Drop not dropping in an empty list or at the end of a populated list

26 views Asked by At

I'm working on a drag and drop page with multiple lists on the page but have several issues getting it right. Issues as follows. 1/ I'm unable to drop an item into an empty list and 2/ I'm unable to add an item to the end of a list that does have items in it. Here's my current code:

    <div class="flex">
        <ul id="todo-1" class="container flex-auto p-4 mx-4 border-2 droppable" style="min-height: 300px;">
            <li draggable="true" class="m-2 cursor-pointer box">item 1/1</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 1/2</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 1/3</li>
        </ul>

        <ul id="todo-2" class="container flex-auto p-4 mx-4 border-2 droppable">
            <li draggable="true" class="m-2 cursor-pointer box">item 2/1</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 2/2</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 2/3</li>
        </ul>

        <ul id="todo-3" class="container flex-auto p-4 mx-4 border-2 droppable">
            <li draggable="true" class="m-2 cursor-pointer box">item 3/1</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 3/2</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 3/3</li>
        </ul>

        <p>alloc</p>
        <ul id="alloc-1" class="container flex-auto p-4 mx-24 border-2">
            <li draggable="true" class="m-2 cursor-pointer box">item 4/1</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 4/2</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 4/3</li>
        </ul>
    </div>

    <div class="flex">
        <ul id="done-1" class="container flex-auto p-4 mx-4 border-2 droppable" style="min-height: 300px;">
            <li draggable="true" class="m-2 cursor-pointer box">item 5/1</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 5/2</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 5/3</li>
        </ul>

        <ul id="done-2" class="container flex-auto p-4 mx-4 border-2 droppable">

        </ul>

        <ul id="done-3" class="container flex-auto p-4 mx-4 border-2 droppable">
            <li draggable="true" class="m-2 cursor-pointer box">item 7/1</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 7/2</li>
            <li draggable="true" class="m-2 cursor-pointer box">item 7/3</li>
        </ul>

        <p>alloc</p>
        <ul id="alloc-2" class="container flex-auto p-4 mx-24 border-2 droppable">

        </ul>
    </div>

    <script>
        document.addEventListener('DOMContentLoaded', (event) => {
            let dragSrcEl = null;
            let placeholder = null;

            function handleDragStart(e) {
                this.style.opacity = '0.4';
                dragSrcEl = this;
                e.dataTransfer.effectAllowed = 'move';
                e.dataTransfer.setData('text/html', this.outerHTML);

                // Create a placeholder element
                placeholder = document.createElement('li');
                placeholder.className = 'm-2 cursor-pointer box placeholder';
                placeholder.style.height = this.offsetHeight + 'px'; // Match the height
            }

            function handleDragEnd(e) {
                this.style.opacity = '1';

                if (placeholder && placeholder.parentNode) {
                    placeholder.parentNode.removeChild(placeholder);
                }

                items.forEach(function (item) {
                    item.classList.remove('over');
                });
            }

            function handleDragOver(e) {
                e.preventDefault();
                e.dataTransfer.dropEffect = 'move';
            }

            function handleDragEnter(e) {
                this.classList.add('over');

                if (placeholder) {
                    if (this.classList.contains('box')) {
                        this.parentNode.insertBefore(placeholder, this);
                    } else if (this.nodeName === 'UL') {
                        this.appendChild(placeholder);
                    }
                }
            }

            function handleDragLeave(e) {
                this.classList.remove('over');
            }

            function handleDrop(e) {
                e.stopPropagation();
                if (dragSrcEl !== this) {
                    if (placeholder && placeholder.parentNode) {
                        placeholder.parentNode.removeChild(placeholder);
                    }

                    if (e.target.classList.contains('box')) {
                        this.parentNode.insertBefore(dragSrcEl, this);
                    } else if (e.target.nodeName === 'UL' || e.target.classList.contains('droppable')) {
                        e.target.appendChild(dragSrcEl);
                    }
                }
            }

            let items = document.querySelectorAll('.container .box');
            items.forEach(function (item) {
                item.addEventListener('dragstart', handleDragStart);
                item.addEventListener('dragover', handleDragOver);
                item.addEventListener('dragenter', handleDragEnter);
                item.addEventListener('dragleave', handleDragLeave);
                item.addEventListener('dragend', handleDragEnd);
                item.addEventListener('drop', handleDrop);
            });
        });
    </script>

I have other things to do on this but getting this aspect to work will help me progress.

0

There are 0 answers