Datatables with child rows and field conditions

This is really a nested table with shared headers, with a parent row that uses colspan for the wide message field, a child row for the wide pattern field, and another child row with the details. The next step is adding editing to the two child rows, but not the parent row.

HTML

<script src="https://code.jquery.com/jquery-1.9.1.js"></script>
<link rel="stylesheet" href="https://cdn.datatables.net/1.10.1/css/jquery.dataTables.css">
<script src="https://cdn.datatables.net/1.10.1/js/jquery.dataTables.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-mockjax/1.6.2/jquery.mockjax.min.js"></script>
<script src="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
        
<table id="messages" class="table compact row-border order-column" cellspacing="0" width="100%">
  <thead>
      <tr>
        <th>ID</th>
        <th>Group</th>
        <th>Key</th>
        <th>Message</th>
        <th>Category</th>
        <th>Type</th>
        <th>Action</th>
        <th>Object</th>
        <th>Context</th>
        <th>Status</th>
        <th>Reason</th>
      </tr>
  </thead>
</table>

JavaScript

var dataSet = [
    {
      "id": 9973,
      "vendorCategory": "Security-Auditing",
      "key": "4776",
      "message": "The domain controller attempted to validate the credentials for an account.\n\nAuthentication Package: %1\nLogon Account: %2\nSource Workstation: %3\nError Code: %4",
      "patterns": [
        {
          "id": 5237,
          "idx": 1,
          "category": "access",
          "type": "user",
          "action": "login",
          "status": "",
          "pattern": "(?<detail>The domain controller attempted to validate the credentials for an account)\\. Authentication Package: MICROSOFT_AUTHENTICATION_PACKAGE_V1_0 (?:Logon Account: (?<user>.+?)|Logon Account:) Source Workstation: (?:(?<source>.*?) )?Error Code: (?<result>0x[0-9A-Fa-f]+)"
        }
      ],
      "DT_RowId": "row_1"
    },
]

$.mockjax({
  url: 'data.json',
  responseTime: 10,
  responseText: {
    "data": dataSet
  }
});

var dt
/*
 * Join the sorted set of distinct field values from row using the provided separator
 */
function separatedFieldValues(row, field, sep) {
  return jQuery.unique(
    row.patterns.map(   function(o) {return o[field]})
    .filter(function(o) {return o != null})
    .sort()
  ).join(sep)
}
function nvl(x) {
  return x ? x : ''
}
function encoded(x) {
  if (x == null) {
    return '-'
  }
  return $('<div/>').text(x).html()
}
    
$(function () {
    dt = $('#messages').DataTable({
          "paging":         false,
          "multiSort":      true,
          "order":       [[1, 'asc'], [2, 'asc'], [3,'asc']],
          columns: [
              {data: "id", name:'vendorCategory','defaultContent': '-', visible:false},
              {data: "vendorCategory", name:'vendorCategory','defaultContent': '-'},
              {data: "key", 'defaultContent': ''},
              {data: "message", 'defaultContent': '', visible:false},
              // The rest of the columns are for the child rows
              {data: "category", 'defaultContent': ''},
         ...