Search code examples
jquery-uihtml-tablejquery-ui-sortable

Is there a way to use jQueryUI sortable on table with hidden columns


Recently I had to fix a strange behaviour on a table which use jQueryUI sortable on rows.

When I drag and move a row, the table is shrinked.

After some research, I was able te reproduce the behaviour on simple table :

jsFiddle link

#sort2 .hidden {
  display: none;
}
.fullsize {
  width: 100%;
}
.fix30 {
  width: 30px;
}
    
.fix100 {
  width: 100px;
}
    <html>
      <body>
      <table id="sort1" class="fullsize">
      <thead><tr>
        <th class="hidden">hide</th>
        <th class="hidden">hide</th>
        <th class="hidden">hide</th>
        <th class="fix30">Test1</th>
        <th>Test2</th>
        <th class="fix100">Test3</th>
        <th class="fix100">Test4</th>
        <th class="fix100">Test5</th>
      </tr></thead>
      <tbody>
        <tr>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td>1</td>
          <td>2</td>
          <td>3</td>
          <td>4</td>
          <td>5</td>
        </tr>
        <tr>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td>1</td>
          <td>2</td>
          <td>3</td>
          <td>4</td>
          <td>5</td>
        </tr>
        <tr>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td>1</td>
          <td>2</td>
          <td>3</td>
          <td>4</td>
          <td>5</td>
        </tr>
      </tbody>
      </table>
      
      <hr />
      
        <table id="sort2" class="fullsize">
      <thead><tr>
        <th class="hidden">hide</th>
        <th class="hidden">hide</th>
        <th class="hidden">hide</th>
        <th class="fix30">Test1</th>
        <th>Test2</th>
        <th class="fix100">Test3</th>
        <th class="fix100">Test4</th>
        <th class="fix100">Test5</th>
      </tr></thead>
      <tbody>
        <tr>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td>1</td>
          <td>2</td>
          <td>3</td>
          <td>4</td>
          <td>5</td>
        </tr>
        <tr>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td>1</td>
          <td>2</td>
          <td>3</td>
          <td>4</td>
          <td>5</td>
        </tr>
        <tr>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td class="hidden">hide</td>
          <td>1</td>
          <td>2</td>
          <td>3</td>
          <td>4</td>
          <td>5</td>
        </tr>
      </tbody>
      </table>
      
      </body>
    </html>
    var fixHelperModified = function(e, tr) {
        var $originals = tr.children();
        var $helper = tr.clone();
        $helper.children().each(function(index)
        {
          $(this).width($originals.eq(index).width())
        });
        return $helper;
    };
    
    $("tbody").sortable({
        helper: fixHelperModified 
        
    }).disableSelection();

My guess, when some columns are hidden, the navigator thinks there is more cols in the row compared to the one in the header.

My question : does anyone had the same issue and how to fix it ?


Solution

  • I was able to fix it by modifying you JS a bit, here is what I did:

    var fixHelperModified = function(e, tr) {
        var $originals = tr.children();
        var $helper = tr.clone();
        $helper.children().each(function(index)
        {
          $(this).outerWidth($originals.eq(index).outerWidth())
        });
        
        return $helper;
    };
    
    $("tbody").sortable({
      start: function(event, ui) {
        ui.helper.css('display', 'table')
      },
      stop: function(event, ui) {
        ui.item.css('display', '')
      },
    
        helper: fixHelperModified ,
        start: function(event, ui) {
        return ui.placeholder.children().each(function(index, child) {
          var source;
          source = ui.helper.children().eq(index);
          $(child).removeAttr('class').removeAttr('colspan');
          $(child).addClass(source.attr('class'));
          if (source.attr('colspan')) {
            return $(child).attr('colspan', source.attr('colspan'));
          }
        });
      }
        
    }).disableSelection();
    

    this problem happens because you have a hidden cell (and in the placeholder that the sortable creates for you there are 8 cells and non of them are hidden