javascriptjquerydrag-and-dropdragula

How to change elements being copied on dragging using Dragula JS Plugin


I have a page which is similar to page builder template editor. Im using Dragula.JS as a plugin for drag and drop and used their method copy to copy elements from other container. This is what it looks like: enter image description here

The problem is when I drag from right side columns and put in the left box elements are copied exactly what it is on the right columns. This is my code:

<div id="2col" class="collapse column-choices">
 <a href="#" class="list-group-item">
        <div class="row">
          <div class="layoutBorder one-half"></div>
          <div class="layoutBorder one-half"></div>
        </div>
      </a>
      <a href="#" class="list-group-item">
        <div class="row">
          <div class="one-four layoutBorder"></div>
          <div class="three-four layoutBorder"></div>
        </div>
      </a>
      <a href="#" class="list-group-item">
        <div class="row">
          <div class="three-four layoutBorder"></div>
          <div class="one-four layoutBorder"></div>
        </div>
      </a>
    </div>

and my JS:

 //  the `templateContainer is the right box container`
 dragula([document.getElementById('2col'), document.getElementById('templateContainer')], {
copy: true,
   });

When I drag things to left box container this code will be put on:

<a href="#" class="list-group-item">
        <div class="row">
          <div class="layoutBorder one-half"></div>
          <div class="layoutBorder one-half"></div>
        </div>
      </a>

That is not I want. Question is How to copy elements from right container and when put to left box container elements are going to changed this my aim. I will change elements to:

<div class="element-to-paste">
      This thing will be copy on the left box. From Right.
    </div>

Please point me on other drag and drop plugin that can make my objective.


Solution

  • The way to do what your asking is to utilize the .drop Dragula callback.

    .on("drop", function(el, container, source) {}

    https://github.com/bevacqua/dragula#drakeon-events

    I've built one app where the 'drop zone' only had one column, so all elements would be lined-up vertically.. Similar to a sortable list. I used Angular for my project and my whole drop-zone used an ng-repeat directive, which is just a way to loop through an array of data. For an example it could be:

    var data = [
    {
      index: 1,
      type: 'image',
      data: 'image.jpg'
    },
    { 
      index: 2,
      type: 'textblock',
      data: 'lorem ipsum, blah blah'
    }]
    

    Then in your ng-repeat directive you can read the type property, and put in some HTML for it, like

    <div ng-if="mydata.type='image'">
      <img src='{{ mydata.data}}'>
    </div>
    
    <div ng-if="mydata.type='text'">
      <p>{{ mydata.data }}</p>
    </div>
    

    To get the correct order for your elements, you could use the ng-orderBy directive using the object's index.

    This way the dropping action is a facade. You actually remove the dragged element from the DOM and replace it with a new one.

    Dragula appends a .gu-transit class to elements while they're being dragged, so within your .drop callback you can loop through the DOM elements in your drop-container, find the .gu-transit, then you know the index that it's at, and can assign it a correct index property when you push it into your data array.

    I'm using Angular as an example because that's what I used, and I think using it or another framework substantially helped implement this functionality. I think it'd be a lot more difficult to do with straight jQuery.