')[0];\n var __filter_div_textContent = __filter_div.textContent !== undefined;\n\n // Update the filtering data for each row if needed (by invalidation or first run)\n function _fnFilterData(settings) {\n var columns = settings.aoColumns;\n var data = settings.aoData;\n var column;\n var j, jen, filterData, cellData, row;\n var wasInvalidated = false;\n for (var rowIdx = 0; rowIdx < data.length; rowIdx++) {\n if (!data[rowIdx]) {\n continue;\n }\n row = data[rowIdx];\n if (!row._aFilterData) {\n filterData = [];\n for (j = 0, jen = columns.length; j < jen; j++) {\n column = columns[j];\n if (column.bSearchable) {\n cellData = _fnGetCellData(settings, rowIdx, j, 'filter');\n\n // Search in DataTables is string based\n if (cellData === null) {\n cellData = '';\n }\n if (typeof cellData !== 'string' && cellData.toString) {\n cellData = cellData.toString();\n }\n } else {\n cellData = '';\n }\n\n // If it looks like there is an HTML entity in the string,\n // attempt to decode it so sorting works as expected. Note that\n // we could use a single line of jQuery to do this, but the DOM\n // method used here is much faster https://jsperf.com/html-decode\n if (cellData.indexOf && cellData.indexOf('&') !== -1) {\n __filter_div.innerHTML = cellData;\n cellData = __filter_div_textContent ? __filter_div.textContent : __filter_div.innerText;\n }\n if (cellData.replace) {\n cellData = cellData.replace(/[\\r\\n\\u2028]/g, '');\n }\n filterData.push(cellData);\n }\n row._aFilterData = filterData;\n row._sFilterRow = filterData.join(' ');\n wasInvalidated = true;\n }\n }\n return wasInvalidated;\n }\n\n /**\n * Draw the table for the first time, adding all required features\n * @param {object} settings dataTables settings object\n * @memberof DataTable#oApi\n */\n function _fnInitialise(settings) {\n var i;\n var init = settings.oInit;\n var deferLoading = settings.deferLoading;\n var dataSrc = _fnDataSource(settings);\n\n // Ensure that the table data is fully initialised\n if (!settings.bInitialised) {\n setTimeout(function () {\n _fnInitialise(settings);\n }, 200);\n return;\n }\n\n // Build the header / footer for the table\n _fnBuildHead(settings, 'header');\n _fnBuildHead(settings, 'footer');\n\n // Load the table's state (if needed) and then render around it and draw\n _fnLoadState(settings, init, function () {\n // Then draw the header / footer\n _fnDrawHead(settings, settings.aoHeader);\n _fnDrawHead(settings, settings.aoFooter);\n\n // Cache the paging start point, as the first redraw will reset it\n var iAjaxStart = settings.iInitDisplayStart;\n\n // Local data load\n // Check if there is data passing into the constructor\n if (init.aaData) {\n for (i = 0; i < init.aaData.length; i++) {\n _fnAddData(settings, init.aaData[i]);\n }\n } else if (deferLoading || dataSrc == 'dom') {\n // Grab the data from the page\n _fnAddTr(settings, $(settings.nTBody).children('tr'));\n }\n\n // Filter not yet applied - copy the display master\n settings.aiDisplay = settings.aiDisplayMaster.slice();\n\n // Enable features\n _fnAddOptionsHtml(settings);\n _fnSortInit(settings);\n _colGroup(settings);\n\n /* Okay to show that something is going on now */\n _fnProcessingDisplay(settings, true);\n _fnCallbackFire(settings, null, 'preInit', [settings], true);\n\n // If there is default sorting required - let's do it. The sort function\n // will do the drawing for us. Otherwise we draw the table regardless of the\n // Ajax source - this allows the table to look initialised for Ajax sourcing\n // data (show 'loading' message possibly)\n _fnReDraw(settings);\n\n // Server-side processing init complete is done by _fnAjaxUpdateDraw\n if (dataSrc != 'ssp' || deferLoading) {\n // if there is an ajax source load the data\n if (dataSrc == 'ajax') {\n _fnBuildAjax(settings, {}, function (json) {\n var aData = _fnAjaxDataSrc(settings, json);\n\n // Got the data - add it to the table\n for (i = 0; i < aData.length; i++) {\n _fnAddData(settings, aData[i]);\n }\n\n // Reset the init display for cookie saving. We've already done\n // a filter, and therefore cleared it before. So we need to make\n // it appear 'fresh'\n settings.iInitDisplayStart = iAjaxStart;\n _fnReDraw(settings);\n _fnProcessingDisplay(settings, false);\n _fnInitComplete(settings);\n }, settings);\n } else {\n _fnInitComplete(settings);\n _fnProcessingDisplay(settings, false);\n }\n }\n });\n }\n\n /**\n * Draw the table for the first time, adding all required features\n * @param {object} settings dataTables settings object\n * @memberof DataTable#oApi\n */\n function _fnInitComplete(settings) {\n if (settings._bInitComplete) {\n return;\n }\n var args = [settings, settings.json];\n settings._bInitComplete = true;\n\n // Table is fully set up and we have data, so calculate the\n // column widths\n _fnAdjustColumnSizing(settings);\n _fnCallbackFire(settings, null, 'plugin-init', args, true);\n _fnCallbackFire(settings, 'aoInitComplete', 'init', args, true);\n }\n function _fnLengthChange(settings, val) {\n var len = parseInt(val, 10);\n settings._iDisplayLength = len;\n _fnLengthOverflow(settings);\n\n // Fire length change event\n _fnCallbackFire(settings, null, 'length', [settings, len]);\n }\n\n /**\n * Alter the display settings to change the page\n * @param {object} settings DataTables settings object\n * @param {string|int} action Paging action to take: \"first\", \"previous\",\n * \"next\" or \"last\" or page number to jump to (integer)\n * @param [bool] redraw Automatically draw the update or not\n * @returns {bool} true page has changed, false - no change\n * @memberof DataTable#oApi\n */\n function _fnPageChange(settings, action, redraw) {\n var start = settings._iDisplayStart,\n len = settings._iDisplayLength,\n records = settings.fnRecordsDisplay();\n if (records === 0 || len === -1) {\n start = 0;\n } else if (typeof action === \"number\") {\n start = action * len;\n if (start > records) {\n start = 0;\n }\n } else if (action == \"first\") {\n start = 0;\n } else if (action == \"previous\") {\n start = len >= 0 ? start - len : 0;\n if (start < 0) {\n start = 0;\n }\n } else if (action == \"next\") {\n if (start + len < records) {\n start += len;\n }\n } else if (action == \"last\") {\n start = Math.floor((records - 1) / len) * len;\n } else if (action === 'ellipsis') {\n return;\n } else {\n _fnLog(settings, 0, \"Unknown paging action: \" + action, 5);\n }\n var changed = settings._iDisplayStart !== start;\n settings._iDisplayStart = start;\n _fnCallbackFire(settings, null, changed ? 'page' : 'page-nc', [settings]);\n if (changed && redraw) {\n _fnDraw(settings);\n }\n return changed;\n }\n\n /**\n * Generate the node required for the processing node\n * @param {object} settings DataTables settings object\n */\n function _processingHtml(settings) {\n var table = settings.nTable;\n var scrolling = settings.oScroll.sX !== '' || settings.oScroll.sY !== '';\n if (settings.oFeatures.bProcessing) {\n var n = $('
', {\n 'id': settings.sTableId + '_processing',\n 'class': settings.oClasses.processing.container,\n 'role': 'status'\n }).html(settings.oLanguage.sProcessing).append('
');\n\n // Different positioning depending on if scrolling is enabled or not\n if (scrolling) {\n n.prependTo($('div.dt-scroll', settings.nTableWrapper));\n } else {\n n.insertBefore(table);\n }\n $(table).on('processing.dt.DT', function (e, s, show) {\n n.css('display', show ? 'block' : 'none');\n });\n }\n }\n\n /**\n * Display or hide the processing indicator\n * @param {object} settings DataTables settings object\n * @param {bool} show Show the processing indicator (true) or not (false)\n */\n function _fnProcessingDisplay(settings, show) {\n // Ignore cases when we are still redrawing\n if (settings.bDrawing && show === false) {\n return;\n }\n _fnCallbackFire(settings, null, 'processing', [settings, show]);\n }\n\n /**\n * Show the processing element if an action takes longer than a given time\n *\n * @param {*} settings DataTables settings object\n * @param {*} enable Do (true) or not (false) async processing (local feature enablement)\n * @param {*} run Function to run\n */\n function _fnProcessingRun(settings, enable, run) {\n if (!enable) {\n // Immediate execution, synchronous\n run();\n } else {\n _fnProcessingDisplay(settings, true);\n\n // Allow the processing display to show if needed\n setTimeout(function () {\n run();\n _fnProcessingDisplay(settings, false);\n }, 0);\n }\n }\n /**\n * Add any control elements for the table - specifically scrolling\n * @param {object} settings dataTables settings object\n * @returns {node} Node to add to the DOM\n * @memberof DataTable#oApi\n */\n function _fnFeatureHtmlTable(settings) {\n var table = $(settings.nTable);\n\n // Scrolling from here on in\n var scroll = settings.oScroll;\n if (scroll.sX === '' && scroll.sY === '') {\n return settings.nTable;\n }\n var scrollX = scroll.sX;\n var scrollY = scroll.sY;\n var classes = settings.oClasses.scrolling;\n var caption = settings.captionNode;\n var captionSide = caption ? caption._captionSide : null;\n var headerClone = $(table[0].cloneNode(false));\n var footerClone = $(table[0].cloneNode(false));\n var footer = table.children('tfoot');\n var _div = '
';\n var size = function (s) {\n return !s ? null : _fnStringToCss(s);\n };\n if (!footer.length) {\n footer = null;\n }\n\n /*\n * The HTML structure that we want to generate in this function is:\n * div - scroller\n * div - scroll head\n * div - scroll head inner\n * table - scroll head table\n * thead - thead\n * div - scroll body\n * table - table (master table)\n * thead - thead clone for sizing\n * tbody - tbody\n * div - scroll foot\n * div - scroll foot inner\n * table - scroll foot table\n * tfoot - tfoot\n */\n var scroller = $(_div, {\n 'class': classes.container\n }).append($(_div, {\n 'class': classes.header.self\n }).css({\n overflow: 'hidden',\n position: 'relative',\n border: 0,\n width: scrollX ? size(scrollX) : '100%'\n }).append($(_div, {\n 'class': classes.header.inner\n }).css({\n 'box-sizing': 'content-box',\n width: scroll.sXInner || '100%'\n }).append(headerClone.removeAttr('id').css('margin-left', 0).append(captionSide === 'top' ? caption : null).append(table.children('thead'))))).append($(_div, {\n 'class': classes.body\n }).css({\n position: 'relative',\n overflow: 'auto',\n width: size(scrollX)\n }).append(table));\n if (footer) {\n scroller.append($(_div, {\n 'class': classes.footer.self\n }).css({\n overflow: 'hidden',\n border: 0,\n width: scrollX ? size(scrollX) : '100%'\n }).append($(_div, {\n 'class': classes.footer.inner\n }).append(footerClone.removeAttr('id').css('margin-left', 0).append(captionSide === 'bottom' ? caption : null).append(table.children('tfoot')))));\n }\n var children = scroller.children();\n var scrollHead = children[0];\n var scrollBody = children[1];\n var scrollFoot = footer ? children[2] : null;\n\n // When the body is scrolled, then we also want to scroll the headers\n $(scrollBody).on('scroll.DT', function () {\n var scrollLeft = this.scrollLeft;\n scrollHead.scrollLeft = scrollLeft;\n if (footer) {\n scrollFoot.scrollLeft = scrollLeft;\n }\n });\n\n // When focus is put on the header cells, we might need to scroll the body\n $('th, td', scrollHead).on('focus', function () {\n var scrollLeft = scrollHead.scrollLeft;\n scrollBody.scrollLeft = scrollLeft;\n if (footer) {\n scrollBody.scrollLeft = scrollLeft;\n }\n });\n $(scrollBody).css('max-height', scrollY);\n if (!scroll.bCollapse) {\n $(scrollBody).css('height', scrollY);\n }\n settings.nScrollHead = scrollHead;\n settings.nScrollBody = scrollBody;\n settings.nScrollFoot = scrollFoot;\n\n // On redraw - align columns\n settings.aoDrawCallback.push(_fnScrollDraw);\n return scroller[0];\n }\n\n /**\n * Update the header, footer and body tables for resizing - i.e. column\n * alignment.\n *\n * Welcome to the most horrible function DataTables. The process that this\n * function follows is basically:\n * 1. Re-create the table inside the scrolling div\n * 2. Correct colgroup > col values if needed\n * 3. Copy colgroup > col over to header and footer\n * 4. Clean up\n *\n * @param {object} settings dataTables settings object\n * @memberof DataTable#oApi\n */\n function _fnScrollDraw(settings) {\n // Given that this is such a monster function, a lot of variables are use\n // to try and keep the minimised size as small as possible\n var scroll = settings.oScroll,\n barWidth = scroll.iBarWidth,\n divHeader = $(settings.nScrollHead),\n divHeaderInner = divHeader.children('div'),\n divHeaderTable = divHeaderInner.children('table'),\n divBodyEl = settings.nScrollBody,\n divBody = $(divBodyEl),\n divFooter = $(settings.nScrollFoot),\n divFooterInner = divFooter.children('div'),\n divFooterTable = divFooterInner.children('table'),\n header = $(settings.nTHead),\n table = $(settings.nTable),\n footer = settings.nTFoot && $('th, td', settings.nTFoot).length ? $(settings.nTFoot) : null,\n browser = settings.oBrowser,\n headerCopy,\n footerCopy;\n\n // If the scrollbar visibility has changed from the last draw, we need to\n // adjust the column sizes as the table width will have changed to account\n // for the scrollbar\n var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;\n if (settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined) {\n settings.scrollBarVis = scrollBarVis;\n _fnAdjustColumnSizing(settings);\n return; // adjust column sizing will call this function again\n } else {\n settings.scrollBarVis = scrollBarVis;\n }\n\n // 1. Re-create the table inside the scrolling div\n // Remove the old minimised thead and tfoot elements in the inner table\n table.children('thead, tfoot').remove();\n\n // Clone the current header and footer elements and then place it into the inner table\n headerCopy = header.clone().prependTo(table);\n headerCopy.find('th, td').removeAttr('tabindex');\n headerCopy.find('[id]').removeAttr('id');\n if (footer) {\n footerCopy = footer.clone().prependTo(table);\n footerCopy.find('[id]').removeAttr('id');\n }\n\n // 2. Correct colgroup > col values if needed\n // It is possible that the cell sizes are smaller than the content, so we need to\n // correct colgroup>col for such cases. This can happen if the auto width detection\n // uses a cell which has a longer string, but isn't the widest! For example \n // \"Chief Executive Officer (CEO)\" is the longest string in the demo, but\n // \"Systems Administrator\" is actually the widest string since it doesn't collapse.\n // Note the use of translating into a column index to get the `col` element. This\n // is because of Responsive which might remove `col` elements, knocking the alignment\n // of the indexes out.\n if (settings.aiDisplay.length) {\n // Get the column sizes from the first row in the table. This should really be a\n // [].find, but it wasn't supported in Chrome until Sept 2015, and DT has 10 year\n // browser support\n var firstTr = null;\n for (i = settings._iDisplayStart; i < settings.aiDisplay.length; i++) {\n var idx = settings.aiDisplay[i];\n var tr = settings.aoData[idx].nTr;\n if (tr) {\n firstTr = tr;\n break;\n }\n }\n if (firstTr) {\n var colSizes = $(firstTr).children('th, td').map(function (vis) {\n return {\n idx: _fnVisibleToColumnIndex(settings, vis),\n width: $(this).outerWidth()\n };\n });\n\n // Check against what the colgroup > col is set to and correct if needed\n for (var i = 0; i < colSizes.length; i++) {\n var colEl = settings.aoColumns[colSizes[i].idx].colEl[0];\n var colWidth = colEl.style.width.replace('px', '');\n if (colWidth !== colSizes[i].width) {\n colEl.style.width = colSizes[i].width + 'px';\n }\n }\n }\n }\n\n // 3. Copy the colgroup over to the header and footer\n divHeaderTable.find('colgroup').remove();\n divHeaderTable.append(settings.colgroup.clone());\n if (footer) {\n divFooterTable.find('colgroup').remove();\n divFooterTable.append(settings.colgroup.clone());\n }\n\n // \"Hide\" the header and footer that we used for the sizing. We need to keep\n // the content of the cell so that the width applied to the header and body\n // both match, but we want to hide it completely.\n $('th, td', headerCopy).each(function () {\n $(this.childNodes).wrapAll('