Search code examples
javascriptjquerydatatablejquery-ui-sortable

Detect the table where the sortable item comes from


I have two tables where I can drag and drop items between tables and drag and drop items within the same table. I want to detect the table from which the item is coming.

Receive event only fires when items come from other table. I also need to detect when item comes only from the same table and once item is dropped. Any ideas? See demo

$("#peopleTable1 tbody").sortable({
  connectWith: "#peopleTable2 tbody",
  helper: function(e, tr) {
    const $originals = tr.children();
    const $helper = tr.clone();
    $helper.children().each(function(index) {
      // Set helper cell sizes to match the original sizes
      $(this).width($originals.eq(index).width());
    });
    return $helper;
  },
  start: function(e, ui) {},
  stop: function(e, ui) {},
  receive: function(e, ui) {
    console.log("Users2 -- Users1")
  },
  axis: "xy",
});

$("#peopleTable2 tbody").sortable({
  connectWith: "#peopleTable1 tbody",
  helper: function(e, tr) {
    const $originals = tr.children();
    const $helper = tr.clone();
    $helper.children().each(function(index) {
      // Set helper cell sizes to match the original sizes
      $(this).width($originals.eq(index).width());
    });
    return $helper;
  },
  start: function(e, ui) {},
  update: function(e, ui) {

  },
  receive: function(e, ui) {
    console.log("Users1 -- Users2")
  },
  axis: "xy",
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
<table id="peopleTable1">
  <thead class="thead-acu">
    <tr>
      <th class="col-30p">Name</th>
      <th class="col-35p">Age</th>
      <th class="col">Sex</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>Peter</td>
      <td>13</td>
      <td>Boy</td>
    </tr>
    <tr>
      <td>David</td>
      <td>20</td>
      <td>Boy</td>
    </tr>
    <tr>
      <td>Martha</td>
      <td>40</td>
      <td>Girl</td>
    </tr>
  </tbody>
</table>

<table id="peopleTable2">
  <thead class="thead-acu">
    <tr>
      <th class="col-30p">Name</th>
      <th class="col-35p">Age</th>
      <th class="col">Sex</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>John</td>
      <td>7</td>
      <td>Boy</td>
    </tr>
    <tr>
      <td>Laura</td>
      <td>27</td>
      <td>Girl</td>
    </tr>
    <tr>
      <td>ELisabeth</td>
      <td>73</td>
      <td>Girl</td>
    </tr>
  </tbody>
</table>


Solution

  • To achieve your goal you need to do multiple updates:

    a) Assign the common class to <tbody> of both tables and merge 2 sortable({...}) codes into one.

    b) For each row <tr> of the table add data-attribute(data-table-id) and provide the corresponding table id into it.

    c) Use the stop option to capture the event.

    d) Check the data attribute of the dropped/sorted ui.item element and compare it with the current table id. (using ui.item.closest('table')[0].id)

    e) If both are different then raise an alert from a different table and then change the data-attribute value. (put current table ID into it)

    f) If both are the same then alert from the same table and do nothing.

    Working snippet:

    $("#peopleTable1 > tbody,#peopleTable2 > tbody").sortable({
      connectWith: ".contentEditable",
      helper: function(e, tr) {
        const $originals = tr.children();
        const $helper = tr.clone();
        $helper.children().each(function(index) {
          $(this).width($originals.eq(index).width());
        });
        return $helper;
      },
      stop: function(event, ui) {
        if (ui.item.data('table-id') != ui.item.closest('table')[0].id) {
          alert('from different table');
          //this will change attribute value,but it will not reflect on browser
          ui.item.data('table-id', ui.item.closest('table')[0].id);
          //To show changed value on browser use below code,You can skip it as well if not required
          ui.item.attr('data-table-id', ui.item.closest('table')[0].id);
        } else {
          alert('from same table');
        }
      },
      axis: "xy",
    });
    table {
      margin: 10px;
      padding: 20px;
    }
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
    <script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"></script>
    <table id="peopleTable1">
      <thead class="thead-acu">
        <tr>
          <th class="col-30p">Name</th>
          <th class="col-35p">Age</th>
          <th class="col">Sex</th>
        </tr>
      </thead>
      <tbody class="contentEditable">
        <tr data-table-id="peopleTable1">
          <td>Peter</td>
          <td>13</td>
          <td>Boy</td>
        </tr>
        <tr data-table-id="peopleTable1">
          <td>David</td>
          <td>20</td>
          <td>Boy</td>
        </tr>
        <tr data-table-id="peopleTable1">
          <td>Martha</td>
          <td>40</td>
          <td>Girl</td>
        </tr>
      </tbody>
    </table>
    
    <table id="peopleTable2">
      <thead class="thead-acu">
        <tr>
          <th class="col-30p">Name</th>
          <th class="col-35p">Age</th>
          <th class="col">Sex</th>
        </tr>
      </thead>
      <tbody class="contentEditable">
        <tr data-table-id="peopleTable2">
          <td>John</td>
          <td>7</td>
          <td>Boy</td>
        </tr>
        <tr data-table-id="peopleTable2">
          <td>Laura</td>
          <td>27</td>
          <td>Girl</td>
        </tr>
        <tr data-table-id="peopleTable2">
          <td>ELisabeth</td>
          <td>73</td>
          <td>Girl</td>
        </tr>
      </tbody>
    </table>