What can I change in this jQuery plugin to include sorting on table rows which are hidden

58 views Asked by At

After mucking around with various tablesorting jQuery plugins, I came accross one which works perfectly in that it meets the following requirements :

  • Sorts dates properly
  • Sorts numbers properly
  • Sorts words of numbers (eg: One, Two, Three) properly
  • It sorts in a DOM aware manner. This means that if you update the contents of a table cell, when you click the table header to sort on that column it recognizes the new value instead of sorting on what it was when the page was first loaded. (this feature was especially difficult to find as the popular tablesorters don't recognize changes at runtime when sorting)

The only issue I am having, is that it seems to only sort the rows which are visible. I would like for it to sort the entire table, not just the visible ones, while keeping all the above features in tact (esp the DOM aware portion) as this will be used on a table where the data may be updated by the user, and subsequently sorted.

I will be open-sourcing this jQuery plugin so I have no issues sharing the code here. The jQuery code here is mine, and the plugin I am using for the sort portion is here: http://www.kryogenix.org/code/browser/sorttable.

The following code demonstrates the issue. You can click on any of the cells to get an edit inline and can make changes to the DOM portion this way.

(function($) {
  $.fn.tables = function(options) {

    var settings = $.extend({
      page: 0,
      pageCount: 10,
    }, options);

    $thead = this.find('thead');
    $tbody = this.find('tbody');
    $tfoot = this.find('tfoot > tr > td').attr('colspan', $tbody.find('tr')[0].cells.length);

    var align = '';
    for (var content_align = 0; content_align < $thead.find('tr')[0].cells.length; content_align++) {
      align = $($thead.find('tr')[0].cells[content_align]).attr('data-align');
      if (align === undefined) {

      } else {
        $tbody.find('tr > td:nth-child(' + (content_align + 1) + ')').each(function() {
          $(this).addClass(align);
        });
      }
    }

    var numRows = $tbody.find('tr').length;
    var numPages = Math.ceil(numRows / settings.pageCount);

    this.bind('repaginate', function() {
      $tbody.find('tr').removeClass('visible').slice(settings.page * settings.pageCount, (settings.page + 1) * settings.pageCount).addClass('visible');
    });
    this.trigger('repaginate');

    $tfoot.find('td').html('');
    for (var page = 0; page < numPages; page++) {
      $('<a></a>').text(page + 1).bind('click', {
        newPage: page
      }, function(event) {
        settings.page = event.data['newPage'];
        $(this).trigger('repaginate');
        $(this).addClass('active').siblings().removeClass('active');
        if (options.pageChanged !== undefined) {
          options.pageChanged(this);
        }
      }).appendTo($tfoot); //.addClass('clickable');
    }

    $tbody.find('td').click(function() {
      if (options.cellClick !== undefined) {
        if ($(this).hasClass('editing') == false) {
          var col = $(this).parent().children().index($(this));
          var row = $(this).parent().parent().children().index($(this).parent())

          var type = $($thead.find('tr')[0].cells[col]).attr('data-type');
          var typevalues = $($thead.find('tr')[0].cells[col]).attr('data-values');
          var align = $($thead.find('tr')[0].cells[col]).attr('data-align');

          console.log(type);

          $(this).addClass('editing');
          options.cellClick(this, true, col, row);
          switch (type) {
            case 'text':
              $(this).html('<input type="text" value="' + $(this).text() + '">');
              $(this).find('input').focus().blur(function() {
                $(this).parent().removeClass('editing');
                options.cellClick($(this).parent(), false, col, row);
                $(this).parent().html($(this).prop('value'));
              });
              break;
            case 'textarea':
              _html = $(this).html();
              $(this).html('<textarea type="text">' + $(this).html().replace(/\<br\\?>/g, "\n") + '</textarea>');
              $(this).find('textarea').focus().blur(function() {
                $(this).parent().removeClass('editing');
                options.cellClick($(this).parent(), false, col, row);
                $(this).parent().html($(this).prop('value').replace(/\n/g, "<br>"));
              });
              break;
            case 'number':
              $(this).html('<input type="number" value="' + $(this).text() + '">');
              $(this).find('input').focus().blur(function() {
                $(this).parent().removeClass('editing');
                options.cellClick($(this).parent(), false, col, row);
                $(this).parent().html($(this).prop('value'));
              });
              break;
            case 'currency':
              $(this).html('<input type="currency" value="' + $(this).text() + '">');
              $(this).find('input').focus().blur(function() {
                $(this).parent().removeClass('editing');
                options.cellClick($(this).parent(), false, col, row);
                $(this).parent().html($(this).prop('value'));
              });
              break;
            case 'select':
              if (typevalues === undefined) {
                console.log('You must define both \'data-type\' and \'data-values\' for select elements. \'data-values\' should be a comma delimited array of the items to be displayed in the drop-down');
              } else {
                typevalues = typevalues.split(',');
                _html = '<select>';
                for (var i = 0; i < typevalues.length; i++) {
                  if (typevalues[i] == $(this).text()) {
                    _html = _html + '<option value="' + typevalues[i] + '" selected>' + typevalues[i] + '</option>';
                  } else {
                    _html = _html + '<option value="' + typevalues[i] + '">' + typevalues[i] + '</option>';
                  }
                }
                _html = _html + '</select>';
                $(this).html(_html);
                $(this).find('select').focus().change(function() {
                  $(this).parent().removeClass('editing');
                  options.cellClick($(this).parent(), false, col, row);
                  $(this).parent().html($(this).prop('value'));
                }).blur(function() {
                  $(this).parent().removeClass('editing');
                  options.cellClick($(this).parent(), false, col, row);
                  $(this).parent().html($(this).prop('value'));
                });
              }
              break;
            case 'checkbox':
              if (typevalues === undefined) {
                $($thead.find('tr')[0].cells[col]).attr('data-values', 'T,F');
                typevalues = $($thead.find('tr')[0].cells[col]).attr('data-values');
                console.log('You can define the \'data-values\' parameter for checkbox elements. \'data-values\' should be a comma delimited array of two items. The first item is the \'checked\' value, and the second item is the \'unchecked\' value. Defaults to \'T,F\'');
              }
              typevalues = typevalues.split(',');
              _html = '';
              if (typevalues[0] == $(this).text()) {
                _html = '<input type="checkbox" checked="checked">';
              } else {
                _html = '<input type="checkbox">';
              }
              $(this).html(_html);
              $(this).find('input').focus().click(function() {
                  $(this).parent().removeClass('editing');
                  options.cellClick($(this).parent(), false, col, row);
                  typevalues = $($thead.find('tr')[0].cells[col]).attr('data-values').split(',');
                  if (this.checked) {
                    $(this).parent().html(typevalues[0]);
                  } else {
                    $(this).parent().html(typevalues[1]);
                  }
                })
                .blur(function() {
                  $(this).parent().removeClass('editing');
                  options.cellClick($(this).parent(), false, col, row);
                  typevalues = $($thead.find('tr')[0].cells[col]).attr('data-values').split(',');
                  if (this.checked) {
                    $(this).parent().html(typevalues[0]);
                  } else {
                    $(this).parent().html(typevalues[1]);
                  }
                });
              break;
          }
        }
      }
    })

    this.addClass('sortable');

    $tfoot.find('a:first-child').addClass('active');

    return this;
  };
}(jQuery));
:root {
  --tables-even-color: #CDEDF7;
  --tables-odd-color: #90C3D4;
}
.tables {
  border-collapse: collapse;
}
/* Header */

.tables thead > tr {
  background: #3E8096;
  color: #CDEDF7;
}
.tables thead > tr > td {
  padding: 4px;
  padding-left: 8px;
  padding-right: 10px;
}
.tables thead > tr > td:hover {
  background: #CDEDF7 !important;
  color: #3E8096 !important;
}
/* Footer */

.tables tfoot > tr {
  background: #3E8096;
  color: #CDEDF7;
}
.tables tfoot > tr > td > a {
  border: 1px solid #3E8096;
  padding: 4px;
  cursor: pointer;
  display: inline-block;
}
.tables tfoot > tr > td > a:hover {
  border: 1px solid #CDEDF7;
}
.tables tfoot > tr > td > a.active {
  background: #CDEDF7;
  color: #3E8096;
}
/* Rows */

.tables tbody > tr:nth-child(even) {
  background: #CDEDF7;
  color: #90C3D4;
}
.tables tbody > tr:nth-child(even):hover {
  background: #18EAF5;
  color: #90C3D4;
}
.tables tbody > tr:nth-child(odd) {
  background: #90C3D4;
  color: #CDEDF7;
}
.tables tbody > tr:nth-child(odd):hover {
  background: #18EAF5;
  color: #90C3D4;
}
.tables tbody > tr {
  display: none;
}
.tables tbody > tr.visible {
  display: table-row !important;
}
.tables tbody > tr > td {
  padding: 5px;
  cursor: default;
}
/* Cell Content */

.tables tbody > tr > td.center {
  text-align: center;
}
.tables tbody > tr > td.center > input {
  text-align: center;
}
.tables tbody > tr > td.center > textarea {
  text-align: center;
}
.tables tbody > tr > td.right {
  text-align: right;
}
.tables tbody > tr > td.right > input {
  text-align: right;
}
.tables tbody > tr > td.right > textarea {
  text-align: right;
}
<html>

<head>
  <script src="https://code.jquery.com/jquery-2.2.0.min.js" type="text/javascript"></script>
  <script src="http://www.kryogenix.org/code/browser/sorttable/sorttable.js" type="text/javascript"></script>
  <link rel="stylesheet" type="text/css" href="jquery.tables.css">
  <script type="text/javascript">
    $(document).ready(function() {
      $table = $('.tables').tables({
        pageChanged: function(item) {
          console.log($(item).text());
        },
        cellClick: function(item, focused, column, row) {
          console.log('COLUMN: ' + column + ', ROW: ' + row);
        }
      });

    })
  </script>

</head>

<body>
  <table class="tables">
    <thead>
      <tr>
        <td data-type="textarea">Column 1</td>
        <td data-type="checkbox" data-align="center">Column 2</td>
        <td data-type="select" data-values="Apples,Oranges,Bananas">Column 3</td>
      </tr>
    </thead>

    <tbody>
      <tr>
        <td>aa</td>
        <td>ab</td>
        <td>Apples</td>
      </tr>

      <tr>
        <td>ac</td>
        <td>ad</td>
        <td>Oranges</td>
      </tr>

      <tr>
        <td>bb
          <br>ccc<b>newline</b>
        </td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>aaa</td>
        <td>T</td>
        <td>Apples</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>
      <tr>
        <td>bbccc</td>
        <td>F</td>
        <td>Oranges</td>
      </tr>

    </tbody>

    <tfoot>
      <tr>
        <td colspan="1"></td>
      </tr>
    </tfoot>
  </table>
</body>

</html>

Bonus: If you can figure out how to correct the css alternating row colors after sort, that would be awesome (without adding something to each TD... basically, just 'refresh' the css somehow)

1

There are 1 answers

0
Kraang Prime On

Figured out how to do the sort in DOM while being aware of any changes made to underlying elements, however I still am unable to revert the sorting back to the original order (unsorted).

Following is what I have come up with so far:

(function ( $ ) {
 $.fn.tables = function( options ) {
  
  var settings = $.extend({
   page: 0,
   pageCount: 10,
  }, options );

  this.addClass('sortable');
  
  $thead = this.find('thead');
  $tbody = this.find('tbody');
  $tfoot = this.find('tfoot > tr > td').attr('colspan', $tbody.find('tr')[0].cells.length);

  var align = '';
  for(var content_align = 0; content_align < $thead.find('tr')[0].cells.length; content_align++) {
   align = $($thead.find('tr')[0].cells[content_align]).attr('data-align');
   if(align === undefined) {

   } else {
    $tbody.find('tr > td:nth-child(' + (content_align + 1) + ')').each(function(){
     $(this).addClass(align);
    });
   }
  }
  
  var numRows = $tbody.find('tr').length;
  var numPages = Math.ceil(numRows / settings.pageCount);

  this.bind('repaginate', function() {
   $tbody.find('tr').removeClass('visible').slice(settings.page * settings.pageCount, (settings.page + 1) * settings.pageCount).addClass('visible');
  });
  this.trigger('repaginate');

  $thead.find('tr > td').click(function() {
   var rows = $tbody.find('tr').get();
   var col = $(this).parent().children().index($(this));
   col++;

   if($(this).hasClass('desc')) {
    $(this).removeClass('desc');
   }
   
   if($(this).hasClass('asc')) {
    $(this).removeClass('asc').addClass('desc');
    rows.sort(function(a, b) {
      alert(col);
      var A = $(a).children('td:nth-child(' + col + ')').eq(0).text().toUpperCase();
      var B = $(b).children('td:nth-child(' + col + ')').eq(0).text().toUpperCase();

      if($.isNumeric(A) || $.isNumeric(B)) { A = parseInt(A); B = parseInt(B); }

      if(A > B) { return -1; }
      if(A < B) { return 1; }
      return 0;
    });
   } else {
    $(this).addClass('asc');
    rows.sort(function(a, b) {
      alert(col);
      var A = $(a).children('td:nth-child(' + col + ')').eq(0).text().toUpperCase();
      var B = $(b).children('td:nth-child(' + col + ')').eq(0).text().toUpperCase();

      if($.isNumeric(A) || $.isNumeric(B)) { A = parseInt(A); B = parseInt(B); }

      if(A < B) { return -1; }
      if(A > B) { return 1; }
      return 0;
    });
   }

   $(this).siblings().removeClass('asc').removeClass('desc');
   
   $.each(rows, function(index, row) {
     $tbody.append(row);
   });
   
   $tbody.find('tr').removeClass('visible').slice(settings.page * settings.pageCount, (settings.page + 1) * settings.pageCount).addClass('visible');
   
  });
  
  
  $tfoot.find('td').html('');
  for (var page = 0; page < numPages; page++) {
   $('<a></a>').text(page + 1).bind('click', {
    newPage: page
   }, function(event) {
    settings.page = event.data['newPage'];
    $(this).trigger('repaginate');
    $(this).addClass('active').siblings().removeClass('active');
    if(options.pageChanged !== undefined) {
     options.pageChanged(this);
    }
   }).appendTo($tfoot); //.addClass('clickable');
  }
  
  $tbody.find('td').click(function() {
   if(options.cellClick !== undefined) {
    if($(this).hasClass('editing') == false) {
     var col = $(this).parent().children().index($(this));
     var row = $(this).parent().parent().children().index($(this).parent())

     var type = $($thead.find('tr')[0].cells[col]).attr('data-type');
     var typevalues = $($thead.find('tr')[0].cells[col]).attr('data-values');
     var align = $($thead.find('tr')[0].cells[col]).attr('data-align');
     
     console.log(type);
     
     $(this).addClass('editing');
     options.cellClick(this, true, col, row);
     switch(type) {
      case 'text':
       $(this).html( '<input type="text" value="' + $(this).text() + '">' );
       $(this).find('input').focus().blur(function(){
        $(this).parent().removeClass('editing');
        options.cellClick($(this).parent(), false, col, row);
        $(this).parent().html( $(this).prop('value') );
       });
       break;
      case 'textarea':
       _html = $(this).html();
       $(this).html( '<textarea type="text">' + $(this).html().replace(/\<br\\?>/g, "\n") + '</textarea>' );
       $(this).find('textarea').focus().blur(function(){
        $(this).parent().removeClass('editing');
        options.cellClick($(this).parent(), false, col, row);
        $(this).parent().html( $(this).prop('value').replace(/\n/g,"<br>") );
       });
       break;      
      case 'number':
       $(this).html( '<input type="number" value="' + $(this).text() + '">' );
       $(this).find('input').focus().blur(function(){
        $(this).parent().removeClass('editing');
        options.cellClick($(this).parent(), false, col, row);
        $(this).parent().html( $(this).prop('value') );
       });
       break;
      case 'currency':
       $(this).html( '<input type="currency" value="' + $(this).text() + '">' );
       $(this).find('input').focus().blur(function(){
        $(this).parent().removeClass('editing');
        options.cellClick($(this).parent(), false, col, row);
        $(this).parent().html( $(this).prop('value') );
       });
       break;
      case 'select':
       if(typevalues === undefined) {
        console.log('You must define both \'data-type\' and \'data-values\' for select elements. \'data-values\' should be a comma delimited array of the items to be displayed in the drop-down');
       } else {
        typevalues = typevalues.split(',');
        _html = '<select>';
        for(var i = 0; i < typevalues.length; i++) {
         if(typevalues[i] == $(this).text()) {
          _html = _html + '<option value="' + typevalues[i] + '" selected>' + typevalues[i] + '</option>';
         } else {
          _html = _html + '<option value="' + typevalues[i] + '">' + typevalues[i] + '</option>';
         }
        }
        _html = _html + '</select>';
        $(this).html( _html );
        $(this).find('select').focus().change(function(){
         $(this).parent().removeClass('editing');
         options.cellClick($(this).parent(), false, col, row);
         $(this).parent().html( $(this).prop('value') );
        }).blur(function(){
         $(this).parent().removeClass('editing');
         options.cellClick($(this).parent(), false, col, row);
         $(this).parent().html( $(this).prop('value') );
        });
       }
       break;
      case 'checkbox':
       if(typevalues === undefined) {
        $($thead.find('tr')[0].cells[col]).attr('data-values', 'T,F');
        typevalues = $($thead.find('tr')[0].cells[col]).attr('data-values');
        console.log('You can define the \'data-values\' parameter for checkbox elements. \'data-values\' should be a comma delimited array of two items. The first item is the \'checked\' value, and the second item is the \'unchecked\' value. Defaults to \'T,F\'');
       }
       typevalues = typevalues.split(',');
       _html = '';
       if(typevalues[0] == $(this).text()) {
        _html = '<input type="checkbox" checked="checked">';
       } else {
        _html = '<input type="checkbox">';
       }
       $(this).html( _html );
       $(this).find('input').focus().click(function(){
        $(this).parent().removeClass('editing');
        options.cellClick($(this).parent(), false, col, row);
        typevalues = $($thead.find('tr')[0].cells[col]).attr('data-values').split(',');
        if(this.checked) {
         $(this).parent().html( typevalues[0] );
        } else {
         $(this).parent().html( typevalues[1] );
        }
       })
       .blur(function(){
        $(this).parent().removeClass('editing');
        options.cellClick($(this).parent(), false, col, row);
        typevalues = $($thead.find('tr')[0].cells[col]).attr('data-values').split(',');
        if(this.checked) {
         $(this).parent().html( typevalues[0] );
        } else {
         $(this).parent().html( typevalues[1] );
        }
       });
       break;
     }
    }
   }
  })
  
  $tfoot.find('a:first-child').addClass('active');
  
  return this;
 };
}(jQuery));
:root {
  --tables-even-color: #CDEDF7;
  --tables-odd-color: #90C3D4;
}

.tables {
 border-collapse: collapse;
}

/* Header */
.tables > thead  > tr {
 background: #3E8096;
 color: #CDEDF7;
}

.tables > thead > tr > td {
 padding: 4px;
 padding-left: 8px;
 padding-right: 10px;
}
.tables > thead > tr > td:hover{
 background: #CDEDF7 !important;
 color: #3E8096;
}

.tables > thead > tr > td::after {
 content: " \22EF";
}

.tables > thead > tr > td.asc::after {
 content: " \22F1";
}
.tables > thead > tr > td.desc::after {
 content: " \22F0";
}

/* Footer */
.tables > tfoot  > tr {
 background: #3E8096;
 color: #CDEDF7;
}

.tables > tfoot > tr > td > a {
 border: 1px solid #3E8096;
 padding: 4px;
 cursor: pointer;
 display: inline-block;
}

.tables > tfoot > tr > td > a:hover {
 border: 1px solid #CDEDF7;
}

.tables > tfoot > tr > td > a.active {
 background: #CDEDF7;
 color: #3E8096;
}

/* Rows */
.tables > tbody > tr:nth-child(even) {
 background: #CDEDF7;
 color: #90C3D4;
}
.tables > tbody > tr:nth-child(even):hover {
 background: #18EAF5;
 color: #90C3D4;
}

.tables > tbody > tr:nth-child(odd) {
 background: #90C3D4;
 color: #CDEDF7;
}
.tables > tbody > tr:nth-child(odd):hover {
 background: #18EAF5;
 color: #90C3D4;
}

.tables > tbody > tr {
 display: none;
}

.tables > tbody > tr.visible {
 display: table-row !important;
}

.tables > tbody > tr > td {
 padding: 5px;
 cursor: default;
}

/* Cell Content */
.tables > tbody > tr > td.center {
 text-align: center;
}
.tables > tbody > tr > td.center  > input {
 text-align: center;
}
.tables > tbody > tr > td.center  > textarea {
 text-align: center;
}


.tables > tbody > tr > td.right {
 text-align: right;
}
.tables > tbody > tr > td.right  > input {
 text-align: right;
}
.tables > tbody > tr > td.right  > textarea {
 text-align: right;
}
<html>
 <head>
  <script src="https://code.jquery.com/jquery-2.2.0.min.js" type="text/javascript"></script>

  <script type="text/javascript">
   $(document).ready(function() {
    $table = $('.tables').tables( {
     pageChanged: function(item) {
      //alert(e.text());
      console.log($(item).text());
     },
     cellClick: function(item, focused, column, row) {
      //console.log('COLUMN: ' + column + ', ROW: ' + row);
     }
    });
   })
  </script>
  
 </head>
 
 <body>
  <table class="tables">
   <thead>
    <tr>
     <td data-type="textarea">Column 1</td>
     <td data-type="checkbox" data-align="center">Column 2</td>
<!--     <td data-type="select" data-values="Apples,Oranges,Bananas">Column 2</td> -->
    </tr>
   </thead>
   
   <tbody>
    <tr>
     <td>aa</td>
     <td>ab</td>
    </tr>
 
    <tr>
     <td>ac</td>
     <td>ad</td>
    </tr>

    <tr><td>bb<br>ccc<b>hello</b></td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr><td>bb</td><td>bc</td></tr>
    <tr>
     <td>ac</td>
     <td>ad</td>
    </tr>    
   </tbody>
   
   <tfoot>
    <tr><td colspan="1"></td></tr>
   </tfoot>
  </table>
 </body>
</html>