0

I have a JQuery UI Sortable against a table. In Firefox, when you click and drag a row all the way to bottom Chrome will scroll the list for you, but in Firefox, it just drags off the screen into the nothingness below the last visible row.

This particular table with is within a div with a fixed height.

I am using JQuery 2.1.0 and JQuery UI 1.12.

Here is a code pen:- https://codepen.io/anon/pen/BWVpdE

Here is the HTML:-

<div class="scrollableContainer">

<table>
    <thead>
      <tr class="ui-state-default">
        <th colspan="4">Original</th>
        <th colspan="4">table heading</th>
        <th colspan="4">table heading</th>
        <th colspan="4">table heading</th>
        <th colspan="4">table heading</th>
        <th colspan="4">Current Pos</th>
      </tr>
    </thead>
    <tfoot>
      <tr class="ui-state-default">
        <th colspan="4">Original</th>
        <th colspan="4">table footer</th>
        <th colspan="4">table footer</th>
        <th colspan="4">table footer</th>
        <th colspan="4">table footer</th>
        <th colspan="4">Current Pos</th>
      </tr>
    </tfoot>
    <tbody>
    <tr class="ui-state-default">
      <th colspan="4">First Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">1</td>
    </tr>
    <tr class="ui-state-default even">
      <th colspan="4">Second Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">2</td>
    </tr>
    <tr class="ui-state-default">
      <th colspan="4">Third Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">3</td>
    </tr>
    <tr class="ui-state-default even">
      <th colspan="4">Fourth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">4</td>
    </tr>
    <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
          <tr class="ui-state-default">
      <th colspan="4">Fifth Row</th>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">data</td>
      <td colspan="4">5</td>
    </tr>
    </tbody>
</table>
</div>

Here is the SCSS:-

.scrollableContainer {
  padding-top:60px;
  height: 200px;
  position:relative;
}
.scrollArea {
  height:100%;
  overflow-x:hidden;
  overflow-y:auto;
}
table {
  border-collapse: collapse;
  overflow-x: hidden;
  overflow-y: auto;
}

td, th {
    background: #fff;
  border-width: 0;
    border-bottom: 1px solid #B8B8B8;
    font-weight: normal !important;
  padding: 15px;
    text-align: left;
    vertical-align: middle;
}

tr.even {
  td, th {
    background: #f1f1f1;
  }
}

thead, tfoot {
  text-transform: uppercase;

  th {
    background: #ccc;
  }
}

body {
  color: #111;
  font-size: 16px;
  font-family: sans-serif;
}

Here is the JS:-

$( "table tbody" ).sortable( {
    update: function( event, ui ) {
    $(this).children().each(function(index) {
            $(this).find('td').last().html(index + 1)
    });
  }
});
user1545858
  • 725
  • 4
  • 21

1 Answers1

0

OK, so I have found a solution using MutationObserver and getBoundingClientRect.

It is actually, not a great solution, but it works.

Here is the updated JS:-

var observer = null;
// Code taken from: http://stackoverflow.com/a/27263050/1545858
$.expr.filters.offscreen = function(el) {
  var rect = el.getBoundingClientRect();
  return (rect.x + rect.width) < 0 
             || (rect.y + rect.height) < 0
             || (rect.x > window.innerWidth || rect.y > window.innerHeight)
         ;
};
$( "table tbody" ).sortable( {
  start: function(event, ui) {
    observer = new MutationObserver(function(mutations) {
      window.requestAnimationFrame(function() {
        if (mutations[0].attributeName === 'style') { 
            if (ui.item.is(':offscreen')) {
                window.requestAnimationFrame(function () {
                   ui.item[0].scrollIntoView();            
                });

            }
        }
      });
    });
    observer.observe(ui.item[0], { attributes: true });
  },
  stop: function(event, ui) {
    observer.disconnect();
  },
    update: function( event, ui ) {
    $(this).children().each(function(index) {
            $(this).find('td').last().html(index + 1)
    });
  }
});

If anyone can let me know why I have to do this, it would be good. I have a feeling it is a bug in JQuery/JQuery UI/Firefox, but I don't know why.

Thanks.

user1545858
  • 725
  • 4
  • 21