title: How do I achieve jQuery DataTables colspan with striping after sorting?
body: <p><strong>Details follow, but the question is:</strong></p>
  
  <p>Is there a recommended best practice for using colspan / child rows with jQuery DataTables that is compatible with sorting and uses the same row coloring as the parent row?</p>
  
  <p><strong>Constraint (non negotiable):</strong></p>
  
  <p>My client wants a sortable table that includes multiple child rows that span the entire table.</p>
  
  <p>Some of the <code>colspan</code> rows exist only if there is data to support them.</p>
  
  <p>(Thank you in advance for your comments such as "colspan is horrible!" and "tables are gross!" but they are not helpful here.)</p>
  
  <p><strong>Attempted solution</strong></p>
  
  <p>I am using <a href="http://datatables.net" rel="nofollow">jQuery DataTables</a>, which is a rad library for progressive enhancement and scripted generation of HTML tables. Note that on this website Javascript is required, and I opted to create the table dynamically via Javascript rather than to render HTML <code>table</code> and enhance it.</p>
  
  <p>I was able to achieve the colspan effect by using the <code>row().child()</code> feature <a href="https://datatables.net/reference/api/row().child()" rel="nofollow">documented here</a>.</p>
  
  <p>The client requires the child  rows to have the same row striping color as the parent row, and to not look indented. DataTables assigns <code>odd</code> and <code>even</code> class names to each <code>TR</code> element (rather than using <code>nth-child()</code> CSS selectors), which is actually helpful in this case because I can use the same CSS class (<code>odd</code> or <code>even</code>) to style the child rows.</p>
  
  <p>However, I ran into a style problem when sorting because the child rows persist (are not regenerated) upon order operations. The result looks kinda bad, and requires an even number of rows to observe. (Run snippet, and click on the <code>Name</code> column to see the problem)</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var rows = [{
      ID: 1,
      Name: "Bob",
      Comments: "Bob is a hard worker"
  }, {
      ID: 2,
      Name: "Ann",
      Comments: "Ann takes a lot of smoke breaks"
  }, {
      ID: 3,
      Name: "Carl",
      Comments: "Carl needs some serious help"
  }, {
      ID: 4,
      Name: "Dave",
      Comments: "Dave is a rockstar",
      Extra: "Extra comments go here"
  }];
  
  var columns = [{
      name: 'id',
      data: 'ID',
      title: 'ID',
      orderable: true
  }, {
      name: 'name',
      data: 'Name',
      title: 'Name',
      orderable: true
  }];
  
  var tableOptions = {
      data: rows,
      columns: columns,
      info: false,
      paging: false,
      processing: false,
      searching: false,
  };
  
  var dataTable = $("#t").DataTable(tableOptions);
  
  var rows = dataTable.rows()[0];
  $.each(rows, function (idx, rowIdx) {
      var row = dataTable.row(rowIdx);
      var rowData = row.data();
      var cssClass = idx % 2 === 0 ? 'odd' : 'even'; // in DT-speak, first body row is even (not odd)
      var childRows = [];
      childRows.push(rowData.Comments);
      if (rowData.Extra) {
          childRows.push(rowData.Extra);
      }
      row.child(childRows, cssClass).show();
  });</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>table.dataTable thead tr {
      background-color: #ccc;
  }
  table.dataTable tbody tr.odd {
      background-color: #DAE4F0;
  }
  table.dataTable tbody tr.even {
      background-color: #eeeeee;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;
  &lt;link href="http://cdn.datatables.net/1.10.6/css/jquery.dataTables.css" rel="stylesheet"/&gt;
  &lt;script src="http://cdn.datatables.net/1.10.6/js/jquery.dataTables.min.js"&gt;&lt;/script&gt;
  &lt;table id='t'&gt;&lt;/table&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p><strong>Attempted solution, take 2</strong></p>
  
  <p>I added an event handler to fix the CSS classes on child rows when the <code>order</code> event fires on the DataTable using <code>dataTable.on('order.dt', function(){...})</code></p>
  
  <p>This works, but feels clunky, like I am abusing the <code>row().child()</code> concept maybe. Maybe not. Does anybody know of a better way? (Run snippet below for the "fixed" example).</p>
  
  <p><div class="snippet" data-lang="js" data-hide="false">
  <div class="snippet-code">
  <pre class="snippet-code-js lang-js prettyprint-override"><code>var rows = [{
      ID: 1,
      Name: "Bob",
      Comments: "Bob is a hard worker"
  }, {
      ID: 2,
      Name: "Ann",
      Comments: "Ann takes a lot of smoke breaks"
  }, {
      ID: 3,
      Name: "Carl",
      Comments: "Carl needs some serious help"
  }, {
      ID: 4,
      Name: "Dave",
      Comments: "Dave is a rockstar",
      Extra: "Extra comments go here"
  }];
  
  var columns = [{
      name: 'id',
      data: 'ID',
      title: 'ID',
      orderable: true
  }, {
      name: 'name',
      data: 'Name',
      title: 'Name',
      orderable: true
  }];
  
  var tableOptions = {
      data: rows,
      columns: columns,
      info: false,
      paging: false,
      processing: false,
      searching: false,
  };
  
  var dataTable = $("#t").DataTable(tableOptions);
  
  var rows = dataTable.rows()[0];
  $.each(rows, function (idx, rowIdx) {
      var row = dataTable.row(rowIdx);
      var rowData = row.data();
      var cssClass = idx % 2 === 0 ? 'odd' : 'even'; // in DT-speak, first body row is even (not odd)
      var childRows = [];
      childRows.push(rowData.Comments);
      if (rowData.Extra) {
          childRows.push(rowData.Extra);
      }
      row.child(childRows, cssClass).show();
  });
  
  dataTable.on('order.dt', function () {
  var rows = dataTable.rows()[0];
  $.each(rows, function (idx, rowIdx) {
      var row = dataTable.row(rowIdx);
      var childRows = row.child();
      childRows.removeClass("even odd");
      var cssClass = idx % 2 === 0 ? 'odd' : 'even'; // in DT-speak, first body row is even (not odd)
      childRows.addClass(cssClass);
  });
  });</code></pre>
  <pre class="snippet-code-css lang-css prettyprint-override"><code>table.dataTable thead tr {
      background-color: #ccc;
  }
  table.dataTable tbody tr.odd {
      background-color: #DAE4F0;
  }
  table.dataTable tbody tr.even {
      background-color: #eeeeee;
  }</code></pre>
  <pre class="snippet-code-html lang-html prettyprint-override"><code>&lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"&gt;&lt;/script&gt;
  &lt;link href="http://cdn.datatables.net/1.10.6/css/jquery.dataTables.css" rel="stylesheet"/&gt;
  &lt;script src="http://cdn.datatables.net/1.10.6/js/jquery.dataTables.min.js"&gt;&lt;/script&gt;
  &lt;table id='t'&gt;&lt;/table&gt;</code></pre>
  </div>
  </div>
  </p>
  
  <p>Thanks for reading! </p>
  
  <p>Am I making it harder than it is? Is this the only way to achieve my solution using jQuery DataTables? Is there perhaps a different library that is similar but has better out-of-box support for colspan?</p>
  
  <p>Here is same example in JSFiddle if you prefer: <a href="http://jsfiddle.net/h57vjof6/3/" rel="nofollow">http://jsfiddle.net/h57vjof6/3/</a></p>