Search code examples
javascripthtmldrag-and-drop

Update li attribute based on HTML5 and JS drag and drop


I have implemented HTML5 drag and drop functionality alongside JS for my one of projects. The issue that I'm currently facing is the following:

I need to update data-iterator when using drag and drop sorting of my LI elements. In other words, when I want to move Test 3 to the first position, data iterator should change from 3 to 0. I think you get the idea.

HTML

<ul id="_slides_slideshow_repeat">
    <li class="postbox" data-iterator="0" draggable="true">Test</li>
    <li class="postbox" data-iterator="1" draggable="true">Test 1</li>
    <li class="postbox" data-iterator="2" draggable="true">Test 2</li>
    <li class="postbox" data-iterator="3" draggable="true">Test 3</li>
</ul>

JS

    function sortable(rootEl, onUpdate) {
   var dragEl;

   // Making all siblings movable
   [].slice.call(rootEl.children).forEach(function (itemEl) {
       itemEl.draggable = true;
   });

   // Function responsible for sorting
   function _onDragOver(evt) {
       evt.preventDefault();
       evt.dataTransfer.dropEffect = 'move';

       var target = evt.target;
       if (target && target !== dragEl && target.nodeName == 'LI') {
           // Sorting
           rootEl.insertBefore(dragEl, target.nextSibling || target);
       }
   }

   // End of sorting
   function _onDragEnd(evt){
       evt.preventDefault();

       dragEl.classList.remove('ghost');
       rootEl.removeEventListener('dragover', _onDragOver, false);
       rootEl.removeEventListener('dragend', _onDragEnd, false);


       // Notification about the end of sorting
       onUpdate(dragEl);
   }

   // Sorting starts
   rootEl.addEventListener('dragstart', function (evt){
       dragEl = evt.target; // Remembering an element that will be moved

       // Limiting the movement type
       evt.dataTransfer.effectAllowed = 'move';
       evt.dataTransfer.setData('Text', dragEl.textContent);


       // Subscribing to the events at dnd
       rootEl.addEventListener('dragover', _onDragOver, false);
       rootEl.addEventListener('dragend', _onDragEnd, false);


       setTimeout(function () {
           // If this action is performed without setTimeout, then
           // the moved object will be of this class.
           dragEl.classList.add('ghost');
       }, 0)
   }, false);
}

// Using                    
sortable(document.getElementById('_slides_slideshow_repeat'), function (item) {
   console.log(item);
});

I'm not sure which JS line code I should modify, so any help would be highly appreciated.


Solution

  • You can modify your_onDragEnd function so that it updated the data-iterator attribute after every order change

        // End of sorting
        function _onDragEnd(evt){
            var iterator = 0;
            var items = rootEl.getElementsByTagName('li');
            
            evt.preventDefault();
    
            dragEl.classList.remove('ghost');
            rootEl.removeEventListener('dragover', _onDragOver, false);
            rootEl.removeEventListener('dragend', _onDragEnd, false);
    
            // Notification about the end of sorting
            
            for (var i = 0; i < items.length; i++) {
                items[i].setAttribute('data-iterator', i)
            }
            
            onUpdate(dragEl);
        }