Bachir Messaouri
Bachir Messaouri

Reputation: 784

jQueryUI sortable to drag & drop columns in a responsive table

I'm trying to learn the jQueryUI sortable feature in order to make it work on a responsive table I'm using on my webpage.

I made a jsfiddle to make some tests and I just can't figure out how to drag and drop columns (not only th's).

I suspected I should use the "connectWith" (or "items"?) option and connect all the td's that share the same id than the dragged th but I just don't succeed in doing that.

I'm not even sure that's what "connectWith" or "items" are made for actually but there is nothing else I can find in the documentation that seems to help me achieve a column drag & drop.

HTML:

<html>
    <body>
        <table>
           <thead>
                <tr>
                    <th>Col 1</th>
                    <th>Col 2</th>
                    <th>Col 3</th> 
                    <th>Col 4</th>
                </tr>
           </thead>
           <tbody>
                <tr>
                    <td>data 1</td>
                    <td>data 2</td>
                    <td>data 3</td>
                    <td>data 4</td>
                </tr>
                <tr>
                    <td>data 1</td>
                    <td>data 2</td>
                    <td>data 3</td>
                    <td>data 4</td>
                </tr>
            </tbody>
        </table>
    </body>
</html>

CSS:

*html, body {
    margin:0px;
    padding:0px;
    width:100%;
    height:100%;
}

 body:before{
     content: "";
     display: block;
     position: fixed;
     left: 0;
     top: 0;
     width: 100%;
     height: 100%;
 }

table{
    table-layout: fixed;
    margin: 0 auto;
    border-collapse: collapse;
    overflow: hidden;
    white-space: nowrap; 
    width:100%;
    color:#000;
    float:left;
}

tr{
    display:table-row;
    border: 1px solid black
}

th, td {
    border:1px solid #000;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    display: table-cell;
    text-align:center;
}

th{
    position: relative;
    background:#bbb;
}

jQuery:

$( function() {
    $('thead tr').sortable({
        start: function(e, ui)
        {
            var ind_th= ui.item.index();
            $('tbody td:nth-child('+(ind_th+1)+')').addClass('drg').css('color','red');
        },
        connectWith:".drg",
        stop: function(e, ui)
        {
            $('tbody td').removeClass('drg')
        }
    });
});

Thank you for your help.

Upvotes: 0

Views: 2274

Answers (1)

Twisty
Twisty

Reputation: 30893

It's not exactly pretty, yet it will do the job.

Working Example: https://jsfiddle.net/Twisty/q7oyh9mj/53/

JavaScript

$(function() {
  $('thead tr').sortable({
    containment: "parent",
    placeholder: "placeholder",
    opacity: 0.5,
    helper: "clone",
    axis: 'x',
    start: function(e, ui) {
      var ind_th = ui.item.index();
      $('tbody tr').each(function(ind, el) {
        $('td', el).eq(ind_th).addClass('drg').css('color', 'red');
      });
    },
    stop: function(e, ui) {
      var itInd = ui.item.index();
      $("tbody tr").each(function(ind, el) {
        var cell = $(".drg", el).detach();
        cell.insertBefore($("td", el).eq(itInd));
        cell.removeClass("drg").css("color", "black");
      });
    }
  });
  $('thead tr').disableSelection();
});

You can also create your own helper using function(event, element), yet it does not mesh well in stop or update.

So in start, I am adding the class drg to help identify the cells that will get moved. Once the stop is triggered, I use .detach() to remove them from the rows and then insertBefore() to place them back in the new position in the row based on the header index.

If you have a lot of data, I would advise looking at DataTables. I believe it offers this functionality.

Update

New Example: https://jsfiddle.net/Twisty/q7oyh9mj/72/

Two minor changes:

  1. Removed containment; this was preventing header from dragging beyond table borders and could not be placed in the first position.
  2. Add if for when drop point should be the last item

You can also adjust the tolerance options: https://jsfiddle.net/Twisty/q7oyh9mj/73/

Your choice on how to manage it.

Hope that helps.

Upvotes: 1

Related Questions